/* **************************************************************
 *								*
 *			  MACHINE2.C				*
 *	UTILITIES FOR USE IN ADDING/ CHANGING MACHINE TABLE	*
 *		  last modified 02/22/84 dsb			*
 *								*
 ************************************************************** */

/* #define DBUG 1 */

#include "libc.h"
#include "machine.h"
#include "hardio.h"

#define MAX_PROD  20	   /* consider any higher product numbers invalid */
#define MAX_MACH  128	   

       
ret_esc_msg()
{
    printf("\nRETURN to keep current setting, ");
    printf("\nESC to go back to main menu");
}


help_find_serial(fig)	    /* describe how to get serial number */
struct CONFIGURE *fig;
{
    if(fig)
	switch(fig->prod)
	{
	   default: help_not_installed(fig);
		    break;
	    case 1: help_zbsc_3(fig);
		    break;
	}
    else
	printf("\nYour manual can tell you how to find the serial number.");
    printf("\n");
    return();
} /* help_find_serial */

help_not_installed(fig)
struct CONFIGURE *fig;
{
    printf("\nYour manual can tell you how to find the");
    printf(" serial number on a %s.",fig->long_name);
    return();
}

help_zbsc_3(fig)
struct CONFIGURE *fig;
{
    printf("\nTo find the serial number on a %s, enter the ",fig->long_name);
    printf("PROM Monitor\nand type D3FE<cr>.  The first four bytes dumped");
    printf(" are the serial \nnumber (that is, the two bytes on the line ");
    printf("labeled 03FE and\nthe first two bytes of the line labeled 0400).");
    return();
}

/*page*/
get_iobyte(ent,adding,def_ok)
struct MTentry *ent;
int adding;
int def_ok;
{
    register struct CONFIGURE *x;
    int  def_con = -1;
    int  def_prt = -1;
    register int  def_iobyte;
    char keep_default;
    char *standard = "STANDARD";
    register char *cp;

    if((x = mt_findmodel(&(ent->product))) == NULL)
    {
	printf("\n*BUG* in get_iobyte, can't identify model");
	return(0x54);
    }

    keep_default = 'N';
    if(adding || !def_ok)
    {
	def_iobyte = x->def_iob;
	printf("\nThe default console for the %s is %s",x->long_name,
			product[x->prod].io->con[def_iobyte & 0x03]->longer);
	keep_default = yorn("\nWill you accept the default console");
    } /* if adding (give chance to use machine default) */

    else
    {
	def_iobyte = ent->iobyte;
	if(x && ((def_iobyte & 0x03) == (x->def_iob & 0x03)))
	    cp = standard;
	else
	    cp = product[ent->product].io->con[def_iobyte & 0x03]->longer;
	printf("\nThe current console selection is %s",cp);
	if(cp != standard)
	    printf(" (%s)",cpm_console[def_iobyte & 0x03]);
	keep_default = yorn("\nDo you want to keep this console setting");
    } /* if modifying (give chance to keep current setting) */

    if(keep_default == 'Y')
	def_con = def_iobyte & 0x03;
    else
    {
	if(adding)
	    def_con = pick_console(&(x->prod));
	else
	    def_con = pick_console(&(ent->product));
    }
    if(def_con < 0)
	return(-1);

    keep_default = 'N';
    if(!adding) 		  /* now pick a printer */
    {
	if(x && ((def_iobyte & 0xE0) == (x->def_iob & 0xE0)))
	    cp = standard;
	else
	    cp = product[ent->product].io->prt[(def_iobyte & 0xE0)>>5]->longer;
	printf("\nThe current printer selection is %s",cp);
	keep_default = yorn("\nDo you want to keep this printer setting");
    } /* if modifying (give chance to keep current setting) */
/*page*/
    if(keep_default == 'Y')
	def_prt = def_iobyte & 0xE0;
    else
    {
	if(adding)
	    def_prt = pick_printer(&(x->prod),x->def_iob);
	else
	    def_prt = pick_printer(&(ent->product),x->def_iob);
    }
    if(def_prt < 0)
	return(-1);

    ent->iobyte = def_prt + (def_iobyte & 0x1C) + def_con;
    return(ent->iobyte);
} /* get_iobyte */

