Sign in Join

Live chat for Free Pascal, Lazarus, Delphi and every Pascal programmer.

Mailing lists / lazarus / 2010-02

CreateRelativePath document error.

24 messages · 7 people · –

Reply by email Subscribe to this list Your subscription

Read-only archive. Use j and k to move between messages.

Juha Manninen
to Juha Manninen

Another thing related to CreateRelativePath:

  RelPath:=CreateRelativePath(FileName, BasePath);

Now, when
BasePath is '/TopDir/Tests/MyProj/'
and
FileName is '/TopDir/Tests/MyProj/src/MyUnit.pas'
then
RelPath = 'src/MyUnit.pas'
which is correct.

However if the BasePath is longer (deeper) than FileName's path, it doesn't work. For example, when
BasePath is '/TopDir/Tests/MyProj/src/'
and
FileName is '/TopDir/Tests/MyProj/MyFile.cfg'
then I want to have
RelPath = '../MyFile.cfg' ( <-- note ../ )
but it doesn't happen.

Is there such a function hidden somewhere in FPC/Lazarus vast amount of code? If not, then CreateRelativePath should be fixed.

Regards,
Juha Manninen

Reply by email

Graeme Geldenhuys
to Juha Manninen
Juha Manninen wrote
Is there such a function hidden somewhere in FPC/Lazarus vast amount of code?

I wouldn't know, but I have my own version of trimming long paths and rather use ellipse (...) to denote hidden information. Using Unicode, the '...' could probably be reduced to one unicode character (?).

See attached test program with path trim function. Maybe it could be useful to you.

Sample output:

$ ./trimming_long_paths
/Users/milipili/Projec...r1/pixie/client/src/pixie/pixie.lpi /home/graemeg/programm..._AdrsBook_MGM/Demo_AdrsBook_MGM.lpi

The trim function can be told how long to make the resulting text, which side to trim from and how long the remaining (right side) text should be. Above I used a limit of 60 characters and 35 character on the right of the ellipse.

Regards,
- Graeme -

fpGUI Toolkit - a cross-platform GUI toolkit using Free Pascal http://opensoft.homeip.net/fpgui/ -------------- next part -------------- A non-text attachment was scrubbed... Name: trimming_long_paths.pas Type: text/x-pascal Size: 1009 bytes Desc: not available URL: <http://lists.lazarus.freepascal.org/pipermail/lazarus/attachments/20100209/33ab521e/attachment-0001.bin>

Reply by email

