/*****************************************************************************
*           Change Log
*  Date     | Change
*-----------+-----------------------------------------------------------------
* 15-Nov-85 | [1.40] Created
* 25-Nov-85 | [1.125] Default extension to .cdr
* 25-Nov-85 | [1.135] Set eof only for last card of last deck
*  7-Dec-85 | [1.152] Change sense of '.' test to be correct
* 13-Dec-85 | [1.183] Cloned from cdr.c
* 31-Dec-85 | [1.288] If no punch name, do not try to open file
*  8-Feb-86 | [1.357] Turn on name button while active.
*           | <> => "" in includes
*           | support color
*  8-Feb-86 | [1.358] Added hide, show operations around drawing card
*           | image (mainly to suppress non-mouse cursor)
* 22-Feb-86 | [1.361] Delete punch card when clear button hit
* 23-Feb-86 | [1.366] replace printf with scdspmsg for color support
* 18-Aug-86 | [1.414] screen.h -> bscreen.h
* 10-Nov-91 | [1.428] <jmn> converted to Microsoft C 6.0
* 18-Nov-91 | [1.428] <jmn> memory.h => mem1401.h, avoid ANSI name
* 24-Nov-91 | [1.472] <jmn> _oserr => errno
* 23-Dec-91 | [1.539] <jmn> use char_corner characters
*****************************************************************************/

/*****************************************************************************
				 1401 Emulator

			      Virtual Card Punch
*****************************************************************************/

#include "stdio.h"
#include "boolean.h"
#include "string.h"
#include "errno.h"

#include "btypes.h"
#include "scdspmsg.h"

#include "mach.h"
#include "mem1401.h"
#include "periph.h"
#include "button.h"
#include "hercules.h"
/* #include "graph.h" */
#include "disp.h"
#include "bcd.h"
#include "color.h"
#include "display.h"
#include "kb.h"
#include "scan.h"
#include "diag.h"
#include "cdr.h"
#include "chars.h"

extern void cdp_clear();
extern void cdp_name();
extern char * malloc();

button 
cdp_clear_button = { cdp_clear_X, cdp_clear_Y, "Clear", false, cdp_clear,
	COLOR_YELLOW, COLOR_YELLOW, COLOR_YELLOW};
button 
cdp_name_button =  { cdp_name_X,  cdp_name_Y,  "Name ", false, cdp_name,
	COLOR_GREEN, COLOR_GREEN, COLOR_GREEN};
/* nice big scratch buffer */
	
#define CDP_LENGTH 81

static char punch_status_area[81];
static int card_count;
static boolean cdp_open = false;
static FILE * cdp = NULL;
static boolean status_error = false;
static char punchname[80] ="";

extern void cdp_clear(void);
extern void cdp_name(void);
extern void draw_punch_card(boolean erase);
void punch_status(char * msg,boolean error);

/****************************************************************************
*                                 show_cdp_status
* Effect: 
*       Draws the card punch status on the card
****************************************************************************/

void show_cdp_status()
    {
     char msg[cardwidth];
     char fmt[20];
     unsigned char fore;
     unsigned char back;


     if(ismono())
        { /* mono */
	 fore = (status_error ? H_BLINK : H_NORMAL);
	 back = 0;
	} /* mono */
     else
        { /* color */
	 fore = COLOR_BLACK;
	 back = COLOR_LTRED;	/* blinking red background */
	} /* color */


     if(!showing_peripherals()) 
	return;
     if(strlen(punch_status_area) > 0)
        { /* text */
	 sprintf(fmt,"%%-%ds",cardwidth-2);
	 sprintf(msg,fmt,punch_status_area);
     
	 scdspmsg(punchbase_Y+2,punchbase_X+1,
     		fore, back, msg);
	} /* text */
     else
        { /* count */
	 if(card_count>0)
	    { /* show it */
	     sprintf(msg,"%5d card%s punched",card_count,(card_count == 1 ? "" : "s"));
	     scdspmsg(punchbase_Y+2,punchbase_X+1,H_NORMAL,0,msg);
	    } /* show it */
	} /* count */
	 
    }

/****************************************************************************
*                                 punch_status
* Inputs:
*       char * msg: Message to display on top card
*	boolean error: true if error, false if non-error status
* Effect: 
*       Displays the message on the punch stack
****************************************************************************/

void punch_status(char * msg,boolean error)
    {
     strcpy(punch_status_area,msg);
     status_error = error;
     if(!showing_peripherals()) 
	return;
     show_cdp_status();
    }


/****************************************************************************
*                                 draw_punch
* Effect: 
*       Draws the punch control box
****************************************************************************/

void draw_punch()
    {
     attrib fore;
     attrib back;

     if(ismono())
        { /* mono */
	 fore = H_NORMAL;
	 back = 0;
	} /* mono */
     else
        { /* color */
	 fore = COLOR_WHITE;
	 back = COLOR_BLACK;
	} /* color */

     scdspmsg(punch_Y,punch_X,fore,back,  "ÚÄÄÄÄÄÄÄÄÄÄÄÄÄÄ¿");
     scdspmsg(punch_Y+1,punch_X,fore,back,"³Card Punch    ³");
     scdspmsg(punch_Y+2,punch_X,fore,back,"³              ³");
     scdspmsg(punch_Y+3,punch_X,fore,back,"³              ³");
     scdspmsg(punch_Y+4,punch_X,fore,back,"³              ³");
     scdspmsg(punch_Y+5,punch_X,fore,back,"ÀÄÄÄÄÄÄÄÄÄÄÄÄÄÄÙ");

     draw_button(&cdp_clear_button);
     draw_button(&cdp_name_button);

     if(strlen(punchname) > 0) 
        draw_punch_card(true);
    }


