Code Conversion Guide/de

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)

Delphi zu Lazarus Code Konvertierungs Handbuch

Über

Diese Seite handelt darüber, wie man bestehenden Code konvertiert, um ihn mit dem Free Pascal Compiler und der Lazarus IDE zum Laufen zu bringen. Obwohl Lazarus und der Free Pascal Compiler gemeinsame Aspekte mit Delphi und Kylix haben, sind sie keine Klone. Es gibt eine Anzahl von Bibliotheksaufrufen und Konventionsunterschieden... und in einigen Bereichen ist FPC erweitert und kann anspruchsvoller sein about correct syntax. Bitte schauen sie im Lazarus For Delphi Users Handbuch nach für eine Beschreibung einiger der funktionellen Unterschiede.

Der Zweck dieses Handbuchs ist es, einige der spezifischen Unterschiede zu dokumentieren, die häufig auftreten während des Codekonvertierungsprozesses, wenn existierender Code von Delphi nach Lazarus übersetzt wird.

Dieses Dokument wurde im Wissensbasis Bereich des Wikis platziert, so daß es einfach erweitert werden kann von jedem, who had encountered a unique problem and would like to post it for others to be aware of.

Auswahl einer Komponente oder Bibliothek für die Konvertierung

Wo Code zum Konvertieren zu finden ist

Im Internet ist eine MENGE von Code verfügbar, der konvertiert werden kann für die Verwendung mit FPC und Lazarus. Hier ist eine Seite, die einfach ein Anfang ist. Please add to it if you know of any other good locations. TurboPower Software has recently released their entire commercial offering under the MPL. Eine Liste von verfügbaren Packages ist hier zu finden.

Um doppelten Aufwand zu vermeiden, sind bereits konvertierte Packages gelistet auf der Components and Code examples Seite. Wenn sie ein Package konvertiert haben oder daran arbeiten, dann fügen sie bitte eine Notiz auf der Current conversion projects Seite hinzu.

Lizenzierung

Lizenzen für existierenden Code reichen von Freeware/Public Domain bis zu eingeschränkten Versionen, welche Modifizierung, Weiterverteilung und kommerzielle Verwendung verbieten. Bevor sie irgendein Package konvertieren, ist es eine gute Idee, seine Lizenz zu überprüfen und sicherzustellen, daß sie kompatibel wird mit Lazarus und dem Free Pascal Compiler. Lizenzauswahl ist besonders wichtig bei Komponenten, seit das Ablegen auf einem Formular eine nicht gewollte oder inkompatible Lizenz für die gesamte Anwendung aufbürden kann.

Wenn sie Komponenten konvertieren, respektieren sie bitte die Wünsche des Originalautors und belassen alle Copyright- und Lizenz-Header mit Email-Adressen und URl's. Es gehört zum guten Ton und ist oft hilfreich, um den Autor zu informieren, daß seine Komponente konvertiert wurde... besonders wenn sich die Komponente unter einer restriktiven Lizenz befindet. Neues Interesse an einer alten oder vergessenen Komponente kann manchmal die Autoren inspirieren, um ihr Original und die allzu restriktive Lizenzierung zu überarbeiten.

Im Allgemeinen sind Public Domain (Freeware) und die LGPL/MPL Komponenten die flexibelsten zum Vertreiben. Für mehr Information ist die Open Source Definition ein guter Platz zum starten. Dort gibt es auch verschiedene Vergleiche to help clarify how the various types of licenses work and what impact they'll have on code they're linked to. Suchen sie nach "open source license comparison"

Abhängigkeiten

Ein anderer Schritt bevor sie an einer Konvertierung arbeiten ist, daß sie überprüfen, daß der Code keine verborgenen Abhängigkeiten von anderen Packages enthält, die nicht verfügbar sein können oder eine beträchtliche Konvertierungsherausforderung darstellen. Einige Freeware Angebote sind gebunden an oder erweitern proprietäre Packages, die häufig nicht länger erhältlich sind oder mit ungeeigneten Lizenzen kommen.

Compiler Probleme

Siehe:

Plattform und OS Probleme

Lazarus und der Free Pascal Compiler sind cross-platform und cross-architecture Entwicklungswerkzeuge. Im Gegensatz wurde der meiste existierende Delphi Code speziell vorgesehen, auf einem Intel Prozessor unter Win32 zu laufen. Wenn ihr Kandidat eine Menge von Win32 spezifischem Code hat, mag es weise sein, nach einer weniger plattformabhängigen Alternative zu suchen. Aber lassen sie sich davon nicht entmutigen... es ist echt erstaunlich, was die LCL unterstützt!

Doing the conversion

Einrichten der Lazarus Umgebung für ein conversion Projekt