Paul van Helden
to Juha Manninen: Another thing related to CreateRelativePath: RelPath:=CreateRelativePath(FileName,…

Hi Juha,

FPC RTL comes with ExtractRelativePath. I still use my own code because Delphi's didn't work properly either. It seems FPC's ExtractRelativePath is much shorter than mine. If someone can confirm it works well that would be great (no time now to test thoroughly).

I use the following code (comes from Delphi but with some changes). The second function is to expand a relative path. I don't know how you can have one without the other, but then I probably don't know where to look for it.

function ExtractRelativePath(const BaseName, DestName: string): string;
var
   BasePath, DestPath: string;
   BaseLead, DestLead: PChar;
   BasePtr, DestPtr: PChar;
   function ExtractFilePathNoDrive(const FileName: string): string;
   begin
     Result := ExtractFilePath(FileName);
     Delete(Result, 1, Length(ExtractFileDrive(FileName)));
   end;
   function Next(var Lead: PChar): PChar;
   begin
     Result := Lead;
     if Result = nil then Exit;
     Lead := AnsiStrScan(Lead, PathDelim);
     if Lead  nil then
     begin
       Lead^ := #0;
       Inc(Lead);
     end;
   end;
begin
   if SameFilename(ExtractFileDrive(BaseName),
ExtractFileDrive(DestName)) then
   begin
     BasePath := ExtractFilePathNoDrive(BaseName);
     DestPath := ExtractFilePathNoDrive(DestName);
     BaseLead := PChar(BasePath);
     BasePtr := Next(BaseLead);
     DestLead := Pointer(DestPath);
     DestPtr := Next(DestLead);
     while (BasePtr  nil) and (DestPtr  nil) and
SameFilename(BasePtr, DestPtr) do
     begin
       BasePtr := Next(BaseLead);
       DestPtr := Next(DestLead);
     end;
     Result := '';
     while BaseLead  nil do
     begin
       Result := Result + '..' + PathDelim;
       Next(BaseLead);
     end;
     if (DestPtr  nil) and (DestPtr^  #0) then
       Result := Result + DestPtr + PathDelim;
     if DestLead  nil then
       Result := Result + DestLead;     // destlead already has a
trailing backslash
     Result := Result + ExtractFileName(DestName);
     if Result='' then Result:='.';
   end
   else
     Result := DestName;
end;
function ExpandRelativePath(const BaseName, DestName: String): String;
var
   BasePath, DestPath: string;
   BaseDirs, DestDirs: array[0..129] of PChar;
   BaseDirCount, DestDirCount: Integer;
   I, J: Integer;
   function ExtractFilePathNoDrive(const FileName: string): string;
   begin
     Result := ExtractFilePath(FileName);
     Result := Copy(Result, Length(ExtractFileDrive(FileName)) + 1, 32767);
   end;
   procedure SplitDirs(var Path: string; var Dirs: array of PChar;
     var DirCount: Integer);
   var
     I, J, L: Integer;
   begin
     I := 1;
     J := 0;
     L := Length(Path);
     while (I<=L) and (Path[I] in LeadBytes) do Inc(I);
     if I<=L then
     begin
       if Path[I] = PathDelim then
       begin
         Path[I] := #0;
         Dirs[J] := @Path[I + 1];
         Inc(J);
       end
       else
       begin
         Dirs[J] := @Path[I];
         Inc(J);
       end;
       Inc(I);
     end;
     while I<=L do
     begin
       if Path[I] = PathDelim then
       begin
         Path[I] := #0;
         Dirs[J] := @Path[I + 1];
         Inc(J);
       end;
       Inc(I);
     end;
     DirCount := J - 1;
   end;
begin
   if (DestName='.') or (DestName='') then Result:=ExtractFilePath(BaseName)
   else if ExtractFileDrive(DestName)='' then
   begin
     if DestName[1]=PathDelim then
Result:=ExtractFileDrive(BaseName)+DestName
     else
     begin
       BasePath := ExtractFilePathNoDrive(BaseName);
       DestPath := ExtractFilePathNoDrive(DestName);
       SplitDirs(BasePath, BaseDirs, BaseDirCount);
       SplitDirs(DestPath, DestDirs, DestDirCount);
       I:=0;
       while (I<DestDirCount) and (StrComp(DestDirs[I], '..')=0) do Inc(I);
       Result := '';
       for J := 0 to BaseDirCount-I-1 do
         Result := Result + BaseDirs[J] + PathDelim;
       for J := I to DestDirCount - 1 do
         Result := Result + DestDirs[J] + PathDelim;
       Result:=Result+ExtractFileName(DestName);
     end;
   end
   else Result := DestName;
end;

Regards,

Paul.

Reply by email

Graeme Geldenhuys
to Paul van Helden
Paul van Helden wrote
I use the following code (comes from Delphi but with some changes). The second function is to expand a relative path.

NOTE:
Please do not consider submitting this to FPC or Lazarus. We do not what the whole "copyright" issue again in FPC source code.

Regards,
- Graeme -

fpGUI Toolkit - a cross-platform GUI toolkit using Free Pascal http://opensoft.homeip.net/fpgui/

Reply by email

Juha Manninen
to Paul van Helden: FPC RTL comes with ExtractRelativePath. I still use my own code because Delphi's didn't…

Hi!

FPC RTL comes with ExtractRelativePath. I still use my own code because Delphi's didn't work properly either. It seems FPC's ExtractRelativePath is much shorter than mine. If someone can confirm it works well that would be great (no time now to test thoroughly).

ExtractRelativePath seems to work well, thanks.

Now, damn, it seems that FileUtil.CreateRelativePath works correctly, too. I was testing it in Lazarus Converter code and it used a version in lazarus/ide/ideprogs/ instead of FileUtil, even though FileUtil is higher in "uses" list.
I think there is some redundant and useless code in Lazarus, but it is understandable in such a big project.

So, these 2 work identically in my tests and you should be able to use them, too:

    RelPath:=FileUtil.CreateRelativePath(PasFile, ABasePath);
    RelPath:=ExtractRelativePath(ABasePath, PasFile);

Regards,
Juha Manninen

Reply by email

Paul van Helden
to Juha Manninen
Juha Manninen wrote 17 lines
ExtractRelativePath seems to work well, thanks. Now, damn, it seems that FileUtil.CreateRelativePath works correctly, too. I was testing it in Lazarus Converter code and it used a version in lazarus/ide/ideprogs/ instead of FileUtil, even though FileUtil is higher in "uses" list. I think there is some redundant and useless code in Lazarus, but it is understandable in such a big project. So, these 2 work identically in my tests and you should be able to use them, too: RelPath:=FileUtil.CreateRelativePath(PasFile, ABasePath); RelPath:=ExtractRelativePath(ABasePath, PasFile);

Good. What is the recommended function for the inverse process?

Reply by email

Graeme Geldenhuys
to Juha Manninen: Hi! ExtractRelativePath seems to work well, thanks. Now, damn, it seems that…
Juha Manninen wrote
I was testing it in Lazarus Converter code and it used a version in lazarus/ide/ideprogs/ instead of FileUtil, even though FileUtil is higher in "uses" list.

The last unit in the uses list (which has same signature function) takes precedence, not the first unit in uses list. I had many such issues in tiOPF with SyncObject unit and Windows unit if I remember correctly. I had to always make sure Windows unit was before SyncObject unit so I can use correct function from SyncObject - without specifying unit.function syntax.

As for the redundant units or functions. Please report them in Mantis so they can be remove, otherwise things will only get worse over time.

Regards,
- Graeme -

fpGUI Toolkit - a cross-platform GUI toolkit using Free Pascal http://opensoft.homeip.net/fpgui/

Reply by email

Mattias Gärtner
to Juha Manninen: Hi! ExtractRelativePath seems to work well, thanks. Now, damn, it seems that…

Zitat von Juha Manninen :

Show quoted text 10 lines
Hi! > FPC RTL comes with ExtractRelativePath. I still use my own code because > Delphi's didn't work properly either. It seems FPC's ExtractRelativePath > is much shorter than mine. If someone can confirm it works well that > would be great (no time now to test thoroughly). ExtractRelativePath seems to work well, thanks. Now, damn, it seems that FileUtil.CreateRelativePath works correctly, too.

:)
It is used at a lot of places in the IDE.

I was testing it in Lazarus Converter code and it used a version in lazarus/ide/ideprogs/ instead of FileUtil, even though FileUtil is higher in "uses" list.

Both CreateRelativePath functions are the same.
And 'higher' in uses list means more to the end (right, down).

I think there is some redundant and useless code in Lazarus, but it is understandable in such a big project.

The ideprocs version is a simple alias. I will delete it. The codetools and lcl are separate and independent things (by license and by directory).

Show quoted text 5 lines
So, these 2 work identically in my tests and you should be able to use them, too: RelPath:=FileUtil.CreateRelativePath(PasFile, ABasePath); RelPath:=ExtractRelativePath(ABasePath, PasFile);

No.
ExtractRelativePath works case insensitive, even under Linux. CreateRelativePath expects trimmed filenames. That means no double slashes '//'. I will change it, so that it also works with untrimmed filenames.

Mattias

Reply by email

Graeme Geldenhuys
to Paul van Helden: Good. What is the recommended function for the inverse process?
Paul van Helden wrote
> Good. What is the recommended function for the inverse process?

Doing a quick search, I would imagine one of the following:

- ExpandFileName()
- ExpandUNCFileName()
- ExpandFileNameUTF8()
- CleanAndExpandFilename()
- ExpandUNCFileNameUTF8()
- CleanAndExpandDirectory()

We sure have no limitations regarding choices. :-)

