//+++keyword+++ "@(#)%v %n, %f, %w"
// "@(#)8 SSAFE.S, 04-Feb-95,01:36:46, LDH"

macro_file SSAFE;
/******************************************************************************
                             Multi-Edit Macro File
                               15-Aug-93  02:08

  This macro is the specific interface code for the VCS pakcage SourceSafe by
  One Tree Software

  SSafeExt     -
  SSafeLFile   -
  SSafeChkLib  -
  SSafeCmds    - The SourceSafe command interface.
  SSafeFile    - Creates a file dialog box for the SourceSafe VCS package.
  SSafeLogin   - Check if a SourceSafe user is logged in, and prompts if not.

                 Copyright (C) 1994 by Small Systems Support.
********************************************************************( ldh )***/

#include WINSMALL.SH
#include DIALOG.SH
#include WINEXEC.SH
#include IDEXE.SH
#include FPROMPT.SH
#include MEWLIST2.SH
#include EXIT.SH
#include METOOLS.SH
#include DBTOOLS.SH
#include DB.SH
#include VCS.SH

#ifdef   _DEBUG_
  #include DBUG.SH                      // Dbug macros
  #include SPRINTF.SH
#endif

#ifdef  _BETA_
  #define _SSAFE_VER   "7.00p(0.09b)á"
#else
  #define _SSAFE_VER   "7.00p(0.09b)"
#endif

prototype SSafe {
  int  SSafeExec( str CmdLine, int Show_Win, int Chg_Dir );
  str  SSafeXlate( str Path, str FName, str Project );
  str  SSafeExt( str FName );
  int  SSafeChkLib( str Project, str FName, int Pm );
  str  SSafeGetFName( str LibFile );
  int  SSafeChkLock( );
  int  SSafeLogin( int Chg_Usr );
  str  SSafeLookup( str FName, str Field1, str Field2 );
  str  SSafeCfgFile( str FName, str Param );
  int  SSafeCmds( str Cmd, str FName, str Project );
  int  SSafeGetPrj( str &Project, int Change );
  int  SSafeGetLib( str FName );
  void SSafeParseErr( );
  str  SSafeGetUser( );
  int  SSafeGetDirFile( int NewScan, int ChkOnly );
  int  SSafeUpdDirFile( str FName, str FStr );
  // Dialog macros in SSAFE.SWI
  int  SSafeFileSelPrj( str &Project, int Change );
  int  SSafeFileSetLst( str &Project, int hDlg, int FWOnly, int NewScan );
  void SSafeFileBtnProc( );
  void SSafeFileCmds( );
  int  SSafeFileMsgProc( int &RetVal, int Window, int Message, int WParam,
          int LParam, str Parms );
  void SSafeFileDlg( str Title, str Project );
}

global {
  str ssafeDirFile     "&ssafeDirFile";
  str ssafeUser        "&ssafeUser";    // Contains the current user name
  str ssafeUsr1        "&ssafeUsr1";    // Contains the original user name
  str ssafeIni         "&ssafeIni";     // Contains the SRCSAFE.INI file path
  str ssafePrj         "&ssafePrj";     // Contains the current project
  str ssafePwd         "&ssafePwd";     // Contains the temporary user password
  str ssafeCfg         "!ssafeCfg";     // Contains the command/setup options
  str ssafeLUT         "!ssafeLUT";     // Contains the LOOKUP data record
  str ssafeFUsr        "!ssafeFUsr";
  int ssafeRDir        "!ssafeRDir";
}

#include SSAFE.SWI                      // Include Windows dialog macros


macro SSafe Trans {
/******************************************************************************
                               Multi-Edit Macro
                               15-Sep-94  21:25

  Name    : SSafe

  Function: Checks that the GET executable is found and initilizes SourceSafe
            support.

  Syntax  : Rm( "SSafe /I" );

  Entry   : /I              - Initialize the system if checks pass.

  Exit    : Return_Int
              False         - SrcSafe support not installed and checks failed.
              True          - SrcSafe support installed and checks passed.

            gstr !vcsVerStr - "SSAFE " + macro version number.
            gstr !vcsRevStr - macro revision number.

  Globals : int !vcsNoMenu  - True disables most of the menu commands.
            int !vcsNoAct   - True disables the interactive menu command.
            int !vcsNoCUId  - True disables the change use Id menu command.
            str !vcsVerStr  - Returns the string "SSAFE " + macro version no.
            str !vcsRevStr  - Returns the macro revision number.

  Macros  : int VcsChkVer
            mac PathSearch

                 Copyright (C) 1994 by Small Systems Support.
********************************************************************( ldh )***/

//+++keyword+++ "@(#)%v %n, %f, %w"
  str Rev_Id = "@(#)8 SSAFE.S, 04-Feb-95,01:36:46, LDH";
  str Cmd = Copy( _GET_CMDL, 1, XPos( " ", _GET_CMDL, 1 ) - 1 );

  // Check for get command EXE file
  Return_Str = ExecSearchPath( Cmd, "<%PATH>" );
  Return_Int = ( Return_Str != "" );
  if ( Return_Int ) {
    if ( VcsChkVer( _SSAFE_VER ) ) {
      if ( XPos( "/I", MParm_Str, 1 )) {  // Initialize?
        vcsDoLogin = True;              // Enable change user ID menu item
        if ( ssafeUser == "" ) {
          if ( !( Return_Int = SSafeLogin( False ) ) ) {
            Error_Level = 9012;         // Set login error
          }
        }
      }
    }
    else {
      Error_Level = 9011;               // Set version error
    }
  }
  else {
    Error_Level = 9010;                 // Set no EXE found error
  }
  vcsVerStr = "SSAFE " + _SSAFE_VER;
  vcsRevStr = Rev_Id;

}  // SSafe

macro SSafeView Trans2 {
/******************************************************************************
                               Multi-Edit Macro
                               18-Aug-93  22:49

  Name    : SSafeView

  Function: The SourceSafe specific view macro to view the changes to the
            current work file compared to the latest revision in the archive.

  Syntax  : Rm( "SSafeView" );

  Entry   : gstr !vcsFName  - Filename of file to compare
            gint !vcsLibFnd - Set True if archive found.

  Exit    : Return_Int
              True          - No Error
              False         - ( Error_Level == 0 ) Cancelled
                              ( Error_Level != 0 ) Error

  Globals : str !vcsFName   - The work file name.
            int !vcsLibFnd  - The archive found status (True = found).
            str !vcsDlgMsg  - The dialog message when calling VcsGetLib.
            str !vcsMsg     - The status line message when exec is run.
            str !ssafeCfg   - The SSAFE specific command/setup options.
            str !vcsName    - The vcs temp file name.


  Macros  : int  SSafeGetLib
            int  SSafeExec
            mac  CDiff
            void VcsViewWinDlg

                Copyright (C) 1990-94 by Small Systems Support.
********************************************************************( ldh )***/

  str FName = Truncate_Path( vcsFName );
  str TFName = TempFileName( FName );

  int Frn = False;

  if ( !vcsLibFnd ) {
    vcsDlgMsg = "(SSAFE) VIEW Project.";
    if ( !vcsLibFnd = SSafeGetLib( vcsFName )) {
      vcsMsg = "SSAFE archive for \"" + FName + "\" not found.";
      Error_Level = 3002;
      Return_Int = False;
    }
  }
  if ( vcsLibFnd ) {
    Working;
    if ( Switch_File( vcsFName )) {
      if ( File_Changed ) {
        Rm( "SaveFile /NP=1" );
      }
    }
    if ( _RVC ) {
      if ( File_Exists( TFName )) {
        Set_File_Attr( _VCS3_TMP, 0 );
        Del_File( _VCS3_TMP );
        Rename_File( TFName, _VCS3_TMP );
        Frn = True;
      }
    }
    vcsMsg = "Viewing changes made to \"" + FName + "\"...";
    vcsDlgMsg = "(SSAFE) VIEW Command Line.";
    if ( Return_Int = SSafeExec( _VIEW_CMDL, _DISP_WIN, _DO_CD )) {
      if ( _RVC ) {
        Rm( "CDiff /F=" + TFName + "/D=" + str( !_CDIF ));
        if ( Return_Int == 1 ) {
          vcsMsg = "Files the same.";
        }
        else {
          vcsMsg = "CDIFF complete.";
        }
        Set_File_Attr( TFName, 0 );
        Del_File( TFName );
        Return_Int = True;
      }
      else if ( Switch_File( vcsName )) {
        Return_Int = False;
        Error_Level = 0;
        if ( vcsNameLoaded == False ) {
          Load_File( vcsName );
        }
        if ( !Error_Level ) {
          VcsViewWinDlg( "(SSAFE) Differences of " + Truncate_Path( vcsFName ),
              100, 18, "", hc_vcs_View );
          vcsMsg = "SSAFE VIEW command complete.";
          Return_Int = True;
        }
      }
    }
    if ( Frn ) {
      Rename_File( _VCS3_TMP, TFName );
    }
  }
}  // SSafeView

