/****************************************************************
 *								*
 *	Copyright 2001, 2011 Fidelity Information Services, Inc	*
 *								*
 *	This source code contains the intellectual property	*
 *	of its copyright holder(s), and is made available	*
 *	under a license.  If you do not know the terms of	*
 *	the license, please stop and do not read further.	*
 *								*
 ****************************************************************/

#include "mdef.h"
#include "gtm_string.h"
#include "compiler.h"
#include "show_source_line.h"
#include "gtmmsg.h"
#ifdef UNICODE_SUPPORTED
#include "gtm_utf8.h"
#endif

GBLREF short int 	source_name_len, source_line;
GBLREF char 		source_file_name[];
GBLREF unsigned char	*source_buffer;
GBLREF bool		dec_nofac;
GBLREF boolean_t	run_time;

error_def(ERR_SRCLIN);
error_def(ERR_SRCLOC);
error_def(ERR_SRCLNNTDSP);
error_def(ERR_ARROWNTDSP);

#define MAXLINESIZEFORDISPLAY 1023

void show_source_line(char* buf, ssize_t buflen, boolean_t warn)
{
	char 	*b, *b_top, *c, *c_top;
	int	chlen, chwidth;
	unsigned int ch, line_chwidth = 0;
	boolean_t unable_to_complete_arrow = FALSE;
	mstr	msgstr;
	DCL_THREADGBL_ACCESS;

	SETUP_THREADGBL_ACCESS;
	b_top = buf + buflen - STR_LIT_LEN(ARROW) - 1; /* allow room for arrow and string terminator */
	for (c = (char *)source_buffer, b = buf, c_top = c + TREF(last_source_column) - 1; c < c_top;)
	{
		if ('\t' == *c)
		{
			if ((b + 1) > b_top)
			{
				unable_to_complete_arrow = TRUE;
				break;
			}
			*b++ = *c++;
		}
		else if (!gtm_utf8_mode || (ASCII_MAX >= *(uchar_ptr_t)c))
		{
			if ((b + 1) > b_top)
			{
				unable_to_complete_arrow = TRUE;
				break;
			}
			*b++ = ' ';
			c++;
		}
#		ifdef UNICODE_SUPPORTED
		else
		{
			chlen = (int)(UTF8_MBTOWC(c, c_top, ch) - (uchar_ptr_t)c);
			if (WEOF != ch && (0 < (chwidth = UTF8_WCWIDTH(ch))))	/* assignment */
			{
				if ((b + chwidth) > b_top)
				{
					unable_to_complete_arrow = TRUE;
					break;
				}
				memset(b, ' ', chwidth);
				b += chwidth;
			}
			c += chlen;
		}
#		endif
	}
	if (unable_to_complete_arrow)
	{
		msgstr.addr = buf;
		msgstr.len = buflen;
		dec_nofac = TRUE;
		gtm_getmsg(ERR_ARROWNTDSP, &msgstr);
		dec_nofac = FALSE;
	} else
	{
		memcpy(b, ARROW, STR_LIT_LEN(ARROW));
		b += STR_LIT_LEN(ARROW);
		*b = '\0';
	}
	if (warn)
	{
		for (c = (char *)source_buffer; c < (char *)source_buffer + STRLEN((char *)source_buffer) - 1; )
		{
			if ('\t' == *c)
			{
				line_chwidth++;
				c++;
			}
			else if (!gtm_utf8_mode || (ASCII_MAX >= *(uchar_ptr_t)c))
			{
				line_chwidth++;
				c++;
			} else
			{
#			ifdef UNICODE_SUPPORTED		/* funky positioning makes VMS compiler happy */
				chlen = (int)(UTF8_MBTOWC(c, (char *)source_buffer + STRLEN((char *)source_buffer) - 1, ch)
						- (uchar_ptr_t)c);
				if ((WEOF != ch) && 0 < (chwidth = UTF8_WCWIDTH(ch)))
					line_chwidth += chwidth;
				c += chlen;
#			endif
			}
		}
		dec_nofac = TRUE;
		if (MAXLINESIZEFORDISPLAY > line_chwidth)
			if (unable_to_complete_arrow)
				dec_err(VARLSTCNT(6) ERR_SRCLIN, 4, LEN_AND_STR((char *)source_buffer), msgstr.len, msgstr.addr);
			else
				dec_err(VARLSTCNT(6) ERR_SRCLIN, 4, LEN_AND_STR((char *)source_buffer), b - buf, buf);
		else
			dec_err(VARLSTCNT(2) ERR_SRCLNNTDSP, 1, MAXLINESIZEFORDISPLAY);
		if (!run_time)
			dec_err(VARLSTCNT(6) ERR_SRCLOC, 4, TREF(last_source_column), source_line,
				source_name_len, source_file_name);
		dec_nofac = FALSE;
	}
}
