/*****************************************************************************
*           Change Log
*  Date     | Change
*-----------+-----------------------------------------------------------------
* 23-Nov-85 | [1.93] Created
* 24-Dec-85 | [1.231] check_diag now calls ce_panel
* 24-Dec-85 | [1.235] Display_on not static
* 24-Jan-86 | [1.325] Handle off-by-one on check_diag
* 27-Jan-86 | [1.350] message_length again signed, cast in malloc call
* 30-Jul-86 | [1.403] Added log_console_event
*  6-Aug-86 | [1.410] Make sure event is a char * to log_console event
* 18-Aug-86 | [1.414] screen.h -> bscreen.h
* 10-Nov-91 | [1.428] <jmn> converted to Microsoft C 6.0
* 24-Nov-91 | [1.472] <jmn> _oserr => errno
*****************************************************************************/
#include "stdio.h"
#include "stdlib.h"
#include "string.h"
#include "time.h"

#include "btypes.h"
#include "scdspmsg.h"

#include "hercules.h"
#include "graph.h"
#include "disp.h"
#include "boolean.h"
#include "color.h"
#include "1401.h"
#include "hercules.h"
#include "select.h"
#include "display.h"
#include "errno.h"

#include "panel.h"

#define message_cache_size 3
#define message_length 79

char diag_buffer[512];
extern char version[];
extern boolean color_printer;
extern boolean slow;
extern boolean mousing;
extern char * lpt;

static char * message_roll[message_cache_size];
static FILE * message_file;

boolean diagnostics_on = false;
boolean display_on = false;

static boolean file_initialized = false;
static char * debugfn = "ce.log";

void debuglog(char * S);
void tellmsg(char * S);

/****************************************************************************
*                                  diag_init
* Effect: 
*       Initializes the diagnostics message cache and other such things
****************************************************************************/

void diag_init()
    {
     int i;
#if 0
     for (i=0; i< message_cache_size; i++)
        { /* create empty messages */
	 
	 message_roll[i] = (char *) malloc((unsigned) (message_length+1));
	 *message_roll[i] = '\0';
	} /* create empty messages */
#endif

     message_file = NULL;
     diagnostics_on = display_on = false;
    }


/****************************************************************************
*                                  mark_diag
* Inputs:
*       int display_mode: Display mode to use
* Effect: 
*       Highlights the diagnostic mode according to the indicated mode
****************************************************************************/

void mark_diag(unsigned char display_mode)
    {
     scdspmsg(diag_key_Y+1,diag_key_X+1,display_mode,0,"D");
    }


/****************************************************************************
*                                scroll_window
* Effect: 
*       Scrolls the message window
****************************************************************************/

void scroll_window()
    {
#if 0
     if(!display_on) 
	return;
     scscroll(1,H_REVERSE,diag_Y,diag_X,
     				diag_Y+message_cache_size,
				diag_X+message_length,SCR_UP);
			/* scroll upwards */
#endif
    }

/*****************************************************************************
*				   nextline
*
* Inputs: None
*
* Effects:
*	Scroll the status area.  Simulate scrolling in message retention
*	area.
*****************************************************************************/

static void nextline()
  {
#if 0
   char * t;
   int i;

   if(display_on)
       {
	scroll_window();
       }
    t = message_roll[message_cache_size - 1];

    for(i=message_cache_size-1;i>0;i--)
   	{ 
	 message_roll[i+1] = message_roll[i];
	}

   message_roll[0] = t;
#endif
  }

/****************************************************************************
*                                store_message
* Inputs:
*       char * S: Message to store
*
* Effect: 
*       Stores the message (at least the first max_message_length characters)
*	in the message_roll[message_cache_size] buffer.  If the buffer 
*	pointer is NULL, allocate it.
****************************************************************************/

static void store_message(char * S)
    {
#if 0
     strncpy(message_roll[0],S,message_length+1);
     message_roll[message_length+1] = '\0';
#endif
    }

/*****************************************************************************
*				    tellmsg
* Inputs:
*	char * S: The message to display
*
* Effects:
*	Displays the message on the topmost debug scrolling window line
*	Stores the message in the message buffer[0]
*****************************************************************************/

static void tellmsg(char * S)
   {
#if 0
    store_message(S);
#endif

    debuglog(S);

#if 0
    if(display_on)
        scdspmsg(diag_Y+message_cache_size,diag_X, H_REVERSE, 0 , S);
#endif
   }

/*****************************************************************************
*				     tell
* Inputs:
*	char * S: Message to display on floating reporting line
*
* Side effects:
*	Window is scrolled down to make room for the message
*	Message is displayed
*****************************************************************************/

void tell(char * S)
   {
    nextline();
    tellmsg(S);
   }