macro SSafeList Trans2 {
/******************************************************************************
                               Multi-Edit Macro
                               18-Aug-93  22:49

  Name    : SSafeList

  Function:

  Syntax  :

  Entry   :

  Exit    : Return_Int
              True          - No Error
              False         - ( Error_Level == 0 ) Cancelled
                              ( Error_Level != 0 ) Error

  Globals :

  Macros  :

                Copyright (C) 1990-94 by Small Systems Support.
********************************************************************( ldh )***/

  str FName = Truncate_Path( vcsFName );

  if ( !vcsLibFnd ) {
    vcsDlgMsg = "(SSAFE) LIST Project.";
    if ( !vcsLibFnd = SSafeGetLib( vcsFName )) {
      vcsMsg = "SSAFE archive for \"" + FName + "\" not found.";
      Error_Level = 3002;
      Return_Int = False;
    }
  }
  if ( vcsLibFnd ) {
    vcsMsg = "Listing versions of \"" + Truncate_Path( vcsFName ) + "\"...";
    vcsDlgMsg = "(SSAFE) LIST Command Line.";
    if ( Return_Int = SSafeExec( _LIST_CMDL, _DISP_WIN, False ) ) {  // No vcs errors
      if ( Switch_File( vcsName ) ) {
        Return_Int = False;
        Error_Level = 0;
        if ( vcsNameLoaded == False ) {
          Load_File( vcsName );
        }
        if ( !Error_Level ) {
          Right_Margin = 70;
          while ( Find_Text( "Comment: ", 0, 0 ) ) {
            Word_Wrap_Line( True, False );
          }
          if ( File_Changed == True ) {

            int TSave = Save_Resets_Changed;

            Save_Resets_Changed = True;
            Save_File;
            Save_Resets_Changed = TSave;
          }
          Tof;
          VcsViewWinDlg( "(SSAFE) Versions of " + Truncate_Path( vcsFName ),
              100, 18, "BT_VCS_109", hc_vcs_List );
          vcsMsg = "SSAFE LIST command complete.";
          Return_Int = True;
        }
      }
    }
  }
}  // SSafeList

macro SSafeLock Trans2 {
/******************************************************************************
                               Multi-Edit Macro
                               18-Aug-93  22:49

  Name    : SSafeLock

  Function:

  Syntax  :

  Entry   :

  Exit    : Return_Int
              True          - No Error
              False         - ( Error_Level == 0 ) Cancelled
                              ( Error_Level != 0 ) Error

  Globals :

  Macros  :

                Copyright (C) 1990-94 by Small Systems Support.
********************************************************************( ldh )***/

  str FName = Truncate_Path( vcsFName );

  int Frn = False;

  if ( !vcsLibFnd ) {
    vcsDlgMsg = "(SSAFE) LOCK Project.";
    if ( !vcsLibFnd = VcsGetLib( vcsFName ) ) {
      vcsMsg = "SSAFE archive for \"" + FName + "\" not found.";
      Error_Level = 3002;
      Return_Int = False;
    }
  }
  if ( vcsLibFnd ) {
    if ( Return_Int = !SSafeChkLock( ) ) {
      if ( File_Exists( vcsFName ) ) {
        Set_File_Attr( _VCS3_TMP, 0 );
        Del_File( _VCS3_TMP );
        Rename_File( vcsFName, _VCS3_TMP );
        Frn = True;
      }
      vcsMsg = "Locking \"" + vcsFName + "\"...";
      vcsDlgMsg = "(SSAFE) LOCK Command Line.";
      Return_Int = SSafeExec( _LOCK_CMDL, _DISP_WIN, _DO_CD );
      if ( Return_Int ) {
        vcsDlgMsg = "\x7F" + "F=" + FName + "\x7F" + "U=" + ssafeUser +
            "\x7F" + "D=" + Date + " ";
        Return_Str = Time;
        Return_Str = Copy( Return_Str, 1, Length( Return_Str ) - 5 ) +
            Lower( Copy( Return_Str, Length( Return_Str ) - 1, 1 ) );
        vcsDlgMsg += Return_Str + "\x7F" + "WD=" + Get_Path( vcsFName );
        SSafeUpdDirFile( vcsAFile, vcsDlgMsg );
      }
      if ( Frn ) {
        if ( Return_Int ) {
          Rename_File( _VCS3_TMP, vcsFName );
        }
        else {
          int Sel = Error_Level;

          Set_File_Attr( _VCS3_TMP, 0 );
          Del_File( _VCS3_TMP );
          Error_Level = Sel;
        }
      }
    }
  }
}  // SSafeLock

