macro_file WinExec;

#include winsmall.sh
#include mew_dlgs.sh
#include metools.sh
#include winexec.sh
#include shellapi.sh
#include idexe.sh

#DEFINE exec_use_semiphore 1

INT WinExecAndWait(STR Path, STR working_dir, INT flags, STR title,
        STR semiphore_file ) trans2
{
  int line_height = 0, font_height = 0, font_width = 0, dfont = 0;
  int main_dlg = 0, visibility = SW_ShowNormal, loop_res = 0;

  int InstanceID, result = _EXEC_Success;

  int using_semiphore = (svl(semiphore_file) != 0);

  int frame_is_enabled;
  int tr =refresh;

  int NoExec = ( Flags & _EP_FLAGS_NOEXEC );

  refresh = false;
  working;

  ExecErrorCode = 0;

  STRUCT TMsg Msg;

	switch ( flags & 0x000f0000 )
	{
		case _EP_FLAGS_HIDE :
										visibility = SW_Hide;
										break;

		case _EP_FLAGS_MINIMIZED :
										visibility = SW_ShowMinimized;
										break;

		case _EP_FLAGS_MAXIMIZED :
										visibility = SW_ShowMaximized;
										break;
	}

  call Build_Exec_Box;

  if(using_semiphore)
  {
    set_file_attr( semiphore_file, 0 );
    error_level = 0;
    del_file(semiphore_file);
    error_level = 0;
  }

  if ( NoExec ) {

    int Han;

    if ( S_Create_File( Path, Han ) == 0 ) {  // Create start file
      S_Close_File( Han );
    }
  }
  else {
    int param_index = xpos(" ", path, 1 );

    if(!param_index )
      param_index = svl(path) + 1;

      /*  this is still in the works.
    if(flags & _EP_FLAGS_VMEXEC )
    {
      struct vmdef vmd;
      title = "";             // title of window if in windowed mode
      exePath = copy(Path, 1,param_index - 1 );// Path of .exe to run.
      exeArgs = copy(Path, param_index + 1, 2048 ); // Argument list.
      workDir = working_dir;           // Working drive/dir.
      pifFlags = fPifWindow;           // PIF flags.
      disFlags = 0;           // Display flags.
      pageWant = 640 / 4;     // Desired V86 pages for VM.
      pageMin  = 300 / 4;     // Minimum V86 pages for VM.
      forePriority = 100;       // Foreground priority.
      backPriority = 50;       // Background priority.
      kbMaxEMS     = 4000;       // Maximum EMS KB.
      kbMinEMS     = 0;       // Minimum EMS KB.
      kbMaxXMS     = 4000;       // Maximum XMS KB.
      kbMinXMS     = 0;       // Minimum XMS KB.

      VMExec( &vmdef );
    }
    else
    */
    {

      InstanceID = ShellExecute(frame_handle,
                              "open",
                              copy(Path, 1,param_index - 1 ),
                              copy(Path, param_index + 1, 2048 ),
                              working_dir,
                              Visibility
                              );
    }


    if(InstanceID < 32) // a value less than 32 indicates an Exec error
    {
      call Kill_Exec_Box;
      ExecErrorCode = InstanceId;
      refresh = tr;
      return( _EXEC_Error );
    }
  }
  working;

  do
  {
    if( result == _EXEC_Success )
    {
      while( PeekMessage(&Msg,0,0,0,PM_REMOVE) )
      {
        if( Msg.Message == WM_QUIT)
        {
          PostMessage( msg.hwnd, msg.message, msg.wparam, msg.lparam );
          result = _EXEC_Abort;
          break;
        }

        if( !(flags & _EP_FLAGS_NOBYPASS) )
        {
          if ( msg.message == $400 )
          {
            if (( msg.wparam == 2 ) || (msg.wparam == 999))
            {
              result = _EXEC_Abort;
              break;
            }
          }
        }
        TranslateMessage(&Msg);
        DispatchMessage(&Msg);
        working;
      }
    }
    if( using_semiphore )
    {
      loop_res = file_exists( semiphore_file );
      if ( NoExec == False ) {
        if ( loop_res ) {
          loop_res = FALSE;
          using_semiphore = false;
        }
      }
    }
    else
      loop_res = (GetModuleUsage(InstanceID) == 0);
  }
  while ( ( !result ) && ( !loop_res ) );

  call Kill_Exec_Box;
  refresh = tr;
  return(result);

Build_Exec_Box:
  if( !(flags & _EP_FLAGS_NOBYPASS) )
  {
    main_dlg = Create_MEW_Dlg( "Executing...", "", frame_handle, 0);

    Get_MEW_Dlg_Metrics( main_dlg, line_height, font_height, font_width, dfont );


    int dc = GetDc( main_dlg );
    Selectobject( dc, dfont );

		if ( title == "" )
		{
			title = path;
		}

    int l = GetTextExtent( dc, title, svl(title) + 1) & 0xFFFF;
    if(l > 500)
    {
      l = 500;
    }
    if(l < 100)
      l = 100;
    ReleaseDC( main_dlg, dc );

    Create_MEW_Ctrl( "STATIC", "", SS_BLACKFRAME,1,7,l + 8 ,line_height * 3 + 6,main_dlg,1004,app_handle, 0);
    Create_MEW_Ctrl( "STATIC", title, SS_CENTER,font_width,10,l ,line_height * 3,main_dlg,1004,app_handle, 0);

    Create_MEW_Ctrl( "BUTTON", "Bypass", bs_defpushbutton ,(l / 2) - (font_width * 7),5 * line_height,font_width * 14,line_height + (font_height / 2),main_dlg,2,app_handle, 0);

    EnableWindow( main_dlg, TRUE );
    BringWindowToTop( main_dlg );
    ShowWindow( main_dlg, TRUE );
  }
  /* else
  {
    frame_is_enabled = IsWindowEnabled(frame_handle);
    if(frame_is_enabled)
      EnableWindow( frame_handle, false );
  } */
  ret;

Kill_Exec_Box:
  if(main_dlg != 0)
    destroy_mew_dlg( main_dlg )
  /* else
  {
    if(frame_is_enabled)
      EnableWindow(frame_handle, true );
  } */
  ret;

}



