FCONVERT.CPP
资源名称:commutil.zip [点击查看]
上传用户:xr_qian
上传日期:2007-01-05
资源大小:443k
文件大小:31k
源码类别:
通讯/手机编程
开发平台:
DOS
- // ******************************************************************** //
- // //
- // FCONVERT.CPP //
- // Copyright (c) 1993, Michael Holmes and Bob Flanders //
- // C++ Communication Utilities //
- // //
- // This file contains the routines for converting to and //
- // from the G3 fax format. //
- // //
- // ******************************************************************** //
- //
- // Conversion Routine Globals
- //
- int f_handle = -1, // G3 file handle
- f_pgcnt, // maximum page count
- f_write_flag, // write_out bit buffer flag
- f_write_cnt; // write_out global counter
- char *f_buffer, // work buffer
- *f_ptr, // ..and current pointer
- f_filename[MAX_PATH]; // fax filename
- long f_page; // current G3 page size
- #define HDR_LEN 128 // header length
- #define BUF_SIZE 256 // buffer size
- /* ******************************************************************** *
- *
- * f_locate() -- find a G3 formatted file and check its integrity
- *
- * returns: 0 = file opened
- * 1 = file not found
- *
- * ******************************************************************** */
- int f_locate(char *s) // source filename
- {
- long file_size, // file size
- pos; // current file position
- if (f_handle != -1) // q. already open?
- {
- close(f_handle); // a. yes .. close file
- f_handle = -1; // ..and clear flag
- }
- if (NOT first_nonblank(s)) // q. empty string?
- return(1); // a. yes .. just return
- if ((f_handle = open(s, // q. find and open file ok?
- _O_RDONLY | _O_BINARY)) == -1)
- return(1); // a. no .. return w/error
- file_size = lseek(f_handle, 0L, SEEK_END); // get file size
- lseek(f_handle, 0L, SEEK_SET); // ..and back to file start
- if ((read(f_handle, page, 128) != 128) || // q. file header available
- strncmp((char *) page, "G3", 2)) // ..and our format?
- {
- close(f_handle); // a. no .. just close file
- f_handle = -1; // ..clear flag
- return(1); // ..and return to caller
- }
- pos = lseek(f_handle, 0L, SEEK_CUR); // get starting position
- for (f_pgcnt = 0;;) // count available fax pages
- {
- if (read(f_handle, (char *) &f_page, // q. read in enough to cover
- sizeof(long)) != sizeof(long)) // ..the page length field?
- break; // a. no .. exit loop
- if ((f_page < 1) || // q. page size non-positive?
- ((f_page + pos + 4) > file_size)) // ..or bigger than the file?
- break; // a. yes .. exit loop
- if ((pos = lseek(f_handle, f_page, // q. properly position to the
- SEEK_CUR)) == -1L) // ..start of the next page?
- break; // a. no .. exit loop
- f_pgcnt++; // count this page
- }
- strcpy(f_filename, s); // save filename ..
- return(0); // ..then return all ok
- }
- /* ******************************************************************** *
- *
- * f_get_next_byte() -- get the next byte from the G3 file
- *
- * returns: -1 = end of data or error
- * n = next byte
- *
- * ******************************************************************** */
- int f_get_next_byte(void)
- {
- static
- int rb; // remaining buffer count
- if (f_ptr == 0 || rb == 0) // q. 1st call or out of data?
- { // a. yes .. get the next blk
- if (f_page == 0) // q. out of data to read?
- return(-1); // a. yes .. return all done
- if (f_buffer == 0) // q. buffer allocated?
- f_buffer = (char *) // a. no .. get a buffer
- malloc_chk(BUF_SIZE);
- rb = (int)((f_page > BUF_SIZE) ? // set count to smaller of
- BUF_SIZE : f_page); // ..what's left or buffer size
- if (read(f_handle, f_buffer, rb) != rb) // q. file read ok?
- quit_with(read_error); // a. no .. give error message
- f_page -= rb; // deduct what was read
- f_ptr = f_buffer; // set up character pointer
- }
- rb--; // decriment remaining count
- return(*(unsigned char *) f_ptr++); // ..and return character
- }
- /* ******************************************************************** *
- *
- * f_get_byte() -- get the next value from the G3 file handling DLEs
- *
- * returns: -1 = end of data or error
- * n = next byte
- *
- * ******************************************************************** */
- int f_get_byte(void)
- {
- int v; // work value
- while (1)
- {
- if ((v = f_get_next_byte()) == -1) // q. out of data?
- return(-1); // a. yes .. return EOF
- if (v == DLE) // q. DLE character?
- { // a. yes .. get another
- if ((v = f_get_next_byte()) == -1) // q. get another char ok?
- return(-1); // a. no .. return EOF
- if (v == DLE) // q. another DLE?
- return(v); // a. yes .. return the goods
- }
- else
- return(v); // else .. return w/character
- }
- }
- /* ******************************************************************** *
- *
- * f_get_bit() -- get the next bit from the G3 file
- *
- * returns: -1 = end of data or error
- * 0 = zero bit found
- * 1 = one bit found
- *
- * ******************************************************************** */
- int f_get_bit(void)
- {
- static
- int w, // work byte
- c = 0; // bit count
- w >>= 1; // move next bit into place
- if (f_ptr == 0 || c == 0) // q. 1st call or out of data?
- { // a. yes .. get a byte
- if ((w = f_get_byte()) == -1) // q. out of data?
- return(-1); // a. yes .. return EOF
- c = 8; // number of available bits
- }
- c--; // show another one used
- return(w & 1); // ..then rtn a bit to caller
- }
- /* ******************************************************************** *
- *
- * f_search() -- search for a codeword match
- *
- * returns: -2 = end of line or error
- * -1 = no match found
- * n = match found, n is nbr of bits in codeword
- *
- * ******************************************************************** */
- int f_search(int type, // type of code
- // 0 = white space
- // 1 = black space
- int l, // length in bits
- int a) // accumulator
- {
- struct code_entry *e; // codeword table entries
- if (l == 12 && a == 1) // q. end of line found?
- return(-2); // a. yes .. return to caller
- if ((e = code_table[l - 1][type]) != 0) // q. table entry found?
- { // a. yes .. check table
- for (; e->code; e++) // scan a codeword table
- if (e->code == a) // q. find a codeword match?
- return(e->value); // a. yes .. return
- }
- if (l == 13) // q. reach max codeword size?
- return(-2); // a. yes .. return w/error
- else
- return(-1); // else .. rtn nothing found
- }
- /* ******************************************************************** *
- *
- * f_get_code() -- get the next codeword from the G3 stream
- *
- * returns: 0 = converted next word ok
- * 1 = error or end of line
- *
- * ******************************************************************** */
- int f_get_code(int type, // type of code
- // 0 = white space
- // 1 = black space
- int *len) // length in bits
- {
- int a = 0, // accumulator
- b, // one bit work area
- l = 0; // working length
- while (1)
- {
- if ((b = f_get_bit()) == -1) // q. get a bit successfully?
- return(1); // a. no .. must be out of data
- a = (a << 1) | b; // shift in a new bit
- l++; // ..tally up bits received
- switch (*len = f_search(type, l, a)) // check for match
- {
- case -2: // end of line or error
- return(1); // ..just return
- case -1: // nothing found
- break; // ..continue looping
- default: // found codeword
- return(0); // ..return ok
- }
- }
- return(0); // make MSC C/C++ happy
- }
- /* ******************************************************************** *
- *
- * f_get_pels() -- get the next group of PELS from the G3 stream
- *
- * returns: 0 = converted next word ok
- * 1 = error or end of line
- *
- * ******************************************************************** */
- int f_get_pels(int type, // type of code
- // 0 = white space
- // 1 = black space
- int *len) // length in bits
- {
- int a = 0; // accumulator
- while (1)
- {
- if (f_get_code(type, len)) // q. get a code word?
- return(1); // a. no .. must be out of data
- if (*len > 63) // q. get a makeup code?
- a = *len; // a. yes .. save for later
- else
- {
- *len += a; // else .. add in any makeups
- return(0); // ..and return all ok
- }
- }
- }
- /* ******************************************************************** *
- *
- * f_get_eol() -- read to end of line in current page
- *
- * ******************************************************************** */
- void f_get_eol(void)
- {
- int a, // accumulator
- b; // work bit
- for (a = 0xfff; a != 1;) // try to find an EOL bit
- { // ..pattern of 000000000001
- if ((b = f_get_bit()) == -1) // q. get a bit successfully?
- return; // a. no .. must be out of data
- a = ((a << 1) | b) & 0xfff; // move in new bit
- }
- }
- /* ******************************************************************** *
- *
- * f_read_g3() -- read a page and convert from G3 format
- *
- * returns: 0 = page converted sucessfully
- * 1 = page not found or error
- *
- * ******************************************************************** */
- int f_read_g3(int n) // page number
- {
- int pels, // pixels counter
- lines, // lines counter
- type, // type of codeword
- codes, // codewords processed
- eol, // consecutive EOLs found
- l = 0; // work length
- char huge *p; // bitmap line pointer
- lseek(f_handle, HDR_LEN, SEEK_SET); // get to start of 1st page
- while(1) // loop to find requested page
- {
- if (read(f_handle, (char *) &f_page, // q. read in enough to cover
- sizeof(long)) != sizeof(long)) // ..the page length field?
- return(1); // a. no .. return not found
- if (--n == 0) // q. find target page?
- break; // a. yes .. exit loop
- if (lseek(f_handle, f_page, // q. properly position to the
- SEEK_CUR) == -1L) // ..start of the next page?
- return(1); // a. no .. return not found
- }
- f_ptr = 0; // set global pointer
- f_get_eol(); // find end of first line
- for (lines = 0, p = page; // for the whole bitmap
- lines < LINES; // ..run through line
- lines++, p += LINE) // ..by line
- memset(p, 0, LINE); // ..and clear white space
- for (lines = 0, p = page, eol = 0; // fill in each line in the
- lines < LINES; // ..bitmap page by processing
- lines++, p += LINE) // ..one line at a time
- {
- for (pels = 0, type = 0, codes = 0; // for each bit available
- pels < PELS; // ..in the bitmap line get
- pels += l, codes++) // ..codewords and convert
- {
- if (f_get_pels(type, &l)) // q. end of line found?
- break; // a. yes .. exit loop
- if (l > (PELS - pels)) // q. too much data?
- l = PELS - pels; // a. yes .. set to max
- if (type) // q. black bits?
- set_bits(p, pels, l); // a. yes .. set bits on
- type = (type + 1) & 1; // switch back and forth
- } // ..between black and white
- f_get_eol(); // find the end of this line
- if (NOT codes) // q. empty line?
- {
- eol++; // a. yes .. tally empty lines
- if (eol == 6) // q. find the end of page?
- break; // a. yes .. finish looping
- }
- else
- eol = 0; // else .. clear EOL counter
- }
- return(0); // finally, return ok
- }
- /* ******************************************************************** *
- *
- * f_write_hdr() -- write a fax file header
- *
- * ******************************************************************** */
- void f_write_hdr(void)
- {
- char buf[HDR_LEN]; // header buffer
- memset(buf, 0, HDR_LEN); // clear buffer to nulls
- strcpy(buf, "G3"); // ..and put in our marker
- write(f_handle, buf, HDR_LEN); // write header
- }
- /* ******************************************************************** *
- *
- * f_write_out() -- write bits to output fax file
- *
- * ******************************************************************** */
- void f_write_out(int bits, // output bits
- int len) // ..and number of bits
- {
- static unsigned
- char w; // byte wide queue
- if (len > 16) // q. too many bits?
- return; // a. yes .. just return
- bits <<= 16 - len; // shift to MSB end of word
- while (len--) // while there is input
- {
- w >>= 1; // shift queue over by one
- if (bits & 0x8000) // q. source bit on?
- w |= 0x80; // a. yes .. turn on dest
- if (++f_write_flag == 8) // q. reach limit?
- {
- write(f_handle, (void *) &w, 1); // a. yes .. write a byte
- if (w == DLE) // q. special character?
- write(f_handle, (void *) &w, 1);// a. yes .. write it again
- f_write_flag = 0; // clear the flag
- f_write_cnt++; // ..and tally the byte
- }
- bits <<= 1; // shift source by one bit
- }
- }
- /* ******************************************************************** *
- *
- * f_encode() -- encode a string of bits into G3 format
- *
- * ******************************************************************** */
- void f_encode(int cnt, // number of bits from bitmap
- int type) // ..and bit color
- {
- struct encode_entry *ee; // encode entry
- if (cnt > 63) // q. big run of bits?
- {
- ee = &encode_table[(cnt / 64) + 63][type]; // a. yes .. get pointer
- f_write_out(ee->code, ee->bits); // ..write make-up code
- cnt %= 64; // ..and update bit count
- }
- ee = &encode_table[cnt][type]; // get element pointer
- f_write_out(ee->code, ee->bits); // write terminating code
- }
- /* ******************************************************************** *
- *
- * f_scan_out() -- scan the bitmap and output a codeword
- *
- * ******************************************************************** */
- int f_scan_out(char huge *p, // bitmap line
- int i, // starting bit offset
- int type) // type to search
- {
- int cnt; // work counter
- for (cnt = 0; i < PELS; i++, cnt++) // scan bitmap line
- if (get_bit( // q. find a bit which is not
- (unsigned char *) p, i) != type)// ..the same as type?
- break; // a. yes .. exit loop
- f_encode(cnt, type); // build/output codeword
- return(cnt); // ..then return with count
- }
- /* ******************************************************************** *
- *
- * f_write_page() -- write a fax file page
- *
- * ******************************************************************** */
- void f_write_page(Window *w) // window to display msgs in
- {
- int i, j = 0, // loop counter
- line, // line counter
- type; // pixel type
- char buf[60], // work buffer
- huge *p; // ..and pointer
- long start_pos, // page starting position
- page_len; // ..and page length
- static
- long percent, // percent complete
- last, // last display time
- far *timer = (long far *) // BIOS timer tick counter
- MK_FP(0x40, 0x6c); // ..down in low memory
- lseek(f_handle, 0L, SEEK_END); // goto end of file
- start_pos = tell(f_handle); // ..and get position info
- memset(buf, 0, sizeof(buf)); // clear buffer to nulls
- write(f_handle, buf, 4); // write page length
- write(f_handle, buf, 10); // ..and some nulls
- f_write_flag = 0; // clear output flag
- f_write_out(1, 12); // ..and write an EOL
- for (p = page, line = 0; line < LINES; // for each line in the bitmap
- line++, p += LINE) // ..encode into G3 format
- {
- f_write_cnt = 0; // clear output byte count
- if ((*timer - last) > 9) // q. has half a second past?
- {
- percent = (line * 100L) / LINES; // a. yes .. get percentage
- sprintf(buf, write_msg, // build status message
- f_pgcnt, percent); // ..into a work buffer
- w->Display(buf); // ..display the message
- last = *timer; // ..and pickup current time
- }
- if (reverse_scan((char *) p, 0, LINE)) // q. anything on line?
- { // a. yes .. process
- for (i = type = 0; i < PELS; i += j)// scan across the bitmap line
- {
- j = f_scan_out(p, i, type); // scan bitmap for pixels
- type = (type + 1) & 1; // flip-flop the type code
- }
- }
- else
- f_encode(1728, 0); // else .. put out blank line
- if (f_write_flag) // q. any residual bits?
- f_write_out(0, 8 - f_write_flag); // a. yes .. put out the rest
- if (i < 40) // q. need to pad out line?
- write(f_handle, (void *) &buf, // a. yes .. write a string
- 40 - i); // ..of up to 40 null bytes
- f_write_out(1, 12); // then put out an EOL
- }
- for (i = 0; i < 5; i++) // at end of page
- f_write_out(1, 12); // ..put out 5 more EOLs
- buf[0] = DLE; // set up termination
- buf[1] = ETX; // ..with DLE ETX
- write(f_handle, buf, 2); // ..then put them out
- page_len = tell(f_handle) - start_pos - 4; // compute page data length
- lseek(f_handle, start_pos, SEEK_SET); // position to length field
- write(f_handle, (void *) &page_len, 4); // ..and update field
- }
- /* ******************************************************************** *
- *
- * f_build_char() -- fill in bitmap position with a character
- *
- * ******************************************************************** */
- void f_build_char(char cc, // character to use
- int c, int r) // column and row
- {
- UINT *ce, // table entry pointer
- i; // loop counter
- char huge *p, // bitmap pointer
- ch1, ch2; // high and low bytes
- ce = &ascii_map[cc][0]; // get entry in table
- p = &page[((r * 22L) * LINE) + (c * 2)]; // get starting point
- for (i = 0; i < 11; i++, ce++) // for each of the chars rows
- {
- if (*ce) // q. anything to put in bitmap?
- { // a. yes .. process bits
- ch1 = *ce >> 8; // get high order byte
- ch2 = *ce & 0xff; // ..and low order byte
- *p |= ch1; // "or" in each cols bits
- *(p + 1) |= ch2; // ..for both bytes
- p += LINE; // move to next line
- *p |= ch1; // "or" in each cols bits
- *(p + 1) |= ch2; // ..for both bytes
- p += LINE; // move to next line
- }
- else
- p += LINE * 2; // else .. skip two bitmap lines
- }
- }
- /* ******************************************************************** *
- *
- * f_build_page() -- read an ASCII text file and build a bitmap
- *
- * returns: 0 = end of file reached
- * n = characters encoded
- *
- * ******************************************************************** */
- int f_build_page(FILE *f) // input file pointer
- {
- int i, // chars processed
- lines, // lines counter
- c, r, // column and row (0 based)
- cc; // character buffer
- char huge *p; // bitmap line pointer
- for (lines = 0, p = page; // for the whole bitmap
- lines < LINES; // ..run through line
- lines++, p += LINE) // ..by line
- memset(p, 0, LINE); // ..and clear white space
- c = r = 0; // start column & row at top
- for (i = 0; ; i++) // loop building bitmap
- {
- if ((cc = fgetc(f)) == EOF) // q. get a good character?
- return(i); // a. no .. return w/count
- f_build_char(cc, c, r); // bld bitmap at column & row
- switch (cc) // update column & row
- {
- case LF: // line feed
- if (++r >= ROWS) // q. reach bottom limit?
- return(i); // a. yes .. then page is done
- break; // else .. get next character
- case CR: // carriage return
- c = 0; // start at next beginning
- break; // ..and get next character
- case 12: // form feed
- return(++i); // return w/nbr chars processed
- case BACKSPACE: // backspace
- if (--c < 0) // q. backup too far?
- c = 0; // a. yes .. goto column 0
- break; // else .. get next character
- case TAB: // tab
- c = (c & ~0x7) + 8; // move to next tab stop
- if (c >= COLUMNS) // q. too far out?
- {
- c = 0; // a. yes .. just wrap around
- if (++r >= ROWS) // q. reach bottom of page?
- return(i); // a. yes .. stop here
- }
- break; // else .. get next character
- default: // everything else
- if (++c >= COLUMNS) // q. reach right margin?
- {
- c = 0; // a. yes .. just wrap around
- if (++r >= ROWS) // q. reach bottom of page?
- return(i); // a. yes .. stop here
- }
- }
- }
- return(0); // make MSC C/C++ happy
- }
- /* ******************************************************************** *
- *
- * f_build_fax() -- build a fax file from an ASCII text file
- *
- * ******************************************************************** */
- void f_build_fax(char *f, // file name
- Window *w) // window to update
- {
- FILE *fi; // input file
- int i; // string index
- char buf[60], buf2[60], // format buffers
- *p; // ..and pointer
- if (f_handle != -1) // q. already open?
- {
- close(f_handle); // a. yes .. close file
- f_handle = -1; // ..and clear flag
- }
- if ((fi = fopen(f, "rb")) == 0) // q. open ok?
- return; // a. no .. just return
- strcpy(buf, f); // copy base filename
- if ((p = strrchr(buf, '.')) == 0) // q. file extension found?
- p = &buf[strlen(buf)]; // a. no .. point to end
- strcpy(p, ".fax"); // copy in extension
- if ((f_handle = open(buf, // q. open new file ok?
- _O_BINARY | _O_TRUNC | _O_RDWR | _O_CREAT)) == -1)
- return; // a. no .. just return
- sprintf(buf2, create_msg, buf); // build display message
- w->Display(buf2); // ..and send to user window
- if ((i = 34 - (strlen(f) + // q. able to center the
- strlen(status_conv) - 2)) < 0) // .."Converting: XXXX" msg?
- i = 0; // a. no .. flush left
- memset(buf2, ' ', sizeof(buf2)); // clear area to blanks
- sprintf(&buf2[i / 2], status_conv, f); // format build information
- status_line(status, buf2); // update status line
- f_write_hdr(); // write header information
- for (f_pgcnt = 1; ; f_pgcnt++) // loop building and writing
- {
- if (f_build_page(fi) == 0) // q. read ASCII ok?
- break; // a. no .. end of file
- f_write_page(w); // encode bitmap & write file
- }
- fclose(fi); // close input file
- close(f_handle); // ..and output file
- f_handle = -1; // ..and reset global
- f_locate(buf); // set up to view/print file
- sprintf(buf2, status_file, // format file information
- buf, f_pgcnt); // ..for status line
- if (f_pgcnt > 1) // q. more than 1 page fax?
- strcat(buf2, "s"); // a. yes .. pluralize page
- status_line(status, buf2); // update status line
- }