macro SSafeGet Trans2 {
/******************************************************************************
                               Multi-Edit Macro
                               18-Aug-93  22:49

  Name    : SSafeGet

  Function:

  Syntax  :

  Entry   :

  Exit    : Return_Int
              True          - No Error
              False         - ( Error_Level == 0 ) Cancelled
                              ( Error_Level != 0 ) Error

  Globals :

  Macros  :

                Copyright (C) 1990-94 by Small Systems Support.
********************************************************************( ldh )***/

  str Vcs_Cmd[ 128 ];
  str FName = Truncate_Path( vcsFName );
  str Cmd[ 20 ] = Parse_Str( "/C=", MParm_Str );

  int Fw = 0;
  int Frn = False;
  int Sel;

  if ( !vcsLibFnd ) {
    vcsDlgMsg = "(SSAFE) " + Cmd + " Project.";
    if ( !vcsLibFnd = SSafeGetLib( vcsFName ) ) {
      vcsMsg = "SSAFE archive for \"" + FName + "\" not found.";
      Error_Level = 3002;
      Return_Int = False;
    }
  }
  if ( vcsLibFnd ) {
    Return_Int = True;
    if ( Cmd == "GET" ) {
      Return_Int = !SSafeChkLock( );
      Vcs_Cmd = _GET_CMDL;
    }
    else {
      Vcs_Cmd = _BROWSE_CMDL;
    }
    if ( Return_Int ) {
      if ( File_Name == vcsFName ) {
        Frn = True;
      }
      else if ( Switch_File( vcsFName ) ) {
        Frn = True;
      }
      if ( Frn ) {
        if ( !Read_Only || vcsDF || ( Truncate_Path( File_Name ) != FName ) ) {
          Rm( "Verify /H=" + hc_vcs_Verify + "/T=" + vcsFName +
              " Already loaded, OVERWRITE? /BL= ARE YOU SURE? " );
        }
        if ( Return_Int ) {
          Fw = Window_Id;
          VcsPushPos( );
          Erase_Window;
        }
      }
      else if ( File_Exists( vcsFName ) ) {
        Rm( "Verify /H=" + hc_vcs_Verify + "/T=" + vcsFName +
            " Already exists, OVERWRITE? /BL= ARE YOU SURE? " );
      }
    }
    if ( Return_Int ) {
      Frn = False;
      if ( File_Exists( vcsFName ) ) {
        Set_File_Attr( _VCS3_TMP, 0 );
        Del_File( _VCS3_TMP );
        Rename_File( vcsFName, _VCS3_TMP );
        Frn = True;
      }
      vcsMsg = "Retrieving \"" + vcsFName + "\"...";
      vcsDlgMsg = "(SSAFE) " + Cmd + " Command Line.";
      if ( Return_Int = SSafeExec( Vcs_Cmd, _DISP_WIN, _DO_CD ) ) {
        if ( Frn ) {
          Sel = Error_Level;
          Set_File_Attr( _VCS3_TMP, 0 );
          Del_File( _VCS3_TMP );
          Error_Level = Sel;
        }
        if ( Cmd == "GET" ) {
          vcsDlgMsg = "\x7F" + "F=" + FName + "\x7F" + "U=" + ssafeUser +
              "\x7F" + "D=" + Date + " ";
          Return_Str = Time;
          Return_Str = Copy( Return_Str, 1, Length( Return_Str ) - 5 ) +
              Lower( Copy( Return_Str, Length( Return_Str ) - 1, 1 ) );
          vcsDlgMsg += Return_Str + "\x7F" + "WD=" + Get_Path( vcsFName );
          SSafeUpdDirFile( vcsAFile, vcsDlgMsg );
        }
      }
      else {                            // error, restore file
        if ( Frn ) {
          Rename_File( _VCS3_TMP, vcsFName );
        }
        if ( Switch_Win_Id( Fw ) ) {
          Sel = Error_Level;
          Error_Level = 0;
          Load_File( vcsFName );
          if ( !Error_Level ) {
            Rm( "ExtSetup" );
          }
          VcsPopPos( True );
          Error_Level = Sel;
          Return_Int = False;
        }
      }
    }
  }
}  // SSafeGet

macro SSafePut Trans2 {
/******************************************************************************
                               Multi-Edit Macro
                               18-Aug-93  22:49

  Name    : SSafePut

  Function: The SourceSafe specific CREATE/PUT/UNLOCK commands.

  Syntax  :

  Entry   :

  Exit    : Return_Int
              True          - No Error
              False         - ( Error_Level == 0 ) Cancelled
                              ( Error_Level != 0 ) Error
  Globals :

  Macros  :

                Copyright (C) 1990-94 by Small Systems Support.
********************************************************************( ldh )***/

  str Vcs_Cmd[ 128 ];
  str Cmd[ 20 ] = Parse_Str( "/C=", MParm_Str );
  str FName[ 12 ] = Truncate_Path( vcsFName );
  str SavPrj;

  int Sel;
  int Sri;
  int Fw = 0;
  int Ow = 0;
  int Get_Cmt = False;
  int Chg_Prj = False;

  Return_Int = True;
  if ( vcsChkMod != "V" ) {
    Return_Int = !SSafeChkLock( );
  }
  if ( Return_Int ) {
    if ( File_Name == vcsFName ) {
      Fw = Window_Id;
    }
    else if ( Switch_File( vcsFName ) ) {
      Fw = Window_Id;
    }
    if ( Fw ) {
      VcsPushPos( );
    }
    if ( vcsChkMod == "V" ) {
      if ( Window_Id == Fw ) {
        Erase_Window;
      }
      if ( File_Exists( vcsFName ) ) {
        Set_File_Attr( vcsFName, 0 );
        Del_File( vcsFName );
      }
    }
    else {
      if ( !vcsLibFnd ) {
        vcsDlgMsg = "(SSAFE) " + Cmd + " Project.";
        vcsLibFnd = SSafeGetLib( vcsFName );
        Return_Int = !Error_Level;
        Error_Level = 0;
      }
      if ( Return_Int ) {
        if ( Cmd == "PUT" ) {
          Get_Cmt = True;
          if ( !vcsLibFnd ) {
            Cmd = "CREATE";
          }
          if ( !Fw ) {
            Ow = Window_Id;
            Switch_Window( Window_Count );
            Create_Window;
            Load_File( vcsFName );
            Fw = Window_Id;
          }
        }
        Return_Int = True;
        switch ( Cmd ) {
          case "CREATE":
            if ( vcsAFile != ssafePrj ) {
              SavPrj = ssafePrj;
              vcsMsg = "Changing to SSAFE project " + vcsAFile + "...";
              if ( Return_Int = SSafeCmds( "CP", "", vcsAFile ) ) {
                Chg_Prj = True;
              }
            }
            Vcs_Cmd = _CREATE_CMDL;
            vcsMsg = "Creating \"" + Get_Path( vcsAFile ) + FName + "\" ...";
            vcsDlgMsg = "(SSAFE) Describe \"" + FName + "\".";
            break;

          case "PUT":
            Vcs_Cmd = _PUT_CMDL;
            vcsMsg = "Storing \"" + FName + "\" in \"" + Get_Path( vcsAFile ) +
                FName + "\"...";
            vcsDlgMsg = "(SSAFE) Describe changes to \"" + FName + "\".";
            break;

          case "UNLOCK":
            Vcs_Cmd = _UNLOCK_CMDL;
            vcsMsg = "Unlocking \"" + Get_Path( vcsAFile ) + FName + "\"...";
            break;
        }
        if ( Return_Int  ) {
          if ( Get_Cmt ) {
            Return_Int = VcsGetCmt( True, False );
          }
        }
        if ( Return_Int ) {
          if ( Fw ) {
            Erase_Window;
          }
          vcsDlgMsg = "(SSAFE) " + Cmd + " Command Line.";
          if ( Return_Int = SSafeExec( Vcs_Cmd, _DISP_WIN, _DO_CD ) ) {
            if ( File_Exists( vcsFName ) ) {
              if ( _DEL_SRC ) {
                Sel = Error_Level;
                Set_File_Attr( vcsFName, 0 );
                Del_File( vcsFName );
                Error_Level = Sel;
              }
              else if ( Cmd == "UNLOCK" ) {
                Set_File_Attr( vcsFName, 0x01 );  // force file readonly
              }
            }
            if ( Ow ) {
              Delete_Window;
              Switch_Win_Id( Ow );
            }
            vcsDlgMsg = "\x7F" + "F=" + FName;
            SSafeUpdDirFile( vcsAFile, vcsDlgMsg );
          }
          else {                        // error, reload file
            if ( Switch_Win_Id( Fw ) ) {
              Sel = Error_Level;
              Error_Level = 0;
              Load_File( vcsFName );
              if ( Error_Level == 0 ) {
                if ( Get_Cmt && vcsChgFlg ) {
                  VcsPutCmt( False );
                }
                Rm( "ExtSetup" );
              }
              Get_Cmt = True;
              if ( Ow ) {
                Delete_Window;
                Switch_Win_Id( Ow );
                Get_Cmt = False;
              }
              VcsPopPos( Get_Cmt );
              Error_Level = Sel;
              Return_Int = False;
            }
          }
        }
        if ( Chg_Prj ) {
          Sel = Error_Level;
          Sri = Return_Int;
          vcsMsg = "Changing to SSAFE project " + SavPrj + "...";
          SSafeCmds( "CP", "", SavPrj );
          Return_Int = Sri;
          Error_Level = Sel;
        }
      }
    }
  }
}  // SSafePut