Regards,
- Graeme -

fpGUI Toolkit - a cross-platform GUI toolkit using Free Pascal http://opensoft.homeip.net/fpgui/

Reply by email

Mattias Gärtner
to Paul van Helden: Good. What is the recommended function for the inverse process?

Zitat von Paul van Helden :

Show quoted text 20 lines
On 2010/02/09 01:36 PM, Juha Manninen wrote: > ExtractRelativePath seems to work well, thanks. > Now, damn, it seems that FileUtil.CreateRelativePath works correctly, too. > I was testing it in Lazarus Converter code and it used a version in > lazarus/ide/ideprogs/ instead of FileUtil, even though FileUtil is higher in > "uses" list. > I think there is some redundant and useless code in Lazarus, but it is > understandable in such a big project. > > So, these 2 work identically in my tests and you should be able to use them, > too: > > RelPath:=FileUtil.CreateRelativePath(PasFile, ABasePath); > RelPath:=ExtractRelativePath(ABasePath, PasFile); > > > > Good. What is the recommended function for the inverse process?

I don't know for the ExtractRelativePath, but for CreateRelativePath it is simple:

AbsolutePath:=AppendPathDelim(ABasePath)+RelPath

Mattias

Reply by email

Paul van Helden
to Mattias Gärtner
Mattias G?rtner wrote 11 lines
Zitat von Paul van Helden : > > Good. What is the recommended function for the inverse process? I don't know for the ExtractRelativePath, but for CreateRelativePath it is simple: AbsolutePath:=AppendPathDelim(ABasePath)+RelPath