int DosExec( STR path,  STR working_dir, INT Visibility, STR stdio_file[128],
        stderr_file[128], INT flags ) trans2
{
  int tr = refresh,
      tw = window_id,
      result;
  int ohandle;

  str Out_File[128] = TempFileName( 'EXEC.OUT' );
  str Ini_File[128] = TempFileName( 'EXEC.INI' );
  str Semiphore_File[128] = TempFileName( 'EXEC.SEM' );
  str ExecRunFile[128] = TempFileName( 'DOSEXEC.RUN' );
  str StartFile[128] = TempFileName( 'EXEC.DOS' );

  int DosExecRunning = ( File_Exists( ExecRunFile ) == 1 );
  int ExecKeep = Global_Int( '@ExecKeep' );

  Refresh = FALSE;

  Create_Window;
  File_Name = Ini_File;

  put_line('/O=' +  stdio_file );
  down;
  put_line('/E=' + stderr_file );
  down;
  put_line('/C=' + path );
  down;

  if( exec_use_semiphore )
  {
    del_file(semiphore_file);
    put_line('/S=' + semiphore_file );
  }
  Down;
  Put_Line( '/R=' + Str( ( Global_Int( '@ExecNoDisplay' ) == 0 ) * 2 ) );
  if ( DosExecRunning == True ) {
    if ( Working_Dir == '' ) {
      Working_Dir = Get_Path( FExpand( '' ) );
      if ( ( Svl( Working_Dir ) > 3 ) &&
          ( Copy( Working_Dir, Svl( Working_Dir ), 1 ) == "\\" ) ) {
        Working_Dir = Copy( Working_Dir, 1, Svl( Working_Dir ) - 1 );
      }
    }
    Down;
    Put_Line( '/W=' + Working_Dir );
  }
  Down;
  Put_Line( '/K=' + Str( ExecKeep != -1 ) );

  save_file;

  delete_window;
  switch_win_id(tw);
  if ( DosExecRunning == True ) {       // DOSEXEC already running
    Flags |= _EP_FLAGS_NOEXEC;
    Result = WinExecAndWait( StartFile, Working_Dir, Flags, Path,
        Semiphore_File );
  }
  else {
    if ( ExecKeep > 0 ) {
      if ( S_Create_File( StartFile, OHandle ) == 0 ) {  // Create start file
        S_Close_File( OHandle );
      }
      StartFile = ' ' + StartFile;
    }
    else {
      StartFile = '';
    }
    if ( DosExecMethod == _DosExec_Direct ) {
      result = WinExecAndWait( me_path + 'DOSEXEC.EXE ' + ini_file + ' ' +
          out_file + StartFile, working_dir, flags, path, semiphore_file);
    }
    else
    {
    int fh;
    str pifn[128];

    pifn = CreateUserPath( 'DOSEXECX.PIF', false );

    int pifn_exists = (first_file( pifn ) == 0);

    if(pifn_exists)
    {
      int lfn = last_file_time;
      if(first_file( me_path + 'DOSEXEC.PIF' ) == 0)
      {
        if ( lfn < last_file_time )
        {
          pifn_exists = false;
        }
      }
    }

    if( !pifn_exists )
    {
      if( copy_file(me_path + 'DOSEXEC.PIF', pifn, false ) != 0)
      {
        pifn = me_path + 'DOSEXEC.PIF';
      }
    }

    if( s_open_file( pifn, 2, fh ) == 0)
    {
      if( s_move_file_ptr( fh, 0, 0x24 ) == 0)
      {
        int count;
        str tstr[80];
        s_read_bytes( tstr, fh, 63 );

        tstr = caps(shorten_str(tstr));
        if(get_path(tstr) != me_path)
        {
          if( s_move_file_ptr( fh, 0, 0x24 ) == 0)
          {
            tstr = me_path + truncate_path( tstr ) + char(0);
            pad_str(tstr, 63, ' ' );
            tstr = copy(tstr,1,63);
            count = 63;
            s_write_bytes( tstr, fh, count );
          }
        }
      }
      s_close_file(fh);
    }
    result = WinExecAndWait( pifn + ' ' + ini_file + ' ' + out_file + StartFile,
        working_dir, flags, path, semiphore_file);
    }
  }

  ExecReturnCode = 0;

  if( s_open_file( out_file, 0, ohandle ) == 0)
  {
    if( s_read_bytes( ini_file, ohandle, 127 ) == 0)
    {
      ExecReturnCode = parse_int("/RETURN_CODE=", ini_file );
    }
    s_close_file( ohandle );
  }

  refresh = tr;
  return(result);
}

