/* $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: fputwc.c 1.3 90/04/21 $@(#)libw-port:wstdio/fputwc.c	1.0"

/*
 * Fputwc transforms the process code c into the EUC,
 * and writes it onto the output stream "iop".
 */
#include "shlib.h"
#include <stdio.h>
#include <errno.h>
#include <euc.h>
#include <widec.h>
#include "libw_pcode.h"
#define putbyte(x,p)	{ if (putc((x),(p)) == EOF) return(EOF); }

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

wchar_t
fputwc(c, iop)
register wchar_t c;
register FILE *iop;
{
	register size, i, ssch;

	if (! *_cswidth)
		_xgetwidth(); /* get character width */

	/*
	 * "Switch" on a pattern of "00", "11", "01", or "10",
	 * depending on high bits of low two bytes of Process Code.
	 */
	if(pcw > sizeof(unsigned short)) {
	switch (c & F_EUCMASK) {
		case F_P00: /* Code Set 0 */
			putbyte(c, iop);
			return(c);
		case F_P11: /* Code Set 1 */
			ssch = 0;
			size = _cswidth[1];
			break;
		case F_P01: /* Code Set 2 */
			if (control1(c)) { /* control character 1 */
				putbyte(c, iop);
				return(c);
			}
			ssch = SS2;
			size = _cswidth[2];
			break;
		case F_P10: /* Code Set 3 */
			ssch = SS3;
			size = _cswidth[3];
	}
	} else {
	switch (c & EUCMASK) {
		case P00: /* Code Set 0 */
			putbyte(c, iop);
			return(c);
		case P11: /* Code Set 1 */
			ssch = 0;
			size = _cswidth[1];
			break;
		case P01: /* Code Set 2 */
			if (control1(c)) { /* control character 1 */
				putbyte(c, iop);
				return(c);
			}
			ssch = SS2;
			size = _cswidth[2];
			break;
		case P10: /* Code Set 3 */
			ssch = SS3;
			size = _cswidth[3];
	}
	}
	/*
	 * Error checking for Process Code in supplementary code set.
	 */
	if (size == 0 ) { /* EUC size is zero */
		errno = EILSEQ;
		return(EOF);
	}
	i = size;
	while (i--) { /* Check each byte */
		if(pcw > sizeof(unsigned short)) {
			if ( controlc(c >> (i * 7)) ) { /* Error if 8 bits pattern is */
				errno = EILSEQ;         /* a control character */
				return(EOF);
			}
		} else {
			if ( controlc(c >> (i * 8)) ) { /* Error if 8 bits pattern is */
				errno = EILSEQ;         /* a control character */
				return(EOF);
			}
		}
	}
	/*
	 * Output Single Shift Code For Set 2 or 3
	 */
	if (ssch) {
		putbyte(ssch, iop);
	}
	/*
	 * Output bytes from highest order to lowest order, masking
	 * the high order bits of the process code to ON. The return
	 * expression shifts the char right by the correct number of
	 * bits, ANDs it with FF to make sure we only get the lowest
	 * byte. If unexpected EOF occurs in this loop, return EOF
	 * for the whole thing.
	 */
	while (size--) {
		if(pcw > sizeof(unsigned short)) {
			putbyte((c >> (size * 7) & 0xFF | 0x80), iop);
		} else {
			putbyte((c >> (size * 8) & 0xFF | 0x80), iop);
		}
	}
	return(c);
}