pick_console(map)	/* argument is a pointer to an array of which */
char *map;		/* the 1st byte is product type and the next  */
{			/* six are the option map for this model      */
    register int i,j;
    long x;
    int max_valid = 3;
    char valid[4];
    char standard;
    register struct PORT **pp;
    char display_map[4];

    
    display_map[0] =  0;	/* For most products, this order will  */
    display_map[1] =  2;	/* put serial port 0 first, then the   */
    display_map[2] =  1;	/* fox parallel port, then the others  */
    display_map[3] =  3;	/* (which are much less common!)       */

    pp = &(product[*map].io->con);  /* point to first console description */
				    /* for this product type */
#ifdef DBUG 
    printf("\n&product[%x] = %x",*map,&(product[*map]));
    printf("\n &(.io) = %x, &(.io->con) = %x",&(product[*map].io),
		&(product[*map].io->con));
    printf("\npp = %x",pp);
    wait_user();
#endif

    for(i=0; i<4; i++)
	valid[i] = map_test(map+1,pp[i]->map1) || map_test(map+1,pp[i]->map2);

    for(i=0; i < max_valid+1; i++)   /* eliminate selections that aren't */
	if(!valid[display_map[i]])   /* valid on this model machine */
	{
	    for(j=i; j<max_valid; j++)
		display_map[j] = display_map[j+1];
	    max_valid--;
	    i--;		/* check the same one again */
	}
    do
    {
	printf("\nPossible console types are:\n");
	for(i=0; i <= max_valid; i++)
	    printf("\n%6d - %-16s (%s)",i+1,pp[i]->longer,cpm_console[i]);
	printf("\nEnter your choice --> ");
	x = gethex(1,2);
	j = (int) x;
	if(abort_req && (j == ESC))
	    return(-1);
	j--;	
	if((j<0) || (j>max_valid) || !valid[display_map[j]])
	    printf("\07Invalid entry!");
    } while(error || (j < 0) || (j > max_valid) || !valid[display_map[j]]);
    return(display_map[j]);
} /* get console assignment */
/*page*/