int SSafeExec( str CmdLine, int Show_Win, int Chg_Dir ) Trans2 {
/******************************************************************************
                               Multi-Edit Macro
                               15-Sep-94  21:42

  Name    : SSafeExec

  Function: Execute the SSAFE command in cmdline.

  Syntax  : pass = SSafeExec( CmdLine, Show_Win, Chg_Dir );

  Entry   : str CmdLine
            int Show_Win
            int Chg_Dir
            gstr !vcsFName
            gstr !vcsAFile
            gint !vcsSNCL

  Exit    : int
              True            - No Error.
              False           - ( Error_Level == 0 ) Cancelled
                                ( Error_Level = Error number ) Error
                gstr !vcsMsg  - Error message  ( Only when Error_Level != 0 )

            gstr !vcsDlgMsg   - Cleared.

  Globals : str !vcsFName   - Contains the work file name.
            str !vcsAFile   - Contains the archive file name.
            int !vcsSNCL    - Flag to not show cmdline dialog ( True ).
            str !vcsCfg     - Contains the main vcs config options.
            str !vcsMsg     - Contains the status line message.
            str !vcsName    - Contains the vcs temp file name.
            str !vcsDlgMsg  - Contains the show cmdline dialog message.

  Macros  : str SSafeXlate
            int VcsEditStrDlg
            int ExecProg

                Copyright (C) 1990-94 by Small Systems Support.
********************************************************************( ldh )***/

  int Result = True;
  int Ow = Window_Id;
  int Srf = Refresh;

  Refresh = False;
  CmdLine = SSafeXlate( CmdLine, vcsFName, vcsAFile );
  Error_Level = 0;
  if ( vcsSNCL ) {
    if ( Check_Key && ( ( Key1 == 27 ) && ( Key2 == 1 ) ) ) {
      Result = False;
    }
  }
  else if ( _SHOW_CMD ) {
    Result = VcsEditStrDlg( vcsDlgMsg, CmdLine, False );
  }
  if ( Result ) {
    Set_File_Attr( vcsName, 0 );
    Del_File( vcsName );                // Erase tmp capture file
    Result = False;
    Working;
    Make_Message( vcsMsg );
    vcsMsg = "";
    if ( XPos( "SSWCL.EXE", CmdLine, 1 ) || Xpos( "SS.EXE", CmdLine, 1 ) ) {
      if ( ssafeUser != ssafeUsr1 ) {
        CmdLine += " -Y" + ssafeUser + SIf( ssafePwd != "", "," + ssafePwd, "" );
      }
    }
// DBWin( "SSafeExec Before ExecProg Ow=%d Cw=%d", Ow, Window_Id );
    Error_Level = ExecProg( CmdLine, vcsPrjDir, vcsName, vcsName,
        _EP_FLAGS_NOBYPASS );
//     if ( Window_Id != Ow ) {            // DBug
//       Beep;
//       DBug( "SSafeExec Error! Ow=%d Cw=%d", Ow, Window_Id );  // DBug
//     }                                   // DBug
// DBWin( "SSafeExec After ExecProg Ow=%d Cw=%d", Ow, Window_Id );
    switch ( Error_Level ) {

      case _Exec_Abort :
        Error_Level = 0;
        break;

      case _Exec_Error :
        Error_Level = ExecErrorCode;
        break;

      case _Exec_Success :
        Error_Level = 0;
        switch ( ExecId ) {

          case _Exe_Id_Windows :
            SSafeParseErr( );

          case _Exe_Id_Dos :
          case _Exe_Id_Os2 :
            Error_Level = ExecReturnCode;
            if ( Error_Level == 0 ) {
              Result = True;
              break;
            }

          default :
            Error_Level += 9000;
        }
    }
  }
  vcsDlgMsg = "";
  Switch_Win_Id( Ow );
  Refresh = Srf;
  return ( Result );

}  // SSafeExec

str SSafeXlate(
        str Path = Return_Str,
        str FName = Parse_Str( "/F=", MParm_Str ),
        str Project = Parse_Str( "/P=", MParm_Str )
    ) Trans2 {
/******************************************************************************
                               Multi-Edit Macro
                               12-Aug-94  23:34

  Name    : SSafeXlate

  Function: Place holder for adding code to implement any SourceSafe specific
            tranlation metacommands. Call VcsXlate to finish the translations.

  Syntax  : Path = SSafeXlate( Path, FName, Project );

  Entry   : str Path            - The string to be translated.
            str FName           - The work file name.
            str Project         - The SourceSafe project.

  Exit    : str ( Return_Str )  - The expanded command line.

  Globals : none

  Macros  : str VcsXlate

                Copyright (C) 1990-94 by Small Systems Support.
********************************************************************( ldh )***/

  return ( VcsXlate( Path, FName, Project ) );

}  // SSafeXlate

str SSafeExt( str FName = Parse_Str( "/F=", MParm_Str ) ) Trans2 {
/******************************************************************************
                               Multi-Edit Macro
                               15-Aug-94  23:05

  Name    : SSafeExt

  Function: Takes a filename extension and converts it to the equivalent
            SourceSafe LIBEXT extension.

  Syntax  : RcsExt( str FName );

  Entry   : str FName     - Filename for which the extension is translated.

  Exit    : str           - The vcs file extension based upon LIBEXT.

  Globals : none.

  Macros  : none.

                Copyright (C) 1990-94 by Small Systems Support.
********************************************************************( ldh )***/

  return ( Get_Extension( FName ) );

}  // SSafeExt

int SSafeChkLib(
        str Project = Parse_Str( "/P=", MParm_Str ),
        str FName = Parse_Str( "/F=", MParm_Str ),
        int Pm = Parse_Int( "/M=", MParm_Str )
    ) Trans2 {
/******************************************************************************
                               Multi-Edit Macro
                               12-Aug-94  23:31

  Name    : SSafeChkLib

  Function: Search "Project" for the SourceSafe archive for "FName" based upon
            "Pm".

  Syntax  : LibFnd = SSafeChkLib( Project, FName, Pm );

  Entry   : gstr !vcsID   - The name of the currently selected vcs package.
            str  Project  - Contains the search path.
            str  FName    - The filename for which to find archive.
            int  Pm       - Path Mode.
              -2          - Check for and return archive file only.
              -1          - Check for and return archive file,
                            iff no file return 1st lib path.
               0          - Return full archive path.
              +#          - Return # directory from archive path.

  Exit    : int ( gint !vcsRInt )
              #                 - File was found in # path.
                gstr !vcsAFile  - The found archive filename or path.
              0                 - File NOT found.
                gstr !vcsAFile  - The archive path based upon pm.
                                  ( Not set if Pm == -2 ).

  Globals : str !vcsID    - The name of the currently selected vcs package.
            int !vcsRInt  - The return integer.
            str !vcsAFile - The found archive filename or path.

  Macros  : int SSafeXlate
            int SSafeCmds

                Copyright (C) 1993-94 by Small Systems Support.
********************************************************************( ldh )***/

  str FPath[ 128 ] = "";
  str LPath[ 128 ];
  str TFName = Truncate_Path( FName );

  int Jx;
  int Jy = 0;
  int Cnt = 0;

  vcsRInt = False;
  ssafeFUsr = "";
  if ( ( Project == _LIB_PATH ) && ( _DO_CD == 2 ) ) {
    Project = "<LOOKUP>";
  }
  if ( ( Project = SSafeXlate( Project, FName, "" ) ) != "" ) {
    if ( Pm ) {
      while ( True ) {
        if ( Jy > Svl( Project ) ) {
          if ( Pm != -2 ) {
            vcsAFile = LPath;
          }
          break;
        }
        Jx = XPos( ";", Project, Jy + 1 );
        if ( Jx == 0 ) {
          Jx = Svl( Project ) + 1;
        }
        FPath = Copy( Project, Jy + 1, Jx - Jy - 1 );
        if ( ( Svl( Project ) > 0 ) &&
            ( Copy( FPath, Svl( FPath ), 1 ) != "\\" ) ) {
          FPath += "\\";
        }
        Jy = Jx;
        if ( Pm == ++Cnt ) {
          vcsAFile = FPath;
          vcsRInt = Cnt;
          break;
        }
        if ( Pm < 0 ) {
          vcsMsg = "Checking for \"" + TFName + "\" in \"" +
              FPath + "\"...";
          vcsRInt = SSafeCmds( "DIR", FName, FPath );
          Set_File_Attr( vcsName, 0 );
          Del_File( vcsName );
          Error_Level = 0;
          if ( vcsRInt ) {
            vcsAFile = FPath + TFName;
            vcsRInt = Cnt;
            break;
          }
        }
        if ( Cnt == 1 ) {
          LPath = FPath;
        }
      }
    }
    else {
      vcsAFile = Project;
    }
  }
  return ( vcsRInt );

}  // SSafeChkLib

