/*
 *  TEX Device Driver  ver 2.02-
 *  copyright(c) 1988, 1989 by TSG, 1990-93 by SHIMA
 *
 *  err.c :
 *         September 10, 1988 : first edition
 *             April 15, 1989 : second editon
 *                              programed by T.IWAI
 *	very slightly modified against warnings by Oh-Yeah? 25 May 1992
 *	modified for "-wait" option by sempa, 1 Sept 1992
 */

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define _DEF_STDIO_H_
#ifndef  UNIX
#include <conio.h>
#endif
#include <stdarg.h>
#define _DEF_STDARG_H_
#include "dd.h"
#include "inter.h"
#include "err.h"

#define	MSGBUFSIZE	0x1800	/* smaller than COMMON_SIZE */

/* device.c */
void device_pause(void);
void device_cont(void);

/* putdvi.c */
extern BOOL device_open_flag;

/* wmain.c */
int ShowMessage(char *, char *, int);

#if DEBUG & TRACE_LVL
static MODULE main_module =
{"main", NULL};
MODULE *last_module = &main_module;

void module_list_out(void)
{
	MODULE *tmp;

	fprintf(stderr, "(%s", last_module->name);
	for (tmp = last_module->prio; tmp; tmp = tmp->prio)
		fprintf(stderr, "<=%s", tmp->name);
	fprintf(stderr, ")\n\n");
}

#endif

#define HALT   0
#define RETRY  1
#define IGNORE 2
#define KEEP   3
#define FLUSH  4
#define LOGS   5
#define CHOOSE 6
#define	WAITOK 7
#define	CHOOSE2 8

void device_cont(void);
void device_pause(void);

static struct {
	char *msg;
	int recovery;
}

#ifdef	WIN32G
#define	WINRETRY	RETRY
#else
#define	WINRETRY	HALT
#endif

err [] = {
	{
		"No File", RETRY
	}
	,
	{
		"No Memory", HALT
	}
	,
	{
		"Memory Fault", HALT
	}
	,
	{
		"File Fault", HALT
	}
	,
	{
		"Illegal Args", WINRETRY
	}
	,
	{
		"Bad System", IGNORE
	}
	,
	{
		"No Font", WINRETRY
	}
	,
	{
		"Font Mismatch", HALT
	}
	,
	{
		"Command Error", HALT
	}
	,
	{
		"Unpack Error in Font", HALT
	}
	,
	{
		"Program Stop", HALT
	}
	,
	{
		"", KEEP
	}
	,
	{
		"", IGNORE
	}
	,
	{
		"Warning", IGNORE
	}
	,
	{
		"Warning", CHOOSE
	}
	,
	{
		"Warning", CHOOSE2
	}
	,
	{
		"Error", WAITOK
	}
	,
	{
		"", FLUSH
	}
	,
	{
		"Data", LOGS
	}
};

int f_wait = 1;
uint g_nErrorCode;

#ifdef	WIN32G
int	f_sm_edit = SM_EDIT;
int view_warning(int flag)
{
	if(flag!=0)
		f_sm_edit = (f_sm_edit == SM_EDIT)?SM_NOEDIT:SM_EDIT;
	return (f_sm_edit == SM_EDIT);
}
#else
#define	f_sm_edit SM_EDIT
#endif

void more(void)
{
#ifndef	WIN32G
	if (f_wait!=1)
		return;
	fprintf(stderr, "\n=== More ===");
	if (GetCh() == 0x1b) {
		/* ESC key is hit */
		fprintf(stderr, "\n<< BREAK >>\n");
		EXIT(0);
	}
	fprintf(stderr, "\r            \r");
	return;
#endif
}

#ifndef	WIN32G
static BOOL ask_retry(int mode)
{
	int code;

	if (!f_wait)
		return FALSE;
	fprintf(stderr, (mode == RETRY) ? "CONTINUE ? (y/n)" : "IGNORE ? (y/n)");
  repeat:						/* */
	if ((code = GetCh()) == 'y' || code == 'Y') {
		return (TRUE);
	}
	else if (code == 'n' || code == 'N')
		return (FALSE);
	goto repeat;
}
#endif