I'm talking specifically about /relative/ paths, ie. ones with ../../../ in them.

Graeme Geldenhuys wrote 8 lines
- ExpandFileName() - ExpandUNCFileName() - ExpandFileNameUTF8() - CleanAndExpandFilename() - ExpandUNCFileNameUTF8() - CleanAndExpandDirectory()

Graeme: you also missed this. None of those functions take a base path and applies a relative path to produce a new absolute path. The function must be able to go up some directories and then down some others.

Paul.

Reply by email

Michael Van Canneyt
to Paul van Helden
Paul van Helden wrote 28 lines
On 2010/02/09 02:48 PM, Mattias G?rtner wrote: > Zitat von Paul van Helden : > >> >> Good. What is the recommended function for the inverse process? > > I don't know for the ExtractRelativePath, but for CreateRelativePath it is > simple: > > AbsolutePath:=AppendPathDelim(ABasePath)+RelPath > > I'm talking specifically about /relative/ paths, ie. ones with ../../../ in them. On 2010/02/09 02:02 PM, Graeme Geldenhuys wrote: > - ExpandFileName() > - ExpandUNCFileName() > - ExpandFileNameUTF8() > - CleanAndExpandFilename() > - ExpandUNCFileNameUTF8() > - CleanAndExpandDirectory() > > Graeme: you also missed this. None of those functions take a base path and applies a relative path to produce a new absolute path. The function must be able to go up some directories and then down some others.

ExpandFileName does exactly that.

Michael.

Reply by email

Graeme Geldenhuys
to Michael Van Canneyt
Michael Van Canneyt wrote 6 lines
>> > Graeme: you also missed this. None of those functions take a base path and > applies a relative path to produce a new absolute path. The function must be > able to go up some directories and then down some others. ExpandFileName does exactly that.

Thank-you, that is exactly what I though. :-)

Regards,
- Graeme -

fpGUI Toolkit - a cross-platform GUI toolkit using Free Pascal http://opensoft.homeip.net/fpgui/

Reply by email

Paul van Helden
to Michael Van Canneyt: ExpandFileName does exactly that. Michael.
Michael Van Canneyt wrote 21 lines
> I'm talking specifically about /relative/ paths, ie. ones with > ../../../ in them. > > On 2010/02/09 02:02 PM, Graeme Geldenhuys wrote: >> - ExpandFileName() >> - ExpandUNCFileName() >> - ExpandFileNameUTF8() >> - CleanAndExpandFilename() >> - ExpandUNCFileNameUTF8() >> - CleanAndExpandDirectory() >> >> > Graeme: you also missed this. None of those functions take a base > path and applies a relative path to produce a new absolute path. The > function must be able to go up some directories and then down some > others. ExpandFileName does exactly that.

No it doesn't, unless you're assuming your current directory as the base path. ExtractRelativePath specifically takes a base path as a parameter. Its inverse should do the same. In a GUI app (at least mine) I don't care about my current directory.

Reply by email

Marco van de Voort
to Paul van Helden
Paul van Helden wrote 7 lines
> ExpandFileName does exactly that. > > No it doesn't, unless you're assuming your current directory as the base path. ExtractRelativePath specifically takes a base path as a parameter. Its inverse should do the same. In a GUI app (at least mine) I don't care about my current directory.

Moreover, expandfilename afaik walks the filesystem, which is not always good (e.g. whe you are laying out a new dir hierarchy)

Reply by email

Mattias Gärtner
to Michael Van Canneyt: ExpandFileName does exactly that. Michael.

Zitat von Michael Van Canneyt :

Show quoted text 33 lines
On Tue, 9 Feb 2010, Paul van Helden wrote: > > On 2010/02/09 02:48 PM, Mattias G?rtner wrote: >> Zitat von Paul van Helden : >> >>> >>> Good. What is the recommended function for the inverse process? >> >> I don't know for the ExtractRelativePath, but for >> CreateRelativePath it is simple: >> >> AbsolutePath:=AppendPathDelim(ABasePath)+RelPath >> >> > I'm talking specifically about /relative/ paths, ie. ones with > ../../../ in them. > [...] >> - ExpandFileName() [...] >> - CleanAndExpandFilename() >> - CleanAndExpandDirectory() >> >> > Graeme: you also missed this. None of those functions take a base > path and applies a relative path to produce a new absolute path. > The function must be able to go up some directories and then down > some others. ExpandFileName does exactly that.