str SSafeGetFName( str LibFile = Parse_Str( "/P=", MParm_Str ) ) Trans2 {
/******************************************************************************
                               Multi-Edit Macro
                               18-Aug-93  22:49

  Name    : SSafeGetFName

  Function: Returns the work file name extracted from the archive "LibFile" or
            "" when archive doesn't exist.

  Syntax  : FName = SSafeGetFName( LibFile );

  Entry   : str LibFile           - archive file name

  Exit    : str ( gstr !vcsRStr ) - The workfile_name or "".

  Globals : str !vcsRStr          - The return string.

  Macros  : none

                Copyright (C) 1993-94 by Small Systems Support.
********************************************************************( ldh )***/

  vcsRStr = LibFile;
  return ( vcsRStr );

}  // SSafeGetFName

int SSafeChkLock( ) Trans2 {
/******************************************************************************
                               Multi-Edit Macro
                               30-Mar-94  01:39

  Name    : SSafeChkLock

  Function: Check to see if a SourceSafe archive file is locked.

  Syntax  : Locked = SSafeChkLock( );

  Entry   : gint !vcsAFile  - The project filename.

  Exit    : int
              True      - Archive file locked.
              False     - Archive file not locked.

  Globals : str !vcsAFile - The project name
            str !ssafeFUsr   - The username who has the file checked out.
            str &ssafeUser   - The current username.

  Macros  : mac MessageBox

                Copyright (C) 1993-94 by Small Systems Support.
**********************************************************************(ldh)***/

  int Result = False;

  str User = ssafeFUsr;

  ssafeFUsr = "";
  if ( ( User != "" ) && ( Caps( User ) != Caps( ssafeUser ) ) ) {
    Rm( "MessageBox /B=1/T=SSAFE Error/M=" + vcsAFile + " is locked by \"" +
        User + "\"" );
    Result = True;
  }
  return ( Result );

}  // SSafeChkLock

macro SSafeDir Trans2 {
/******************************************************************************
                               Multi-Edit Macro
                               20-Sep-94  16:29

  Name    : SSafeDir

  Function: Displays directory listing of SourseSafe project files.  Allows
            user to select a file to be retrieved for modification, viewing
            only, or listing the version history.

  Syntax  : Rm( "SSafeDir"  );

  Entry   : None.

  Exit    : None.

  Globals : None.

  Macros  : void SSafeFileDlg;

                Copyright (C) 1993-94 by Small Systems Support.
********************************************************************( ldh )***/

  SSafeFileDlg( "(SSAFE) Archive Files", ssafePrj );

}  // SSafeDir

macro SSafeIActive Trans {
/******************************************************************************
                               Multi-Edit Macro
                               15-Aug-94  23:05

  Name    : SSafeIActive

  Function: Runs the "menu command line" that is contained in "!ssafeCfg" global
            variable.

  Syntax  : Rm( "SSafeIActive" );

  Entry   : none.

  Exit    : none.

  Globals : str !ssafeCfg - Contains the commands/setup options for SourceSafe.

  Macros  : int WinExecAndWait

                Copyright (C) 1993-94 by Small Systems Support.
********************************************************************( ldh )***/

  str CmdLine = _MENU_CMDL;

  if ( _SHOW_CMD ) {
    vcsDlgMsg = "(SSAFE) Run Interactive Command Line";
    Return_Int = VcsEditStrDlg( vcsDlgMsg, CmdLine, False );
  }
  if ( Return_Int ) {
    WinExecAndWait( CmdLine, "", _EP_Flags_DontWait, "", "" );
  }
}  // SSafeIActive

int SSafeLogin( int Chg_Usr = XPos( "/CU", MParm_Str, 1 ) ) Trans {
/******************************************************************************
                               Multi-Edit Macro
                               26-Mar-94  15:49

  Name    : SSafeLogin

  Function: Check if a SourceSafe user is logged in, and prompts if not.

  Syntax  : Logged = SSafeLogin( Chg_Usr );

  Entry   : int Chg_Usr   - Force a prompt for a new user.

  Exit    : int
              True        - User logged in.
              False       - Error checking user logged in.
            gstr &ssafeUser  - Set to SourceSafe user name.

  Globals : str &ssafePrj
            str &ssafeINI
            str &ssafeUser

  Macros  : mac MessageBox
            int SSafeCmds
            mac Data_In
            mac Verify

                Copyright (C) 1992-94 by Small Systems Support.
********************************************************************( ldh )***/

  int Ow = Window_Id;
  int Srf = Refresh;
  int Jx;
  int Result;
  int Pass2 = False;

  str User;
  str Pwd;

  Result = !Chg_Usr;                // Change User
  Refresh = False;
  if ( Result ) {
    Make_Message( "Checking SourceSafe Login Status..." );
    ssafeUser = "";
    Result = SSafeCmds( "LOGIN", "", "" );
  }
  if ( Result == False ) {
    Pass2 = True;
    while ( True ) {
      if ( ( User = ssafeUser ) == "" ) {
        User = SSafeGetUser( );
      }
      Result = VcsLoginDlg( "SourceSafe Login", User, Pwd );
      if ( Result ) {
        ssafeUser = User;
        ssafePwd =  Pwd;
        Make_Message( "Logging into SourceSafe..." );
        Result = SSafeCmds( "LOGIN", "", "" );
        if ( Result ) {
          if ( Caps( User ) == Caps( ssafeUsr1 ) ) {
            ssafePwd = "";
          }
          vcsDoLogin = True;          // Enable change user ID menu item
          break;
        }
        Rm( "Verify /T=Invalid User or Password./BL=Try Again? /H=" +
            hc_vcs_Verify );
        Result = Return_Int;
        if ( Result == False ) {
          Rm( "MessageBox /T=SourceSafe Login Error/M=\"SSINIT\" not found," +
              " SSAFE Support not Loaded" );
          vcsId = "";
          vcsDoLogin = False;             // Disable change user ID menu item
          break;
        }
      }
      else {
        break;
      }
    }
  }
  if ( Result == True ) {
    Switch_Window( Window_Count );
    Create_Window;
    Error_Level = 0;
    Load_File( vcsName );
    if ( !Error_Level ) {
      if ( Find_Text( "User: ", 0, 0 ) ) {
        ssafeUser = Shorten_Str( Parse_Str( "User: ", Get_Line ) );
        if ( ( Pass2 == False ) && ( ssafeUsr1 == '' ) ) {
          ssafeUsr1 = ssafeUser;
        }
      }
      if ( Find_Text( "Project: ", 0, 0 ) ) {
        ssafePrj = Caps( Shorten_Str( Parse_Str( "Project: ", Get_Line ) ) );
        Jx = 1;
        while ( Jx = XPos( "/", ssafePrj, Jx ) ) {
          ssafePrj = Str_Del( ssafePrj, Jx, 1 );
          ssafePrj = Str_Ins( "\\", ssafePrj, Jx );
        }
        if ( Length( ssafePrj ) != 2 ) {
          ssafePrj += "\\";
        }
      }
      if ( Find_Text( "Ini file: ", 0, 0 ) ) {
        ssafeINI = Shorten_Str( Copy( Get_Line, Length( Found_Str ) + 1, 255 ) );
      }
    }
    Delete_Window;
  }

Exit:
  Error_Level = 0;
//   Set_File_Attr( vcsName, 0 );
//   Del_File( vcsName );
  Switch_Win_Id( Ow );
  Refresh = Srf;
  return ( Result );

}  // SSafeLogin