static int f_keep;
static int f_keep_type;
char msg_keep[MSGBUFSIZE];

#ifdef	WIN32G
char *GetMessagePtr(void)
{
	return msg_keep;
}

void ResetMessagePtr(void)
{
	f_keep = 0;
}
#endif

int error(ERROR_NUM error_num, char *message,...)
{
	va_list arg_ptr;
	int len;
	int  f_ret, type;
	static int multi;
	char s[MSGBUFSIZE], title[0x20], *t;

	f_ret = 0;
#ifdef WIN32G
	if(error_num == DIRECT && f_wait)
		return f_ret;
#endif
	if (error_num < NO_FILE || error_num > DATALOG)
		error_num = PROGRAM_STOP;
	if (err[error_num].recovery != HALT){
		if(f_wait>=3
#ifndef	WIN32G
		  || error_num == DATALOG
#endif
		)
			return f_ret;
		if(f_wait<2) goto devp;
	}else
devp:
#ifdef WIN32G
	if(error_num == C_MSG || error_num == DIRECT){
		va_start(arg_ptr, message);
		if(error_num == C_MSG && f_keep_type == DIRECT && f_keep > 0){
flush_msg:	strcpy(s, msg_keep);
			f_keep = 0;
			strcpy(title, "Message");
			if(multi)
				sprintf(title+7, ": %d ->... ", multi);
			ShowMessage(s, title, f_sm_edit);
		}
		vsprintf(s, message, arg_ptr);
		len = strlen(s);
		if( f_keep + len > MSGBUFSIZE-0x100 ){
			if( (f_keep + len > MSGBUFSIZE-0x100
				&& msg_keep[f_keep-1] == '\n' && f_keep > 0)
			  || f_keep + len >= MSGBUFSIZE-2){
				if (f_keep > 0){
					multi++;
					goto flush_msg;
				}
				multi = 0;
				return f_ret;
			}
		}
		strcpy(msg_keep + f_keep, s);
		f_keep += len;
		f_keep_type = error_num;
		if(f_keep && *(msg_keep - 1  + f_keep) == '\n' && error_num == DIRECT){
			strcpy(s, msg_keep);
			f_keep=0;
			return ShowMessage(s, "Message", f_sm_edit);
		}
		return f_ret;
	}
#endif
	if(device_open_flag)
		device_pause();
	va_start(arg_ptr, message);
	s[0] = 0;
#ifdef	WIN32G
	if(f_keep){
		f_keep = 0;
		strcpy(s, msg_keep);
	}
	switch(err[error_num].recovery){
		case CHOOSE: type = SM_ABREIG;
					break;
		case CHOOSE2: type = SM_YESNO;
					break;
		case HALT:	type = SM_OKEXIT;
					break;
		case FLUSH:	type = SM_EDIT;
					t = msg_keep;
					vsprintf(t, message, arg_ptr);
					goto sm;
		case LOGS:	type = SM_LOG;
					break;
		case WAITOK: type = SM_OKCONT;
					break;
		default	 :	type = f_sm_edit;
					break;
	}
	vsprintf(s + strlen(s), message, arg_ptr);
	t = err[error_num].msg;
sm:
	f_ret = ShowMessage(s, t, type);
	multi = 0;
#else
	if(error_num != DIRECT && error_num != C_MSG)
		sprintf(s, "\n%s: ", err[error_num].msg);
	len = strlen(s);
	vsprintf(s + len, message, arg_ptr);
	if(error_num != DIRECT && error_num != C_MSG)
		strcat(s, "\n");
	fprintf(stderr, "%s", s);
# if DEBUG & TRACE_LVL
	module_list_out();
# endif

	if (err[error_num].recovery != HALT){
		if (f_wait == 2 || error_num == DIRECT || error_num == C_MSG
			|| error_num == DATATITLE)
			goto ret;
		if (ask_retry(err[error_num].recovery)) {
			fprintf(stderr, "\n");
ret:		if (device_open_flag)
				device_cont();
			return f_ret;
		}
	}
	else more();
	if (errno == 0)
		errno = 1;

	EXIT(errno);
#endif
	return f_ret;
}

/* end of file : err.c */
