From: jing@resmel.bhp.com.au (Jian Feng)
Subject: A Program for reading HXWZ on your mainframe.
Organization: BHP Research - Melbourne Laboratories, AUSTRALIA
Date: Thu, 10 Sep 1992 03:55:45 GMT

I used to read HXWZ by saving the uuencoded file, transfer it to the PC
and invoke a Chinese Character editor. Now I have written a little
program in C, which saves the two last steps in reading HXWZ. In fact, it
can be used for all uuencoded gb files. No great stuff, but useful.

You need to run zW-DOS on your PC before you telnet/kermit/procomm/...
to your server. zW-DOS is available at ftp site ahkcus.org.

If you people like it, cut the following source text, and compile it with
your news server's native C-compiler. Program is absolutely free, and I will
assume absolutely no responsibility for the program.

If you have trouble, you can email me at jing@resmel.bhp.com.au
-----------------------------------------------------------------
/*
 * uudec [input] <-nNL -lNCOL>
 * example: uudecc file.1 -n20 -l80, reads uuencoded gb files, 20 lines
 *          and 80 (ASCII) columns per screen.
 *
 * decode a uuencoded file to the standard output for viewing gb files.
 * Use in combination with zwdos
 * This program allows you to read uuencoded gb files without downloading
 * it to the PC. It simply translates uuencoded gb text directly into HZ
 * codes, which zwdos supports.
 * Great for reading HuaXiaWenZia
 * 
 * How to use it?
 * Save this document into a file named uudec.c 
 * Invoke your UNIX' c compiler like this: cc uudec.c -o uudec
 * Copy it into your local program directory or in the directory where
 * you save your HuaXiaWenZia files.
 * Next time you see HuaXiaWenZia on the newsgroup, you save it into
 * your directory, and read it with: uudec filename.
 *
 * Saves you the effort of downloading. 
 * uudec also has page making capability (crude, but useful).
 *
 * This program is COMPLETELY FREE, for whatever purpose, and absolutely
 * no warranty is implied.
 */
#include <stdio.h>

/* ENC is the basic 1 character encoding function to make a char printing */
#define ENC(c) ((c) ? ((c) & 077) + ' ': '`')
/* DEC is the basic 1 character decoding macro */
#define DEC(c) ((c-'`') ? ( c - ' ' ) : 0 )

static int HZMODE=0, HZHIGH=0;

/* HZMODE true -> output in HZ mode
   HZHIGH true -> HZ high byte is the current HZ byte */

static int NROW=24, NCOL=80; 	/* default screen row and col numbers */

main(argc, argv)
char **argv;
int argc;
{
	FILE *in;
	int mode = 1, i, na=0;
	char buf[80];

/* scan for switches */
	for (i=1;i<argc;i++)
	  {
	    if (argv[i][0]=='-')
	      {
		 switch(argv[i][1])
		     {
			 case 'N':
			 case 'n':	/* define screen rows */
				   NROW = atoi(&argv[i][2]);
				   break;
			 case 'L':
			 case 'l':	/* define scree column */
				   NCOL = atoi(&argv[i][2]);
				   break;
		     }
	      }
	     else na=i;
	   }
	/* optional 1st argument */
	if (na > 0) {
		if ((in = fopen(argv[na], "r")) == NULL) {
			fprintf(stderr,"Can't open %s\n",argv[1]);
			exit(1);
		}
	} else
		in = stdin;

	while (mode) {
		if (fgets(buf,79,in)==NULL)
		   {
		      fprintf(stderr,"Not a uuencoded file\n");
		      exit(2);
		   }
		buf[5] = 0;
		mode = strcmp("begin",buf);
	}

	decode(in);

	exit(0);
}

/*
 * copy from in to out, encoding as you go along.
 */