Erstellen eines Testprojekts

  • Platzieren sie den zu konvertierenden Code in ein Unterverzeichnis (z.B.: convertdir)
  • Holen sie Lazarus hervor
  • Datei -> Alles speichern in das convertdir Unterverzeichnis. Aussagekräftige Namen für Projekt und Units sind optional.
  • Öffnen sie die zu konvertierende "main" Unit in convertdir
  • Fügen sie sie zum Projekt hinzu: Projekt -> Datei im Editor ins Projekt aufnehmen
  • Starten sie Werkzeuge -> Schnelle Syntaxüberprüfung oder Run Build All to get started.

Initial items to watch out for

  • Dateinamen sind case sensitive with the 1.0.x series compilers. Wenn sie mit dieser Version arbeiten, schreiben sie alle Dateinamen klein. Sie werden "File not found" Fehler bekommen, wenn sie es nicht tun.

Delphi VCL, Kylix CLX Sources in Lazarus

When converting Delphi/Kylix sources, it is often useful to do a find declaration to see, what a specific function is doing. The Lazarus IDE can parse the Delphi/Kylix sources. To do this it needs some searchpaths and compiler settings. You can easily setup this in Environment->CodeTools Defines Editor->Insert Template

Konvertierungsprobleme und Lösungen

Delphi / Kylix Datei-Entsprechungen in Lazarus

Delphi / Kylix Lazarus Beschreibung
.pas

.dfm / .xfm .dcu / .dpu .dpr (main project file) .res .dof / .kof --- --- ---

.pas, .pp

.lfm .o .lpr --- --- .lrs .lpi (main project file) .ppu

Pascal Unit Datei

Formulardaten Datei Compilierte Unit Datei Projektdatei Ressourcendatei Projektoptionen Datei Lazarus Ressourcen Datei Lazarus Projekt Informations Datei FPC Unit Beschreibungsdatei

Konvertierung von Delphi Projekten/Formularen/Units nach Lazarus

Rename or copy the .dpr file to a .lpr file. Comment out or remove the

{$R *.res}

directive and add a

{$mode delphi}{$H+}

or

{$mode objfpc}{$H+}

directive to the .lpr file. The Lazarus IDE can assist in this conversion through the Tools menu item "Convert Delphi Project to Lazarus Project". It asks for a .dpr (Delphi Project) file and converts it to .lpr; furthermore, it creates the .lpi file.

Many existing Delphi forms can be converted to work with Lazarus by using the IDE's built in .dfm to .lfm form converter. It can be found under the Tools menu item as "Convert DFM file to LFM". Bring up the file dialog, select the dfm and the converter will do the rest.

If you need to convert the whole unit (with or without a form), Lazarus also includes a built in "Convert Delphi unit to Lazarus unit" which will do the following for you -

  1. renames the .pas and .dfm file to lowercase.
  2. converts .dfm file to .lfm file (currently without content check, just format)
  3. creates an empty .lrs file (the content will be created later)
  4. adds
    {$mode delphi}
    directive
  5. replaces windows unit with LCLIntf
  6. adds LResources unit if needed (i.e., if unit.lrs is to be used;
    uses LResources
    can be in the implementation part)
  7. removes variants unit
  8. removes
    {$R *.dfm}
    directive
  9. adds initialization section and
    {$i unit.lrs}
    directive

This allows quick and easy conversion of most units from Delphi format to Lazarus format. It does not do any validity check, or automatic syntax changes, so any syntax changes you need to make, additional unit/unit name changes, or dfm/pas changes for control/component differences you must still do manually, though in time some wizards to help facilitate some of this, especially the repairing of converted forms(lfm), may become available.

Auswahl des richtigen Compilermodus

Der Free Pascal Compiler unterstützt 5 unterschiedliche Pascal Modi. Zum Beispiel TP für Turbo Pascal, lässt sie Turbo Pascal Units kompilieren. Es gibt auch einen DELPHI Kompatibilitäts-Modus, der gesetzt werden kann, um bestehenden Code einfacher zu konvertieren. Lazarus bevorzugt den OBJFPC Modus, welcher fast dem DELPHI Modus gleicht, aber weniger mehrdeutig als die Delphi Syntax ist. Hier sind die wichtigen Punkte:

Der Modus kann auf der Befehlszeile oder beim Start der Quelle gewählt werden. Die Verwendung der Befehlszeile hat den Vorteil, daß sie die Quelle nicht ändern müssen, aber den Nachteil, daß others erzählt werden muß.

Die meisten Delphi Units können mit dem Free Pascal Compiler kompiliert werden durch hinzufügen von

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

gleich nach dem Unit Namen.

Für mehr Details über die Free Pascal Modi siehe die Free Pascal Dokumentation.

