Code Conversion Guide/fr

From Lazarus wiki
Jump to navigationJump to search

Deutsch (de) English (en) español (es) français (fr) 日本語 (ja) português (pt) русский (ru) slovenčina (sk)

Cette page traite de la façon de convertir le code existant en Delphi ou Kylix pour fonctionner avec le compilateur Free Pascal et l'IDE Lazarus. Bien que Lazarus et le compilateur Free Pascal ont des aspects en commun avec Delphi et Kylix, ce ne sont pas des clones. Il y a un certain nombre de différences de convention et d'appel de bibliothèque ... et dans quelques secteurs , FPC est amélioré et peut être plus exigeant sur une syntaxe correcte . Veuillez voir le guide Lazarus For Delphi Users pour une description de quelques unes des différences fonctionnelles .

Le but de ce guide est de documenter certaines des différences spécifiques qui sont fréquemment rencontrées pendant le processus de conversion de code en traduisant le code existant de Delphi à Lazarus.

Ce document a été placé dans la base de connaissance du wiki ainsi il pourrait être facilement complété par n'importe qui qui avait rencontré un problème unique et voudrait le signaler pour que d'autres s'en rendent compte.

Choix d'un composant ou d'une bibliothèque pour la conversion

Où trouver le code pour convertir

Il y a beaucoup de code disponible sur le net qui peut être converti pour être utilisé par FPC et Lazarus . Voici une Page de sites de code qui juste un début. S'il vous plaie complétez le si vous connaissez d'autres bonnes adresses. TurboPower Software a récemment réalisé son offre commerciale entièrement sous MPL(Licence publique de Mozilla) . Une liste de paquets disponibles peut être trouvée ici .

Pour éviter un double effort , les paquets qui ont été déjà convertis sont listés sur la page composants et Exemples de code . Si vous avez converti un paquet ou travaillez sur un , veuillez ajouter une note sur la page Projets en cours de conversion .

Autorisation

Les Licences pour la gamme de code existante du domaine freeware/public aux versions restrictives qui interdisent la modification , la redistribution et l'utilisation commerciale . Avant de convertir tout paquet , c'est une bonne idée d'examiner sa Licence et de s'assurer qu'il va être compatible avec Lazarus et le compilateur Free Pascal. Le sélection de la licence est particulièrement importante avec les composants puisque en déposer une sur une fiche peut imposer une licence non désiré ou incompatible à une application entière.

Quand vous convertissez des composants, veuillez respecter les souhaits de l'auteur original en concervant tout le copyright et les en-têtes de licence avec les adresses email et les URL . Il est courtois et souvent utile d'informer l'auteur que leur composant est converti ... particulièrement si le composant est sous une licence restrictive . Un nouvel intérêt pour un composant vieux ou oublié peut parfois inspirer les auteurs à mettre à jour leur licence d'origine excessivement restrictive.

En général , Le domaine public(freeware), et la licence LGPL/MPL sont les plus flexibles pour la distribution de composants . Pour plus d'information , la [Définition Open Source http://www.opensource.org/docs/definition.php] est un bon endroit pour commencer . Il y a également plusieurs comparaisons disponibles pour aider à clarifier comment les divers types de licences fonctionnent et quel impact ils auront sur le code auquel ils sont lié. Recherche sur "la comparaison des licences open source license"

Dépendances

Une autre étape avant de commencer à travailler sur une conversion est vérifier que le code n'a pas des dépendances profondes avec d'autres paquets qui pourraient ne pas être disponibles ou qui représente un défi considérable de conversion . Quelques offres de freeware sont liées à ou bien prolongent les paquets propriétaires qui ne sont fréquemment plus disponible ou viennent avec des licences inadéquates .

Problèmes liés au Compilateur

Voir :

Questions sur l'OS et de plate-forme

Lazarus et le compilateur Free Pascal sont des outils de developpement multi plate-forme et multi-architecture. En revanche , la plupart du code existant Delphi a été spécifiquement conçu pour fonctionner sur un processeur Intel sous Win32 . Si votre composant candidat a beaucoup de code spécifique Win32 , il pourrait être sage d'essayer et de trouver une plateforme alternative . Mais ne laissez pas ceci vous stopper... c'est véritablement étonnant ce que la LCL supporte!

Faire la conversion

Paramétrer l'environnement de Lazarus pour un projet de conversion