macro SSafeAdminPrj Trans {
/******************************************************************************
                               Multi-Edit Macro
                               15-Aug-94  23:05

  Name    : SSafeAdminPrj

  Function: Create, edit and delete entries in the user's administer project
            database for SourceSafe.

  Syntax  : Rm( "SSafeAdminPrj" );

  Entry   : none.

  Exit    : none.

  Globals : str !ssafeLUT - The contents of the current db record.

  Macros  : mac SSafeChkAdmin

                 Copyright (C) 1994 by Small Systems Support.
********************************************************************( ldh )***/

  ssafeLUT = "";                         // clear global lookup variable
  Db( _VCS_DB, "SSAFE.VAD", "MEWHDRS.DB", "VCSVAD.HDR",
      "(SSAFE) Associate Directories",
      "(SSAFE) Associate Directories Setup",
      "!VAD", 0,
      "/BMP=BT_VCS_102/NDF=1/PRE=!VAD/H=" + hc_vcs_Admin +
          "/CP=New File Directory:/MOVE=1/MACRO=SSafeChkAdmin" );

}  // SSafeAdminPrj

str SSafeLookup(
        str FName = Parse_str( "/F=", MParm_Str ),
        str Field1 = Parse_Str( "/F1=", MParm_Str ),
        str Field2 = Parse_Str( "/F2=", MParm_Str )
    ) Trans2 {
/******************************************************************************
                               Multi-Edit Macro
                               15-Aug-94  23:05

  Name    : SSafeLookup

  Function: Returns the string in "Field2" of the SSAFE administer project
            database when the directory of "FName" matches a string in
            "Field1".

  Syntax  : Str_Val = SSafeLookup( FName, Field1, Field2 );

  Entry   : str FName  - The filename to extract the directory name from.
            str Field1 - The field name of the field to match the directory to.
            str Field2 - The field name fo the field to return the string from.

  Exit    : str ( gstr !vcsRStr )
              ""          - Empty string if no match or Field2 empty.
              [Field2]    - Contents of Field2 when match found.

            gstr !ssafeLUT  - Contains the found record.

  Globals : str !vcsRStr  - The return string.
            str !ssafeLUT   - The contents of the matched db record.

  Macros  : int DbGetRecord

                 Copyright (C) 1994 by Small Systems Support.
********************************************************************( ldh )***/

  int Result = True;

  vcsRStr = "";
  FName = Caps( Get_Path( FName ) );
  if ( FName != Parse_Str( "\x7F" + Field1 + "=", ssafeLUT ) ) {

    int Cnt = 0;
    int OrgWin = Window_Id;
    int TRefresh = Refresh;
    int Flags = _dbf_NoDelWin | _dbf_NoSwitchWin;

    str ADField = "\x7F" + "AD=";
    str DbName = _VCS_DB;
    str TStr;
    str SFName = FName;

    Result = False;
    Refresh = False;
    ssafeLUT = "";
    while ( DbGetRecord( DbName, "SSAFE.VAD", Field1, FName, Cnt, Flags, "" ) ==
        _NoError ) {
      if ( ssafeLUT != "" ) {
        TStr =  Parse_Str( ADField, ssafeLUT ) + ";" +
            Parse_Str( ADField, FName );
        Return_Str = ADField;
        Rm( "ChngParm /G=!ssafeLUT/P=" + TStr );
      }
      else {
        ssafeLUT = FName;
        if ( Field1 == "AD" ) {
          break;
        }
      }
      Flags =  _dbf_NoDelWin | _dbf_NoSwitchWin | _sf_Position;
      FName = SFName;
      DbName = "";
      Result = True;
    }
    Switch_Win_Id( OrgWin );
    Refresh = TRefresh;
  }
  if ( Result ) {
    vcsRStr = Parse_Str( "\x7F" + Field2 + "=", ssafeLUT );
    if ( Field1 == "AD" ) {
      ssafeLUT = "";
    }
  }
  return ( vcsRStr );

}  // SSafeLookup

str SSafeCfgFile(
        str FName = Parse_Str( "/F=", MParm_Str ),
        str Param = Parse_Str( "/P=", MParm_Str )
    ) Trans2 {
/******************************************************************************
                               Multi-Edit Macro
                               20-Dec-94  00:50

  Name    : SSafeCfgFile

  Function: Parse and return the value for Param.
            (Note: SourceSafe uses the <LOOKUP> method for this function)

  Syntax  : Str_Val = SSafeCfgFile( FName, Param );

  Entry   : str FName   - The filename to extract the directory name from
            str Param   - The parameter to parse for the return string

  Exit    : str ( gstr !vcsRStr )
              ""          - Empty string if no match
              [Param]     - Contents of Param from config file when match found

  Globals : str !vcsRStr  - The return string
            str !ssafeCfg
            str &ssafeUser

  Macros  : str SSafeLookUp

                 Copyright (C) 1994 by Small Systems Support.
********************************************************************( ldh )***/

  vcsRStr = "";
  switch ( Param ) {
    case "ARCDIR" :
      vcsRStr = SSafeLookup( FName, "FD", "AD" );
      break;

    case "ARCEXT" :
      vcsRStr = _LIB_EXT;
      break;

    case "USER" :
      vcsRStr = ssafeUser;
      break;

    case "WORKDIR" :
      vcsRStr = SSafeLookup( FName, "FD", "WD" );
      break;
  }
  return ( vcsRStr );

}  // SSafeCfgFile

macro SSafeChkAdmin Trans {
/******************************************************************************
                               Multi-Edit Macro
                               15-Aug-94  23:05

  Name    : SSafeChkAdmin

  Function: Called by the AdminPrj dialog to capitialize, check and update all
            directories to end with a \ when saving the data in the dialog.

  Syntax  : Called only by the DB macro when in the AdminPrj dialog.

  Entry   : Values passed by the DB macro.

  Exit    : updated data.

  Globals : none.

  Macros  : none.

                 Copyright (C) 1994 by Small Systems Support.
********************************************************************( ldh )***/

  if ( Parse_Int( "/P=", MParm_Str ) != 0 ) {

    str GStr = Parse_Str( "/GLO=", MParm_Str );
    str TStr = Caps( Global_Str( GStr ) );

    int Len = Svl( TStr );
    int Jx = 1;

    while ( Jx < Len ) {
      if ( ( Jx = XPos( "\x7F", TStr, ++Jx ) ) == 0 ) {
        Jx = Len + 1;
      }
      if ( Pos( Copy( TStr, Jx - 2, 1 ), "=" ) == 0 ) {
        if ( Pos( Copy( TStr, Jx - 1, 1 ), ";>\\" ) == 0 ) {
          TStr = Str_Ins( "\\", TStr, Jx );
          Len = Svl( TStr );
        }
      }
    }
    Jx = 1;
    while ( Jx = XPos( ";", TStr, Jx ) ) {
      if ( Copy( TStr, Jx - 1, 1 ) != "\\" ) {
        TStr = Str_Ins( "\\", TStr, Jx );
      }
      ++Jx;
    }
    Set_Global_Str( GStr, TStr );
  }
}  // SSafeChkAdmin