Cross-Platform Überlegungen

  • Inline Assembler ist immer ein Problem, weil er den Code an die Intel Architektur bindet. Some developers do algorithm prototypes in Pascal and ifdef the their optimized assembler. Fortunately TurboPower did this in numerous places with their code. If this is the case with the package you're converting, throw the switch back to Pascal.
  • Don't reference specific memory location like the BIOS data area. Find out what the code needs and try to find a cross platform alternative.
  • Don't do processor specific tricks (like using the Intel TSC) without enclosing your code in an ifdef for the platform the code needs... and providing an alternative for environments that don't have the hardware capability.
  • If you need some OS specific code, then you can use IFDEFs. See below for a list of macros.

Hilfreiche Compiler Variablen

Um Code zu schreiben, der sich auf verschiedenen Systemen unterschiedlich verhält, können sie die

{$IFDEF Name}

Anweisungen verwenden.

  • {$IfDef LCL}

Diese Variable ist definiert, wenn das LCL Package verwendet wird. Hilfreich um Code zu schreiben, der mit der LCL und Delphi funktioniert.

  • {$IfDef FPC}

Diese Variable ist definiert, wenn der FPC Compiler verwendet wird. Hilfreich um Code zu schreiben, der mit FPC und Delphi funktioniert.

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

Von FPC für das aktuelle Ziel OS definiert. Delphi definiert "Linux", "Win32" und "MSWindows". Free Pascal läuft auf viel mehr Plattformen und daher wird empfohlen, allgemeinere Begriffe zu verwenden. Zum Beispiel ist "Unix" definiert für Linux, FreeBSD, NetBSD und OpenBSD, wo Lazarus bereits läuft. Verwenden sie

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

to work around this for Kylix.

Für mehr Details siehe die Free Pascal Dokumentation.

Finden eines fehlenden Bezeichners

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/*


Wichtige Unit Unterschiede zwischen Lazarus und 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 Unterschiede

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
;

Ressourcen

Delphi Ressourcendateien sind Win32 spezifisch und nicht kompatibel mit Lazarus, so daß sie sie neu erstellen und mit Lazres kompilieren müssen. Lazres ist im lazarus/tools Unterverzeichnis zu finden. Wenn sie die Lazarus Quellen heruntergeladen haben, müssen sie es erst kompilieren.

  • cd lazarus/tools
  • make install

Um eine Ressource zu ihrer Anwendung hinzuzufügen:

  • lazres myresource.lrs mypix.xpm anotherpix.xpm
  • Fügen sie die LResources Unit zu ihrem Uses Abschnitt hinzu
  • Nehmen sie die von ihnen erstellte .lrs Datei unter dem initialization Block auf

Beispiel:

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 (This does not work with early Delphi versions as they do not produce a text based .dfm file)
  • 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 :-)



Hilfe erhalten

Wenn sie während der Konvertierung auf ein Problem stoßen, das sie gerade nicht lösen können, gibt es eine große Auswahl von Orten, um Hilfe zu erhalten. Für reine Object Pascal und FPC Probleme, ist der beste Ort zu beginnen die Free Pascal Dokumentation von Michaël Van Canneyt und Florian Klämpfl. Für mehr Lazarus orientierte Probleme ist die Lazarus Projekt Dokumentation in der Lazarus-CCR Knowledgebase Main Page der nächste Ort zum nachschauen. Schließlich können sie eine Frage posten in einer der Mailing Listen für den Free Pascal Compiler oder den FPC Foren, wo eine Menge Experten eingeschrieben sind.

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 betreibt eine schnelle Such Engine speziell für die Borland Usenet Archive. Mer Systems Inc. bietet eine ähnliche Such 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

Erstellen eines Lazarus Package für ihre Komponente(n)

Das Erstellen eines Packages macht die Installation ihres konvertierten Codes viel einfacher... besonders wenn sie mehr als eine Komponente anbieten. Mattias Gärtner hat eine Übersicht über Lazarus Packages geschrieben, die gelesen werden sollte bevor sie mit diesem Prozess beginnen.

Dokumentation

Der Zweck dieser Seite und dem Wiki Format ist, die Generierung einer professionellen Dokumenation zu einem einfachen und schnellen Prozess zu machen. Das Wiki macht es auch möglich, die Resultate ihres posting unverzüglich zu sehen und erlaubt ihnen, Änderungen in Echtzeit zu machen.

Die Verwendung des Lazarus-CCR Wiki um eine schön anzuschauende Dokumentation zu erstellen ist sehr einfach. Wenn sie noch nie zuvor die Wiki Sprache verwendet haben, können sie sich damit vertraut machen in dem Sand Box Übungsbereich.

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:

  • Edit the Components and Code examples page and add a project name wiki link entry for your component in the "Released Components" section. Save the modified page.
  • Go to the Component Release Template, select all and copy. Hit the back button on your browser to return to the Components and Code examples page.
  • Click on your new wiki component name entry and paste the release template into the blank edit box.
  • Edit the template accordingly and hit save.
  • Do edit-saves until your document looks the way you want it to.

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.

If you think you need to continue to develop on the component, we can also put it into CVS so you'll continue to have access to it.

Mitwirkende und Änderungen

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