/* part.c */


/*
 * 24-Nov-88	jye. 	change and add codes so that can be used for MS-DOS
 */
#include "obdefs.h"
#include "gemdefs.h"
#include "osbind.h"
#include "mydefs.h"
#include "part.h"
#include "bsl.h"
#include "hdx.h"
#include "addr.h"


extern char sbuf[];
extern int rebootp;
extern int npart;
extern int uplim;
extern long bslsiz;
extern long gbslsiz();
extern int noinfo;		/* 1: no information inside the wincap */

/*
 * Complain about partition error.
 *
 */
parterr(devno)
int devno;
{
    char *pdev="X";
    
    *pdev = devno + '0';
    (cantpart[PTNDEV].ob_spec)->te_ptext = pdev;
    cantpart[PTNERROK].ob_state = NORMAL;
    execform(cantpart);
    return ERROR;
}


/*
 * Fill in partition entry with default information
 * and configuration values from the current "pr" wincap entry.
 *
 */
fillpart(n, part)
int n;
PART *part;
{
    long num;
    char *partid;
    char *idstr = "XX";
    char *wgetstr();

    idstr[1] = n + '0';

    /* see if `pX' is mentioned */
    *idstr = 'p';
    if (wgetnum(idstr, &num) == OK)
    {
	/* do the ST partition assignment */
		npart++;
		part->p_siz = (LONG)(num / 512);
	   	part->p_flg = P_EXISTS;
		if (part->p_siz < MB16)	{
    		part->p_id[0] = 'G';
    		part->p_id[1] = 'E';
    		part->p_id[2] = 'M';
		} else {
    		part->p_id[0] = 'B';
    		part->p_id[1] = 'G';
    		part->p_id[2] = 'M';
		}
    }
}


/* set the partition informations to the partition structures */

setpart(part, pnam, hsize)
PART *part;
char *pnam;
long hsize;
{
    long onepart, remain;
	int i;

	npart = 4;
	if ((!noinfo) && (*pnam)) 	{
		/* there is a partition scheme inside the wincap */
		msetpart(part, pnam, hsize);
		return OK;
	}
	onepart = hsize/4;
	remain = (hsize - onepart * 4) / 4;
	for ( i = 0; i < 4; i++, part++)	{
		if (i == 4)	{
			part->p_siz = hsize - (onepart + remain) * 3;
		} else {
			part->p_siz = onepart+remain;
		}
   		part->p_flg = P_EXISTS;
		if (part->p_siz < MB16)	{
   			part->p_id[0] = 'G';
   			part->p_id[1] = 'E';
   			part->p_id[2] = 'M';
		} else {
   			part->p_id[0] = 'B';
   			part->p_id[1] = 'G';
   			part->p_id[2] = 'M';
		}
	}
}

/* set the partition informations from the 'pname'. 	*/
/* For example, pname = 12-12-14-14						*/		

msetpart(part, pname, hsize)
PART *part;
char *pname;
long hsize;
{
    long part1, part2, part3, part4, remain;
	int i, np;

	npart = 4;
	np = 4;
	convs2i(pname, &part1, 1);		/* 1: get first ASCII */
	if (convs2i(pname, &part2, 2) == 1)		{		/* 2: get second ASCII */
		/* only one partition */
		part2 = 0;
		part3 = 0;
		part4 = 0;
		np = 1;
	} else if (convs2i(pname, &part3, 3) == 2)	{	/* 3: get third ASCII */
		/* only two partitions */
		part3 = 0;
		part4 = 0;
		np = 2;
	} else if (convs2i(pname, &part4, 4) == 3)	{	/* 4: get fourth ASCII */
		/* only three partitions */
		part4 = 0;
		np = 3;
	}
	remain = (hsize - (part1 + part2 + part3 + part4)) / np;
	if (np == 1)	{
		part1 = hsize;
	} else if (np == 2)	{
		part1 += remain;
		part2 = hsize - part1;
	} else if (np == 3)	{
		part1 += remain;
		part2 += remain;
		part3 = hsize - part1 - part2;
	} else {
		part1 += remain;
		part2 += remain;
		part3 += remain;
		part4 = hsize - part1 - part2 - part3;
	}
	for ( i = 0; i < 4; i++, part++)	{
		switch(i)	{
			case 0:	part->p_siz = part1;
					break;
			case 1:	part->p_siz = part2;
					break;
			case 2:	part->p_siz = part3;
					break;
			case 3:	part->p_siz = part4;
					break;
		}
		if (!part->p_siz) continue;
   		part->p_flg = P_EXISTS;
		if (part->p_siz < MB16)	{
   			part->p_id[0] = 'G';
   			part->p_id[1] = 'E';
   			part->p_id[2] = 'M';
		} else {
   			part->p_id[0] = 'B';
   			part->p_id[1] = 'G';
   			part->p_id[2] = 'M';
		}
	}
}


/* conver the string 12-12-14-14 to a integer */

convs2i(pname, num, flag)

char *pname;
long *num;
int flag;		/* 1: conver the first one. 3: conver the third one */