int SSafeCmds( str Cmd, str FName, str Project ) Trans2 {
/******************************************************************************
                               Multi-Edit Macro
                               26-Mar-94  16:08

  Name    : SSafeCmds
  Function: The SourceSafe command interface.
  Syntax  : Rm( "SSafeCmds /C=str/F=str" );
  Entry   : /F=str      The filename
                        CP
            /C=str      DIR
                        LOGIN
            Return_Str  Contains the project name.
  Exit    : Return_Int
              False - File not Found.
              True  - File Found.
            Return_Str  The found project\file name or User.

                Copyright (C) 1992-94 by Small Systems Support.
********************************************************************( ldh )***/

  int Result;
  int SavSNCL = vcsSNCL;

  vcsSNCL = True;
//   vcsSNCL = False;
  switch ( Cmd ) {

    case "LOGIN" :
      Result = SSafeExec( "SSWLOGIN.EXE -E -O@" + vcsName + " " + ssafeUser +
          " " + ssafePwd, 0, False);
      break;

    case "DIR" :
      if ( SSafeGetDirFile( False, True ) ) {
        vcsAFile = Project;
        vcsFName = FName;
        Result = SSafeUpdDirFile( vcsAFile + Truncate_Path( FName ), "" );
        if ( Result == False ) {
          FName = "";
        }
        vcsAFile = Project + Truncate_Path( FName );
        break;
      }

    case "SDIR" :
      if ( ssafeRDir == True ) {
        Project = "$\\";
      }
      vcsAFile = Project;
      vcsFName = FName;
      if ( !( Result = SSafeExec(
          "SSWCL.EXE DIR -EXITCODE -I- -E -O&@" + vcsName +
          SIf( ssafeRDir, " -R", "" ) + " \"<LPATH><NAME>.<EXT>\"", 0, False ) ) ) {
        FName = "";
      }
      vcsAFile = Project + Truncate_Path( FName );
      break;

    case "CP" :
      Result = False;
      if ( Project != "" ) {
        if ( ( Result = SSafeGetPrj( Project, True ) ) == True ) {
          ssafePrj = Project;
        }
        else {
          vcsAFile = Project;
          Result = SSafeExec( "SSWCL.EXE CP -EXITCODE -I- -O&@" + vcsName +
              " \"<LPATHX>\" ", 0, False );
          if ( Result == True ) {
            if ( SSafeGetPrj( Project, False ) == True ) {
              ssafePrj = Project;
            }
          }
        }
      }
      break;
  }
  vcsSNCL = SavSNCL;
  return ( Result );

}  // SSafeCmds

int SSafeGetPrj( str &Project, int Change ) {
/******************************************************************************
                               Multi-Edit Macro
                               26-Mar-94  16:02

  Name    : SSafeGetPrj

  Function: Reads the user's SS.INI file for the current project.

  Syntax  : SSafeGetPrj( );

  Entry   : gstr &ssafeINI - contains the path\file name of the user's SS.INI file.

  Exit    : The current users current SourceSafe project is store in the
            gstr &ssafePrj

  Globals : str &ssafeINI  - user's SS.INI path\file name.
            str &ssafePrj  - user's current project.

  Macros  : none.

                Copyright (C) 1993-94 by Small Systems Support.
********************************************************************( ldh )***/

  int Ow = Window_Id;
  int Srf = Refresh;
  int Jx;
  int Result = False;

  str TStr;

  Refresh = False;
  Switch_Window( Window_Count );
  Create_Window;
  Error_Level = 0;
  Load_File( ssafeIni );
  if ( !Error_Level ) {
    TStr = "Project = ";
    if ( Find_Text( TStr, 0, 0 ) ) {
      if ( Change == True ) {
        Jx = 1;
        while ( Jx = XPos( "\\", Project, Jx ) ) {
          Project = Str_Del( Project, Jx, 1 );
          Project = Str_Ins( "/", Project, Jx );
        }
        Jx = Svl( Project );
        if ( ( Jx > 2 ) && ( Copy( Project, Jx, 1 ) == "/" ) ) {
          Project = Copy( Project, 1, Jx - 1 );
        }
        Project = TStr + Caps( Project );
        Put_Line( Project );
        Save_File;
      }
      Project = Caps( Parse_Str( TStr, Get_Line( ) ) );
      Jx = Svl( Project );
      if ( ( Jx > 2 ) && ( Copy( Project, Jx, 1 ) != "/" ) ) {
        Project += "\\";
      }
      Jx = 1;
      while ( Jx = XPos( "/", Project, Jx ) ) {
        Project = Str_Del( Project, Jx, 1 );
        Project = Str_Ins( "\\", Project, Jx );
      }
      Result = True;
    }
  }
  Error_Level = 0;
  Delete_Window;
  Switch_Win_Id( Ow );
  Refresh = Srf;
  return ( Result );

}  // SSafeGetPrj

int SSafeGetLib( str FName ) Trans2 {
/******************************************************************************
                               Multi-Edit Macro
                               29-Mar-94  23:40

  Name    : SSafeGetLib

  Function: Get the archive project and filename for the file "FName".  If it
            doesn't exist in the checkout list and the "No Prompts" options is
            not enabled then a dialog prompting for archive project is given
            and then checked to see if the archive exists.

  Syntax  : LibFnd = SSafeGetLib( FName );

  Entry   : str   FName       - the filename to archive information for.
            gint  !vcsSNP     - global_int used to disable prompts when set.
            gstr  !vcsDlgMsg  - global_str with prompt dialog title.

  Exit    : 0 - Archive does not exists or <ESC> at dialog prompt.

                error_level = 0 except when <ESC> hit then error_level = 9000.
                gstr !vcsAFile set to selected project if prompt accepted.

            1 - Archive exists.

                error_level = 0.
                gstr !vcsChkMod set to checkout mode if found else cleared.
                gstr !vcsAFile set to archive project\filename.

            gstr !vcsDlgMsg cleared.

  Globals : gint !vcsSNP    - show No Prompts option.  True no prompt.
            gstr !vcsDlgMsg - prompt for archive path message.

            gstr vcsAFile  - the archive path and filename.
            gstr vcsChkMod - archive file checkout mode.

  Macros  : int VcsFileOut
            str SSafeXlate
            mac Data_In
            int SSafeChkLib

                Copyright (C) 1993-94 by Small Systems Support.
********************************************************************( ldh )***/

  int Result;
  int Jx;

  str Path;

  Error_Level = 0;
  if ( !( Result = VcsFileOut( FName, 0 ) ) && !vcsSNP ) {
    Path = SSafeXlate( _LIB_PATH, FName, "" );
    if ( Jx = XPos( ";", Path, 1 ) ) {
      Path = Copy( Path, 1, Jx - 1 );
      if ( ( Svl( Path ) > 0 ) && ( Copy( Path, Svl( Path ), 1 ) != "\\" ) ) {
        Path += "\\";
      }
    }
    Result = VcsEditStrDlg( vcsDlgMsg, Path, False );
    if ( Result ) {
      if ( ( Svl( Path ) > 0 ) && ( Copy( Path, Svl( Path ), 1 ) != "\\" ) ) {
        Path += "\\";
      }
      if ( Result = SSafeChkLib( Path, FName, -2 ) ) {
        vcsChkMod = "";
      }
      Error_Level = 0;
    }
    else {
      Error_Level = 9000;
    }
  }
  vcsDlgMsg = "";
  return ( Result );

}  // SSafeGetLib

