Module cWorkspace.pkg

     1// cWorkspace.pkg
     2// Author: SWB
     3Use Windows.pkg
     4Use LanguageText.pkg
     5Use WinShell.pkg // Shell API functions
     6Use seq_chnl.pkg
     7
     8Register_Function IsRegistered String sWorkspace Returns Boolean
     9Register_Function VdfSystemDfPath   Returns String
    10Register_Function VdfSystemMakePath Returns String
    11
    12Enum_List
    13    Define wsWorkspaceOpened       // WS opened ok
    14    Define wsWorkspaceNotFound     // the named WS was not found in the global list
    15    Define wsWorkspaceFileNotFound // the WS file was not found
    16    Define wsDataPathEmpty         // the DataPath entry was empty
    17    Define wsFileListEmpty         // The FileList entry was empty
    18    Define wsFileListNotExist      // The FileList.cfg file could not be found
    19End_Enum_List
    20
    21#IFDEF Get_LastDelimeter
    22#ELSE
    23Function LastDelimeter Global String sDelimeters String sString Returns Integer
    24    // Returns last position of any sDelimeters in the sString
    25    Integer iPos
    26
    27    Move (Length(sString) ) To iPos
    28    While (iPos >0)
    29        If (Mid(sString, 1, iPos)) In sDelimeters Function_Return iPos
    30        Decrement iPos
    31    Loop
    32    Function_Return 0
    33End_Function
    34
    35Function ExtractFilePath Global String sFileName Returns String
    36    // Returns a path from a filename. "c:\Ide\Test\AbData.pkg" would return "c:\Ide\Test\"
    37    Integer iPos
    38    Move (LastDelimeter("\:", sFileName)) To iPos
    39    Function_Return (Left(sFileName, iPos))
    40End_Function
    41
    42Function IsFileNameQualified GLOBAL String sFileName Returns Integer
    43    Function_Return (ExtractFilePath(sFileName) <> "")
    44End_Function
    45
    46Function ExtractFileName Global String sFileName Returns String
    47    // Returns a name from a fully-qualified filename. Eg: "c:\Test\IDE.src" will return "IDE.src"
    48    Integer iPos
    49
    50    Move (LastDelimeter("\:", sFileName)) To iPos
    51
    52    Function_Return (Right(sFileName, Length(sFileName) -iPos))
    53End_Function
    54
    55#ENDIF
    56
    57Define INVALID_HANDLE_VALUE for -1
    58DEFINE MAX_PATH For 260   // Symbol for maximum length of a path
    59
    60Type tWin32FindData
    61    Field tWin32FindData.dwFileAttributes                as Dword
    62    Field tWin32FindData.ftCreationTime.dwLowDateTime    as Dword
    63    Field tWin32FindData.ftCreationTime.dwHighDateTime   as Dword
    64    Field tWin32FindData.ftLastAccessTime.dwLowDateTime  as Dword
    65    Field tWin32FindData.ftLastAccessTime.dwHighDateTime as Dword
    66    Field tWin32FindData.ftLastWriteTime.dwLowDateTime   as Dword
    67    Field tWin32FindData.ftLastWriteTime.dwHighDateTime  as Dword
    68    Field tWin32FindData.nFileSizeHigh                   as Dword
    69    Field tWin32FindData.nFileSizeLow                    as Dword
    70    Field tWin32FindData.dwReserved0                     as Dword
    71    Field tWin32FindData.dwReserved1                     as Dword
    72    Field tWin32FindData.cFileName                       as Char MAX_PATH
    73    Field tWin32FindData.cAlternateFileName              as Char 14
    74End_Type
    75
    76External_Function winFindFirstFile "FindFirstFileA" Kernel32.dll ;
    77    String sFileSpec Pointer lpsWin32FindData Returns Handle
    78
    79External_Function winFindNextFile "FindNextFileA" Kernel32.dll ;
    80    Handle hFindFile Pointer lpsWin32FindData Returns Handle
    81
    82External_Function winFindClose "FindClose" Kernel32.dll ;
    83    Handle hOpenFile Returns Integer
    84
    85Function DoesFileExist GLOBAL String sFilename Returns Boolean
    86        String sWin32FindData sMask
    87        Pointer lpsWin32FindData
    88        Integer iVoid
    89        Handle hFileFind
    90
    91        ZeroType tWin32FindData To sWin32FindData
    92        GetAddress of sWin32FindData To lpsWin32FindData
    93        Move (winFindFirstFile(ToAnsi(sFilename), lpsWin32FindData)) To hFileFind   // JVH 8.3.8.0 must pass Ansi filename
    94        If (hFileFind <> INVALID_HANDLE_VALUE) Begin
    95            Move (winFindClose(hFileFind)) To iVoid
    96        End
    97
    98    Function_Return (hFileFind <> INVALID_HANDLE_VALUE)
    99End_Function
   100
   101
   102Use cIniFile.pkg
   103
   104{ ClassLibrary=Common }
   105{ HelpTopic=cWorkspace }
   106Class cWorkspace is a cObject
   107
   108    Procedure Construct_Object
   109        Forward Send Construct_Object
   110
   111
   112        Property String psAppSrcPath
   113        Property String psBitmapPath
   114        Property String psDataPath
   115        Property String psDdSrcPath
   116        Property String psDescription
   117        Property String psFileList
   118        Property String psHelpPath
   119        Property String psHome
   120        Property String psIdeSrcPath
   121        Property String psProgramPath
   122        Property String psAppHtmlPath
   123        Property String psWorkspaceName
   124        Property String psWorkspaceWSFile
   125
   126        Property String psSystemDfPath // took from the Registry!
   127        Property String psSystemMakePath // took from the Registry!
   128        Property String psDfPath        // Calculated
   129
   130        { Visibility=Private }
   131        Property Boolean pbWorkspaceOpened False // used internally to tell if we are switching workspaces
   132
   133    End_Procedure
   134
   135    { Visibility=Private }
   136    Function FullPathNames String sShortPathNames Returns String
   137        String sFileName
   138        String sFullPathNames sFullPathName sShortPathName
   139        Pointer lpsFullPathName
   140        Pointer lpsFilePart
   141        Integer icChar // the number of characters returned
   142        Integer iPos
   143
   144        Move (Pos(";", sShortPathNames)) To iPos
   145        While (length(sShortPathNames) >0)
   146            If (iPos =0) Begin
   147                Move sShortPathNames To sShortPathName
   148                Move "" To sShortPathNames
   149            End
   150            Else Begin // multiple paths
   151                Move (Left(sShortPathNames, iPos -1)) To sShortPathName
   152                Move (Right(sShortPathNames, length(sShortPathNames) -iPos)) To sShortPathNames // remove this path from the paths
   153            End
   154            Move (Repeat(character(0), 4096)) To sFullPathName
   155            GetAddress of sFullPathName to lpsFullPathName
   156            move -1 to lpsFilePart
   157            Move (GetFullPathName(sShortPathName, 4096, lpsFullPathName, AddressOf(lpsFilePart))) To icChar
   158            Append sFullPathNames (CString(sFullPathName))
   159            If (sShortPathNames <>"") Append sFullPathNames ";"
   160            Move (Pos(";", sShortPathNames)) To iPos
   161        Loop
   162
   163        Function_Return sFullPathNames
   164    End_Function
   165
   166    { Visibility=Private }
   167    Function GetApplicationPath Returns String
   168        // Returns the path of the Application (no trailing "\")
   169        String sApplicationFileName sPath
   170        Boolean bRemoved
   171        Integer iNumChars
   172        String sFilename
   173
   174        Move (Repeat(Character(0), 1024)) to sApplicationFileName
   175        Move (GetModuleFileName(0, AddressOf(sApplicationFileName), 1024)) to iNumChars
   176        Move (CString(sApplicationFileName)) to sApplicationFileName
   177
   178        Move (PathRemoveFileSpec(AddressOf(sApplicationFileName))) to bRemoved
   179        Move (CString(sApplicationFileName)) to sPath
   180
   181        If (Right(sPath, 1) ="\") Move (Left(sPath, Length(sPath) -1)) to sPath
   182        Function_Return sPath
   183    End_Function
   184
   185    Procedure DoClearPaths
   186        // Call this prior to changing from one WorkspAce to another
   187        // if you don't, OpenWorkspaceFile will ignore the new paths.
   188        Set psHome           To ""
   189        Set psAppSrcPath     To ""
   190        Set psBitmapPath     To ""
   191        Set psDataPath       To ""
   192        Set psDdSrcPath      To ""
   193        Set psDescription    To ""
   194        Set psFileList       To ""
   195        Set psHelpPath       To ""
   196        Set psIdeSrcPath     To ""
   197        Set psAppHtmlPath    To ""
   198        Set psProgramPath    To ""
   199        Set psWorkspaceName  To ""
   200        Set psSystemDfPath   To ""
   201        Set psSystemMakePath To ""
   202        Set psWorkspaceWSFile to ""
   203    End_Procedure
   204
   205    Function OpenWorkspaceFile String sWorkspaceFile Returns Integer
   206        String sApplicationStartPath
   207        String sWsName // name of Workspace is inferred from the Workspacefile name
   208        Pointer lpsApplicationStartPath
   209        Boolean bRemoved
   210        Handle hoIniFile
   211        Boolean bSuccess // call succeeded?
   212        String sOldDirectory
   213        String sSystemDfPath sSystemMakePath
   214        Boolean bExist // does the WS file exist?
   215        Boolean bChangingWorkspace
   216
   217        String sHome sAppSrcPath sBitmapPath sDataPath sDdSrcPath sDescription sAppHtmlPath
   218        String sFileList sHelpPath sIdeSrcPath sProgramPath sWorkspaceName
   219        
   220        Set psWorkspaceWSFile to ""
   221        If (sWorkspaceFile ="") Function_Return wsWorkspaceFileNotFound
   222
   223        // Append extension if not supplied...
   224        If (Uppercase(Right(Trim(sWorkspaceFile),3)) <> ".WS") Begin
   225            Move (sWorkspaceFile-".ws") To sWorkspaceFile
   226        End
   227
   228        Get pbWorkspaceOpened To bChangingWorkspace // if we had an existing workspace. We are changing
   229
   230        If (IsFilenameQualified(sWorkspaceFile) = False) Begin
   231            // Set the properties to the paths of the Workspace
   232            // Find the WS file (with program)...
   233            Get GetApplicationPath to sApplicationStartPath
   234
   235            Move sWorkspaceFile To sWsName
   236            Move (sApplicationStartPath +"\" +sWorkspaceFile) To sWorkspaceFile
   237        End
   238        Else Begin
   239            Move (ExtractFileName(sWorkspaceFile)) To sWsName
   240
   241            Move sWorkspaceFile To sApplicationStartPath
   242            GetAddress of sApplicationStartPath To lpsApplicationStartPath
   243            Move (PathRemoveFileSpec(lpsApplicationStartPath)) To bRemoved
   244        End
   245
   246        // Ensure that the file can be found...
   247        //File_Exist (ToAnsi(sWorkspaceFile)) bExist        // [JVH] 8.3.8.0 Convert filename to Ansi
   248        // [JVH] 8.3.8.0 - Temporarily turn off support for
   249        // Ansi extended characters in workspace until we can
   250        // resolve all open issues..........................
   251        Set psWorkspaceWSFile to sWorkspaceFile
   252        File_Exist sWorkspaceFile bExist
   253        If (bExist = False) Function_Return wsWorkspaceFileNotFound
   254
   255        Get psHome           To sHome
   256        Get psAppSrcPath     To sAppSrcPath
   257        Get psAppHtmlPath    To sAppHtmlPath
   258        Get psBitmapPath     To sBitmapPath
   259        Get psDataPath       To sDataPath
   260        Get psDdSrcPath      To sDdSrcPath
   261        Get psDescription    To sDescription
   262        Get psFileList       To sFileList
   263        Get psHelpPath       To sHelpPath
   264        Get psIdeSrcPath     To sIdeSrcPath
   265        Get psProgramPath    To sProgramPath
   266        Get psSystemDfPath   To sSystemDfPath
   267        Get psSystemMakePath To sSystemMakePath
   268        Get psWorkspaceName  To sWorkspaceName
   269
   270        Get_Current_Directory To sOldDirectory
   271        // Note- this conversion is temporarily rolled back
   272        //Move (SetCurrentDirectory(ToAnsi(CString(sApplicationStartPath)))) To bSuccess    // [JVH] 8.3.8.0 Convert AppStartPath to ANSI
   273        Move (SetCurrentDirectory(CString(sApplicationStartPath))) To bSuccess
   274
   275        Get Create U_cIniFile To hoIniFile
   276        Set psFilename of hoIniFile To sWorkspaceFile
   277
   278        If (sHome ="")          Get ReadString of hoIniFile "Workspace" "Home" ""          To sHome
   279        If (sAppSrcPath ="")    Get ReadString of hoIniFile "Workspace" "AppSrcPath" ""    To sAppSrcPath
   280        If (sAppHtmlPath ="")   Get ReadString of hoIniFile "Workspace" "AppHtmlPath" ""   To sAppHtmlPath
   281        If (sBitmapPath ="")    Get ReadString of hoIniFile "Workspace" "BitmapPath" ""    To sBitmapPath
   282        If (sDataPath ="")      Get ReadString of hoIniFile "Workspace" "DataPath" ""      To sDataPath
   283        If (sDdSrcPath ="")     Get ReadString of hoIniFile "Workspace" "DdSrcPath" ""     To sDdSrcPath
   284        If (sDescription ="")   Get ReadString of hoIniFile "Workspace" "Description" ""   To sDescription
   285        If (sFileList ="")      Get ReadString of hoIniFile "Workspace" "FileList" ""      To sFileList
   286        If (sHelpPath ="")      Get ReadString of hoIniFile "Workspace" "HelpPath" ""      To sHelpPath
   287        If (sIdeSrcPath ="")    Get ReadString of hoIniFile "Workspace" "IdeSrcPath" ""    To sIdeSrcPath
   288        If (sProgramPath ="")   Get ReadString of hoIniFile "Workspace" "ProgramPath" ""   To sProgramPath
   289        If (sWorkspaceName ="") Move (Left(sWsName, Length(sWsName) -3))                   To sWorkspaceName
   290
   291        If (sSystemDfPath ="")   Set psSystemDfPath   To (VdfSystemDfPath(self))
   292        If (sSystemMakePath ="") Set psSystemMakePath To (VdfSystemMakePath(self))
   293
   294        Set psHome          To (FullPathNames(self, sHome))
   295
   296        // Set CWD to Home...
   297        Move (SetCurrentDirectory(sHome)) To bSuccess
   298        Set psAppSrcPath    To (FullPathNames(self, sAppSrcPath))
   299        Set psAppHtmlPath   To (FullPathNames(self, sAppHtmlPath))
   300        Set psBitmapPath    To (FullPathNames(self, sBitmapPath))
   301        Set psDataPath      To (FullPathNames(self, sDataPath))
   302        Set psDdSrcPath     To (FullPathNames(self, sDdSrcPath))
   303        Set psFileList      To (FullPathNames(self, sFileList))
   304        Set psHelpPath      To (FullPathNames(self, sHelpPath))
   305        Set psIdeSrcPath    To (FullPathNames(self, sIdeSrcPath))
   306        Set psProgramPath   To (FullPathNames(self, sProgramPath))
   307
   308        Set psWorkspaceName To sWorkspaceName
   309        Set psDescription   To sDescription
   310
   311        Send Destroy of hoIniFile // destroy dynaically created inifile object
   312
   313        // Restore CWD...
   314        Move (SetCurrentDirectory(sOldDirectory)) To sOldDirectory
   315
   316        // Check for error conditions:
   317        // DataPath and FileList must be defined; the FileList entry must point to a valid FileList.cfg
   318        If (psDataPath(self) = "") Function_Return wsDataPathEmpty
   319        If (psFileList(self) = "") Function_Return wsFileListEmpty
   320
   321        //File_Exist (psFileList(self)) bExist
   322        Move (DoesFileExist(psFileList(self))) To bExist
   323        If (bExist = False) Function_Return wsFileListNotExist
   324
   325        If bChangingWorkspace Close DF_ALL // if there is a WS open, we must close all the files
   326
   327        Send DoAssignPaths // set psDfPath
   328        Send DoSetPaths    // Set the application's Attributes of Filelist_Name and Open_Path
   329        Set pbWorkspaceOpened To True
   330
   331        Function_Return wsWorkspaceOpened
   332    End_Function
   333
   334    { Obsolete=True }
   335    Function OpenWorkspace String sWorkspace Returns Integer
   336        // Look in the Workspaces.ini file for the name, then open it by path
   337
   338        Handle hoSections hoIniFile
   339        Integer iWorkspace eOpened
   340        String sWorkspaceName sPath
   341        String sVdfRootDir
   342
   343        Get Create U_Array    To hoSections
   344        Get Create U_cIniFile To hoIniFile
   345
   346        Get_Profile_String "Defaults" "VdfRootDir" To sVdfRootDir
   347        If (Right(sVdfRootDir,1) <>"\") Move (sVdfRootDir +"\") To sVdfRootDir
   348
   349        Set psFilename of hoIniFile To (sVdfRootDir +"bin\Workspaces.ini")
   350
   351        Send ReadSections of hoIniFile hoSections
   352
   353        For iWorkspace from 0 to (Item_Count(hoSections) -1)
   354            Get Value of hoSections iWorkspace To sWorkspaceName
   355            If (Uppercase(sWorkspaceName) = Uppercase(sWorkspace)) Begin
   356                Get ReadString of hoIniFile sWorkspace "Path" "" To sPath
   357                If (Right(sPath,1) <>"\") Move (sPath +"\") To sPath
   358
   359                Get OpenWorkspaceFile (sPath + sWorkspace) To eOpened
   360                Send Destroy of hoSections
   361                Send Destroy of hoIniFile
   362                Function_Return eOpened
   363            End
   364        Loop
   365
   366        Send Destroy of hoSections
   367        Send Destroy of hoIniFile
   368        Function_Return wsWorkspaceNotFound
   369    End_Function
   370
   371    { Obsolete=True }
   372    Function IsRegistered String sWorkspace Returns Boolean
   373        Boolean bRegistered
   374        Handle hoIniFile
   375        String sVdfRootDir
   376
   377        Get Create U_cIniFile To hoIniFile
   378
   379        Get_Profile_String "Defaults" "VdfRootDir" To sVdfRootDir
   380        If (Right(sVdfRootDir,1) <>"\") Move (sVdfRootDir +"\") To sVdfRootDir
   381        Set psFilename of hoIniFile To (sVdfRootDir +"bin\Workspaces.ini")
   382        Move (SectionExists(hoIniFile, sWorkspace)) To bRegistered
   383
   384        Send Destroy of hoIniFile
   385
   386        Function_Return bRegistered
   387    End_Function
   388
   389    { Visibility=Private }
   390    Function VdfSystemDfPath Returns String
   391        String sSystemDfPath
   392        Get_Profile_String "Workspaces" "SystemDfPath" To sSystemDfPath
   393
   394        Function_Return sSystemDfPath
   395    End_Function
   396
   397    { Visibility=Private }
   398    Function VdfSystemMakePath Returns String
   399        String sSystemMakePath
   400        Get_Profile_String "Workspaces" "SystemMakePath" To sSystemMakePath
   401
   402        Function_Return sSystemMakePath
   403    End_Function
   404
   405    Procedure DoAssignPaths
   406        String sDataPath sBitmapPath sHelpPath sProgramPath sSystemDfPath
   407
   408        Get psDataPath     To sDataPath
   409        Get psBitmapPath   To sBitmapPath
   410        Get psHelpPath     To sHelpPath
   411        Get psProgramPath  To sProgramPath
   412        Get psSystemDfPath To sSystemDfPath
   413
   414        Set psDfPath To (sDataPath +';' + sBitmapPath +';' + sHelpPath +';' + sProgramPath +';' + sSystemDfPath)
   415
   416    End_Procedure
   417
   418    Procedure DoSetPaths
   419        // [JVH] 8.3.8.0 - must convert paths to Ansi before setting these values
   420        // Note- this conversion is temporarily rolled back
   421        //Set_Attribute DF_FILELIST_NAME To (ToAnsi(psFileList(self)))
   422        //Set_Attribute DF_OPEN_PATH     To (ToAnsi(psDfPath(self)))
   423        Set_Attribute DF_FILELIST_NAME To (psFileList(self))
   424        Set_Attribute DF_OPEN_PATH     To (psDfPath(self))
   425    End_Procedure
   426
   427    Procedure EnumerateWorkspaceData Handle hoCallBack Handle hmGeneric
   428         String sPath
   429
   430         If (psWorkspaceName(self)="") Send hmGeneric to hoCallBack C_$WorkspaceNotUsed
   431         Else Begin
   432            Send hmGeneric to hoCallBack (SFormat(C_$WorkspaceDesc, psDescription(self)))
   433            Send hmGeneric to hoCallBack (SFormat(C_$WorkspaceName, psWorkspaceName(self)))
   434            Send hmGeneric to hoCallBack ""
   435            Send hmGeneric to hoCallBack (SFormat(C_$Filelist, psFileList(self)))
   436            Send hmGeneric to hoCallBack (SFormat(C_$DataPath, psDataPath(self)))
   437            Send hmGeneric to hoCallBack (SFormat(C_$ProgramPath, psProgramPath(self)))
   438            Send hmGeneric to hoCallBack (SFormat(C_$HelpPath, psHelpPath(self)))
   439            Send hmGeneric to hoCallBack (SFormat(C_$BitmapsPath, psBitmapPath(self)))
   440            Send hmGeneric to hoCallBack (SFormat(C_$SystemPaths, psSystemDfPath(self)))
   441            Send hmGeneric to hoCallBack (SFormat(C_$FullDFPath, psDfPath(self)))
   442         End
   443    End_Procedure
   444
   445    Function OpenWorkspaceErrorMessage Integer eErrorCode Returns String
   446        // Decodes the enumerated integer returned by OpenWorkspace and
   447        // returns a corresponding message string.
   448        String sError
   449
   450        Case Begin
   451            Case (eErrorCode = wsWorkspaceOpened)
   452                Move C_$NoErrors To sError
   453                Case Break
   454            Case (eErrorCode = wsWorkspaceNotFound)
   455                Move C_$NoWsName To sError
   456                Case Break
   457            Case (eErrorCode = wsWorkspaceFileNotFound)
   458                Move C_$NoWsFileFound To sError
   459                Case Break
   460            Case (eErrorCode = wsDataPathEmpty)
   461                Move C_$NoWsDataPath To sError
   462                Case Break
   463            Case (eErrorCode = wsFileListEmpty)
   464                Move C_$NoWsFileList To sError
   465                Case Break
   466            Case (eErrorCode = wsFileListNotExist)
   467                Move C_$NoFileListCfg To sError
   468                Case Break
   469            Case Else
   470                Move C_$UnknownError To sError
   471                Case Break
   472        Case End
   473
   474        Function_Return (sError-".")
   475    End_Function    // OpenWorkspaceErrorMessage
   476
   477    { Obsolete=True }
   478    Function GetWorkspaceFileName String sWorkspace Returns String
   479        // Returns the name of the physical Workspace file for the passed Workspace name.
   480        String sVdfRootDir
   481        Handle hoIniFile
   482        String sPath
   483        String sFileName
   484        String sWorkspacePath
   485
   486        Move "" To sFileName
   487
   488        Get_Profile_String "Defaults" "VdfRootDir" To sVdfRootDir
   489        If (Right(sVdfRootDir,1) <>"\") Move (sVdfRootDir +"\") To sVdfRootDir
   490
   491        Get Create U_cIniFile To hoIniFile
   492        Set psFilename of hoIniFile To (sVdfRootDir +"bin\Workspaces.ini")
   493        Get ReadString of hoIniFile sWorkspace "Path" "" To sWorkspacePath
   494        If (sWorkspacePath <>"") Begin
   495            If (Right(sWorkspacePath,1) <>"\") Move (sWorkspacePath +"\") To sWorkspacePath
   496            Move (sWorkspacePath +sWorkspace +".ws") To sFileName
   497        End
   498        Send Destroy of hoIniFile
   499
   500        Function_Return sFileName
   501    End_Function
   502
   503    Function CountOfPaths String sPaths Returns Integer
   504        // Returns the number of paths defined in a string of paths
   505        Integer iChar icChar icPath
   506
   507        If (sPaths ="") Function_Return 0
   508
   509        Move (Length(sPaths) -1) To icChar
   510        For iChar from 1 To icChar
   511            If (Mid(sPaths, 1, iChar) =";") Increment icPath
   512        Loop
   513
   514        Function_Return (icPath +1)
   515    End_Function
   516
   517    Function PathAtIndex String sPaths Integer iIndex Returns String
   518        // Returns the path at the 1-based index of passed paths.
   519        // If the path contains a trailing "\", it will be removed
   520        Integer iChar icPath iPath iPos
   521        String sPath
   522
   523        Move (sPaths +";") To sPaths
   524        For iPath From 1 To iIndex
   525            Move (Pos(";", sPaths)) To iPos
   526            If iPos Begin
   527                Move (Left(sPaths, iPos -1)) To sPath
   528                If (Right(sPath,1) = '\') Move (Left(sPath, Length(sPath) -1)) To sPath
   529                Move (Right(sPaths, Length(sPaths) -iPos)) To sPaths
   530            End
   531            Else Function_Return "" // index past number of paths
   532        Loop
   533
   534        Function_Return sPath
   535    End_Function
   536
   537End_Class
   538
   539