{
	char tem[10], *ptr;
	int i;
	UWORD n=0;

	ptr = pname;
	for (i = 0; i < 10; i++)
		tem[i] = "\0";

	if (flag == 2)	{	/* conver the second one of pname */
		while ((*ptr != '-') && (*ptr))  	ptr++;
		if (!*ptr)  return 1;	/* only one partition */
		ptr++;
	} else if (flag == 3)	{	/* conver the third one of 12-12-14-14 */
		while (*ptr != '-') 	ptr++;
		ptr++;
		while ((*ptr != '-') && (*ptr))  	ptr++;
		if (!*ptr) return 2;		/* only two partitions */
		ptr++;
	} else if (flag == 4)	{
		while (*ptr != '-') 	ptr++;
		ptr++;
		while (*ptr != '-') 	ptr++;
		ptr++;
		while ((*ptr != '-') && (*ptr))  	ptr++;
		if (!*ptr) return 3;		/* only three partitions */
		ptr++;
	}
	/* copy the string into the buf */
	for (i = 0; (*ptr != '-')&&(*ptr); )	{
		tem[i++] = *ptr++;
	}

	/* conver the string to integer */
	for (i = 0; tem[i] >= '0' && tem[i] <= '9'; ++i)
		n = 10 * n + (UWORD)(tem[i] - '0');

	*num = (long)n * 2048;
	if (!n) return(flag - 1);
	return OK;
}



/* set the menu partition scheme */

setschm(dsize, partnames)

long dsize;
char *partnames;

{
	int part12;
	int part34;
	int i;

	for (i = 0; i < NAMSIZ; i++)	{
		partnames[i] = '\0';
	}
	part34 = dsize/(2048*4) - 2;
	part12 = part34 + 4;
	for (i = 0; i < 4; i++)	{
		if (!part34)		/* add the remainder into part12 */
			part12 += (dsize/2048 - 2 * part12) / 2;
		itoas(partnames, part12, 0);
		itoas(partnames, part34, 1);
		if (part34 == 1)	{		
			part12++; 		/* add the remainder into part12 */
			part34 = 0;
		} else {
			part34 -= 2;
			part12 += 2;
		}
		if (part34 < 0) break;
	}
}


/* convert the integer into ASCII and store it into a buffer like	*/
/* 12-12 if the integer is 12 										*/

itoas(buf, num, flag)
char *buf;
int num;
int flag; 		/* 1: put second part of scheme. Now buf = 12-12\0 */

{
	int i=0, j;
	char tem[10];

	if (*buf)	{ /* 12-12-14-14\010-10\0 inside the buf */
	skp:
		while (*buf)	buf++;
		if ((!flag) || (*(buf+1)))	 buf++;		/* skip between string */
		if (*buf) 	{
			goto skp;
		}
		if (flag)	{	/* put second part of scheme */ 
			*buf++ = '-';
		}
	} 
	/* conver the integer to ASCII */
	do	{	/* generate digits in reverse order */
		tem[i++] = num % 10 + '0';		/* get next digits */
	} while ((num /= 10) > 0);			/* delete it */

	j = i;
	for (; i > 0; )	{	/* reverse string 'buf' in place */
		*buf++ = tem[--i];
	}
	*buf++ = '-';
	for (; j > 0; )	{	/* reverse string 'buf' in place */
		*buf++ = tem[--j];
	}
	*buf++ = '\0';
}


/*
 * Force checksum of sector image to a value
 */
forcesum(image, sum)
UWORD *image;
UWORD sum;
{
    register int i;
    register UWORD w;

    w = 0;
	/* up limit is half of buffer size - 2 */
    for (i = 0; i < ((UWORD)BPS/2 - 1); ++i)
	w += *image++;
    *image++ = sum - w;
}


/*
 * Put word in memory in 8086 byte-reversed format.
 *
 */
iw(wp, w)
UWORD *wp;
UWORD w;
{
    char *p;

    p = (char *)wp;
    p[0] = (w & 0xff);
    p[1] = ((w >> 8) & 0xff);
}

/*
 * Put long word in memory in 8086 word-reversed format.
 *
 */
ilong(lp, l)
long *lp;
long l;
{
    UWORD *p;

    p = (UWORD *)lp;
    iw(&p[0],(UWORD)(l & 0xffff));
    iw(&p[1],(UWORD)((l >> 16) & 0xffff));
}

/*
 * Get long word in memory, from 8086 word-reversed format.
 *
 */
glong(al, lp)   /* al is a swaped return long word,*/
				/* lp is a to be swaped long word */
long *al;
long *lp;

{
   char *p, *q;

    p = (char *)al;
    q = (char *)lp;
	p[0] = q[3];
	p[1] = q[2];
	p[2] = q[1];
	p[3] = q[0];
}

/*
 * Get word in memory, from 8086 byte-reversed format.
 *
 */
UWORD gw(wp, aw)
UWORD *wp;
UWORD *aw;
{
    char *p, *q;

    p = (char *)wp;
    q = (char *)aw;
    q[0] = p[1];
    q[1] = p[0];
    return *aw;
}
