/*****************************************************************************
*           Change Log
*  Date     | Change
*-----------+-----------------------------------------------------------------
* 15-Nov-85 | [1.37] Created
* 15-Dec-85 | [1.199] Implemented set_logic
* 15-Dec-85 | [1.201] Changed system so set_compare sets only the state, not
*           | the indicators (reduces overhead); show_compare now shows the
*           | state.  'compare_state' is part of the global machine state
* 20-Dec-85 | [1.221] set_logic_output => show_logic_output
* 20-Dec-85 | [1.221] Added show_ovf with parm, removed old set_OVF, clear_OVF
* 26-Dec-85 | [1.237] Added logic_state to show display string of logic
* 30-Dec-85 | [1.274] Arranged displays to conform to 1401 order for B=A,
*           | B!=A, B>A, B<A
* 22-Feb-86 | [1.364] Support color.  Use scdspmsg, mark_screen_color
* 25-Feb-86 | [1.374] Use color.h for choosing display colors
* 25-Feb-86 | [1.376] make sure comparison lights come up "off" in digit
*           | colors
* 25-Feb-86 | [1.381] Init last_logic to B=A
* 29-Jul-86 | [1.396] Support lamp test
* 31-Jul-86 | [1.405] Made char variables unsigned
* 19-Aug-86 | [1.422] Call new setcolor routine to get colors for display
* 19-Aug-86 | [1.423] Displayed text is written back-back color
*  7-Dec-91 | [1.481] <jmn> added chars.h, use char_ne to get accurate
*           | representation of not-equal symbol
*****************************************************************************/

/*****************************************************************************
				 1401 Emulator

			       Logic Box Display

This module maintains and updates the 'logic' display on the screen

*****************************************************************************/

/* #include "graph.h" */
#include "stdio.h"
#include "boolean.h"

#include "btypes.h"
#include "scdspmsg.h"

#include "panel.h"
#include "mach.h"
#include "hercules.h"
#include "disp.h"
#include "display.h"

#include "logic.h"
#include "color.h"
#include "kb.h"
#include "scan.h"
#include "chars.h"

#define NLOGIC 5

logic_signal logics[NLOGIC] = {
    {0,0,"  OVF  ",false,logic_OVF},
    {0,0,"  B=A  ",false,logic_BEQA},
    {0,0,"  BØA  ",false,logic_BNEA},   /* logics[2].id[3] is ne symbol */
    {0,0,"  B>A  ",false,logic_BGTA},
    {0,0,"  B<A  ",false,logic_BLTA}
			      };

#define neq logics[2].id[3]

unsigned char last_logic = '\0';

extern void set_logic(short code,boolean state);
extern void show_compare(void);

/****************************************************************************
*                              draw_logic_box
* Effect: 
*       Displays the 'Logic' status box on the screen
****************************************************************************/

void draw_logic_box()
    {
     short i;
     coord row;
     attrib fore;
     attrib back;
     attrib d_fore;
     attrib d_back;

     display_setcolor(false,&d_fore,&d_back,digit_on,
	COLOR_BLACK,digit_off,COLOR_BLACK);

     if(ismono())
        { /* mono */
	 fore = H_NORMAL;
	 back = 0;
	} /* mono */
     else
        { /* color */
	 fore = COLOR_WHITE;
	 back = COLOR_BLACK;
	} /* color */

     neq = char_ne;

     scdspmsg(logic_Y,logic_X,fore,back,"ÚÄLogicÄÂÄ¿");
     row = logic_Y;

     for(i=0;i<NLOGIC;i++)
        { /* print logic */
	 char msg[20];
	 row++;
	 logics[i].Y = row;
	 logics[i].X = logic_X+1;
	 scdspmsg(row,logic_X,fore,back,"³       ³ ³");
	 sprintf(msg,"%s",logics[i].id);
	 scdspmsg(row,logic_X+1,d_back,d_back,msg);
	} /* print logic */

     row++;
     scdspmsg(row,logic_X,fore,back,"³       ³ ³");
     row++;
     scdspmsg(row,logic_X,fore,back,"ÀÄÄÄÄÄÄÄÁÄÙ");

     for(i=0;i<6;i++)
        { /* print output */
	 char msg[5];
	 sprintf(msg,"%c","BA8421"[i]);
	 scdspmsg((coord)(logic_Y+1+i),(coord)(logic_X+9),d_back,d_back,msg);
	} /* print output */


     /* clear the state of the indicators */

     set_logic(logic_BNEA,false);
     set_logic(logic_BGTA,false);
     set_logic(logic_BLTA,false);
     set_logic(logic_BEQA,false);
     set_logic(logic_OVF,false);

     /* now set the indicators to their proper value */

     show_compare();
     show_ovf(overflow);

     show_logic_output(L);
	 
    }