Créer un projet test

  • Placer le code à convertir dans un sous-répertoire (par exemple: convertdir)
  • Lancer Lazarus
  • Fichier->Tout Enregistrer vers le sous-répertoire convertdir. Les noms significatifs pour le Projet et l'unité par défaut sont optionnels.
  • Ouvrir l'unité « principale » à convertir dans convertdir
  • L'ajouter au projet : Projet->Ajouter le fichier de l'éditeur au Projet
  • Lancer Outils->Vérification rapide de la syntaxe ou lancer Executer->Construire Tout pour commencer .

Choses initiales à regarder

  • Les noms de fichier sont sensibles à la casse avec les versions de compileurs 1.0.x . Si vous travaillez avec cette version , faire que tout vos noms de fichiers soient en minuscule. Vous obtiendrez les erreurs "fichiers non trouvées" si vous ne le faites pas .

Sources Delphi VCL, Kylix CLX dans Lazarus

En convertissant des sources Delphi/Kylix, il est souvent utile de trouver des déclarations pour voir , ce qu'une fonction spécifique fait. L'IDE Lazarus peut analyser les sources Delphi/Kylix. Pour faire ceci il en a besoin de quelques chemins de recherche et paramètres du compilateur. Vous pouvez facilement paramétrer ceci dans Configuration->Editeur des directives des outils de code...->Inserer un modèle

Problèmes de conversion et solutions

Fichier Delphi / Kylix équivalents dans Lazarus

Delphi / Kylix Description Lazarus Description
.pas

.dfm/.xfm,

.dcu/.dpu,

.dpr(main project file),

.res,

.dof/.kof

---

---

---

Delphi Source File,

Delphi Form,

Delphi Compiled Unit,

Delphi Project,

Windows Resource File,

Delphi Option File

.pas, .pp

.lfm,

.o,

.lpr

---

---

.lrs,

.lpi(main project file),

.ppu

Pascal unit file,

Form data file,

Compiled unit file,

Project file,

Resource file,

Project options file,

Lazarus resource file,

Lazarus project information file,

FPC unit description file

Convertir les projets/fiches/unités Delphi vers Lazarus

Renommez ou copiez le fichier .dpr vers un fichier .lpr. Mettre en commentaire ou enlevez la directive {$R *.res} et ajouter une directive {$mode delphi}{$H+} ou {$mode objfpc}{$H+} au fichier .lpr. L'IDE Lazarus peut vous assister dans cette conversion à travers l'item du menu outils "Convertir un projet Delphi en projet Lazarus...". Il demande un fichier .dpr (projet Delphi) et le convertit en .lpr; en outre, il crée le fichier .lpi et convertis toutes les unités .

Beaucoup de fiches existantes de Delphi peuvent être converties pour fonctionner avec Lazarus en employant le convertisseur de fiche .dfm vers .lfm intégré de l'IDE. Il peut être trouvé sous le menu outils à l'item "Convertir un fichier DFM en LFM...". Faire appel à la boite de dialogue fichier, sélectionnez le(s) fichier(s) dfm et le convertisseur fera le reste .

Si vous devez convertir l'unité entière (avec ou sans une fiche), Lazarus inclut également un item intégré "Convertir une unité Delphi en unité Lazarus..." qui fera ce qui suit pour vous -

  1. fixe le cas des noms de fichier include et des sections uses.
  2. converti les fichiers .dfm vers les fichiers .lfm (actuellement sans contrôler le contenu, juste le format)
  3. crée un fichier vide .lrs (le contenu sera créé plus tard )
  4. Ajoute la directive {$mode delphi}
  5. Remplace l'unité windows par LCLIntf
  6. Ajoute l'unité LResources si nécessaire (c.-à-d. , si l'unité .lrs doit être utilisée; uses LResources peut être dans la partie implémentation )
  7. Enlève l'unité de variantes
  8. Enlève la directive {$R *.dfm}
  9. Ajoute la section d'initialisation et la directive {$i unit.lrs}

Ceci permet la conversion rapide et facile de la plupart des unités du format Delphi au format Lazarus. Il ne fait aucun contrôle de validité, ou changements automatiques de syntaxe, aussi tout les changements de syntaxe que vous devez faire, les changements additionnels d'unité/de nom d'unité, ou les changements de fichier dfm/pas pour les contrôles/les différences de composants, doivent toujours être fait manuellement, bien que dans le temps quelques assistants(wizards) facilitant une partie de ceci, particulièrement la réparation des fiches converties(lfm), puissent devenir disponible .

