/*
 * |-----------------------------------------------------------|
 * | 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: wsntostr.c,v 1.2.2.1 92/06/24 14:11:14 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/wsntostr.c	1.0"

/*
 * Wsntostr transforms process codes in wchar_t string "s2"
 * into EUC, and transfers those to character string "s1", until
 * "n" characters or the wchar_t type NULL character have 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 *
_wsntostr(s1, s2, n, p)
register char *s1;
wchar_t *s2;
register int n;
wchar_t **p;
{
/*	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 (n > 0) { /* at most n characters */
		if (! (*s2)) { /* end if NULL wchar_t */
			*s1 = '\0';
			break;
		}
		/*
		 * "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++;
				n--;
				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++;
					n--;
					continue;
				}
				ssch = SS2;
				size = _cswidth[2] + 1;
				break;
			case P10: /* Code Set 3 */
				ssch = SS3;
				size = _cswidth[3] + 1;
				break;
			default:
				ssch = size = 0;
				break;
		}
/*	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++;
				n--;
				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++;
					n--;
					continue;
				}
				ssch = SS2;
				size = _cswidth[2] + 1;
				break;
			case F_P10: /* Code Set 3 */
				ssch = SS3;
				size = _cswidth[3] + 1;
				break;
			default:
				ssch = size = 0;
				break;
		}
/*	end for MNLS 3.2	*/
		if ((n -= size) >= 0) {
			if (ssch)
				size--;
			/*
			 * Error checking for Process Code
			 * in supplementary code set
			 */
			if (size == 0) { /* EUC size is zero */
				if (p != 0)
					*p = s2;
				*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	*/
					if (p != 0)
						*p = s2;
					*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++;
		}
		else {
			*s1 = '\0';
			break;
		}
	}
	if (p != 0)
		*p = s2; /* next address of wchar_t string */
	return(os1);
}