/****************************************************************************
*                                  set_logic
* Inputs:
*       short code: Code for flag to set or clear
*	boolean state: true to set flag, false to clear it
* Effect: 
*       Updates the logic flag, redisplays it when appropriate
****************************************************************************/

static void set_logic(short code,boolean state)
    {
     short i;

     for(i=0;i<NLOGIC;i++)
        { /* find flag */
	 if(logics[i].code != code) continue;

	 /* codes are same, we found the lamp to update */

	 if(logics[i].active == state && !lamp_test) break;	/* found it, same state */
	 logics[i].active = state;

	 hide_mouse_cursor();
	 mark_screen_color(logics[i].X,logics[i].Y,logics[i].id,
	 		(boolean)(logics[i].active || lamp_test),
					digit_on,COLOR_BLACK,
					digit_off,COLOR_BLACK);
	 show_mouse_cursor();
	 break;
	} /* find flag */
	 
    }

/****************************************************************************
*                                 set_compare
* Inputs:
*	short state: State code to set, must be one of
*		logic_BEQA
*		logic_BLTA
*		logic_BGTA
* Effect: 
*       Sets the compare status for later display
****************************************************************************/

void set_compare(short state)
    {
     compare_state = state;
    }

/****************************************************************************
*                                 show_compare
* Effect: 
*       Sets the compare status lights according to the compare_state
****************************************************************************/

void show_compare()
    {
     switch(compare_state)
         {
	  case logic_BEQA:
	  	set_logic(logic_BNEA,false);
		set_logic(logic_BGTA,false);
		set_logic(logic_BLTA,false);
		set_logic(logic_BEQA,true);
		break;
	  case logic_BGTA:
	  	set_logic(logic_BEQA,false);
		set_logic(logic_BLTA,false);
		set_logic(logic_BNEA,true);
		set_logic(logic_BGTA,true);
		break;
	  case logic_BLTA:
	  	set_logic(logic_BEQA,false);
		set_logic(logic_BGTA,false);
		set_logic(logic_BNEA,true);
		set_logic(logic_BLTA,true);
		break;
	 }
    }

/****************************************************************************
*                              mark_logic_output
* Inputs:
*       unsigned char ch: Logic output to mark (BA8421 bits only)
*	boolean set: true to highlight, false to unhighlight
* Effect: 
*       Marks the characters on the screen for the logic output
****************************************************************************/

static void mark_logic_output(unsigned char ch,boolean set)
    {
     coord i;
     for(i=0;i<6;i++)
        { /* show it */	 
         if(ch & 1 || lamp_test)
	 	markscreen((coord)(logic_Y+6-i),(coord)(logic_X+9),
				(boolean)(set || lamp_test),
				digit_on,COLOR_BLACK,
				digit_off,COLOR_BLACK);
         ch >>= 1;
	} /* show it */	 
    }

/****************************************************************************
*                              show_logic_output
* Inputs:
*       unsigned char ch: Character which represents logic output.  Only 
*		 BA8421 is looked at
* Effect: 
*       Updates the logic output display
****************************************************************************/

void show_logic_output(unsigned char ch)
    {
     mark_logic_output(last_logic,false);
     mark_logic_output(ch,true);
     last_logic = ch;
    }

/****************************************************************************
*                                  show_ovf
* Inputs:
*       boolean overflow: State of overflow flag
* Effect: 
*       Shows the overflow flag state in the logic display
****************************************************************************/

void show_ovf(boolean overflow)
    {
     set_logic(logic_OVF,overflow);
    }

/****************************************************************************
*                                 logic_state
* Inputs:
*       short ls: logic state
* Result: char *
*       Printable text of logic state
****************************************************************************/

char * logic_state(short ls)
    {
     switch(ls)
        { /* decode */
	 case logic_BLTA: return "B<A";
	 case logic_BGTA: return "B>A";
	 case logic_BEQA: return "B=A";
	} /* decode */
     return "B?A";
    }