No. ExpandFilename does much more and less. It corrects \ and / to path delim, expands a relative filename with the *current working directory* (Get/SetCurrentDir) and it expands tilde '~' to $HOME under Linux.

If you want only create an absolute path from a directory and a relative path use:
AbsPath:=AppendPathDelim(BaseDir)+RelPath;

This can create a file like '/usr/../lib' or '/usr/./lib' or '/usr//lib', which are all valid file names, just somewhat ugly. To resolve '..', '.' and double path delims use TrimFilename:

AbsPath:=TrimFilename(BaseDir+PathDelim+RelPath);

The above three would result in '/usr/lib'.

To even resolve system specials like '~' and cut trailing path delim use CleanAndExpandFilename:

AbsPath:=CleanAndExpandFilename(BaseDir+PathDelim+RelPath);

CleanAndExpandDirectory is like CleanAndExpandFilename but appends a path delim if not already there.

If you even want to resolve symlinks or get the real file name (e.g. OS X UTF8 normalization, case insensitive file systems) there are functions for that too.

Mattias

Reply by email

Michael Van Canneyt
to Paul van Helden: No it doesn't, unless you're assuming your current directory as the base path.…
Paul van Helden wrote 26 lines
On 2010/02/09 03:20 PM, Michael Van Canneyt wrote: >> I'm talking specifically about /relative/ paths, ie. ones with ../../../ >> in them. >> >> On 2010/02/09 02:02 PM, Graeme Geldenhuys wrote: >>> - ExpandFileName() >>> - ExpandUNCFileName() >>> - ExpandFileNameUTF8() >>> - CleanAndExpandFilename() >>> - ExpandUNCFileNameUTF8() >>> - CleanAndExpandDirectory() >>> >>> >> Graeme: you also missed this. None of those functions take a base path and >> applies a relative path to produce a new absolute path. The function must >> be able to go up some directories and then down some others. > > > ExpandFileName does exactly that. > > No it doesn't, unless you're assuming your current directory as the base path. ExtractRelativePath specifically takes a base path as a parameter. Its inverse should do the same. In a GUI app (at least mine) I don't care about my current directory.

Yes it does ?

ExpandFileName(BasePath+RelativePath);

Will get rid of all '..' pairs and do what you need. Obviously, BasePath must be an absolute pathname; But the same holds for ExtractRelativePath.

Michael.

Reply by email

