{***********************************************************************}
{									}
{ UNIT_PGM	Program control 					}
{									}
{ This unit provides allows program control including the loading	}
{ and execution of child processes and a general shell command. 	}
{									}
{  _ExecMemReq								}
{	      Memory requirement for __ExecPgm		     (type)	}
{									}
{	      All vectors that are typically altered by a Turbo 	}
{	      Pascal application are saved in global variables		}
{	      before a child process is spawned.			}
{									}
{  _ExecMemory						     (variable) }
{	      Memory requirements used by __ExecPgm			}
{  _UseHeap   Use heap memory for child process 	     (variable) }
{  _CurVector00 					     (variable) }
{  _CurVector02 					     (variable) }
{  _CurVector1B 					     (variable) }
{  _CurVector23 					     (variable) }
{  _CurVector24 					     (variable) }
{  _CurVector75 					     (variable) }
{									}
{ __FCallPgm  Call a far procedure			     (macro)	}
{ __NCallPgm  Call a near procedure			     (macro)	}
{ __ExecPgm   Load and execute a child process				}
{ __DOSExPgm  Execute a DOS command					}
{ __SpawnPgm  Execute a process 					}
{ __ShellPgm  Invoke a secondary copy of COMMAND			}
{ __WaitPgm   Return the value of the exit code 			}
{ __WinExPgm  Execute a process (using __SpawnPgm) within a window	}
{ __WinShPgm  Invoke a secondary copy of COMMAND within a window	}
{ __ExitRPgm  Terminate the process and remain resident 		}
{ __RemPgm    Remove a resident program from memory			}
{									}
{ Version 4.00	(C)Copyright Blaise Computing Inc.  1987		}
{_______________________________________________________________________}

unit Unit_Pgm;

interface
  uses DOS,				 { Turbo Pascal DOS unit	}
       Unit_Sup,			 { POWER TOOLS general support	}
       Unit_Mem,			 { POWER TOOLS memory management}
       Unit_Utl;			 { POWER TOOLS utility functions}

  type
    _ExecMemReq = record		 { Memory requirements for EXEC }
		    _MinMemory : longint;{ Minimum memory requirements	}
		    _MinHeap   : longint { Minimum heap space required	}
		  end;
  var
    _ExecMemory  : _ExecMemReq;        { Heap use memory requirements	}
    _UseHeap	 : boolean;	       { Use heap space if needed	}

    _CurVector00 : pointer;	       { Interrupt vectors altered	}
    _CurVector02 : pointer;	       { by Turbo Pascal and the	}
    _CurVector1B : pointer;	       { Ctrl/Break handler.		}
    _CurVector23 : pointer;
    _CurVector24 : pointer;
    _CurVector75 : pointer;

  { The following two macros implement a far and near call.  The	}
  { address of the procedure is on the stack, 4 bytes "above" the	}
  { address of the register structure parameter.  Upon return, the	}
  { address of the procedure is removed from the stack. 		}

  procedure __FCallPgm(ProcPtr : pointer; var Reg : registers);
		 Inline(
			 $8B/$DC       { mov  bx,sp			}
			/$83/$C3/$04   { add  bx,4			}
			/$36/$FF/$1F   { call dword ptr ss:[bx] 	}
			/$83/$C4/$04); { add  sp,4			}
  procedure __NCallPgm(ProcPtr : pointer; var Reg : registers);
		 Inline(
			 $8B/$DC       { mov  bx,sp			}
			/$83/$C3/$04   { add  bx,4			}
			/$36/$FF/$17   { call word ptr ss:[bx]		}
			/$83/$C4/$04); { add  sp,4			}

  procedure __ExecPgm (PathName  : _Path ;
			 CmdLine : string;
			FcbFlag  : boolean; var ErrorCode : word);
  procedure __DOSExPgm(  CmdLine : string;  var ErrorCode : word);
  procedure __SpawnPgm( ProgName : _Path;
			 CmdLine : string;  var ErrorCode : word);
  procedure __ShellPgm(var ErrorCode  : word);
  function  __WaitPgm (var ReturnType : byte) : byte;
  procedure __WinExPgm( ProgName : _Path;
			 CmdLine : string;
		     X1,Y1,X2,Y2 : byte;
	       ForeAttr,BackAttr : byte;
		   var ErrorCode : word);
  procedure __WinShPgm(      X1,Y1,X2,Y2 : byte;
		       ForeAttr,BackAttr : byte;
			   var ErrorCode : word);
  procedure __ExitRPgm(ErrorLevel : byte; HeapSize : longint);
  procedure __RemPgm  (   ProgSeg : word;
		       CheckHooks : boolean;
		      var ParsRem,
			ErrorCode : word);

implementation

  var
    WinUpper_	  : word;	       { Window coordinates for child	}
    WinLower_	  : word;	       { process.			}
    VideoAttr_	  : word;	       { Window attributes		}
    Prev10Vector_ : pointer;	       { Previous BIOS Video interrupt	}

  { __DOSPgm is an internal routine.  It invokes DOS function 4B.	}

  {$L dospgm.obj  }
  {$F+}
  procedure __DOSPgm(var Reg : registers); external;
  {$F-}

  {$I execpgm.imp }
  {$I dosexpgm.imp}
  {$I spawnpgm.imp}
  {$I shellpgm.imp}
  {$I waitpgm.imp }

  { __Int10Pgm is the internal BIOS Video interrupt service routine	}
  { used by __WinExPgm and __WinShPgm.					}

  {$L int10pgm.obj}
  procedure __Int10Pgm; external;

  {$I winexpgm.imp}
  {$I winshpgm.imp}
  {$I exitrpgm.imp}
  {$I rempgm.imp  }

  begin {Initialization}

    with _ExecMemory do 	       { Initialize the memory require- }
      begin			       { ments for EXEC.		}
	_MinMemory := 131072;	       { Minimum 128K needed for child	}
	_MinHeap   := 8192	       { Minimum 8K heap required for	}
      end;			       { parent process 		}
    _UseHeap := TRUE		       { Use heap space if available	}

  end.	{Initialization}