/****************************************************************************
*                                check_punch
* Inputs:
*       coord X: screen X-coordinate of mouse hit
*	coord Y: screen Y-coordinate of mouse hit
* Effect: 
*       If a punch operation is selected, performs it
****************************************************************************/

void check_punch(coord X,coord Y)
    {
     if(in_button(X,Y,&cdp_clear_button)) 
	(*cdp_clear_button.push)();
     if(in_button(X,Y,&cdp_name_button)) 
	(*cdp_name_button.push)();
    }

/****************************************************************************
*                                  cdp_clear
* Effect: 
*       Removes all cards from the punch
****************************************************************************/

void cdp_clear()
    {
     clear_off();
     if(cdp!=NULL) 
	fclose(cdp);
     cdp = NULL;
     cdp_open = false;
     strcpy(punch_status_area,"");
     status_error = false;
     card_count = 0;
     draw_punch_card(true);

    }

/****************************************************************************
*                                  cdp_name
* Effect: 
*       Prompts user for filename of new card image
****************************************************************************/

void cdp_name()
    {
     char name[80];
     coord Y;
     coord X;

     clear_off();

     Y = punchbase_Y;
     X = punchbase_X;


     /* turn the button on */

     cdp_name_button.active = true;

     draw_button(&cdp_name_button);

     /* Create an icon */

     draw_punch_card(false);

     /* Create a space for the user to type */
     scscroll(1,H_REVERSE,(coord)(Y+1),(coord)(X+2),(coord)(Y+1),(coord)(X+cardwidth-3),SCR_UP);

     sccurset((coord)(Y+1),(coord)(X+2));
     
     gets(name);

     scscroll(1,H_NORMAL,(coord)(Y+1),(coord)(X+2),(coord)(Y+1),(coord)(X+cardwidth-3),SCR_UP);

     strcpy(punchname,name);

     if(strlen(punchname)==0)
        { /* delete card */
	 draw_punch_card(true);
	} /* delete card */
     else
        draw_punch_card(false);
     
     /* turn button off */

     cdp_name_button.active = false;

     draw_button(&cdp_name_button);

    }


/****************************************************************************
*                               draw_punch_card
* Inputs:
*	boolean erase: true to erase image
*		       false if no erasure
* Effect: 
*       Draws the card punch deck
****************************************************************************/

void draw_punch_card(boolean erase)
    {
     char msg[cardwidth+5];
     char fmt[20];
     coord Y;
     coord X;
     unsigned char fore;
     unsigned char back;

     if(ismono())
        { /* mono */
	 fore = H_NORMAL;
	 back = 0;
	} /* mono */
     else
        { /* color */
	 fore = COLOR_WHITE;
	 back = COLOR_BLACK;
	} /* color */

     if(!showing_peripherals()) 
	return;

     hide_mouse_cursor();

     X = punchbase_X;
     Y = punchbase_Y;

     if(erase)
        scdspmsg(Y,X,fore,back,"                        ");
     else
        { /* draw card */
	 char L[40];
	 sprintf(L," %cÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ¿",char_corner1);
	 scdspmsg(Y,X,fore,back,L);
	} /* draw card */

     Y = punchbase_Y + 1;
     X = punchbase_X;

     if(erase)
        {
	 scdspmsg(Y,X,fore,back,"                        ");
	}
     else
        { 
	 sprintf(fmt,"%c %%-%ds ³",char_corner2,cardwidth-4);
	 sprintf(msg,fmt,punchname);
	 scdspmsg(Y,X,fore,back,msg);
	}

     Y = punchbase_Y + 2;
     X = punchbase_X;

     if(erase)
         scdspmsg(Y,X,fore,back,"                        ");
     else
         scdspmsg(Y,X,fore,back,"³                      ³");
     Y = punchbase_Y + 3;
     X = punchbase_X;

     if(erase)
        scdspmsg(Y,X,fore,back,"                        ");
     else
        scdspmsg(Y,X,fore,back,"ÀÄÄÄÄÄÄÄpunchÄÄÄÄÄÄÄÄÄÄÙ");
	     
     show_cdp_status();
     
     show_mouse_cursor();

    }


/****************************************************************************
*                                  punch_card
* Result: boolean
*       true if card was punched successfully
*	false if card jammed, no virtual card punch assigned or similar
*	problem
* Effect: 
*       Punches a card image from memory locations 101-180
*	to the virtual card punch
****************************************************************************/

boolean punch_card()
    {
     int i;
     char buffer[81];
     int limit;

     if(!cdp_open)
        { /* open punch */
	 
	 if(strlen(punchname) == 0)  /* no punch name to open */
	    { /* no name */
	     tell("No virtual card punch assigned");
	     return false;
	    } /* no name */

	 cdp = fopen(punchname,"w"); 

	 if(cdp == NULL)
	    { /* failed */
	     int err = errno;
	     char * msg;

	     msg = file_error(err);
	     punch_status(msg,true);
	     tell("Unable to open file");
	     return false;
	    } /* failed */
	 strcpy(punch_status_area,"");
	 cdp_open = true;
	} /* open punch */

     for(i=180;i>101;i--)
        { /* kill end spaces */
	 if(BA8421(memory[i]) != '\0') break;
	} /* kill end spaces */

     /* i is highest valid memory location */

     limit = i+1;
	 
     buffer[0] = '\0';

     for(i=0;i<limit - 101;i++)
        { 
	 buffer[i] = bcd_to_ascii(BA8421(memory[101+i]));
	 buffer[i+1] = '\0';
	}

     fprintf(cdp,"%s\n",buffer);

     card_count++;

     show_cdp_status();

     return true;
    }