void SSafeParseErr( ) Trans2 {
/******************************************************************************
                               Multi-Edit Macro
                               15-Sep-94  21:42

  Name    : SSafeParseErr

  Function: Parse the exit code out of the captured SSWCL.EXE command output.

  Syntax  : SSafeParseErr( );

  Entry   : None.

  Exit    : gint ExecReturnCode - The exit code from the captured file.
               0                  No Error
               1                  Minor Error
              100                 Major Error

  Globals : int ExecReturnCode  - The return code of the executed program.
            int !vcsNameLoaded  - Set when the vcsName file has loaded.

  Macros  : None.

                  Copyright (C) 1994 by Small Systems Support
********************************************************************( ldh )***/

  int Result;
  int SwF = False;

  if ( !Switch_File( vcsName ) ) {
    SwF = True;
    Switch_Window( Window_Count );
    Create_Window;
  }
  ExecReturnCode = 100;                 // Assume major failure
  Error_Level = 0;
  Load_File( vcsName );
  if ( Error_Level == 0 ) {
    vcsNameLoaded = True;
    if ( Find_Text( "Exit code: ", 0, 0 ) ) {
      Val( Result, Parse_Str( "Exit code: ", Get_Line ) );
      ExecReturnCode = Result;
    }
    else {
      Tof;
      if ( Find_Text( "User: ", 0, 0 ) ) {
        ExecReturnCode = 0;             // Found user with SSWLOGIN.EXE
      }
    }
    Tof;
  }
  if ( SwF == True ) {
    Delete_Window;
    vcsNameLoaded = False;
  }

}  // SSafeParseErr

str SSafeGetUser( ) {
/******************************************************************************
                               Multi-Edit Macro
                               04-Jan-95  12:32

  Name    :
  Function:
  Syntax  :
  Entry   :
  Exit    :
  Globals :
  Macros  :

               Copyright (C) 1995 by American Cybernectics, Inc.
********************************************************************( ldh )***/

  str Result = Get_Environment( "SSUSER" );

  if ( Result == "" ) {
    Result = _VCS_USERID;
  }
  return ( Result );

}  // SSafeGetUser

int SSafeGetDirFile( int NewScan, int ChkOnly ) {
/******************************************************************************
                               Multi-Edit Macro
                               22-Sep-94  14:08

  Name    :
  Function:
  Syntax  :
  Entry   :
  Exit    :
  Globals :
  Macros  :

                  Copyright (C) 1994 by Small Systems Support
********************************************************************( ldh )***/

  int Result = False;
  int Srf = Refresh;
  int Ow = Window_Id;
  int LLen;
  int Jx;
  int Jy;
  int Cnt;
  str TLine;
  str TStr;


  if ( ssafeDirFile == "" ) {
    ssafeDirFile = TempFileName( "SSAFEDIR.TMP" );
  }
  Refresh = False;
  if ( !( Result = Switch_File( ssafeDirFile ) ) ) {
    Switch_Window( Window_Count );
    Create_Window;
    Window_Attr = 0x81;
    NewScan = True;
  }
  if ( ChkOnly ) {
    NewScan = False;
  }
  if ( NewScan ) {
    vcsMsg = "Scanning projects...";
    ssafeRDir = True;
    Result = SSafeCmds( "SDIR", "", "" );
    Make_Message( "" );
    ssafeRDir = False;
    if ( Result ) {
      Error_Level = 0;
      Load_File( vcsName );
      File_Name = ssafeDirFile;
      if ( Error_Level ) {
        Error_Level = 0;
        Result = False;
      }
    }
    Set_File_Attr( vcsName, 0 );
    Del_File( vcsName );
    if ( Result == True ) {
      if ( Find_Text( "item(s)", 0, 0 ) ) {
        Block_Begin;
        Eof;
        Delete_Block;
      }
      Tof;
      Put_Line( "\x7F" + "L=0" + "\x7F" + "P=$\\" );
      Down;
      while ( !At_Eof ) {
        TLine = Remove_Space( Get_Line );
        LLen = Svl( TLine );
        if ( Copy( TLine, LLen, 1 ) == ":" ) {
          Cnt = 0;
          TLine = Copy( TLine, 1, LLen - 1 );
          Jx = 0;
          TStr = "";
          while ( Jy = XPos( "/", TLine, ++Jx ) ) {
            ++Cnt;
            TStr += Copy( TLine, Jx, Jy - Jx ) + "\\";
            Jx = Jy;
          }
          TLine = "\x7F" + "L=" + Str( Cnt ) + "\x7F" + "P1=" + TStr +
              "\x7F" + "P=" + Copy( TLine, Jx, Jx - LLen - 1);
          Put_Line( TLine );
        }
        else if ( XPos( "$", TLine, 1 ) ) {
          Del_Line;
          Up;
        }
        else if ( TLine != "" ) {
          TStr = "\x7F" + "F=" + TLine;
          if ( Jx = XPos( " ", TStr, 1 ) ) {
            TStr = Str_Ins( "\x7F" + "U=", Str_Del( TStr, Jx, 1 ), Jx );
            Jx = XPos( " ", TStr, Jx );
            TStr = Str_Ins( "\x7F" + "D=", Str_Del( TStr, Jx, 1 ), Jx );
            Jx = XPos( " ", TStr, Jx );
            Jx = XPos( " ", TStr, ++Jx );
            TStr = Str_Ins( "\x7F" + "WD=", Str_Del( TStr, Jx, 1 ), Jx );
          }
          Put_Line( TStr );
        }
        Down;
      }
      if ( File_Changed ) {
        Save_File;
      }
    }
  }
  if ( Result == False ) {
    Delete_Window;
  }
  Switch_Win_Id( Ow );
  Refresh = Srf;
  return ( Result );

}  // SSafeGetDirFile

int SSafeUpdDirFile( str FName, str FStr ) {
/******************************************************************************
                               Multi-Edit Macro
                               22-Sep-94  23:51

  Name    :
  Function:
  Syntax  :
  Entry   :
  Exit    :
  Globals :
  Macros  :

                  Copyright (C) 1994 by Small Systems Support
********************************************************************( ldh )***/

  int Result = False;
  int Ow = Window_Id;
  int Srf = Refresh;
  int Jx;
  int Jy;
  int Cnt;
  str TStr;
  str TLine;

  Refresh = False;
  if ( Switch_File( ssafeDirFile ) ) {
    TStr = "\x7F" + "P1=" + Get_Path( FName );
    TStr = Copy( TStr, 1, Svl( TStr ) - 1 );
    Cnt = 0;
    Jx = 0;
    while ( Jy = XPos( "\\", TStr, ++Jx ) ) {
      ++Cnt;
      Jx = Jy;
    }
    TStr = "\x7F" + "L=" + Str( Cnt ) + Str_Ins( "\x7F" + "P=", TStr, Jx );
    Tof;
    while ( Find_Text( TStr, 0, 0 ) ) {
      if ( Found_Str == Get_Line ) {
        Down;
        Jx = C_Line;
        TStr = "\x7F" + "F=" + Truncate_Path( FName );
        while ( ( TLine = Get_Line ) != "" ) {
          if ( XPos( TStr, TLine, 1 ) ) {
            if ( Truncate_Path( FName ) == Parse_Str( "\x7F" + "F=", TLine ) ) {
              if ( FStr != "" ) {
                Put_Line( FStr );
              }
              else {
                ssafeFUsr = Parse_Str( "\x7F" + "U=", TLine );
              }
              Result = True;
              break;
            }
          }
          Down;
        }
        if ( ( FStr != "" ) && ( Result == False ) ) {
          Cr;
          Up;
          Put_Line( FStr );
          QSort_Lines( Jx, C_Line, True, 3, 12, True );
        }
        break;
      }
    }
  }
  Switch_Win_Id( Ow );
  Refresh = Srf;
  return ( Result );

}  // SSafeUpdDirFile
