home *** CD-ROM | disk | FTP | other *** search
/ DP Tool Club 31 / CDASC_31_1996_juillet_aout.iso / vrac / nfbtr745.zip / NFBTRANS.C < prev    next >
C/C++ Source or Header  |  1996-03-28  |  164KB  |  6,032 lines

  1. /*nfbtrans.c converted from Pascal to C by Randy Formenti N8KL*/
  2. /*Ammended to by Brian Buhrow in order to use under the Unix operating
  3. system*/
  4. #ifndef unix
  5. #define LINT_ARGS
  6. #define DOS
  7. #else
  8. #define UNIX_PATH "/usr/local/lib/"
  9. #endif           /* unix */
  10. #ifndef lint
  11. #endif           /* lint */
  12. #include    <stdio.h>
  13. #include <sys/types.h>
  14. #include <sys/stat.h>
  15. #include <stdlib.h>
  16. #ifdef DOS
  17. #include <io.h>
  18. #include <string.h>
  19. #include <ctype.h>
  20. #include <fcntl.h>
  21. #include <conio.h>
  22. #include <dos.h>
  23. #include <memory.h>
  24. #include <process.h>
  25. #else
  26. #include <string.h>
  27. #include <fcntl.h>
  28. #include <stdarg.h>
  29. #define MAXARGS 7
  30. #ifdef sunos
  31. #define max(a,b)  (((a) > (b)) ? (a) : (b))
  32. #define min(a,b)  (((a) < (b)) ? (a) : (b))
  33. #endif
  34.  
  35. #endif           /* DOS */
  36. #include <time.h>
  37. #include <signal.h>
  38. #include <errno.h>
  39.  
  40. #ifdef unix
  41. #define CONFIG_FILE "nfbtrans.cnf"      /* For us Unix types who hate
  42.                      * uppercase */
  43. #define MAXPATHLEN 1023 /* For the longest possible pathname */
  44. #define O_BINARY 0 /* We don't need it here */
  45. /*Definition of mode bits for open*/
  46. #ifndef S_ISUID    /* If we've seen this before, no redefinition */
  47. #define S_ISUID 04000    /* set User id on execution */
  48. #define S_ISGID 02000    /* set Group id on execution */
  49. #define S_ISVTX 01000    /* save text image after termination */
  50. #define S_IREAD 00400    /* read by owner */
  51. #define S_IWRITE 00200    /* write by owner */
  52. #define S_IEXEC 00100    /* execute by owner */
  53. #endif           /* The following are not usually defined */
  54. #define STD_OPEN 00777    /* rwxrwxrwx */
  55. #define delay(a) delay_unix(a)
  56. #define FOPEN_READ "r"
  57. #define FOPEN_WRITE "w"
  58. #else           /* DOS */
  59. #define CONFIG_FILE "NFBTRANS.CNF"      /* For those DOS heades */
  60. #define STD_OPEN S_IWRITE    /* Standard DOs open */
  61. #define MAXPATHLEN 127    /* for the longest possible path name in DOS */
  62. #define FOPEN_READ "rt"
  63. #define FOPEN_WRITE "wt"
  64. #endif           /* unix */
  65.  
  66. #ifdef _S_IFCHR
  67. #define IFCHR _S_IFCHR
  68. #elif defined(S_IFCHR)
  69. #define IFCHR S_IFCHR
  70. #else
  71. #define IFCHR _IFCHR
  72. #endif
  73.  
  74. /*defines and defaults*/
  75. #define     VERSION     "Version 7.45, \nMarch 27, 1996"
  76. #define COPYRIGHT "Written by the National Federation of the Blind and Randy \
  77. Formenti"
  78. #define MAX_MATCH 20
  79. #define MAX_REP 11
  80. #define MAXTAB        1400    /* number of entries in binary table of
  81.                  * braille rules */
  82. #define MAX_FILES 50    /* max # of files stored using wildcard spec in dos */
  83. #define MAX_EXTENSIONS 40    /* # of extensions for auto format */
  84. #define MAX_INIT 45/* max length of pre_init & post_init strings */
  85. #define MAX_TOKENS 40    /* max # of token on a line of .efl file */
  86. #define MAXWORDLEN 132
  87. #define MAX_TOC_ENTRY 250
  88. #define MAX_EFL_DATA 40
  89. #define MAX_EFL_DATA_LEN 40
  90. #define MAX_COL_WIDTH 20    /* in table definition */
  91. #define MAX_DIC_LEN 40    /* max length of word in hyphenation dictionary */
  92. #define TRUE 1
  93. #define FALSE 0
  94. #define BUFSIZE 4096
  95. #define POETRY 1
  96. # define TEXT 2
  97. #define BLOCK 3
  98. #define LISTS 4
  99. #define BLOCK_PARA 5
  100. #define AUTO_FORMAT 6
  101. #define UPPER 2
  102. #define LOWER 1
  103. #define NUMERIC 4
  104. #define NOTRANS 8
  105. #define SKIPTRANS 24
  106. #define UPPER_ALL 34
  107. #define BIT0 1
  108. #define BIT1 2
  109. #define BIT2 4
  110. #define BIT3 8
  111. #define BIT4 16
  112. #define BIT5 32
  113. #define BIT6 64
  114. #define BIT7 128
  115.  
  116. /*global variables*/
  117. char temp[256];
  118. int paramcount;
  119. char **paramstr;
  120.  
  121. typedef struct
  122. {
  123.   char *name;
  124.   int value;
  125. }   tokentype;
  126.  
  127. tokentype options[93] = /* all allowed options alphabetically */
  128. {"BE", 63, "BM", 63, "CA", 63, "CL", 63, "CO", 7, "CS", 63, "DB", 63, "DE", 63,
  129.   "DM", 63, "DS", 63, "EF", 39, "ET", 7, "EX", 2, "FC", 63, "FP", 63,
  130.   "FS", 63, "GD", 47, "GM", 63, "HB", 47, "HD", 47, "HK", 3,
  131.   "HL", 47, "HM", 47, "HN", 47, "HP", 47, "HT", 3, "HV", 2, "HX", 47,
  132.   "I0", 2, "I1", 2, "I2", 2, "I3", 2, "I4", 2, "I5", 2, "I6", 2, "I7", 2,
  133.   "I8", 2, "I9", 2, "IA", 2, "IB", 2, "IC", 2, "ID", 2, "IE", 2, "IF", 15,
  134.   "IP", 47, "IT", 63, "KC", 47, "KF", 7, "L0", 6, "L1", 6, "L2", 6, "LE", 46,
  135.   "LF", 24, "LI", 63, "LM", 63, "LP", 6, "LS", 47, "MA", 36, "MS", 46, "MT", 46,
  136.   "NC", 3, "OB", 63, "OC", 38, "OW", 2, "PA", 2, "PD", 39, "PE", 11, "PF", 39,
  137.   "PL", 46, "PN", 2, "PS", 47, "PW", 46, "QM", 63, "RC", 4, "RP", 6, "RW", 47,
  138.   "S0", 2, "SI", 2, "SO", 63, "SP", 2, "ST", 47, "TC", 2, "TD", 8, "TE", 8,
  139.   "TF", 27, "TM", 3, "TN", 2, "TO", 63, "TP", 6, "TS", 47, "TV", 2, "VC", 4,
  140. NULL, 0};
  141. char *option_types[6] = {"on command line", "in configuration file",
  142.   "in table file", "during translation", "in EFL file",
  143. "in initialization string"};
  144. char *main_menu[3] = {
  145.   "  1 - Translate a Text File\n",
  146.   "  2 - Emboss a File that has already been Translated\n",
  147. "  3 - Back Translate a Grade Two file\n"};
  148. char *call_prefix[15] =
  149. {"KA", "KB", "KC", "KD", "KE", "KF", "K", "N", "WA", "WB", "WD", "W", "VE",
  150. "VO", NULL};
  151. char single_dot[5] = {"@,'\042"};
  152. char prn[13] = {"prn"};
  153. char stdin_name[13] = {"stdin"};
  154. char string_format[4] = {"%s"};
  155. char *progress[2] = {"Skipping", "On"};
  156. char braille_punct[16] = {"012346780-'"};
  157. char leading_punct[8] = {"("};
  158. char lead_back_punct[8] = {"6780"};
  159. char trailing_punct[16] = {".!?,:;'"};
  160.  
  161. tokentype tokens[22] =
  162. {"D", 1, "T", 2, "LIS", 3, "SK", 4, "C", 5, "IND", 6, "PAG", 80, "FIE", 100, "OM", 101,
  163.   "ST", 102, "A", 199, "MAT", 202, "REPL", 301, "REPS*", 305, "REPS", 306,
  164. "REPW*", 310, "REPW", 311, "OP", 315, "LIN", 320, "G", 325, NULL, 999};
  165. char *stateid[60] =
  166. {"AK\000Alaska", "AL\000Alabama", "AR\000Arkansas",
  167.   "AZ\000Arizona", "AS\000American Samoa", "CA\000California",
  168.   "CO\000Colorado", "CT\000Connecticut", "CZ\000Canal Zone",
  169.   "DC\000District of Columbia", "DE\000Delaware", "FL\000Florida",
  170.   "GA\000Georgia", "GU\000Guam", "HI\000Hawaii",
  171.   "ID\000Idaho", "IL\000Ilinois", "IN\000Indiana",
  172.   "IA\000Iowa",
  173.   "KS\000Kansas", "KY\000Kentucky", "LA\000Lousiana", "ME\000Maine",
  174.   "MD\000Maryland", "MA\000Massachusetts", "MI\000Michigan",
  175.   "MN\000Minnesota", "MS\000Mississippi", "MO\000Missouri",
  176.   "MT\000Montana", "NE\000Nebraska", "NV\000Nevada",
  177.   "NH\000New Hampshire", "NJ\000New Jersey", "NM\000New Mexico",
  178.   "NY\000New York", "NC\000North Carolina", "ND\000North Dakota",
  179.   "CN\000Northern Mariana Is", "OH\000Ohio", "OK\000Oklahoma",
  180.   "OR\000Oregon", "PA\000Pennsylvania", "PR\000Puerto Rico",
  181.   "RI\000Rhode Island", "SC\000South Carolina", "SD\000South Dakota",
  182.   "TN\000Tennessee", "TT\000Trust Territories", "TX\000Texas",
  183.   "UT\000Utah", ",VT\000Vermont", "VA\000Virginia",
  184.   "VI\000Virgin Islands", "WA\000Washington", "WV\000West Virginia",
  185. "Wi\000Wisconsin", "WY\000Wyoming", NULL};
  186.  
  187. typedef int BOOL;
  188.  
  189. /*globals for buffered read*/
  190. char iobuf[BUFSIZE + 1];
  191. unsigned int bytes_in_buf;
  192. char *ioptr, *eolptr;
  193. int timer = 0xe00; /* default delay timing value only if linked with
  194.             * nfbasm.asm */
  195. int emboss_delay = 0, current_table_line;
  196. int hot_key = 0;   /* no hot keys by default */
  197. int ab_flag = 0;   /* abort */
  198. int output_case = 3;    /* output uppercase by default */
  199. int it_flag = 0, math_flag = 0;
  200. int stdin_tty = 0, stdout_tty = 0;    /* is stdin or stdout 1 keyboard or 0
  201.                      * file */
  202. int print_date = 0, print_file = 0;    /* prints date and file on first page
  203.                      * if true */
  204. int current_pass, toc_word;
  205. int spool = 0, charspersec = 40;
  206. int keep_together = 0, keep_together_save = 0, keep_format = 0;
  207. int prog_init;
  208. int file_count, current_file, total_files = 0, total_equations = 0;
  209. struct tm *tm;
  210.  
  211. typedef struct
  212. {
  213.   unsigned int startline, endline;
  214.   BOOL lflag;
  215.   int fopstart, fopend, dummy;
  216. }   loptype;
  217.  
  218. typedef struct
  219. {
  220.   int fop;       /* operation */
  221.   int fstart;       /* field start */
  222.   int flen;       /* field length */
  223.   int fappo;       /* pointer to data */
  224. }   foptype;
  225.  
  226. typedef struct
  227. {           /* holds binary form of braille rules */
  228.   int typex[MAXTAB + 1];
  229.   int start1[256];
  230.   int start2[27][27];
  231.   char match[MAXTAB + 1][MAX_MATCH + 1];
  232.   char replace[MAXTAB + 1][MAX_REP + 1];
  233. }   tablet;
  234.  
  235. typedef struct
  236. {
  237.   int braille, print;
  238. }   toctype;
  239.  
  240. toctype toc_pages[MAX_TOC_ENTRY], toc_page;
  241.  
  242. typedef struct
  243. {
  244.   char ext[10];
  245.   int init_val;
  246. }   extension_t;
  247.  
  248. typedef struct
  249. {
  250.   int total;
  251.   extension_t prog_ext[MAX_EXTENSIONS];
  252. }   prog_ext_t;
  253. prog_ext_t prog_extension;
  254.  
  255. typedef struct
  256. {
  257.   char pre_init[MAX_INIT + 1], post_init[MAX_INIT + 1], format;
  258. }   init_t;
  259. init_t init[15];   /* for i0 - i9 */
  260.  
  261. typedef char columnt[MAX_COL_WIDTH + 1];
  262.  
  263. BOOL usr_default = FALSE;
  264. int pagestart = 0, pagestart_save, pageend = -1, pageend_save;
  265. int pagestart_roman = 1, pageend_roman = 9999;
  266. char field_[256];
  267. char *field = field_;
  268. int count, copies, lastcopy = 0, rejoin, quiet_mode = 0, book_mode = 3;
  269. int bpagec, pagenumlen, hyphen_searches, hyphen_matches, ham_call = 0, total_ham_calls;
  270. int hyphen_mode = 0, min_hyp_len = 4, hyp_words_added = 0, hyp_int = 5;
  271. int remove_page_nums, hyphens_used, hyp_dic_tested = 0, split_word = 0, dash_flag;
  272. int max_consec_hyphens = 3, consec_hyphens, hyphens_skipped, max_hyp_page = 99, hyp_page;
  273. char token[MAX_TOKENS][40];
  274. int token_count, token_char;
  275. int current_token;
  276. int fopcount, lopcount;
  277. int lineskips = 99, linesperpage = 25, back_numbers;
  278. int maxline = 0, make_sound = 1;
  279. int display_braille = -1;
  280. int display_source = -1;
  281. BOOL printit = TRUE;
  282. int skip_output = 0, over_write = 0, input_file_arg = 0, start_arg = 1;
  283. int graphics_mode = 0;    /* skip chars with b7 set */
  284. int guide_dots = 2;
  285. int keep_control = 0, expand_tab = 0;
  286. int table_entries;
  287. BOOL no_copyright = FALSE;    /* display copyright by default */
  288. int leftmargin = -1;
  289. int capvec[256], subvec[256];
  290. int trans_mode = -1, trans_mode1 = 0, trans_default = 21;
  291. int pause_time = 0, inf_path_len = 0;
  292. unsigned long total_words, total_dots[8], total_cells, total_lines, emboss_time, config_lines;
  293. time_t time1, time2;
  294. time_t hyp_date_verify[5] = {0, 0, 0, 0, 0};
  295. char hyp_name_verify[5][24];
  296. long in_length, out_length, total = 0l, total_rejoins, total_not_rejoined, table_start_line;
  297. unsigned int hyphen_line_count;
  298. typedef struct
  299. {
  300.   long pos;
  301.   unsigned int line;
  302. }   dictype;
  303. dictype hyphen_dic_start[191];
  304. int efl_mode = 0;
  305. BOOL reload_table = TRUE;
  306. char inf_name[MAXPATHLEN] = {0};
  307. char inf_name_ext[10];
  308. char file_name[MAX_FILES][13];
  309. char hyphen_dic_name[64] = {0};
  310. char hyphen_dic_line[MAX_DIC_LEN + 1];
  311. char part1[MAX_DIC_LEN + 1], part2[MAX_DIC_LEN + 1];
  312. char bad_hyp_fname[64] = {"BAD.DIC"};
  313. int outf_des = 0;
  314. FILE *intext = NULL, *lfile, *conf_ptr, *hyp_dic_ptr = NULL, *rejoin_out_ptr = NULL;
  315. FILE *dic_out_ptr = NULL, *bad_hyp_ptr = NULL, *table_stat_file = NULL;
  316. FILE *toc_file_ptr = NULL;
  317. int inf_des, inf_des_save = 0, toc_line_count;
  318. char outf_name[49] = {0};
  319. char toc_file_name[16] = {"tocfile.$$$"}, toc_line[80];
  320. char toc_format[16] = {"~s2~c~f"};
  321. char efl_file[64];
  322. foptype f[40];
  323. char efl_data[MAX_EFL_DATA][MAX_EFL_DATA_LEN + 1];
  324. int appcount, linecount;
  325. BOOL lopactive = FALSE;
  326. unsigned int inpglen = 66;    /* input page length */
  327. char transpath[MAXPATHLEN + 1] = {0};
  328. char table_file[2][20] = {"braille.tab", "back.tab"};
  329. char active_table[20];
  330. char math_table[20] = {"math.tab"};
  331. char math_symbols[30] = {"=<>"};
  332. char stat_file[MAXPATHLEN + 1] = {0};
  333. char config_file[MAXPATHLEN] = {CONFIG_FILE};
  334. char indent[30] = {"  "};
  335. char format_char = '~';
  336. char ignore_format[20] = {0};
  337. char date_string[20];
  338. char *dayofweek[7] = {"sun", "mon", "tue", "wed", "thu", "fri", "sat"};
  339. char s0_init[20] = {0};
  340. char l0[4] = {0};
  341. char l1[4] = {0};
  342. char *l2[10] = {"DE\000\000\000", "HET\000\000", "EEN\000\000", ""};
  343. char vowels[40] = {"AEIOUY\201\202\203\205\210\211\212\213\214\220\223\225\226\227\232\240\241\242\243"};
  344. char consonants[40] = {"BCDFGHJKLMNPQRSTVWXZ\200\207"};
  345. char *t1[6] = {",TITLE\0\0\0\0", ",PR9T\0\0\0\0\0", ",BRL\0\0\0\0\0\0",
  346. "\0\0\0\0\0\0\0\0\0\0", ",PAGE\0\0\0\0\0", ",PAGE\0\0\0\0\0"};
  347. char table_definition[40] = {0}, table_sscan[25] = {"%s %s %s %s %s %s %s %s"};
  348. char italics[4] = {"_"};
  349. char cap_single[4] = {","};
  350. char cap_all[4] = {",,"};
  351. char vbar = '|';
  352. char letter_sign[4] = {";"};
  353. char quotes[4] = {"\042\047"};
  354. int field_width[8];
  355. int cols_in_table, cols_in_line, chars_in_table, chars_in_line;
  356. loptype l[40];
  357. unsigned char dot_table[128] = {    /* braille dot equivilent for each
  358.                      * ascii char, used in statistics
  359.                      * file */
  360.   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,    /* ascii 0-15 b0 = dot
  361.                              * 1, b1 = dot 2 ... */
  362.   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,    /* ascii 16-31 */
  363.   0, 46, 16, 60, 43, 41, 47, 4, 55, 62, 33, 44, 32, 36, 40, 12, /* / ascii 32-47 */
  364.   52, 2, 6, 18, 50, 34, 22, 54, 38, 20, 49, 48, 35, 63, 28, 57, /* ? ascii 48-63 */
  365.   8, 65, 67, 73, 89, 81, 75, 91, 83, 74, 90, 69, 71, 77, 93, 75,    /* @-O */
  366.   79, 95, 87, 78, 94, 101, 103, 122, 109, 125, 117, 42, 51, 59, 24, 56, /* _ */
  367.   0, 1, 3, 9, 25, 17, 11, 27, 19, 10, 26, 5, 7, 13, 29, 21,    /* 96-o */
  368.   15, 31, 23, 14, 30, 37, 39, 58, 45, 61, 53, 0, 0, 0, 0, 0,    /* p-127 */
  369. };
  370.  
  371. unsigned char graph_tab[170] = {
  372.   /* converts ascii representation of braille to ibm graphic characters */
  373.   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,    /* ascii 0-15 */
  374.   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,    /* ascii 16-31 */
  375.   32, 221, 189, 163, 196, 211, 219, 0, 224, 208, 220, 201, 190, 173, 251, 175,    /* 32-47 ' */
  376.   162, 172, 0, 186, 174, 206, 161, 0, 191, 170, 215, 223, 0, 198, 193, 212,    /* 63 27< */
  377.   0, 225, 226, 227, 228, 229, 230, 231, 232, 233, 234, 235, 236, 237, 238, 239, /* 64-79 @ */
  378.   240, 241, 242, 243, 244, 245, 246, 247, 248, 249, 250, 188, 197, 252, 253    /* 80-95 */
  379. };
  380.  
  381. columnt *column = (columnt *) & graph_tab[0];    /* graph_tab unused for now */
  382. char bnumber[] = {"jabcdefghi"};        /* lowercase for 8 dot braille */
  383. char bnumber_back[] = {"1234567890"};
  384. tablet *b;
  385. /*variables for do_translate*/
  386. BOOL done;
  387. char oldword[200];
  388. char oldline[256], oldline6[256];
  389. char tline[256];
  390. char fline[256];
  391. char hline[256];
  392. char bline[256];
  393. char bline6[256];
  394. char wline[256];
  395. int blinec, bpageb, bpageh, linelength, fill_length = 7, auto_toc_flag;
  396. int center_length = 30;
  397. int first_page = FALSE;
  398. int curmax;
  399.  
  400. unsigned char c, page_sep = '\14';
  401. char words[200];
  402. char bword[200];
  403. char bword6[200];
  404.  
  405. BOOL join, pjoin, rjoin;
  406. BOOL group;
  407. BOOL pgroup;
  408. BOOL xjoin;
  409. BOOL xgroup;
  410. BOOL xpjoin;
  411. BOOL xpgroup;
  412.  
  413. int xgrade = -1, grade_mod = 0;
  414. BOOL xcenter, find_toc_pages, got_toc_page, last_toc_word = FALSE;
  415. int xformat = -1, xformat_save;
  416. int blank_lines, djoin;
  417. BOOL xdouble, xtab, xacronym, xheading, xfooting, makefoot, makehead, fillit;
  418.  
  419. BOOL quoteopen, quoteclose;
  420.  
  421. int margin, point, firstletter, chardec, lastmatch, prev_type;
  422. char linein[256], *plinein, line_end[4] = {0};
  423. unsigned int lineinct;
  424. BOOL newline;
  425. int quotecount;
  426. BOOL dopagenum = TRUE;
  427. BOOL doroman, dobook, toc_entry, braille_page_nums, roman_flag, arabic_flag;
  428. unsigned char tabtable[256];
  429. BOOL disablecol;
  430. int setmargin, oldmargin;
  431. BOOL tabmargin;
  432. BOOL pageset;
  433. char addchar[11], fill_char = '\042';
  434. int actualpage;
  435. int interpoint = FALSE;
  436. char *roman[10] =
  437. {"", "I", "II", "III", "IV", "V", "VI", "VII", "VIII", "IX"};
  438. char *roman10[10] = {"", "X", "XX", "XXX", "XL", "L", "LX", "LXX", "LXXX", "XC"};
  439. struct stat infilestat, outfilestat, hypfilestat;
  440.  
  441. #ifdef DOS
  442. struct find_t fileinfo; /* wildcard support for dos */
  443. #endif           /* DOS */
  444.  
  445. /*function prototypes*/
  446. void top_of_form(void);
  447. void page_beep(void);
  448. void backspace_int(int);
  449. void dofillit(void);
  450. void make_roman(void);
  451. void make_arabic(int *, char *);
  452. void make_book(void);
  453. void bpurge(void);
  454. void format_first_line(void);
  455. void build_line(void);
  456. int split_hyphen_word(int);
  457. void remove_dashes(char *, int);
  458. void flush_if_not_blank(void);
  459. void add_case(void);
  460. void add_dots(char *);
  461. int get_integer(char *);
  462. int is_equation(void);
  463. void get_digit(void);
  464. void get_date(void);
  465. void do_commands(int);
  466. void process_fill(char *);
  467. void process_auto_toc(void);
  468. void read_toc_line(void);
  469. void compact_line(char *);
  470. void do_lop_op(foptype);
  471. void do_lop(void);
  472. void getline(void);
  473. void get_input(char *, int);
  474. int get_paragraph_type(int);
  475. void check_purge(void);
  476. void get_word(void);
  477. void set_vect(char *);
  478. void do_letter(int, char *);
  479. void do_number(char *);
  480. void do_punct(char *);
  481. void build_word(char *, char *);
  482. void check_ham_call(char *);
  483. void trans_word(char *);
  484. BOOL store_next_token(void);
  485. void pop_token(char *);
  486. int check_token(void);
  487. void store_commands(void);
  488. void add_efl_data(char *);
  489. void test_range(char *);
  490. void load_template(void);
  491. void do_translate(void);
  492. void translate_word(char *, char *);
  493. void write_stat_file(void);
  494. void advance_page(void);
  495. FILE *open_option_file(char *);
  496. void load_tables(char *);
  497. int test_bracket(char *, int);
  498. int search_hyphen_dictionary(char *);
  499. void insert_hyphen_word(void);
  500. void remove_trailing_punct(char *);
  501. void test_hyphen_dictionary(int);
  502. void translate_file(void);
  503. int get_path_component(char *);
  504. int open_input_file(void);
  505. void report_open_error(char *);
  506. int test_file_exist(void);
  507. int test_extension(char *);
  508. int search_extensions(char *);
  509. #ifndef __TURBOC__
  510. void delay(int);
  511. void sound(int);
  512. void nosound(void);
  513. #endif
  514. void emboss_file(void);
  515. void spool_file(void);
  516. void get_copies(void);
  517. void get_page_range(void);
  518. void get_end_page(char *);
  519. int page_in_range(void);
  520. void get_config(void);
  521. FILE *open_config_file(int);
  522. void rewrite_config(void);
  523. void write_hv(FILE *);
  524. void process_options(char *, int);
  525. void report_option_error(int, int);
  526. void open_hyp_dictionary(char *, int);
  527. void process_table_definition(void);
  528. void trim(char *);
  529. int strpos(char *, char *);
  530. void insert(char *, char *);
  531. void move(char *, char *, int);
  532. void do_pause(void);
  533. void get_printer_file_name(void);
  534. void pause_program(void);
  535. int check_keyboard(int);
  536. void write_toc_header(void);
  537. void write_string(char *, int);
  538. void write_char(char);
  539. void no_space(void);
  540. void sort_names(void);
  541. void copy_string(char *, char *, int);
  542. void delete(char *, int);
  543. void strncpy_zero(char *, char *, int);
  544. void cleanup(int);
  545. void exit_program(int);
  546. void print_error(char *,...);
  547. int ISalpha(char);
  548. int Isdigit(char);
  549. void main(int, char **);
  550. #ifdef unix
  551. extern char *strlwr(char *string);
  552. extern char *strupr(char *string);
  553. extern int getch(void);
  554. extern int getche(void);
  555. extern long filelength(int descriptor);
  556. extern int beep(int count);
  557. extern int kbhit(void);
  558. #endif           /* unix */
  559.  
  560. void top_of_form()
  561. {
  562.   int i;
  563.   BOOL dopagesave = dopagenum;
  564.   if (bpagec >= pageend)
  565.   {
  566.     done = TRUE;
  567.     bline[0] = bline6[0] = bword[0] = 0;
  568.     return;
  569.   }
  570.   actualpage++;
  571.   bpagec++;
  572.   if (page_in_range() > 1)
  573.   {           /* page in range */
  574.     if (lineskips < 99)
  575.       for (i = 0; i < lineskips + linesperpage - blinec; i++)
  576.     write_string(" ", 1);
  577.     else
  578.     {
  579.       write_char(page_sep);    /* formfeed */
  580.       if (lineskips == 101 && stdin_tty && stdout_tty && printit)
  581.       {        /* pause */
  582.     fprintf(stderr, "\7\nPress <ESC> to abort or any other key for next page\n");
  583.     i = getch();
  584.     if (i == 27)
  585.       ab_flag = done = TRUE;
  586.       }        /* pause */
  587.     }
  588.   }           /* page in range */
  589.   blinec = hyp_page = 0;
  590.   keep_together = keep_together_save;
  591.   if (done == FALSE || xfooting == TRUE)
  592.   {           /* next page */
  593.     pagenumlen = 0;
  594. /*if interpoint mode do not print even page numbers*/
  595.     if (interpoint && (bpagec & 1) == 0)
  596.       dopagenum = FALSE;
  597.     if (dopagenum && ((bpagec > 1 - (first_page > 0)) || pageset) && !xheading)
  598.     {           /* adjust for page number */
  599.       pagenumlen = (4 + (bpagec > 9) + (bpagec > 99));
  600.       linelength = curmax - pagenumlen - margin - (int) (strlen(addchar) + 1);
  601.     }           /* adjust for page number */
  602.     else
  603.       linelength = curmax + 1 - margin;
  604.     if (xcenter)
  605.       linelength = center_length;
  606.     dopagenum = dopagesave;
  607.     page_beep();
  608.     if (display_braille)
  609.     {           /* display_braille */
  610.       sprintf(wline, "Copy %d of %d   page %d", copies, lastcopy, bpagec);
  611.       strcpy(temp, wline);
  612.       i = ((int) strlen(wline) - maxline) >> 1;
  613.       if (i > 0)
  614.       {
  615.     memset(field, 32, maxline);
  616.     strnset(field, '*', i);
  617.     field[i] = 0;
  618.     sprintf(wline, "%s%s%s", field, temp, field);
  619.       }
  620.       if (!skip_output)
  621.     fprintf(stderr, "%s\n", wline);
  622.     }           /* display_braille */
  623.     else
  624.     if (skip_output + quiet_mode == 0)
  625.     {           /* report progress */
  626.       sprintf(temp, "%s page %d", progress[(page_in_range() > 0)], bpagec);
  627.       if (lastcopy > 1)
  628.     sprintf(temp + strlen(temp), " Copy %d of %d", copies,
  629.         lastcopy);
  630.       fprintf(stderr, "%s\n", temp);
  631.     }           /* report progress */
  632.  
  633.     if (printit)
  634.       delay(emboss_delay);
  635.   }           /* next page */
  636.   else
  637.     bpagec--;
  638. }           /* top_of_form */
  639.  
  640. void page_beep()
  641. {
  642.   if (make_sound)
  643.   {
  644. #ifndef unix
  645.     sound(2000);
  646.     delay(3);
  647.     nosound();
  648. #else
  649.     beep(1);       /* Beep terminal */
  650. #endif           /* unix */
  651.   }
  652. }           /* page_beep */
  653.  
  654. void backspace_int(int j)
  655. {           /* output a packspace so cursor is at first number of
  656.             * integer */
  657.   do
  658.   {
  659.     j /= 10;
  660.     fprintf(stderr, "%c", 8);
  661.   }
  662.   while (j > 0);
  663. }           /* backspace_int */
  664.  
  665. void dofillit()
  666. {
  667.   int i, j;
  668.   fillit = FALSE;
  669.   i = strlen(bline) - 1;
  670.   if (got_toc_page)
  671.   {           /* add page number to bline */
  672.     bline[curmax] = 0;
  673.     if (toc_entry && (book_mode & 4))
  674.     {           /* store print and braille page numbers */
  675.       make_arabic(&toc_page.print, temp);
  676.       make_arabic(&toc_page.braille, temp + 10);
  677.       sprintf(field, "%5s %5s", temp, temp + 10);
  678.     }           /* store print and braille page numbers */
  679.     else
  680.       make_arabic(&toc_page.braille, field);
  681.     i += 2;       /* indexes first character of page number */
  682.     sprintf(bline + i - 1, " %s", field);
  683.   }           /* add page number to bline */
  684.   else
  685.   {           /* process last word on line */
  686.     if (i <= 0)
  687.       return;
  688.     /* find out where last word on bline begins */
  689.     while (bline[i] != ' ' && i > 0)
  690.       i--;
  691.     if (bline[i] == ' ')
  692.       i++;
  693.     strcpy(field, bline + i);    /* store the last word of bline */
  694.     if ((int) strlen(field) >= fill_length)
  695.       print_error("\007Last word %s of TOC longer than %d characters in line %ld\n",
  696.           field, fill_length - 1, total_lines);
  697.   }           /* process last word on line */
  698.   memset(bline + i, fill_char, maxline - i);    /* fill with quotes dot 5 */
  699.   j = maxline - i - strlen(field) - 1;
  700.   if (j < guide_dots && j > 0)
  701.     memset(bline + i, ' ', j);  /* remove guide dots */
  702.   i = maxline - strlen(field);
  703.   strcpy(bline + i, field);
  704.   bline[i - 1] = ' ';   /* put blank before last word */
  705. }           /* dofillit */
  706.  
  707. void make_roman()
  708. {
  709.   if (bpagec >= 100)
  710.     make_arabic(&bpagec, field);
  711.   else
  712.     sprintf(field, ";%s%s", roman10[bpagec / 10], roman[bpagec % 10]);
  713.   if (!braille_page_nums)
  714.     delete(field, 1);
  715. }           /* make_roman */
  716.  
  717. void make_arabic(int *page, char *string)
  718. {
  719.   int i;
  720.   sprintf(string, "#%d", *page);
  721.   if (braille_page_nums)
  722.   {
  723.     i = 1;
  724.     while (string[i])
  725.     {
  726.       string[i] = bnumber[(int) (string[i] - (char) 48)];
  727.       i++;
  728.     }           /* while */
  729.   }
  730.   else
  731.     delete(string, 1);
  732.   if (page == &bpagec)
  733.     strcat(string, addchar);
  734. }           /* make_arabec */
  735.  
  736. void make_book()
  737. {
  738.   make_arabic(&bpageb, field + 1);
  739.   if (bpagec - bpageh > 1)
  740.     field[0] = (char) ((int) ('A') + bpagec - 2 - bpageh);
  741.   else
  742.     delete(field, 1);    /* remove first char of field */
  743. }           /* make_book */
  744.  
  745. void bpurge()
  746. {
  747.   int j, guide_line = 0;
  748.   BOOL dopagesave = dopagenum;
  749.   char ch = 0;
  750.   blinec++;       /* increment current braille line */
  751.   if (bline[0])
  752.   {           /* bline not empty */
  753.     if (strlen(bline6) > strlen(bline))
  754.       strcpy(bline, bline6);
  755.     ch = bline[curmax];
  756.     bline[curmax] = 0;    /* set bline to <curmax chars long */
  757.  
  758.     if (margin > 1)
  759.     {           /* insert space before left margin */
  760.       move(bline, bline + margin - 1, curmax + 1 - margin);
  761.       /* insert space in front of line if necessary */
  762.       memset(bline, 32, margin - 1);    /* fill in left margin with spaces */
  763.     }           /* insert space before left margin */
  764.   }           /* bline not empty */
  765.  
  766.   if (xcenter)
  767.   {           /* center */
  768.     trim(bline);
  769.     j = (curmax - (int) strlen(bline)) >> 1;
  770.     if (j > 0)
  771.     {
  772.       move(bline, bline + j, (int) strlen(bline));
  773.       memset(bline, 32, j);
  774.     }
  775.     if (newline)
  776.       xcenter = FALSE;
  777.   }           /* center */
  778.  
  779.   if (fillit && newline)
  780.   {
  781.     bline[curmax] = ch;
  782.     dofillit();
  783.     guide_line = 1;/* line of toc with dot 5 guidemarks */
  784.   }
  785.  
  786.   if (blinec == 1)
  787.   {           /* first line on this page */
  788.     field[0] = 0;
  789.     if (interpoint && (bpagec & 1) == 0)
  790.       dopagenum = FALSE;    /* no even page numbers for interpoint */
  791.     if (((bpagec > 1 - (first_page > 0)) || pageset || dobook) && dopagenum)
  792.     {           /* store braille page number in field */
  793.       if (doroman)
  794.     make_roman();
  795.       else
  796.       if (dobook && (book_mode & 2))
  797.     make_book();
  798.       else
  799.     make_arabic(&bpagec, field);
  800.       if (guide_line || (fillit && toc_word) || (table_definition[0] &&
  801.                       chars_in_table + pagenumlen > curmax))
  802.       {        /* cannot have this line on a line with a page number */
  803.     strcpy(bline6, bline);
  804.     bline[0] = 0;
  805.     format_first_line();
  806.     if (page_in_range())
  807.       write_string(bline, 1);
  808.     strcpy(bline, bline6);
  809.     blinec++;
  810.     if (toc_word)
  811.       write_toc_header();
  812.     field[0] = 0;
  813.       }        /* cannot have this line on a page number line */
  814.     }           /* store braille page number in field */
  815.     else
  816.     if (toc_word)
  817.       write_toc_header();
  818.     dopagenum = dopagesave;
  819.     if (xheading)
  820.     {           /* xheading */
  821.       strcpy(hline + strlen(hline) - strlen(field), field);
  822.       if (page_in_range())
  823.     write_string(hline, 1);
  824.       blinec++;
  825.     }           /* xheading */
  826.     else
  827.     if (field[0])
  828.       format_first_line();
  829.   }           /* first line on page */
  830.   else
  831.   if (keep_together)
  832.   {           /* conditional skip & not first line */
  833.     /* find out if bline has only spaces */
  834.     strcpy(field, bline);
  835.     trim(field);
  836.     if (!field[0] && blinec + keep_together > linesperpage)
  837.     {           /* skip rest of page */
  838.       blinec--;
  839.       top_of_form();
  840.       return;
  841.     }           /* skip rest of page */
  842.   }           /* conditional skip & not first line */
  843.  
  844.   if (dobook && blinec >= linesperpage && (book_mode & 2) && guide_line == 0)
  845.   {           /* put braille page in lower right corner */
  846.     make_arabic(&bpagec, field);
  847.     j = (int) strlen(bline);
  848.     memset(bline + j, 32, maxline - j);
  849.     strcpy(bline + maxline - strlen(field), field);
  850.   }           /* put braille page number in lower right corner. */
  851.  
  852.   if (page_in_range())
  853.   {           /* output */
  854.     if (keep_format)
  855.       for (j = 0; linein[j] == ' '; j++)
  856.     write_char(' ');
  857.     write_string(bline, 1);
  858.     if (xdouble)
  859.       write_string(" ", 1);
  860.   }           /* output */
  861.   if (xdouble)
  862.     blinec++;
  863.  
  864.   bline[0] = bline6[0] = 0;
  865.   if (!(xformat == TEXT) || fillit)
  866.     strcpy(bline, indent);
  867.   if (xformat == BLOCK || xformat == BLOCK_PARA)
  868.     bline[0] = '\0';
  869.   strcpy(bline6, bline);
  870.   pjoin = pgroup = FALSE;
  871.   if (xfooting && (blinec >= linesperpage - 1))
  872.   {           /* put footing on bottom of current page */
  873.     if (dobook)
  874.     {           /* adjust footing for braille page in lower right corner */
  875.       make_arabic(&bpagec, field);
  876.       strcpy(oldline, fline);    /* save fline */
  877.       delete(fline, strlen(field) + 1);
  878.       sprintf(fline + strlen(fline), " %s", field);
  879.     }           /* adjust footing for braille page in lower right corner */
  880.     if (page_in_range())
  881.       write_string(fline, 1);
  882.     if (dobook)
  883.       strcpy(fline, oldline);
  884.     blinec++;
  885.   }           /* put footing on bottom of current page */
  886.   if (blinec >= linesperpage)
  887.     top_of_form();
  888.   else
  889.   if (dobook && (blinec >= linesperpage - 1) && !xfooting)
  890.     linelength = curmax - pagenumlen - margin + 1;
  891.   else
  892.     linelength = curmax + 1 - margin;
  893.   if (xcenter)
  894.     linelength = center_length;
  895.   newline = FALSE;
  896. }           /* bpurge */
  897.  
  898. void format_first_line()
  899. {
  900.   int j;
  901.   j = (int) strlen(bline);
  902.   memset(bline + j, 32, maxline - j);
  903.   strcpy(bline + maxline - strlen(field), field);
  904. }           /* format_first_line */
  905.  
  906. void build_line()
  907. {
  908.   int i, j, r, build_bpurge = 0, bword_len, dash_pos, bline_len;
  909.   char c;
  910.   i = bline_len = (int) strlen(bline);
  911.   if (xtab)
  912.   {           /* xtab */
  913.     j = r = 0;
  914.     do
  915.     {
  916.       r++;
  917.       if (tabtable[i + r] != 0)
  918.     j = r;       /* found tab */
  919.     }
  920.     while (j == 0 && (i + r < linelength));
  921.  
  922.     if (!j)
  923.       j = 1;
  924.     for (r = 1; r < j; r++)
  925.     {
  926.       strcat(bline, " ");
  927.       strcat(bline6, " ");
  928.     }
  929.     pjoin = pgroup = xtab = FALSE;
  930.   }           /* xtab */
  931.  
  932.   if (l1[0] && strcmp(words, l1) == 0)
  933.     pjoin = TRUE;
  934.   if (djoin)
  935.   {           /* dutch braille l2 */
  936.     djoin++;
  937.     if (djoin == 3)
  938.     {
  939.       djoin = 0;
  940.       for (j = 0; l2[j][0]; j++)
  941.     if (!strcmp(words, l2[j]))
  942.       pjoin = TRUE;
  943.     }
  944.   }           /* dutch braille l2 */
  945.  
  946.   if (!(pjoin || (pgroup && group)))
  947.     i++;       /* account for space */
  948.   j = i + (int) strlen(bword6);
  949.   bword_len = (int) strlen(bword);
  950.   i += bword_len;
  951.  
  952.   if (i > linelength || j > linelength)
  953.     build_bpurge++;
  954.   if (l0[0])
  955.     if (strchr(l0, words[strlen(words + 1)]))
  956.       join = TRUE;
  957.  
  958.   if (rjoin)
  959.   {
  960.     join = TRUE;
  961.     rjoin = FALSE;
  962.   }
  963.   if (fillit)
  964.   {           /* fillit */
  965.     if (!toc_word)
  966.       write_toc_header();
  967.     toc_word++;
  968.     if (i > linelength -
  969.     fill_length || j > linelength - fill_length)
  970.       build_bpurge++;    /* flush output unless last_toc_word */
  971.     if (last_toc_word)
  972.       build_bpurge = FALSE;    /* do not flush output line, must be
  973.                  * processed by dofillit */
  974.   }           /* fillit */
  975.   if (((hyphen_mode & 65) == 65) && xgrade && current_pass == 1 &&
  976.       ((find_toc_pages == 0 && page_in_range()) || find_toc_pages))
  977.     if (!strpbrk(words, "0123456789|"))
  978.     {           /* check word */
  979.       r = 1;       /* check this word by default */
  980.       strcpy(field, words);
  981.       strlwr(field);    /* produces the shortest length when translated */
  982.       if (strchr(leading_punct, field[0]))
  983.     delete(field, 1);
  984.       remove_trailing_punct(field);
  985.       if (field[0])
  986.       {
  987.     translate_word(field, temp);
  988.     if ((int) strlen(temp) < min_hyp_len)
  989.       r = 0;
  990.       }
  991.       else
  992.     r = 0;
  993.       if (r)
  994.       {        /* test word */
  995.     strupr(field);
  996.     r = search_hyphen_dictionary(field);
  997.     hyphen_searches--;
  998.     if (strpbrk(field, "~-()<>/_'[]\042"))
  999.       r = 1;   /* pretend word is already in dictionary, do not add to
  1000.             * any file */
  1001.     if (!r)
  1002.     {       /* not in dictionary */
  1003.       r = 1;
  1004.       if (!bad_hyp_ptr)
  1005.         bad_hyp_ptr = fopen(bad_hyp_fname, "r+");
  1006.       if (bad_hyp_ptr)
  1007.       {       /* search bad word file */
  1008.         fseek(bad_hyp_ptr, 0l, 0);    /* start from first line */
  1009.         while (fgets(temp, 80, bad_hyp_ptr))
  1010.         {
  1011.           temp[strlen(temp) - 1] = 0;
  1012.           r = (int) strcmp(field, temp);
  1013.           if (!r)
  1014.         break;    /* word already there */
  1015.         }       /* while */
  1016.       }       /* search bad word file */
  1017.       if (r)
  1018.       {       /* ask */
  1019.         fprintf(stderr, "%s (Y/N): ", field);
  1020.         do
  1021.         {
  1022.           get_digit();
  1023.           temp[0] = (char) tolower(temp[0]);
  1024.         }
  1025.         while (temp[0] != 'y' && temp[0] != 'n');
  1026.         fprintf(stderr, "\n");
  1027.         if (temp[0] == 'y')
  1028.           for (;;)
  1029.           {
  1030.         fprintf(stderr, "Enter dictionary word: ");
  1031.         gets(temp);
  1032.         if (!temp[0])
  1033.           break;
  1034.         strupr(temp);
  1035.         if (!strchr(temp, '-'))
  1036.           continue;
  1037.         if (temp[0] < 'A' && temp[0] >= '\0')
  1038.           continue;
  1039.         temp[MAX_DIC_LEN] = 0;
  1040.         strcpy(hyphen_dic_line, temp);
  1041.         remove_dashes(hyphen_dic_line, 1);
  1042.         if (strcmp(field, hyphen_dic_line))
  1043.         {
  1044.           fprintf(stderr, "\7Words don't match!\n");
  1045.           continue;
  1046.         }
  1047.         insert_hyphen_word();
  1048.         break;
  1049.           }    /* for */
  1050.         else
  1051.         {       /* add to bad words file */
  1052.           if (!bad_hyp_ptr)
  1053.           {    /* open */
  1054.         bad_hyp_ptr = fopen(bad_hyp_fname, "w+");
  1055.         if (!bad_hyp_ptr)
  1056.           print_error("\7Cannot open %s\n", bad_hyp_fname);
  1057.           }    /* open */
  1058.           if (r)
  1059.         fprintf(bad_hyp_ptr, "%s\n", field);
  1060.         }       /* add to bad word file */
  1061.       }       /* ask */
  1062.     }       /* not in dictionary */
  1063.       }
  1064.     }           /* check word */
  1065.   if (build_bpurge)
  1066.     if (bline[0] && strcmp(bline, indent))
  1067.     {           /* line not empty or blank */
  1068.       if ((hyp_dic_ptr && (hyphen_mode & BIT0)) || (hyphen_mode & BIT1))
  1069.       {
  1070.     if (xgrade && fillit == FALSE && bword_len >= min_hyp_len
  1071.         && i - bword_len < linelength - 1)
  1072.     {       /* search hyphenation dictionary */
  1073.       dash_pos = search_hyphen_dictionary(words);
  1074.       if (dash_pos)
  1075.       {       /* found dictionary word */
  1076.         hyphen_matches++;
  1077.         /* restore original case of word */
  1078.         r = 0;
  1079.         for (j = 0; hyphen_dic_line[j]; j++)
  1080.         {
  1081.           if (dash_flag == 0 && (hyphen_dic_line[j] == '-' || hyphen_dic_line[j] == vbar))
  1082.         continue;
  1083.           if (capvec[r] == LOWER)
  1084.         hyphen_dic_line[j] = (char) tolower(hyphen_dic_line[j]);
  1085.           r++;
  1086.         }       /* j */
  1087.         do
  1088.         {
  1089.           dash_pos = split_hyphen_word(dash_pos);
  1090.           if (dash_pos)
  1091.           {    /* test split word */
  1092.         split_word = 1;
  1093.         c = format_char;
  1094.         format_char = '~';
  1095.         translate_word(part1, temp);
  1096.         format_char = c;
  1097.         if (i - bword_len + (int) strlen(temp) > linelength)
  1098.           continue;    /* split word still too long */
  1099.         consec_hyphens++;
  1100.         hyp_page++;
  1101.         if (consec_hyphens > max_consec_hyphens || hyp_page > max_hyp_page)
  1102.         {  /* too many consecutive hyphens */
  1103.           consec_hyphens = 0;
  1104.           hyphens_skipped++;
  1105.           continue;
  1106.         }  /* too many consecutive hyphens */
  1107.         hyphens_used++;
  1108.         sprintf(bline + bline_len, " %s", temp);
  1109.         /* remove space if word should join previous word */
  1110.         if (pjoin)
  1111.           delete(bline + bline_len, 1);
  1112.         format_char = '~';
  1113.         split_word = 2;
  1114.         translate_word(part2, bword);
  1115.         format_char = c;
  1116.         if (hyphen_mode & BIT4)
  1117.           if (fprintf(dic_out_ptr, "%s page %d\n", words, bpagec) < 0)
  1118.             no_space();
  1119.         break;
  1120.           }    /* test split word */
  1121.         }
  1122.         while (dash_pos);
  1123.         split_word = 0;
  1124.       }       /* found dictionary word */
  1125.       else
  1126.       {
  1127.         consec_hyphens = 0;
  1128.         if (hyphen_mode & BIT5)
  1129.         {       /* word not found */
  1130.           if (fprintf(dic_out_ptr, "%s page %d not found\n", words, bpagec) < 0)
  1131.         no_space();
  1132.         }       /* word not found */
  1133.       }
  1134.     }       /* search hyphenation dictionary */
  1135.       }
  1136.       else
  1137.     consec_hyphens = 0;
  1138.       bpurge();
  1139.     }           /* line not empty or blank */
  1140.   if (pjoin || (pgroup && group) || (strcmp(bword, "1") == 0 && xgrade > 0)
  1141.       || (bline[0] == '\0'))
  1142.   {
  1143.     sprintf(bline6, "%s%s", bline, bword6);
  1144.     strcat(bline, bword);
  1145.   }
  1146.   else
  1147.   {
  1148.     r = (int) strlen(bline);
  1149.     if (bline[r - 1] == ' ')
  1150.     {
  1151.       sprintf(bline6, "%s%s", bline, bword6);
  1152.       strcat(bline, bword);
  1153.     }
  1154.     else
  1155.     {
  1156.       sprintf(bline6, "%s %s", bline, bword6);
  1157.       sprintf(bline + r, " %s", bword);
  1158.     }
  1159.   }
  1160.  
  1161.   if (last_toc_word)
  1162.   {           /* output toc line */
  1163.     last_toc_word = FALSE;
  1164.     newline = TRUE;
  1165.     bpurge();
  1166.   }           /* output toc line */
  1167.  
  1168.   if (table_definition[0] && plinein >= eolptr)
  1169.   {           /* table defined & last word on line */
  1170.     sscanf(bline, table_sscan, column[0], column[1],
  1171.        column[2], column[3], column[4], column[5], column[6], column[7]);
  1172.     for (i = 0; i < cols_in_table; i++)
  1173.     {
  1174.       if ((int) strlen(column[i]) > field_width[i])
  1175.     print_error("\007Field %d > %d characters in line %ld\n", i + 1,
  1176.             field_width[i], total_lines);
  1177.       if (column[i][0] == '`' && column[i][1] == '\0')
  1178.     column[i][0] = 0;    /* have a column with blanks */
  1179.     }           /* i */
  1180.     sprintf(bline, table_definition, column[0], column[1], column[2],
  1181.         column[3], column[4], column[5], column[6], column[7]);
  1182.     bpurge();
  1183.   }           /* table defined & last word on line */
  1184.  
  1185.   if (!strcmp(bline, "BE"))
  1186.     if (xgrade > 1)
  1187.       strcpy(bline, "2");       /* braille for be */
  1188.   bword6[0] = '\0';
  1189.   pgroup = group;
  1190.   pjoin = join;
  1191.   join = FALSE;
  1192.   r = (int) strlen(bline);
  1193.   if (r > linelength)
  1194.   {           /* line too long */
  1195.     /* look for repeating characters */
  1196.     j = 0;
  1197.     c = bline[0];
  1198.     for (i = 1; bline[i]; i++)
  1199.       if (bline[i] == c)
  1200.     j++;
  1201.       else
  1202.       {        /* no repeat */
  1203.     j = 0;
  1204.     c = bline[i];
  1205.       }        /* no repeat */
  1206.     if (r - j < linelength)
  1207.     {           /* truncate repeats */
  1208.   truncate:
  1209.       if (bline[0] == ' ')
  1210.     delete(bline, strlen(indent));
  1211.       bline[linelength] = '\0';
  1212.       bpurge();
  1213.       return;
  1214.     }           /* truncate repeats */
  1215.     else
  1216.     {           /* line still too long */
  1217.       /* look for double repeats */
  1218.       i = (int) (r - 3);
  1219.       while (i >= 0)
  1220.     if (bline[i] == bline[r - 1] && bline[i - 1] == bline[r - 2])
  1221.       i -= 2;
  1222.     else
  1223.       break;
  1224.       if (i + 3 < linelength)
  1225.     goto truncate;
  1226.       /* no double repeate so continue on next line */
  1227.       strcpy(bword, bline + linelength);
  1228.       bline[linelength] = bline6[0] = bword6[0] = '\0';
  1229.       build_line();
  1230.     }           /* word still too long */
  1231.   }           /* line too long */
  1232. }           /* build_line */
  1233.  
  1234. int split_hyphen_word(int dash_pos)
  1235. {
  1236.   for (;;)
  1237.   {
  1238.     dash_pos--;
  1239.     if (!dash_pos)
  1240.       break;
  1241.     if (hyphen_dic_line[dash_pos] == '-')
  1242.     {           /* found rightmost dash */
  1243.       strcpy(part2, hyphen_dic_line + dash_pos + 1);
  1244.       strlwr(part2);
  1245.       strcpy(part1, hyphen_dic_line);
  1246.       part1[dash_pos + 1] = 0;
  1247.       if (!dash_flag)
  1248.       {
  1249.     remove_dashes(part1, 0);
  1250.     remove_dashes(part2, 0);
  1251.       }
  1252.       break;
  1253.     }           /* found rightmost dash */
  1254.   }
  1255.   return (dash_pos);
  1256. }           /* split_hyphen_word */
  1257.  
  1258. void remove_dashes(char *string, int vertical)
  1259. {           /* remove dashes except if last char of string.  If
  1260.             * vertical, also remove | */
  1261.   int i, j = 0;
  1262.   for (i = 0; string[i]; i++)
  1263.     if ((string[i] != '-' && !vertical) ||
  1264.     (vertical && string[i] != vbar && string[i] != '-'))
  1265.       string[j++] = string[i];
  1266.     else
  1267.     if (!string[i + 1])
  1268.       string[j++] = '-';        /* leave trailing - */
  1269.   string[j] = 0;
  1270. }           /* remove_dashes */
  1271.  
  1272. void flush_if_not_blank()
  1273. {
  1274.   int i;
  1275.   for (i = 0; bline[i]; i++)
  1276.     if (bline[i] != ' ')
  1277.     {           /* line contains a nonblank character */
  1278.       bpurge();
  1279.       break;
  1280.     }           /* line contains a nonblank character */
  1281. }           /* flush_if_not_blank */
  1282.  
  1283. int get_integer(char *string)
  1284. {           /* returns integer from string and removes digits. 18hello
  1285.             * becomes hello returning 18 */
  1286.   int j = 0, retval = 0, minusflag = 0;
  1287.   if (string[0] == '-')
  1288.   {
  1289.     minusflag = 1;
  1290.     j++;
  1291.   }
  1292.   while (Isdigit(string[j]))
  1293.   {
  1294.     retval = 10 * retval + (int) (string[j] - (char) 48);
  1295.     j++;
  1296.   }           /* while */
  1297.   if (j - minusflag)
  1298.     delete(string, j);    /* remove digits */
  1299.   if (minusflag)
  1300.     retval = -retval;
  1301.   return (retval);
  1302. }           /* get_integer */
  1303.  
  1304. int is_equation()
  1305. {           /* returns TRUE if word is a mathimatical equation,
  1306.             * otherwise FALSE */
  1307.   if (!strpbrk(words, math_symbols))
  1308.     return (FALSE);
  1309.   if (strpbrk(words, "0123456789<>"))
  1310.   {
  1311.     total_equations++;
  1312.     if (math_flag == 2)
  1313.       fprintf(stderr, "%ld - %s\n", total_words, words);
  1314.     return (1);
  1315.   }
  1316.   return (0);
  1317. }           /* is_equation */
  1318.  
  1319. void get_digit()
  1320. {
  1321.   if (hot_key)
  1322.   {
  1323.     temp[1] = 0;
  1324.     temp[0] = (char) getche();
  1325.     if (temp[0] <= '\r')
  1326.       temp[0] = 0;
  1327.     if (temp[0] == (char) 27)
  1328.     {           /* escape */
  1329.       fprintf(stderr, "\n");
  1330.       exit_program(0);
  1331.     }           /* escape */
  1332.   }
  1333.   else
  1334.     get_input(temp, 80);
  1335. }           /* get_digit */
  1336.  
  1337. void get_date()
  1338. {           /* stores date in date_string */
  1339.   time(&time1);
  1340.   tm = localtime(&time1);
  1341.   sprintf(date_string, "%s %02d/%02d/%02d %02d:%02d",
  1342.       dayofweek[tm->tm_wday], tm->tm_mon + 1, tm->tm_mday, tm->tm_year,
  1343.       tm->tm_hour, tm->tm_min);
  1344. }           /* get_date */
  1345.  
  1346. void add_dots(char *string)
  1347. {
  1348.   int dot, i = 0, j;
  1349.   while (string[i])
  1350.   {
  1351.     dot = dot_table[(int) string[i]];
  1352.     if (xgrade)
  1353.       dot &= 63;   /* remove dot 7 unless we're doing computer braille */
  1354.     total_cells++;
  1355.     for (j = 0; j < 7; j++)
  1356.     {
  1357.       if (dot & 1)
  1358.     total_dots[j]++;
  1359.       dot = dot >> 1;
  1360.     }           /* j */
  1361.     i++;
  1362.   }           /* while */
  1363. }           /* add_dots */
  1364. void add_case()
  1365. {
  1366.   int i, j = 0, k;
  1367.   BOOL show_caps = TRUE, show_lower = FALSE;
  1368.   for (i = 0; words[i]; i++)
  1369.   {
  1370.     if (isupper(words[i]) && show_caps)
  1371.     {           /* add comma */
  1372.       bword[j++] = ',';
  1373.       if (isupper(words[i + 1]))
  1374.       {        /* add another comma */
  1375.     bword[j++] = ',';
  1376.     show_caps = FALSE;
  1377.     show_lower = TRUE;
  1378.       }        /* add another comma */
  1379.     }           /* add a comma */
  1380.     if (islower(words[i]) && show_lower)
  1381.     {
  1382.       bword[j++] = ';';
  1383.       show_lower = FALSE;
  1384.       show_caps = TRUE;
  1385.     }
  1386.     if (words[i] < ' ')
  1387.     {
  1388.       k = b->start1[(int) words[i]];
  1389.       strcpy(bword + j, b->replace[k]);
  1390.       j += (int) (strlen(b->replace[k]));
  1391.       continue;
  1392.     }
  1393.     bword[j++] = words[i];
  1394.   }           /* i */
  1395.   bword[j] = 0;
  1396. }           /* add_case */
  1397.  
  1398. void do_commands(int option_mask)
  1399. {
  1400.   int tilpos, i, j, k, l, grade_modified = 0;
  1401.   int it_word = -1;
  1402.   char c, *cptr;
  1403.   if ((cptr = strchr(words, format_char)) == NULL)
  1404.     return;       /* no format commands in word */
  1405.   /* assume command will terminate TOC, centering or table */
  1406.   newline = TRUE;
  1407.  
  1408.   tilpos = 1 + (int) (cptr - words);
  1409.   if (words[tilpos])    /* theres a character after the tilda */
  1410.     do
  1411.     {
  1412.       c = (char) toupper(words[tilpos]);    /* the character after the ~ */
  1413.       cptr = words + tilpos - 1;
  1414.       if (!strchr("ILZ[", c))
  1415.     delete(cptr, 2);    /* for every char except ILZ[ */
  1416.       if (strchr("CEFMSTY[_", c))
  1417.     flush_if_not_blank();
  1418.  
  1419.       switch (c)
  1420.       {
  1421.       case 'A':   /* Acronym Logic - Betty Desimone */
  1422.     xacronym = TRUE;
  1423.     newline = FALSE;
  1424.     break;
  1425.       case 'B':   /* Textbook Break */
  1426.     doroman = FALSE;
  1427.     dobook = TRUE;
  1428.     bpageh = bpagec;    /* set to current page */
  1429.     /* blinec is 0 if first line has not been written to page */
  1430.     if (blinec < linesperpage)
  1431.       bpageh--;
  1432.     bpageb = get_integer(cptr);
  1433.     if (!bpageb)
  1434.       bpageb = 1;    /* set to 1 if invalid integer */
  1435.     if (book_mode & 1)
  1436.     {       /* mark with dashes */
  1437.       flush_if_not_blank();
  1438.       memset(tline, '-', maxline);  /* dots 3/6 */
  1439.       i = maxline;
  1440.       make_arabic(&bpageb, field);
  1441.       strcpy(tline + maxline - strlen(field), field);    /* put page num at end
  1442.                                  * of line */
  1443.       if (blinec > 1 && blinec < linesperpage - 1)
  1444.       {       /* not at top 2 or bottom 2 lines of page */
  1445.         if (page_in_range())
  1446.           write_string(tline, 1);
  1447.         blinec++;
  1448.       }       /* not at top 2 or bottom 2 lines of page */
  1449.       else
  1450.         linelength = curmax - pagenumlen - margin + 1;
  1451.     }       /* mark with dashes */
  1452.     break;
  1453.       case 'C':   /* Center */
  1454.     xcenter = TRUE;
  1455.     if (center_length > curmax - 6)
  1456.       center_length = curmax - 6;
  1457.     linelength = center_length;
  1458.     break;
  1459.       case 'D':   /* Double Toggle */
  1460.     xdouble ^= xdouble;
  1461.     break;
  1462.       case 'E':   /* Poetry */
  1463.     xformat = POETRY;
  1464.     break;
  1465.       case 'F':   /* Fill Line - Index table of contents */
  1466.     process_fill(cptr);
  1467.     break;
  1468.       case 'G':   /* Set Right Margin */
  1469.     i = curmax;
  1470.     curmax = get_integer(cptr);
  1471.     if (curmax < 1)
  1472.       curmax = 1;
  1473.     if (curmax > maxline)
  1474.       curmax = maxline;
  1475.     linelength = curmax + 1 - margin;
  1476.     break;
  1477.  
  1478.       case 'H':   /* Heading */
  1479.     strcpy(oldline, bline);
  1480.     strcpy(oldline6, bline6);
  1481.     xheading = TRUE;
  1482.     xpgroup = pgroup;
  1483.     xpjoin = pjoin;
  1484.     xjoin = join;
  1485.     xgroup = group;
  1486.     makehead = TRUE;
  1487.     bline[0] = 0;
  1488.     bline6[0] = 0;
  1489.     pgroup = FALSE;
  1490.     group = FALSE;
  1491.     join = FALSE;
  1492.     pjoin = FALSE;
  1493.     break;
  1494.       case 'I':   /* Italics */
  1495.     newline = FALSE;
  1496.     words[tilpos] = italics[0];
  1497.     if (words[tilpos + 1] == '\\')
  1498.     {
  1499.       it_flag += 1;
  1500.       delete(words + tilpos - 1, 3);    /* remove ~i\ */
  1501.       if (it_word == (int) total_words)
  1502.       {       /* more than 1 ~i\ in the word */
  1503.         delete(words, 1);    /* only leave 1 italics sign */
  1504.         break;
  1505.       }       /* more than 1 ~i\ in the word */
  1506.       it_word = (int) total_words;
  1507.       for (i = 0; i <= (it_flag & 1); i++)
  1508.         insert(italics, words);
  1509.       if (it_flag == 2)
  1510.         it_flag = 0;
  1511.       break;
  1512.     }       /* ~i\ */
  1513.     else
  1514.       it_flag = 0;
  1515.     if (tilpos > 1)
  1516.     {       /* >=1 char before ~ */
  1517.       if (isalpha(words[tilpos - 2]))
  1518.         words[tilpos - 1] = '-';
  1519.       else
  1520.         delete(words + tilpos - 1, 1);
  1521.     }
  1522.     else
  1523.     {
  1524.       words[tilpos - 1] = italics[0];
  1525.       delete(words + tilpos - 1, 1);
  1526.     }
  1527.     break;
  1528.       case 'J':   /* Stop Heading */
  1529.     xheading = FALSE;
  1530.     break;
  1531.       case 'K':   /* Stop Footing */
  1532.     xfooting = FALSE;
  1533.     break;
  1534.       case 'L':   /* Letter Sign */
  1535.     words[tilpos - 1] = vbar;    /* don't translate next character */
  1536.     words[tilpos] = ';';
  1537.     /* newline=FALSE;  */
  1538.     break;
  1539.       case 'M':   /* Left Margin Set */
  1540.     i = margin;
  1541.     margin = get_integer(cptr);
  1542.     if (margin < 1)
  1543.       margin = 1;
  1544.     if (margin > 30)
  1545.       margin = 30;
  1546.     linelength += i - margin;
  1547.     setmargin += margin - oldmargin;
  1548.     oldmargin = margin;
  1549.     break;
  1550.  
  1551.       case 'N':   /* Set PageNum */
  1552.     addchar[0] = 0;
  1553.     dopagenum = TRUE;
  1554.     doroman = FALSE;
  1555.     bpagec = get_integer(cptr);
  1556.     if (isupper(words[0]))
  1557.     {       /* uppercase letter followed number */
  1558.       sprintf(addchar, ";%c", words[0]);
  1559.       words[0] = 0;
  1560.     }       /* uppercase letter followed word */
  1561.     if (bpagec == 1)
  1562.       pageset = TRUE;
  1563.     bpageh = bpagec;
  1564.     if (blinec == 0)
  1565.       linelength = curmax - pagenumlen - margin - (int) (strlen(addchar) + 1);
  1566.     break;
  1567.       case 'O':   /* Offset for Wrap */
  1568.     i = get_integer(cptr);
  1569.     if (i >= 30)
  1570.       i = 2;   /* keep values reasonable */
  1571.     memset(indent, 32, i);
  1572.     indent[i] = '\0';
  1573.     break;
  1574.       case 'P':   /* page */
  1575.     if (*cptr == '+' || *cptr == '-')
  1576.     {
  1577.       braille_page_nums = FALSE;
  1578.       if (*cptr == '+')
  1579.         braille_page_nums = TRUE;
  1580.       delete(cptr, 1);
  1581.       break;
  1582.     }
  1583.     if (!Isdigit(cptr[0]))
  1584.     {       /* always skip page */
  1585.       k = 1;
  1586.       if (cptr[0] == ':')
  1587.       {       /* colon */
  1588.         delete(cptr, 1);
  1589.         i = get_integer(cptr);
  1590.         strcpy(field, bline);
  1591.         trim(field);
  1592.         if (field[0])
  1593.           i++;
  1594.         if (blinec + i < linesperpage)
  1595.           k = -1;    /* no page break */
  1596.       }       /* colon */
  1597.  
  1598.       if (cptr[0] && isalpha(cptr[0]))
  1599.       {       /* letter */
  1600.         /* skip to next odd page if interpoint right facing page is odd */
  1601.         if (interpoint && (bpagec & 1))
  1602.           k++;
  1603.         delete(cptr, 1);
  1604.       }       /* letter */
  1605.       for (l = 0; l < k; l++)
  1606.       {
  1607.         if (blinec >= linesperpage - 1)
  1608.           bpurge(); /* last line on page */
  1609.         else
  1610.         {       /* not last line on page */
  1611.           flush_if_not_blank();
  1612.           if (dobook)
  1613.           {
  1614.         /* we have to put page number in lower right corner */
  1615.         j = blinec;
  1616.         for (i = j; i < linesperpage; i++)
  1617.           bpurge();
  1618.           }
  1619.           else
  1620.         top_of_form();
  1621.         }       /* not last line on page */
  1622.       }       /* l */
  1623.     }       /* always skip page */
  1624.     else
  1625.     {       /* conditional skip */
  1626.       keep_together = get_integer(cptr);
  1627.       if (keep_together > linesperpage / 2)
  1628.         keep_together = linesperpage / 2;
  1629.       keep_together_save = keep_together;
  1630.     }       /* conditional skip */
  1631.     break;
  1632.       case 'Q':   /* clear all tabs */
  1633.     memset(tabtable, 0, sizeof(tabtable));
  1634.     break;
  1635.       case 'R':   /* Roman Numerals */
  1636.     doroman = TRUE;
  1637.     dobook = FALSE;
  1638.     break;
  1639.       case 'S':   /* Skip a line */
  1640.     i = get_integer(cptr);
  1641.     if (blinec >= i - 1)
  1642.       bpurge();
  1643.     break;
  1644.       case 'T':   /* Text Format */
  1645.     xformat = TEXT;
  1646.     strcat(bline, indent);
  1647.     strcpy(bline6, bline);
  1648.     line_end[0] = '\0';
  1649.     break;
  1650.       case 'U':   /* page Numbering Off */
  1651.     addchar[0] = 0;
  1652.     dopagenum = FALSE;
  1653.     break;
  1654.       case 'V':   /* set tab */
  1655.     i = get_integer(words);
  1656.     if (!i)
  1657.       i = 1;
  1658.     if (i >= linelength)
  1659.       print_error("\007Tab set beyond line length in line %d\n",
  1660.               lineinct);
  1661.     tabtable[i] = 1;
  1662.     break;
  1663.       case 'W':   /* Footing */
  1664.     strcpy(oldline, bline);
  1665.     strcpy(oldline6, bline6);
  1666.     xfooting = TRUE;
  1667.     xpgroup = pgroup;
  1668.     xpjoin = pjoin;
  1669.     xjoin = join;
  1670.     xgroup = group;
  1671.     makefoot = TRUE;
  1672.     bline[0] = 0;
  1673.     bline6[0] = 0;
  1674.     pgroup = FALSE;
  1675.     group = FALSE;
  1676.     join = FALSE;
  1677.     pjoin = FALSE;
  1678.     break;
  1679.       case 'X':
  1680.     xtab = TRUE;
  1681.     j = get_integer(cptr);
  1682.     if (j)
  1683.     {
  1684.       for (i = 0; i < j; i++)
  1685.         if ((int) strlen(bline) < linelength)
  1686.           strcat(bline, " ");
  1687.     }
  1688.     else
  1689.       xtab = TRUE;
  1690.     break;
  1691.       case 'Y':
  1692.     xformat = LISTS;    /* TABLE Format */
  1693.     break;
  1694.       case 'Z':   /* Terminator */
  1695.     words[tilpos] = '`';
  1696.     delete(words + tilpos - 1, 1);
  1697.     newline = FALSE;
  1698.     break;
  1699.       case '\47': /* Apostrophe */
  1700.     words[tilpos] = '=';
  1701.     delete(words + tilpos - 1, 1);
  1702.     newline = FALSE;
  1703.     break;
  1704.       case '_':
  1705.     break;
  1706.       case '0':   /* Grade 0 */
  1707.       case '1':   /* grade 1 */
  1708.       case '2':   /* grade 2 */
  1709.       case '3':   /* grade 3 */
  1710.     if (grade_modified++)
  1711.       print_error(
  1712.               "\007Two grade modifiers in word not allowed in line %ld\n", total_lines);
  1713.     newline = FALSE;
  1714.     group = join = FALSE;
  1715.     i = xgrade;
  1716.     cptr = strchr(ignore_format, c);
  1717.     xgrade = (int) (c - '0');
  1718.     if (xgrade == 3 && cptr == NULL)
  1719.       reload_table = TRUE;
  1720.     if (xgrade >= 2 && cptr == NULL)
  1721.       load_tables(table_file[0]);
  1722.     if (xgrade == 3 && cptr == NULL)
  1723.       reload_table = TRUE;
  1724.     if (xgrade == 0 || xgrade == 3)
  1725.     {       /* test mod */
  1726.       if (!cptr)
  1727.         grade_mod = 0;
  1728.       if (Isdigit(words[tilpos - 1]))
  1729.       {
  1730.         if (!cptr)
  1731.           grade_mod = (int) (words[tilpos - 1] - (char) 48);
  1732.         delete(words + tilpos - 1, 1);
  1733.       }
  1734.     }       /* test mod */
  1735.     if (cptr)
  1736.       xgrade = i;
  1737.     if (pjoin && xgrade == 0)
  1738.     {
  1739.       pjoin = FALSE;
  1740.       strcpy(bline, bline6);
  1741.     }
  1742.     break;
  1743.       case '4':   /* block */
  1744.     newline = FALSE;
  1745.     xformat = BLOCK;
  1746.     break;
  1747.       case '5':   /* blockparagraphs */
  1748.     newline = FALSE;
  1749.     xformat = BLOCK_PARA;
  1750.     break;
  1751.       case '6':   /* auto format */
  1752.     newline = FALSE;
  1753.     xformat = AUTO_FORMAT;
  1754.     break;
  1755.       case '[':   /* escape */
  1756.     i = tilpos - 1;
  1757.     words[i] = (char) 27;    /* escape character */
  1758.     delete(words + tilpos, 1);    /* remove the [ */
  1759.     do
  1760.     {       /* write escape sequence directly to printer or file */
  1761.       write_char(words[i]);
  1762.       i++;
  1763.     }
  1764.     while (words[i] != '\0' && words[i] != '~');
  1765.     strcpy(words + tilpos - 1, words + i);
  1766.     break;
  1767.       case '-':   /* process as command line option */
  1768.     j = tilpos;
  1769.     while (words[j] && words[j] != '~')
  1770.       j++;
  1771.     strcpy(temp, words + tilpos - 1);
  1772.     strcpy(words + tilpos - 1, words + j);
  1773.     temp[j - tilpos + 1] = '\0';
  1774.     strupr(temp);
  1775.     /* if quoted string, the first quote starts in char 4 xx= */
  1776.     if ((temp[3] == '\042' || temp[3] == '\047') &&
  1777.         (strchr(temp + 4, temp[3]) == NULL))
  1778.       while (plinein < eolptr)
  1779.       {
  1780.         get_word();
  1781.         sprintf(temp + strlen(temp), " %s", words);
  1782.         if (strchr(temp + 4, temp[3]))
  1783.         {
  1784.           words[0] = '\0';
  1785.           break;
  1786.         }
  1787.       }       /* while */
  1788.     process_options(temp, option_mask);
  1789.     break;
  1790.       case '.':
  1791.     j = test_extension(words + tilpos - 1);
  1792.     if (j < 0)
  1793.       print_error("\7Excluded extension in line %ld\n", total_lines);
  1794.     strcpy(words, init[j].pre_init);
  1795.     break;
  1796.       case '~':
  1797.     format_char = '\r';
  1798.     break;
  1799.       default:
  1800.     bad_format:
  1801.     fprintf(stderr, "\007Format error in ");
  1802.     if (total_lines)    /* error occurred in input file */
  1803.       print_error("line %ld\n%s", total_lines, linein);
  1804.     print_error("i%d=%s|%s\n", prog_init,
  1805.             init[prog_init].pre_init, init[prog_init].post_init);
  1806.       }        /* switch */
  1807.       if (strchr("AL", c) && words[0] == '\0')
  1808.     goto bad_format;
  1809.       if ((cptr = strchr(words, format_char)) != NULL)
  1810.     tilpos = 1 + (int) (cptr - words);
  1811.     }
  1812.     while (cptr != NULL);
  1813. }           /* do_commands */
  1814.  
  1815. void process_fill(char *cptr)
  1816. {
  1817.   int i, j;
  1818.   char *p;
  1819.   fillit = TRUE;
  1820.   /* assume a normal ~f not followed by digit */
  1821.   got_toc_page = FALSE;
  1822.   fill_length = 7;
  1823.   if (Isdigit(*cptr))
  1824.   {           /* process toc mark */
  1825.     i = get_integer(cptr);
  1826.     if (i > MAX_TOC_ENTRY)
  1827.       print_error("\007More than %d TOC entries not allowed\n", MAX_TOC_ENTRY);
  1828.     j = i - 1;
  1829.     if (current_pass == 1)
  1830.     {           /* first pass */
  1831.       if (!i)
  1832.       {        /* one pass required before embossing */
  1833.     if (find_toc_pages)
  1834.       goto duplicate;
  1835.     /*
  1836.      * set starting and ending page so program translates entire file but
  1837.      * never writes to disk during first pass
  1838.      */
  1839.     pagestart = pageend = 32767;
  1840.     find_toc_pages = TRUE;
  1841.     fillit = FALSE;
  1842.     toc_file_ptr = fopen(toc_file_name, "w+");
  1843.     if (!toc_file_ptr)
  1844.       print_error("\7Cannot open %s\n", toc_file_name);
  1845.     return;
  1846.       }        /* one pass required before embossing */
  1847.       /* in first pass with i in range */
  1848.       if (!find_toc_pages)
  1849.     print_error("\007~f0 not found before ~F%d on line %ld\n",
  1850.             i, total_lines);
  1851.       if (toc_pages[j].braille > 0)
  1852.     duplicate:
  1853.     print_error("\007Duplicate ~f%d entry on line %ld\n", i, total_lines);
  1854.       if (!toc_pages[j].braille)
  1855.       {        /* toc entry on first pass */
  1856.     toc_pages[j].braille = -1;    /* found first toc mark */
  1857.     got_toc_page = TRUE;    /* page is correct only on second pass */
  1858.     if (book_mode & 4)
  1859.       fill_length = 13;
  1860.     toc_entry = TRUE;
  1861.     /* store toc line skipping the ~f digits */
  1862.     p = strchr(linein, format_char) + 2;
  1863.     while (isdigit(*p))
  1864.       p++;
  1865.     fprintf(toc_file_ptr, "%s\n", p);
  1866.     if (!j)
  1867.       strcpy(toc_line, p);
  1868.     compact_line(toc_line);
  1869.       }        /* toc entry on first pass */
  1870.       else
  1871.       {        /* found second toc mark first pass */
  1872.     if ((book_mode & 4) && bpageb == 0)
  1873.       print_error("\7Print page undefined for TOC title ~f%d\n", i);
  1874.     toc_pages[j].braille = bpagec;
  1875.     toc_pages[j].print = bpageb;
  1876.     fillit = toc_entry = FALSE;    /* title, not actual toc entry */
  1877.       }        /* second toc entry first pass */
  1878.     }           /* first pass */
  1879.     else
  1880.     {           /* second pass */
  1881.       if (!i)
  1882.       {        /* ~f0 second pass */
  1883.     fillit = FALSE;
  1884.     return;
  1885.       }        /* ~f0 second pass */
  1886.       if (toc_pages[j].braille)
  1887.       {        /* toc entry second pass */
  1888.     toc_page = toc_pages[j];
  1889.     toc_pages[j].braille = 0;    /* indicates this contents/title pair
  1890.                      * has been processed */
  1891.     got_toc_page = TRUE;
  1892.     if (book_mode & 4)
  1893.       fill_length = 13;
  1894.     toc_entry = TRUE;
  1895.     if (!j)
  1896.     {
  1897.       rewind(toc_file_ptr);
  1898.       read_toc_line();
  1899.     }
  1900.       }        /* toc entry second pass */
  1901.       else
  1902.       {        /* title entry second pass */
  1903.     fillit = toc_entry = FALSE;
  1904.       }        /* title entry second pass */
  1905.     }           /* second pass */
  1906.   }           /* process toc entry */
  1907.   else
  1908.     switch (*cptr)
  1909.     {
  1910.     case ':':
  1911.       delete(cptr, 1);
  1912.       fill_length = get_integer(cptr);
  1913.       break;
  1914.     case '+':
  1915.     case '-':
  1916.       fillit = FALSE;
  1917.       auto_toc_flag = (*cptr == '+');
  1918.       delete(cptr, 1);
  1919.     }           /* switch */
  1920. }           /* process_fill */
  1921.  
  1922. void process_auto_toc()
  1923. {
  1924.   int l, l1;
  1925.   char *cptr;
  1926.   l = l1 = strlen(linein) - 1;
  1927.   if (l)
  1928.   {           /* line not empty */
  1929.     cptr = strchr(linein, format_char);
  1930.     if (cptr && toupper(cptr[1]) == 'F')
  1931.       return;
  1932.     /* find beginning of trailing number */
  1933.     while (l >= 0 && isdigit(linein[l]))
  1934.       l--;
  1935.     if (l < l1)
  1936.       while (l > 0 && (linein[l] == '.' || linein[l] == ' '))
  1937.     l--;
  1938.     if (l > 4)
  1939.     {
  1940.       linein[l + 1] = '\0';
  1941.       l = 0;
  1942.       while (linein[l] == ' ')
  1943.     l++;
  1944.       sprintf(temp, "%cf%d", format_char, auto_toc_flag++);
  1945.       insert(temp, linein + l);
  1946.     }
  1947.   }           /* line not empty */
  1948. }           /* process_auto_toc */
  1949.  
  1950. void read_toc_line()
  1951. {
  1952.   int l;
  1953.   fgets(toc_line, 70, toc_file_ptr);
  1954.   l = strlen(toc_line) - 1;
  1955.   if (toc_line[l] == '\n')
  1956.     toc_line[l] = '\0';
  1957.   toc_line_count++;
  1958.   compact_line(toc_line);
  1959. }           /* read_toc_line */
  1960.  
  1961. void compact_line(char *string)
  1962. {
  1963.   int i = 0, j = 0, blanks = 0;
  1964.   char c;
  1965.   while (string[i] == ' ' || string[i] == '-')
  1966.     i++;
  1967.   strcpy(string, string + i);
  1968.   for (i = 0; string[i]; i++)
  1969.   {
  1970.     c = string[i];
  1971.     if (c == (char) 9)
  1972.       string[i] = c = ' ';
  1973.     if (c == ' ')
  1974.       blanks++;
  1975.     else
  1976.       blanks = 0;
  1977.     if (blanks < 2)
  1978.       string[j++] = c;
  1979.   }           /* i */
  1980.   string[j] = '\0';
  1981. }           /* compact_line */
  1982.  
  1983. void do_lop_op(foptype fop)
  1984. {           /* Execute the Operation */
  1985.   int i, j, l;
  1986.   if (fop.fop < 100)
  1987.   {           /* not field match or replace */
  1988.     switch (fop.fop)
  1989.     {
  1990.     case 1:      /* delete */
  1991.       linein[0] = 1;
  1992.       linein[1] = 0;    /* delete but don't count as blank */
  1993.       break;
  1994.     case 2:      /* text */
  1995.       xformat = TEXT;
  1996.       break;
  1997.     case 3:      /* list */
  1998.       xformat = LISTS;
  1999.       break;
  2000.     case 4:      /* skip line */
  2001.       strcpy(linein, "~S ");
  2002.       linein[0] = format_char;
  2003.       break;
  2004.     case 5:      /* center */
  2005.       trim(linein);
  2006.       strcpy(field, linein);
  2007.       sprintf(linein, "~C%s", field);
  2008.       linein[0] = format_char;
  2009.       break;
  2010.     case 6:      /* indent */
  2011.       setmargin = oldmargin + 2;
  2012.       break;
  2013.     case 80:      /* page */
  2014.       inpglen = (unsigned int) fop.fstart;
  2015.       break;
  2016.     }           /* switch */
  2017.     eolptr = linein + strlen(linein);
  2018.     return;
  2019.   }           /* not field match or replace */
  2020.   if (!linein[0])
  2021.     return;       /* nothing to do on empty line */
  2022.   if (fop.fop < 300)
  2023.   {           /* field or match */
  2024.     j = (int) strlen(linein);
  2025.     if (j < fop.fstart + 1)
  2026.       for (i = j; i <= fop.fstart; i++)
  2027.     strcat(linein, " ");    /* fill in line so field isn't garbage */
  2028.     strcpy(field, linein + fop.fstart);
  2029.     field[fop.flen] = 0;
  2030.  
  2031.     if (fop.fop < 200)
  2032.     {           /* field state omit append */
  2033.       tabmargin = TRUE;
  2034.       delete(linein + fop.fstart, fop.flen);    /* remove field from linein */
  2035.       trim(field);
  2036.  
  2037.       switch (fop.fop)
  2038.       {        /* switch op */
  2039.       case 101:   /* omit */
  2040.     field[0] = 0;
  2041.     break;
  2042.       case 102:   /* state */
  2043.     if (field[0])
  2044.     {       /* field not empty */
  2045.       for (i = 0; stateid[i]; i++)
  2046.       {       /* i */
  2047.         j = strpos(field, stateid[i]);
  2048.         if (j)
  2049.         {       /* found state abbreviation */
  2050.           delete(field + j - 1, 2);
  2051.           insert(stateid[i] + 3, field + j - 1);
  2052.           break;
  2053.         }       /* found state abbreviation */
  2054.       }       /* i */
  2055.     }       /* field not empty */
  2056.       }        /* switch */
  2057.       if (fop.fappo > 0)
  2058.     strcat(field, efl_data[fop.fappo - 1]);
  2059.       insert(field, linein + fop.fstart);
  2060.       eolptr = linein + strlen(linein);
  2061.       return;
  2062.     }           /* <200 */
  2063.  
  2064. /*process match operations which are the only ones left*/
  2065.     if ((fop.fappo > 0) && (strpos(field, efl_data[fop.fappo - 1]) > 0))
  2066.     {           /* match string is not empty */
  2067.       disablecol = TRUE;
  2068.       switch (fop.fop)
  2069.       {
  2070.       case 201:   /* delete */
  2071.     linein[0] = 0;
  2072.     break;
  2073.       case 202:   /* match */
  2074.     disablecol = TRUE;
  2075.     break;
  2076.       }        /* switch */
  2077.     }           /* match string is not empty */
  2078.   }           /* field or match */
  2079.   if (fop.fop > 300 && fop.fop < 312)
  2080.   {           /* replace */
  2081.     l = 0;
  2082.     strcpy(field, efl_data[fop.fappo - 1]);
  2083.     do
  2084.     {
  2085.       strcpy(temp, linein);
  2086.       strupr(temp);
  2087.       j = strpos(temp + l, field);
  2088.       if (!j)
  2089.     return;
  2090.       j--;       /* relative to zero */
  2091.       switch (fop.fop)
  2092.       {
  2093.       case 301:   /* replace line */
  2094.     strcpy(linein, efl_data[fop.fappo]);
  2095.     eolptr = linein + strlen(linein);
  2096.     return;
  2097.       case 305:   /* reps* */
  2098.       case 306:   /* reps */
  2099.     delete(linein + j + l, strlen(field));    /* remove substring */
  2100.     if (strlen(linein) + strlen(efl_data[fop.fappo]) > 255)
  2101.       print_error("\7Line > 255 characters (reps*)line %ld\n", total_lines);
  2102.     insert(efl_data[fop.fappo], linein + j + l);
  2103.     l += (int) (strlen(efl_data[fop.fappo]) + j);
  2104.     break;
  2105.       case 310:   /* replace word */
  2106.       case 311:   /* repw */
  2107.     /* find first char of word */
  2108.     while (linein[j + l] != ' ' && j > 0)
  2109.       j--;
  2110.     if (linein[j + l] == ' ')
  2111.       j++;
  2112.     /* j points to first character of word */
  2113.     i = j + l + 1;
  2114.     while (linein[i] != ' ' && linein[i] != '\0')
  2115.       i++;
  2116.     strcpy(linein + j + l, linein + i);    /* remove the word */
  2117.     if (strlen(linein) + strlen(efl_data[fop.fappo]) > 255)
  2118.       print_error("\7Line > 255 characters (repw*) line %ld\n", total_lines);
  2119.     insert(efl_data[fop.fappo], linein + j + l);
  2120.     l += (int) (strlen(efl_data[fop.fappo]) + j);
  2121.     break;
  2122.       }        /* switch */
  2123.     }
  2124.     while (fop.fop == 305 || fop.fop == 310);
  2125.   }           /* replace */
  2126.   switch (fop.fop)
  2127.   {
  2128.   case 315:
  2129.     process_options(efl_data[fop.fappo - 1], 16);
  2130.     break;
  2131.   case 320:
  2132.     sprintf(temp, "%s%ld", efl_data[fop.fappo - 1], total_lines);
  2133.     /* insert after leading blanks */
  2134.     i = 0;
  2135.     while (linein[i] == ' ' && linein[i])
  2136.       i++;
  2137.     if (linein[i])
  2138.     {
  2139.       if (strlen(linein) + strlen(temp) > 255)
  2140.     print_error("\7Line > 255 characters (line) line %ld\n", total_lines);
  2141.       insert(temp, linein + i);
  2142.     }
  2143.     break;
  2144.   case 325:      /* graphics */
  2145.     for (i = 0; linein[i]; i++)
  2146.       if (linein[i] < '\0')
  2147.       {        /* extended graphics */
  2148.     sprintf(temp, "%s%d", efl_data[fop.fappo - 1],
  2149.         (int) (unsigned char) linein[i]);
  2150.     delete(linein + i, 1);
  2151.     if (strlen(linein) + strlen(temp) > 255)
  2152.       print_error("\7Line > 255 characters (graph) line %ld\n", total_lines);
  2153.     insert(temp, linein + i);
  2154.       }        /* extended graphics */
  2155.   }           /* switch */
  2156.   l = strlen(linein);
  2157.   while (l > 0 && linein[l - 1] == ' ')
  2158.     l--;
  2159.   linein[l] = '\0';
  2160.   eolptr = linein + l;
  2161. }           /* do_lop_op */
  2162.  
  2163. void do_lop()
  2164. {           /* Do Line Operation Processing -- outer loop */
  2165.   int i, j;
  2166.   disablecol = FALSE;
  2167.   for (i = 0; i < lopcount; i++)
  2168.     if (l[i].lflag)/* match active */
  2169.       if ((lineinct >= l[i].startline) && (lineinct <= l[i].endline))
  2170.       {        /* line within range */
  2171.     j = l[i].fopstart;
  2172.     do_lop_op(f[j]);
  2173.     if (disablecol)
  2174.       for (j = l[i].fopstart + 1; j < l[i].fopend; j++)
  2175.         do_lop_op(f[j]);
  2176.       }        /* line within range */
  2177.   if (!disablecol)
  2178.     for (i = 0; i < lopcount; i++)
  2179.       if (!l[i].lflag)
  2180.     if ((lineinct >= l[i].startline) && (lineinct <= l[i].endline))
  2181.       for (j = l[i].fopstart; j < l[i].fopend; j++)
  2182.         do_lop_op(f[j]);
  2183.  
  2184.   if (disablecol)
  2185.     tabmargin = FALSE;
  2186. }           /* do_lop */
  2187.  
  2188. void getline()
  2189. {
  2190.   int i = -1, j;
  2191.   for (;;)
  2192.   {           /* do until line read, line too long, or eof */
  2193.     i++;
  2194.     if (!bytes_in_buf)
  2195.     {           /* empty buffer so fill it up */
  2196.       bytes_in_buf = read(inf_des, iobuf, (unsigned int) BUFSIZE);
  2197.       if (bytes_in_buf <= 0)
  2198.       {        /* eof */
  2199.     done = TRUE;
  2200.     if (i > 0 && c != '\n')
  2201.       done = FALSE; /* file ended without crlf */
  2202.     break;
  2203.       }        /* eof */
  2204.       ioptr = iobuf;
  2205.     }           /* buffer empty so fill it up */
  2206.     c = (char) *ioptr;
  2207.     bytes_in_buf--;
  2208.     ioptr++;
  2209.     if (c >= (unsigned char) 128)
  2210.     {           /* b7 */
  2211.       if (!graphics_mode)
  2212.     goto skip_char;
  2213.       if (graphics_mode == 1)
  2214.     c &= 127;  /* remove b7 */
  2215.     }           /* b7 */
  2216.     if (c == 31)
  2217.       c = vbar;
  2218.     if (c == '\10' && i > 0)
  2219.     {           /* backspace */
  2220.       i -= 2;
  2221.       continue;
  2222.     }           /* backspace */
  2223.     if (c == (char) 30)
  2224.     {
  2225.   skip_char:
  2226.       i--;
  2227.       continue;
  2228.     }
  2229.     else
  2230.       linein[i] = c;
  2231.     if (c == '\13' || c == '\14')
  2232.       lineinct = 0;
  2233.     if (c == '\n')
  2234.       break;       /* actual eol */
  2235.     if (c == '\t' && lopactive > 0 && expand_tab > 0)
  2236.     {
  2237.       c = ' ';
  2238.       for (j = 0; j < expand_tab; j++)
  2239.     linein[i++] = ' ';
  2240.       i--;
  2241.     }
  2242.     if (i > 170)
  2243.     {           /* look for word break */
  2244.       if (c == ' ' || i > 250)
  2245.       {
  2246.     total_lines--;
  2247.     break;       /* line too long, end at word */
  2248.       }
  2249.     }           /* look for word break */
  2250.     if (c == '\15')
  2251.       goto space;
  2252.     if (c < ' ' && keep_control == 0)
  2253.   space:linein[i] = ' ';
  2254.     /* remove all control chars */
  2255.   }           /* for */
  2256.   linein[i] = linein[i + 1] = '\0';
  2257.   i--;
  2258.   while (i >= 0 && linein[i] == ' ')
  2259.     linein[i--] = 0;    /* remove trailing spaces */
  2260.   eolptr = linein + i + 1;
  2261.   plinein = &linein[0];
  2262.   if (inpglen > 0 && lineinct > inpglen)
  2263.     lineinct = 0;  /* reset lineinct for next input page. Used by .efl files */
  2264.   lineinct++;
  2265.   total_lines++;
  2266.  
  2267.   if (lopactive)
  2268.     do_lop();
  2269.  
  2270.   if (display_source)
  2271.     printf("=>%s\n", linein);
  2272. }           /* getline */
  2273.  
  2274. void get_input(char *string, int length)
  2275. {           /* gets a line of input from stdin up to length bytes */
  2276.   int l;
  2277.   fgets(string, length, stdin);
  2278.   l = (int) (strlen(string) - 1);
  2279.   if (string[l] == '\n' && l >= 0)
  2280.     string[l] = 0;
  2281. }           /* get_input */
  2282.  
  2283. int get_paragraph_type(int mode)
  2284. {
  2285.   int indents = 0, blanks = 0, l = 0;
  2286.   char prev_char = '\1';
  2287.   int save_disp = display_source;
  2288.   if (!mode)
  2289.     xformat = TEXT;
  2290.   if (stdin_tty == 0 || (infilestat.st_mode & IFCHR))
  2291.     return (0);
  2292.   display_source = 0, done = FALSE, bytes_in_buf = 0;
  2293.   total_lines = 0;
  2294.   do
  2295.   {
  2296.     getline();
  2297.     l = max(l, (int) strlen(linein));
  2298.     if (linein[0])
  2299.     {           /* line not empty */
  2300.       if (prev_char == '\0')
  2301.     blanks++;
  2302.       if (!strncmp(linein, "    ", 4))
  2303.     indents++;
  2304.     }           /* line not empty */
  2305.     prev_char = linein[0];
  2306.   }
  2307.   while (done == FALSE && total_lines < 1000);
  2308.   display_source = save_disp;
  2309.   if (!mode)
  2310.     if (blanks > indents)
  2311.       xformat = BLOCK_PARA;
  2312.   linein[0] = '\0';
  2313.   return (l);
  2314. }           /* get_paragraph_type */
  2315.  
  2316. void check_purge(void)
  2317. {           /* see if line should be written */
  2318.   int i, j;
  2319.   BOOL purgit = TRUE;
  2320.   /* flush unless the first leftmargin-1 chars contain a nonspace char */
  2321.   for (i = 0; i < leftmargin; i++)
  2322.     /* Determine whether to flush */
  2323.     if (linein[i] != ' ' && linein[i] != '\0')  /* when reading a new Line */
  2324.       purgit = FALSE;
  2325.  
  2326.   if (xformat == LISTS || xformat == BLOCK)
  2327.     purgit ^= 1;   /* toggle purgit */
  2328.   if (xformat == BLOCK_PARA)
  2329.     if (!linein[0])
  2330.     {           /* blank */
  2331.       if (!blank_lines++)
  2332.     purgit = TRUE;    /* indent since this line is blank */
  2333.       else
  2334.     purgit = FALSE;
  2335.       if (!bline[0])
  2336.     purgit = FALSE;
  2337.     }           /* blank */
  2338.     else
  2339.     {           /* not blank */
  2340.       purgit = FALSE;
  2341.       blank_lines = 0;
  2342.     }           /* not blank */
  2343.  
  2344.   if (disablecol)
  2345.     purgit = TRUE;
  2346.  
  2347.   if (purgit)       /* Check for Indentation */
  2348.   {
  2349.     newline = TRUE;
  2350.     j = -1;
  2351.     for (i = 0; bline[i]; i++)
  2352.       if (bline[i] != ' ')
  2353.     j = i;
  2354.     if (j >= 0 || xformat == BLOCK_PARA)
  2355.       bpurge();
  2356.     bline[0] = 0;
  2357.     if (xformat == TEXT || xformat == BLOCK_PARA)
  2358.       strcat(bline, indent);
  2359.     strcpy(bline6, bline);
  2360.     quotecount = 0;
  2361.     if (tabmargin)
  2362.       margin = setmargin;
  2363.     else
  2364.       margin = oldmargin;
  2365.     tabmargin = FALSE;
  2366.   }
  2367. }           /* check_purge */
  2368.  
  2369. void get_word()
  2370. {           /* extract a word from the input text and check for
  2371.             * commands */
  2372.   char *cptr;
  2373.   int l, l1 = 0;
  2374.   xacronym = FALSE;
  2375.  
  2376.   newline = FALSE;
  2377.   while (*plinein == '\0' && !done)
  2378.   {           /* blank line and not eof */
  2379.     /*
  2380.      * line could also be blank because all words were removed from read
  2381.      * buffer
  2382.      */
  2383.     l = strlen(bline);    /* length of pending braille line */
  2384.     if (makefoot)
  2385.     {           /* foot */
  2386.       makefoot = FALSE; /* only do once for each ~w command */
  2387.       memset(fline, 32, curmax);
  2388.       fline[linelength] = 0;
  2389.       if (bline[0])
  2390.     move(bline, fline + linelength - l + 1, l - 1);
  2391.       strcpy(bline, oldline);
  2392.       strcpy(bline6, oldline6);
  2393.       pgroup = xpgroup;
  2394.       pjoin = xpjoin;
  2395.       join = xjoin;
  2396.       group = xgroup;
  2397.     }           /* foot */
  2398.     if (makehead)
  2399.     {           /* head */
  2400.       /* use bline to consstruct header */
  2401.       makehead = FALSE; /* only do this once for each ~h command */
  2402.       memset(hline, 32, curmax);    /* fill with spaces */
  2403.       hline[curmax] = 0;
  2404.       if (bline[0])
  2405.     move(bline, hline + (linelength - l) / 2, l - 1);
  2406.       strcpy(bline, oldline);
  2407.       strcpy(bline6, oldline6);
  2408.       pgroup = xpgroup;
  2409.       pjoin = xpjoin;
  2410.       join = xjoin;
  2411.       group = xgroup;
  2412.     }           /* head */
  2413.     getline();
  2414.     if (trans_mode == 3 && remove_page_nums &&
  2415.     (int) strlen(linein) == remove_page_nums)
  2416.     {           /* look for braille page number */
  2417.       l = l1 = remove_page_nums - 1;
  2418.       /* check for arabic braille numbers */
  2419.       while (toupper(linein[l]) >= 'A' && toupper(linein[l]) <= 'J')
  2420.     l--;
  2421.       if (linein[l] != '#')
  2422.       {        /* not arabic */
  2423.     /* check for roman braille number */
  2424.     while (strchr("IXVixv", linein[l1]))
  2425.       l1--;
  2426.     if (linein[l1] == ';')
  2427.       l = l1;
  2428.       }        /* not arabic */
  2429.       if ((linein[l] == '#' || linein[l] == ';')
  2430.       && l > remove_page_nums - 5 && linein[l - 1] == ' ' &&
  2431.       linein[l - 2] == ' ')
  2432.       {        /* got number */
  2433.     while (l > 0 && linein[l - 1] == ' ')
  2434.       linein[--l] = '\0';   /* remove trailing spaces */
  2435.     eolptr = linein + l;
  2436.       }        /* got number */
  2437.     }           /* look for braille page number */
  2438.  
  2439.     if (auto_toc_flag)
  2440.       process_auto_toc();
  2441.     if (toc_line[0])
  2442.     {
  2443.       strcpy(temp, linein);
  2444.       compact_line(temp);
  2445.       if (strcmpi(temp, toc_line) == 0)
  2446.       {
  2447.     if (toc_line_count == 0 && current_pass == 1)
  2448.     {
  2449.       rewind(toc_file_ptr);
  2450.       read_toc_line();
  2451.     }
  2452.     sprintf(temp, "%s%d", toc_format, toc_line_count);
  2453.     insert(temp, linein);
  2454.     read_toc_line();
  2455.       }
  2456.     }
  2457.     check_purge();
  2458.     if (keep_format)
  2459.       break;
  2460.     if (!linein[0])
  2461.       table_definition[0] = '\0';
  2462.   }           /* blank line and not eof */
  2463.   if (!linein[0])
  2464.     if (done)
  2465.     {
  2466.       words[0] = 0;
  2467.       return;
  2468.     }
  2469.   while (*plinein == ' ')
  2470.     plinein++;       /* skip leading blanks */
  2471.   cptr = strchr(plinein, ' ');
  2472.   if (cptr)
  2473.   {           /* space found */
  2474.     *cptr = 0;       /* put null at end of word */
  2475.     strncpy_zero(words, plinein, sizeof(words));
  2476.     *cptr = ' ';   /* restore linein */
  2477.     plinein = cptr + 1; /* where to search for next word */
  2478.   }           /* space found */
  2479.   else
  2480.   {           /* word at end of line */
  2481.     strncpy_zero(words, plinein, sizeof(words));
  2482.     plinein += strlen(words);    /* we are done with this line */
  2483.   }           /* word at end of line */
  2484.   if (strchr(words, format_char))
  2485.     do_commands(8);
  2486.   words[MAXWORDLEN] = '\0';     /* words shouldn't be longer than that anyway */
  2487.   /* change words containing string of _ to -, looks better in braille */
  2488.   if (words[0] == '_')
  2489.   {           /* _ */
  2490.     l = 0;
  2491.     while (words[++l] == '_');
  2492.     if (l > 2 && words[l] == '\0')
  2493.       strnset(words, '-', l);
  2494.   }           /* _ */
  2495.   return;
  2496. }           /* get_word */
  2497.  
  2498. void set_vect(char *wordstring)
  2499. {           /* set up the vector for the characters in a word */
  2500.   char *wptr = &wordstring[0];
  2501.   int *cap_ptr = &capvec[0], *sub_ptr = &subvec[0];
  2502.   int i;
  2503.   do
  2504.   {
  2505.     *cap_ptr = *sub_ptr = 0;
  2506.     if (*wptr >= '\0')
  2507.     {           /* not graphics character */
  2508.       if (isupper(*wptr))
  2509.     *cap_ptr = UPPER;
  2510.       else
  2511.       {        /* not uppercase */
  2512.     if (islower(*wptr))
  2513.       *cap_ptr = LOWER;
  2514.     else
  2515.       if (*wptr == vbar && format_char != '\r' && wptr[1] != '\0' &&
  2516.           isdigit(b->replace[b->start1[48]][0]) == 0)
  2517.     {       /* vertical bar */
  2518.       *cap_ptr = SKIPTRANS;
  2519.       cap_ptr++;
  2520.       sub_ptr++;
  2521.       wptr++;
  2522.       *cap_ptr = NOTRANS;    /* do not translate character after | */
  2523.       if (trans_mode != 3)
  2524.         *wptr |= 128;    /* set b7 on character not to be translated */
  2525.       /* this prevents this char from being a match in do_letter */
  2526.     }       /* vertical bar */
  2527.       }        /* is not uppercase */
  2528.     }           /* not graphics character */
  2529.     else
  2530.     {           /* graphics character */
  2531.       *cap_ptr = LOWER;
  2532.       i = b->typex[b->start1[(int) (unsigned char) *wptr]];
  2533.       if (i == 29)
  2534.     *cap_ptr = UPPER;
  2535.     }           /* graphics character */
  2536.     wptr++;
  2537.     cap_ptr++;
  2538.     sub_ptr++;
  2539.   }
  2540.   while (*wptr);
  2541.   strupr(wordstring);
  2542.   if (trans_mode == 3)
  2543.   {
  2544.     for (i = 0; wordstring[i]; i++)
  2545.       if (capvec[i] != SKIPTRANS)
  2546.     capvec[i] = LOWER;
  2547.   }
  2548. }           /* set_vect */
  2549.  
  2550. void do_letter(int wlength, char *wordstring)
  2551. {           /* Check the extracted word against the table of valid
  2552.             * types: 1-use anywhere 2-must be exact match 3-at
  2553.             * beginning or all 4-only in middle 5-joins with same
  2554.             * type 6-joins next-to,into,by 7-not at beginning 8-the
  2555.             * word BE 9-his,was,were,enough 10-only at end         */
  2556.   int i, j, k, l, matchend, wstart, casetype;
  2557.   BOOL matched, end_flag;
  2558.   char current_match[MAX_MATCH + 1], *next_match, ch;
  2559.   lastmatch = count;
  2560.   wstart = k = 0;
  2561.   join = group = matched = FALSE;
  2562.   firstletter++;
  2563.   subvec[count] = point;    /* subvec indexes single letter in case
  2564.                  * there's no match */
  2565.   ch = wordstring[count + 1];
  2566.   i = (int) (unsigned char) (wordstring[count] - 64);
  2567.   if (i <= 0 || i > 26)
  2568.     i = point;       /* graphics or control character */
  2569.   else
  2570.   {           /* letter */
  2571.     j = (int) (unsigned char) (ch - 64);
  2572.     if (!ch)
  2573.       j = 0;
  2574.     if ((j <= 0 || j > 26) && ch)
  2575.     {           /* not letter */
  2576.       i = (int) (point + 1);
  2577.       if (b->match[point][0] != b->match[point + 1][0] || trans_mode == 3)
  2578.     i--;       /* only one entry for this character in table */
  2579.     }           /* not letter */
  2580.     else
  2581.       i = b->start2[i][j];
  2582.   }           /* letter */
  2583. /*for example the word this i=20 j=8 and start2[i][j] points to where words
  2584. * starting with th start*/
  2585.   if (xgrade >= 2 && !xacronym)
  2586.     do
  2587.     {
  2588.   restart:
  2589.       strcpy(current_match, b->match[i]);
  2590.       l = (int) strlen(current_match);
  2591.       matchend = count + l - 1; /* points to last character of proposed match */
  2592.       if (strncmp(current_match, wordstring + count, l))
  2593.     goto try_next_match;    /* not a match */
  2594.       k = b->typex[i];
  2595.       if (trans_mode == 3 && firstletter == 1 && count < 4)
  2596.       {
  2597.     if (strchr(lead_back_punct, wordstring[0]))
  2598.       wstart = 1;
  2599.     if (wordstring[0] == '9' && wordstring[1] == '6')
  2600.       wstart = 1;
  2601.       }
  2602.       if (firstletter == wstart)
  2603.       {        /* at beginning of word */
  2604.     if (split_word)
  2605.     {       /* split word */
  2606.       if (k == 2 && strcmp(current_match, b->replace[i]))
  2607.         goto try_next_match;
  2608.       if (k == 7 && split_word == 2)
  2609.         k = 1;
  2610.     }       /* split word */
  2611.     if (k == 4 || k == 7 || k == 15)
  2612.       goto try_next_match;    /* these types cannot be at beginning of word */
  2613.       }        /* at beginning of word */
  2614.       else
  2615.     if ((k == 2 || k == 3 || k == 6 || k == 8 ||
  2616.          k == 11 || k == 12 || k == 18))
  2617.     goto try_next_match;    /* not a match because not at beginning of
  2618.                  * word */
  2619.  
  2620.       j = b->typex[b->start1[(int) wordstring[matchend + 1]]];    /* Next Letter */
  2621.       if (j > 0 && j < 19)
  2622.       {        /* not at end next char is a letter */
  2623.     end_flag = FALSE;    /* assume not at end of word */
  2624.     if (trans_mode == 3)
  2625.     {       /* back translate */
  2626.       ch = wordstring[matchend + 1];
  2627.       if (ch == '\47' && current_match[0] != '\47')
  2628.         end_flag = TRUE;
  2629.       if (strchr(braille_punct, ch) && wordstring[0] != '7')
  2630.         if (wordstring[matchend + 2] == '\0' ||
  2631.         (wordstring[matchend + 2] &&
  2632.          strchr(braille_punct, wordstring[matchend + 2]) &&
  2633.          strchr(",'", current_match[0]) == NULL))
  2634.           end_flag = TRUE;
  2635.     }       /* back translate */
  2636.     if ((k == 2 || k == 6 || k == 10 || k == 12) && end_flag == FALSE)
  2637.       goto try_next_match;
  2638.     if ((k == 13 || k == 15) && strchr(vowels, wordstring[matchend + 1]) == NULL)
  2639.       goto try_next_match;
  2640.     if (k == 14 && strchr(consonants, wordstring[matchend + 1]) == NULL)
  2641.       goto try_next_match;
  2642.     if (k == 15 && strchr(vowels, wordstring[count - 1]) == NULL)
  2643.       goto try_next_match;
  2644.       }        /* not at end */
  2645.       else       /* Set end of Word if next char not Letter */
  2646.     end_flag = TRUE;
  2647.       if (end_flag)
  2648.       {        /* at end */
  2649.     if (k == 4 || (k == 3 && strcmp(current_match, "IN") == 0))
  2650.       /* in [3,4] */
  2651.       goto try_next_match;
  2652.     if (k == 11 || (k > 12 && k < 16))
  2653.       goto try_next_match;    /* at beginning not all, or French types */
  2654.  
  2655.     if (k == 5 && firstletter == wstart && wordstring[wstart] != '\\')
  2656.     {
  2657.       group = TRUE; /* join with same type */
  2658.       if (pgroup == FALSE && strcmp(current_match, "A") == 0)
  2659.         group = FALSE;
  2660.     }
  2661.     if (pjoin && k == 8)
  2662.       goto try_next_match;
  2663.     if (k == 2 && strcmp(current_match, "US") == 0 &&
  2664.         capvec[firstletter] == UPPER && capvec[firstletter + 1] == UPPER)
  2665.       goto try_next_match;
  2666.       }        /* at end */
  2667.       if ((k == 8) && (matchend == wlength - 1)
  2668.       && (wlength != l))
  2669.     goto try_next_match;
  2670.       if ((k == 9) &&    /* was, his, etc. */
  2671.       ((l != wlength) ||
  2672.        pjoin))
  2673.     goto try_next_match;
  2674.  
  2675.       if (k == 6)
  2676.       {
  2677.     if (matchend - wstart + 1 != wlength)
  2678.       goto try_next_match;    /* to Into by */
  2679.     join = TRUE;
  2680.       }
  2681.       if (k == 12)
  2682.     djoin = 1;
  2683.       if (k == 16)
  2684.       {
  2685.     if (prev_type == 16)
  2686.     {
  2687.       i++;
  2688.       subvec[count - 1]++;
  2689.       prev_type = 1;
  2690.     }
  2691.       }
  2692.       else
  2693.       if (prev_type == 16)
  2694.     subvec[count - 1]++;
  2695.       prev_type = k;
  2696.  
  2697.       casetype = capvec[count];
  2698.       if (casetype == LOWER)    /* lowercase */
  2699.     for (j = 1; current_match[j]; j++)
  2700.       if (isupper(current_match[j]))
  2701.         if (capvec[count + j] != casetype)
  2702.           goto try_next_match;    /* no matches with lower and upper
  2703.                      * case */
  2704.       if (k == 17 && trans_mode == 3)
  2705.       {        /* set case */
  2706.     if (strchr(current_match, letter_sign[0]))
  2707.       for (l = matchend + 1; wordstring[l]; l++)
  2708.         capvec[l] = LOWER;
  2709.     if (strchr(current_match, ','))
  2710.     {       /* capitalization */
  2711.       capvec[matchend + 1] = UPPER;
  2712.       if (strpos(current_match, ",,"))
  2713.         for (l = matchend + 1; wordstring[l]; l++)
  2714.           capvec[l] = UPPER_ALL;
  2715.     }       /* capitalization */
  2716.     if (count == 0 && strchr(current_match, ','))
  2717.       firstletter = -1;
  2718.       }        /* set case */
  2719.       subvec[count] = i;
  2720.       count = matchend;
  2721.       matched = TRUE;
  2722.       break;
  2723.  
  2724.   try_next_match:
  2725.       if (table_stat_file)
  2726.     if ((long) total_lines >= table_start_line)
  2727.       fprintf(table_stat_file, "    %s %d skipped\n", current_match, b->typex[i]);
  2728.       i++;
  2729.       next_match = b->match[i];
  2730.       if (wordstring[count] < 0 || wordstring[count + 1] < 0)
  2731.       {        /* extended graphics */
  2732.     if (current_match[0] == next_match[0])
  2733.       current_match[1] = next_match[1];
  2734.       }        /* extended graphics */
  2735.       if (trans_mode == 3)
  2736.     if (next_match[0] == current_match[0])
  2737.       goto restart;
  2738.     }           /* while */
  2739.     while (next_match[1] == current_match[1]);
  2740.  
  2741.   if (k == 18 || k == 19)
  2742.     do_number(wordstring);
  2743.   if (table_stat_file && (long) total_lines >= table_start_line)
  2744.   {
  2745.     k = subvec[lastmatch];
  2746.     fprintf(table_stat_file, "  %s %s %d\n", b->match[k], b->replace[k], b->typex[k]);
  2747.   }
  2748.   quoteopen = quoteclose = FALSE;
  2749. }           /* do_letter */
  2750.  
  2751. void do_number(char *wordstring)
  2752. {           /* convert numbers type 19 */
  2753.   int i;
  2754.   char ch;
  2755.   if (!xgrade)
  2756.     return;       /* check for minus - make in (9) sign */
  2757.   if (trans_mode == 3)
  2758.   {           /* back translate */
  2759.     firstletter++;
  2760.     for (i = count + 1; wordstring[i]; i++)
  2761.     {
  2762.       ch = wordstring[i];
  2763.       if (ch == ';' || ch == ',' || ch > 'J')
  2764.     break;       /* letter sign follows numbers */
  2765.       if (ch == '-')
  2766.     continue;
  2767.       if (ch >= 'A' && ch <= 'J')
  2768.       {        /* braille digit */
  2769.     capvec[i] = NOTRANS;
  2770.     wordstring[i] |= (char) -128;
  2771.       }        /* braille digit */
  2772.     }           /* i */
  2773.     if (back_numbers < 0)
  2774.       back_numbers = count + 1;
  2775.     return;
  2776.   }           /* back translate */
  2777.   firstletter = -1;
  2778.   subvec[count] = point;
  2779.   capvec[count] = NUMERIC;
  2780.   quoteopen = quoteclose = FALSE;
  2781. }           /* do_number */
  2782.  
  2783. /*  Convert THE PUNCTUATION    */
  2784. /*  Type 21 - Simple Replace   */
  2785. /*     22 - .            */
  2786. /*     24 - '                */
  2787. /*     25 - "                */
  2788. /*     27 - -            */
  2789. void do_punct(char *wordstring)
  2790. {
  2791.   int i, k;
  2792.   BOOL matched;
  2793.   char ch = b->match[point][0];
  2794.   BOOL apostrophe;
  2795.  
  2796.   while (strncmp(b->match[point], wordstring + count, strlen(b->match[point])))
  2797.   {
  2798.     point++;
  2799.     if (b->match[point][0] != ch)
  2800.       print_error("\7Unable to match punctuation in line %ld\n", total_lines);
  2801.   }           /* while */
  2802.  
  2803.   if (count > 0)   /* Check for capital mark requirement */
  2804.     if (lastmatch >= 0)
  2805.     {
  2806.       k = b->typex[abs(subvec[lastmatch])];
  2807.       if (k == 6 || k == 8 || k == 9)
  2808.     subvec[lastmatch] = -abs(subvec[lastmatch]);    /* lower sign not
  2809.                              * allowed following
  2810.                              * punctuation */
  2811.     }
  2812.  
  2813.   matched = FALSE;
  2814.  
  2815.   join = group = pgroup = apostrophe = FALSE;
  2816.   k = b->typex[point];
  2817.  
  2818.   if (k == 24)
  2819.   {           /* apostrophe */
  2820.     if (!count)
  2821.       apostrophe = TRUE;
  2822.     if ((isupper(wordstring[count - 1]) || isdigit(wordstring[count - 1])) &&
  2823.     (isupper(wordstring[count + 1]) || isdigit(wordstring[count + 1])))
  2824.       apostrophe = TRUE;
  2825.     if ((isupper(wordstring[count - 1]) || isdigit(wordstring[count - 1])) &&
  2826.     quotecount == 0)
  2827.       apostrophe = TRUE;
  2828.   }           /* apostrophe */
  2829.   if (apostrophe == FALSE && (k == 24 || k == 25))
  2830.   {           /* Handle quotes */
  2831.     c = wordstring[count - 1];
  2832.     if (quoteopen || ((count > 0) &&
  2833.         !(c == '(' || c == '-' || c == '"' || c == '\47' || c == '[') &&
  2834.               !quoteclose))
  2835.     {           /* Ending quote */
  2836.       if (quotecount & 1)
  2837.     subvec[count] = b->start1[34] + 1;
  2838.       else
  2839.     subvec[count] = b->start1[34] + 3;
  2840.       quotecount--;
  2841.       quoteopen = TRUE;
  2842.     }           /* ending quote */
  2843.     else
  2844.     {           /* Beginning quote */
  2845.       if (pjoin)
  2846.       {
  2847.     pjoin = FALSE;
  2848.     strcpy(bline, bline6);    /* reset for to into by */
  2849.       }
  2850.       quotecount++;
  2851.       if (quotecount & 1)
  2852.     subvec[count] = b->start1[34];
  2853.       else
  2854.     subvec[count] = b->start1[34] + 2;
  2855.       quoteclose = TRUE;
  2856.     }           /* beginning quote */
  2857.     return;
  2858.   }           /* handle quote */
  2859.  
  2860.   do
  2861.   {           /* Find replacement */
  2862.     i = (int) (count + strlen(b->match[point]) - 1);
  2863.     if (!strncmp(b->match[point], wordstring + count, strlen(b->match[point])))
  2864.     {
  2865.       matched = TRUE;
  2866.       subvec[count] = point;
  2867.       count = i;
  2868.     }
  2869.     else
  2870.       point++;
  2871.   }
  2872.   while (!matched);
  2873.  
  2874.   if (b->typex[point] != 27)
  2875.     firstletter = -1;
  2876.   quoteopen = FALSE;
  2877.   quoteclose = FALSE;
  2878. }           /* do_punct */
  2879.  
  2880. void build_word(char *wordstring, char *bwordstring)
  2881. {           /* build the word from the information kept in the
  2882.             * contraction vector.  The grade two translation for hour
  2883.             * would set subvec[0] to index h, subvec[1] to index the
  2884.             * ou sign, subvec[2] would be 0, and subvec[3] indexes r */
  2885.   BOOL no_lower_sign, num = FALSE, allcaps = FALSE;
  2886.   int i, i1, j, k, k1;
  2887.   bwordstring[0] = bword6[0] = '\0';    /* start with no word */
  2888.   bwordstring[MAXWORDLEN] = '\0';       /* tells if word gets too long */
  2889.  
  2890.   strcpy(oldword, wordstring);
  2891.   for (i = 0; wordstring[i]; i++)
  2892.   {
  2893.     if (bwordstring[MAXWORDLEN])
  2894.       break;       /* quit before bword overflows */
  2895.     j = (int) strlen(bwordstring);
  2896.     if (capvec[i] & NOTRANS)
  2897.     {           /* do not translate this char */
  2898.       if (capvec[i] != SKIPTRANS)
  2899.       {        /* vertical bar */
  2900.     if (back_numbers >= 0 && i >= back_numbers && wordstring[i] < '\0')
  2901.     {       /* convert to print digit */
  2902.       wordstring[i] &= (char) 127;
  2903.       bwordstring[j] = bnumber_back[(int) wordstring[i] - 65];
  2904.     }       /* convert to print digit */
  2905.     else
  2906.     {
  2907.       wordstring[i] &= (char) 127;
  2908.       bwordstring[j] = (char) toupper(wordstring[i]);
  2909.     }
  2910.     bwordstring[j + 1] = 0; /* only 1 character was added to bword */
  2911.       }        /* vertical bar */
  2912.     }           /* do not translate this char */
  2913.     else
  2914.     if (subvec[i])
  2915.     {           /* add translation to bword */
  2916.       if (subvec[i] < 0)
  2917.       {        /* lower sign not allowed before punctuation */
  2918.     no_lower_sign = TRUE;
  2919.     subvec[i] = -subvec[i];
  2920.       }        /* lower sign not allowed before punctuation */
  2921.       else
  2922.     no_lower_sign = FALSE;
  2923.  
  2924.       i1 = subvec[i];
  2925.       k = b->typex[i1];
  2926.       k1 = b->typex[subvec[i + 1]];
  2927.       if (trans_mode == 3 && k == 19)
  2928.     k = 1;
  2929.       if ((!num) && ((k == 19)
  2930.              || ((k == 22) && (k1 == 19))))
  2931.       {        /* start of number or decimal number */
  2932.     if (isdigit(b->replace[i1][0]) == 0 || k == 22)
  2933.       strcat(bwordstring, "#");
  2934.     num = TRUE;
  2935.     allcaps = join = group = pgroup = FALSE;
  2936.       }        /* start of number or decimal number */
  2937.  
  2938.       if (k == 19 || k == 21 || k == 23 || k == 24 || k == 25 || k == 27 || k == 28)
  2939.     strcat(bwordstring, b->replace[i1]);
  2940.  
  2941.       if (k == 22) /* period */
  2942.     if (k1 == 19)    /* numeric follows period */
  2943.       strcat(bwordstring, ".");     /* decimal point */
  2944.     else
  2945.       strcat(bwordstring, b->replace[i1]);
  2946.  
  2947.       if (k == 26)
  2948.     /* Percent */
  2949.     if (num)
  2950.     {
  2951.       j = strpos(bwordstring, "#");
  2952.       if (!j)
  2953.         j++;
  2954.       insert(b->replace[i1], bwordstring + j - 1);
  2955.     }
  2956.     else
  2957.       strcat(bwordstring, b->replace[i1]);
  2958.  
  2959.       if ((k > 0 && k < 19) || k == 29)
  2960.       {        /* 1-19 28 */
  2961.     if (num && strcmp(b->match[i1], "-"))
  2962.     {       /* end of number */
  2963.       num = FALSE;
  2964.       if (wordstring[i + 1] == '\0' && wordstring[i] == 'S' && wordstring[i - 1] != '\47')
  2965.         strcat(bwordstring, "'");
  2966.       else
  2967.       {
  2968.         strcat(bwordstring, letter_sign);
  2969.         if (wordstring[i - 1] == '-' && wordstring[i] > 'J')
  2970.           bwordstring[j] = '\0';    /* remove letter sign */
  2971.       }
  2972.     }       /* end of number */
  2973.     if (allcaps == FALSE && capvec[i] == UPPER)
  2974.     {       /* insert capital marks */
  2975.       pgroup = FALSE;
  2976.       j = (int) strlen(bwordstring);
  2977.       strcat(bwordstring, cap_single);
  2978.       if (capvec[i + 1] == UPPER)
  2979.       {
  2980.         strcpy(bwordstring + j, cap_all);
  2981.         allcaps = TRUE;
  2982.       }
  2983.     }       /* insert capital marks */
  2984.     if (k == 6)
  2985.     {       /* to into by */
  2986.       sprintf(bword6, "%s%s", bword, b->match[subvec[i]]);
  2987.       if (!strcmp(bword6, "INTO"))
  2988.         strcpy(bword6, "9TO");
  2989.     }       /* to into by */
  2990.  
  2991.     if (no_lower_sign)
  2992.       strcat(bwordstring, b->match[i1]);
  2993.     else
  2994.       strcat(bwordstring, b->replace[i1]);
  2995.     if (trans_mode == 3)
  2996.     {
  2997.       if (capvec[i] == LOWER)
  2998.         strlwr(bwordstring + j);
  2999.       if (capvec[i] & UPPER)
  3000.         strupr(bwordstring + j);
  3001.       if (capvec[i] != UPPER_ALL)
  3002.         strlwr(bwordstring + j + 1);
  3003.     }
  3004.       }        /* 1-19 28 */
  3005.     }           /* add translation */
  3006.     if (!strcmp(wordstring, "$"))
  3007.     {
  3008.       strcpy(bwordstring, "4#");
  3009.       strcpy(bword6, bwordstring);
  3010.     }
  3011.   }           /* i */
  3012. }           /* build_word */
  3013.  
  3014. void check_ham_call(char *wordstring)
  3015. {
  3016.   int i = 0, l = (int) strlen(wordstring), l1;
  3017.   ham_call = 0;
  3018.   if (l > 6 || trans_mode == 3)
  3019.     return;       /* too long or back translating */
  3020.   strcpy(temp, wordstring);
  3021.   strupr(temp);
  3022.   if (strcmp(temp, wordstring))
  3023.     return;       /* not uppercase */
  3024.   while (call_prefix[i])
  3025.   {
  3026.     l1 = (int) strlen(call_prefix[i]);
  3027.     if (!strncmp(temp, call_prefix[i], l1))
  3028.     {           /* match */
  3029.       if (isdigit(temp[l1]) == 0 || isalpha(temp[l1 + 1]) == 0)
  3030.     return;
  3031.       xacronym = TRUE;
  3032.       ham_call = 1;
  3033.       total_ham_calls++;
  3034.       break;
  3035.     }           /* match */
  3036.     i++;
  3037.   }           /* while */
  3038. }           /* check_ham_call */
  3039.  
  3040. void trans_word(char *wordstring)
  3041. {
  3042.   int k, l;
  3043.   quoteopen = quoteclose = FALSE;
  3044.   lastmatch = 0;
  3045.   firstletter = count = prev_type = back_numbers = -1;
  3046.   l = (int) strlen(wordstring);
  3047.   if (table_stat_file && (long) total_lines > table_start_line)
  3048.     fprintf(table_stat_file, "%s\n", wordstring);
  3049.   do
  3050.   {
  3051.     count++;
  3052.     if (!(capvec[count] & NOTRANS))
  3053.     {           /* not | */
  3054.       chardec = (int) (unsigned char) wordstring[count];
  3055.       point = b->start1[chardec];    /* = first table entry for this
  3056.                      * character */
  3057.       k = b->typex[point];
  3058.       if (!k)
  3059.     print_error("\007Character \042%c\042 decimal %d not in %s line %ld %s\n",
  3060.             wordstring[count], chardec, active_table, total_lines,
  3061.             inf_name);
  3062.       if ((k == 28 || k == 29) && xgrade > 1)
  3063.     if (b->match[point][0] == b->match[point + 1][0])
  3064.     {
  3065.       point++;
  3066.       k = b->typex[point];
  3067.     }
  3068.       if (k <= 16)
  3069.     do_letter(l, wordstring);
  3070.       else
  3071.       {        /* not a letter */
  3072.     if (k == 19)
  3073.       do_number(wordstring);
  3074.     else
  3075.       do_punct(wordstring);
  3076.       }        /* not letter */
  3077.     }           /* not | */
  3078.   }
  3079.   while (wordstring[count + 1]);
  3080. }           /* trans_word */
  3081.  
  3082. BOOL store_next_token()
  3083. {           /* removes next token from temp storing it in token[]
  3084.             * increment token_count */
  3085.   int retval = FALSE;
  3086.   char delim = ' ';
  3087.   char *cptr;
  3088.   while (temp[0] == ' ')
  3089.     delete(temp, 1);    /* remove leading spaces */
  3090.   if (temp[0] == (char) 39 || temp[0] == (char) 34)
  3091.   {           /* ' or " */
  3092.     delim = temp[0];
  3093.     delete(temp, 1);    /* remove delim */
  3094.   }
  3095.   if (!temp[0])
  3096.     return (FALSE);/* empty line */
  3097.   if (token_count >= MAX_TOKENS)
  3098.     print_error("More than %d tokens on line %d\n", MAX_TOKENS,
  3099.         linecount);
  3100.  
  3101.   cptr = strchr(temp, delim);
  3102.   if (cptr == NULL)
  3103.   {           /* last token on line */
  3104.     strcpy(token[token_count], temp);
  3105.     temp[0] = 0;
  3106.   }           /* last token */
  3107.   else
  3108.   {           /* found matching delim */
  3109.     *cptr = 0;
  3110.     strcpy(token[token_count], temp);
  3111.     strcpy(temp, cptr + 1);
  3112.     retval = TRUE;
  3113.   }           /* found delim match */
  3114.   token_count++;
  3115.   return (retval);
  3116. }           /* store_next_token */
  3117.  
  3118. void pop_token(char *string)
  3119. {
  3120.   string[0] = 0;
  3121.   if (current_token >= token_count)
  3122.     return;       /* no more stored tokens */
  3123.   strcpy(string, token[current_token]);
  3124.   current_token++;
  3125. }           /* pop_token */
  3126.  
  3127. int check_token()
  3128. {
  3129.   int i;
  3130.   if (!field[0])
  3131.     token_char = 199;
  3132.   else
  3133.   {           /* not empty */
  3134.     if (atol(field) > 0)
  3135.       token_char = 888;
  3136.     else
  3137.     {           /* word */
  3138.       strupr(field);
  3139.       i = -1;
  3140.       do
  3141.       {
  3142.     i++;
  3143.     if (!strncmp(field, tokens[i].name, strlen(tokens[i].name)))
  3144.       break;
  3145.       }
  3146.       while (tokens[i].name != NULL);
  3147.       if (tokens[i].value == 999)
  3148.     print_error("Unknown token %s in line %d\n", field, linecount);
  3149.       token_char = tokens[i].value;
  3150.     }           /* word */
  3151.   }           /* not empty */
  3152.   return (token_char);
  3153. }           /* check_token */
  3154.  
  3155. void add_efl_data(char *string)
  3156. {
  3157.   if (appcount >= MAX_EFL_DATA)
  3158.     print_error("\007More than %d emf_data entries\n");
  3159.   if (strlen(string) > MAX_EFL_DATA_LEN)
  3160.     print_error("\007efl_string > %d characters in line %d\n",
  3161.         MAX_EFL_DATA_LEN, linecount);
  3162.   strcpy(efl_data[appcount], string);
  3163.   appcount++;
  3164. }           /* add_efl_data */
  3165.  
  3166. void store_commands()
  3167. {
  3168.   current_token = 0;    /* start from beginning of token list */
  3169.   pop_token(field);/* get first token */
  3170.   strupr(field);
  3171.   if (strcmp(field, "LINE"))
  3172.     print_error("Invalid first Operation - must be LINE in line %d\n",
  3173.         linecount);
  3174.  
  3175.   pop_token(field);
  3176.   if (check_token() != 888)
  3177.     print_error("No line numbers specified in line %d\n", linecount);
  3178.  
  3179.   l[lopcount].startline = atoi(field);    /* starting line */
  3180.   l[lopcount].endline = l[lopcount].startline;    /* in case there isn't a
  3181.                          * second line number */
  3182.   l[lopcount].fopstart = (int) fopcount;    /* where commands start for
  3183.                          * this line */
  3184.   pop_token(field);
  3185.   if (check_token() == 888)
  3186.   {           /* ending line number specified */
  3187.     l[lopcount].endline = atoi(field);
  3188.     if (l[lopcount].endline < l[lopcount].startline)
  3189.       print_error("\7Ending line less than starting line in line %d\n",
  3190.           linecount);
  3191.     pop_token(field);
  3192.   }           /* ending line number specified */
  3193.  
  3194.   while (check_token() < 100)
  3195.   {           /* delete skip center indent list text page */
  3196.     if (format_char == '\r' && (token_char == 4 || token_char == 5))
  3197.       print_error("\007Cannot skip or center lines: formatting is disabled in line %d\n",
  3198.           linecount);
  3199.     f[fopcount].fop = token_char;
  3200.     pop_token(field);
  3201.     if (token_char == 80)
  3202.     {           /* page */
  3203.       f[fopcount].fstart = atoi(field);
  3204.       pop_token(field);
  3205.     }           /* page */
  3206.     fopcount++;
  3207.   }           /* while */
  3208.  
  3209.   if (check_token() == 202)
  3210.   {           /* match */
  3211.     test_range("match");
  3212.     l[lopcount].lflag = TRUE;    /* match subcommand is active */
  3213.     f[fopcount].fop = 202;    /* match operation */
  3214.     add_efl_data(field);
  3215.     f[fopcount].fappo = appcount;    /* index to match data -1 */
  3216.     pop_token(field);
  3217.     if (check_token() == 1)    /* delete */
  3218.       f[fopcount].fop = 201;    /* delete if match */
  3219.     fopcount++;
  3220.   }           /* match */
  3221.  
  3222.   while (check_token() == 100)
  3223.   {           /* field */
  3224.     f[fopcount].fop = 100;    /* indicate a field operation */
  3225.     test_range("field");
  3226.     f[fopcount].fop = 0;
  3227.  
  3228.     if (check_token() > 100 && token_char < 199)
  3229.     {           /* state or omit token */
  3230.       f[fopcount].fop = token_char;
  3231.       pop_token(field);
  3232.     }           /* state or omit */
  3233.  
  3234.     if (check_token() == 199)
  3235.     {           /* append */
  3236.       pop_token(field);
  3237.       add_efl_data(field);
  3238.       f[fopcount].fappo = appcount;
  3239.       pop_token(field);
  3240.       if (!f[fopcount].fop)
  3241.     /* there was no previous state or omit */
  3242.     f[fopcount].fop = 199;    /* indicate append operation */
  3243.     }           /* append */
  3244.     if (f[fopcount].fop)
  3245.       fopcount++;  /* valid field op was found */
  3246.   }           /* while */
  3247.  
  3248.   if (token_char >= 301 && token_char <= 311)
  3249.   {           /* replace */
  3250.     pop_token(field);
  3251.     strupr(field); /* make case insensitive */
  3252.     add_efl_data(field);
  3253.     if (!field[0])
  3254.       print_error("\007No string to replace in line %d\n", linecount);
  3255.     f[fopcount].fappo = appcount;
  3256.     pop_token(field);
  3257.     add_efl_data(field);
  3258.     f[fopcount].fop = token_char;
  3259.     fopcount++;
  3260.   }           /* replace */
  3261.  
  3262.   if (token_char == 315 || token_char == 320 || token_char == 325)
  3263.   {           /* option or line */
  3264.     pop_token(field);
  3265.     strupr(field); /* make case insensitive */
  3266.     add_efl_data(field);
  3267.     f[fopcount].fappo = appcount;
  3268.     f[fopcount].fop = token_char;
  3269.     fopcount++;
  3270.   }           /* option or line */
  3271.   l[lopcount].fopend = fopcount;
  3272.   lopcount++;
  3273. }           /* store_commands */
  3274.  
  3275. void test_range(char *string)
  3276. {           /* used in store_commands to test range of match or field
  3277.             * entry */
  3278.   int i, fieldpos = 160, op;
  3279.   pop_token(field);
  3280.   if (check_token() != 888)
  3281.   {           /* no number specified */
  3282.     print_error("\007No %s numbers specified in line %d\n", string, linecount);
  3283.   }           /* no number specified */
  3284.   f[fopcount].fstart = (abs(atoi(field)) - 1);
  3285.   f[fopcount].flen = 1;
  3286.   pop_token(field);
  3287.   if (check_token() == 888)
  3288.   {           /* got a number */
  3289.     i = abs(atoi(field)) - 1;
  3290.     f[fopcount].flen = i - f[fopcount].fstart + 1;
  3291.     if (f[fopcount].flen < 1)
  3292.       print_error("\007Invalid %s range in line %d\n", string, linecount);
  3293.     pop_token(field);
  3294.   }           /* got number */
  3295.   if (f[fopcount].fstart + f[fopcount].flen > 160)
  3296.     print_error("\007%s specification > 160 in line %d\n", string, linecount);
  3297.   for (i = l[lopcount].fopstart; i <= fopcount; i++)
  3298.   {
  3299.     op = f[i].fop;
  3300.     if (op >= 100 && op < 200)
  3301.     {           /* field operation */
  3302.       if (f[i].fstart + f[i].flen - 1 >= fieldpos)
  3303.     print_error("\007Fields out of order in line %d\n", linecount);
  3304.       fieldpos = f[i].fstart;
  3305.     }           /* field operation */
  3306.   }           /* i */
  3307. }           /* test_range */
  3308.  
  3309. void load_template()
  3310. {
  3311.   if (!(efl_mode & 1))
  3312.     return;
  3313. #ifdef unix
  3314.   strlwr(efl_file);
  3315. #endif
  3316.   lfile = fopen(efl_file, FOPEN_READ);
  3317.   if (lfile == NULL)
  3318.   {           /* not found */
  3319.     if (!(efl_mode & 2))
  3320.       return;       /* ignore error, translate without .efl file */
  3321.     print_error("\007External Format File %s not found ...\n", efl_file);
  3322.   }           /* not found */
  3323.  
  3324.   if (efl_mode & 4)
  3325.     fprintf(stderr, "External Format File %s\n", efl_file);
  3326.  
  3327.   linecount = lopcount = fopcount = appcount = 0;
  3328.   /* initialize structures */
  3329.   memset(f, 0, sizeof(foptype));
  3330.   memset(l, 0, sizeof(loptype));
  3331.   memset(efl_data, 0, sizeof(efl_data));
  3332.   while (fgets(temp, 100, lfile))
  3333.   {           /* while there are lines to read */
  3334.     temp[strlen(temp) - 1] = 0; /* get rid of lf */
  3335.     linecount++;
  3336.     if (temp[0] == ';' || temp[0] == '#')
  3337.       continue;    /* skip comment */
  3338.     token_count = 0;    /* tokens found on this line */
  3339.     while (store_next_token()); /* store tokens from entire line */
  3340.     if (token_count)
  3341.       store_commands(); /* tokens were found */
  3342.   }           /* while */
  3343.   if (lopcount)
  3344.   {
  3345.     lopactive = TRUE;
  3346.     if (efl_mode & 4)
  3347.       fprintf(stderr, "%d External Format lines were Processed\n", linecount);
  3348.   }
  3349.   else
  3350.     fprintf(stderr, "No external format lines were processed\n");
  3351.   fclose(lfile);
  3352. }           /* load_template */
  3353.  
  3354. void do_translate()
  3355. {
  3356.   int subtotal_eq = 0, grade_save = xgrade;
  3357.   int hyphen_mode_save, i, j;
  3358.  
  3359.   copies++;
  3360.   current_pass = 1;
  3361.   xformat_save = xformat;
  3362.   toc_line[0] = '\0';
  3363. get_next_pass:
  3364.   /* initialize variables before translation */
  3365.   memset(tabtable, 0, sizeof(tabtable));
  3366.   pgroup = pjoin = join = rjoin = group = FALSE;
  3367.   xacronym = braille_page_nums = TRUE;
  3368.   xcenter = FALSE;
  3369.   blank_lines = djoin = toc_line_count = auto_toc_flag = 0;
  3370.   xtab = dobook = xdouble = xheading = xfooting = FALSE;
  3371.   if (current_pass == 1)
  3372.     makefoot = makehead = FALSE;
  3373.   pageset = FALSE;
  3374.   doroman = FALSE;
  3375.   pagenumlen = 4 * (dopagenum == TRUE);
  3376.   disablecol = fillit = FALSE;
  3377.   quotecount = 0;
  3378.   margin = setmargin = oldmargin = 1;
  3379.   tabmargin = FALSE;
  3380.   bpageb = bpagec = blinec = actualpage = lineinct = inpglen = it_flag = 0;
  3381.   total_equations = toc_word = hyphen_searches = hyphen_matches = total_ham_calls = 0;
  3382.   hyphens_used = consec_hyphens = hyphens_skipped = 0;
  3383.   total_words = total_cells = total_rejoins = total_lines = total_not_rejoined = 0l;
  3384.   memset(total_dots, 0, 28);
  3385.   field[0] = 0;
  3386.   addchar[0] = 0;
  3387.   curmax = maxline;
  3388.   linelength = maxline + 1 - margin;
  3389.   plinein = &linein[0];
  3390.   fill_length = 7;
  3391.   done = FALSE;
  3392.   top_of_form();
  3393.   bline[0] = '\0';
  3394.   if (!total_words)
  3395.   {
  3396.     if (print_file)
  3397.     {           /* file */
  3398.       strcpy(bline, inf_name + (print_file > 1) * inf_path_len);
  3399.       if (!print_date)
  3400.     bline[curmax - 4] = '\0';
  3401.       else
  3402.     bline[20 + 12 * (print_date > 1)] = '\0';       /* leave room for date */
  3403. #ifdef DOS
  3404.       strlwr(bline);
  3405. #endif
  3406.     }           /* file */
  3407.     if (print_date)
  3408.     {           /* date */
  3409.       if (bline[0])
  3410.     strcat(bline, " ");
  3411.       if (print_date > 1)
  3412.     date_string[12] = '\0';
  3413.       strcat(bline, date_string);
  3414.       date_string[12] = ' ';
  3415.     }           /* date */
  3416.     if (bline[0] && pagestart == 1)
  3417.       bpurge();
  3418.     bline[0] = 0;
  3419.   }
  3420.  
  3421.   if (inf_des)
  3422.     lseek(inf_des, 0l, 0);    /* start from beginning for each copy */
  3423.   bytes_in_buf = 0;/* no bytes in iobuf */
  3424.   do
  3425.   {
  3426.     get_word();
  3427.     if (math_flag && xgrade > 0)
  3428.     {           /* math */
  3429.       if (is_equation())
  3430.       {        /* equation */
  3431.     subtotal_eq++;
  3432.     if (subtotal_eq == 1)
  3433.     {
  3434.       reload_table = TRUE;
  3435.       load_tables(math_table);
  3436.     }
  3437.       }        /* equation */
  3438.       else
  3439.       if (subtotal_eq)
  3440.       {
  3441.     subtotal_eq = 0;
  3442.     reload_table = TRUE;
  3443.     load_tables(table_file[0]);
  3444.       }
  3445.     }           /* math */
  3446.     if (plinein >= eolptr)
  3447.     {           /* last word on line */
  3448.       if (fillit && got_toc_page == 0 && (words[0] == '$' || words[0] == '`'))
  3449.       {        /* last toc word */
  3450.     if (words[0] == '`')
  3451.       delete(words, 1);
  3452.     last_toc_word = TRUE;
  3453.       }        /* last toc word */
  3454.       if ((rejoin & BIT0) && hyp_dic_ptr)
  3455.       {        /* rejoin is active and dictionary is open */
  3456.     j = strlen(words);
  3457.     if (j > 1 && words[j - 1] == '-')
  3458.       if ((ISalpha(words[j - 2]) && strpbrk(words, "*+/%()") == NULL) ||
  3459.           (trans_mode == 3 && words[0] != '-'))
  3460.       {       /* proposed hyphenated word */
  3461.         strcpy(wline, words);    /* save partial word */
  3462.         get_word();
  3463.         if ((ISalpha(words[0]) && ISalpha(words[1]) &&
  3464.          strchr(words, '-') == NULL) || trans_mode == 3)
  3465.         {       /* join */
  3466.           if (strlen(words) + strlen(wline) > 200)
  3467.         print_error("\7Joined word > 200 characters line %ld\n",
  3468.                 total_lines);
  3469.           strncpy_zero(wline + j - 1, words, sizeof(words) - j);
  3470.           strcpy(words, wline);
  3471.           strcpy(field, words);
  3472.           hyphen_mode_save = hyphen_mode;
  3473.           hyphen_mode = 13;
  3474.           if (trans_mode == 3)
  3475.           {    /* back translate */
  3476.         i = (strchr(lead_back_punct, field[0]) != NULL);
  3477.         translate_word(field + i, bword);
  3478.         strcpy(field, bword);
  3479.           }    /* back translate */
  3480.           strupr(field);
  3481.           i = search_hyphen_dictionary(field);
  3482.           hyphen_mode = hyphen_mode_save;
  3483.           hyphen_searches--;
  3484.           if (i)
  3485.           {    /* word in dictionary */
  3486.         total_rejoins++;
  3487.         if (rejoin & BIT1)
  3488.           fprintf(rejoin_out_ptr, "%s rejoined input line %ld output page %d\n",
  3489.               field, total_lines, bpagec);
  3490.           }    /* word in dictionary */
  3491.           else
  3492.           {    /* word not in dictionary */
  3493.         total_not_rejoined++;
  3494.         if (rejoin & BIT2)
  3495.           fprintf(rejoin_out_ptr, "%s not rejoined input line %ld output page %d\n",
  3496.               field, total_lines, bpagec);
  3497.         goto no_rejoin;
  3498.           }    /* word not in dictionary */
  3499.         }       /* join */
  3500.         else
  3501.         {       /* doesn't begin with a letter so don't join */
  3502.       no_rejoin:
  3503.           plinein = &linein[0];    /* unget the word */
  3504.           strcpy(words, wline);    /* restore previous word */
  3505.           words[j - 1] = '-';
  3506.           words[j] = '\0';
  3507.           rjoin = TRUE;
  3508.         }       /* word doesn't begin with letter so don't join */
  3509.       }       /* proposed hyphenated word */
  3510.       }        /* rejoin is active and dictionary is open */
  3511.     }           /* last word on line */
  3512.     if (words[0])
  3513.     {           /* word not empty */
  3514.       total_words++;
  3515.       if (xgrade)
  3516.       {        /* grade 1-3 */
  3517.     check_ham_call(words);
  3518.     translate_word(words, bword);
  3519.       }        /* grade 1-3 */
  3520.       else
  3521.       {        /* computer braille */
  3522.     if (!grade_mod)
  3523.     {       /* grade 0 no translation */
  3524.       strcpy(bword, words);
  3525.       strcpy(bword6, words);
  3526.       if (output_case & 2)
  3527.         strupr(bword);
  3528.     }       /* grade 0 no translation */
  3529.     else
  3530.       add_case();
  3531.       }        /* computer braille */
  3532.       if (plinein >= eolptr && line_end[0])
  3533.     strcat(bword, line_end);
  3534.       build_line();
  3535.     }           /* word not empty */
  3536.     if (keep_format && (plinein >= eolptr || linein[0] == '\0'))
  3537.     {
  3538.       bpurge();
  3539.     }
  3540.     if (stdin_tty)
  3541.       check_keyboard(1);
  3542.   }           /* while */
  3543.   while (!done);
  3544.   if (inf_des_save != inf_des)
  3545.     close(inf_des);/* close linked file */
  3546.   inf_des = inf_des_save;
  3547.   if (ab_flag)
  3548.     return;
  3549.   if (find_toc_pages && current_pass < 2)
  3550.   {           /* end first pass with toc */
  3551.     /* look for toc entry without corresponding title */
  3552.     for (i = 0; i < MAX_TOC_ENTRY; i++)
  3553.     {
  3554.       if (toc_pages[i].braille < 0)
  3555.     print_error("\007Cannot find matching ~F%d in %s\n", i + 1, inf_name);
  3556.       if (dobook && (book_mode & 4) &&
  3557.       toc_pages[i].braille > 0 && toc_pages[i].print == 0)
  3558.     print_error("\7Ink-print page undefined for ~f%d\n", i + 1);
  3559.     }           /* i */
  3560.     if (dobook && (book_mode & 4))
  3561.  
  3562.       if (bpagec < pagestart_save && pagestart != 32766)
  3563.     goto delete;
  3564.     current_pass++;
  3565.     pagestart = pagestart_save;
  3566.     pageend = pageend_save;
  3567.     xformat = xformat_save;
  3568.     xgrade = grade_save;
  3569.     goto get_next_pass;
  3570.   }
  3571.   if (bpagec < pagestart && pagestart != 32766)
  3572.   {
  3573.     if (strcmp(outf_name, prn))
  3574.     {
  3575.   delete:close(outf_des);
  3576.       unlink(outf_name);
  3577.     }
  3578.     return;
  3579.   }
  3580.   if (strcmp(bline, indent))
  3581.   {
  3582.     bpurge();
  3583.     if (xfooting && blinec > 0)
  3584.     {           /* put footing on last page */
  3585.       for (i = blinec + 2; i <= linesperpage; i++)
  3586.     if (page_in_range())
  3587.       write_string(" ", 1);
  3588.       if (page_in_range())
  3589.     write_string(fline, 1);
  3590.       blinec = linesperpage;
  3591.     }           /* put footing on last page */
  3592.   }
  3593.  
  3594.   if (blinec > 0)
  3595.   {           /* advance to top of next page */
  3596.     advance_page();
  3597.     /* we are at the top of bpagec+1 */
  3598.     actualpage++;
  3599.   }           /* advance to top of next page */
  3600.  
  3601.   if (interpoint)
  3602.   {
  3603.     if (!(actualpage & 1))
  3604.     {           /* skip interpoint even page */
  3605.       blinec = 0;  /* skip whole page */
  3606.       advance_page();
  3607.     }           /* skip interpoint even page */
  3608.     if (interpoint > 1)
  3609.       for (i = 0; i < 2; i++)
  3610.     advance_page();
  3611.   }           /* interpoint */
  3612. }           /* do_translate */
  3613.  
  3614. void translate_word(char *wordstring, char *bwordstring)
  3615. {
  3616.   if (trans_mode == 3)
  3617.     strupr(wordstring);
  3618.   set_vect(wordstring);
  3619.   trans_word(wordstring);
  3620.   build_word(wordstring, bwordstring);
  3621. }           /* translate_word */
  3622.  
  3623. void write_stat_file()
  3624. {
  3625.   int i;
  3626.   if (bpagec < pagestart)
  3627.     return;       /* no output */
  3628.   if (stat_file[0] && intext == NULL)
  3629.     intext = fopen(stat_file, "a");
  3630.   if (intext != NULL)
  3631.   {           /* open */
  3632.     time(&time2);
  3633.     time2 -= time1;
  3634.     fprintf(intext, "%s\n", date_string);
  3635.     if (inf_name[0])
  3636.       fprintf(intext, "Input File: %s\n", inf_name);
  3637.     fprintf(intext, "Translation time: %ld minutes %ld seconds\n", time2 / 60l, time2 % 60l);
  3638.     fprintf(intext, "LinesPerPage: %d\n", linesperpage);
  3639.     fprintf(intext, "LineLength: %d\n", curmax);
  3640.     if (remove_page_nums > 1)
  3641.       fprintf(intext, "Max Length of Input Line: %d\n", remove_page_nums);
  3642.     fprintf(intext, "Words: %ld\n", total_words);
  3643.     fprintf(intext, "Pages: %d\n", bpagec);
  3644.     fprintf(intext, "Words per Page: %ld\n", total_words / (long) bpagec);
  3645.     if (time2)
  3646.     {
  3647.       fprintf(intext, "Words per Second: %ld\n", total_words / time2);
  3648.       fprintf(intext, "Characters per Second: %ld\n", total_cells / time2);
  3649.     }
  3650.     if (current_pass == 2)
  3651.       fprintf(intext, "Passes: 2\n");
  3652.     if (trans_mode != 3)
  3653.       fprintf(intext, "Estimated Embossing Time: %ld Minutes\n", emboss_time);
  3654.     if (total_rejoins)
  3655.       fprintf(intext, "Rejoined words: %ld\n", total_rejoins);
  3656.     if (total_not_rejoined)
  3657.       fprintf(intext, "Words not rejoined: %ld\n", total_not_rejoined);
  3658.     if (hyphen_searches)
  3659.       fprintf(intext, "Hyphen Searches: %d\n", hyphen_searches);
  3660.     if (hyphen_matches)
  3661.       fprintf(intext, "Hyphen Matches: %d\n", hyphen_matches);
  3662.     if (hyphens_used)
  3663.       fprintf(intext, "Hyphens Used: %d\n", hyphens_used);
  3664.     if (hyphens_skipped)
  3665.       fprintf(intext, "Hyphens Skipped: %d\n", hyphens_skipped);
  3666.     if (trans_mode != 3)
  3667.     {           /* not back translate */
  3668.       if (total_equations)
  3669.     fprintf(intext, "equations: %d\n", total_equations);
  3670.       if (total_ham_calls)
  3671.     fprintf(intext, "Amateur Calls: %d\n", total_ham_calls);
  3672.       fprintf(intext, "Total Cells: %ld\n", total_cells);
  3673.       total = 0l;
  3674.       for (i = 0; i <= 5; i++)
  3675.     total += total_dots[i];
  3676.       fprintf(intext, "Total Dots: %ld\n", total);
  3677.       if (total)
  3678.     for (i = 0; i <= 5; i++)
  3679.       fprintf(intext, "Dot%d: %6ld = %ld%%\n", i + 1, total_dots[i],
  3680.           total_dots[i] * 100l / total);
  3681.       if (total_dots[6])
  3682.     fprintf(intext, "Dot 7: %6ld\n", total_dots[6]);
  3683.     }           /* not back translate */
  3684.     if (in_length)
  3685.       fprintf(intext, "Input file length: %ld\n", in_length);
  3686.     fprintf(intext, "Output file length: %ld\n", out_length);
  3687.     if (!ab_flag)
  3688.       if (in_length != 0l && ab_flag == 0 && out_length != 0)
  3689.     fprintf(intext, "Output is %ld%% of input\n", 100l * out_length / in_length);
  3690.     if (ab_flag)
  3691.       fprintf(intext, "Aborted\n");
  3692.     fprintf(intext, "Entries in table: %d\n\n", table_entries);
  3693.   }           /* open */
  3694. }           /* write_stat_file */
  3695.  
  3696. void advance_page()
  3697. {
  3698.   int i;
  3699.   if (lineskips < 99)
  3700.     for (i = blinec; i < linesperpage + lineskips; i++)
  3701.     {
  3702.       write_string(" ", 1);     /* do it with linefeeds */
  3703.     }
  3704.   if (lineskips == 99)
  3705.     write_char(12);/* do it with a formfeed */
  3706.   if (lineskips == 999)
  3707.     write_char(11);/* vertical tab no lf */
  3708.   if (lineskips == 9999)
  3709.   {
  3710.     write_string("\14", 0);     /* formfeed with linefeed */
  3711.     printf("\nTo Continue, Press Return\n");
  3712.     getch();
  3713.   }
  3714. }           /* advance_page */
  3715.  
  3716. FILE *open_option_file(char *name)
  3717. {           /* store file name in temp and attempt to open for reading */
  3718.   char *f = field + 10;
  3719.   FILE *fptr;
  3720.   strcpy(f, name);
  3721.   if (name[0] == '/' || name[1] == ':')
  3722.     strcpy(temp, f);    /* path already specified */
  3723.   else
  3724.     sprintf(temp, "%s%s", transpath, f);
  3725.   if ((fptr = fopen(temp, FOPEN_READ)) == NULL)
  3726.     report_open_error(temp);
  3727.   return (fptr);
  3728. }           /* open_option_file */
  3729.  
  3730. void load_tables(char *table_name)
  3731. {
  3732.   int i, j, k, error = 0;
  3733.   char match[MAX_MATCH + 1], prev_match[MAX_MATCH + 1];
  3734.   int lenmat, lenrep, typex;
  3735.   FILE *btable;
  3736.   char *ver_bar, *c;
  3737.   if (!reload_table)
  3738.     return;
  3739.   reload_table = FALSE;
  3740.   btable = open_option_file(table_name);
  3741.   strcpy(active_table, table_name);
  3742.   table_entries = current_table_line = 0;
  3743.   memset(b, 0, sizeof(tablet)); /* fill in structure with zeros */
  3744.   prev_match[0] = '\0'; /* forces mismatch between match and prev_match on
  3745.              * first line */
  3746.   while (fgets(temp, 80, btable))
  3747.   {           /* while there are lines to read */
  3748.     current_table_line++;
  3749.     trim(temp);
  3750.     /* skip blank lines and comments starting with ; or # */
  3751.     if (temp[0] < ' ' || temp[0] == ';' || temp[0] == '#')
  3752.       continue;
  3753.     strupr(temp);
  3754.     if (isalpha(temp[0]) && temp[2] == '=')
  3755.     {           /* option */
  3756.       process_options(temp, 4);
  3757.       continue;
  3758.     }           /* option */
  3759.     if ((ver_bar = strchr(temp, vbar)) == NULL)
  3760.     {           /* error */
  3761.   no_ver_bar:error++;
  3762.       fprintf(stderr, "\7Improper placement of | error in line %d\n",
  3763.           current_table_line);
  3764.       break;
  3765.     }           /* error */
  3766.     *ver_bar = (char) 0;
  3767.     typex = atoi(temp);
  3768.     *ver_bar = vbar;    /* restore temp */
  3769.     c = ver_bar + 1;    /* beginning of match */
  3770.     if ((ver_bar = strchr(ver_bar + 1, vbar)) == NULL)
  3771.       goto no_ver_bar;
  3772.     *ver_bar = (char) 0;
  3773.     if (test_bracket(c, 1))
  3774.       error++;
  3775.     lenmat = (int) strlen(c);
  3776.     if (lenmat > MAX_MATCH)
  3777.     {           /* too long */
  3778.       fprintf(stderr, "\7Match more than %d characters in line %d\n%s\n",
  3779.           MAX_MATCH, current_table_line, temp);
  3780.       error++;
  3781.       break;
  3782.     }           /* too long */
  3783.     strcpy(match, c);
  3784.     *ver_bar = vbar;    /* restore temp */
  3785.     c = strchr(ver_bar, ' ');
  3786.     if (c)
  3787.       *c = '\0';   /* remove extra comment words after table entry */
  3788.     if (test_bracket(ver_bar + 1, 2))
  3789.       error++;
  3790.     if (error)
  3791.       break;
  3792.     lenrep = (int) strlen(ver_bar + 1);
  3793.     if (lenrep > MAX_REP)
  3794.     {           /* replace too long */
  3795.       fprintf(stderr, "\7Replace more than %d characters in line %d\n%s\n",
  3796.           MAX_REP, current_table_line, temp);
  3797.       error++;
  3798.       break;
  3799.     }           /* replace too long */
  3800.     if (table_entries >= MAXTAB)
  3801.     {           /* too many entries */
  3802.       fprintf(stderr, "\7More than %d entries in table not allowed\n", MAXTAB);
  3803.       error++;
  3804.       break;
  3805.     }           /* too many entries */
  3806.     if (typex <= -32 || typex >= 64)
  3807.     {           /* bad type */
  3808.   bad_type:
  3809.       fprintf(stderr, "\7Invalid type %d in line %d\n", typex, current_table_line);
  3810.       error++;
  3811.       break;
  3812.     }           /* type error */
  3813.     if (xgrade == 3)
  3814.     {           /* grade 3 */
  3815.       if (grade_mod == 0 && typex < 0)
  3816.     continue;  /* skip unwanted g2 entry */
  3817.       typex = abs(typex);
  3818.       if (typex > 32 && grade_mod > 0)
  3819.       {        /* grade_mod nonstandard grade 3 */
  3820.     /* skip entries other than dot 4 5 45 and 456 contractions */
  3821.     if (!strpbrk(ver_bar + 1, "@\042^_"))
  3822.       continue;
  3823.     temp[1] = '\0';
  3824.     temp[0] = ver_bar[2];
  3825.     if ((grade_mod & 1) && (isupper(temp[0])))
  3826.       goto keep_entry;
  3827.     if ((grade_mod & 2) && (Isdigit(temp[0])))
  3828.       goto keep_entry;
  3829.     if ((grade_mod & 4) && (strpbrk(temp, single_dot) == NULL)
  3830.         && (grade_mod & 3) == 0)
  3831.       goto keep_entry;
  3832.     if ((grade_mod & 8) && strpbrk(temp, single_dot))
  3833.       goto keep_entry;
  3834.     continue;
  3835.       }        /* grade_mod */
  3836.  
  3837.   keep_entry:
  3838.       typex &= 31;
  3839.     }           /* grade 3 */
  3840.     else
  3841.     if (typex > 32)
  3842.       continue;    /* skip g3 entry */
  3843.     if (typex > 29)
  3844.       goto bad_type;
  3845.     if (trans_mode < 3)
  3846.     {
  3847.       if (typex > 16 && typex < 19)
  3848.     goto bad_type;
  3849.     }
  3850.     else
  3851.     if ((typex > 10 && typex < 17) || typex > 19)
  3852.       goto bad_type;
  3853.     if (table_entries)    /* store previous match in prev_match */
  3854.       strcpy(prev_match, b->match[table_entries]);
  3855.     table_entries++;    /* we found a valid line, store results */
  3856.     b->typex[table_entries] = abs(typex);
  3857.     strcpy(b->match[table_entries], match);
  3858.     strcpy(b->replace[table_entries], ver_bar + 1);
  3859.     j = (int) (match[0] - '@');
  3860.     if (j < 0 || j > 27)
  3861.       j = 0;
  3862.     if (strcmp(prev_match, match) >= 0)
  3863.       if (strncmp(prev_match, match, lenmat))
  3864.       {
  3865.     fprintf(stderr, "\007Sorting error in line %d\n", current_table_line);
  3866.     error++;
  3867.     break;
  3868.       }
  3869.     if (match[0] != prev_match[0])
  3870.     {           /* first characters differ */
  3871.       if (match[0] >= 'A' && match[0] <= 'Z')
  3872.       {        /* letter */
  3873.     if (lenmat != 1 && trans_mode < 3)
  3874.     {       /* error */
  3875.       fprintf(stderr, "\007Match should be a single character in line %d %s\n"
  3876.           ,current_table_line, temp);
  3877.       error++;
  3878.       break;
  3879.     }       /* error */
  3880.     for (i = 0; i < 27; i++)
  3881.       b->start2[j][i] = table_entries;
  3882.       }        /* letter */
  3883.       b->start1[(int) (unsigned char) (match[0])] = table_entries;
  3884.     }           /* first characters differ */
  3885.     else
  3886.     if ((match[1] != prev_match[1]))
  3887.     {           /* second element of match and previous match differ */
  3888.       k = (int) (match[1] - '@');
  3889.       if (k > 0 && k < 27)
  3890.     b->start2[j][k] = table_entries;
  3891.     }           /* second elements differ */
  3892.   }           /* while */
  3893.   fclose(btable);
  3894.   if (error)
  3895.     print_error("Correct error in %s and restart program.\n", table_name);
  3896. }           /* load_tables */
  3897.  
  3898. int test_bracket(char *c, int x)
  3899. {
  3900.   char *bracket;
  3901.   do
  3902.   {
  3903.     bracket = strchr(c, '[');
  3904.     if (bracket && bracket[1] >= '0' && bracket[1] <= '9')
  3905.     {           /* digit */
  3906.       if (!strchr(bracket, ']'))
  3907.       {        /* no ] */
  3908.     if (x > 1)
  3909.       break;
  3910.     fprintf(stderr, "\7Unmatched bracket in line %d\n",
  3911.         current_table_line);
  3912.     return (1);
  3913.       }        /* no ] */
  3914.       bracket[0] = (unsigned char) get_integer(bracket + 1);
  3915.       delete(bracket + 1, 1);
  3916.     }           /* digit */
  3917.     else
  3918.       bracket = NULL;
  3919.   }
  3920.   while (bracket);
  3921.   return (0);
  3922. }           /* test_bracket */
  3923.  
  3924. int search_hyphen_dictionary(char *string)
  3925. {           /* returns length of word if in dictionary otherwise 0 */
  3926.   int k, l, index, string_len, leading = 0;
  3927.   char *cptr, *h, lead[4];
  3928.   char hword[MAX_DIC_LEN + 1], prev = 'A';
  3929.   dash_flag = 0;
  3930.   if (hyphen_mode & BIT1)
  3931.   {           /* test for dash */
  3932.     cptr = strchr(string, '-');
  3933.     if (cptr)
  3934.     {           /* found dash */
  3935.       cptr--;
  3936.       if (isalpha(cptr[0]) && isalpha(cptr[2]))
  3937.       {        /* - between letters */
  3938.     string[MAX_DIC_LEN] = '\0';
  3939.     strcpy(hyphen_dic_line, string);
  3940.     hyphen_searches++;
  3941.     hyphen_line_count = 0;
  3942.     string_len = strlen(string);
  3943.     if (string[string_len - 1] == '-')
  3944.       string_len--;
  3945.     dash_flag = 1;
  3946.     return (string_len);
  3947.       }        /* - between letters */
  3948.     }           /* found dash */
  3949.   }           /* test for dash */
  3950.   if (!(hyphen_mode & BIT0))
  3951.     return (0);    /* not active */
  3952.   if (hyphen_mode & BIT2)
  3953.   {           /* look for leading punctuation */
  3954.     lead[0] = lead[1] = '\0';
  3955.     if (strchr(leading_punct, string[0]))
  3956.     {
  3957.       leading = 1;
  3958.       lead[0] = string[0];
  3959.     }
  3960.   }           /* look for leading punctuation */
  3961.   hyphen_searches++;    /* for statistics file */
  3962.   index = (int) (unsigned char) string[leading] - 65;
  3963.   if (index < 0 || index > 191)
  3964.     return (0);    /* search word doesn't begin with a letter */
  3965.   if (hyphen_mode & BIT3)
  3966.     remove_trailing_punct(string);
  3967.   /*
  3968.    * seek to where word with this letter starts otherwise where previous
  3969.    * letter starts
  3970.    */
  3971.   while (index > 0 && hyphen_dic_start[index].pos == 0l)
  3972.     index--;
  3973.   fseek(hyp_dic_ptr, hyphen_dic_start[index].pos, 0);
  3974.   hyphen_line_count = hyphen_dic_start[index].line;
  3975.   while (fgets(hyphen_dic_line, MAX_DIC_LEN, hyp_dic_ptr))
  3976.   {
  3977.     hyphen_line_count++;
  3978.     l = strlen(hyphen_dic_line);
  3979.     hyphen_dic_line[l - 1] = 0; /* remove lf */
  3980.     if (prev != hyphen_dic_line[0])
  3981.     {           /* first word starting with this letter */
  3982.       index = (int) (unsigned char) hyphen_dic_line[0] - 65;
  3983.       if (index < 1 || index > 191)
  3984.       {
  3985.     fprintf(stderr,
  3986.         "\7Line %d in %s must begin with letters or extended \n",
  3987.         hyphen_line_count, hyphen_dic_name);
  3988.     print_error("graphics characters\n");
  3989.       }
  3990.       if (!hyphen_dic_start[index].pos)
  3991.       {        /* store word position */
  3992.     hyphen_dic_start[index].pos = ftell(hyp_dic_ptr) - (long) (l + 1);
  3993. #ifdef unix
  3994.     hyphen_dic_start[index].pos++;    /* no cr in unix */
  3995. #endif
  3996.     hyphen_dic_start[index].line = hyphen_line_count - 1;
  3997.       }        /* store word position */
  3998.       prev = hyphen_dic_line[0];
  3999.     }           /* first word starting with this letter */
  4000.     /* build hword by removing all dashes & | from the line */
  4001.     k = 0;
  4002.     h = hyphen_dic_line;
  4003.     for (; *h; h++)
  4004.       if (*h != '-' && *h != vbar)
  4005.     hword[k++] = *h;
  4006.     hword[k] = 0;
  4007.     k = strcmp(hword, string + leading);
  4008.     if (k < 0)
  4009.       continue;
  4010.     if (hyphen_mode & BIT3)
  4011.     {
  4012.       strcat(hyphen_dic_line, temp);    /* restore trailing punctuation */
  4013.       strcat(string, temp);
  4014.     }
  4015.     if (hyphen_mode & BIT2)
  4016.       insert(lead, hyphen_dic_line);
  4017.     if (k > 0)
  4018.       return (FALSE);    /* word not found */
  4019.     l = strlen(hyphen_dic_line);
  4020.     return (l - 2);
  4021.   }           /* while */
  4022.   return (FALSE);
  4023. }           /* search_hyphen_dictionary */
  4024.  
  4025. void insert_hyphen_word()
  4026. {           /* temp contains word with dashes to insert.
  4027.             * hyphen_dic_line contains word with dashes removed */
  4028.   int i, j = 0, l, lines = 0, flag = 0;
  4029.   char *temp_hyp_file = field + 100;
  4030.   FILE *tempfile;
  4031.   strcpy(temp_hyp_file, hyphen_dic_name);
  4032.   for (i = 0; temp_hyp_file[i]; i++)
  4033.     if (temp_hyp_file[i] == '\\' || temp_hyp_file[i] == ':' || temp_hyp_file[i] == '/')
  4034.       j = i + 1;
  4035.   strcpy(temp_hyp_file + j, "tmphyp.$$$");
  4036.   fseek(hyp_dic_ptr, 0l, 0);
  4037.   tempfile = fopen(temp_hyp_file, "w");
  4038.   if (!tempfile)
  4039.     print_error("\7Cannot open temp hyphen dictionary\n");
  4040.   hyp_words_added++;
  4041.   fprintf(stderr, "Inserting %s at line ", hyphen_dic_line);
  4042.   l = (int) (unsigned char) hyphen_dic_line[0] - 64;
  4043.   j = strlen(temp) + 2;
  4044. #ifdef unix
  4045.   j--;
  4046. #endif
  4047.   for (i = l; i < 191; i++)
  4048.     if (hyphen_dic_start[i].pos)
  4049.     {
  4050.       hyphen_dic_start[i].pos += (long) j;
  4051.       hyphen_dic_start[i].line++;
  4052.     }
  4053.   while (fgets(field, 80, hyp_dic_ptr))
  4054.   {
  4055.     lines++;
  4056.     l = strlen(field);
  4057.     field[l - 1] = 0;
  4058.     strcpy(field + 50, field);
  4059.     remove_dashes(field + 50, 1);
  4060.     if (strcmp(field + 50, hyphen_dic_line) > 0 && flag == 0)
  4061.     {
  4062.       flag++;
  4063.       if (fprintf(tempfile, "%s\n", temp) < 0)
  4064.     no_space();
  4065.       fprintf(stderr, "%d\n", lines);
  4066.     }
  4067.     if (fprintf(tempfile, "%s\n", field) < 0)
  4068.       no_space();
  4069.   }           /* while */
  4070.   fclose(tempfile);
  4071.   fclose(hyp_dic_ptr);
  4072.   unlink(hyphen_dic_name);
  4073.   rename(temp_hyp_file, hyphen_dic_name);
  4074.   hyp_dic_ptr = NULL;
  4075.   open_hyp_dictionary(hyphen_dic_name, (hyp_words_added % hyp_int == 0));
  4076. }           /* insert_hyphen_word */
  4077.  
  4078. void remove_trailing_punct(char *string)
  4079. {           /* test for punctuation */
  4080.   int string_len;
  4081.   char *cptr;
  4082.   string_len = (int) (strlen(string) - 1);
  4083.   cptr = strpbrk(string + 1, trailing_punct);
  4084.   if (cptr)
  4085.   {           /* ends in punctuation */
  4086.     strncpy_zero(temp, cptr, 5);    /* so hyphen_dic_line won't overflow */
  4087.     *cptr = '\0';
  4088.   }           /* ends in punctuation */
  4089.   else
  4090.     temp[0] = '\0';
  4091. }           /* remove_trailing_punct */
  4092.  
  4093. void test_hyphen_dictionary(int mode)
  4094. {
  4095.   int i, l;
  4096.   unsigned k, total = 0, dash_line = 0, long_line = 0, max_len = 0, max_dash = 0;
  4097.   char hword[MAX_DIC_LEN + 1], prevword[MAX_DIC_LEN + 1];
  4098.   if (mode == 1)
  4099.     fprintf(stderr, "Checking consistency of %s Please Wait...\n", hyphen_dic_name);
  4100.   hyp_dic_tested = TRUE;
  4101.   prevword[0] = 0;
  4102.   fseek(hyp_dic_ptr, 0l, 0);
  4103.   while (fgets(temp, 80, hyp_dic_ptr))
  4104.   {
  4105.     total++;
  4106. /*test for uppercase*/
  4107.     strcpy(field, temp);
  4108.     strupr(field);
  4109.     if (strcmp(field, temp))
  4110.       print_error("\7Line %u must be uppercase\n", total);
  4111.     if (!strchr(temp, '-'))
  4112.       print_error("\7- not found in line %u\n", total);
  4113.     k = strlen(temp);
  4114.     if (temp[k - 2] == '-')
  4115.       print_error("\7Word ends with - line %u\n", total);
  4116.     if (k > max_len)
  4117.     {
  4118.       max_len = k;
  4119.       long_line = total;
  4120.       if (k > MAX_DIC_LEN)
  4121.     print_error("\7Word > %d characters in line %u\n", MAX_DIC_LEN, total);
  4122.     }
  4123.     /* build hword by removing all dashes from temp */
  4124.     k = l = 0;
  4125.     for (i = 0; temp[i]; i++)
  4126.       if (temp[i] != '-' && temp[i] != vbar)
  4127.     hword[l++] = temp[i];
  4128.       else
  4129.     k++;
  4130.     if (k > max_dash)
  4131.     {
  4132.       max_dash = k;
  4133.       dash_line = total;
  4134.     }
  4135.     hword[l] = 0;
  4136.     l = strcmp(hword, prevword);
  4137.     if (l < 0)
  4138.       print_error("\7Sorting error in line %u\n", total);
  4139.     if (!l)
  4140.       print_error("\7Duplicate entry in line %u\n", total);
  4141.     strcpy(prevword, hword);
  4142.   }           /* while */
  4143.   if (!mode)
  4144.   {
  4145.     fprintf(stderr, "Longest word is %u characters in line %u\n", max_len, long_line);
  4146.     fprintf(stderr, "Maximum hyphens %u in line %u\n", max_dash, dash_line);
  4147.   }
  4148. }           /* test_hyphen_dictionary */
  4149.  
  4150. void get_config()
  4151. {
  4152.   int i;
  4153.   char *c, *cptr;
  4154.   if (!total_files)
  4155.   {           /* first time called */
  4156.     if (paramcount > 0)
  4157.     {           /* test for cf= */
  4158.       strcpy(temp, paramstr[1]);
  4159.       strupr(temp);
  4160.       if (!strncmp(temp, "CF=", 3))
  4161.       {        /* new config file */
  4162.     strcpy(config_file, paramstr[1] + 3);
  4163.     start_arg++;
  4164.       }        /* new config file */
  4165.     }           /* test for cf= */
  4166.     /*
  4167.      * use nfbtrans environment variable, current directory, and then program
  4168.      * or unix path
  4169.      */
  4170.     c = (char *) getenv("NFBTRANS");
  4171.     if (c)
  4172.     {           /* nfbtrans defined */
  4173.       strcpy(transpath, c);
  4174. #ifdef DOS
  4175.       strcat(transpath, "\\");
  4176. #else
  4177.       strcat(transpath, "/");
  4178. #endif
  4179.     }           /* nfbtrans defined */
  4180.     if (!open_config_file(0))
  4181.     {           /* not in environment */
  4182.       transpath[0] = '\0';
  4183.       if (!open_config_file(0))
  4184.       {        /* not in environment or current directory */
  4185. #ifdef DOS
  4186.     strcpy(transpath, paramstr[0]);
  4187.     c = strrchr(transpath, '\\');
  4188.     if (c)
  4189.       c[1] = 0;/* we have program path */
  4190.     else
  4191.       transpath[0] = '\0';
  4192. #else
  4193.     strcpy(transpath, UNIX_PATH);
  4194. #endif
  4195.     open_config_file(1);
  4196.       }        /* not in current dir or environment */
  4197.     }           /* not in environment */
  4198.   }           /* first time called */
  4199.   else
  4200.     fseek(conf_ptr, 0l, 0);
  4201.   config_lines = 0l;
  4202.   while (fgets(temp, 150, conf_ptr))
  4203.   {           /* while there are lines to read */
  4204.     config_lines++;
  4205.     if (strlen(temp) > 145)
  4206.       print_error("\7Line too long in %s%s\n", transpath,
  4207.           config_file);
  4208.     strupr(temp);
  4209.     trim(temp);
  4210.     if (temp[0] == '\n' || temp[0] == ';' || temp[0] == '#')
  4211.       continue;    /* skip */
  4212.     cptr = strchr(temp, ' ');
  4213.     if (cptr)
  4214.       if (!strchr(quotes, temp[3]))
  4215.     *cptr = 0; /* allows comments starting with second word */
  4216.     process_options(temp, 2);
  4217.   }           /* while */
  4218.   if (hyp_dic_ptr && hyp_dic_tested)
  4219.     rewrite_config();
  4220.   config_lines = 0l;
  4221.   if (!total_files)
  4222.     for (i = start_arg; i <= paramcount; i++)
  4223.     {
  4224.       if (paramstr[i][2] == '=')
  4225.       {        /* xx= */
  4226.     strupr(paramstr[i]);
  4227.     process_options(paramstr[i], 1);
  4228.       }        /* xx= */
  4229.       else
  4230.       {        /* not xx= */
  4231.     usr_default = TRUE;
  4232.     /*
  4233.      * if input is from keyboard assume arguments are input files. Else
  4234.      * ignore
  4235.      */
  4236.     if (stdin_tty)
  4237.       input_file_arg = i;
  4238.     break;
  4239.       }        /* not xx= */
  4240.     }           /* i */
  4241.   if (!stdin_tty)
  4242.   {
  4243.     inf_des = 0;
  4244.     usr_default = TRUE;
  4245.   }
  4246.   if (!stdout_tty)
  4247.   {
  4248.     outf_des = 1;
  4249. #ifdef DOS
  4250.     setmode(1, O_BINARY);
  4251. #endif
  4252.     trans_mode = trans_mode1 = 1;
  4253.   }
  4254.   if (usr_default)
  4255.   {
  4256.     display_source = FALSE;
  4257.     lastcopy = 1;
  4258.     if (pagestart <= 0)
  4259.       pagestart = 1;
  4260.     if (pageend < pagestart)
  4261.       pageend = 9999;    /* print entire document */
  4262.     if (leftmargin < 1)
  4263.       leftmargin = 1;
  4264.     if (maxline <= 1)
  4265.       maxline = 40;
  4266.     if (linesperpage <= 0)
  4267.       linesperpage = 25;
  4268.     if (lineskips < 0)
  4269.       lineskips = 99;
  4270.     if (trans_mode <= 0)
  4271.       trans_mode = 1, trans_mode1 = 2;
  4272.     display_braille = 0;
  4273.   }
  4274. }           /* get_config */
  4275.  
  4276. FILE *open_config_file(int mode)
  4277. {
  4278.   sprintf(temp, "%s%s", transpath, config_file);
  4279.   conf_ptr = fopen(temp, FOPEN_READ);
  4280.   if (mode && conf_ptr == NULL)
  4281.     print_error("\007%s not found\n", config_file);
  4282.   return (conf_ptr);
  4283. }           /* open_config_file */
  4284.  
  4285. void rewrite_config()
  4286. {
  4287.   int h_v = 0;
  4288.   char *buf = field + 50;
  4289.   FILE *f;
  4290.   rewind(conf_ptr);
  4291.   sprintf(field, "%snfb%d", transpath, getpid());
  4292.   f = fopen(field, "w");
  4293.   if (!f)
  4294.     print_error("\7Cannot open %s\n", field);
  4295.  
  4296.   while (fgets(temp, 100, conf_ptr))
  4297.   {           /* while there are lines to read */
  4298.     strcpy(buf, temp);
  4299.     strupr(temp);
  4300.     trim(temp);
  4301.     if (!strncmp(temp, "HV=", 3))
  4302.       continue;
  4303.     if (!strncmp(temp, "HD=", 3))
  4304.     {           /* write hp= option */
  4305.       h_v++;
  4306.       write_hv(f);
  4307.     }           /* write hp= option */
  4308.     if (fprintf(f, string_format, buf) < 0)
  4309.       no_space();
  4310.   }           /* while */
  4311.   if (!h_v)
  4312.     write_hv(f);
  4313.   fclose(f);
  4314.   fclose(conf_ptr);
  4315.   sprintf(temp, "%s%s", transpath, config_file);
  4316.   unlink(temp);
  4317.   rename(field, temp);
  4318.   open_config_file(1);
  4319. }           /* rewrite_config */
  4320.  
  4321. void write_hv(FILE * f)
  4322. {           /* write hv= option into nfbtrans.cnf */
  4323.   int j;
  4324.   strcpy(temp, "hv=");
  4325.   for (j = 0; j < 5; j++)
  4326.     sprintf(temp + strlen(temp), "%s=%ld|", hyp_name_verify[j], hyp_date_verify[j]);
  4327.   temp[strlen(temp) - 1] = '\0';
  4328.   fprintf(f, "%s\n", temp);
  4329. }           /* write_hv */
  4330.  
  4331. void process_options(char *string, int option_mode)
  4332. {
  4333.   int j, x, y;
  4334.   char *cptr = string + 3, *vptr, *eptr, delim;
  4335.   for (j = 0; options[j].name; j++)
  4336.   {
  4337.     if (!strncmp(string, options[j].name, 2))
  4338.     {           /* option matched */
  4339.       if (*cptr <= ' ')
  4340.     print_error("\7Improper option format: %s nothing follows =.\n", string);
  4341.       vptr = strchr(quotes, cptr[0]);
  4342.       if (vptr)
  4343.       {        /* quoted string */
  4344.     delim = *cptr;
  4345.     delete(cptr, 1);
  4346.     vptr = strchr(cptr, delim);
  4347.     if (vptr == NULL)
  4348.     {
  4349.       if (config_lines)
  4350.         total_lines = config_lines;
  4351.       print_error("\007Unmatched quoted string in line %ld",
  4352.               total_lines);
  4353.     }
  4354.     vptr[0] = 0;
  4355.       }        /* quoted string */
  4356.       if (options[j].value & 256)
  4357.     return;    /* ignore this option */
  4358.       if (!(option_mode & options[j].value))
  4359.     report_option_error(option_mode, j);
  4360.       x = atoi(cptr);    /* saves multiple calls to atoi */
  4361.       y = abs(x);
  4362.       switch (j)
  4363.       {
  4364.       case 0:      /* be */
  4365. #ifdef DOS
  4366.     sound(x);
  4367.     get_integer(cptr);
  4368.     x = 0;
  4369.     if (cptr[0])
  4370.       x = get_integer(cptr + 1);
  4371.     if (!x)
  4372.       x = 500;
  4373.     delay(x);
  4374.     nosound();
  4375. #endif
  4376.     break;
  4377.       case 1:      /* bm */
  4378.     book_mode = x;
  4379.     if (book_mode & 8)
  4380.       book_mode |= 4;    /* make sure book TOC bit is set */
  4381.     break;
  4382.       case 2:      /* ca */
  4383.     vptr = strchr(cptr, vbar);
  4384.     if (!vptr)
  4385.       goto no_ver_bar;
  4386.     *vptr = '\0';
  4387.     strncpy_zero(cap_single, cptr, sizeof(cap_single));
  4388.     cptr = strchr(vptr + 1, vbar);
  4389.     if (cptr)
  4390.     {
  4391.       *cptr = '\0';
  4392.       strncpy_zero(letter_sign, cptr + 1, sizeof(letter_sign));
  4393.     }
  4394.     strncpy_zero(cap_all, vptr + 1, sizeof(cap_all));
  4395.     break;
  4396.       case 3:      /* cl */
  4397.     center_length = min(y, 43);
  4398.     break;
  4399.       case 4:      /* co */
  4400.     lastcopy = y;
  4401.     break;
  4402.       case 5:      /* cs */
  4403.     charspersec = y;
  4404.     break;
  4405.       case 6:      /* db */
  4406.     display_braille = y;
  4407.     break;
  4408.       case 7:      /* de */
  4409.     emboss_delay = y;
  4410.     break;
  4411.       case 8:      /* dm */
  4412.     fprintf(stderr, "%s\n", cptr);
  4413.     break;
  4414.       case 9:      /* ds */
  4415.     display_source = y;
  4416.     break;
  4417.       case 10:      /* ef */
  4418.     efl_mode = x;
  4419.     break;
  4420.       case 11:      /* et */
  4421.     expand_tab = min(y, 32);
  4422.     break;
  4423.       case 12:      /* ex */
  4424.     if (total_files)
  4425.       break;   /* only get once from nfbtrans.cnf */
  4426.     for (;;)
  4427.     {
  4428.       if (prog_extension.total >= MAX_EXTENSIONS)
  4429.         print_error(
  4430.           "\007Too many extensions.  only the first %d can be stored\n",
  4431.             MAX_EXTENSIONS);
  4432.       vptr = strchr(cptr, '=');
  4433.       if (vptr == NULL)
  4434.         break; /* no more extensions */
  4435.       *vptr = 0;    /* terminate extension */
  4436.       if (strlen(cptr) > 8)
  4437.         goto invalid;
  4438.       strcpy(prog_extension.prog_ext[prog_extension.total].ext, cptr);
  4439.       *vptr = ' ';  /* in case theres an error */
  4440.       x = (int) (vptr[1] - 48);
  4441.       if (vptr[1] == '-')
  4442.         vptr[1] = '0';
  4443.       if (x > 9)
  4444.         x -= 7;
  4445.       if (x > 14 || isxdigit(vptr[1]) == 0)
  4446.         goto invalid;
  4447.       prog_extension.prog_ext[prog_extension.total].init_val = x;
  4448.       cptr = vptr + 2;
  4449.       prog_extension.total++;
  4450.     }
  4451.     break;
  4452.       case 13:      /* fc */
  4453.     fill_char = *cptr;
  4454.     break;
  4455.       case 14:      /* fp */
  4456.     first_page = y;
  4457.     break;
  4458.       case 15:      /* fs */
  4459.     format_char = *cptr;
  4460.     if (!format_char)
  4461.       format_char = '\r';
  4462.     break;
  4463.       case 16:      /* gd */
  4464.     guide_dots = min(y, 80);
  4465.     break;
  4466.       case 17:      /* gm */
  4467.     graphics_mode = x;
  4468.     break;
  4469.       case 18:      /* hb */
  4470.     strncpy_zero(bad_hyp_fname, cptr, sizeof(bad_hyp_fname));
  4471.     break;
  4472.       case 19:      /* hd */
  4473.     open_hyp_dictionary(cptr, 1);
  4474.     break;
  4475.       case 20:      /* hk */
  4476.     hot_key = y;
  4477.     break;
  4478.       case 21:      /* hl */
  4479.     min_hyp_len = min(y, 4);
  4480.     break;
  4481.       case 22:      /* hm */
  4482.     hyphen_mode = get_integer(cptr);    /* used because option may
  4483.                          * contain a filename */
  4484.     if (dic_out_ptr != NULL && dic_out_ptr != stderr)
  4485.       fclose(dic_out_ptr);
  4486.     dic_out_ptr = NULL;
  4487.     if (*cptr)
  4488.       dic_out_ptr = fopen(cptr, "a");
  4489.     if (!dic_out_ptr)
  4490.       dic_out_ptr = stderr;
  4491.     break;
  4492.       case 23:      /* hn */
  4493.     hyp_int = max(y, 1);
  4494.     break;
  4495.       case 24:      /* hp */
  4496.     max_hyp_page = y;
  4497.     break;
  4498.       case 25:      /* ht */
  4499.     hyp_dic_ptr = open_option_file(cptr);
  4500.     memset(hyphen_dic_start, 0, sizeof(hyphen_dic_start));
  4501.     test_hyphen_dictionary(0);
  4502.     for (;;)
  4503.     {
  4504.       fprintf(stderr, "enter word <RETURN> to exit: ");
  4505.       gets(field);
  4506.       if (strlen(field) < 2)
  4507.         break;
  4508.       strupr(field);
  4509.       if (search_hyphen_dictionary(field))
  4510.         fprintf(stderr, "%s was found on line %u\n", field, hyphen_line_count);
  4511.       else
  4512.         fprintf(stderr, "\7%s not found line %u\n", field, hyphen_line_count);
  4513.     }
  4514.     exit_program(0);
  4515.     break;
  4516.       case 26:      /* hv */
  4517.     j = 0;
  4518.     do
  4519.     {
  4520.       vptr = strchr(cptr, vbar);
  4521.       eptr = strchr(cptr, '=');
  4522.       if (eptr)
  4523.       {       /* found = */
  4524.         *eptr = '\0';
  4525.         if (strcmp(cptr, hyphen_dic_name))
  4526.         {
  4527.           strcpy(hyp_name_verify[j], cptr);
  4528.           hyp_date_verify[j] = (time_t) atol(eptr + 1);
  4529.         }
  4530.         j++;
  4531.       }       /* found = */
  4532.       if (vptr)
  4533.         cptr = vptr + 1;
  4534.     }
  4535.     while (vptr);
  4536.     break;
  4537.       case 27:      /* hx */
  4538.     max_consec_hyphens = y;
  4539.     break;
  4540.       case 28:      /* i0 */
  4541.       case 29:      /* i1 */
  4542.       case 30:      /* i2 */
  4543.       case 31:      /* i3 */
  4544.       case 32:      /* i4 */
  4545.       case 33:      /* i5 */
  4546.       case 34:      /* i6 */
  4547.       case 35:      /* i7 */
  4548.       case 36:      /* i8 */
  4549.       case 37:      /* i9 */
  4550.       case 38:      /* ia */
  4551.       case 39:      /* ib */
  4552.       case 40:      /* ic */
  4553.       case 41:      /* id */
  4554.       case 42:      /* ie */
  4555.     options[j].value = 256; /* ignore from now on */
  4556.     x = (int) (string[1] - 48);
  4557.     if (x > 9)
  4558.       x -= 7;
  4559.     vptr = strchr(cptr, vbar);
  4560.     if (!vptr)
  4561.       no_ver_bar:print_error("\007Missing | in %s\n", string);
  4562.     *vptr = 0;
  4563.     if (strlen(cptr) > MAX_INIT)
  4564.     {
  4565.       init_err:
  4566.       print_error("\007Initialization string > %d characters %s\n",
  4567.               MAX_INIT, string);
  4568.     }
  4569.     copy_string(init[x].pre_init, cptr, MAX_INIT);
  4570.     cptr = vptr + 1;
  4571.     vptr = strchr(cptr, vbar);
  4572.     if (!vptr)
  4573.       goto no_ver_bar;
  4574.     *vptr = 0;
  4575.     if (strlen(cptr) > MAX_INIT)
  4576.       goto init_err;
  4577.     copy_string(init[x].post_init, cptr, MAX_INIT);
  4578.     init[x].format = vptr[1];
  4579.     if (!init[x].format)
  4580.       init[x].format = '\r';
  4581.     break;
  4582.       case 43:      /* IF */
  4583.     strncpy_zero(ignore_format, cptr, sizeof(ignore_format));
  4584.     break;
  4585.       case 44:      /* interpoint */
  4586.     interpoint = y;
  4587.     break;
  4588.       case 45:      /* it */
  4589.     italics[0] = *cptr;
  4590.     break;
  4591.       case 46:      /* kc */
  4592.     keep_control = y;
  4593.     break;
  4594.       case 47:      /* kf */
  4595.     keep_format = y;
  4596.     if (keep_format)
  4597.     {
  4598.       hyphen_mode = remove_page_nums = rejoin = 0;
  4599.       maxline = curmax = 99;
  4600.       dopagenum = FALSE;
  4601.       indent[0] = '\0';
  4602.     }
  4603.     break;
  4604.       case 48:      /* l0 */
  4605.     strncpy_zero(l0, cptr, sizeof(l0));
  4606.     break;
  4607.       case 49:      /* l1 */
  4608.     strncpy_zero(l1, cptr, sizeof(l1));
  4609.     break;
  4610.       case 50:      /* l2 */
  4611.     j = 0;
  4612.     do
  4613.     {
  4614.       vptr = strchr(cptr, vbar);
  4615.       if (vptr)
  4616.         *vptr = '\0';
  4617.       strcpy(l2[j], cptr);
  4618.       cptr = vptr + 1;
  4619.       j++;
  4620.     }
  4621.     while (vptr != NULL && j < 9);
  4622.     l2[j] = '\0';
  4623.     break;
  4624.       case 51:      /* le */
  4625.     if (*cptr)
  4626.     {       /* not empty */
  4627.       strncpy_zero(efl_file, cptr, sizeof(efl_file));
  4628.       j = efl_mode;
  4629.       efl_mode |= 1;
  4630.       efl_mode &= 5;
  4631.       load_template();
  4632.       if (!lfile)
  4633.       {       /* try program directory */
  4634.         efl_mode |= 2;    /* abort if not found */
  4635.         sprintf(efl_file, "%s%s", transpath, cptr);
  4636.         load_template();
  4637.       }       /* try program directory */
  4638.       efl_mode = j;
  4639.     }       /* not empty */
  4640.     else
  4641.       lopactive = FALSE;
  4642.     break;
  4643.       case 52:      /* lf */
  4644.     if (inf_des_save != inf_des)
  4645.       close(inf_des);
  4646.     strcpy(inf_name + inf_path_len, cptr);
  4647.     inf_des = open_input_file();
  4648.     bytes_in_buf = 0;
  4649.     linein[0] = 0;
  4650.     break;
  4651.       case 53:      /* li */
  4652.     strncpy_zero(line_end, cptr, sizeof(line_end));
  4653.     break;
  4654.       case 54:      /* lm */
  4655.     leftmargin = min(y, 43);
  4656.     break;
  4657.       case 55:      /* lp */
  4658.     strncpy_zero(leading_punct, cptr, sizeof(leading_punct));
  4659.     break;
  4660.       case 56:      /* ls */
  4661.     if (y > 10)
  4662.       y = 99;  /* ff */
  4663.     lineskips = y;
  4664.     page_sep = '\14';
  4665.     if (cptr[0] == 'F')
  4666.       lineskips = 99;
  4667.     if (cptr[0] == 'V')
  4668.     {
  4669.       lineskips = 100;
  4670.       page_sep = '\13';
  4671.     }
  4672.     if (cptr[0] == 'P')
  4673.       lineskips = 101;
  4674.     break;
  4675.       case 57:      /* ma */
  4676.     math_flag = 0;
  4677.     if (!Isdigit(cptr[0]))
  4678.     {       /* not a digit */
  4679.       reload_table = TRUE;
  4680.       if (*cptr == '+')
  4681.         load_tables(math_table);
  4682.       else
  4683.         load_tables(table_file[0]);
  4684.     }       /* not a digit */
  4685.     else
  4686.       math_flag = x;
  4687.     break;
  4688.       case 58:      /* ms */
  4689.     strncpy_zero(math_symbols, cptr, sizeof(math_symbols));
  4690.     break;
  4691.       case 59:      /* mt */
  4692.     strncpy_zero(math_table, cptr, sizeof(math_table));
  4693.     break;
  4694.       case 60:      /* nc */
  4695.     no_copyright = y;
  4696.     break;
  4697.       case 61:      /* ob */
  4698.     for (x = 0; options[x].name; x++)
  4699.       if (!strncmp(options[x].name, cptr, 2))
  4700.       {
  4701.         options[x].value = atoi(cptr + 3);
  4702.         return;
  4703.       }
  4704.     goto invalid;
  4705.     break;
  4706.       case 62:      /* oc */
  4707.     output_case = y;
  4708.     break;
  4709.       case 63:      /* ow */
  4710.     over_write = y;
  4711.     break;
  4712.       case 64:      /* pa */
  4713.     pause_time = y;
  4714.     spool = 0;
  4715.     display_braille = display_source = FALSE;
  4716.     break;
  4717.       case 65:      /* pd */
  4718.     print_date = y;
  4719.     break;
  4720.       case 66:      /* pe */
  4721.     pageend = y;
  4722.     break;
  4723.       case 67:      /* pf */
  4724.     print_file = y;
  4725.     break;
  4726.       case 68:      /* pl */
  4727.     linesperpage = max(y, 5);
  4728.     break;
  4729.       case 69:      /* pn */
  4730.     strncpy_zero(prn, cptr, sizeof(prn));
  4731.     break;
  4732.       case 70:      /* ps */
  4733.     pagestart = y;
  4734.     break;
  4735.       case 71:      /* pw */
  4736.     maxline = curmax = min(y, 255);
  4737.     break;
  4738.       case 72:      /* qm */
  4739.     quiet_mode = y;
  4740.     break;
  4741.       case 73:      /* rc */
  4742.     delim = format_char;
  4743.     format_char = '~';
  4744.     strcpy(words, cptr);
  4745.     do_commands(8);
  4746.     format_char = delim;
  4747.     break;
  4748.       case 74:      /* rp */
  4749.     remove_page_nums = (y > 0);
  4750.     break;
  4751.       case 75:      /* rw */
  4752.     rejoin = get_integer(cptr);    /* used because option may contain a
  4753.                      * filename */
  4754.     if (rejoin_out_ptr != NULL && rejoin_out_ptr != stderr)
  4755.       fclose(rejoin_out_ptr);
  4756.     rejoin_out_ptr = NULL;
  4757.     if (*cptr)
  4758.       rejoin_out_ptr = fopen(cptr, "a");
  4759.     if (!rejoin_out_ptr)
  4760.       rejoin_out_ptr = stderr;
  4761.     break;
  4762.       case 76:      /* s0 */
  4763.     strncpy_zero(s0_init, cptr, sizeof(s0_init));
  4764.     break;
  4765.       case 77:      /* si */
  4766.     strncpy_zero(stdin_name, cptr, sizeof(stdin_name));
  4767.     break;
  4768.       case 78:      /* so */
  4769.     make_sound = y;
  4770.     break;
  4771.       case 79:      /* sp */
  4772.     spool = y;
  4773.     pause_time = 0;
  4774.     break;
  4775.       case 80:      /* st */
  4776.     strncpy_zero(stat_file, cptr, sizeof(stat_file));
  4777. #ifdef unix
  4778.     strlwr(stat_file);
  4779. #endif
  4780.     break;
  4781.       case 81:      /* tc */
  4782.     j = 0;
  4783.     do
  4784.     {
  4785.       vptr = strchr(cptr, vbar);
  4786.       if (vptr)
  4787.         *vptr = '\0';
  4788.       strcpy(t1[j], cptr);
  4789.       cptr = vptr + 1;
  4790.       j++;
  4791.     }
  4792.     while (vptr != NULL && j < 6);
  4793.     break;
  4794.       case 82:      /* td */
  4795.     strncpy_zero(table_definition, cptr, 40);
  4796.     process_table_definition();
  4797.     break;
  4798.       case 83:      /* te */
  4799.     vptr = strchr(cptr, ' ');
  4800.     if (vptr)
  4801.       *vptr++ = '\0';
  4802.     else
  4803.       vptr = cptr + strlen(cptr);
  4804.     for (x = 0; x < table_entries; x++)
  4805.       if (!strcmp(b->match[x], cptr))
  4806.         strncpy_zero(b->replace[x], vptr, MAX_REP);
  4807.     break;
  4808.       case 84:      /* tf */
  4809.     vptr = strchr(cptr, ';');
  4810.     if (vptr)
  4811.     {       /* back trans table specified */
  4812.       *vptr = '\0';
  4813.       strcpy(table_file[1], vptr + 1);
  4814.     }       /* back trans table specified */
  4815.     strcpy(table_file[0], cptr);
  4816.     reload_table = TRUE;
  4817.     load_tables(table_file[trans_mode > 2]);
  4818.     break;
  4819.       case 85:      /* tm */
  4820.     if (!total_files)
  4821.     {
  4822.       trans_mode = (y % 10);
  4823.       trans_mode1 = (y / 10);
  4824.     }
  4825.     break;
  4826.       case 86:      /* tn */
  4827.     trans_default = y;
  4828.     break;
  4829.       case 87:      /* to */
  4830.     strncpy_zero(toc_format, cptr, sizeof(toc_format));
  4831.     break;
  4832.       case 88:      /* tp */
  4833.     strncpy_zero(trailing_punct, cptr, sizeof(trailing_punct));
  4834.     break;
  4835.       case 89:      /* ts */
  4836.     table_start_line = (long) get_integer(cptr);
  4837.     if (table_stat_file)
  4838.       fclose(table_stat_file);
  4839.     table_stat_file = fopen(cptr, "w");
  4840.     break;
  4841.       case 90:      /* tv */
  4842.     timer = y;
  4843.     break;
  4844.       case 91:      /* vc */
  4845.     vptr = strchr(cptr, vbar);
  4846.     if (!vptr)
  4847.       goto no_ver_bar;
  4848.     *vptr = '\0';
  4849.     strncpy_zero(vowels, cptr, sizeof(vowels));
  4850.     strncpy_zero(consonants, vptr + 1, sizeof(consonants));
  4851.     break;
  4852.       }        /* switch */
  4853.       break;
  4854.     }           /* option matched */
  4855.   }           /* j */
  4856.   if (options[j].name == NULL)
  4857.   {           /* invalid */
  4858. invalid:
  4859.     fprintf(stderr, "\7Invalid option %s", string);
  4860.     if (total_lines)
  4861.       fprintf(stderr, " in line %ld", total_lines);
  4862.     for (j = 0; j < 8; j++)
  4863.       if (option_mode & (1 << j))
  4864.     print_error(" %s\n", option_types[j]);
  4865.   }           /* invalid */
  4866. }           /* process_options */
  4867.  
  4868. void report_option_error(int mode, int number)
  4869. {
  4870.   int i;
  4871.   for (i = 0; i < 8; i++)
  4872.     if (mode & (1 << i))
  4873.       print_error("\7option %s= not allowed %s\n", options[number].name,
  4874.           option_types[i]);
  4875. }           /* report_option_error */
  4876.  
  4877. void open_hyp_dictionary(char *string, int do_check)
  4878. {
  4879.   int i, j = 0;
  4880.   if (!strcmp(hyphen_dic_name, string) && hyp_dic_ptr != NULL)
  4881.     return;       /* don't close & reopen unless names are different */
  4882.   strncpy_zero(hyphen_dic_name, string, sizeof(hyphen_dic_name));
  4883.   if (hyp_dic_ptr)
  4884.   {           /* close hyphen dictionary */
  4885.     fclose(hyp_dic_ptr);
  4886.     hyp_dic_ptr = NULL;
  4887.   }           /* close hyphen dictionary */
  4888.   if (string[0])
  4889.   {           /* open hyphen dictionary */
  4890.     hyp_dic_ptr = open_option_file(string);
  4891.     if (do_check)
  4892.       memset(hyphen_dic_start, 0, sizeof(hyphen_dic_start));
  4893.     hyphen_mode |= BIT0;
  4894.     hyp_dic_tested = 0;
  4895.     stat(temp, &hypfilestat);
  4896.     if (hyphen_mode > 0 && do_check)
  4897.     {           /* do consistency check */
  4898.       for (i = 0; i < 5; i++)
  4899.       {
  4900.     if (!hyp_name_verify[i][0])
  4901.     {       /* empty entry with no prior match */
  4902.       strcpy(hyp_name_verify[i], hyphen_dic_name);
  4903.       hyp_date_verify[i] = hypfilestat.st_ctime;
  4904.       break;
  4905.     }       /* empty entry with no prior match */
  4906.     if (!strcmp(hyphen_dic_name, hyp_name_verify[i]))
  4907.     {       /* match */
  4908.       if (hypfilestat.st_ctime == hyp_date_verify[i])
  4909.         j++;
  4910.       else
  4911.         hyp_date_verify[i] = hypfilestat.st_ctime;
  4912.       break;
  4913.     }       /* match */
  4914.       }        /* i */
  4915.       if (!j)
  4916.       {        /* check consistency */
  4917.     test_hyphen_dictionary(1);
  4918.     if (!config_lines)
  4919.       rewrite_config();
  4920.       }        /* test consistency */
  4921.     }           /* do consistency check */
  4922.   }           /* open hyphen dictionary */
  4923.   else
  4924.     hyp_dic_ptr = NULL;
  4925. }           /* open_hyp_dictionary */
  4926.  
  4927. void process_table_definition()
  4928. {
  4929.   int j;
  4930.   if (!total_lines)
  4931.     print_error("\007td option not allowed on command line or nfbtrans.cnf\n");
  4932.   if (!table_definition[0])
  4933.     return;
  4934.   strlwr(table_definition);
  4935.   cols_in_table = chars_in_table = 0;
  4936.   strcpy(temp, table_definition);
  4937.   for (j = 0; temp[j]; j++)
  4938.   {
  4939.     if (temp[j] == '%')
  4940.     {           /* percent */
  4941.       if ((isdigit(temp[j + 1]) || ((temp[j + 1] == '-') &&
  4942.                     isdigit(temp[j + 2]))))
  4943.       {        /* field spec */
  4944.     if (cols_in_table >= 8)
  4945.       print_error("\007> 8 columns in line %ld\n",
  4946.               total_lines);
  4947.     j++;       /* index digit */
  4948.     field_width[cols_in_table] = abs(get_integer(temp + j));
  4949.     if (field_width[cols_in_table] > MAX_COL_WIDTH)
  4950.       print_error("\007> %d characters in field %d of table definition in line %ld\n",
  4951.               MAX_COL_WIDTH, cols_in_table + 1, total_lines);
  4952.     chars_in_table += field_width[cols_in_table];
  4953.     if (temp[j] != 's')
  4954.       print_error("\007Invalid field specifier in %s\n",
  4955.               table_definition);
  4956.     cols_in_table++;
  4957.     continue;
  4958.       }        /* field spec */
  4959.       if (temp[j + 1] == '*')
  4960.     print_error("%s\n", "\007%* not allowed in table definition");
  4961.     }           /* percent */
  4962.     chars_in_table++;
  4963.   }           /* j */
  4964.   if (chars_in_table > curmax + margin - 1)
  4965.     print_error("\007Table definition > %d characters in line %ld\n",
  4966.         curmax + margin - 1, total_lines);
  4967.   flush_if_not_blank();
  4968. }           /* process_table_definition */
  4969.  
  4970. void trim(char *string)
  4971. {
  4972.   int i, l = strlen(string);
  4973. /*remove trailing cr lf and spaces*/
  4974.   for (i = l - 1; i >= 0; i--)
  4975.   {
  4976.     switch (string[i])
  4977.     {
  4978.     case ' ':
  4979.     case '\12':   /* lf */
  4980.     case '\15':   /* cr */
  4981.       break;
  4982.     default:
  4983.       string[i + 1] = 0;
  4984.       i = 0;
  4985.       while (string[i] == ' ')
  4986.     i++;
  4987.       if (i)
  4988.     delete(string, i);
  4989.       return;
  4990.     }
  4991.   }           /* i */
  4992. }           /* trim */
  4993.  
  4994. int strpos(char *string, char *substring)
  4995. {
  4996.   int i = 0, j, stringlen, sublen;
  4997.   stringlen = strlen(string);
  4998.   sublen = strlen(substring);
  4999.   if ((!stringlen) || (!sublen) || (sublen > stringlen))
  5000.     return (0);
  5001.   do
  5002.   {
  5003.     for (j = 0; j < sublen; j++)
  5004.       if (string[i + j] != substring[j])
  5005.     goto retry;
  5006.     return (i + 1);
  5007. retry:;
  5008.   }
  5009.   while (++i < stringlen);
  5010.   return (0);
  5011. }           /* strpos */
  5012.  
  5013. void insert(char *ins, char *string)
  5014. {
  5015.   char buf[256];
  5016.   strcpy(buf, ins);
  5017.   strcat(buf, string);
  5018.   strcpy(string, buf);
  5019. }           /* insert */
  5020.  
  5021. void delete(char *string, int bytes)
  5022. {
  5023.   strcpy(string, string + bytes);
  5024. }           /* delete */
  5025.  
  5026. void strncpy_zero(char *dest, char *source, int bytes)
  5027. {
  5028.   strncpy(dest, source, bytes);
  5029.   dest[bytes - 1] = '\0';
  5030. }           /* strncpy_zero */
  5031.  
  5032. void move(char *string1, char *string2, int bytes)
  5033. {
  5034.   while (bytes >= 0)
  5035.   {
  5036.     string2[bytes] = string1[bytes];
  5037.     bytes--;
  5038.   }           /* while */
  5039. }           /* move */
  5040.  
  5041. #ifdef DOS
  5042. void sort_names()
  5043. {           /* sorts names in file_names */
  5044.   int i, j;
  5045.   if (file_count < 2)
  5046.     return;       /* nothing to sort */
  5047.   for (i = 0; i < file_count; i++)
  5048.     for (j = i + 1; j < file_count; j++)
  5049.       if (strcmp(file_name[i], file_name[j]) > 0)
  5050.       {        /* out of order */
  5051.     strcpy(temp, file_name[i]);
  5052.     strcpy(file_name[i], file_name[j]);
  5053.     strcpy(file_name[j], temp);
  5054.       }        /* out of order */
  5055. }           /* sort_names */
  5056.  
  5057. #endif           /* DOS */
  5058.  
  5059. void translate_file()
  5060. {
  5061.   int i, input_mode = 0, startfile;
  5062.   char *cptr, c;
  5063.   FILE *indirect_ptr = NULL;
  5064.   intext = NULL;   /* for statistics file */
  5065.   do
  5066.   {
  5067.     if (!stdin_tty)
  5068.       strcpy(inf_name, stdin_name);
  5069.     else
  5070.     {           /* input filename required */
  5071.       if (!input_file_arg)
  5072.       {        /* no file args */
  5073.     fprintf(stderr, "\nEnter source File name <RETURN> to exit? ");
  5074.     get_input(temp, 80);
  5075.     if (!temp[0])
  5076.       exit_program(0);
  5077.     strcpy(inf_name, temp);
  5078.     input_file_arg = paramcount;
  5079.       }        /* no file args */
  5080.       else
  5081.       if (!indirect_ptr)
  5082.     strcpy(inf_name, paramstr[input_file_arg]);
  5083.       input_mode = 1;
  5084.       if (inf_name[0] == '@' && indirect_ptr == NULL)
  5085.       {        /* indirect mode */
  5086.     delete(inf_name, 1);    /* remove @ */
  5087.     indirect_ptr = fopen(inf_name, "r");
  5088.     if (!indirect_ptr)
  5089.       report_open_error(inf_name);
  5090.     pagestart = 1;
  5091.       }        /* indirect mode */
  5092.  
  5093.       if (indirect_ptr)
  5094.     if (fgets(inf_name, 128, indirect_ptr))
  5095.     {       /* not eof */
  5096.       i = (int) (strlen(inf_name) - 1);
  5097.       if (i >= 0 && inf_name[i] == '\n')
  5098.         inf_name[i] = '\0';
  5099.       if (!i)
  5100.         continue;    /* skip blank lines */
  5101.     }       /* not eof */
  5102.     else
  5103.     {       /* eof */
  5104.       fclose(indirect_ptr);
  5105.       indirect_ptr = NULL;
  5106.       input_file_arg++;
  5107.       continue;
  5108.     }       /* eof */
  5109.  
  5110.       inf_path_len = get_path_component(inf_name);
  5111.       file_count = current_file = 0;
  5112.       startfile = 1;
  5113. #ifdef DOS
  5114.       if (strpbrk(inf_name, "?*"))
  5115.       {        /* wildcard chars */
  5116.     input_mode = 2; /* wildcard chars specified */
  5117.     pagestart = 1;
  5118.     cptr = strpbrk(inf_name, ",;");
  5119.     if (cptr)
  5120.     {       /* find startfile */
  5121.       *cptr = '\0'; /* remove startfile from filename */
  5122.       startfile = atoi(cptr + 1);
  5123.       if (startfile < 1)
  5124.         startfile = 1;
  5125.     }       /* find startfile */
  5126.       }        /* wildcard chars */
  5127.       if (!_dos_findfirst(inf_name, 0, &fileinfo))
  5128.     do
  5129.     {       /* store and sort matching file names */
  5130.       if (test_extension(fileinfo.name) < 0)
  5131.         continue;    /* extension was excluded */
  5132.       strcpy(file_name[file_count++], fileinfo.name);
  5133.       if (file_count >= MAX_FILES)
  5134.         break; /* don't store any more */
  5135.     }
  5136.     while (!_dos_findnext(&fileinfo));
  5137.       if (!file_count)
  5138. /*no file was found in search but store name anyway*/
  5139.     strcpy(file_name[file_count++], inf_name + inf_path_len);
  5140.       sort_names();
  5141.       current_file = startfile - 1;
  5142.       if (current_file > file_count)
  5143.     break;
  5144.   get_next_file:
  5145.       strcpy(inf_name + inf_path_len, file_name[current_file++]);
  5146. #endif
  5147.     }           /* input filename required */
  5148.     total_lines = 0l;
  5149.     if (total_files)
  5150.     {           /* not first file */
  5151.       lopactive = FALSE;
  5152.       l0[0] = l1[0] = '\0';
  5153.       ignore_format[0] = '\0';
  5154.       get_config();
  5155.     }           /* not first file */
  5156.     prog_init = test_extension(inf_name);
  5157.     if (prog_init < 0)
  5158.       print_error("\7%s: Excluded by ex= option\n", inf_name);
  5159.     if (stdin_tty)
  5160.     {           /* input filename required */
  5161.       inf_des = open_input_file();
  5162.       inf_des_save = inf_des;    /* in case the lf option is encountered */
  5163.       if (spool > 1 && total_files > 0 && stdout_tty > 0)
  5164.     pause_program();
  5165.       if (ab_flag)
  5166.     break;
  5167. #ifndef unix
  5168.       strlwr(inf_name);
  5169. #endif
  5170.       if (skip_output == 0 && (indirect_ptr != NULL || input_mode == 2
  5171.                    || total_files > 0))
  5172.     fprintf(stderr, "Translating %s\n", inf_name);
  5173.       total_files++;
  5174.       fstat(inf_des, &infilestat);
  5175.       if (efl_mode && (infilestat.st_mode & IFCHR) == 0 && lopactive == FALSE)
  5176.       {        /* process .efl file */
  5177.     strcpy(efl_file, inf_name);
  5178.     cptr = strchr(efl_file, '.');
  5179.     if (!cptr)
  5180.       cptr = efl_file + strlen(efl_file);
  5181.     strlwr(cptr);
  5182.     if (strcmp(cptr, ".efl"))
  5183.     {       /* load */
  5184.       strcpy(cptr, ".EFL");
  5185.       if (trans_mode < 3)
  5186.         format_char = init[prog_init].format;
  5187.       load_template();
  5188.     }       /* load */
  5189.       }        /* process .efl file */
  5190.     }           /* input file required */
  5191.     get_date();    /* put date in date_string */
  5192.     if (leftmargin < 0)
  5193.     {           /* get left margin */
  5194.       leftmargin = 1;
  5195.       fprintf(stderr, "Enter Number of spaces before Left Margin of source File \n");
  5196.       fprintf(stderr, "     (usually 1)? %d", leftmargin);
  5197.       backspace_int(leftmargin);
  5198.       get_input(temp, 4);
  5199.       leftmargin = atoi(temp);
  5200.       if (leftmargin <= 0)
  5201.     leftmargin = 1;
  5202.     }           /* get left margin */
  5203.     if (maxline <= 0)
  5204.     {           /* get maxline */
  5205.       maxline = 40;
  5206.       fprintf(stderr, "Enter Number of braille cells to emboss\n");
  5207.       fprintf(stderr, "  on a Line (usually 40)? %d", maxline);
  5208.       backspace_int(maxline);
  5209.       get_input(temp, 3);
  5210.       maxline = atoi(temp);
  5211.       if (maxline <= 0)
  5212.     maxline = 40;
  5213.     }           /* get maxline */
  5214.     get_page_range();
  5215.     if (display_source < 0)
  5216.     {           /* display source? */
  5217.       fprintf(stderr, "\nDisplay Source Text (Y/N)? N\010");
  5218.       get_digit();
  5219.       if (temp[0] == 'y' || temp[0] == 'Y')
  5220.     display_source = TRUE;
  5221.       else
  5222.     display_source = FALSE;
  5223.     }           /* display source? */
  5224.     if (display_braille < 0)
  5225.     {           /* display braille? */
  5226.       fprintf(stderr, "\nDisplay Translated Text (Y/N)? Y\010");
  5227.       get_digit();
  5228.       if (temp[0] == 'n' || temp[0] == 'N')
  5229.     display_braille = FALSE;
  5230.     }           /* display braille? */
  5231.     if (linesperpage <= 0)
  5232.     {
  5233.       linesperpage = 25;
  5234.       fprintf(stderr, "\nNumber of Lines per Page? %d", linesperpage);
  5235.       backspace_int(linesperpage);
  5236.       get_input(temp, 5);
  5237.       if (temp[0])
  5238.     linesperpage = atoi(temp);
  5239.       if (linesperpage <= 0)
  5240.     linesperpage = 25;
  5241.     }
  5242.     if (lineskips < 0)
  5243.     {
  5244.       lineskips = 99;
  5245.       fprintf(stderr, "Line Skips between Pages (99-FF, 999-VT)? %d", lineskips);
  5246.       backspace_int(lineskips);
  5247.       get_input(temp, 5);
  5248.       if (temp[0])
  5249.     lineskips = atoi(temp);
  5250.       if (lineskips < 0)
  5251.     lineskips = 99;
  5252.     }
  5253.     if (current_file < 2)
  5254.       printit = TRUE;
  5255.     if (trans_mode == 3)
  5256.       trans_mode1 = 1;
  5257. #ifdef unix
  5258.     trans_mode1 = 1;
  5259. #endif
  5260.     if (!trans_mode1)
  5261.     {           /* get secondary translation mode */
  5262.       i = (trans_default / 10);
  5263.       fprintf(stderr, "\nPlease select ");
  5264.       fprintf(stderr, "\n  1 to Translate and store in a File or");
  5265.       fprintf(stderr, "\n  2 Translate and emboss immediately.\n  Choice? %d",
  5266.           i);
  5267.       backspace_int(i);
  5268.       do
  5269.       {
  5270.     get_digit();
  5271.     if (!temp[0])
  5272.       i = (trans_default / 10);
  5273.     else
  5274.       i = atoi(temp);
  5275.       }
  5276.       while (i < 1 || i > 2);
  5277.     }           /* get secondary translation mode */
  5278.     else
  5279.       i = trans_mode1;
  5280.     trans_mode1 = i;
  5281.     if (i == 1)
  5282.     {           /* translate and store */
  5283.       printit = FALSE;
  5284.       if (!outf_name[0] && stdout_tty != 0)
  5285.       {        /* output file required */
  5286.     fprintf(stderr, "\nEnter name of File to create? ");
  5287.     get_input(outf_name, 48);
  5288.     if (!outf_name[0])
  5289.       exit_program(0);
  5290.       }        /* output file required */
  5291.     }           /* translate and store */
  5292.     if (!rejoin)
  5293.       rejoin = TRUE;
  5294.     xgrade = 2;
  5295.     xformat = TEXT;
  5296.     find_toc_pages = FALSE;
  5297.     memset(toc_pages, 0, sizeof(toctype));
  5298.     current_pass = 1;
  5299.     if (spool > 0 && file_count >= 9 && printit)
  5300.       spool++;       /* pause between files so queue won't overflow */
  5301.     if ((printit && !(usr_default)))
  5302.       get_page_range();
  5303.     get_copies();
  5304.     if (printit == FALSE && stdout_tty != 0)
  5305.     {           /* disk file */
  5306. #ifndef unix
  5307.       strlwr(outf_name);
  5308. #endif
  5309.       if (test_file_exist())
  5310.     return;
  5311.       if (stdout_tty)
  5312.     printf("Writing to file - %s\n", outf_name);
  5313.     }           /* disk file */
  5314.     else
  5315.     {
  5316.       get_printer_file_name();
  5317.       if (total_files == 1)
  5318.     do_pause();
  5319.     }
  5320.     if (ab_flag)
  5321.       return;
  5322.     time(&time1);
  5323.     if (outf_name[0] && outf_des == 0)
  5324.       outf_des = open(outf_name, (int) (O_BINARY | O_CREAT | O_TRUNC | O_WRONLY), STD_OPEN);
  5325.     keep_control = 0;
  5326.     keep_together = keep_together_save = 0;
  5327.     total_lines = 0l;
  5328.     switch (trans_mode)
  5329.     {
  5330.     case 1:
  5331.       load_tables(table_file[0]);
  5332.       break;
  5333.     case 3:
  5334.       reload_table = TRUE;
  5335.       load_tables(table_file[1]);
  5336.       if (remove_page_nums)
  5337.     remove_page_nums = get_paragraph_type(1);
  5338.     }           /* switch */
  5339.     c = format_char;
  5340.     format_char = '~';
  5341.     strcpy(words, init[prog_init].pre_init);
  5342.     do_commands(32);
  5343.     if (trans_mode < 3)
  5344.       format_char = init[prog_init].format;
  5345.     if (xformat == AUTO_FORMAT)
  5346.       get_paragraph_type(0);
  5347.     if (printit && spool)
  5348.     {           /* printer ignore formfeed */
  5349.       format_char = '~';
  5350.       strcpy(words, s0_init);
  5351.       do_commands(32);
  5352.       format_char = init[prog_init].format;
  5353.     }           /* printer ignore formfeed */
  5354. #ifdef unix
  5355.     unbuf_stdin(); /* so we can check for esc */
  5356. #endif
  5357.     in_length = filelength(inf_des);
  5358.     if (infilestat.st_mode & IFCHR)
  5359.       in_length = 0l;
  5360.     if (trans_mode == 3)
  5361.       format_char = c;
  5362.  
  5363.     do
  5364.     {
  5365.       do_translate();
  5366.       if (toc_file_ptr)
  5367.       {        /* close */
  5368.     fclose(toc_file_ptr);
  5369.     unlink(toc_file_name);
  5370.     toc_file_ptr = NULL;
  5371.       }        /* close */
  5372.     }
  5373.     while (copies < lastcopy && ab_flag == 0);
  5374.     format_char = '~';
  5375.     strcpy(words, init[prog_init].post_init);
  5376.     do_commands(32);
  5377.     if (trans_mode == 3)
  5378.       format_char = c;
  5379.     out_length = filelength(outf_des);
  5380.     close(inf_des);
  5381.     emboss_time = total_cells / (60l * (long) charspersec);
  5382.     write_stat_file();
  5383. #ifdef DOS
  5384.     if (printit && spool && ab_flag == 0)
  5385.     {           /* spool */
  5386.       if (stdout_tty)
  5387.       {        /* output not redirected */
  5388.     if (emboss_time > 1l)
  5389.       printf("Estimated embossing time: %ld minutes\n",
  5390.          emboss_time);
  5391.       }        /* output not redirected */
  5392.       close(outf_des);
  5393.       outf_des = 0;
  5394.       spool_file();
  5395.     }           /* spool */
  5396.     if (ab_flag)
  5397.       break;
  5398.     if (input_mode)
  5399.     {
  5400.       copies = 0;
  5401.       if (current_file < file_count)
  5402.     goto get_next_file;
  5403.     }
  5404. #endif           /* DOS */
  5405.     if (input_mode == 2)
  5406.     {           /* wildcards */
  5407.       input_mode = 1;
  5408.     }           /* wildcards */
  5409.     if (indirect_ptr)
  5410.       continue;
  5411.     input_file_arg++;
  5412.   }
  5413.   while (input_file_arg <= paramcount);
  5414.   if (outf_des > 1)
  5415.     close(outf_des);
  5416.   if (intext)
  5417.     fclose(intext);
  5418.   fclose(conf_ptr);
  5419. }           /* translate_file */
  5420. int get_path_component(char *string)
  5421. {
  5422.   int i, retval = 0;
  5423.   for (i = 0; string[i]; i++)
  5424.     if (string[i] == '\\' || string[i] == '/' || string[i] == ':')
  5425.       retval = i + 1;
  5426.   return (retval);
  5427. }           /* get_path_component */
  5428.  
  5429. int open_input_file()
  5430. {
  5431.   int h;
  5432.   h = open(inf_name, O_BINARY | O_RDONLY);
  5433.   if (h < 0)
  5434.     report_open_error(inf_name);
  5435.   return (h);
  5436. }           /* open_input_file */
  5437.  
  5438. int test_file_exist()
  5439. {
  5440.   int i, retval = 0;
  5441.   if (!access(outf_name, 0))
  5442.   {           /* exists */
  5443.     i = get_path_component(outf_name);
  5444.     stat(outf_name, &outfilestat);
  5445.     if (infilestat.st_ctime == outfilestat.st_ctime &&
  5446.     infilestat.st_size == outfilestat.st_size &&
  5447.     strcmp(inf_name + inf_path_len, outf_name + i) == 0)
  5448.       print_error("\7Cannot translate a file on to itself\n");
  5449.     if (over_write == 0)
  5450.     {           /* file already exists */
  5451.       printf("\007File %s exists - Overwrite (Y/N)? Y\010", outf_name);
  5452.       get_digit();
  5453.       if (temp[0] == 'n' || temp[0] == 'N')
  5454.     retval = 1;
  5455.     }           /* file already exist */
  5456.   }           /* exists */
  5457.   return (retval);
  5458. }           /* test_file_exist */
  5459.  
  5460. void report_open_error(char *string)
  5461. {
  5462.   if (errno == EACCES)
  5463.     print_error("\007%s is a directory\n", string);
  5464.   else
  5465.     print_error("\7%s not found.\n", string);
  5466. }           /* report_open_error */
  5467.  
  5468. void spool_file()
  5469. {
  5470.   sprintf(temp, "print %s", outf_name);
  5471.   if (system(temp))
  5472.     print_error("\007Could not execute %s\n", temp);
  5473. }           /* spool_file */
  5474.  
  5475. int test_extension(char *string)
  5476. {
  5477.   int i, j = 0;
  5478.   char *cptr;
  5479.   /* get file extension */
  5480.   cptr = strchr(string, '.');
  5481.   if (cptr == NULL)
  5482.   {           /* no extension */
  5483.     for (i = 0; string[i]; i++)
  5484.       if (string[i] == ':' || string[i] == '\\' || string[i] == '/')
  5485.     j = i + 1;
  5486.     /* copy the filename without path component */
  5487.     strncpy_zero(inf_name_ext, string + j, 8);
  5488.     j = search_extensions(inf_name_ext);
  5489.     if (j)
  5490.       goto done_test;
  5491.     cptr = string + strlen(string) - 1;
  5492.   }           /* no extension */
  5493.   strcpy(inf_name_ext, cptr + 1);
  5494.   /* find out if extension is in an ex= option */
  5495.   j = search_extensions(inf_name_ext);
  5496. done_test:
  5497.   if (j)
  5498.     return (prog_extension.prog_ext[j - 1].init_val);
  5499.   return (0);       /* for extensions not in ex= */
  5500. }           /* test_extension */
  5501.  
  5502. int search_extensions(char *string)
  5503. {
  5504.   int i, j = 0;
  5505.   strupr(string);
  5506.   for (i = 0; i < prog_extension.total; i++)
  5507.     if (!strcmp(string, prog_extension.prog_ext[i].ext))
  5508.       j = i + 1;   /* extension was in list */
  5509.   return (j);
  5510. }           /* search_extensions */
  5511.  
  5512. void emboss_file()
  5513. {
  5514.   char ch, *cptr;
  5515.   if (!inf_name[0])
  5516.   {           /* get filename */
  5517.     printf("\nEnter the name of the already Translated File <RETURN> to exit: ");
  5518.     get_input(temp, 48);
  5519.     if (!temp[0])
  5520.       exit_program(0);
  5521.     strcpy(inf_name, temp);
  5522.   }           /* get filename */
  5523.   if ((intext = fopen(inf_name, FOPEN_READ)) == NULL)
  5524.     print_error("\7%s does not exist\n", inf_name);
  5525.   get_copies();
  5526.   get_page_range();
  5527.   usr_default = FALSE;
  5528.   printit = TRUE;
  5529.   get_date();
  5530.   get_printer_file_name();
  5531.   do_pause();
  5532.   if (ab_flag)
  5533.     return;
  5534.   outf_des = open(outf_name, O_BINARY | O_CREAT | O_TRUNC | O_WRONLY, S_IWRITE);
  5535.   do
  5536.   {           /* while there are copies to emboss */
  5537.     copies++;
  5538.     actualpage = 0;
  5539.     bpagec = 1;    /* current braille page */
  5540.     lineinct = 0;
  5541.     rewind(intext);/* start from beginning of file for this copy */
  5542.     while ((fgets(field, 80, intext)) && bpagec <= pageend)
  5543.     {           /* while there are lines to read and not passed ending
  5544.             * page */
  5545.       if (check_keyboard(0) < 0)
  5546.     break;
  5547.       lineinct++;
  5548.       linecount = (int) strlen(field);
  5549.       field[linecount - 1] = 0; /* remove \n */
  5550.       if ((cptr = strpbrk(field, "\013\014")) != NULL ||
  5551.       (int) lineinct > linesperpage)
  5552.       {        /* new page */
  5553.     bpagec++;  /* ff or vt */
  5554.     page_beep();
  5555.     if (!skip_output)
  5556.       fprintf(stderr, "Embossing page %d\n", bpagec);
  5557.     lineinct = 1;    /* first line on new page */
  5558.     if (bpagec > pageend)
  5559.       break;   /* done */
  5560.     if (display_braille > 0 && page_in_range() && skip_output == 0)
  5561.     {       /* display braille */
  5562.       fprintf(stderr, "%s\n", field);
  5563.       if (linecount >= 20)
  5564.         fprintf(stderr, "       Copy %d of %d\n", copies, lastcopy);
  5565.     }       /* display_braille */
  5566.       }        /* new page */
  5567.       if (page_in_range())
  5568.       {        /* process page */
  5569.     if (cptr)
  5570.     {       /* vt or ff */
  5571.       ch = *cptr;
  5572.       if (!skip_output)
  5573.         fprintf(stderr, "%s\n", field);
  5574.       strcpy(field, cptr + 1);
  5575.       if (actualpage)
  5576.         write_char(ch);
  5577.       actualpage++;
  5578.       delay(emboss_delay);
  5579.       if (field[0])
  5580.         write_string(field, 0);
  5581.     }       /* ff or vt */
  5582.     else
  5583.     {       /* no ff or vt */
  5584.       write_string(field, 1);
  5585.     }       /* no f or vt */
  5586.       }        /* process page */
  5587.     }           /* while */
  5588.   }
  5589.   while (copies < lastcopy);
  5590.   fclose(intext);
  5591.   close(outf_des);
  5592.   if (spool)
  5593.     spool_file();
  5594. }           /* emboss_file */
  5595.  
  5596. void get_page_range()
  5597. {
  5598.   int i;
  5599.   char *cptr;
  5600.   pagestart_roman = 1;
  5601.   pageend_roman = 9999;
  5602.   roman_flag = 0;
  5603.   arabic_flag = 1;
  5604.   if (trans_mode == 3)
  5605.     pagestart = 1, pageend = 9999;
  5606.   if (pagestart <= 0)
  5607.   {           /* get starting page */
  5608.     fprintf(stderr, "Start at Page? 1\010");
  5609.     get_input(temp, 80);
  5610.     if (!temp[0])
  5611.       pagestart = 1;
  5612.     cptr = strpbrk(temp, "-, ");
  5613.     if (cptr)
  5614.       *cptr = '\0';
  5615.     i = atoi(temp);
  5616.     /* if interpoint then page should be odd */
  5617.     if (interpoint && (i & 1) == 0)
  5618.       i--;
  5619.     if (strchr(temp, 'r'))
  5620.     {
  5621.       pagestart_roman = i;
  5622.       roman_flag = 1;
  5623.     }
  5624.     else
  5625.       pagestart = i;
  5626.     if (cptr)
  5627.       get_end_page(cptr + 1);
  5628.     if (pagestart <= 0)
  5629.       pagestart = 1;
  5630.   }           /* get starting page */
  5631.   if (pageend < pagestart)
  5632.   {           /* pageend */
  5633.     pageend = 9999;
  5634.     fprintf(stderr, "Stop at Page (RETURN for end)? %d", pageend);
  5635.     backspace_int(pageend);
  5636.     get_input(temp, 5);
  5637.     get_end_page(temp);
  5638.   }           /* pageend */
  5639.   pagestart_save = pagestart;
  5640.   pageend_save = pageend;
  5641. }           /* get_page_range */
  5642.  
  5643. void get_end_page(char *string)
  5644. {
  5645.   int i;
  5646.   i = atoi(string);
  5647.   if (!string[0])
  5648.     i = 9999;
  5649.   if (interpoint && (i & 1))
  5650.     i++;       /* make even */
  5651.   if (strchr(string, 'r'))
  5652.   {           /* roman */
  5653.     pageend_roman = i;
  5654.     pagestart = pageend = 32766;
  5655.     arabic_flag = 0;
  5656.   }           /* roman */
  5657.   else
  5658.     pageend = i;
  5659.   if (pageend < 1)
  5660.     pageend = 1000;
  5661. }           /* get_end_page */
  5662.  
  5663. int page_in_range()
  5664. {
  5665.   int retval = 0;
  5666.   if (doroman)
  5667.   {           /* roman page number */
  5668.     if (roman_flag)
  5669.     {           /* roman range specified */
  5670.       if (bpagec >= pagestart_roman)
  5671.     retval = bpagec + 1 - pagestart_roman;
  5672.       if (bpagec > pageend_roman)
  5673.     retval = 0;
  5674.     }           /* roman range specified */
  5675.     else
  5676.     if (bpagec >= pagestart)
  5677.       retval = bpagec + 1 - pagestart;
  5678.     if (pagestart == 32767)
  5679.       retval = 0;  /* no output pass 1 of 2 */
  5680.   }           /* roman page number */
  5681.   else
  5682.   if (bpagec >= pagestart)
  5683.     retval = bpagec + 1 - pagestart;
  5684.   return (retval);
  5685. }           /* page_in_range */
  5686.  
  5687. void get_copies()
  5688. {
  5689.   if (lastcopy <= 0)
  5690.   {
  5691.     lastcopy = 1;
  5692.     printf("\nNumber of Copies? %d\010", lastcopy);
  5693.     get_input(temp, 80);
  5694.     lastcopy = atoi(temp);
  5695.     if (lastcopy <= 0)
  5696.       lastcopy = 1;
  5697.   }
  5698. }           /* get_copies */
  5699.  
  5700. void get_printer_file_name()
  5701. {
  5702.   int tries = 0;
  5703.   char *cptr;
  5704.   if (printit)
  5705.     if (stdout_tty)
  5706.     {           /* stdout is tty */
  5707.       if (!spool)
  5708.     strcpy(outf_name, prn);
  5709.       else
  5710.       {        /* spool */
  5711.     /* get location of temp file */
  5712.     cptr = (char *) getenv("TMP");
  5713.     if (cptr)
  5714.       strcpy(temp, cptr);
  5715.     else
  5716.       temp[0] = 0;
  5717.     do
  5718.     {
  5719.       tries++;
  5720.       sprintf(outf_name, "%s%02d%02d%02d", temp, tm->tm_hour, tm->tm_min,
  5721.           tm->tm_sec);
  5722.       if (!access(outf_name, 0))
  5723.         tm->tm_sec++;    /* file exists so use a different name */
  5724.       else
  5725.         break;
  5726.     }
  5727.     while (tries < 10);
  5728.  
  5729.     if (interpoint > 1)
  5730.       interpoint = 1;    /* don't eject blank page */
  5731.     printf("Creating %s\n", outf_name);
  5732.       }        /* spool */
  5733.     }           /* stdout is tty */
  5734. }           /* get_printer_file_name */
  5735.  
  5736. void do_pause()
  5737. {
  5738.   int i;
  5739.   if (pause_time && printit)
  5740.   {           /* pause */
  5741.     for (i = 0; i < pause_time; i++)
  5742.     {
  5743.       if (make_sound)
  5744. #ifdef DOS
  5745.     sound(440);
  5746.       delay(80);
  5747.       nosound();
  5748. #else           /* unix */
  5749.     beep(1);
  5750. #endif           /* DOS */
  5751.       delay(800);
  5752.       if (stdin_tty)
  5753.     if (check_keyboard(0) > 0)
  5754.       getch();
  5755.     }           /* i */
  5756.     skip_output = TRUE;
  5757.   }           /* pause */
  5758. }           /* do_pause */
  5759.  
  5760. void pause_program()
  5761. {
  5762.   if (emboss_time)
  5763.   {           /* pause */
  5764.     printf("Press any key to continue or wait %ld minutes for embossing\n",
  5765.        emboss_time);
  5766.     time1 = (long) time(NULL);
  5767.     do
  5768.     {
  5769.       if (check_keyboard(0))
  5770.     break;
  5771.     }
  5772.     while ((long) time(NULL) - time1 < emboss_time * 60l);
  5773.   }           /* pause */
  5774. }           /* pause_program */
  5775.  
  5776. int check_keyboard(int toggle)
  5777. {           /* returns -1 for esc 0 for no key and 1 otherwise */
  5778.   int retval = 0;
  5779.   long pos;
  5780.   if (kbhit())
  5781.   {           /* get key */
  5782.     switch (getch())
  5783.     {
  5784.     case 32:
  5785.       if (toggle)
  5786.     make_sound ^= TRUE;
  5787.       break;
  5788.     case 27:
  5789.       done = TRUE; /* abort */
  5790.       ab_flag = 1;
  5791.       retval = -1;
  5792.       break;
  5793.     case 70:
  5794.     case 102:
  5795.       pos = lseek(inf_des, 0l, 1) + (long) (ioptr - iobuf) - (long) BUFSIZE;
  5796.       fprintf(stderr, "%s %d %d = %ld%%\n", inf_name, inf_des, bpagec,
  5797.           (100l * pos) / in_length);
  5798.     default:
  5799.       retval = 1;
  5800.     }           /* switch */
  5801.   }           /* get key */
  5802.   return (retval);
  5803. }           /* check_keyboard */
  5804.  
  5805. void write_string(char *string, int display)
  5806. {
  5807.   int l;
  5808. #ifdef DOS
  5809.   l = sprintf(temp, "%s\r\n", string);
  5810. #else
  5811. #ifdef sysv
  5812.   l = sprintf(temp, "%s\n", string);
  5813. #else           /* not sysv */
  5814.   sprintf(temp, "%s\n", string);
  5815.   l = strlen(temp);
  5816. #endif           /* sysv */
  5817. #endif           /* DOS */
  5818.   if (!output_case)
  5819.     strlwr(temp);
  5820.   if (write(outf_des, temp, l) < 0)
  5821.     no_space();
  5822.   if (printit)
  5823.     delay(emboss_delay);
  5824.   if (display)
  5825.     if (display_braille && skip_output == FALSE)
  5826.       fprintf(stderr, string_format, temp);
  5827.   if (stat_file[0])
  5828.     add_dots(string);
  5829. }           /* write_string */
  5830.  
  5831. void write_toc_header()
  5832. {
  5833.   int i;
  5834.   char string[16];
  5835.   if (toc_entry == 0 || (book_mode & 8) == 0)
  5836.     return;
  5837.   i = 2 + (toc_word == 0);
  5838.   if (blinec + i > linesperpage)
  5839.   {
  5840.     top_of_form();
  5841.     blinec = i;
  5842.   }
  5843.   else
  5844.     blinec += i;
  5845.   if (page_in_range())
  5846.   {
  5847.     sprintf(string, "%%-%ds%%5s %%5s", curmax - fill_length + 1);
  5848.     sprintf(field, string, t1[0], t1[1], t1[2]);
  5849.     write_string(field, 0);
  5850.     sprintf(field, string, t1[3], t1[4], t1[5]);
  5851.     write_string(field, 0);
  5852.     if (!toc_word)
  5853.       write_string(" ", 0);
  5854.   }
  5855.   field[0] = 0;
  5856. }           /* write_toc_header */
  5857.  
  5858. void write_char(char ch)
  5859. {
  5860.   if (write(outf_des, &ch, 1) <= 0)
  5861.     no_space();
  5862. }           /* write_char */
  5863.  
  5864. void no_space()
  5865. {
  5866.   int i;
  5867.   fprintf(stderr, "Error with output file: ");
  5868.   perror("Error");
  5869.   if (make_sound)
  5870.     for (i = 0; i < 5; i++)
  5871.     {
  5872. #ifdef DOS
  5873.       sound(750);
  5874.       delay(100);
  5875.       sound(1500);
  5876.       delay(100);
  5877. #else           /* unix */
  5878.       beep(2);
  5879. #endif           /* DOS */
  5880.     }
  5881. #ifdef DOS
  5882.   nosound();
  5883. #endif           /* DOS */
  5884.   exit_program(1);
  5885. }           /* no_space */
  5886.  
  5887. void copy_string(char *string1, char *string2, int maxlen)
  5888. {           /* copies at most length bytes of string2 into string1
  5889.             * accounting for escaped characters */
  5890.   int i, j = 0, k;
  5891.   for (i = 0; (string2[i] != '\0' && j < maxlen); i++)
  5892.     if (string2[i] != '\\')
  5893.       string1[j++] = string2[i];
  5894.     else
  5895.     {           /* escape */
  5896.       i++;       /* skip \ */
  5897.       if (isdigit(string2[i]))
  5898.       {        /* digit */
  5899.     k = atoi(string2 + i);
  5900.     if (k > 9)
  5901.       i++;
  5902.     if (k > 99)
  5903.       i++;
  5904.     string1[j++] = (char) k;
  5905.       }        /* digit */
  5906.     }           /* escape */
  5907.   string1[j] = '\0';
  5908. }           /* copy_string */
  5909.  
  5910. void cleanup(int x)
  5911. {
  5912. #ifdef DOS
  5913.   setmode(1, O_TEXT);
  5914. #else           /* unix */
  5915.   restore_stdin();
  5916. #endif
  5917.   if (x == SIGINT)
  5918.     exit(0);
  5919. }           /* cleanup */
  5920.  
  5921. void exit_program(int x)
  5922. {
  5923.   cleanup(-1);
  5924.   exit(x);
  5925. }           /* exit_program */
  5926.  
  5927. void print_error(char *message,...)
  5928. {           /* prints message to stderr and exits program */
  5929. #ifdef unix
  5930.   int ip[MAXARGS + 1];
  5931.   int i;
  5932.   va_list ap;
  5933.   va_start(ap, message);
  5934.   for (i = 1; i <= MAXARGS; i++)
  5935.     ip[i] = va_arg(ap, int);
  5936.   va_end(ap);
  5937. #else
  5938.   long *ip = (long *) &message;
  5939. #endif
  5940.   fprintf(stderr, message, ip[1], ip[2], ip[3], ip[4], ip[5], ip[6]);
  5941.   exit_program(1);
  5942. }           /* print_error */
  5943.  
  5944. int ISalpha(char c)
  5945. {
  5946.   if (c < '\0')
  5947.   {
  5948.     if (rejoin & 8)
  5949.       return (1);
  5950.     return (0);
  5951.   }
  5952.   return (isalpha(c));
  5953. }           /* ISalpha */
  5954.  
  5955. int Isdigit(char c)
  5956. {
  5957.   if (c <= '\0')
  5958.     return (0);
  5959.   return (isdigit(c));
  5960. }           /* Isdigit */
  5961.  
  5962. void main(int argc, char *argv[])
  5963. {
  5964.   int i, j;
  5965.   paramcount = argc - 1;
  5966.   paramstr = argv;
  5967.   /* initialize structures */
  5968.   b = (tablet *) malloc(sizeof(tablet));
  5969.   if (!b)
  5970.     print_error("\7Unable to allocate memory for table\n");
  5971.   memset(init, 0, sizeof(init_t));
  5972.   memset(&prog_extension.total, 0, sizeof(prog_ext_t));
  5973.   memset(hyp_name_verify, 0, sizeof(hyp_name_verify));
  5974.   stdin_tty = isatty(0);
  5975.   stdout_tty = isatty(1);
  5976. #ifdef unix
  5977.   save_stdin();
  5978.   if (stdout_tty)
  5979.     setbuf(stdout, NULL);    /* so printf always prints */
  5980. #endif           /* unix */
  5981.   get_config();
  5982.   signal(SIGINT, cleanup);
  5983.   if (no_copyright == FALSE)
  5984.   {           /* display message */
  5985.     fprintf(stderr, "\nNFBTRANS Grade Two Braille Translator - Release %s\n", VERSION);
  5986.     fprintf(stderr, "%s\n\n", COPYRIGHT);
  5987.   }           /* display message */
  5988.  
  5989.   copies = 0;
  5990.   if (usr_default == FALSE && pagestart <= 1 && trans_mode <= 0)
  5991.   {           /* choose mode */
  5992.     j = (trans_default % 10);
  5993.     fprintf(stderr, "\nPlease select\n");
  5994.     for (i = 0; i < 3; i++)
  5995.       fprintf(stderr, main_menu[i]);
  5996.     while (trans_mode < 1 || trans_mode > 3)
  5997.     {
  5998.       fprintf(stderr, "\nChoice? %d", j);
  5999.       backspace_int(j);
  6000. #ifdef DOS
  6001.       if (make_sound)
  6002.       {
  6003.     sound(440);
  6004.     delay(20);
  6005.     sound(1760);
  6006.     delay(20);
  6007.     nosound();
  6008.       }
  6009. #endif           /* DOS */
  6010.       get_digit();
  6011.       if (!temp[0])
  6012.     trans_mode = j;
  6013.       else
  6014.     trans_mode = atoi(temp);
  6015.     }           /* while */
  6016.   }           /* choose mode */
  6017.   if (trans_mode == 1 || trans_mode == 3 || usr_default == TRUE)
  6018.     translate_file();
  6019.   else
  6020.   if (trans_mode == 2)
  6021.     emboss_file();
  6022.   if (ab_flag)
  6023.     fprintf(
  6024.         stderr, "Program aborted\n");
  6025.   if (skip_output == TRUE && stdout_tty == TRUE)
  6026.   {
  6027.     do_pause();
  6028.     getch();
  6029.   }
  6030.   exit_program(0);
  6031. }           /* main */
  6032.