/*****************************************************************************
*				   debuglog
* Inputs:
*	char * S: String to add to debug log
*
* Global State:
*	boolean file_initialized: false if file is initialized
*				  true if file is initialized
*
* Effects:
*	Opens the log file, for output if file_initialized false and
*	for append if file_initialized true.  Writes the string to the
*	file and closes the file (this is so the log is intact in case of
*	program abort via ^C
*
*****************************************************************************/

void debuglog(char * S)
    {
     char * mode;
     FILE * logfile;

     if(file_initialized)
	  mode = "aa";		/* if initialized, use append mode */
     else
     	  mode = "wa";		/* if not initialized, use write mode */
 
     logfile = fopen(debugfn,mode);

     if(logfile==NULL) 
        { /* no log */
	 int err;

	 err = errno;
	 printf("Failure to open log file, errcode = %d (%s), mode %s\n",
	 		err, strerror(err), mode);
	 return;
	} /* no log */

     if(!file_initialized)
        {
	 char date[80];
	 time_t timeval;

	 time(&timeval);

	 fprintf(logfile,"CE Diagnostic file\n");
	 fprintf(logfile,"    Simulator version %s\n",version);
#if 0
	 if(ismono())
	    fprintf(logfile,"    Monochrome display\n");
	 else
	    fprintf(logfile,"    Color display\n");

	 if(color_printer)
	    fprintf(logfile,"    -color\n");

	 if(slow)
	    fprintf(logfile,"    -slow\n");

	 if(!mousing)
	    fprintf(logfile,"    -nomouse\n");

	 fprintf(logfile,"    -printer %s\n",lpt);

	 strftime(date,sizeof(date),"Recorded on %A, %d-%b-%y at %X",
	 		localtime(&timeval));
	 fprintf(logfile," %s\n",date);
#endif
	}

     fprintf(logfile,"%s\n",S);
     fclose(logfile);
     file_initialized = true;
     return;

    }



/****************************************************************************
*                               redraw_messages
* Effect: 
*       Redraws any saved messages
****************************************************************************/

void redraw_messages()
    {
     int i;

#if 0
     if(!display_on) 
	return;

     for(i=0;i<message_cache_size;i++)
        { /* write message */
	 scroll_window();
	 scdspmsg(diag_Y, diag_X, H_REVERSE, 0, message_roll[i] );
	} /* write message */
#endif
    }

/****************************************************************************
*                             draw_diagnostic_key
* Effect: 
*       Draws diagnostic key on console
****************************************************************************/

void draw_diagnostic_key()
    {
     attrib fore;
     attrib back;
     attrib on1;		/* "D" when partial diagnostics on */
     attrib on2;		/* "D" when full diagnostics on */
     attrib off;		/* "D" when all diagnostics are off */

     if(ismono())
        { /* mono */
	 fore = H_NORMAL;
	 on1 = H_INTENSIFIED;
	 on2 = H_REVERSE;
	 off = H_NORMAL;
	 back = 0;
	} /* mono */
     else
        { /* color */
	 fore = RED;
	 on1 = LTRED;
	 on2 = RED;
	 off = WHITE;
	 back = BLACK;
	} /* color */

     scdspmsg(diag_key_Y,diag_key_X,fore,back,  "ÉÍ»");
     scdspmsg(diag_key_Y+1,diag_key_X,fore,back,"º º");
     scdspmsg(diag_key_Y+2,diag_key_X,fore,back,"ÈÍ¼");

     if(diagnostics_on)
        { /* yes */
	 if(display_on)
	    mark_diag(on1);
	 else
	    mark_diag(on2);
	} /* yes */
     else
        { /* no */
	 mark_diag(off);
	} /* no */
	 
    }

/****************************************************************************
*                                 check_diag
* Inputs:
*       coord X: screen coordinate of mouse hit
*	coord Y: screen coordinate of mouse hit
* Effect:
*	Enters the CE panel	
*
****************************************************************************/

void check_diag(coord X,coord Y)
    {
     if(bounded(X,Y,
     		diag_key_X,diag_key_Y,
		(coord)(diag_key_X+diag_key_width-1),
		(coord)(diag_key_Y+diag_key_height-1)))
        { /* hit diagnostic key */
	 ce_panel();
	} /* hit diagnostic key */
    }

/****************************************************************************
*                                log_console_event
* Inputs:
*       char * event: Console Event to record
* Result: void
*       
* Effect: 
*       If diagnostics are on, logs a console event
****************************************************************************/

void log_console_event(char * event)
    {
     
     if(!diagnostics_on) 
	return;
     sprintf(diag_buffer,">>> %s <<<",event);
     tell(diag_buffer);
    }
