
/* Listing starts here */
#include <alloc.h>
#include <ctype.h>
#include <stdio.h>
#include <conio.h>
#include <string.h>
#include <stdlib.h>
#include <dos.h>

/* Emulates Dave Jewell's version only if there is only one COMMAND.COM */


#define JAYCODE 1		/* Set this for JA Youngman's changes */
#define DEBUG   0		/* Set this to show PSPs as we track them */

/* JA Youngman's code */

/*
	Prototypes
*/
void get_env_info( unsigned int *, unsigned int *);
unsigned int env_back (int);
unsigned int psp_back(unsigned
 int, int);
void panic(const char *);

/*
	Code
*/

void get_env_info( unsigned int * ParentEnv, unsigned int *envSize )
{
	/* Find a certain environment, and its size. */

	int back;
	char ch;

	if ( _argc >= 3 )
		back = atoi( _argv[2] );
	else
		back = -1; /* Go back as far as possible = Master Block */
			   /* i.e. emulate Dave Jewell's version 	*/
			   /* EXCEPT for the case of more than 1 	*/
			   /* COMMAND.COM in memory */

	*ParentEnv = env_back( back );

	/* Find Environment size */
	ch = * (char far *)MK_FP(*ParentEnv-1, 0);
	if (ch != 'M' && ch != 'Z')
		panic("can't find MCB for environment");

	*envSize = 16 * (* (unsigned int far *)MK_FP(*ParentEnv-1, 3));
}


unsigned int env_back (int count) /* Find ancestor environment */
{
	return * (unsigned int far *)MK_FP(psp_back(_psp,count),0x2C);
}

unsigned int psp_back(unsigned int psp_at, int count) /* Ancestor PSP */
{
	/* Move back count PSPs. */
	/* Uses word at offset 0x16 in PSP */

	unsigned int last;

	while (count--)
	{
		last =
 psp_at;
		psp_at = * (unsigned int far *)MK_FP(psp_at, 0x16);
#ifndef NDEBUG
		printf("PSP at %X\n", psp_at);
#endif

		if (psp_at == last)
			break;		/* Found *_ANY_* COMMAND.COM */

		else if (psp_at == 0)
			panic ("can't find parent PSP");
	}
	return psp_at;
}

void panic(const char *msg)
{
	fprintf(stderr, "fatal error: %s\n", msg);
	exit(-1);
}









// Dave Jewell's code follows.

char far * findVar (char far * masterEnv, char * name, unsigned * end)
{
	int len;

	char far * found = NULL;

	len = strlen(name);
	while (*masterEnv != '\0')
	{
		if (masterEnv [len] == '=' && found == NULL)
		{
			// Lengths match, now see if name matches

			masterEnv [ len] = '\0';
			if ( _fstrcmp(masterEnv, name) == 0) found = masterEnv + len + 1;
			masterEnv [len] = '=';
		}
		masterEnv += _fstrlen (masterEnv) + 1;
	}

	*end = FP_OFF (masterEnv);
	return found;
}

unsigned keyPress (void)
{
	char ch;
	return (ch = getch()) != '\0' ? ch : 0x8000 | getch();
}


void SetCursor (unsigned size)
{
	asm	mov	ah,1
	asm	mov	cx,size
	asm	push	bp
	asm	int 	10h
	asm	pop	bp
}

