/*
 * |-----------------------------------------------------------|
 * | Copyright (c) 1990 MIPS Computer Systems, Inc.            |
 * | All Rights Reserved                                       |
 * |-----------------------------------------------------------|
 * |          Restricted Rights Legend                         |
 * | Use, duplication, or disclosure by the Government is      |
 * | subject to restrictions as set forth in                   |
 * | subparagraph (c)(1)(ii) of the Rights in Technical        |
 * | Data and Computer Software Clause of DFARS 52.227-7013.   |
 * |         MIPS Computer Systems, Inc.                       |
 * |         928 Arques Avenue                                 |
 * |         Sunnyvale, CA 94086                               |
 * |-----------------------------------------------------------|
 */
#ident	"$Header: wstostr.c,v 1.1.2.1 92/06/24 14:11:18 marker Exp $"

/*	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.	*/

/*	This module is created for NLS on Sep.03.86		*/

/*	This module is modified for MNLS 3.2 on Jan 18 1989	*/

#ident	"@(#)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>
/*	start for MNLS 3.2 by UNIX Pacific on Jan 18 1989	*/
#include <euc.h>
/*	end for MNLS 3.2	*/
#include "pcode.h"
#define NULL	0

extern int  _cswidth[];
extern void _xgetwidth();
/*	start for MNLS 3.2 by UNIX Pacific on Jan 18 1989	*/
extern eucwidth_t _eucwidth;
#define pcw _eucwidth._pcw	/* use for checking wchar_t is 2 or 4 bytes	*/
/*	end for MNLS 3.2	*/

char *
wstostr(s1, s2)
register char *s1;
register wchar_t *s2;
{
/*	start for MNLS 3.2 by UNIX Pacific on Jan 18 1989	*/
/*	register size, ssch, i;	*/
	register size, ssch, i, u;
/*	end for MNLS 3.2	*/
	char *os1 = s1;

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

/*	start for MNLS 3.2 by UNIX Pacific on Jan 18 1989	*/
	u = (pcw == sizeof(unsigned short)) ? 8 : 7;
/*	end for MNLS 3.2	*/

	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.
		 */
/*	start for MNLS 3.2 by UNIX Pacific on Jan 18 1989	*/
		if (pcw == sizeof(unsigned short))
/*	end for MNLS 3.2	*/
		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];
		}
/*	start for MNLS 3.2 by UNIX Pacific on Jan 18 1989	*/
		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];
		}
/*	end for MNLS 3.2	*/
		/*
		 * 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 */
/*	start for MNLS 3.2 by UNIX Pacific on Jan 18 1989	*/
/*			if ( controlc(*s2 >> (i * 8)) ) {	*/
			if ( controlc(*s2 >> (i * u)) ) {
/*	end for MNLS 3.2	*/
				*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--) {
/*	start for MNLS 3.2 by UNIX Pacific on Jan 18 1989	*/
/*			*s1++ = *s2 >> (size * 8) | 0x80;	*/
			*s1++ = *s2 >> (size * u) | 0x80;
/*	end for MNLS 3.2	*/
		}
		s2++;
	}
	*s1 = '\0';
	return(os1);
}