Choix du bon mode du compilateur

Le compilateur Free Pascal supporte 5 modes Pascal différents. Par exemple TP pour turbo pascal, vous laisse compiler des unités en turbo pascal. Il y a également un mode de compatibilité DELPHI qui peut être choisi pour rendre le code existant plus facile à convertir. Lazarus préfère le mode OBJFPC, qui est presque égal au mode DELPHI, mais est moins ambigu que la syntaxe de Delphi. Voici les points importants :

Le mode peut être choisi en ligne de commande ou au début de la source . Employer la ligne de commande a l'avantage , que vous n'avez pas besoin de changer la source, mais l'inconvénient , que les autres doivent être renseignés .

La plupart des unités Delphi peuvent être compilées par le compilateur Free Pascal en ajoutant

{$IFDEF FPC}
  {$MODE DELPHI}
{$ENDIF}

juste après le nom de l'unité .

Pour plus de détails à propos des modes de Free Pascal voir la Documentation de Free Pascal

Considérations sur les logiciels multiplate-formes

  • L'assembleur inline est toujours un problème parce qu'il liera le code à l'architecture Intel. Quelques développeurs font des prototypes d'algorithme en Pascal et utilisent la directive IFDEF avec leur assembleur optimisé. Heureusement TurboPower a fait ceci dans de nombreux endroits avec leur code . Si c'est le cas avec le paquet que vous convertissez , remettez la directive sur Pascal.
  • Ne pas mettre en référence des endroits de mémoire spécifique comme le secteur de données du BIOS. Découvrez ce dont le code a besoin et essayez de trouver une alternative multiplate-forme .
  • Ne pas faire les tours spécifiques du processeur (comme employer le compteur temporel d'Intel (time stamp counter)) sans insérer votre code dans une directive IFDEF pour la plate-forme que le code nécessite ... et fournissant une alternative pour des environnements qui n'ont pas les possibilités matérielles .
  • Si vous avez besoin de quelque code spécifique au système d'exploitation(OS) , alors vous pouvez employer la directive IFDEF. Voir ci-dessous pour une liste des macros .

Les variables utiles pour le compilateur

Pour écrire du code, qui se comporte sur différents systèmes différemment, vous pouvez employer les directives {$IFDEF Name}.

  • {$IfDef LCL} Cette variable est définie, en utilisant le paquet LCL. Utile pour écrire du code, qui fonctionne avec la bibliothèque LCL et Delphi.
  • {$IfDef LCLGtk}, {$IfDef LCLWin32}, {$IfDef LCLQt}, ...

Cette variable est définie, en utilisant le paquet LCL et le jeux de composants spécifique est actuellement employé. Utile pour écrire du code, qui fonctionne avec la bibliothèque LCL sur une plate-forme spécifique.

  • {$IfDef FPC}

Cette variable est définie, en utilisant le compilateur FPC. Utile pour écrire du code, qui fonctionne avec FPC et Delphi.

  • {$IfDef Unix}, {$IfDef Win32}, ...

Défini par FPC pour le système d'exploitation cible courant. Delphi définit "Linux", "Win32" et "MSWindows". Free Pascal s'exécute sur beaucoup plus de plate-formes et ainsi on lui recommande d'employer l'item le plus courant. Par exemple "Unix" est défini pour Linux, FreeBSD, NetBSD et OpenBSD, là où Lazarus s'exécute déjà . Utilisez

{$IfDef Linux}
  {$Define Unix}
{$EndIf}

pour travailler autour de ceci pour Kylix .

Pour plus de détails voir la Documentation de Free Pascal. Texte gras

Finding a missing identifier

There are differences in how the LCL is organized when compared to the Delphi VCL. If you get a "not found" compiler error about a major class or identifier, the chances are good that it's in a different unit. A complete cross reference can be found by grep'ing lazarus/docs/xml or the lcl subdirectory.

For example the commonly used tbutton typically throws an error in Delphi code because it's located in a unit named buttons.pp. The following command finds the correct unit very quickly (in the lazarus source directory):

 grep -in ' tbutton =' lcl/*


Major unit differences between Lazarus and Delphi

Please add to this topic!

  • Windows->Interfaces, LCLIntf, LCLType, LCLProc, VCLGlobals, ...)

As the LCL is not windows specific, the code that is in the Delphi Windows unit for directly accessing the Win32 API is abstracted into seperate interfaces, which can be accessed from the LCLIntf unit. Keep in mind, that Lazarus does not emulate win32, so many functions are missing and some do not work as their win32 counterparts. These functions only exist for Delphi compatibility and should only be used for quick & dirty porting. LCL also breaks out many of the types, so often LCLType, and sometimes VCLGlobals are required. LCLProc also contains a few functions which can be useful for lower level handling such as "FreeThenNil" as is in Delphi 5 and higher, "DeleteAmpersands" to remove additional ampersands from a string for controls(& vs && etc). The Interfaces unit needs to be included in the .lpr file to initialize the appropriate widgetset.

  • Messages->LMessages

TControl Messages for win32 event callbacks of the format WM_CALLBACK and the structs associated with them are often found in the Messages unit in Delphi. In the LCL these types of messages and there structs are usually found in LMessages, usually with name changes of WM to LM, so for instance WM_MOUSEENTER becomes LM_MOUSEENTER, and TWMMouse becomes TLMMouse.

  • Graphics, Controls->GraphTypes, GraphMath, Graphics, Controls

To simplify some things and break complexity of circles between units, a few types have been abstracted into a shared unit called GraphType, which includes things, which in Delphi are located in Graphics or Controls, for instance the bvNone etc of panels. So sometimes you have to include it. Also a unit which, although incompatible with Delphi, adds other useful functionality is GraphMath, which adds a TFloatPoint for precision, misc routines for dealing with beziers, lines, and arcs, as well as some operator overloading for use with TPoints and TRect, such as for instance Point1 := Point2 + Point3, and comparing two rects like if (rect1 = rect2) then ...

  • Mask->MaskEdit

For more intelligent naming considerations, the unit for TMaskEdit is called [MaskEdit|] instead of the slightly more nebulous Mask as in many versions of Delphi.

  • StdCtrls->StdCtrls,Buttons

In many version of Delphi TButton is located in StdCtrls, while TSpeedButton and TBitBtn are in Buttons. For consistency and simplicity the LCL puts all button types in Buttons, which can occasionally break code conversion, so it is always a good idea to include.

Property and method differences Delphi -> FPC/LCL

  • TBitmap contains a canvas in the LCL

Syntax differences

Please add to this topic!

Because of the inherent strictness in FPC, some syntax changes are necessary, even though

{$Mode Delphi}

does allow more laziness like Delphi does. For this reason complying as much with the syntax rules of

{$Mode ObjFPC}

as possible is highly recommended, even when the codebase is still going to be shared between Delphi and the LCL. Some of these are simply better coding practices, and sometimes because Delphi mode is not entirely accurate, or in a few instances Delphi acceptible code does not function as expected with FPC, even though it might compile. To that end even though not all such are strictly required, the following list of changes should be considered mandatory :


When assigning an event handling entry point, prefix it with an "@"

For instance, you might assign a button callback manually

Delphi FPC
begin
if not
Assigned(MyButton.OnClick)
then
MyButton.OnClick:= SomeFunction;
//@ not required
//more code...
end
;
begin
if not
Assigned(MyButton.OnClick)
then
MyButton.OnClick:= @SomeFunction;
//@ IS required
//more code...
end
;
When calling a procedure variable use this syntax: theprocname()

In Delphi there is no difference between a function result and a variable, however there is in FPC, so to call a function, even if it has no parameters, you must append parenthesis. For Example -

Delphi FPC
With
(SomeObject)
do begin
If
Assigned(OnMyCallback)
then
OnMyCallback;
//parenthesis not required
end
;
With
(SomeObject)
do begin
If
Assigned(OnMyCallback)
then
OnMyCallback();
//parenthesis required
end
;
When accessing values in a pointer to a record you must dereference first

In Delphi it is not required to de-reference a pointer to a record to access values within it, it can, in fact, be treated just like the record itself, or any other object. In FPC it must be first de-referenced. As an example,

Delphi FPC
Function
GetSomeValue(ARecord: PMyRecord)
:
Integer;
begin
If
Assigned(ARecord)
then
Result
:=
ARecord.SomeValue
else
Result:=
0
;
end
;
Function
GetSomeValue(ARecord: PMyRecord)
:
Integer;
begin
If
Assigned(ARecord)
then
Result
:=
ARecord^.SomeValue
else
Result:=
0
;
end
;
When accessing chars of an indexed string Property of an object, it must be enclosed in parentheses

With Delphi it is possible to treat a Property exactly like some other const or var, even to accessing for instance individual chars of a string directly, while this is not always possible in FPC, specifically for indexed properties. Instead it must be enclosed in parentheses, to make distinct. While this may not always hold true it is probably a good practice to consider anyway. For example

Delphi FPC
Type
TSomeComponent=
class
(TComponent)
//More code...
Published
Property
MyString:
String
index
3
read
GetMyString;
//More code...
End
;
var
MyChar
:
char;
begin
If
Length(MyString)>
2
then
//no parenthesis needed
MyChar:= MyString[
3
];
//More code...
end
;
Type
TSomeComponent=
class
(TComponent)
//More code...
Published
Property
MyString:
String
index
3
read
GetMyString;
//More code...
End
;
var
MyChar
:
char;
begin
If
Length(MyString)>
2
then
//parenthesis sometimes needed
MyChar:= (MyString)[
3
];
//More code...
end
;


You must typecast pointers to actual type when using with var or function of that type

Sometimes in Delphi you will have a null pointer variable representing an object. While it might seem a complex situation, it is oddly quite common especially in large component packs as a method of preventing too many circular includes between objects in different units. In Delphi it is then possible to send this null pointer to a function expecting that object, without bothering to typecast to actual type, in fpc you must typecast.

For example -

Delphi FPC
Unit 1
Type
TSomeObject=
class
(TComponent)
//More code...
End
;
Procedure
DoSomething(Value: TSomeObject);
Function
GetSomeObject: TSomeObject;
Unit 2
Type
TSomeComponent=
class
(TComponent)
//More code...
Published
SomeObject: Pointer
;
//More code...
End
;
Application
var
MyComponent: TSomeComponent
;
begin
MyComponent.SomeObject
:=
GetSomeObject;
//More code...
DoSomething(MyComponent.SomeObject)
;
end
;
Unit 1
Type
TSomeObject=
class
(TComponent)
//More code...
End
;
Procedure
DoSomething(Value: TSomeObject);
Function
GetSomeObject: TSomeObject;
Unit 2
Type
TSomeComponent=
class
(TComponent)
//More code...
Published
SomeObject: Pointer
;
//More code...
End
;
Application
var
MyComponent: TSomeComponent
;
begin
MyComponent.SomeObject
:=
Pointer(GetSomeObject);
//More code...
DoSomething(TSomeObject(MyComponent.SomeObject))
;
end
;

Resources

Delphi resource files are win32 specific and not compatible with Lazarus, so you'll have to recreate and compile them using the lazres. Lazres can be found in the lazarus/tools subdirectory. If you've downloaded the Lazarus sources, you'll need to compile it first.

  • cd lazarus/tools
  • make install

To add a resource to your application:

  • lazres myresource.lrs mypix.xpm anotherpix.xpm
  • Add the LResources unit to your Uses clause
  • Include the .lrs file you created under the initialization block

Example:

function
TForm1.LoadGlyph(
const
GlyphName:
String
): TBitMap;
begin
Result:= TPixmap.Create
;
Result.LoadFromLazarusResource(GlyphName)
;
end
;
//More code...
begin
Speedbutton1.glyph:= LoadGlyph('mypix')
;
//More code...
end
;
initialization
{$I unit1.lrs}
{$I myresource.lrs}
end
.



Another method to convert a Delphi or Kylix project to Lazarus

  • Rename or copy all .dfm or .xfm files to .lfm (Early Delphi versions do not produce a text-based .dfm file. The convert utility, if present in the \bin folder can be used to covert the .dfm first))
  • Rename or copy .dpr file to .lpr
  • Make necessary changes to .lpr file:
  1. Add {$mode delphi}{$H+} or {$mode objfpc}{H+} directives
  2. Add 'Interfaces' to uses clause
  3. Comment out or delete {$R *.res} or directive
  • Make necessary changes to all .pas unit files:
  1. Add {$mode delphi}{$H+} or {$mode objfpc}{H+} directives
  2. Add 'LResources', and if the form has buttons, add 'Buttons' to uses clause
  3. Comment out or delete {$R *.dfm} or {$R *.xfm} directive
  4. Add 'Initialization' section at the end of each unit file, and add {$I unitname.lrs} directive in it
  • Select Project->New Project form file
  • Select the .lpr file
  • At 'Create a new project' window, choose 'Application'
  • Build project and make further necessary corrections to get proper compilation, at this point the .lpi file is generated automaticaly. You may also get 'Error reading Form' messages, click on 'Continue Loading' if you do.
  • Save all, and you have a Lazarus project :-)

Getting Help

If you encounter a problem during conversion that you just can't solve, there are a wide variety of places to get help. For pure Object Pascal and FPC issues, the best place to start is the Free Pascal Documentation by Michaël Van Canneyt and Florian Klämpfl. For more Lazarus oriented problems, the Lazarus Project Documentation in the Lazarus-CCR Knowledgebase Main Page is the next place to look. Finally you can post a question on any of the mailing lists for the Free Pascal Compiler or the FPC forums where a lot of experts are subscribed.

There are some outstanding search and knowledge bases online that can also be a great help for learning new techniques and solving problems. Tamarack Associates operates a fast search engine specifically for the Borland usenet archives. Mer Systems Inc. provides a similar search engine. Another outstanding source of information along with a sitewide search capability is Earl F. Glynn's Computer Lab and Reference Library.

Packaging and Releasing your component

Creating a Lazarus package for your component(s)

Creating a package makes installing the code you've converted a much easier process... especially if you're providing more then one component. Mattias Gärtner has written an overview of Lazarus Packages that should be read before beginning this process.

Documentation

The purpose of this site and the wiki format is to make the generation of professional documentation an easy and quick process. The wiki also makes it possible to see the results of your posting immediately and make any changes you'd like in real time.

Using the Lazarus-CCR wiki to create nice looking documentation is very easy. If you've never used wiki markup before, you can get familiar with it in the Sand Box practice area.

Creating a Code Release Page

The Code Release Page contains vital information about your component that a potential downloader will need to know, such as license, intended platform, status (alpha, beta, stable...), where to download it, who wrote it, is support available... etc.

The following procedure will let you create a Code Release Page with your browser:

  • Go to the Release new component
  • Type the name of your component in the textbox and click on Create Article
  • Fill in the template and hit save.
  • Edit the Components and Code examples page and add the link to your newly created page to the "Released Components" section. Save the modified page.

Submitting the component

If you're a release technician on the project, upload your component to the SourceForge File Release System and add it to the list of release packages. Otherwise send it to one of the project administrators (Tom Lisjac or Vincent Snijders) and we'll add it to the repository. Before we upload it to SourceForge, you have to create a Code Release Page to describe your component. You can use the Release new component page, to start creating such a page.

If you think you need to continue to develop on the component, we can also put it into SVN so you'll continue to have access to it. If we get tired from submitting your patches, we will give you write access to the SVN, so you can commit your patches yourself. For details see Using the Lazarus-ccr SVN repository.

Contributors and Changes

This page has been converted from the epikwiki version.

  • Initial version by Tom Lisjac and Mattias Gärtner - 9/22/2003 VlxAdmin
  • Moved Getting help from the main page. T. Lisjac - 9/24/2003 VlxAdmin
  • Added documentation templates, procedure and links. 9/25/2003 VlxAdmin
  • LCLLinux was renamed to LCLIntf, Jesus Reyes, 9/27/2003
  • added more information on Unit changes, AndrewJohnson 9/27/2003
  • Updated Syntax differences, including some examples, AndrewJohnson 9/27/2003
  • FPC 1.0.x doesn't support interfaces, Vincent Snijders 9/28/2003
  • Fixed some of the examples per new WikiWord definition, 9/28/2003 VlxAdmin
  • Made code more consistant to remove last accidental Pascal WikiWord definitions, AndrewJohnson 9/27/2003
  • Use tables for code examples for nice blocks, and easy side by side view of Delphi->FPC differences, AndrewJohnson 10/17/2003
  • Use pascal stylesheet to make example code more readable, AndrewJohnson 10/18/2003
  • Added 'Another method to convert a Delphi or Kylix project to Lazarus' section , George Lober, 2/17/2006