char *EditString (char far * p, int free )
{
	int x, y, redo = 1;
	int rootx, rooty;
	int index = 0;
	int insert = 1;
	static char buff [256];
	unsigned ch;
#ifdef JAYCODE
	int length;
#endif

	rootx = wherex();
	rooty = wherey();
	_fstrcpy (buff, p);
	p = buff;
	printf(buff);

	for(;;)
	{
		if (redo)
		{
			redo ^= 1;
			gotoxy(1,1);
			printf("Free bytes in master 
environment = %u    ",
				free);
			gotoxy(rootx, rooty);
			printf("%s",buff);
		}

		x = rootx; y = rooty;
		while ( x + index > 80)  { x -= 80; y++; }
		gotoxy (x + index, y);
		SetCursor( insert ? 0x0107 : 0x0607);

		switch (ch = keyPress() )
		{
			case 0x1B:	SetCursor(0x0607); return (NULL); // ESC
			case 0x0D:	SetCursor(0x0607); return (buff); // Enter
			case 0x8047:	index = 0; break;		  // Home
			case 0x8052:	insert ^= 1; break;		  // Insert toggle
			case 0x804B:	if (index > 0
) index--;		  // Left arrow
						break;
			case 0x804D:	if (index < strlen(buff)) index++;// Right arrow
						break;
			case 0x804F:	index = strlen(buff); break;	  // End
			case '\b':	if (index == 0) break;		  // BS
					else index--;
			case 0x8053:	if (index < strlen(buff))	  // Del
					{
						redo ^= 1;
						free++;
						strcpy(&buff[index], &buff[index+1]);
#ifdef JAYCODE
						length = strlen(buff);
						/* Normalise coordinates */
						while ( x + length > 80)  { x -= 80; y++; 
}
						gotoxy (x + length, y);
						putchar(' ');

#endif
					}
					break;
			default:	if (free == 0 || ch < ' ' || ch >= 127)
						putch ('\a');
					else
					{
						if (index == strlen(buff))
						{
							buff[index++] = ch;
							buff[index] = '\0';
							redo ^= 1;
							free--;
						}
						else if (insert == 0)
						{
							buff[index++] = ch;
							redo ^= 1;
						}
						else
						{
							memmove(buff+index+1, buff+index, strlen(&buff[index])+1);
							b
uff [index++] = ch;
							redo ^= 1;
							free--;
						}
					}
					break;
		}
	}
}

void eset (char *name)
{
	char ch;
	unsigned end;
	char far *p;
	char * newstr;
	char far * src;
	char far * dest;
	char far * newEnv;
	char far * MasterEnv = NULL;
	unsigned envSize;

#ifdef JAYCODE
	unsigned int MasterEnvSeg;

	get_env_info( &MasterEnvSeg, &envSize);
	MasterEnv = MK_FP(MasterEnvSeg, 0);
#else

	// Locate the master Environment

	asm	mov	ax, 352Eh	// get int $2E address

	asm	int	21h		// result in ES:BX
	asm	mov	ax,es:2Ch	// load master env seg
	asm	mov	word ptr MasterEnv+2,ax // save it in C-land
	asm	dec	ax		// Point at MCB
	asm	mov	es,ax		// ES addresses it
	asm	mov	ax,es:3		// get size word
	asm	mov	cl,4		// 4 shifts
	asm	shl	ax,cl		// multiply by 16
	asm 	mov	envSize,ax	// save it for later
#endif

	if (( p = findVar (MasterEnv, strupr(name), &end)) == NULL)
	{
		printf ("Environment variable '%s' not found.  Add it (Y/N) ? : ", name);
		printf ("%c\n", 
ch = getch());
		if (ch != 'y' && ch != 'Y') return;
		p = "";
	}


#ifdef JAYCODE
	if (envSize - end < 10)
	{
		printf("There is not enough space left "
			"in your environment (%i bytes of %i used).\n",
			end, envSize );
		exit(1);
	}
#endif
	clrscr();
	gotoxy(1,3);
	printf("%s=", name);
	newstr = EditString (p, envSize - end - 10);
	clrscr();
	if (newstr == NULL) printf ("No changes made\n");
	else
	{
		// Build a new master environment block

		dest = newEnv = farmalloc(envSize
);
		src = MasterEnv;

		if ( *p == '\0')	// New environment variable
		{
			while (*dest++ = *name++)   ;
			* (dest - 1) = '=';
			while (*dest++ = *newstr++) ;
		}
		else
		{
			while (src != p - strlen (name) - 1) *dest++ = *src++;
			if (*newstr == '\0') printf ("Environment variable '%s' deleted\n", name);
			else
			{
				while (*dest++ = *name++)   ;
				*(dest - 1) = '=';
				while (*dest++ = *newstr++) ;
			}
			src = p + _fstrlen (p) + 1;
		}
		while (FP_OFF(src) != end) *des
t++ = *src++;
		*dest++ = *src++;
		*dest++ = *src++;
		*dest++ = *src++;
		while (*dest++ = *newstr++) ;
		_fmemcpy(MasterEnv, newEnv, envSize);
	}
}

void main (int argc, char *argv[])
{
	if (argc < 2) printf("Usage: envset envvar\n");
	else eset (argv [1]);
}

/* Listing ends here */

