
/********************************************************************
Program:  folding.c 
Change "no hard return" GuoBiao text into "hard return" GuoBiao text 
i.e., add in hard return (\n) after a specified number of Chinese char.
Two modes:  Default:  Count ASCII char as 1 byte and GuoBiao char as 2 byte.
        Expand mode:  Count both ASCII and GuoBiao char as 2 byte.
The annoying <CR> (\r) are striped off in the folding process
To remove all <CR> code without changing text format, specify a 
very large text width (line length) such as 5000.
For usage, type  "folding"  on command line (after compilation). 
Author: Rupert Zhu.  April 24/1991.
Revised: April 27/1991, May 4/1991.
Send suggestion or bug report to  <rzhu@watmath.waterloo.edu> 
********************************************************************/

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
#define  DEFAULT_LENGTH    72    /* 36 Chinese characters per line */
#define  TRUE       1
#define  FALSE      0

char	*pgname;      /* name of this program  */
int	width_flag = FALSE;   /* command line flag for text width */
int	expand_flag = FALSE;   /* if on, count each ASCII char as 2 byte */
int	s_flag = FALSE;   /* command line flag for using stdin and stdout */
int	name_flag = FALSE;  /* indicate whether a file_name is provided */
int	line_length = DEFAULT_LENGTH;
int	lf_count = 0;  /*  no. of <LF> added */
int	cr_count = 0;  /*  no. of <CR> removed */
int	line_count = 0;  /*  total no. of <LF> in output file   */
char in_name[81];     /* input file name (with extension) */
char out_name[81];    /* output file name (with extension .gb0) */
char name[81];        /* file name (without extension */
FILE *in_file; 
FILE *out_file;

void usage()
{
fprintf(stderr, "|--------------------------------------------------------|\n");
fprintf(stderr, "| Usage 1:  folding [-wn] [-e] file_name   (Recommended) |\n");
fprintf(stderr, "|    Option -wn: Width = n Chinese characters.  Default  |\n");
fprintf(stderr, "|             n = 36.  (no space between w and number n) |\n");
fprintf(stderr, "|    Option -e:  Expand, i.e., count ASCII character as  |\n");
fprintf(stderr, "|                2 byte when calculating text width      |\n");
fprintf(stderr, "|    Output =  file_name.gb0                             |\n");
fprintf(stderr, "| Usage 2:  folding  [-wn] [-e] -s     (Not recommended) |\n");
fprintf(stderr, "|    Flag -s:  input = stdin,  output = stdout           |\n");
fprintf(stderr, "| Example 1:  folding  CM9104A.GB                        |\n");
fprintf(stderr, "|     Formatted (folded) text in file CM9104A.gb0        |\n");
fprintf(stderr, "| Example 2:  folding  -w35  -e  testfile                |\n");
fprintf(stderr, "|     Formatted (folded) text in file  testfile.gb0      |\n");
fprintf(stderr, "|--------------------------------------------------------|\n");
exit(1);
}

/* this does the real folding work */
void fold()
{
	int	b, width_count=0;   /* counting no. of char in current line */
	unsigned int	c;
	int	even = TRUE;

	while ( ( b=fgetc(in_file) ) != EOF) {
		c = (unsigned int) b;
		if ( c == '\r' ) {
			cr_count ++;
			c = fgetc(in_file);   /* strip off <CR> */
		}
		if ( c == '\t' )
			width_count += 8;
		else if ( isprint(c) && expand_flag )
			width_count += 2;
		else
			width_count += 1;
		if ( c == '\n' ) {
			width_count = 0;
			line_count ++;
		}
		if ( isprint(c) || isspace(c) )
			even = TRUE;
		if ( c >= 0xA1  &&  c <= 0xFE )   /* GB range */
			even = !even;     /* Chinese char is a pair of bytes */
		if ( width_count < line_length ) {
			fputc(c, out_file);
		}
		else {
			if (!even) 
				fputc(c, out_file);
			else {                    /* add a '\n' here */
				fputc(c, out_file);
				fputc('\n', out_file);
				lf_count ++;
				width_count = 0;
				line_count ++;
			}
		}
	}
}

/* if -s flag, use stdin and stdout; otherwise, use the name provided */
void open_file()
{
	if ( s_flag ) {
		in_file = stdin;
		out_file = stdout;
	}
	else if (name_flag) {
		if ((in_file=fopen(in_name, "r+b")) == NULL)
			usage();
		if ((out_file=fopen(out_name,"w+b")) == NULL) {
			fprintf(stderr, "Cannot open out_file");
			exit(1);
		}
	}
}

/* report to user what is done */
void message()
{
	if (name_flag && !s_flag) {
		fprintf(stderr, "\t|----------------------------------|\n");
		fprintf(stderr, "\t| Input_file  =  %-16.15s  |\n", in_name);
		fprintf(stderr, "\t| Output_file =  %-16.15s  |\n", out_name);
		fprintf(stderr, "\t| Formatted: Text Width  =  %4d   |\n",
		line_length / 2 );
		fprintf(stderr, "\t| Number of <LF> added   =  %4d   |\n",
		lf_count);
		fprintf(stderr, "\t| Number of <CR> removed =  %4d   |\n",
		cr_count);
		fprintf(stderr, "\t| Total number of lines  =  %4d   |\n",
		line_count);
		fprintf(stderr, "\t| Job Well Done !                  |\n");
		fprintf(stderr, "\t|----------------------------------|\n");
	}
}

main(argc, argv)
int argc; char *argv[];
{
	int	i;
	char	*cp;

	if (argc <= 1 || argc >= 5) 
		usage();
	pgname = argv[0];
	in_file = NULL;
	out_file = NULL;
	for (i=1; i<argc; i++) {
		cp = argv[i];
		if (*cp == '-') {  /* a flag */
			if (*++cp == 'w') {   /*  width flag  */
				width_flag++;
				line_length = 2 * atoi(++cp);
			}     /* one Chinese character takes two bytes */
			else if ( *cp == 'e' ) {  /* expand char to 2-byte */
				expand_flag ++;
			}
			else if ( *cp == 's' ) {  /* stdin, stdout */
				s_flag ++;
			}
		}
		else {         /* a file name argument */
			if ( name_flag == TRUE ) 
				usage();
			name_flag = TRUE;
			strcpy(in_name, cp);
			sscanf(in_name, "%[^.]", name);
			strcpy(out_name, "");   /* initialization */
			strcat(out_name, name);
			strcat(out_name, ".gb0");   /* use extension .gb0 */
		}
	}
	if ( !name_flag && !s_flag )
		usage();
	else {
		open_file();
		fold();
		message();
	}
}

/* This is written in standard C, instead of ANSI C, for maximum
   portability.  (Some old C compilers do not know ANSI C yet.)  */

