/* $Copyright:	$
 * Copyright (c) 1984, 1985, 1986, 1987, 1988, 1989, 1990 
 * Sequent Computer Systems, Inc.   All rights reserved.
 *  
 * This software is furnished under a license and may be used
 * only in accordance with the terms of that license and with the
 * inclusion of the above copyright notice.   This software may not
 * be provided or otherwise made available to, or used by, any
 * other person.  No title to or ownership of the software is
 * hereby transferred.
*/

/*	Copyright (c) 1986 AT&T	*/
/*	  All Rights Reserved  	*/

/*	THIS IS UNPUBLISHED PROPRIETARY SOURCE CODE OF AT&T	*/
/*	The copyright notice above does not evidence any   	*/
/*	actual or intended publication of such source code.	*/


#ident	"$Header: fgetwc.c 1.3 90/04/21 $@(#)libw-port:wstdio/fgetwc.c	1.0"

/*
 * Fgetwc transforms the next character in EUC from the named input
 * "iop" into the Process Code, and returns it as an integer.
 * The character widths in EUC are determined from an environment
 * variable CSWIDTH.
 */

#include "../../inc/shlib.h"
#include <stdio.h>
#include <errno.h>
#include <euc.h>
#include <widec.h>
#include "libw_pcode.h"

extern int  _filbuf();
extern void _xgetwidth();
extern int  _cswidth[];
extern int  _pcmask[];
extern eucwidth_t _eucwidth;
#define pcw	_eucwidth._pcw

wchar_t
fgetwc(iop)
FILE *iop;
{
	register wchar_t byte, temp = 0, mask;
	register int size, cset;

	if ( (byte = getc(iop)) == EOF )
		return(EOF);

	if ( !(byte & 0x80) )	/* ASCII code */
		return(byte);

	if (! *_cswidth)
		_xgetwidth(); /* get char width from CSWIDTH */
	/*
	 * "Size" tells us how many bytes to expect following.
	 * Value returned by "_xgetwidth" for Set 1 is the number of
	 * bytes; subtract 1 to get number of bytes to expect.
	 */
	switch (byte) {
		case SS2: /* set 2 */
			if(pcw > sizeof(unsigned short))
				mask = F_P01;
			else
				mask = P01;
			cset = 2;
			size = _cswidth[2];
			goto testsize;
		case SS3: /* set 3 */
			if(pcw > sizeof(unsigned short))
				mask = F_P10;
			else
				mask = P10;
			cset = 3;
			size = _cswidth[3];
		testsize: /* EUC size is zero */
			if (size == 0)
				return(byte);
			break;
		default:  /* set 1 */
			if (control1(byte)) /* control character 1 */
				return(byte);

			if(pcw > sizeof(unsigned short))
				mask = F_P11;
			else
				mask = P11;

			cset = 1;
			if ((size = _cswidth[1] - 1) >= 0)
				temp = byte;
			else { /* EUC size is zero */
				ungetc(byte, iop);
				errno = EILSEQ;
				return(EOF);
			}
	}
	/*
	 * This loop shifts previous bytes left, sticking the
	 * new byte into the low order byte of temp. If unexpected
	 * EOF or byte detects in this loop, return EOF
	 * for the whole thing.
	 */
	while (size--) {
		if ((byte = getc(iop)) == EOF || !graphic(byte)) {
			ungetc(byte, iop);
			errno = EILSEQ;
			return(EOF);
		}
		if( pcw > sizeof(unsigned short) )
{
			temp = ((temp << 7) | (byte & 0177));
}
		else
			temp = ((temp << 8) | (byte & 0177));
	}
	/*
	 * Mask the value so that it fits into the proper character
	 * set pattern for the high order bits of each byte:
	 *     CS0-0000   CS1=0011   CS2=0001   CS3=0010
	 */
	return(temp | mask);
}