Michael Van Canneyt
to Marco van de Voort: Moreover, expandfilename afaik walks the filesystem, which is not always good (e.g. whe…
Marco van de Voort wrote 11 lines
On Tue, Feb 09, 2010 at 03:41:38PM +0200, Paul van Helden wrote: >> ExpandFileName does exactly that. >> >> > No it doesn't, unless you're assuming your current directory as the base > path. ExtractRelativePath specifically takes a base path as a parameter. > Its inverse should do the same. In a GUI app (at least mine) I don't > care about my current directory. Moreover, expandfilename afaik walks the filesystem, which is not always good (e.g. whe you are laying out a new dir hierarchy)

It does not. In case it detects a relative path, it just asks the current working directory. That's it. All the rest is string manipulation.

Michael.

Reply by email

Paul van Helden
to Mattias Gärtner: Zitat von Michael Van Canneyt : No. ExpandFilename does much more and less. It corrects \…
Mattias G?rtner wrote 33 lines
> ExpandFileName does exactly that. No. ExpandFilename does much more and less. It corrects \ and / to path delim, expands a relative filename with the *current working directory* (Get/SetCurrentDir) and it expands tilde '~' to $HOME under Linux. If you want only create an absolute path from a directory and a relative path use: AbsPath:=AppendPathDelim(BaseDir)+RelPath; This can create a file like '/usr/../lib' or '/usr/./lib' or '/usr//lib', which are all valid file names, just somewhat ugly. To resolve '..', '.' and double path delims use TrimFilename: AbsPath:=TrimFilename(BaseDir+PathDelim+RelPath); The above three would result in '/usr/lib'. To even resolve system specials like '~' and cut trailing path delim use CleanAndExpandFilename: AbsPath:=CleanAndExpandFilename(BaseDir+PathDelim+RelPath); CleanAndExpandDirectory is like CleanAndExpandFilename but appends a path delim if not already there. If you even want to resolve symlinks or get the real file name (e.g. OS X UTF8 normalization, case insensitive file systems) there are functions for that too.

Thanks Mattias (& Michael)! What a wonderful explanation! That FExpand function is a beast and I didn't study it properly. I will indeed start using it.

Paul.

Reply by email

Mattias Gärtner
to Paul van Helden

Zitat von Paul van Helden :

Show quoted text 21 lines
On 2010/02/09 04:20 PM, Mattias G?rtner wrote: >> ExpandFileName does exactly that. > > > No. ExpandFilename does much more and less. It corrects \ and / to > path delim, expands a relative filename with the *current working > directory* (Get/SetCurrentDir) and it expands tilde '~' to $HOME > under Linux. > > If you want only create an absolute path from a directory and a > relative path use: > AbsPath:=AppendPathDelim(BaseDir)+RelPath; > > This can create a file like '/usr/../lib' or '/usr/./lib' or > '/usr//lib', which are all valid file names, just somewhat ugly. > To resolve '..', '.' and double path delims use TrimFilename: > > AbsPath:=TrimFilename(BaseDir+PathDelim+RelPath); > > The above three would result in '/usr/lib'.

/usr/../lib is of course resolved to /lib, not /usr/lib.

Show quoted text 16 lines
> To even resolve system specials like '~' and cut trailing path > delim use CleanAndExpandFilename: > > AbsPath:=CleanAndExpandFilename(BaseDir+PathDelim+RelPath); > > CleanAndExpandDirectory is like CleanAndExpandFilename but appends > a path delim if not already there. > > If you even want to resolve symlinks or get the real file name > (e.g. OS X UTF8 normalization, case insensitive file systems) there > are functions for that too. > > Thanks Mattias (& Michael)! What a wonderful explanation! That FExpand function is a beast and I didn't study it properly. I will indeed start using it.

Where is the file tutorial on the wiki?

Mattias

Reply by email

Juha Manninen
to Mattias Gärtner: Zitat von Juha Manninen : :) It is used at a lot of places in the IDE. Both…
Mattias G?rtner wrote
> Now, damn, it seems that FileUtil.CreateRelativePath works correctly, too. :)It is used at a lot of places in the IDE.

Yes, I don't know what happened. Now all those functions seem to work correctly.

The ideprocs version is a simple alias. I will delete it. The codetools and lcl are separate and independent things (by license and by directory).

The ideprocs version is an alias to function in codetools/fileprocs which is ALMOST identical with the LCL fileutils version.
I would myself get rid of duplicate code.
Code reuse is GOOD and duplicated code is BAD.

License difference?
Other is "modified LGPL" and other is "GNU General Public License". They are both free and open source. No big deal... :-)

ExtractRelativePath works case insensitive, even under Linux. CreateRelativePath expects trimmed filenames. That means no double slashes '//'. I will change it, so that it also works with untrimmed filenames.

Ok.
There are so many file and file name manipulations functions in different places (RTL, LCL, codetools). I hope they will be unified in future.

Regards,
Juha

Reply by email

Mattias Gaertner
to Juha Manninen
Show quoted text 7 lines
[...] > The ideprocs version is a simple alias. I will delete it. > The codetools and lcl are separate and independent things (by license > and by directory). The ideprocs version is an alias to function in codetools/fileprocs which is ALMOST identical with the LCL fileutils version.

Yes, maybe eventually such functions will go to the a package shared by the codetools and the LCL.

I would myself get rid of duplicate code. Code reuse is GOOD and duplicated code is BAD.

True.

License difference? Other is "modified LGPL" and other is "GNU General Public License". They are both free and open source. No big deal... :-)

LCL can be used in closed source, codetools not. For some people this is a big deal.

Show quoted text 8 lines
> ExtractRelativePath works case insensitive, even under Linux. > CreateRelativePath expects trimmed filenames. That means no double > slashes '//'. I will change it, so that it also works with untrimmed > filenames. Ok. There are so many file and file name manipulations functions in different places (RTL, LCL, codetools). I hope they will be unified in future.

Some functions were moved to the RTL. The fpc team can cherry pick whatever they want.
But there are some big differences: RTL uses system encoding and are programmed with simple porting in mind, LCL and codetools use UTF8. codetools are optimized for file searches. IDE has some file name functions that work in a special way.
The LCL+codetools functions do not support empty file names and many treat double pathdelims as one.

Mattias

Reply by email