decode(in)
register FILE *in;
{
	char buf[80];
	register int i, j, n, N; 

	for (;;) {
		/* 1 (up to) 61 character line */
		if  (fgets(buf, 79, in) ==NULL) 
		  {
		     fprintf(stderr,"Incomplete file!\n");
		     exit(1);
		  } 
		n = strlen(buf);
		buf[n-1] = 0;	/* change '\n' to a zero */
                if (! strcmp(buf,"end")) break;
		N = DEC(*buf);  /* recover number of chars in one line */

		for (i=1; i<n; i++)
			buf[i-1] = DEC(buf[i]); /* back to 6bit number */
                for (i=0,j=0; i<N; i+=3,j+=4)
			outdec(&buf[j],&buf[i]); /* reverse 4 -> 3 bytes */
		for (i=0; i<N; i++) 
		    {
		      if (buf[i] & 0200)  /* if 8th on first char- > gb */
			{			/* enter gb -> hZ mode */
			   if (! HZMODE)	/* if not yet, so set */
			      {
			   	pager(0x0d);
			   	HZMODE = 1;
				HZHIGH = 0;
                              }
			   HZHIGH = (HZHIGH + 1) & 01;
			   pager(buf[i] & 0177);
                        }
			else	/* enter non gb code ascii */
			 { 
			   if (HZMODE) 	/* back to ascii */
			     	{  
			   		pager(0x0d); 
					/* ox0d representing CC escape */
					HZMODE = 0;
					HZHIGH = 0;
			         }
		    	   if (buf[i] != 0x0d) 
				 {
				       pager(buf[i]);
				  }
			 }
		     } 	/* for i <N loop */

	}
}

/*
 * output one group of reassembled 3 bytes, pointed at by p, 
 * returned at q; 
 */
outdec(p, q)
register char *p,*q;
{

	*q = ((*p << 2) & 0374) | ((p[1] >> 4) & 03);
	q[1] = ((p[1] << 4) & 0360) | ((p[2] >> 2) & 017);
	q[2] = ((p[2] << 6) & 0300) | (p[3] & 077);

}

static int lcnum=0, llnum=0; 
/* printed char in a line and numb. of lines printed */

/* This function makes sure that the HZ start code ~{ and end code ~}
   are inserted when lines end/start on the screen. Also provides crude
   page making 
*/
pager(c)
char c;
{
char dummy[80];

switch(c)
  {
    case 0x0d:
	if (HZMODE)
	  {
	   putc('~',stdout);
	   putc('}',stdout);
	   lcnum += 2;
	   HZMODE = 0; 	/* make sure that hZ mode is exit in any case */
   	  }
	  else
	  {
	   if (lcnum >=NCOL-7 )	/* do not start Hz code if line longer 73 */
	     {
		putc('\n',stdout);
		llnum++;
		lcnum = 0;
	     }
	    if (llnum < NROW-1)
	     {
	       putc('~',stdout);   /* start new line for zwdos if line <23 */
	       putc('{',stdout);   /* otherwise let pager do job */
	       lcnum += 2;
	     }
	     else HZMODE = 1; /* make sure the new page line starts ok */
	  }
	break;
    case '\n':
	putc(c,stdout);
	llnum++;
	lcnum=0;
	break;
    default:
        putc(c,stdout);
	lcnum++;
  }

if ((HZMODE)&&(! HZHIGH))
  {
    if (lcnum >= NCOL-3 ) 
		/* break long lines into lines shorter than 78 bytes */
      {
	llnum++;
	lcnum = 0;
	putc('~',stdout);
	putc('}',stdout);	/* end line correctly for zwdos */
	putc('\n',stdout);	/* break line */
	if (llnum < NROW-1)
	  {
	    putc('~',stdout);	/* start new line for zwdos if line <23 */
	    putc('{',stdout);
	    lcnum = 2;
	  }
      }
  }
if (! HZMODE)
  {
    if (lcnum >= NCOL-1) 	/* break long lines into lines shorter than 79 bytes */
      {
	llnum++;
	lcnum = 0;
	putc('\n',stdout);	/* break line */	
      }
  }
if (llnum >= NROW-1 )
   {
	llnum = 0;
	lcnum = 2;
	printf("<RETURN> to continue; x to stop: ");
	gets(dummy);
	if ((dummy[0]|0x20)=='x') exit(0);

	if (HZMODE) /* start new page correctly for zwdos */
	 { 
	   putc('~',stdout);
	   putc('{',stdout);
	   return(0);
   	}
   }
return(0);
}
Newsgroups: alt.chinese.text