Status of XDev Toolkit


Contents

Introduction
Installation
MakePasX & DfmToLfm: Delphi converters
MakeVer: Create a version info file
CvtHelp & HelpUtil: Convert WinHelp RTF to HTML
OS X scripts: Create an app bundle
RtfDoc & ViewDoc: RTF document creation and viewing
To Do
Other Resources


Introduction

These notes describe the status of the XDev Toolkit, a set of utilities for cross-platform development with Lazarus and Free Pascal. Please send your bug reports, suggestions and comments to:

  MacPgmr (at) fastermac (dot) net

Note: You can also post to the Lazarus forum if you want your bug reports and suggestions to be seen by the entire Lazarus community.

The XDev Toolkit source code is here: http://web.fastermac.net/~MacPgmr/XDev/downloads

All source code included in the XDev Toolkit is released under the Modified LGPL license.


Installation

  1. Unzip the source files into their own folder.

  2. Open a terminal window and compile each utility and test program with FPC. For example:

    fpc -Sd DfmToLfm.pas

  3. To see a utility's syntax, simply run it in a terminal window without any parameters or switches. For example:

    dfmtolfm


MakePasX & DfmToLfm: Delphi converters

These two utilities are provided for converting Delphi projects to Lazarus and optionally maintaining the project's forms on both Delphi and Lazarus. The MakePasX utility is used to make Delphi code files cross-platform (.dpr and .pas). The DfmToLfm utility is used to create Lazarus form design files (.lfm) from Delphi form design files (.dfm).

Once you've converted a Delphi app to Lazarus you can continue to develop the app with Delphi on Windows and use Lazarus to compile the app on other platforms. This type of app can provide the best of both worlds: taking advantage of the Windows-specific features of Delphi while utilizing Free Pascal and Lazarus to add cross-platform capability to the app.

  1. Use the MakePasX utility to make the Delphi project file (.dpr) and form code files (.pas) cross-platform. This is a one-time conversion that results in a set of source files that can be compiled by both Delphi and Lazarus.

  2. Use the DfmToLfm utility to create Lazarus form files (.lfm) from the Delphi form files (.dfm).

  3. Use the Lazarus lazres utility to create the Lazarus resource file (.lrs) from the form file (.lfm) Repeat steps 2 and 3 whenever you make changes to the Delphi form files. If your project has a number of forms, run these utilities for each form in a batch or shell file to automate the conversion.

  4. Compile the resulting files with Lazarus on Windows to test the converted code and form files.

  5. Move the Lazarus project's files over to OS X or Linux and compile and test them there with that platform's version of Lazarus.

MakeVer: Create a version info file

This simple utility extracts version information from a Delphi .dof file and creates an INI-style .version file that can be distributed with a Lazarus app.


CvtHelp & HelpUtil: Convert WinHelp RTF to HTML

The CvtHelp utility can be used to convert a WinHelp RTF help file to an HTML file that can be used in a Lazarus app that uses the HelpUtil unit.
  1. Use Word to save the WinHelp RTF file to a "Web Page, Filtered" HTML file. For example, open myapp.rtf and save it as myapp.htm.

  2. Run CvtHelp on the resulting HTML file and the WinHelp help project (.hpj) file. For example:

    cvthelp myapp.htm myapp.html

  3. Add the HelpUtil unit to the uses section of your Lazarus app's main form.

  4. In your main form's FormCreate handler:

    Application.HelpFile := ChangeFileExt(ParamStr(0), '.html');

    HelpManager := THelpUtilManager.Create;

  5. In your main form's FormDestroy handler:

    HelpManager.Free;

  6. To invoke help, add something like this to a menu command or button OnClick handler:

    Application.HelpContext(1);

For more information, refer to the CvtHelp and HelpUtil source code.


OS X scripts: Create an app bundle

This script (create_app_mac.sh) creates an .app bundle (folder) for an executable created with Lazarus and its Carbon widgetset so you can double-click the app to start it or drag and drop the app on the dock.

For more information or to customize this script for a specific app, open it in a text editor and read the comments.


RtfDoc & ViewDoc: RTF document creation and viewing

With Delphi, you can use a TRichEdit control to create, display and allow the user to edit simple documents in Rich Text Format (RTF). TRichEdit is a wrapper around the Windows RICHED32.DLL library that's also used by Windows WordPad to create and edit RTF files. RTF is a well-documented text format that's fully supported by Microsoft Word and OpenOffice.org.

TRichEdit is a handy control for creating or displaying simple reports, but if you try to use it for more than that you will be quickly disappointed because TRichEdit has serious limitations. For one thing, Borland never added support to TRichEdit for newer versions of the Rich Edit library (RICHED20.DLL). And although it's possible to hack the Delphi ComCtrls unit to add support for RICHED20.DLL, Microsoft never fixed some of the bugs in this library or supported more than just a subset of RTF.