int Os2Exec( str Path,  str Working_Dir, int Visibility, str Stdio_File[128],
        str Stderr_File[128], int Flags ) Trans2
{
  int TRefresh = Refresh;
  int OrgWinId = Window_Id;
  int Result;
  int ExecKeep = Global_Int( '@ExecKeep' );
  int OHandle;

  str Out_File[128] = TempFileName( 'EXEC.OUT' );
  str Ini_File[128] = TempFileName( 'EXEC.INI' );
  str Semiphore_File[128] = TempFileName( 'EXEC.SEM' );
  str StartFile[128] = TempFileName( 'EXEC.OS2' );
  str ExecRunFile[128] = TempFileName( 'OS2EXEC.RUN' );

  Refresh = False;
  Create_Window;
  File_Name = Ini_File;

  Put_Line( '/O=' +  Stdio_File );
  Down;
  Put_Line( '/E=' + Stderr_File );
  Down;
  Put_Line( '/C=' + Path );
  Down;
  Del_File( Semiphore_File );
  Put_Line( '/S=' + Semiphore_File );
  Down;
  Put_Line( '/R=' + Str( ( Global_Int( '@ExecNoDisplay' ) == 0 ) * 2 ) );
  Down;
  if ( Working_Dir == '' ) {
    Working_Dir = Get_Path( FExpand( '' ) );
    if ( ( Svl( Working_Dir ) > 3 ) &&
        ( Copy( Working_Dir, Svl( Working_Dir ), 1 ) == "\\" ) ) {
      Working_Dir = Copy( Working_Dir, 1, Svl( Working_Dir) - 1 );
    }
  }
  Put_Line( '/W=' + Working_Dir );
  Down;
  Put_Line( '/K=' + Str( ExecKeep != -1 ) );

  Save_File;
  Delete_Window;
  Switch_Win_Id( OrgWinId );

  if ( File_Exists( ExecRunFile ) == 1 ) {  // OS2EXEC already running
    Flags |= _EP_FLAGS_NOEXEC;
    Result = WinExecAndWait( StartFile, Working_Dir, Flags, Path,
        Semiphore_File );
  }
  else {
    if ( ExecKeep > 0 ) {
      if ( S_Create_File( StartFile, OHandle ) == 0 ) {  // Create start file
        S_Close_File( OHandle );
      }
      StartFile = ' ' + StartFile;
    }
    else {
      StartFile = '';
    }
    Result = WinExecAndWait( Me_Path + 'OS2EXEC.EXE ' + Ini_File + ' ' +
        Out_File + StartFile, Working_Dir, Flags, Path, Semiphore_File);
  }
  ExecReturnCode = 0;
  if ( S_Open_File( Out_File, 0, OHandle ) == 0 ) {
    if ( S_Read_Bytes( Ini_File, OHandle, 127 ) == 0 ) {
      ExecReturnCode = Parse_Int( '/RETURN_CODE=', Ini_File );
    }
    S_Close_File( OHandle );
  }
  Refresh = TRefresh;
  return( Result );

}  // Os2Exec