pick_printer(map,def_iob)	/* map is a pointer to an array same as */
char *map;			/* in pick_console.  def_iob is the usual */
char def_iob;			/* default iobyte for this model. */
{
    register int i,j;
    long x;
    int max_valid = 7;
    char valid[8];
    char standard;
    register struct PORT **pp;
    char display_map[8];

    for(i=0; i<8; i++)
	display_map[i] =  i;	/* this mapping will be altered so that  */
				/*  the first entry is the number of the */
				/* default printer for this model computer, */
				/* and second entry is the spooler. */

    pp = &(product[*map].io->prt);  /* point to first printer description */

#ifdef DBUG 
    printf("\n&product[%x] = %x",*map,&(product[*map]));
    printf("\n &(.io) = %x, &(.io->prt) = %x, content=%x",&(product[*map].io),
		&(product[*map].io->prt),product[*map].io->prt);
    printf("\npp = %x",pp);
    wait_user();
#endif


    for(i=0; i<8; i++)
	valid[i] = map_test(map+1,pp[i]->map1) || map_test(map+1,pp[i]->map2);

    standard = (def_iob & 0xE0) >> 5;	    /* find "normal" printer */
    j = display_map[0];
    display_map[0] = standard;		    /* make it first on the list */
#ifdef DBUG
    printf("\nputting standard (%x) into dmap[0]",standard);
    printf("\nsaving previous dmap[0] which is %x",j);
#endif

    for(i=1; i<8; i++)
	if(display_map[i] == standard)	    /* find where it was in the list */
	{				    /* and put the old first entry */
	    display_map[i] = j; 	    /* in that place instead */
#ifdef DBUG
	    printf("\nputting that %x into dmap[%x]",j,i);
#endif
	    break;
	}

    j = display_map[1]; 		    /* if there's a spooler in the */
    for(i=2; i<8; i++)			    /* list, switch its place with */
	if((pp[display_map[i]]->map1 == OP_SPOOLER)  /* the current second */
	 ||(pp[display_map[i]]->map2 == OP_SPOOLER)) /* entry in list */
	{
#ifdef DBUG
	    printf("\nfound spooled at entry %x",i);
	    printf("\nswitching it with the %x at entry 1",j);
#endif
	    display_map[1] = display_map[i];
	    display_map[i] = j;
	    break;
	}

    for(i=0; i < max_valid+1; i++)	/* eliminate invalid selections */
	if(!valid[display_map[i]])
	{
#ifdef DBUG
	    printf("\ndisplay_map[%x] = %x which is invalid",x,display_map[x]);
	    printf("\nas you don't have options %x or %x",
		      pp[display_map[i]]->map1,pp[display_map[i]]->map2);
#endif
	    for(j=i; j<max_valid; j++)
	       display_map[j] = display_map[j+1];
	    max_valid--;
	    i--;		/* check the same one again */
	}
/*page*/
#ifdef DBUG
    for(i=0; i<8; i++)
	printf("\ndmap[%x]=%x; pp[%x] = %x",i,display_map[i],
		    display_map[i],pp[display_map[i]]);
    wait_user();
#endif
    do
    {
	printf("\nPossible printer types are:\n");
	if(max_valid >= 0)
	{
	    printf("\n     1 - STANDARD (%s)",pp[display_map[0]]->longer);
	    if(cpm_printer[display_map[0]])
		printf(" (%s)",cpm_printer[display_map[0]]);
	}
	if(max_valid >= 1) 
	{
	    printf("\n     2 - %-16s\n",pp[display_map[1]]->longer);
	    if(cpm_printer[display_map[1]])
		printf(" (%s)",cpm_printer[display_map[1]]);
	}
	for(i=2; i <= max_valid; i++)
	{
	    printf("\n%6d - %-16s",i+1,pp[display_map[i]]->longer);
	    if(cpm_printer[display_map[i]])
		printf(" (%s)",cpm_printer[display_map[i]]);
	}
	printf("\nEnter your choice --> ");
	x = gethex(1,2);
	j = (int) x;
	if(abort_req && (j == ESC))
	    return(-1);
	j--;	
	if((j<0) || (j>max_valid) || !valid[display_map[j]])
	    printf("\07Invalid entry!");
    } while(error || (j < 0) || (j > max_valid) || !valid[display_map[j]]);
    return(display_map[j] << 5);
} /* get printer assignment */

/*page*/
get_serial(p,def_ok)
long *p;
int def_ok;   
{

    do
    {
	abort_req = FALSE;
	*p = gethex(8,8);
	if((abort_req) && long_eq(*p,(long)ESC))
	    return();	 
	if((abort_req && !def_ok) || error)
	{
	    error = TRUE;
	    printf("%cinvalid input... try again --> ",BELL);
	}
	else
	    upside(p,4);	/* char array is upside down compared to */
				/* numerical value of long */
    } while (error);
    return();
} /* get serial number (once) */

/*page*/
get_new_serial(p,must_put)	/* get serial num, re-entering to verify */
long *p;			/* return TRUE if something was input */
int must_put;
{
    long ser1,ser2;

    do
    {
	get_serial(&ser1,!must_put);
	if(abort_req)
	{
	    if(long_eq(ser1,(long)ESC))
		*p = (long)ESC;
	    return(FALSE);
	}
	printf("\nEnter the same number again for verification --> ");
	get_serial(&ser2,FALSE);
	if(abort_req)
	{
	    if(long_eq(ser2,(long)ESC))
		*p = (long)ESC;
	    return(FALSE);
	}
	if(!long_eq(ser1,ser2))
	{
	    printf("\n\07Number wasn't verified correctly!");
	    printf("\nRe-enter the serial number --> ");
	    must_put = TRUE;
	}
    } while(!long_eq(ser1,ser2));
    *p = ser1;
    return(TRUE);
} /* get_new_serial (verify by entering it again) */


upside(p1,len) 
char *p1;
int len;
{
    register int i;
    char t;
    register char *p2;

    p2 = p1 + len - 1;
    for(i=0; i< len/2; i++, p1++, p2--)
    {
	t = *p1;
	*p1 = *p2;
	*p2 = t;
    }
} /* upside (turn a serial number or other string around backwards) */

-)
    {
	t = *p1;
	*p1 = *p2;
	*p2 = t;
   