Since Lazarus is a cross-platform tool, it doesn't provide a TRichEdit control. And even if it did, this type of control might not meet your needs. After all, TRichEdit is trying to be a word processor, something the creators of Word and OpenOffice.org have spent many years developing. Wouldn't it make more sense just to use an actual word processor to create and display reports?

Using TRtfParser to create RTF documents

With Windows, the easiest way to control a word processor externally from another program is to start the Word or OpenOffice.org Automation server and use the server to create, manipulate and display documents. But this is a Windows-only solution; OS X and Linux don't have an equivalent to Windows Automation.

Fortunately Free Pascal includes a unit named RtfPars that includes the TRtfParser class. While this class was designed to parse and proof existing RTF documents, you can also run it "backwards" to create RTF documents as well.

To simplify use of the TRtfParser class, the XDev Toolkit includes unit RtfDoc, which introduces a TRtfParser descendant, TRtfDoc, which can be used to create RTF files without knowing how TRtfParser works. For information on how to use it, look at the RtfDoc.pas file and TestRtfDoc.pas example program. You'll also want to look at the Free Pascal rtfdata.inc file for a list of constants that you'll need to use with TRtfDoc.

For more information on the RTF specification, refer to Microsoft's documentation.

Using Word and OpenOffice.org to display RTF documents

Assuming you can create your RTF report document as described in the previous section, you now need a way to display it with a word processor. With Windows, you would probably start the Word or OpenOffice.org Automation server, load the report document, then make the program visible so the user can browse, edit, print or save the report. To do this in a cross-platform way, you can instead shell to the word processor and pass the report file name on the command line. Here are the steps: The XDev Toolkit includes unit ViewDoc, which takes care of most of the details. The first two steps are handled by its ViewDocument function, to which you pass the document name and which word processor to use (Word or OO) and let it determine the word processor's location and launch it. The clean-up step is handled by the unit's DeleteViewedDocs function. For more information on how to use these functions, look at file ViewDoc.pas and ViewWith.pas, a test program that uses the ViewDoc unit.

Why would you need to clean up after launching the word processor? Usually this step is necessary because the report document will be a temporary file that you'll want to delete. You probably shouldn't require your users to name each report document that your program creates. This will quickly annoy them; it also forces your users to clean up the clutter of saved report documents. Instead, you should use the GetTempFilename function (in the Lazarus FileUtil unit) to get a file name to use for your temporary file, then delete this file yourself at some point after launching the word processor. (Don't use the same file name for all reports since this will restrict your users to viewing only one report at a time.)

But how can you delete a file if it's open in another program? Remember, your word processor is running externally to your program and locks the file as long as it's open. The file and the word processor won't be closed until the user decides to close them. And even if the file has already been closed, are you sure you want to delete it? What if your user made changes to the report and saved it?

The solution that ViewDocument uses is to start the word processor with a switch that tells it to create a new document based on the report file (that is, using it as a template). ViewDocument can also add the report file to a list of temporary files to be deleted when your program shuts down. Even though your program still can't delete the temporary file as long as the new document based on it is open in the word processor, this does mean that if the user saves the new document, it won't be with the report file's name.

To delete the temporary files created by your program, call the DeleteViewedDocs function in your main form's FormCloseQuery handler. If DeleteViewedDocs returns False, you can remind your user to save or close any reports still open in the word processor. DeleteViewedDocs is also called by the ViewDoc unit's finalization code to clean up whatever it can when the program finally does shut down.

One final note: With OS X, the normal way to start a program from a terminal command line or when shelling is to use the Open command. Unfortunately, the only parameter that Open passes along to the program is the name of the file to open, so there's no way to pass any switches to Word or NeoOffice. With OS X, ViewDocument instead sets the temporary report file to read-only, thus forcing the user to use a different name when saving the report. A disadvantage of this approach is that the word processor shows the name of the temporary file in the title bar (for example, rpt1.tmp) rather than Document1 or Untitled1 as it normally does with a new document. ViewDocument also uses this approach with AbiWord, which doesn't appear to support a command line template switch.


To Do

  1. Generalize MakeVer so it can use a Delphi .bdsproj file as input and also be able to output version information to a Lazarus .lpi file.

  2. Review Free Pascal's rtfdata.inc file for additional bugs.

Other Resources

http://wiki.lazarus.freepascal.org/The_Power_of_Proper_Planning_and_Practices

http://wiki.lazarus.freepascal.org/Multiplatform_Programming_Guide

http://wiki.lazarus.freepascal.org/OS_X_Programming_Tips

http://wiki.lazarus.freepascal.org/Deploying_Your_Application


Last updated: April 15, 2007