int ExecProg( str prog[128] = parse_str("/PROG=", mparm_str),
              str working_dir[128] = parse_str("/WD=",mparm_str),
              str stdout_file[128] = parse_str("/RED=", mparm_str),
              str stderr_file[128] = parse_str("/REDERR=", mparm_str),
              int flags = parse_int("/FLAGS=", mparm_str ) )
{

  str cmd_line[128], tstr, tdir[128] = Fexpand("");
  str Ext[ 3 ];

  int jx,
      result = 0,
      cmd = ((flags & _EP_FLAGS_COMSPEC ) != 0);
  int BoundAsDos = ( ( Flags & _EP_FLAGS_BNDASDOS ) != 0 );

  ExecReturnCode = 0;
  ExecErrorCode = 0;

	set_global_int('MENU_LEVEL',global_int('MENU_LEVEL') + 1); //prevents autosave

  prog = TranslateCmdLine( prog,file_name );
  jx = xpos(' ', prog, 1 );
	if(  jx > 0  ) {
    cmd_line = copy(prog, jx, 128 );
    prog = copy( prog, 1, jx - 1 );
	}

  if ( Cmd == 0 ) {
    Ext = Caps( Get_Extension( Prog ) );
    if ( ( Ext == 'BAT' ) || ( Ext == 'CMD' ) ) {
      Cmd = 1;
    }
  }
  if ( Get_Path( Prog ) == '' ) {
    TStr = ExecSearchPath( Prog, Get_Environment( 'PATH' ) );
    if ( TStr != '' ) {
      Prog = TStr;
      Ext = Caps( Get_Extension( TStr ) );
      if ( ( Ext == 'BAT' ) || ( Ext == 'CMD' ) ) {
        Cmd = 1;
      }
    }
    else {
      Cmd = 1;
    }
	}

  if(stdout_file ==  "")
	{
    stdout_file = "NUL";
	}

  if(stderr_file ==  "")
	{
    stderr_file = "NUL";
	}

  if(flags & _EP_FLAGS_WDPROG )
  {
    working_dir = get_path( prog );
  }

  if ( working_dir != "" )
  {
    if(svl(working_dir) > 3)
    {
      if(copy(working_dir,svl(working_dir),1) == '\')
      {
        working_dir = copy(working_dir,1,svl(working_dir) - 1);
      }
    }
  //  Change_Dir(  working_dir );
  }

  ExecId = IdExe( Prog );
  if ( ( ExecId == ( _Exe_Id_Bound | _Exe_Id_Os2 ) ) &&
      ( BaseOs != _BaseOs_Os2 ) ) {
    BoundAsDos = True;
  }
  if ( BoundAsDos ) {
    if ( ( ExecId & _Exe_Id_Bound ) != 0 ) {
      ExecId = _Exe_Id_Dos;
    }
  }
  ExecId &= ( 0xFFFF ^ _Exe_Id_Bound );
  if ( Cmd ) {
    if ( ( BaseOs == _BaseOs_Os2 ) && ( ExecId == _Exe_Id_Os2 ) ) {
      Result = Os2Exec( '%COMSPEC /C ' + Prog + Cmd_Line, Working_Dir,
          sw_ShowNormal, Stdout_File, Stderr_File, Flags );
    }
    else {
      result = DosExec( comspec + ' /C ' + prog + cmd_line, working_dir,
          sw_shownormal, stdout_file, stderr_file, flags );
    }
  }
  else {
    if ( ExecId == _Exe_Id_Dos ) {
      result = DosExec( prog + cmd_line, working_dir, sw_shownormal,
          stdout_file, stderr_file, flags );
    }
    else if ( ( BaseOs == _BaseOs_Os2 ) && ( ExecId == _Exe_Id_Os2 ) ) {
      Result = Os2Exec( Prog + Cmd_Line, Working_Dir, sw_ShowNormal,
          Stdout_File, Stderr_File, Flags );
    }
    else {
//         if( ExecId == _EXE_ID_Windows )
      result = WinExecAndWait( prog  + cmd_line, working_dir,
                            flags, '' , '');
    }
 //   else
 //   {
 //     RM("MessageBox /T=ERROR/M=" + prog + " is an unknown executable format.");
 //     result = -1;
 //   }
  }


  if ( working_dir != "" )
  {
    if(svl(tdir) > 3)
    {
      if(copy(tdir,svl(tdir),1) == "\\")
      {
        tdir = copy(tdir,1,svl(tdir) - 1);
      }
    }
    Change_Dir(  tdir );
  }

	set_global_int('MENU_LEVEL',global_int('MENU_LEVEL') - 1); //prevents autosave
  return(result);
}


macro EXEC TRANS2 {
/*******************************************************************************
																MULTI-EDIT MACRO

Name: EXEC

Description:  Executes a DOS command or program

Parameters:
              Return_Str = the command line
							/CMD=1		Use COMMAND.COM (or COMSPEC equivalent).
											/WAIT=1   Wait for a key
											/CMDLN=1  Write the command line in the window.
							/RED=str  Redirect stdout to file str
							/REDERR=str Redirect stderr to file str.

									NOTE:  To redirect STDERR to the same file as STDOUT, simply specify
												 /REDERR=STDOUT

							/APPEND=1 Append redirect file instead of overwrite.

Returns:			The exit code of the DOS command or program will be in the
							integer EXIT_CODE.

							 (C) Copyright 1991 by American Cybernetics, Inc.
*******************************************************************************/

  int flags = 0;

  if ( parse_int("/CMD=", mparm_str) == 1 )
  {
    flags |= _EP_FLAGS_COMSPEC;
  }
  if( parse_int("/APPEND=", mparm_str) == 1)
  {
    flags |= _EP_FLAGS_APPEND;
  }


  return_int = ExecProg( return_str, "",parse_str("/RED=", mparm_str),
                         parse_str("/REDERR=", mparm_str),
                         flags );
}

str ExecSearchPath( str Program, str FPath ) {
/*******************************************************************************
Description: Searches for a filename in a given path
            TranslateCmdLine is called to parse out any metacommands BEFORE
            the search takes place.  When extension is blank will try to find
            an executable file .COM .EXE .BAT .CMD

Returns:    complete path and filename, or a NUL string if
            the search was not successful.

*******************************************************************************/

  str TPath ;
  str Ext = "COMEXEBATCMD";
  str TProg;

  int Jx;
  int Jy = 0;
  int NoExt;
  int ExtLen = Svl( Ext );

  Program = TranslateCmdLine( Program, "" );
  TPath = TranslateCmdLine( FPath, "" );
  FPath = "";
  NoExt = Get_Extension( Program ) == "";
  while ( True ) {
    if ( NoExt ) {
      for ( Jx = 1; Jx < ExtLen; Jx = Jx + 3 ) {
        TProg = Program + "." + Copy( Ext, Jx, 3 );
        if ( File_Exists( FPath + TProg ) ) {
          return ( FExpand( FPath + TProg ) );
        }
      }
    }
    else {
      if ( File_Exists( FPath + Program ) ) {
        return ( FExpand( FPath + Program ) );
      }
    }
    if ( Jy > Svl( TPath ) ) {
      return ( "" );
    }
    Jx = XPos( ";", TPath, Jy + 1 );
    if ( Jx == 0 ) {
      Jx = Svl( TPath ) + 1;
    }
    FPath = Copy( TPath, Jy + 1, Jx - Jy - 1 );
    if ( ( Svl( FPath ) > 0 ) && ( Copy( FPath, Svl( FPath ), 1 ) != "\\" ) ) {
      FPath = FPath + "\\";
    }
    Jy = Jx;
  }
}  // ExecSearchPath
