{***********************************************************************}
{									}
{ __PutEnUtl  Place a string in the environment 			}
{									}
{ function  __PutEnUtl(EnvStr : string) : string			}
{									}
{	      EnvStr	The environment string to be placed in the	}
{			environment space.				}
{									}
{ Description The __PutEnUtl function places a string in the environ-	}
{	      ment.  __PutEnUtl always makes a copy of the environment, }
{	      altering the global variable _EnvPtr, the pointer to the	}
{	      local environment space.	If EnvMemPtr_ is NIL, then this }
{	      is the first copy, but if not, the previous space is re-	}
{	      released. 						}
{									}
{	      The first step is to reformat the environment string	}
{	      parameter to conform with DOS rules.  It must have an	}
{	      equal sign, no leading blanks, and all characters before	}
{	      the equal sign (the environment variable) are shifted to	}
{	      upper case.  The value of the function is the reformatted }
{	      string if it is successfully placed in the environment;	}
{	      otherwise the null string is returned (length is 0).	}
{									}
{	      The next step is to search the current environment to	}
{	      find the position where the variable appears (if it does	}
{	      at all).	The new environment size is computed, and space }
{	      allocated.  The environment strings that do not change	}
{	      are copied to the new space, and the new (or altered)	}
{	      string is placed at the end of the environment.		}
{									}
{ Version     4.00 (C)Copyright Blaise Computing Inc. 1987		}
{_______________________________________________________________________}

function __PutEnUtl(EnvStr : string) : string;

  const
    EQUAL = '=';
    BLANK = ' ';
    TAB   = #9;

  type
    Environment    = array[1..32767] of char;
    EnvironmentPtr = ^Environment;

  var
    PrevSize	   : word;
    NewSize	   : word;
    TempSize	   : word;
    VarPos,VarSize : integer;
    I,J 	   : integer;
    LenEnvStr	   : integer;
    EqualPos	   : integer;
    EqSign	   : integer;
    EqPos	   : integer;
    Found	   : boolean;
    EnvVar,RetStr  : string;
    PrevEnvPtr	   : EnvironmentPtr;
    NewEnvPtr	   : EnvironmentPtr;
    TempPtr	   : pointer;
    TempCh	   : char;

  begin {__PutEnUtl}

    { First reformat EnvStr so that it has no leading blanks and all	}
    { characters before the equal sign are shifted to upper case.	}

    I	      := 1;
    Found     := TRUE;
    LenEnvStr := Length(EnvStr);
    while ((I <= LenEnvStr) and Found) do
      if ((EnvStr[I] = BLANK) or (EnvStr[I] = TAB)) then
	 Inc(I)
      else
	 Found := FALSE;
    J	      := I - 1; 	       { Number of blanks removed	}
    LenEnvStr := LenEnvStr - J;        { This is the new length 	}

    EqSign := 0;		       { Look for equal sign position	}
    for I  := 1 to LenEnvStr do
      begin
	TempCh := EnvStr[I + J];
	if (TempCh = EQUAL) then
	   begin
	     Inc(EqSign);
	     EqPos  := I
	   end;
	if (EqSign <> 0) then
	   EnvStr[I] := TempCh	       { Just copy the character, but	}
	else			       { before equal sign, shift to	}
	   EnvStr[I] := UpCase(TempCh) { upper case.			}
      end;
    if (EqSign <> 1) then	       { There must be precisely one	}
       begin			       { equal sign in the string.	}
	 __PutEnUtl := '';	       { Return the NULL string and	}
	 Exit			       { exit immediately.		}
       end
    else
       begin
	 EnvStr[0]  := Chr(LenEnvStr);	  { New string length, and set	}
	 __PutEnUtl := EnvStr		  { the function value. 	}
       end;

    { Now search the environment, to compute its length and see if the	}
    { specified environment variable appears.				}

    EnvVar   := Copy(EnvStr,1,EqPos - 1);
    VarPos   := 0;		       { Position where string is found }
    PrevSize := 1;		       { Size of existing environment	}
    RetStr   := __RetEnUtl(PrevSize);
    while (Length(RetStr) <> 0) do     { Search the entire environment	}
      begin
	if (VarPos = 0) then	       { Look for the new string	}
	   if (EnvVar = Copy(RetStr,1,Pos(EQUAL,RetStr) - 1)) then
	      begin
		VarSize := Length(RetStr) + 1;	     { Account for NULL }
		VarPos	:= PrevSize - VarSize
	      end;
	RetStr := __RetEnUtl(PrevSize)
      end;

    { Now compute the total size of the new environment copy.  If the	}
    { environment variable was not found, then size is just the pre-	}
    { vious size plus the length of EnvStr plus 1 (NUL byte).		}
    { If it is found, then the size is the previous size minus the size }
    { of the string found plus the size of the new string. If the new	}
    { string has no parameter, then the string is removed altogether	}
    { from the environment, and the new size is the previous size less	}
    { the size of EnvStr plus 1 (the NUL byte). 			}

    if (Length(Copy(EnvStr,EqPos + 1,255)) = 0) then
       begin			       { Remove the string		}
	 NewSize   := PrevSize;
	 LenEnvStr := 0
       end
    else
       NewSize := PrevSize + LenEnvStr + 1;
    if (VarPos <> 0) then	       { EnvStr was found, so must re-	}
       NewSize := NewSize - VarSize;   { move the old version.		}

    { To make sure the environment is placed on a paragraph boundary,	}
    { add 15 to the requested size, and then put the environment on	}
    { the next paragraph boundary.  The global variable _EnvPtr 	}
    { points to the current environment.				}

    TempSize	 := NewSize + 15;
    GetMem(TempPtr,TempSize);	       { Allocate new environment space }
    PrevEnvPtr	 := EnvironmentPtr(_EnvPtr);
    if (_VectorAddr(TempPtr)._Ofs <> 0) then
       NewEnvPtr := Ptr(_VectorAddr(TempPtr)._Seg + 1,0)
    else
       NewEnvPtr := TempPtr;

    { Now just copy the environment to the new space in chunks. 	}

    if (VarPos = 0) then	       { Just add the new string.	}
       begin
	 Move(PrevEnvPtr^[1],NewEnvPtr^[1],PrevSize - 1);
	 Move(EnvStr[1],NewEnvPtr^[PrevSize],LenEnvStr)
       end
    else
       begin
	 Move(PrevEnvPtr^[1],NewEnvPtr^[1],VarPos - 1);
	 Move(PrevEnvPtr^[VarPos + VarSize],
	       NewEnvPtr^[VarPos],PrevSize - VarPos - VarSize);
	 Move(EnvStr[1],NewEnvPtr^[PrevSize - VarSize],LenEnvStr)
       end;
    NewEnvPtr^[NewSize - 1] := Chr(0);
    NewEnvPtr^[NewSize]     := Chr(0);

    { Finally dispose of any unwanted space, and reset global variables.}
    { Alter the program segment prefix so that offset $2C contains the	}
    { segment address of the environment table. 			}

    if (EnvMemPtr_ <> NIL) then
       FreeMem(EnvMemPtr_,EnvSize_);
    EnvMemPtr_		:= TempPtr;
    EnvSize_		:= TempSize;
    _EnvPtr		:= NewEnvPtr;
    MemW[PrefixSeg:$2C] := _VectorAddr(_EnvPtr)._Seg

  end;	{PutEnUtl}
