FCONVERT.CPP
上传用户:xr_qian
上传日期:2007-01-05
资源大小:443k
文件大小:31k
源码类别:

通讯/手机编程

开发平台:

DOS

  1. // ******************************************************************** //
  2. //                                                                      //
  3. //      FCONVERT.CPP                                                    //
  4. //      Copyright (c) 1993, Michael Holmes and Bob Flanders             //
  5. //      C++ Communication Utilities                                     //
  6. //                                                                      //
  7. //      This file contains the routines for converting to and           //
  8. //      from the G3 fax format.                                         //
  9. //                                                                      //
  10. // ******************************************************************** //
  11. //
  12. //  Conversion Routine Globals
  13. //
  14. int     f_handle = -1,                      // G3 file handle
  15.         f_pgcnt,                            // maximum page count
  16.         f_write_flag,                       // write_out bit buffer flag
  17.         f_write_cnt;                        // write_out global counter
  18. char   *f_buffer,                           // work buffer
  19.        *f_ptr,                              // ..and current pointer
  20.         f_filename[MAX_PATH];               // fax filename
  21. long    f_page;                             // current G3 page size
  22. #define HDR_LEN     128                     // header length
  23. #define BUF_SIZE    256                     // buffer size
  24. /* ******************************************************************** *
  25.  *
  26.  *  f_locate() -- find a G3 formatted file and check its integrity
  27.  *
  28.  *  returns: 0 = file opened
  29.  *           1 = file not found
  30.  *
  31.  * ******************************************************************** */
  32. int     f_locate(char *s)                   // source filename
  33. {
  34. long    file_size,                          // file size
  35.         pos;                                // current file position
  36. if (f_handle != -1)                         // q. already open?
  37.     {
  38.     close(f_handle);                        // a. yes .. close file
  39.     f_handle = -1;                          // ..and clear flag
  40.     }
  41. if (NOT first_nonblank(s))                  // q. empty string?
  42.     return(1);                              // a. yes .. just return
  43. if ((f_handle = open(s,                     // q. find and open file ok?
  44.             O_RDONLY | O_BINARY)) == -1)
  45.     return(1);                              // a. no .. return w/error
  46. file_size = lseek(f_handle, 0L, SEEK_END);  // get file size
  47. lseek(f_handle, 0L, SEEK_SET);              // ..and back to file start
  48. if ((read(f_handle, page, 128) != 128) ||   // q. file header available
  49.         strncmp((char *) page, "G3", 2))    // ..and our format?
  50.     {
  51.     close(f_handle);                        // a. no .. just close file
  52.     f_handle = -1;                          // ..clear flag
  53.     return(1);                              // ..and return to caller
  54.     }
  55. pos = lseek(f_handle, 0L, SEEK_CUR);        // get starting position
  56. for (f_pgcnt = 0;;)                         // count available fax pages
  57.     {
  58.     if (read(f_handle, (char *) &f_page,    // q. read in enough to cover
  59.             sizeof(long)) != sizeof(long))  // ..the page length field?
  60.         break;                              // a. no .. exit loop
  61.     if ((f_page < 1) ||                     // q. page size non-positive?
  62.         ((f_page + pos + 4) > file_size))   // ..or bigger than the file?
  63.         break;                              // a. yes .. exit loop
  64.     if ((pos = lseek(f_handle, f_page,      // q. properly position to the
  65.             SEEK_CUR)) == -1L)              // ..start of the next page?
  66.         break;                              // a. no .. exit loop
  67.     f_pgcnt++;                              // count this page
  68.     }
  69. strcpy(f_filename, s);                      // save filename ..
  70. return(0);                                  // ..then return all ok
  71. }
  72. /* ******************************************************************** *
  73.  *
  74.  *  f_get_next_byte() -- get the next byte from the G3 file
  75.  *
  76.  *  returns: -1 = end of data or error
  77.  *            n = next byte
  78.  *
  79.  * ******************************************************************** */
  80. int     f_get_next_byte(void)
  81. {
  82. static
  83. int     rb;                                 // remaining buffer count
  84. if (f_ptr == 0 || rb == 0)                  // q. 1st call or out of data?
  85.     {                                       // a. yes .. get the next blk
  86.     if (f_page == 0)                        // q. out of data to read?
  87.         return(-1);                         // a. yes .. return all done
  88.     if (f_buffer == 0)                      // q. buffer allocated?
  89.         f_buffer = (char *)                 // a. no .. get a buffer
  90.                  malloc_chk(BUF_SIZE);
  91.     rb = (int)((f_page > BUF_SIZE) ?        // set count to smaller of
  92.                 BUF_SIZE : f_page);         // ..what's left or buffer size
  93.     if (read(f_handle, f_buffer, rb) != rb) // q. file read ok?
  94.         quit_with(read_error);              // a. no .. give error message
  95.     f_page -= rb;                           // deduct what was read
  96.     f_ptr = f_buffer;                       // set up character pointer
  97.     }
  98. rb--;                                       // decriment remaining count
  99. return(*(unsigned char *) f_ptr++);         // ..and return character
  100. }
  101. /* ******************************************************************** *
  102.  *
  103.  *  f_get_byte() -- get the next value from the G3 file handling DLEs
  104.  *
  105.  *  returns: -1 = end of data or error
  106.  *            n = next byte
  107.  *
  108.  * ******************************************************************** */
  109. int     f_get_byte(void)
  110. {
  111. int     v;                                  // work value
  112. while (1)
  113.     {
  114.     if ((v = f_get_next_byte()) == -1)      // q. out of data?
  115.         return(-1);                         // a. yes .. return EOF
  116.     if (v == DLE)                           // q. DLE character?
  117.         {                                   // a. yes .. get another
  118.         if ((v = f_get_next_byte()) == -1)  // q. get another char ok?
  119.             return(-1);                     // a. no .. return EOF
  120.         if (v == DLE)                       // q. another DLE?
  121.             return(v);                      // a. yes .. return the goods
  122.         }
  123.      else
  124.         return(v);                          // else .. return w/character
  125.     }
  126. }
  127. /* ******************************************************************** *
  128.  *
  129.  *  f_get_bit() -- get the next bit from the G3 file
  130.  *
  131.  *  returns: -1 = end of data or error
  132.  *            0 = zero bit found
  133.  *            1 = one bit found
  134.  *
  135.  * ******************************************************************** */
  136. int     f_get_bit(void)
  137. {
  138. static
  139. int     w,                                  // work byte
  140.         c = 0;                              // bit count
  141. w >>= 1;                                    // move next bit into place
  142. if (f_ptr == 0 || c == 0)                   // q. 1st call or out of data?
  143.     {                                       // a. yes .. get a byte
  144.     if ((w = f_get_byte()) == -1)           // q. out of data?
  145.         return(-1);                         // a. yes .. return EOF
  146.     c = 8;                                  // number of available bits
  147.     }
  148. c--;                                        // show another one used
  149. return(w & 1);                              // ..then rtn a bit to caller
  150. }
  151. /* ******************************************************************** *
  152.  *
  153.  *  f_search() -- search for a codeword match
  154.  *
  155.  *  returns: -2 = end of line or error
  156.  *           -1 = no match found
  157.  *            n = match found, n is nbr of bits in codeword
  158.  *
  159.  * ******************************************************************** */
  160. int     f_search(int type,                  // type of code
  161.                                             //  0 = white space
  162.                                             //  1 = black space
  163.                  int l,                     // length in bits
  164.                  int a)                     // accumulator
  165. {
  166. struct  code_entry *e;                      // codeword table entries
  167. if (l == 12 && a == 1)                      // q. end of line found?
  168.     return(-2);                             // a. yes .. return to caller
  169. if ((e = code_table[l - 1][type]) != 0)     // q. table entry found?
  170.     {                                       // a. yes .. check table
  171.     for (; e->code; e++)                    // scan a codeword table
  172.         if (e->code == a)                   // q. find a codeword match?
  173.             return(e->value);               // a. yes .. return
  174.     }
  175. if (l == 13)                                // q. reach max codeword size?
  176.     return(-2);                             // a. yes .. return w/error
  177.  else
  178.     return(-1);                             // else .. rtn nothing found
  179. }
  180. /* ******************************************************************** *
  181.  *
  182.  *  f_get_code() -- get the next codeword from the G3 stream
  183.  *
  184.  *  returns: 0 = converted next word ok
  185.  *           1 = error or end of line
  186.  *
  187.  * ******************************************************************** */
  188. int     f_get_code(int type,                // type of code
  189.                                             //  0 = white space
  190.                                             //  1 = black space
  191.                    int *len)                // length in bits
  192. {
  193. int     a = 0,                              // accumulator
  194.         b,                                  // one bit work area
  195.         l = 0;                              // working length
  196. while (1)
  197.     {
  198.     if ((b = f_get_bit()) == -1)            // q. get a bit successfully?
  199.         return(1);                          // a. no .. must be out of data
  200.     a = (a << 1) | b;                       // shift in a new bit
  201.     l++;                                    // ..tally up bits received
  202.     switch (*len = f_search(type, l, a))    // check for match
  203.         {
  204.         case -2:                            // end of line or error
  205.             return(1);                      // ..just return
  206.         case -1:                            // nothing found
  207.             break;                          // ..continue looping
  208.         default:                            // found codeword
  209.             return(0);                      // ..return ok
  210.         }
  211.     }
  212. }
  213. /* ******************************************************************** *
  214.  *
  215.  *  f_get_pels() -- get the next group of PELS from the G3 stream
  216.  *
  217.  *  returns: 0 = converted next word ok
  218.  *           1 = error or end of line
  219.  *
  220.  * ******************************************************************** */
  221. int     f_get_pels(int type,                // type of code
  222.                                             //  0 = white space
  223.                                             //  1 = black space
  224.                    int *len)                // length in bits
  225. {
  226. int     a = 0;                              // accumulator
  227. while (1)
  228.     {
  229.     if (f_get_code(type, len))              // q. get a code word?
  230.         return(1);                          // a. no .. must be out of data
  231.     if (*len > 63)                          // q. get a makeup code?
  232.         a = *len;                           // a. yes .. save for later
  233.      else
  234.         {
  235.         *len += a;                          // else .. add in any makeups
  236.         return(0);                          // ..and return all ok
  237.         }
  238.     }
  239. }
  240. /* ******************************************************************** *
  241.  *
  242.  *  f_get_eol() -- read to end of line in current page
  243.  *
  244.  * ******************************************************************** */
  245. void    f_get_eol(void)
  246. {
  247. int     a,                                  // accumulator
  248.         b;                                  // work bit
  249. for (a = 0xfff; a != 1;)                    // try to find an EOL bit
  250.     {                                       // ..pattern of 000000000001
  251.     if ((b = f_get_bit()) == -1)            // q. get a bit successfully?
  252.         return;                             // a. no .. must be out of data
  253.     a = ((a << 1) | b) & 0xfff;             // move in new bit
  254.     }
  255. }
  256. /* ******************************************************************** *
  257.  *
  258.  *  f_read_g3() -- read a page and convert from G3 format
  259.  *
  260.  *  returns: 0 = page converted sucessfully
  261.  *           1 = page not found or error
  262.  *
  263.  * ******************************************************************** */
  264. int     f_read_g3(int n)                    // page number
  265. {
  266. int     pels,                               // pixels counter
  267.         lines,                              // lines counter
  268.         type,                               // type of codeword
  269.         codes,                              // codewords processed
  270.         eol,                                // consecutive EOLs found
  271.         l = 0;                              // work length
  272. char    huge *p;                            // bitmap line pointer
  273. lseek(f_handle, HDR_LEN, SEEK_SET);         // get to start of 1st page
  274. while(1)                                    // loop to find requested page
  275.     {
  276.     if (read(f_handle, (char *) &f_page,    // q. read in enough to cover
  277.             sizeof(long)) != sizeof(long))  // ..the page length field?
  278.         return(1);                          // a. no .. return not found
  279.     if (--n == 0)                           // q. find target page?
  280.         break;                              // a. yes .. exit loop
  281.     if (lseek(f_handle, f_page,             // q. properly position to the
  282.             SEEK_CUR) == -1L)               // ..start of the next page?
  283.         return(1);                          // a. no .. return not found
  284.     }
  285. f_ptr = 0;                                  // set global pointer
  286. f_get_eol();                                // find end of first line
  287. for (lines = 0, p = page;                   // for the whole bitmap
  288.             lines < LINES;                  // ..run through line
  289.             lines++, p += LINE)             // ..by line
  290.     memset(p, 0, LINE);                     // ..and clear white space
  291. for (lines = 0, p = page, eol = 0;          // fill in each line in the
  292.             lines < LINES;                  // ..bitmap page by processing
  293.             lines++, p += LINE)             // ..one line at a time
  294.     {
  295.     for (pels = 0, type = 0, codes = 0;     // for each bit available
  296.                 pels < PELS;                // ..in the bitmap line get
  297.                 pels += l, codes++)         // ..codewords and convert
  298.         {
  299.         if (f_get_pels(type, &l))           // q. end of line found?
  300.             break;                          // a. yes .. exit loop
  301.         if (l > (PELS - pels))              // q. too much data?
  302.             l = PELS - pels;                // a. yes .. set to max
  303.         if (type)                           // q. black bits?
  304.             set_bits((char *) p, pels, l);  // a. yes .. set bits on
  305.         type = (type + 1) & 1;              // switch back and forth
  306.         }                                   // ..between black and white
  307.     f_get_eol();                            // find the end of this line
  308.     if (NOT codes)                          // q. empty line?
  309.         {
  310.         eol++;                              // a. yes .. tally empty lines
  311.         if (eol == 6)                       // q. find the end of page?
  312.             break;                          // a. yes .. finish looping
  313.         }
  314.      else
  315.         eol = 0;                            // else .. clear EOL counter
  316.     }
  317. return(0);                                  // finally, return ok
  318. }
  319. /* ******************************************************************** *
  320.  *
  321.  *  f_write_hdr() -- write a fax file header
  322.  *
  323.  * ******************************************************************** */
  324. void    f_write_hdr(void)
  325. {
  326. char    buf[HDR_LEN];                       // header buffer
  327. memset(buf, 0, HDR_LEN);                    // clear buffer to nulls
  328. strcpy(buf, "G3");                          // ..and put in our marker
  329. write(f_handle, buf, HDR_LEN);              // write header
  330. }
  331. /* ******************************************************************** *
  332.  *
  333.  *  f_write_out() -- write bits to output fax file
  334.  *
  335.  * ******************************************************************** */
  336. void    f_write_out(int bits,               // output bits
  337.                     int len)                // ..and number of bits
  338. {
  339. static  unsigned
  340. char    w;                                  // byte wide queue
  341. if (len > 16)                               // q. too many bits?
  342.     return;                                 // a. yes .. just return
  343. bits <<= 16 - len;                          // shift to MSB end of word
  344. while (len--)                               // while there is input
  345.     {
  346.     w >>= 1;                                // shift queue over by one
  347.     if (bits & 0x8000)                      // q. source bit on?
  348.         w |= 0x80;                          // a. yes .. turn on dest
  349.     if (++f_write_flag == 8)                // q. reach limit?
  350.         {
  351.         write(f_handle, (void *) &w, 1);    // a. yes .. write a byte
  352.         if (w == DLE)                       // q. special character?
  353.             write(f_handle, (void *) &w, 1);// a. yes .. write it again
  354.         f_write_flag = 0;                   // clear the flag
  355.         f_write_cnt++;                      // ..and tally the byte
  356.         }
  357.     bits <<= 1;                             // shift source by one bit
  358.     }
  359. }
  360. /* ******************************************************************** *
  361.  *
  362.  *  f_encode() -- encode a string of bits into G3 format
  363.  *
  364.  * ******************************************************************** */
  365. void    f_encode(int cnt,                   // number of bits from bitmap
  366.                  int type)                  // ..and bit color
  367. {
  368. struct  encode_entry *ee;                   // encode entry
  369. if (cnt > 63)                                   // q. big run of bits?
  370.     {
  371.     ee = &encode_table[(cnt / 64) + 63][type];  // a. yes .. get pointer
  372.     f_write_out(ee->code, ee->bits);            // ..write make-up code
  373.     cnt %= 64;                                  // ..and update bit count
  374.     }
  375. ee = &encode_table[cnt][type];              // get element pointer
  376. f_write_out(ee->code, ee->bits);            // write terminating code
  377. }
  378. /* ******************************************************************** *
  379.  *
  380.  *  f_scan_out() -- scan the bitmap and output a codeword
  381.  *
  382.  * ******************************************************************** */
  383. int     f_scan_out(char huge *p,            // bitmap line
  384.                    int  i,                  // starting bit offset
  385.                    int  type)               // type to search
  386. {
  387. int     cnt;                                // work counter
  388. for (cnt = 0; i < PELS; i++, cnt++)         // scan bitmap line
  389.     if (get_bit(                            // q. find a bit which is not
  390.             (unsigned char *) p, i) != type)// ..the same as type?
  391.         break;                              // a. yes .. exit loop
  392. f_encode(cnt, type);                        // build/output codeword
  393. return(cnt);                                // ..then return with count
  394. }
  395. /* ******************************************************************** *
  396.  *
  397.  *  f_write_page() -- write a fax file page
  398.  *
  399.  * ******************************************************************** */
  400. void    f_write_page(Window *w)             // window to display msgs in
  401. {
  402. int     i, j = 0,                           // loop counter
  403.         line,                               // line counter
  404.         type;                               // pixel type
  405. char    buf[60],                            // work buffer
  406.         huge *p;                            // ..and pointer
  407. long    start_pos,                          // page starting position
  408.         page_len;                           // ..and page length
  409. static
  410. long    percent,                            // percent complete
  411.         last,                               // last display time
  412.         far *timer = (long far *)           // BIOS timer tick counter
  413.                         MK_FP(0x40, 0x6c);  // ..down in low memory
  414. lseek(f_handle, 0L, SEEK_END);              // goto end of file
  415. start_pos = tell(f_handle);                 // ..and get position info
  416. memset(buf, 0, sizeof(buf));                // clear buffer to nulls
  417. write(f_handle, buf, 4);                    // write page length
  418. write(f_handle, buf, 10);                   // ..and some nulls
  419. f_write_flag = 0;                           // clear output flag
  420. f_write_out(1, 12);                         // ..and write an EOL
  421. for (p = page, line = 0; line < LINES;      // for each line in the bitmap
  422.             line++, p += LINE)              // ..encode into G3 format
  423.     {
  424.     f_write_cnt = 0;                        // clear output byte count
  425.     if ((*timer - last) > 9)                // q. has half a second past?
  426.         {
  427.         percent = (line * 100L) / LINES;    // a. yes .. get percentage
  428.         sprintf(buf, write_msg,             // build status message
  429.                 f_pgcnt, percent);          // ..into a work buffer
  430.         w->Display(buf);                    // ..display the message
  431.         last = *timer;                      // ..and pickup current time
  432.         }
  433.     if (reverse_scan((char *) p, 0, LINE))  // q. anything on line?
  434.         {                                   // a. yes .. process
  435.         for (i = type = 0; i < PELS; i += j)// scan across the bitmap line
  436.             {
  437.             j = f_scan_out(p, i, type);     // scan bitmap for pixels
  438.             type = (type + 1) & 1;          // flip-flop the type code
  439.             }
  440.         }
  441.      else
  442.         f_encode(1728, 0);                  // else .. put out blank line
  443.     if (f_write_flag)                       // q. any residual bits?
  444.         f_write_out(0, 8 - f_write_flag);   // a. yes .. put out the rest
  445.     if (i < 40)                             // q. need to pad out line?
  446.         write(f_handle, (void *) &buf,      // a. yes .. write a string
  447.                 40 - i);                    // ..of up to 40 null bytes
  448.     f_write_out(1, 12);                     // then put out an EOL
  449.     }
  450. for (i = 0; i < 5; i++)                     // at end of page
  451.     f_write_out(1, 12);                     // ..put out 5 more EOLs
  452. buf[0] = DLE;                               // set up termination
  453. buf[1] = ETX;                               // ..with DLE ETX
  454. write(f_handle, buf, 2);                    // ..then put them out
  455. page_len = tell(f_handle) - start_pos - 4;  // compute page data length
  456. lseek(f_handle, start_pos, SEEK_SET);       // position to length field
  457. write(f_handle, (void *) &page_len, 4);     // ..and update field
  458. }
  459. /* ******************************************************************** *
  460.  *
  461.  *  f_build_char() -- fill in bitmap position with a character
  462.  *
  463.  * ******************************************************************** */
  464. void    f_build_char(char cc,               // character to use
  465.                      int  c, int r)         // column and row
  466. {
  467. UINT   *ce,                                 // table entry pointer
  468.        i;                                   // loop counter
  469. char   huge *p,                             // bitmap pointer
  470.        ch1, ch2;                            // high and low bytes
  471. ce = &ascii_map[cc][0];                     // get entry in table
  472. p = &page[((r * 22L) * LINE) + (c * 2)];    // get starting point
  473. for (i = 0; i < 11; i++, ce++)              // for each of the chars rows
  474.     {
  475.     if (*ce)                                // q. anything to put in bitmap?
  476.         {                                   // a. yes .. process bits
  477.         ch1 = *ce >> 8;                     // get high order byte
  478.         ch2 = *ce & 0xff;                   // ..and low order byte
  479.         *p |= ch1;                          // "or" in each cols bits
  480.         *(p + 1) |= ch2;                    // ..for both bytes
  481.         p += LINE;                          // move to next line
  482.         *p |= ch1;                          // "or" in each cols bits
  483.         *(p + 1) |= ch2;                    // ..for both bytes
  484.         p += LINE;                          // move to next line
  485.         }
  486.      else
  487.         p += LINE * 2;                      // else .. skip two bitmap lines
  488.     }
  489. }
  490. /* ******************************************************************** *
  491.  *
  492.  *  f_build_page() -- read an ASCII text file and build a bitmap
  493.  *
  494.  *  returns: 0 = end of file reached
  495.  *           n = characters encoded
  496.  *
  497.  * ******************************************************************** */
  498. int     f_build_page(FILE *f)               // input file pointer
  499. {
  500. int     i,                                  // chars processed
  501.         lines,                              // lines counter
  502.         c, r,                               // column and row (0 based)
  503.         cc;                                 // character buffer
  504. char    huge *p;                            // bitmap line pointer
  505. for (lines = 0, p = page;                   // for the whole bitmap
  506.             lines < LINES;                  // ..run through line
  507.             lines++, p += LINE)             // ..by line
  508.     memset(p, 0, LINE);                     // ..and clear white space
  509. c = r = 0;                                  // start column & row at top
  510. for (i = 0; ; i++)                          // loop building bitmap
  511.     {
  512.     if ((cc = fgetc(f)) == EOF)             // q. get a good character?
  513.         return(i);                          // a. no .. return w/count
  514.     f_build_char(cc, c, r);                 // bld bitmap at column & row
  515.     switch (cc)                             // update column & row
  516.         {
  517.         case LF:                            // line feed
  518.             if (++r >= ROWS)                // q. reach bottom limit?
  519.                 return(i);                  // a. yes .. then page is done
  520.             break;                          // else .. get next character
  521.         case CR:                            // carriage return
  522.             c = 0;                          // start at next beginning
  523.             break;                          // ..and get next character
  524.         case 12:                            // form feed
  525.             return(++i);                    // return w/nbr chars processed
  526.         case BACKSPACE:                     // backspace
  527.             if (--c < 0)                    // q. backup too far?
  528.                 c = 0;                      // a. yes .. goto column 0
  529.             break;                          // else .. get next character
  530.         case TAB:                           // tab
  531.             c = (c & ~0x7) + 8;             // move to next tab stop
  532.             if (c >= COLUMNS)               // q. too far out?
  533.                 {
  534.                 c = 0;                      // a. yes .. just wrap around
  535.                 if (++r >= ROWS)            // q. reach bottom of page?
  536.                     return(i);              // a. yes .. stop here
  537.                 }
  538.             break;                          // else .. get next character
  539.         default:                            // everything else
  540.             if (++c >= COLUMNS)             // q. reach right margin?
  541.                 {
  542.                 c = 0;                      // a. yes .. just wrap around
  543.                 if (++r >= ROWS)            // q. reach bottom of page?
  544.                     return(i);              // a. yes .. stop here
  545.                 }
  546.         }
  547.     }
  548. }
  549. /* ******************************************************************** *
  550.  *
  551.  *  f_build_fax() -- build a fax file from an ASCII text file
  552.  *
  553.  * ******************************************************************** */
  554. void    f_build_fax(char *f,                // file name
  555.                     Window *w)              // window to update
  556. {
  557. FILE   *fi;                                 // input file
  558. int     i;                                  // string index
  559. char    buf[60], buf2[60],                  // format buffers
  560.        *p;                                  // ..and pointer
  561. if (f_handle != -1)                         // q. already open?
  562.     {
  563.     close(f_handle);                        // a. yes .. close file
  564.     f_handle = -1;                          // ..and clear flag
  565.     }
  566. if ((fi = fopen(f, "rb")) == 0)             // q. open ok?
  567.     return;                                 // a. no .. just return
  568. strcpy(buf, f);                             // copy base filename
  569. if ((p = strrchr(buf, '.')) == 0)           // q. file extension found?
  570.     p = &buf[strlen(buf)];                  // a. no .. point to end
  571. strcpy(p, ".fax");                          // copy in extension
  572. if ((f_handle = open(buf,                   // q. open new file ok?
  573.             O_BINARY | O_TRUNC | O_RDWR | O_CREAT)) == -1)
  574.     return;                                 // a. no .. just return
  575. sprintf(buf2, create_msg, buf);             // build display message
  576. w->Display(buf2);                           // ..and send to user window
  577. if ((i = 34 - (strlen(f) +                  // q. able to center the
  578.         strlen(status_conv) - 2)) < 0)      // .."Converting: XXXX" msg?
  579.     i = 0;                                  // a. no .. flush left
  580. memset(buf2, ' ', sizeof(buf2));            // clear area to blanks
  581. sprintf(&buf2[i / 2], status_conv, f);      // format build information
  582. status_line(status, buf2);                  // update status line
  583. f_write_hdr();                              // write header information
  584. for (f_pgcnt = 1; ; f_pgcnt++)              // loop building and writing
  585.     {
  586.     if (f_build_page(fi) == 0)              // q. read ASCII ok?
  587.         break;                              // a. no .. end of file
  588.     f_write_page(w);                        // encode bitmap & write file
  589.     }
  590. fclose(fi);                                 // close input file
  591. close(f_handle);                            // ..and output file
  592. f_handle = -1;                              // ..and reset global
  593. f_locate(buf);                              // set up to view/print file
  594. sprintf(buf2, status_file,                  // format file information
  595.         buf, f_pgcnt);                      // ..for status line
  596. if (f_pgcnt > 1)                            // q. more than 1 page fax?
  597.     strcat(buf2, "s");                      // a. yes .. pluralize page
  598. status_line(status, buf2);                  // update status line
  599. }