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

/*
 * Wstostr transforms process codes in wchar_t string "s2"
 * into EUC, and transfers those to character string "s1",
 * stopping after the wchar_t type NULL character has been
 * processed.
 */

#include "shlib.h"
#include <widec.h>
#include <errno.h>
#include <euc.h>
#include "libw_pcode.h"
#define NULL	0

extern int  _cswidth[];
extern void _xgetwidth();
extern eucwidth_t _eucwidth;
#define pcw _eucwidth._pcw	/* use for checking wchar_t is 2 or 4 bytes	*/

char *
wstostr(s1, s2)
register char *s1;
register wchar_t *s2;
{
	register size, ssch, i, u;
	char *os1 = s1;

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

	u = (pcw == sizeof(unsigned short)) ? 8 : 7;

	while (*s2) { /* end if wchar_t NULL character */
		/*
		 * "Switch" on a pattern of "00", "11", "01",
		 * or "10", depending on high bits of low two
		 * bytes of Proces Code.
		 */
		if (pcw == sizeof(unsigned short))
		switch (*s2 & EUCMASK) {
			case P00: /* Code Set 0 */
				*s1++ = *s2++;
				continue;
			case P11: /* Cose Set 1 */
				ssch = 0;
				size = _cswidth[1];
				break;
			case P01: /* Code Set 2 */
				if (control1(*s2)) { /* control character 1 */
					*s1++ = *s2++;
					continue;
				}
				ssch = SS2;
				size = _cswidth[2];
				break;
			case P10: /* Code Set 3 */
				ssch = SS3;
				size = _cswidth[3];
		}
		else
		switch (*s2 & F_EUCMASK) {
			case F_P00: /* Code Set 0 */
				*s1++ = *s2++;
				continue;
			case F_P11: /* Cose Set 1 */
				ssch = 0;
				size = _cswidth[1];
				break;
			case F_P01: /* Code Set 2 */
				if (control1(*s2)) { /* control character 1 */
					*s1++ = *s2++;
					continue;
				}
				ssch = SS2;
				size = _cswidth[2];
				break;
			case F_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 */
			*s1 = '\0';
			errno = EILSEQ;
			return(NULL);
		}
		i = size;
		while (i--) { /* Check each bytes */
			if ( controlc(*s2 >> (i * u)) ) {
				*s1 = '\0';
				errno = EILSEQ;
				return(NULL);
			}
		}
		/*
		 * Output Single Shift character if necessary
		 */
		if (ssch)
			*s1++ = ssch;

		/*
		 * Output bytes from highest order to 
		 * lowest order, masking the high order
		 * bits of the process code to ON.
		 */
		while (size--) {
			*s1++ = *s2 >> (size * u) | 0x80;
		}
		s2++;
	}
	*s1 = '\0';
	return(os1);
}
