Re: [Lazarus] Email sending program using Indy stopped working - seems to be an SSL problem

2024-01-15 Thread Tony Whyman via lazarus
The default for SSLVersions is sslvTLSv1, so it looks like your mail 
server stopped accepting TLS v1.x (which it should do as older versions 
are now deprecated). I assume that you are using the out of date Openssl 
1.0.2 library or earlier, given that TIdSSLIOHandlerSocketOpenSSL does 
not work with later versions.


The underlying problem here is that the current Indy version does not 
support OpenSSL beyond 1.0.2. The next problem that you will hit is that 
your OS deprecates this version and you have to build and install 
Openssl 1.0.2 yourself (including any unfixed bugs).


This is already true in the Linux world where Debian 12 only provides 
OpenSSL 3.2. I am still using Mint 20.3 on my desktop, but that has also 
discontinued 1.0.2 with 1.1.1 being the provided version. I am not sure 
what is the status under Windows.


As I reported in my post to this thread on 13th, there is a proposed 
patch available to support OpenSSL 1.1.1 with a hint that the author is 
working on a patch for OpenSSL 3.2. It would be a good idea if all 
affected users could keep pushing, on the github issues list for Indy, 
in order to get this patch done as without it Indy is effectively end of 
life.



On 15/01/2024 07:32, Bo Berglund via lazarus wrote:

FINALLY:

After I posted on the Atozed forum I received a reply where a by me previously
unknown configuration item for TIdSSLIOHandlerSocketOpenSSL was suggested:

constructor TSvnMessage.Create;
begin
   FSvnUsers := TSvnUsers.Create;
   FSubscription := TStringList.Create;
   FSMTP := TIdSMTP.Create(nil);

   FSSLHandler := TIdSSLIOHandlerSocketOpenSSL.Create(nil);
   //Add this to set the scope of SSL versions allowed:
   FSSLHandler.SSLOptions.SSLVersions := [sslvTLSv1, sslvTLSv1_1, sslvTLSv1_2];

   FMailMessage := TIdMessage.Create(nil);
end;

This single line in the code for my mailer made it resume operations toward the
changed mail server!

Posting here in case someone wonders in the future about how to fix it.

Issue closed.-- 
___
lazarus mailing list
lazarus@lists.lazarus-ide.org
https://lists.lazarus-ide.org/listinfo/lazarus


Re: [Lazarus] Email sending program using Indy stopped working - seems to be an SSL problem

2024-01-13 Thread Tony Whyman via lazarus
I came across a similar problem recently with Indy and did some 
research. There is a proposed patch to support Openssl 1.1.1 and hence 
TLS1.3. This is discussed on github under


https://github.com/IndySockets/Indy/pull/299

with a proposed patch published under

https://github.com/mezen/Indy/tree/NewOpenSSL_PR

I have tested this proposed patch out with Lazarus/fpc. It is clearly 
work in progress and seems to have been frozen while a proper upgrade to 
Openssl 3.2. is developed. There is little by the way of additional 
documentation. However, I did get it working as a code library by


1. Adding to the unit path, in addition to the usual Lib/Core, 
Lib/Protocols and Lib/System, the


Lib/Protocols/OpenSSL

Lib/Protocols/OpenSSL/dynamic

directories, and adding to the include path

/Lib/FCL

2. Using the IdOpenSSLIOHandlerClient unit instead of the 
IdSSL,IdSSLOpenSSLunits.


3. For an http client using the TIdOpenSSLIOHandlerClient class instead 
of the TIdSSLIOHandlerSocketOpenSSLclass as the httpclient's SSLHandler 
(no need for any options).


4. compiling and fixing a compile time bug (stray ':' after and "out").

In my test program all then seemed to work fine with OpenSSL 1.1.1. and 
the updated Indy source.


On 13/01/2024 08:30, Michael Van Canneyt via lazarus wrote:



On Sat, 13 Jan 2024, Bo Berglund via lazarus wrote:

I wrote a commit reporting application for Windows Server16 back in 
2018 using

then current Lazarus/Fpc.
It is a command line program called from a hook in subversion to 
distribute the

log message and details of commits among co-workers.

It uses Indy 10.6.2 to do its job.
The mailer class has these in uses:
 {Indy units:}
 IdSMTP,
 IdMessage,
 IdEMailAddress,
 IdIOHandler,
 IdIOHandlerSocket,
 IdIOHandlerStack,
 IdSSL,
 IdSSLOpenSSL,
 IdExplicitTLSClientServerBase,
 IdMessageBuilder,

Back mid-december 2023 the emails stopped arriving but the problem 
was not
discovered/reported until I myself recently did a commit and I did 
not get the

expected log message email...

Now I have looked in the logfiles the application creates and found 
this error

example:

20240111 17:13:35.343 Connecting to mailserver
20240111 17:13:36.590 EXCEPTION: In SendSvnMessage = Error connecting 
with SSL.

error:1409442E:SSL routines:ssl3_read_bytes:tlsv1 alert protocol version

Can someone please advice:
- Is there an external (dll?) file on Windows Server 2016 might need 
to be

updated for ssl to work in email handling using Indy10 with SSL?


Indy 10 uses a completely outdated version of the SSL library, which does
not have the most recent cryptographic routines (notably for tls).

Most likely the server was updated and now rejects this old version.

There is of course a new version of the openssl library (3.2.x).
The interface of that library changed, but to the best of my 
knowledge, indy does not support it.


The sgcWebSockets suite has an updated version of openssl which should 
be able to

support openssl 3, but that is paying software..

Michael.-- 
___
lazarus mailing list
lazarus@lists.lazarus-ide.org
https://lists.lazarus-ide.org/listinfo/lazarus


Re: [Lazarus] Fritzbox TR64 communication

2021-08-19 Thread Tony Whyman via lazarus

Rolf,

You can use the Indy Component library available from 
https://github.com/IndySockets/Indy. This includes support for 
http/https and Digest Authentication.


A few years ago I did implement a SOAP based application using the Web 
Services Toolkit which also used Indy as a comms package.


See.

https://wiki.freepascal.org/Web_Service_Toolkit

Tony

On 19/08/2021 13:26, Rolf Wetjen via lazarus wrote:
Does anyone have some experience how to communicate via TR64 SOAP with 
a Fritzbox?


I've a working Python example (fritzconnection) and I know the 
neccesary http header and data for the SOAP communication.
AVM states that "The default authentication mechanism is HTTP 
authentication using digest (MD5 hashes)".


But I've no idea and I can't find an example how to implement this 
with Lazarus. Do I need a TfpHTTPClient or a TfpHTTPWebClient object 
or someting else? Is there any documentation or tutorial for FPC 
networking?


Thank you,
Rolf


--
___
lazarus mailing list
lazarus@lists.lazarus-ide.org
https://lists.lazarus-ide.org/listinfo/lazarus


Re: [Lazarus] Cross-platform using TRegistry - how to?

2020-05-04 Thread Tony Whyman via lazarus


On 04/05/2020 11:05, Bo Berglund via lazarus wrote:

On Mon, 4 May 2020 10:25:42 +0100, Tony Whyman via lazarus
 wrote:


As to the filename issue: the xml file location is determined from the
Vendor Name and application name and relative to $HOME/.config - is that
really a problem?

First off:
I would NOT use the Registry ever for my new applications...

Instead I would use conf files in ini file format so I can read/write
them using the TIniFile or TMemIniFile classes.
If you are thinking of a new Linux app then I would agree. You only use 
TRegistry if its cross-platform and you need to use the registry under 
Windows.


But my task now is to port a Windows service program which is
controlling the scheduling of external equipment operations.

It is a Windows service and thus non-gui but it implements a socket
communications channel whereby existing Windows (Delphi) applications
can control it by writing config data and look for results etc.

We can no longer use the service application on Windows going forward
because of Microsoft changes to drivers we rely on etc.
So the idea is to convert the service application to FPC/Lazarus and
then port it over to Linux.

So, being a service the server uses the Registry for all of its config
and task data on Windows and it would be simpler to port if I can
continue using that part of the system.
At first look TRegistry seems to handle this.

But there is a problem:

On Windows HKLM is a *global* hive and by what I hear here the
TRegistry implementation for Linux uses xml files instead and that is
no problem, provided that there is one only such file in use.
But if they are application specific then it will not work.
We use different applications to manage the server via the Registry
and this would not work then.


The model is like Windows in that you have both system wide and per user 
hives. If you want a group of applications under the same user to access 
the same registry XML file then you need to make sure that they are 
using the same AppConfigDir. You can ensure this by adding Vendor Name 
and Application Name callbacks so that your applications all use the 
same AppConfigDir.


The issue that you may find is when one process makes a change to the 
XML file that needs to be picked up by the others. Then you may need 
some IPC signalling to make that happen. There may even be a need for a 
lockfile to avoid race conditions - but then you would have the same 
problem with .conf files.




For example we have a local server configuration utility apart from
the TCP/IP socket connection and if I understand it right this
application would operate on a *different* xml file altogether so
whatever changes it makes to the "registry" will not be available to
the service application...

If this is so I need to reconsider the use of TRegistry and dig down
into changing to conf files (which can be global)...
Much more code to convert in that case.


--
___
lazarus mailing list
lazarus@lists.lazarus-ide.org
https://lists.lazarus-ide.org/listinfo/lazarus


Re: [Lazarus] Cross-platform using TRegistry - how to?

2020-05-04 Thread Tony Whyman via lazarus
I often use TRegistry for cross-platform configuration data and you 
should be able to use it and avoid having to maintain different Linux 
and Windows versions.


Under Linux, you are using TXMLRegistry and this saves registry data in 
an application specific XML file. There can be both a common XML file 
(HKEY_LOCAL_MACHINE) and a per user XML file (HKEY_CURRENT_USER). The 
file's location is always relative to the path returned by 
Sysutils.GetAppConfigDir. I create separate TRegistry instances for 
HKEY_LOCAL_MACHINE and HKEY_CURRENT_USER.


In the per user case, the filename is $HOME/.config/name>//xml.reg, where the vendor and application names 
are set by the callbacks OnGetVendorName (default '') and 
OnGetApplicationName (default exe file name) in Sysutils.


Note that the HKEY_LOCAL_MACHINE xml file is probably in a read only 
location unless you are root.


Otherwise, you just keep the same keynames and values as in Windows 
registry. As reported elsewhere, if you insist on having more than one 
instance of TRegistry (for the same root key) at any one time, you 
cannot assume that the keyname is preserved when switching between 
TRegistry instances, and must (for now) always set the keyname before 
accessing a value.


On 03/05/2020 23:40, Bo Berglund via lazarus wrote:

I am porting a Windows service application to Linux ARM (RPi4).
The Windows version is a service and as such its config data resides
in the Registry below HKLM.
The Linux version will be a Daemon and I would like as much of the
code stay unaltered to avoid conversion bugs.

Now I have read that the FPC TRegistry class is able to use the
original commands for reading/writing the data by instead using some
form of ini- or xml-file store on UNIX.

The existing system written in Delphi2007 uses the following key
structure:
HKLM\SOFTWARE\Companyname\Applicationname\Server\(named values)
HKLM\SOFTWARE\Companyname\Applicationname\Configuration\(named values)

But how does this work and where/how are the data actually stored in a
Linux file system?

I have tried to google this but my search skills are not good enough
so I came up empty-handed

Any insight on this very much appreciated.


--
___
lazarus mailing list
lazarus@lists.lazarus-ide.org
https://lists.lazarus-ide.org/listinfo/lazarus


Re: [Lazarus] Cross-platform using TRegistry - how to?

2020-05-04 Thread Tony Whyman via lazarus
Firstly, the question is about TRegistry and not TRegIniFile. On a *nix 
platform TRegistry is implemented using TXMLRegistry and not TRegIniFile.


You should only have a single instance of a TXMLRegistry in any one 
program no matter how many times you create a TRegistry object - they 
all point to the same instance. From a quick check of the code, it looks 
like the problem identified in the bug report  is fairly obvious - the 
current key state is held in TXMLRegistry rather than TRegistry. The fix 
should be to hold the current key state in TRegistry and call 
TXMLRegistry.SetKey before every get or put call on TXMLRegistry (from 
TRegistry).


TRegistry is a very useful way of saving dynamic configuration data 
(e.g. mainform co-ordinates) in order to preserve them from one program 
session to another - and to do so in a cross-platform manner. IMHO. it 
would be a significant loss if it was to be deprecated. I use it all the 
time.


As to the filename issue: the xml file location is determined from the 
Vendor Name and application name and relative to $HOME/.config - is that 
really a problem?


TXMLRegistry writes are normally flushed to disk after every write. Two 
program instances using the same registry keys can get in each other's 
way with one over-writing the other's updates - but then that is also 
true of .conf and .ini files - and even the Windows registry.


On 04/05/2020 08:29, Bart via lazarus wrote:

On Mon, May 4, 2020 at 12:41 AM Bo Berglund via lazarus
 wrote:

structure:
HKLM\SOFTWARE\Companyname\Applicationname\Server\(named values)
HKLM\SOFTWARE\Companyname\Applicationname\Configuration\(named values)

The *nix way is to use .conf files (basically ini-files) for that.
IIRC you have no control over where the xml file (with the registry
keys) is placed.
There are some issues with the xml implementation of the registry.
Most important: TRegIniFile is completely broken and as of 3.2
deprecated on non-windows platforms.
Also, when you have 2 keys opened at the same time, reading/writing
may go to/from the wrong key:
https://bugs.freepascal.org/view.php?id=36842

For a cross-platform application I wouldn't use TRegistry myself.

Bart

--
___
lazarus mailing list
lazarus@lists.lazarus-ide.org
https://lists.lazarus-ide.org/listinfo/lazarus


Re: [Lazarus] Adding Required Packages paths... dynamically

2019-07-19 Thread Tony Whyman via lazarus
My understanding is that when you add a "required package" what actually 
happens is that the IDE adds the package unit paths to the list of unit 
paths for your project, and adds the top level .pas file for the package 
(which usually has the same name as the package) to the "uses" clause in 
your project source file. The latter may not happen if an option is set 
in the package itself.


The result is that the package files get linked into your project. 
However, if you make the top level .pas file find a conditional 
reference from the uses clause then the package files only get linked in 
when the conditional is true.


Of course you also must do the same for any other units from the package 
that you include in your own unit files i.e. make their use conditional 
as well.


On 19/07/2019 14:21, Marcos Douglas B. Santos via lazarus wrote:

Maybe adding "dynamically" the Required Package, rather using
"dynamically paths" by Conditionals, could fix this?
But how to do this?

Just to be more clear, I don't have any "Duplicate units" as compiler is saying!
Thanks.

regards,
Marcos Douglas

--
___
lazarus mailing list
lazarus@lists.lazarus-ide.org
https://lists.lazarus-ide.org/listinfo/lazarus


Re: [Lazarus] IDE

2019-03-15 Thread Tony Whyman via lazarus
My guess is that you are using Windows ;) If you are using Linux then 
there is a problem with your distro's library manager.


I am sure that it is recommended practice by MS to install dependencies 
in an application's folder. Otherwise there is a risk of stealth 
upgrades/downgrades. For that reason, IBX always checks the application 
folder first when looking for the Firebird DLL and only uses the 
registry to locate it and other well known locations, if it can't find 
it there. I would be surprised if Lazarus's SQL objects don't work that 
way as well.


On 15/03/2019 16:31, Eurico JB Silva via lazarus wrote:

Dear,

After retiring, I met Lazarus and I really enjoyed this IDE, for 
several reasons. However, I realized that objects that access Database 
of different types (PostgreSQL, MySQL, SQLite, etc.), require an 
effort to make it work. So, like the vast majority, I downloaded 
*ZeosLib* and as a step of magic everything worked right away.


So I decided to analyze the sources of *ZeosLib* to try to understand 
why, and it seems that the objects included in Lazarus require the 
libraries with their most precise configuration on the machine where 
the application is installed. *ZeosLib* allows the same libraries to 
be present in the same application installation folder. So I'd like to 
suggest that those objects that are already part of Lazarus may have 
the same behavior, so you do not need to download any other object to 
access the database.


A hug to everyone.

--

Eurico JB Silva
#22-992089960


-- 
___
lazarus mailing list
lazarus@lists.lazarus-ide.org
https://lists.lazarus-ide.org/listinfo/lazarus


Re: [Lazarus] TLabel or TStaticText?

2019-03-15 Thread Tony Whyman via lazarus
Using a TPanel as a container is generally good advice for similar 
problems with all TGraphicControl descendents. I often use a TPanel to 
contain a TImage for this reason.


Perhaps the point that needs to come across is that TLabel is a 
TGraphicControl and is drawn by the LCL, while TStaticText is a 
TWinControl descendent (as is TPanel) and is drawn by the underlying 
"interface" e.g. GTK2. They thus behave differently e.g. with Z-order.


On 15/03/2019 14:04, Mattias Gaertner via lazarus wrote:

On Fri, 15 Mar 2019 14:42:52 +0100
frans via lazarus  wrote:


I thougth of that, but I need the focus on the original form. The
mesaage is only informative, all the functionality must be availabe.

mvg
Frans van Leeuwen
M 06-51695390

Op 15-3-2019 om 14:08 schreef John Landmesser via lazarus:

what about a new form with FormStyle := fsSystemStayOnTop ?!

Am 15.03.19 um 12:37 schrieb frans via lazarus:

Hi,

I'm using Lazarus 1.8.4 on Win10. In my application I have a Form
with 2 functions. (1) Is to download files from an internet server
using ftp, (2) is to store the data from those files in the
datacollection.
Sometimes I loose my internet connection and in that case I want
to show a warning in the the middle of the form and in front of
all the other components. For the warning I use a TLabel component
for the layout parameter tlCenter. But the label is partly hidden
behind another component (TFileListBox) and BringToFront doesn't
help. Now I tried a TStaticText component and that works just
fine. Except that it has no Layout property and no Paint procedure
I could override. Is there a component that gives me all the
behaviour I want? Is there a way to bring the TLabel realy in
front of all other components? Is there a way to vertical align
the text of a TStaticText caption?

You can put the TLabel inside a TPanel.

Mattias

--
___
lazarus mailing list
lazarus@lists.lazarus-ide.org
https://lists.lazarus-ide.org/listinfo/lazarus


Re: [Lazarus] Tools for self-extracting executables?

2019-02-18 Thread Tony Whyman via lazarus
Before spending any time on this I would look at the Open Source 7-zip 
compression utility (https://www.7-zip.org/). This is available for both 
Windows and Linux and I use it to package my own Windows/FPC/Lazarus 
builds for self-extraction and installation under Windows (I also use 
Microsoft WIX to build the MSI files).


7z is readily scripted to archive your files into a single zip. All you 
then need to do is to concatenate a pre-built 7z.sfx stub executable 
with a text file containing the installation parameters and the zip 
file. The result is a self-extracting archive. This is described in its 
documentation under the -sfx (Create SFX archive) switch.


On 18/02/2019 12:59, Chavoux Luyt via lazarus wrote:


Hi all,

Many moons ago I wrote small self-extracting executable programs in 
Delphi... the executable would basically include both the program 
itself as well as some INI and data files; when running it would 
access itself on disk, find the addresses within the exe file where 
each data file starts (and its size) and then extract and write them 
to disk. I think I installed a component for this in Delphi. The 
component would both create the self-extracting exe and be included in 
the exe in order to extract the files.


Before I start writing something from scratch, I just wanted to ask if 
there are any such components (or components that would make writing 
it easier) for Lazarus?


Thanks in advance!
Chavoux


-- 
___
lazarus mailing list
lazarus@lists.lazarus-ide.org
https://lists.lazarus-ide.org/listinfo/lazarus


Re: [Lazarus] Fwd: TRadioGroup not found error

2019-01-01 Thread Tony Whyman via lazarus

Tom,

I made transition from Delphi about 9 years ago and never looked back. 
Yes, there are some conceptual differences, especially in the way the 
IDE works and which you have to get your head around but, generally, the 
problems are to do with the occasional name change for library 
functions, or the need to include a different mix of units and these can 
usually be resolved quickly at compile time.


Looking at your comments, I am trying to work out where you are going 
wrong. Further down the EMail, you seem to be tripping over problems 
with which units to include. Expect this as a one-off cost of moving 
from Delphi to Lazarus. The easiest way of resolving the problem with 
LCL objects is to just drop another copy of the object on the form, save 
the form and then delete the new object. The effect is to add the 
missing unit to the uses clause.


EClassNotFound is an odd one. This is a run time error in the streaming 
system - which is very similar to Delphi's streaming system. It suggests 
that you have somehow managed to include a .lfm file that includes a 
reference to a TButton, while the corresponding .pas has lost the Form's 
reference to the button.


e.g. a line such as

FButton1: TButton;

is missing. I would search the .pas file for a match on "TButton".

This can be the result of a simple "fat finger" error deleting a line by 
mistake - I have done that myself, but normally this results in an error 
message that tells you that the form reference is missing. However, if 
this was the only reference and stdctrls is not otherwise linked in then 
perhaps the error you are seeing is the result.


Referring to your point about Delphi /lib, your problem here may be the 
difference between Delphi and Lazarus packages.


It's probably best to think of Lazarus packages as compile time 
conveniences rather than as code libraries that are nicely packaged 
together in a single file. When you create a GUI application in Lazarus, 
you automatically get the LCL package "added" to you project. Its 
compiled units path then gets included in the Project's compiler and 
linker search paths. The same thing happens when you include a component 
in a third party package. You can also explicitly add packages as "New 
Requirements".


To see this in action, in any GUI Lazarus project open the Project 
Options dialog, select "Compiler Options->Compilation and Linking" in 
the left hand pane and then click on the "Show Options button. You 
should then see the full list of options passed to the compiler 
including each package's units directory. This feature is your friend 
when you are trying to work out why a unit is "not found".


When you compile a project, any dependent packages should also get 
compiled if their source code has been modified since they were last 
compiled, their object code then gets linked into the program.


Your problem with your TIndexString unit may have a similar root.

When you add a unit to a project, if its path is not already in the 
project's search path, this should get added - and you can see the 
result with "Show Options". If the unit is not added or, in particular, 
when its search path is not included in the project's "Other Unit paths" 
then the compiler will not able to find it.


Hope the above helps - it really is worth making the effort to move to 
Lazarus.


Regards

Tony Whyman

MWA Software


On 01/01/2019 02:44, Thomas Crone via lazarus wrote:
If this is not the right forum for this,  Please tell me where I can 
post it.


I am getting the same type of message as I got a few weeks ago:

   … '‘EClassNoFound’  with message:
   Class ‘TButton’ not found
   at address 10004A515

I have tried to move to Lazarus from Delphi 4 several times over the 
past 5 or 6 years,

and always given up in frustration.

Errors seem to pop up, go away , and come back for no apparent 
reasons. (some of that,

of course, could be windows problems…)

I’ve been programming since 1970, first in FORTRAN II, then Algol, 
Simula, snobol, icon,
DEC10 assembly, various BASICs, Pascal (Turbo V2 thru Delphi, and on 
VAX VMS), etc.

The most recent new language was python on the Raspberry Pi.

Before I retired a few years ago, I volunteered to help with the 
Lazarus documentation,
when I couldn’t figure out how to move my collection of units (2D & 3d 
geometry, i/o routines,
geographic projections & mapping, music synthesis, etc.) to Lazarus. 
In Delphi, I could just
put the .dcu files in the Delphi /lib directory; for the programs I’m 
now working on, I had to

include the entire source of my TIndexString unit in the program source.

maybe I should rewrite all my objects in python…

Tom Crone

Begin forwarded message:

*From: *Thomas Crone mailto:cr...@cua.edu>>
*Subject: **Re: [Lazarus] TRadioGroup not found error*
*Date: *December 15, 2018 at 9:42:45 PM EST
*To: *Lazarus mailing list >


I had some of the TForm as private and some not.

When I took everything 

Re: [Lazarus] derived forms and frames

2018-09-22 Thread Tony Whyman via Lazarus

Franz,

It sounds like we a share a programming style as I also use lots of 
derived forms and frames.


You have to use packages if you are going to work with Lazarus in this 
way. Create a run-time package for your framework forms and frames and 
their dependencies - you may even want more than one package  in order 
to structure your framework properly and to avoid having a unit in 
multiple packages. Work out the package hierarchy that works best for you.


Create a design time package which registers the forms and other 
components that you want to appear on the palette, plus any property 
editors you need. You may also want to call "RegisterNoIcon" for any 
TFrame descendents that your framework uses. This allows the IDE to 
quickly find the parent class for a derived frame.


The ProjectTemplates package is also very useful here if you have any 
project templates you need to register.


You will have to recompile Lazarus when you add new design time packages 
- but that's just how Lazarus works. You will not have to re-compile 
Lazarus every time you change a unit in a run-time package - that's only 
necessary if you change the design time behaviour of a unit.


When you use your framework in your project, your run-time packages 
should automatically get included if you use a form from your design 
time package - otherwise just add them yourself. There is no need to 
explicitly include in your project a unit define in a package on which 
the project depends.


Tip: If you are editing a frame/form make sure that any descendent 
frames/forms are closed, otherwise you will find that their inherited 
property values are decoupled from the parent frame/form.


Hope this helps.

Regards

Tony Whyman

MWA


On 21/09/18 14:03, Franz Müller via Lazarus wrote:

Hello everybody!

I have been developing programs in Delphi for many years (and even 
before in turbo Pascal).
I would like to switch all my programming from Delphi to Lazarus / 
Free Pascal.


Now I have encountered a serious issue that I don't know how to deal 
with.
I have built a complex framework that I use in my programs. This 
frameworks includes form templates and frame templates from which I 
derive most of the forms of a project. In order to be able to derive a 
new form from a form tempate easily with the means of the lazarus IDE, 
the form template must be part of the project - I don't see another 
way to have a form shown in the menu "file - new".
But in order to make new published properties of the template form 
available in the object inspector, the template form must be compiled 
as part of a package.
But for good reasons it is strongly disadvised to use the same file in 
a package and as part of the project at the same time.


Of course, I could manually modify the source for every new unit that 
I create, but that would be rather cumbersome and error prone.


I would like to ask if there is a solution to the problem that I am 
not aware of - otherwise I would file a feature request. I feel that 
the ability to use forms and frames derived from TForm and TFrame as a 
base for new forms is a very important feature to build an efficient 
programming framework, and this programming framework should not be 
required to be part of every project that uses it. I would suggest a 
procedure similar to "register",  which should place a menu entry for 
a form or a frame from a package into the menu tree "file - new", just 
like register places a component into the component palette.


Best regards
Franz



--
___
Lazarus mailing list
Lazarus@lists.lazarus-ide.org
https://lists.lazarus-ide.org/listinfo/lazarus


Re: [Lazarus] Encrypted connection between Lazarus and Firebird

2018-04-11 Thread Tony Whyman via Lazarus

The first question is a Firebird question.

With Firebird 3, you can configure use of the Srp user authentication 
module and "over-the-wire" encryption. This should give you an encrypted 
connection between client and server. The settings for this are in the 
"firebird.conf" config file.


This should work with all Lazarus database components that support the 
use of a Firebird database (e.g. IBX).


As to the second question - I'll let someone else answer that one - but 
the answer is probably similar.


Tony Whyman

MWA


On 11/04/18 11:25, Kamen Ketev via Lazarus wrote:


Can I make an encrypted connection between Lazarus and Firebird? What 
components should I use?


Can I make an encrypted connection between Lazarus and Microsoft SQL 
Server? What components should I use?


Regards,
Kamen





-- 
___
Lazarus mailing list
Lazarus@lists.lazarus-ide.org
https://lists.lazarus-ide.org/listinfo/lazarus


Re: [Lazarus] How to catch an unhandled exception? [FIXED - but there is an FPC bug here]

2018-03-09 Thread Tony Whyman via Lazarus
A supplementary for anyone confused by the last extra parameter to 
SetString in the previous post (repeated below). When I wrote up the bug 
report, I should have gone one step lower in the code. The SetString 
commented out below is actually an internal function:


procedure TOutputBlockItem.SetString(out S: AnsiString; Buf: PByte;
  Len: integer; CodePage: TSystemCodePage);
var rs: RawByteString;
begin
  system.SetString(rs,PAnsiChar(Buf),len);
  SetCodePage(rs,CodePage,false);
  S := rs;
end;

However, the same result (e.g. the bug disappears) is achieved by 
commenting out the call to system.Setstring.



On 09/03/18 11:09, Tony Whyman via Lazarus wrote:


Thanks to Giuliano mentioning debug libraries I have been able to 
duplicate the problem and to find the source of the bug - but it is as 
weird as it gets.


FYI: tests done on Linux Mint 18 with Lazarus 1.8.0 and fpc 3.0.4.

The evidence so far:

1. Gabor's program ends with an exception when using the FPC release  
RTL and FCL, but not when using RTL and FCL libraries compiled for 
debugging.


2. If I use GDB to step through the final steps of the program, the 
bug disappears!


3. If I add a delay at the end (e.g. a call to sleep(1)), the bug 
disappears.


4. Playing around with code optimisations and debugging flags seems to 
have no effect.


5. Using the age old technique of commenting out bits of the code 
until the bug disappears, I tracked the problem down.


In Gabor's program, the bug is removed by commenting out this line 
(shown in context)


  for i:=0 to SQR.GetCount-1 do
   begin
 case SQR[i].getItemType of isc_info_svc_line:begin
// s:=SQR[i].getAsString;  {This is where the problem starts}
  end;
 end;
 if (s<>'') then WriteLn(s);
   end;

Going deeper into the fbintf package, I have further tracked the 
problem down to this line of code


SetString(Result,FBufPtr+3,len,CP_ACP);

FBufPtr is a pointer and it is fairly simple bit of code, copying a 
string from a buffer (received from Firebird) into an AnsiString. 
Commenting out the line stops the bug. The bug also goes away by 
changing it to


var s: string;
  i: integer;

...
 Result := '';
  SetString(s,FBufPtr+3,len,CP_ACP);
  for i := 1 to length(s) do
    Result += s[i];

which can only be described as a WTF moment. The problem has to be due 
to string disposal.


Finally, knowing all this, I go back to Gabor's program and add the 
line (again shown in context):


   repeat
  SQR:=SM.Query(nil,SRB);
  for i:=0 to SQR.GetCount-1 do
   begin
 case SQR[i].getItemType of isc_info_svc_line:begin
s:=SQR[i].getAsString;
  end;
 end;
 if (s<>'') then WriteLn(s);
 s := ''; {Line added here}
   end;
    until (s='');

and guess what - bug goes away.

It looks like what is happening is that SetString is setting an 
AnsiString in such as away as to cause a problem when the memory 
manager cleans up - but only as a race condition and if the string is 
not cleaned up explicitly.


Looks like an FPC bug report to me.

On 09/03/18 09:14, Gabor Boros via Lazarus wrote:

Hi All,

The result of the attached example (which use MWA's Firebird Pascal 
API) for me is an exception:



Gstat execution time Fri Mar  9 09:29:18 2018

Database header page information:
    Flags   0
    Generation  173
    System Change Number    0
    Page size   8192
    ODS version 12.0
    Oldest transaction  161
    Oldest active   162
    Oldest snapshot 162
    Next transaction    164
    Sequence number 0
    Next attachment ID  27
    Implementation  HW=AMD/Intel/x64 little-endian 
OS=Linux CC=gcc

    Shadow count    0
    Page buffers    0
    Next header page    0
    Database dialect    3
    Creation date   Feb 2, 2018 14:07:24
    Attributes  force write

    Variable header data:
    *END*
Gstat completion time Fri Mar  9 09:29:18 2018

Heap dump by heaptrc unit
355 memory blocks allocated : 948252/948432
355 memory blocks freed : 948252/948432
0 unfreed memory blocks : 0
True heap size : 131072
True free heap : 131072
An unhandled exception occurred at $7FF97F0A3147:
EAccessViolation:
  $7FF97F0A3147


If comment out cthreads from the uses the exception is:


An unhandled exception occurred at $7F21B71F5147:
EAccessViolation:
  $7F21B71F5147
  $7F21B71F751B
  $7F21B71F769C
  $7F21B746BFFF


If run with gdb (and cthreads):


Heap dump by heaptrc unit
355 memory blocks allocated : 948252/948432
355 memory blocks freed : 948252/948432
0 unfreed memory blocks : 0
True heap size : 131072
True free heap : 131072
[Thread 0x75991700 (LWP 2874) exi

Re: [Lazarus] How to catch an unhandled exception? [FIXED - but there is an FPC bug here]

2018-03-09 Thread Tony Whyman via Lazarus
Thanks to Giuliano mentioning debug libraries I have been able to 
duplicate the problem and to find the source of the bug - but it is as 
weird as it gets.


FYI: tests done on Linux Mint 18 with Lazarus 1.8.0 and fpc 3.0.4.

The evidence so far:

1. Gabor's program ends with an exception when using the FPC release  
RTL and FCL, but not when using RTL and FCL libraries compiled for 
debugging.


2. If I use GDB to step through the final steps of the program, the bug 
disappears!


3. If I add a delay at the end (e.g. a call to sleep(1)), the bug 
disappears.


4. Playing around with code optimisations and debugging flags seems to 
have no effect.


5. Using the age old technique of commenting out bits of the code until 
the bug disappears, I tracked the problem down.


In Gabor's program, the bug is removed by commenting out this line 
(shown in context)


  for i:=0 to SQR.GetCount-1 do
   begin
 case SQR[i].getItemType of isc_info_svc_line:begin
// s:=SQR[i].getAsString;  {This is where the problem starts}
  end;
 end;
 if (s<>'') then WriteLn(s);
   end;

Going deeper into the fbintf package, I have further tracked the problem 
down to this line of code


SetString(Result,FBufPtr+3,len,CP_ACP);

FBufPtr is a pointer and it is fairly simple bit of code, copying a 
string from a buffer (received from Firebird) into an AnsiString. 
Commenting out the line stops the bug. The bug also goes away by 
changing it to


var s: string;
  i: integer;

...
 Result := '';
  SetString(s,FBufPtr+3,len,CP_ACP);
  for i := 1 to length(s) do
    Result += s[i];

which can only be described as a WTF moment. The problem has to be due 
to string disposal.


Finally, knowing all this, I go back to Gabor's program and add the line 
(again shown in context):


   repeat
  SQR:=SM.Query(nil,SRB);
  for i:=0 to SQR.GetCount-1 do
   begin
 case SQR[i].getItemType of isc_info_svc_line:begin
s:=SQR[i].getAsString;
  end;
 end;
 if (s<>'') then WriteLn(s);
 s := ''; {Line 
added here}

   end;
    until (s='');

and guess what - bug goes away.

It looks like what is happening is that SetString is setting an 
AnsiString in such as away as to cause a problem when the memory manager 
cleans up - but only as a race condition and if the string is not 
cleaned up explicitly.


Looks like an FPC bug report to me.

On 09/03/18 09:14, Gabor Boros via Lazarus wrote:

Hi All,

The result of the attached example (which use MWA's Firebird Pascal 
API) for me is an exception:



Gstat execution time Fri Mar  9 09:29:18 2018

Database header page information:
    Flags   0
    Generation  173
    System Change Number    0
    Page size   8192
    ODS version 12.0
    Oldest transaction  161
    Oldest active   162
    Oldest snapshot 162
    Next transaction    164
    Sequence number 0
    Next attachment ID  27
    Implementation  HW=AMD/Intel/x64 little-endian 
OS=Linux CC=gcc

    Shadow count    0
    Page buffers    0
    Next header page    0
    Database dialect    3
    Creation date   Feb 2, 2018 14:07:24
    Attributes  force write

    Variable header data:
    *END*
Gstat completion time Fri Mar  9 09:29:18 2018

Heap dump by heaptrc unit
355 memory blocks allocated : 948252/948432
355 memory blocks freed : 948252/948432
0 unfreed memory blocks : 0
True heap size : 131072
True free heap : 131072
An unhandled exception occurred at $7FF97F0A3147:
EAccessViolation:
  $7FF97F0A3147


If comment out cthreads from the uses the exception is:


An unhandled exception occurred at $7F21B71F5147:
EAccessViolation:
  $7F21B71F5147
  $7F21B71F751B
  $7F21B71F769C
  $7F21B746BFFF


If run with gdb (and cthreads):


Heap dump by heaptrc unit
355 memory blocks allocated : 948252/948432
355 memory blocks freed : 948252/948432
0 unfreed memory blocks : 0
True heap size : 131072
True free heap : 131072
[Thread 0x75991700 (LWP 2874) exited]
[Thread 0x76192700 (LWP 2873) exited]
[Thread 0x77fe3740 (LWP 2869) exited]
Cannot find user-level thread for LWP 2875: generic error


Any idea how to detect what/where is the source of the exception?

I use Linux 64bit, FPC 3.0.4 and Lazarus fixes_1_8.

Gabor




-- 
___
Lazarus mailing list
Lazarus@lists.lazarus-ide.org
https://lists.lazarus-ide.org/listinfo/lazarus


Re: [Lazarus] How to catch an unhandled exception?

2018-03-09 Thread Tony Whyman via Lazarus

Giulian,

You may in a roundabout way have pointed me at where the problem lies. I 
always work with fpc debug libraries as well and I can't catch the 
problem. I changed to the standard release and the bug appears! 
Unfortunately, while duplicating the problem is one thing, tracking it 
down when your main debugging tool is unavailable is another...


Tony Whyman

MWA


On 09/03/18 09:56, Giuliano Colla via Lazarus wrote:

Il 09/03/2018 10:14, Gabor Boros via Lazarus ha scritto:


Any idea how to detect what/where is the source of the exception?

I use Linux 64bit, FPC 3.0.4 and Lazarus fixes_1_8. 


To obtain meaningful information from gdb I do the following:
1) Compile both Lazarus LCL and fpc with debug info
2) Install the glibc-debuginfo packages
Otherwise you get only the information about exceptions which generate 
directly from your source code, which is many cases isn't sufficient.


Hope that it helps,

Giuliano


--
___
Lazarus mailing list
Lazarus@lists.lazarus-ide.org
https://lists.lazarus-ide.org/listinfo/lazarus


Re: [Lazarus] How to catch an unhandled exception?

2018-03-09 Thread Tony Whyman via Lazarus

Gabor,

I can't duplicate your problem which probably implies that we are 
looking at some weird race condition during the program tidy up phase. I 
did see occasionally something like this before with Lazarus 1.6.4 on 
Windows with heaptrc - but I never saw it without heaptrc and it cleared 
up with Lazarus 1.8 and hence  I never bothered to pursue it assuming 
that it was a Lazarus bug that got fixed.


You are seeing this problem not so much with IBX, but with the Firebird 
Pascal API. Your example program has excluded the IBX part and focused 
purely on the API.


What might be an issue here is that the FirebirdAPI is accessed via a 
COM interface and the IFirebirdAPI interface is not explicitly released. 
The software just relies upon the system to clean it up at the end. 
There may be a race condition here between the clear up of the interface 
and the dynamic library manager. This is because when the interface is 
released, it then unloads the Firebird DLL/SO. Try adding a finalization 
clause to IB.pas setting "FFirebirdAPI := nil" and see if that clears it 
up - or whether the exception occurs before this point.


It is not obvious if there is a real issue with cthreads. The library 
should only create multiple threads when handling asynchronous Firebird 
events and your program is not using this capability.


Otherwise, yes, it would be really useful to be able to find where this 
exception is being raised.


Tony Whyman

MWA


On 09/03/18 09:14, Gabor Boros via Lazarus wrote:

Hi All,

The result of the attached example (which use MWA's Firebird Pascal 
API) for me is an exception:



Gstat execution time Fri Mar  9 09:29:18 2018

Database header page information:
    Flags   0
    Generation  173
    System Change Number    0
    Page size   8192
    ODS version 12.0
    Oldest transaction  161
    Oldest active   162
    Oldest snapshot 162
    Next transaction    164
    Sequence number 0
    Next attachment ID  27
    Implementation  HW=AMD/Intel/x64 little-endian 
OS=Linux CC=gcc

    Shadow count    0
    Page buffers    0
    Next header page    0
    Database dialect    3
    Creation date   Feb 2, 2018 14:07:24
    Attributes  force write

    Variable header data:
    *END*
Gstat completion time Fri Mar  9 09:29:18 2018

Heap dump by heaptrc unit
355 memory blocks allocated : 948252/948432
355 memory blocks freed : 948252/948432
0 unfreed memory blocks : 0
True heap size : 131072
True free heap : 131072
An unhandled exception occurred at $7FF97F0A3147:
EAccessViolation:
  $7FF97F0A3147


If comment out cthreads from the uses the exception is:


An unhandled exception occurred at $7F21B71F5147:
EAccessViolation:
  $7F21B71F5147
  $7F21B71F751B
  $7F21B71F769C
  $7F21B746BFFF


If run with gdb (and cthreads):


Heap dump by heaptrc unit
355 memory blocks allocated : 948252/948432
355 memory blocks freed : 948252/948432
0 unfreed memory blocks : 0
True heap size : 131072
True free heap : 131072
[Thread 0x75991700 (LWP 2874) exited]
[Thread 0x76192700 (LWP 2873) exited]
[Thread 0x77fe3740 (LWP 2869) exited]
Cannot find user-level thread for LWP 2875: generic error


Any idea how to detect what/where is the source of the exception?

I use Linux 64bit, FPC 3.0.4 and Lazarus fixes_1_8.

Gabor




-- 
___
Lazarus mailing list
Lazarus@lists.lazarus-ide.org
https://lists.lazarus-ide.org/listinfo/lazarus


Re: [Lazarus] Garbage writing to console

2018-02-22 Thread Tony Whyman via Lazarus
You may find the "SetTextCodePage" procedure useful when it comes to 
setting the code page for a Windows console.


e.g. SetTextCodePage(stdout,cp_utf8);

See also 
https://www.freepascal.org/docs-html/rtl/system/settextcodepage.html



On 22/02/18 11:21, Luca Olivetti via Lazarus wrote:
Lazarus 1.8.0, fpc 3.0.4, windows application (with "win32 gui 
application unchecked") or console application (using LazUTF8).

File encoding utf-8 without bom.

writeln('áéí')

produces garbage, contrary to what's said in 
http://wiki.freepascal.org/Unicode_Support_in_Lazarus#Writing_to_console


using {$codepage utf8} (or utf-8 with bom) fixes it, but I'm not sure 
it's recommended to do so: 
http://wiki.freepascal.org/Unicode_Support_in_Lazarus#String_Literals


The strange thing is that:

procedure w(const s:string);
begin
  writeln(s);
end;

w('áéí')


also gives the correct output.
Why? After all I'm using the same string literal.
I suppose there's some underlying automatic conversion going on, but 
it's very confusing.


Bye


--
___
Lazarus mailing list
Lazarus@lists.lazarus-ide.org
https://lists.lazarus-ide.org/listinfo/lazarus


[Lazarus] Fixes_1_8 branches fails to compile

2017-11-29 Thread Tony Whyman via Lazarus
After last night's update from svn, my copy of the 1.8 fixes branch 
fails to compile with the following error:


/tmp/lazarus/components/codetools/codecompletiontool.pas(7094,18) Error: 
(5038) identifier idents no member "GetPriorAtom"
codecompletiontool.pas(9802) Fatal: (10026) There were 1 errors 
compiling module, stopping

Fatal: (1018) Compilation aborted
Makefile:2767: recipe for target 'codetools.ppu' failed
make[1]: *** [codetools.ppu] Error 1
make[1]: Leaving directory '/tmp/lazarus/components/codetools'
Makefile:3241: recipe for target 'codetools' failed
make: *** [codetools] Error 2


--
___
Lazarus mailing list
Lazarus@lists.lazarus-ide.org
https://lists.lazarus-ide.org/listinfo/lazarus


Re: [Lazarus] String vs WideString

2017-08-18 Thread Tony Whyman via Lazarus

Damn, should remember never to copy and paste from Wikipedia!


On 17/08/17 13:40, Michael Schnell via Lazarus wrote:

On 17.08.2017 12:41, Tony Whyman via Lazarus wrote:


Finally: "In UTF-16, code points greater or equal to 2^16 are encoded 
using /two/ 16-bit code units.

2¹⁵ ???
-Michael




-- 
___
Lazarus mailing list
Lazarus@lists.lazarus-ide.org
https://lists.lazarus-ide.org/listinfo/lazarus


Re: [Lazarus] String vs WideString

2017-08-17 Thread Tony Whyman via Lazarus

On 16/08/17 11:05, Juha Manninen via Lazarus wrote:

2. Clean up the char type.

...
Why shouldn't there be a single char type that intuitively represents
a single character regardless of how many bytes are used to represent it.

What do you mean by "a single character"?
A "character" in Unicode can mean about 7 different things. Which one
is your pick?
This question is for everybody in this thread who used the word "character".
Are you making my points for me? If such a basic term as "character" 
means 7 different things then something is badly amiss. It should be 
fairly obvious that in this context, character = printable symbol - 
whilst for practical reasons allowing for format control characters such 
as a "end of line" and "end of string".


I believe that you need to go back to the idea that you have both an 
abstract representation of a character with a constant semantic, 
separate from the actual encoding and for which there may be many 
different and valid encodings. For example, using a somewhat dated 
comparison, a lower case latin alphabet letter 'a' should always have a 
constant semantic, but in ASCII is encoded as decimal 97, while in 
EBCDIC is encoded as decimal 129. Even though they have different binary 
values, the represent the same abstract character.


I want a 'char' type in Pascal to represent a character such as a lower 
case 'a' regardless of the encoding used. Indeed, for a program to be 
properly portable, the programmer should not have to care are the actual 
encoding - only that it is a lower case 'a'.


Hence my proposal that a character type should include an implicit or 
explicit attribute that records the encoding scheme used - which could 
vary from ASCII to UTF-32.


You can then go on to define a text string as an array of characters 
with the same encoding scheme.



Yes, in a world where we have to live with UTF8, UTF16, UTF32, legacy code
pages and Chinese variations on UTF8, that means that dynamic attributes
have to be included in the type. But isn't that the only way to have
consistent and intuitive character handling?

What do you mean? Chinese don't have a variation of UTF8.
UTF8 is global unambiguous encoding standard, part of Unicode.


I was referring to GB 18030 and that it has one, two and four byte code 
points.


The fundamental problem is that you want to hide the complexity of
Unicode by some magic String type of a compiler.
It is not possible. Unicode remains complex but the complexity is NOT
in encodings!
No, a codepoint's encoding is the easy part. For example I was easily
able to create a unit to support encoding agnostic code. See unit
LazUnicode in package LazUtils.
The complexity is elsewhere:
- "Character" composed of codepoints in precomposed and decomposed
(normalized) forms.
- Compare and sort text based on locale.
- Uppercase / Lowercase rules based on locale.
- Glyphs
- Graphemes
- etc.

I must admit I don't understand well those complex parts.
I do understand codeunits and codepoints, and I understand they are
the easy part.

Juha
The point I believe that you are missing is to consider that a character 
is an abstract symbol with a semantic independent of how it is encoded. 
Collation sequences are independent of encoding and should remain the 
same regardless of how a character set is encoded.

--
___
Lazarus mailing list
Lazarus@lists.lazarus-ide.org
https://lists.lazarus-ide.org/listinfo/lazarus


Re: [Lazarus] String vs WideString

2017-08-17 Thread Tony Whyman via Lazarus

On 16/08/17 11:05, Juha Manninen via Lazarus wrote:

On Mon, Aug 14, 2017 at 4:21 PM, Tony Whyman via Lazarus
<lazarus@lists.lazarus-ide.org> wrote:

UTF-16/Unicode can only store 65,536 characters while the Unicode standard
(that covers UTF8 as well) defines 136,755 characters.
UTF-16/Unicode's main advantage seems to be for rapid indexing of large
strings.

That shows complete ignorance from your side about Unicode.
You consider UTF-16 as a fixed-width encoding.  :(
Unfortunately many other programmers had the same wrong idea or they
were just lazy. The result anyway is a lot of broken UTF-16 code out
there.
You do like to use the word "ignorance" don't you. You can if you want 
take the view that all the "other programmers" that got the wrong idea 
are "stupid monkeys that don't know any better"  or, alternatively, that 
they just wanted a nice cup of tea rather than the not quite tea drink 
that was served up.


Wikipedia sums the problem up nicely: "The early 2-byte encoding was 
usually called "Unicode", but is now called "UCS-2". UCS-2 differs from 
UTF-16 by being a constant length encoding and only capable of encoding 
characters of BMP, it is supported by many programs."


This is where the problem starts. The definitive of "Unicode" was 
changed (foolishly in my opinion) after it had been accepted by the 
community and the result is confusion. Hence my first point about not 
even using it. In using "UTF16/Unicode" I was attempting to convey the 
common use of the term which is to see UTF-16 as what is now defined as 
UCS-2. This is because hardly anyone I know uses UCS-2 and instead says 
"Unicode". Perhaps I just spend too much time amongst the ignorant.


Wikipedia also makes the wonderful point that "The UTF-16 encoding 
scheme was developed as a compromise to resolve this impasse in version 
2.0". The impasse having resulted from "4 bytes per character wasted a 
lot of disk space and memory, and because some manufacturers were 
already heavily invested in 2-byte-per-character technology".


Finally: "In UTF-16, code points greater or equal to 2^16 are encoded 
using /two/ 16-bit code units. The standards organizations chose the 
largest block available of un-allocated 16-bit code points to use as 
these code units (since most existing UCS-2 data did not use these code 
points and would be valid UTF-16). Unlike UTF-8 they did not provide a 
means to encode these code points".


Which is from where I get my own view that UTF-16, as defined by the 
standards, is pointless. If you keep it to a UCS-2 (like) subset then 
you can get rapid indexing of character arrays. But as soon as you 
introduce the possibility of some characters being encoded as two 16-bit 
units then you lose rapid indexing and I can see no advantage over UTF-8 
- plus you get all the fun of worrying about byte order.


Indeed, I believe those lazy programmers that you referred to, are 
actually making a conscious decision to prefer to work with a 16-bit 
code point only UTF-16 subset (i.e. the Basic Multilingual Plan) 
precisely so that they can do rapid indexing. As soon as you bring in 2 
x 16-bit code unit code points, you lose that benefit - and perhaps you 
should be using UTF-32.


IMHO, Linux has got it right by using UTF-8 as the standard for 
character encoding and one of Lazarus's USPs is that it follows that 
lead - even for Windows. I can see why a program that does intensive 
text scanning will use a UTF-16 constrained to the BMP (i.e. 16-bit 
only), but not why anyone would prefer an unconstrained UTF-16 over UTF-8.


-- 
___
Lazarus mailing list
Lazarus@lists.lazarus-ide.org
https://lists.lazarus-ide.org/listinfo/lazarus


Re: [Lazarus] String vs WideString

2017-08-15 Thread Tony Whyman via Lazarus

You can me as a "like" on that one.


On 15/08/17 10:13, Mattias Gaertner via Lazarus wrote:

IMHO the main problem of adding a new string type is
https://xkcd.com/927/


--
___
Lazarus mailing list
Lazarus@lists.lazarus-ide.org
https://lists.lazarus-ide.org/listinfo/lazarus


Re: [Lazarus] String vs WideString

2017-08-15 Thread Tony Whyman via Lazarus

On 14/08/17 22:01, Juha Manninen via Lazarus wrote:

Tony Whyman, this issue has been discussed again and again for the
past 10+ years first in FPC mailing lists and then in Lazarus lists.
The current Unicode support in Lazarus works f***ing well and is
amazingly compatible with Delphi.
WinAPI parameters may require an explicit temporary UnicodeString
variable but even then the code is compatible with Delphi.

Tony Whyman, Marcos Douglas and Michael Schnell, please study the facts.
For starters, this is about the current Unicode support in Lazarus:
   http://wiki.freepascal.org/Unicode_Support_in_Lazarus
I think the dynamic encoding and automatic conversion now work perfectly well.
If you have a piece of code where it does not work, please ask for
detailed info.
If a topic keeps on being discussed after 10+ years of argument, the 
reason is usually either (a) the problem and its solution have not been 
documented properly, or (b) the outcome is an unsatisfactory compromise.


In this case, I would argue that both are true.

I went back and read the wiki article you mentioned and was no more the 
wiser as to why the current mess exists. Is it really no more than 
because Delphi continues to screw up in this area, so must FPC? The body 
of the article appears to be a set of notes - not necessarily wrong in 
themselves but lacking the background and context needed to explain why 
it is like it is.


This problem will keep coming up until it is fixed properly and, by 
that, I mean the that solution is consistent, understandable intuitively 
and well documented. Windows eccentricity also need to kept to Windows.


Here is my wish list:

1. Stop using the term "Unicode".

   It is too ambiguous. It is used as both an all embracing term for
   multi-byte encoding and as a synonym for UTF16 and that is really
   too confusing. The problem is made worse by having UnicodeString as
   a two byte wide string type in both FPC and Delphi.


2. Clean up the char type.

   When Wirth created the "char" type in Pascal it was a simple ASCII
   or EBCDIC character. There are now seven different char types
   (including type equivalence) with no guidelines on when each is
   applicable. This is too many. Why shouldn't there be a single char
   type that intuitively represents a single character regardless of
   how many bytes are used to represent it. Yes, in a world where we
   have to live with UTF8, UTF16, UTF32, legacy code pages and Chinese
   variations on UTF8, that means that dynamic attributes have to be
   included in the type. But isn't that the only way to have consistent
   and intuitive character handling?


3. The problem with string handling today is that it is not based on a 
consistent approach to the character type.


   If you clean up character handling then the model for string
   handling should become obvious. A string is after all no more than a
   container for a character array and which should be constrained to
   have the same character encoding. A string should intuitively
   represent a string of text regardless of how many bytes are used to
   represent each character and with dynamic attributes to tell you how
   it is encoded.


4. FPC should clean up Delphi's mess for it. If a unified string type 
follows a consistent model then it should be possible to make all Delphi 
string types synonyms.


   You will need to allow exceptions for legacy programs that insist on
   manipulating the bytes themselves - but that is not rocket science.
   There is also the issue of the Windows API and its insistence on
   Wide Strings - but isn't that why calling conventions such as cdecl
   and stdcall exist - to tell the compiler when it needs to reformat
   the call for a given API convention.

Tony Whyman



-- 
___
Lazarus mailing list
Lazarus@lists.lazarus-ide.org
https://lists.lazarus-ide.org/listinfo/lazarus


Re: [Lazarus] String vs WideString

2017-08-15 Thread Tony Whyman via Lazarus

On 14/08/17 17:47, Sven Barth via Lazarus wrote:
The main problem of such a dynamic type would be the inability to do 
fast indexing as the compiler would need to insert runtime checks for 
the size of a character. I had already thought the same, but then had 
to discard the idea due to this.


Is this really a big problem? It is not as if it would be necessary to 
do a table lookup everytime you index a string as the indexing method 
could be an attribute of the string and updated with the character 
encoding attribute. Is it really that complicated for the compiler to 
generate code that jumps to an indexing method depending upon a data 
attribute?


Is your problem really more about the result type as, depending on the 
character width, the result could be an AnsiChar or WideChar or a UTF8 
character for which I don't believe there is a defined char type (other 
than an arguable  mis-use of UCS4Char)?


I can accept that a clear up of this area would also have to extend to 
the char types as well - but I would also argue that that is well 
overdue. On a quick count, I found 7 different char types in the system 
unit.

--
___
Lazarus mailing list
Lazarus@lists.lazarus-ide.org
https://lists.lazarus-ide.org/listinfo/lazarus


Re: [Lazarus] String vs WideString

2017-08-14 Thread Tony Whyman via Lazarus

On 14/08/17 14:46, Mattias Gaertner via Lazarus wrote:

You made need UTF-16/Unicode support for accessing Microsoft APIs but
apart from that, why is it being promoted as the universal standard?

Who does that?

Mattias


Because the obvious implication when someone argues against AnsiString 
(from which UTF8String derives) and talks about Unicode is that they are 
promoting UTF-16 and the UnicodeString type. Perhaps this is because I 
am old enough to remember when MS first added wide characters to Windows 
and that they called it "Unicode". To me, when people say "Unicode" they 
mean Windows wide characters.


Perhaps the problem is the use of the word "Unicode".  By trying to 
embrace UTF8, UTF16 and UTF32 with the older UCS-2 it is perhaps too 
ambiguous a term - especially as the Delphi/FPC UnicodeString type 
exists and probably (but I'm not certain)  means UTF-16.


What I see in FPC/Lazarus today is:

-  UTF8 supported through AnsiString.

- A confusion of Widestring/UnicodeString for UTF-16 and legacy UCS-2.

- Nothing for UTF-32.

If nothing else, FPC Lazarus could do with a clean-up of both 
terminology and string types. Indeed, why isn't there a single container 
string type for all character sets where the encoding whether a legacy 
code page, UTF8, UTF16 or UTF32 is simply a dynamic attribute of the 
type - a sort of extended AnsiString?






-- 
___
Lazarus mailing list
Lazarus@lists.lazarus-ide.org
https://lists.lazarus-ide.org/listinfo/lazarus


Re: [Lazarus] String vs WideString

2017-08-14 Thread Tony Whyman via Lazarus


On 13/08/17 12:18, Juha Manninen via Lazarus wrote:

Unicode was designed to solve exactly the problems caused by locale differences.
Why don't you use it?

I believe you effectively answer your own question in your preceding post:


Actually using the Windows system codepage is not safe any more.
The current Unicode system in Lazarus maps AnsiString to use UTF-8.
Text with Windows codepage must be converted explicitly.
This is a breaking change compared to the old Unicode suppport in
Lazarus 1.4.x + FPC 2.6.x.
If you are processing strings as "text" then you probably do not care 
how it is encoded and can live with "breaking changes". However, if, for 
some reason you are or need to be aware of how the text is encoded - or 
are using string types as a useful container for binary data then, types 
that sneak up on you with implicit type conversions or which have 
semantics that change between compilers or versions, are just another 
source of bugs.


PChar used to be  a safe means to access binary data - but not anymore, 
especially if you move between FPC and Delphi. (One of my gripes is that 
the FCL still makes too much use of PChar instead of PByte with the 
resulting Delphi incompatibility). The "string" type also used to be a 
safe container for any sort of binary data, but when its definition can 
change between compilers and versions, it is now something to be avoided.


As a general rule, I now always use PByte for any sort of string that is 
binary, untyped or encoding to be determined. It works across compilers 
(FPC and Delphi) with consistent semantics and is safe for such use.


I also really like AnsiString from FCP 3.0 onwards. By making the 
encoding a dynamic attribute of the type, it means that I know what is 
in the container and can keep control.


I am sorry, but I would only even consider using Unicodestrings as a 
type (or the default string type) when I am just processing text for 
which the encoding is a don't care, such as a window caption, or for 
intensive text analysis. If I am reading/writing text from a file or 
database where the encoding is often implicit and may vary from the 
Unicode standard then my preference is for AnsiString. I can then read 
the text (e.g. from the file) into a (RawByteString) buffer, set the 
encoding and then process it safely while often avoiding the overhead 
from any transliteration. PByte comes into its own when the file 
contains a mixture of binary data and text.


Text files and databases tend to use UTF-8 or are encoded using legacy 
Windows Code pages. The Chinese also have GB18030. With a database, the 
encoding is usually known and AnsiString is a good way to read/write 
data and to convey the encoding, especially as databases usually use a 
variable length multi-byte encoding natively and not UTF-16/Unicode. 
With files, the text encoding is usually implicit and AnsiString is 
ideal for this as it lets you read in the text and then assign the 
(implicit) encoding to the string, or ensure the correct encoding when 
writing.


And anyway, I do most of my work in Linux, so why would I even want to 
bother myself with arrays of widechars when the default environment is UTF8?


We do need some stability and consistency in strings which, as someone 
else noted have been confused by Embarcadero. I would like to see that 
focused on AnsiString with UnicodeString being only for specialist use 
on Windows or when intensive text analysis makes a two byte encoding 
more efficient than a variable length multi-byte encoding.


Tony Whyman
MWA

--
___
Lazarus mailing list
Lazarus@lists.lazarus-ide.org
https://lists.lazarus-ide.org/listinfo/lazarus


Re: [Lazarus] Making sources compatible with Delphi (but Lazarus is priority)

2017-05-04 Thread Tony Whyman via Lazarus

On 03/05/17 17:53, Sven Barth via Lazarus wrote:


Am 03.05.2017 14:37 schrieb "Tony Whyman via Lazarus" 
<lazarus@lists.lazarus-ide.org <mailto:lazarus@lists.lazarus-ide.org>>:
> On the other hand, AnsiString and UnicodeString are still separate 
types. Why? Why should there not be a single unified string type with 
(e.g.) ASCII, UTF8 and UTF-16 (or MS Unicode) being just another code 
page?


Because indexed access to the string data would slow down quite a bit 
as the RTL would need to determine whether the string is a 1-Byte, 
2-Byte, 4-Byte or multi Byte String. Yes the compiler could do 
optimizations for this inside loops, but it would definitely slow down 
-O- code.


Regards,
Sven





I don't believe that string indexing even works for UTF8 strings at 
present - at least not in a simple s[i] way.


Is it really that much overhead to have a simple codepage check before 
calling the correct function to index a string? The obvious optimisation 
would be to check for UTF8, then UTF16 then the Default codepage and 
then the rest. Or perhaps UTF16 first for Windows. With register level 
code you are talking about very few actual machine level operations.


To me, a unified string type would have the advantage that:

- You would only have one managed string type "string" (and hence avoids 
the confusion that exists today).


- You would have standard string byte length and string character length 
functions (which yes, in the latter case, would have to have a codepage 
check as above).


- String indexing could be standardised as always returning the 
character at position 'i' (including UTF8 strings - albeit after having 
to "walk" the string).


- Automatic transliteration on string compare (with code page check of 
course) - and perhaps with the option to specific a non-standard collation.


- Readily portable code.

- The only time that a programmer has to think about the character 
encoding is when writing code that interacts directly with an external 
interface.


How often would that extra lookup be significant compared with the 
benefits that unified string handling would bring? And, there is no 
reason why you could not retain the UnicodeString type for cases where 
you really need to optimise UTF16 handling.


I see the unified string type as a further extension to AnsiString to 
include UTF16 and UCS2 code pages together with appropriate function 
support.


Tony


-- 
___
Lazarus mailing list
Lazarus@lists.lazarus-ide.org
http://lists.lazarus-ide.org/listinfo/lazarus


Re: [Lazarus] Making sources compatible with Delphi (but Lazarus is priority)

2017-05-03 Thread Tony Whyman via Lazarus

On 03/05/17 09:52, Graeme Geldenhuys via Lazarus wrote:

[rant]
ps:
   Both FPC and Delphi is in such a messed up state when it comes to
   string and character types. It is the laughing stock of programming
   languages at the moment. At least EMBT is heading in the right
   direction with their Linux Delphi compiler - they completely removed
   AnsiString.

   FPC and Delphi can learn a huge lesson from Java and Qt in how to
   handle string and character types.
[/rant]

Regards,
   Graeme

Is Delphi/FPC string handling that much worse than 'C'?

To me, the great thing about AnsiString is that it provides unified 
handling of UTF8 and legacy codepages in a single managed type by 
including the code page id as a dynamic property of the string.


On the other hand, AnsiString and UnicodeString are still separate 
types. Why? Why should there not be a single unified string type with 
(e.g.) ASCII, UTF8 and UTF-16 (or MS Unicode) being just another code page?

--
___
Lazarus mailing list
Lazarus@lists.lazarus-ide.org
http://lists.lazarus-ide.org/listinfo/lazarus


Re: [Lazarus] Making sources compatible with Delphi (but Lazarus is priority)

2017-05-01 Thread Tony Whyman via Lazarus



On 01/05/17 16:33, Sven Barth via Lazarus wrote:

Would you please elaborate on these and which FPC version you targeted?

Regards,
Sven



I am working with FPC 3.0.x and an example of the solution I used 
follows. Note that with FPC, there is no problem calling a constructor 
from a placeholder, while with delphi I found it necessary to add an 
explicit coercion. I also wanted to return the interface provided by the 
object. Again with FPC, this is easy. With Delphi, I found it necessary 
to use QueryInterface to do the same.


The difference between the two seems to be that FPC waits until the 
generic is instantiated before type checking while Delphi performs type 
checking when compiling the generic itself - or thereabouts. IMHO, FPC 
is much superior to Delphi in this area.


{$IFDEF FPC}
  TOutputBlockItemGroup<_TItem,_IItem> = class(TOutputBlockItem)
{$ELSE}
  TOutputBlockItemGroup<_TItem: TOutputBlockItem; _IItem: IUnknown> = 
class(TOutputBlockItem)

{$ENDIF}
  public
function GetItem(index: integer): _IItem;
function Find(ItemType: byte): _IItem;
property Items[index: integer]: _IItem read getItem; default;
  end;



{$IFDEF FPC}
{ TOutputBlockItemGroup }

function TOutputBlockItemGroup<_TItem,_IItem>.GetItem(index: integer): 
_IItem;

var P: POutputBlockItemData;
begin
  P := inherited getItem(index);
  Result := _TItem.Create(self.Owner,P);
end;

function TOutputBlockItemGroup<_TItem,_IItem>.Find(ItemType: byte): _IItem;
var P: POutputBlockItemData;
begin
  P := inherited Find(ItemType);
  Result := _TItem.Create(self.Owner,P);
end;


{$ELSE}

{ TOutputBlockItemGroup }

function TOutputBlockItemGroup<_TItem,_IItem>.GetItem(index: integer): 
_IItem;

var P: POutputBlockItemData;
Obj: TOutputBlockItem;
begin
  P := inherited getItem(index);
  Obj := TOutputBlockItemClass(_TItem).Create(self.Owner,P);
  if Obj.QueryInterface(GetTypeData(TypeInfo(_IItem))^.Guid,Result) <> 
0 then

IBError(ibxeInterfaceNotSupported,[GuidToString(GetTypeData(TypeInfo(_IItem))^.Guid)]);
end;

function TOutputBlockItemGroup<_TItem,_IItem>.Find(ItemType: byte): _IItem;
var P: POutputBlockItemData;
Obj: TOutputBlockItem;
begin
  P := inherited Find(ItemType);
  Obj := TOutputBlockItemClass(_TItem).Create(self.Owner,P);
  if Obj.QueryInterface(GetTypeData(TypeInfo(_IItem))^.Guid,Result) <> 
0 then

IBError(ibxeInterfaceNotSupported,[GuidToString(GetTypeData(TypeInfo(_IItem))^.Guid)]);
end;


--
___
Lazarus mailing list
Lazarus@lists.lazarus-ide.org
http://lists.lazarus-ide.org/listinfo/lazarus


Re: [Lazarus] Making sources compatible with Delphi (but Lazarus is priority)

2017-05-01 Thread Tony Whyman via Lazarus


On 01/05/17 15:18, Juha Manninen via Lazarus wrote:

On Mon, May 1, 2017 at 12:30 PM, Tony Whyman via Lazarus
<lazarus@lists.lazarus-ide.org> wrote:

When I originally created the Firebird Pascal API package,

Now I realize your code may have been for FPC but not for Lazarus.
Even then the solution provided by LazUtils (2 files there) is good
because it allows compatible and portable code. Later when FPC's
UTF-16 support is ready, such code can be ported easily.

Juha
I assume that you mean that my code is non-visual which is indeed where 
I am coming from. If you want to write an application that is LCL/VCL 
compatible then that is another can of worms.


Your concluding remarks in your other post were:


>>I hope you find this a useful checklist.
It contained so much false information that it only confuses people.

I want to repeat that it is possible to write code dealing with
Unicode that is fully compatible with Delphi at source level.
It will be compatible with a future UTF-16 solution in Lazarus as well.
Encoding agnostic (UTF-8 / UTF-16) code is possible even if you must
iterate individual codepoints. See the wiki page for details.

Remember these to keep your code compatible:
  1. Normally use type "String".
  1. Assign a constant always to a type String variable.
  2. Use type UnicodeString explicitly for API calls that need it.
I am not sure how much your second post rows back from this but I do 
think that false is a bit harsh.


You seem to be coming from a view that strings are strings and the 
compiler should be allowed to work out what is the appropriate string 
encoding for the local environment. All the programmer has to do is 
declare the type as "string" and all will be good. I guess that is your 
definition of portable code: it is agnostic as regards the string encoding.


I am coming from a much messier perspective that says a portable program 
has to deal with whatever string encoding is thrown at it. It may be 
valid criticism to say that I was taking a particularly messy example 
and deriving generic rules from it - but few programs work in a vacuum 
and it is worth being aware of real world problems.


I my case, the real world problem is Firebird. Firebird will expect or 
give you  a string encoded not according to the local environment but 
that which was specified for the database connection and it is the API 
user that decides this and not the API. Ideally, the user specifies 
UTF8, but Firebird supports many other string encodings - but not UTF16 
or Unicode at present. In the original version of the library, the API 
was defined using the "string" type as were the internal structures. 
When I looked at moving to Delphi support, there was no way that this 
would work if "string" suddenly became "UnicodeString". All over the 
place I had assumed that "string" meant "AnsiString" including checking 
and setting the code page in order to match the connection character set 
with whatever code page was being used by the API user.


Could I have written the API without being aware of the character 
encoding? I doubt it. The connection character set is not something that 
the compiler can be aware of. Part of the role of the API library is to 
manage the character encoding on behalf of the user. On the other hand, 
by defining the API using the explicit AnsiString type, it should mean 
that if the API user uses the "string" type, then the compiler can 
automatically transliterate from the API to the API user's string types 
when string means "UnicodeString".


So is my messy example typical or atypical? Am I correct in offering it 
as a source of rules. Ideally, it is atypical. However, I would observe 
that few programs exist in isolation. They have to deal with external 
objects such as files, GUIs and TCP connections. The compiler cannot 
work out the character encoding for itself in these cases and either 
your program or some intermediate library has to be character coding 
aware in order to deal with these objects.


The bottom line is that it would be great if we never needed to be aware 
of the character encoding behind the string type. However, all too often 
you do and, because of that, when you are writing code that is portable 
between platforms and compilers, you either needed to be explicit in the 
string type throughout your program, or at least in the modules that 
deal with external interfaces.


Tony Whyman
--
___
Lazarus mailing list
Lazarus@lists.lazarus-ide.org
http://lists.lazarus-ide.org/listinfo/lazarus


Re: [Lazarus] Making sources compatible with Delphi (but Lazarus is priority)

2017-05-01 Thread Tony Whyman via Lazarus

Marcos,

When I originally created the Firebird Pascal API package, I wrote it 
with FPC as the only intended target. However, I then got feedback 
asking for Delphi compatibility and I couldn't resist the challenge of 
seeing how easy it would be to convert the source code. In the end, it 
was not that difficult and the following summarises the changes needed 
(apart from the minor syntax changes):


1. Standard set of defines for all modules:

{$IFDEF MSWINDOWS}
{$DEFINE WINDOWS}
{$ENDIF}

{$IFDEF FPC}
{$mode delphi}
{$ENDIF}

The first one is needed to ensure that the "WINDOWS" defined symbol 
works with Delphi as well as FPC, while "mode delphi" is needed for FPC.


2. All strings declared explicitly as AnsiString expect where they are 
used with system calls (e.g. FileNames).


This rule may vary between applications. However, as FPC defaults to 
AnsiString and Delphi to WideString, it is usually a good idea to be 
explicit in your string types. In my case, most strings were the ASCII 
subset of UTF8 and AnsiString worked for me.


Similarly AnsiChar instead of Char.

3. PByte instead of PChar.

Most uses of PChar in FPC/Lazarus aren't to character strings but are 
instead used to point to untyped buffers. However, in Delphi, PChar now 
means widestring and you will be caught out if you try and use PChar for 
an untyped buffer. PByte has the same semantic in both FPC and Delphi 
and is a pointer to an unsigned byte.


4. PAnsiChar instead of PChar.

When PChar is used to genuinely point to a character string then as in 
point 2, you should be explicit about which type of string. PWideString 
may also be appropriate for some cases.


5. Take care when using string literals.

I added

{$IFDEF FPC}
{$codepage UTF8}
{$ENDIF}

to sources with string literals just to make sure that FPC interprets 
all strings as UTF8. However, you need to be careful with Delphi. In 
some of the test scripts I ended up with source code such as:


{$IFDEF DCC}
ByName('title').AsString := UTF8Encode('Blob Test ©€');
ByName('Notes').AsString := UTF8Encode('Écoute moi');
{$ELSE}
ByName('title').AsString := 'Blob Test ©€';
ByName('Notes').AsString := 'Écoute moi';
{$ENDIF}

The first case (DCC defined) is Delphi and as my strings were all UTF8, 
I added an explicit UTF8Encode to force the literal to UTF8 before 
assigning to the string. Note the above is a test case with literals 
chosen to show up differences between character sets.


6. Varargs

Delphi is much fussier than FPC about varargs constructs. If you have to 
use them then the only way this seems to work is e.g.


function blah(...): sometype; cdecl varargs;

7. Generics

If you don't have to go here then don't. Unfortunately I had dug a hole 
for myself and made extensive use of generics. Some of the differences 
are minor syntax, but others... Delphi and FPC just don't work the same 
way. Examples of problems are:


- calling a constructor from a function defined using generics.

- extracting an interface from an object defined using generics.

Both are possible, but with very different syntax.

8.TSystemCodePage does not exist in Delphi

You may need to add

{$IF not declared(TSystemCodePage)}
  TSystemCodePage = word; {not defined in Delphi}
{$IFEND}

if you are using any Ansistring code page functions.

9. $IFEND or $ENDIF

As illustrated in point 8, older versions of Delphi demand $IFEND rather 
than $ENDIF to terminate conditional compilation.



I hope you find this a useful checklist.

Regards

Tony Whyman

MWA



On 30/04/17 17:37, Marcos Douglas B. Santos via Lazarus wrote:

It months ago I realized that Lazarus was saving the sources like that:

1- If there is only ANSI chars, save it as ANSI encode;
2. If there is more than ANSI chars, save it as UTF8 encode;

(correct me if I'm wrong about that)

I think this was changed when I updated my FPC to 3.* and Lazarus (trunk).
Everything continues works. This new behavior was completly 
transparent to me... but I have a doubt:


If Delphi sources don't use UTF8, how is the best way to mantain 
sources that need to work in both compilers?


I mean, I would like to work with FPC and Lazarus as I am used to 
doing, without take concerns about "remember to change the encode of 
these files", "remember to not put accented chars on code", or 
something like that.


Is there some wiki page that explains this?
Are you working on projects that have these problems? Could you tell 
me which is the best approach to deal with it?

Thank you.

Best regards,
Marcos Douglas





-- 
___
Lazarus mailing list
Lazarus@lists.lazarus-ide.org
http://lists.lazarus-ide.org/listinfo/lazarus


[Lazarus] https website for Lazarus

2017-03-13 Thread Tony Whyman via Lazarus
Has anyone thought about supporting https on the Lazarus (and Free 
Pascal) websites? Firefox, for example, is getting increasingly sniffy 
about unprotected websites and for good reason.


It would also be useful to protect the svn feeds, if only to reduce the 
risk of a man in the middle attack sneaking something nasty into the 
source code.


Let's encrypt (https://letsencrypt.org/) seems to offer a very good free 
service for https certificates where the objective is to protect the 
connection and give reasonable confidence  that you are talking to the 
named website, so there does not seem to be a cost reason why https is 
not supported.


Tony Whyman

MWA

--
___
Lazarus mailing list
Lazarus@lists.lazarus-ide.org
http://lists.lazarus-ide.org/listinfo/lazarus


[Lazarus] Should Frames be transparent?

2017-01-11 Thread Tony Whyman via Lazarus
I suppose that this could be one of those "is it a feature or is it a 
bug" type questions, but it is also a big difference in behaviour 
between Linux and Windows.


I've realised that if you create a simple application with an image on a 
form and then partially or wholly overlay it with a frame or a even a 
radio group then:


- On Linux: the frame and radio group are not transparent and obscure 
the image.


- On Windows: the frame and radio group are  transparent, have no 
background, and the image shows through.


This applies to both IDE and a running program.

In the windows version, I came readily make the frame opaque when the 
program runs by simply overriding its Paint method as follows:


procedure TFrame1.Paint;
begin
  EraseBackground(Canvas.handle);
  inherited Paint;
end;

So the reason for the transparency is also certainly that the frame's 
background is not being erased under Windows but is being erased under 
Linux.


So bug or feature?

--
___
Lazarus mailing list
Lazarus@lists.lazarus-ide.org
http://lists.lazarus-ide.org/listinfo/lazarus


Re: [Lazarus] fcl-pdf change

2016-11-03 Thread Tony Whyman via Lazarus

Does this affect the Power PDF package or is this entirely independent?


On 03/11/16 08:47, Michael Van Canneyt via Lazarus wrote:

For those using the fcl-pdf package: There has been a change in the API.
Well, there were many additions, but this change may influence 
existing code.


--
___
Lazarus mailing list
Lazarus@lists.lazarus-ide.org
http://lists.lazarus-ide.org/listinfo/lazarus


Re: [Lazarus] TDBEdit, TStringField Size, DataSize, DisplayWidth and MaxLength

2016-10-14 Thread Tony Whyman via Lazarus


On 14/10/16 06:43, LacaK via Lazarus wrote:
I do not know IBX, but don't you use overriden 
TDataSet.InternalInitFieldDefs ? It will allow you put extra info into 
FieldDef and then use overriden TDataSet.CreateFields, which will 
allow you pass extra info from TIBFieldDef into TIBStringField for 
example ...

(AFAICS Zeos do it in this way also)
That is basically what IBX does. My point is that it would be better to 
put the passing of the extra info into a subclassed TFieldDef rather 
than have it in TIBCustomDataSet. After all, isn't the whole point of OO 
programming to group related functionality into the same class. If you 
recommend subclassing the TFieldDef then surely it makes sense to make 
CreateField a virtual method.

--
___
Lazarus mailing list
Lazarus@lists.lazarus-ide.org
http://lists.lazarus-ide.org/listinfo/lazarus


Re: [Lazarus] Teaching Pascal at College

2016-10-12 Thread Tony Whyman via Lazarus
When I read your post ,it sent me back to read the Introduction to 
Nicklaus Wirth's original "Pascal user Manual and Report" where the 
opening paragraph says:


"The development of the language Pascal is based on two principal aims. 
The first is to make available a language suitable to teach programming 
as a systematic discipline based on certain fundamental concepts clearly 
and naturally reflected by the language. The second is to develop 
implementations of this language which are both reliable and efficient 
on presently available (1975) computers".


Certainly the intent was a very good match for what you want and IMHO 
that intent was fully realised.


If you can find it, I would recommend getting hold of a copy of what is 
now an ancient text "Pascal - An Introduction to Methodical Programming 
- Findlay and Watt - ISBN 0 273 01220 7 (Original Edition) now 
978-1857283648". First published 1978. This used to be the definitive 
text for learning Pascal and somewhat to my surprise still seems to be 
available from Amazon in its 3rd Edition.


When I looked down through the content list the order of play and 
presentation still seems just right for a first course in programming. 
It does not deal with Object Oriented programming or even "Units". ISO 
standard Pascal will still some time away but that anyway should be the 
next semester.


I would also caution against starting on GUI programming too early. If 
the students don't have a grasp of fundamentals then they will get lost 
very quickly. Perhaps the best approach is at the end of each subject to 
translate the simple procedural program they have been working on into a 
GUI program as a whole class exercise.


From having myself developed many courses in Data Communications over 
the years, I would also always try and make sure the students understand 
the context, the background to what they are doing and why.


Somehow you need to get Boolean Algebra in there as well. Findlay and 
Watt give a primer on this in chapter 5, which is probably about the 
right stage after having done the basics. And then, of course, there are 
Turing Machines...


Have fun

Tony Whyman

MWA


On 12/10/16 19:10, Adrian De Armas via Lazarus wrote:

Hello everyone,
I am a professor of "introduction to programming". Currently we are 
working with matlab and c.


Today I had a meeting about doing the module more interesting to the 
students. Currently we teach algorithms making console applications 
and usually I receive questions like "Why don't we do something more 
modern?".


I recommended that we should use Pascal in General and Lazarus in 
particular to teach how to create rich GUI Applications and to my 
surprise the idea was well recieved. Now I have to make suggestions 
about how to prepare the module starting from zero. Students do not 
know how to program and I need to include subjects as: variable 
declaration, operations, if, while, for, functions and procedure, 
arrays and multidimensional arrays.


I would love to know what you think about making the transition from 
console to GUI.

This is an exciting opportunity I'd love to make it right.

Regards




-- 
___
Lazarus mailing list
Lazarus@lists.lazarus-ide.org
http://lists.lazarus-ide.org/listinfo/lazarus


Re: [Lazarus] TDBEdit, TStringField Size, DataSize, DisplayWidth and MaxLength

2016-10-12 Thread Tony Whyman via Lazarus

On 11/10/16 19:21, LacaK via Lazarus wrote:
I am aware of it. I have not added all other MBCS because ! I doubt, 
which are realy used nowadays.
My guess is that UTF-8 is far most used / supported as client 
character set.

No problem to add them if there will be real demand from users ...
Perhaps the correct answer is to let the database driver work this one 
out rather than have a fixed decision in the FCL.


I would suggest the following change:

function TStringField.GetDataSize: Integer;

begin
  Result := FieldDef.CharSize * Size + 1;
//  case FCodePage of
//CP_UTF8: Result := 4*Size+1;
//else Result :=   Size+1;
//  end;
end;

TFieldDef.GetCharSize uses the same algorithm so this avoids a code 
duplication anyway. But I also want to make TFieldDef.GetCharSize and 
TFieldDef.CreateField virtual methods. That way a database driver can 
readily expand upon the character sets supported to match what it 
supports rather than be limited by the FCL default.


In IBX, I have already done this using TIBFieldDef and TIBStringField as 
subclasses in order to pass character set information. However, because 
TFieldDef.CreateField is non-virtual, the implementation is not as 
elegant as it should be. That is the extra info is added to the 
TIBStringField as the dataset is opened rather than when the field is 
created. It is also less maintainable as the functionality should be in 
TIBFieldDef rather than in a different class altogether.


Making those two methods virtual is the most important change. I can 
live with TStringField.GetDataSize as it is because that is already 
virtual and a future TIBStringField can readily override it.


Tony Whyman
MWA
-- 
___
Lazarus mailing list
Lazarus@lists.lazarus-ide.org
http://lists.lazarus-ide.org/listinfo/lazarus


Re: [Lazarus] TDBEdit, TStringField Size, DataSize, DisplayWidth and MaxLength

2016-10-11 Thread Tony Whyman via Lazarus

On 11/10/16 15:14, Martin Schreiber via Lazarus wrote:

MSEgui uses below code in order to guess the Firebird character size:
"

FYI, this is the table IBX uses to look up character sets and code pages:

  CharSetMap: array [0..69] of TCharsetMap = (
  (CharsetID: 0; CharSetName: 'NONE'; CharSetWidth: 1; CodePage: CP_NONE),
  (CharsetID: 1; CharSetName: 'OCTETS'; CharSetWidth: 1; CodePage: 
CP_NONE),
  (CharsetID: 2; CharSetName: 'ASCII'; CharSetWidth: 1; CodePage: 
CP_ASCII),
  (CharsetID: 3; CharSetName: 'UNICODE_FSS'; CharSetWidth: 3; CodePage: 
CP_UTF8),

  (CharsetID: 4; CharSetName: 'UTF8'; CharSetWidth: 4; CodePage: CP_UTF8),
  (CharsetID: 5; CharSetName: 'SJIS_0208'; CharSetWidth: 2; CodePage: 
20932),
  (CharsetID: 6; CharSetName: 'EUCJ_0208'; CharSetWidth: 2; CodePage: 
20932),
  (CharsetID: 7; CharSetName: 'Unknown'; CharSetWidth: 0; CodePage: 
CP_NONE),
  (CharsetID: 8; CharSetName: 'Unknown'; CharSetWidth: 0; CodePage: 
CP_NONE),

  (CharsetID: 9; CharSetName: 'DOS737'; CharSetWidth: 1; CodePage: 737),
  (CharsetID: 10; CharSetName: 'DOS437'; CharSetWidth: 1; CodePage: 437),
  (CharsetID: 11; CharSetName: 'DOS850'; CharSetWidth: 1; CodePage: 850),
  (CharsetID: 12; CharSetName: 'DOS865'; CharSetWidth: 1; CodePage: 865),
  (CharsetID: 13; CharSetName: 'DOS860'; CharSetWidth: 1; CodePage: 860),
  (CharsetID: 14; CharSetName: 'DOS863'; CharSetWidth: 1; CodePage: 863),
  (CharsetID: 15; CharSetName: 'DOS775'; CharSetWidth: 1; CodePage: 775),
  (CharsetID: 16; CharSetName: 'DOS858'; CharSetWidth: 1; CodePage: 858),
  (CharsetID: 17; CharSetName: 'DOS862'; CharSetWidth: 1; CodePage: 862),
  (CharsetID: 18; CharSetName: 'DOS864'; CharSetWidth: 1; CodePage: 864),
  (CharsetID: 19; CharSetName: 'NEXT'; CharSetWidth: 1; CodePage: CP_NONE),
  (CharsetID: 20; CharSetName: 'Unknown'; CharSetWidth: 0; CodePage: 
CP_NONE),
  (CharsetID: 21; CharSetName: 'ISO8859_1'; CharSetWidth: 1; CodePage: 
28591),
  (CharsetID: 22; CharSetName: 'ISO8859_2'; CharSetWidth: 1; CodePage: 
28592),
  (CharsetID: 23; CharSetName: 'ISO8859_3'; CharSetWidth: 1; CodePage: 
28593),
  (CharsetID: 24; CharSetName: 'Unknown'; CharSetWidth: 0; CodePage: 
CP_NONE),
  (CharsetID: 25; CharSetName: 'Unknown'; CharSetWidth: 0; CodePage: 
CP_NONE),
  (CharsetID: 26; CharSetName: 'Unknown'; CharSetWidth: 0; CodePage: 
CP_NONE),
  (CharsetID: 27; CharSetName: 'Unknown'; CharSetWidth: 0; CodePage: 
CP_NONE),
  (CharsetID: 28; CharSetName: 'Unknown'; CharSetWidth: 0; CodePage: 
CP_NONE),
  (CharsetID: 29; CharSetName: 'Unknown'; CharSetWidth: 0; CodePage: 
CP_NONE),
  (CharsetID: 30; CharSetName: 'Unknown'; CharSetWidth: 0; CodePage: 
CP_NONE),
  (CharsetID: 31; CharSetName: 'Unknown'; CharSetWidth: 0; CodePage: 
CP_NONE),
  (CharsetID: 32; CharSetName: 'Unknown'; CharSetWidth: 0; CodePage: 
CP_NONE),
  (CharsetID: 33; CharSetName: 'Unknown'; CharSetWidth: 0; CodePage: 
CP_NONE),
  (CharsetID: 34; CharSetName: 'ISO8859_4'; CharSetWidth: 1; CodePage: 
28594),
  (CharsetID: 35; CharSetName: 'ISO8859_5'; CharSetWidth: 1; CodePage: 
28595),
  (CharsetID: 36; CharSetName: 'ISO8859_6'; CharSetWidth: 1; CodePage: 
28596),
  (CharsetID: 37; CharSetName: 'ISO8859_7'; CharSetWidth: 1; CodePage: 
28597),
  (CharsetID: 38; CharSetName: 'ISO8859_8'; CharSetWidth: 1; CodePage: 
28598),
  (CharsetID: 39; CharSetName: 'ISO8859_9'; CharSetWidth: 1; CodePage: 
28599),
  (CharsetID: 40; CharSetName: 'ISO8859_13'; CharSetWidth: 1; CodePage: 
28603),
  (CharsetID: 41; CharSetName: 'Unknown'; CharSetWidth: 0; CodePage: 
CP_NONE),
  (CharsetID: 42; CharSetName: 'Unknown'; CharSetWidth: 0; CodePage: 
CP_NONE),
  (CharsetID: 43; CharSetName: 'Unknown'; CharSetWidth: 0; CodePage: 
CP_NONE),

  (CharsetID: 44; CharSetName: 'KSC_5601'; CharSetWidth: 2; CodePage: 949),
  (CharsetID: 45; CharSetName: 'DOS852'; CharSetWidth: 1; CodePage: 852),
  (CharsetID: 46; CharSetName: 'DOS857'; CharSetWidth: 1; CodePage: 857),
  (CharsetID: 47; CharSetName: 'DOS861'; CharSetWidth: 1; CodePage: 861),
  (CharsetID: 48; CharSetName: 'DOS866'; CharSetWidth: 1; CodePage: 866),
  (CharsetID: 49; CharSetName: 'DOS869'; CharSetWidth: 1; CodePage: 869),
  (CharsetID: 50; CharSetName: 'CYRL'; CharSetWidth: 1; CodePage: 1251),
  (CharsetID: 51; CharSetName: 'WIN1250'; CharSetWidth: 1; CodePage: 1250),
  (CharsetID: 52; CharSetName: 'WIN1251'; CharSetWidth: 1; CodePage: 1251),
  (CharsetID: 53; CharSetName: 'WIN1252'; CharSetWidth: 1; CodePage: 1252),
  (CharsetID: 54; CharSetName: 'WIN1253'; CharSetWidth: 1; CodePage: 1253),
  (CharsetID: 55; CharSetName: 'WIN1254'; CharSetWidth: 1; CodePage: 1254),
  (CharsetID: 56; CharSetName: 'BIG_5'; CharSetWidth: 2; CodePage: 950),
  (CharsetID: 57; CharSetName: 'GB_2312'; CharSetWidth: 2; CodePage: 936),
  (CharsetID: 58; CharSetName: 'WIN1255'; CharSetWidth: 1; CodePage: 1255),
  (CharsetID: 59; CharSetName: 'WIN1256'; CharSetWidth: 1; CodePage: 1256),
  (CharsetID: 60; CharSetName: 'WIN1257'; CharSetWidth: 1; CodePage: 1257),
  (CharsetID: 61; 

Re: [Lazarus] TDBEdit, TStringField Size, DataSize, DisplayWidth and MaxLength

2016-10-11 Thread Tony Whyman via Lazarus


On 11/10/16 15:14, Martin Schreiber via Lazarus wrote:

 case i2 of
  5,6,8,44,56,57,64: begin

Agree with 5,6, 44, 56, 57 as  two byte character sets.

8 doesn't seem to exist (at least in my version).

64 is KOI8U. According to Wikipedia "KOI8-U is an 8-bit character 
encoding, designed to cover Ukrainian, which uses a Cyrillic alphabet. 
It is based on KOI8-R, which covers Russian and Bulgarian, but replaces 
eight graphic characters with four Ukrainian letters Ґ, Є, І, and Ї in 
both upper case and lower case."


It should be the same character width as character set 63 (KOI8R) i.e. 1.
--
___
Lazarus mailing list
Lazarus@lists.lazarus-ide.org
http://lists.lazarus-ide.org/listinfo/lazarus


Re: [Lazarus] TDBEdit, TStringField Size, DataSize, DisplayWidth and MaxLength

2016-10-11 Thread Tony Whyman via Lazarus

Please look at changes in TRUNK.

May be that not all is perfect, but you will see there direction ...

-Laco.



Which FPC version is this likely to be released in?

On a quick review of the code, all seems good. Just one point: 
GetDataSize seems to acknowledge CP_UTF8 as the only multibyte character 
set. The Firebird character set GB18030 (Chinese characters) is 
multi-byte (see wikipedia) and has code page 54936. I believe PostgreSQL 
also supports it.

--
___
Lazarus mailing list
Lazarus@lists.lazarus-ide.org
http://lists.lazarus-ide.org/listinfo/lazarus


[Lazarus] TDBEdit, TStringField Size, DataSize, DisplayWidth and MaxLength

2016-10-11 Thread Tony Whyman via Lazarus
An IBX user came to me with a problem and the problem seems to be a deep 
seated disconnect between multi-byte character sets, TStringField.Size 
and TDBEdit.MaxLength. Something needs to give - but I am not sure what 
should.


Firstly documentation:

If you go back to Delphi, TField.DataSize is the memory needed to hold 
the Field's value. The DisplayWidth is the number of characters to be 
displayed, and Size is, for datatype ftstring, "the maximum number of 
characters in the string". How literally this last definition should be 
taken, I'm not sure, as it may well have been written assuming a single 
byte character set.


On the other hand, the FPC documentation is consistent with Delphi for 
DisplayWidth and DataSize, but more opaque for TField.Size where it is 
the "logical size" - whatever that means, although TStringField is more 
definitive by saying it is the maximum size (in characters) - their 
brackets not mine.


That seems to be consistent with TDBEdit.Maxlength which should be the 
maximum number of characters that can appear in the control and, if you 
look at the code, TDBEdit will source the default value from 
FDatalink.Size (And also seems to ignore DisplayWidth).


The problem comes when you look at the code for TStringField.GetValue, 
where it starts off as:


function TStringField.GetValue(var AValue: string): Boolean;

var Buf, TBuf : TStringFieldBuffer;
DynBuf, TDynBuf : Array of char;

begin
  if DataSize <= dsMaxStringSize then
begin
Result:=GetData(@Buf);
Buf[Size]:=#0;  //limit string to Size
If Result then
  begin
...

If nothing else, this is a "bug in waiting". TStringField.GetDataSize 
always returns "Size+1", so "Buff[Size]:=#0; should work - but only as 
long as the virtual method "GetDataSize" is not overridden (GetValue is 
non-virtual) and Size is the byte length of the string!


There is a built-in assumption here that "Size" is the byte length of 
the string and not the character length. If you have a multi-byte 
character set and set size to the number of characters and DataSize to 
e.g. for UTF8 4*(no of characters)+1, then you will get string 
corruption as a result of the above.


IBX handles multi-byte character sets and does so by defining 
TIBStringField as a subclass of TStringFIeld and setting size to the 
byte length and the Default DisplayWidth to the character width. This is 
compatible with TStringField as it works today. It also seems to be 
compatible with TDBGrid, which uses Field.DisplayWidth. However, it does 
result in TDBEdit accepting too many characters.


What should be done?

It's a problem. Ideally, the TStringField code should be aligned with 
the documentation. However, that could break existing code and would 
need to handled carefully. TStringFIeld also needs fixing i.e. to 
Buf[DataSize-1]:=#0 in order to make this a reality.


Alternatively, the documentation could be amended to reflect the 
implementation. This means that TDBEdit (and maybe more) have to be 
updated - but why doesn't TDBEdit respect the DisplayWidth property anyway?


Perhaps, it is also about time that TStringField got a characterWidth 
property to hold the maximum number of bytes for each character. That 
would at least allow the DataSize to be automatically computed from the 
character width.


If I had to write a bug report today, I would write it to avoid changes 
to IBX - but then is that the right answer?


Tony Whyman

MWA

--
___
Lazarus mailing list
Lazarus@lists.lazarus-ide.org
http://lists.lazarus-ide.org/listinfo/lazarus


Re: [Lazarus] Anyone has experience controlling Excel from FPC/delphi via OLE Automation?

2016-10-05 Thread Tony Whyman via Lazarus

Denis,

Answer is yes - and only yesterday was I working on such a program.

Years ago I did the same from Delphi and used the type libraries. With 
FPC, the key is to use variants. As an example, I've attached a neat 
little unit for exporting a DBGrid to an Excel spreadsheet.


Regards

Tony Whyman

MWA

unit ExcelWorkbook;

{$MODE Delphi}

interface


uses
  Classes, SysUtils, variants, DBGrids, DB, Forms;

type

  { TExcelWorkbook }

  TExcelWorkbook = class
  private
FWorksheet: variant;
FWorkbook: variant;
FServer: variant;
procedure CopyToWorkbook(DBGrid: TDBGrid; aFieldCount: integer); 
overload;

procedure CopyToWorkbook(ds: TDataSet; aFieldCount: integer); overload;
procedure SetCell(Row,Col: integer; aText: string);
procedure WriteFieldList(Fields: TFields; FieldCount: integer);
procedure WriteRecord(DataSet: TDataSet; row, aFieldCount: integer);
  public
constructor Create;
destructor Destroy; override;
procedure SaveAs(DBGrid: TDBGrid; aWorkbookFile: string);
procedure OpenInExcel(DBGrid: TDBGrid);
  end;

implementation

uses ComObj, CSVGridUnit, memds;

const
  ServerName = 'Excel.Application';

resourcestring

  sUnknownField = 'Unknown Field Type';
  sBadGraphic   = 'Unable to generate CSV data for a Graphic Field';
  sBadParadox   = 'Unable to generate CSV data for a Paradox OLE Field';
  sBadDBase = 'Unable to generate CSV data  for a DBase OLE Field';
  sBadBinary= 'Unable to generate CSV data  for a Binary Field';
  sBadCursor= 'Unable to generate CSV data  for a Cursor Field';

  { TExcelWorkbook }

procedure TExcelWorkbook.CopyToWorkbook(DBGrid: TDBGrid; aFieldCount: 
integer);

var ds: TMemDataset;
i: integer;
begin
  if (DBGrid.DataSource = nil) or (DBGrid.DataSource.DataSet = nil) then
raise Exception.Create('Create Excel Workbook: A Dataset must be 
assigned');


  ds := TMemDataset.Create(Application);
  try
ds.Clear(True);
AddFileDefs(ds,DBGrid.Columns);
ds.CreateTable;
ds.Active := true;
CopyData(ds,DBGrid.DataSource.DataSet);
SetColumnHeadings(ds,DBGrid.Columns);
for i := 1 to DBGrid.Columns.Count do
   FWorksheet.Cells.Item(1,i).ColumnWidth := 
DBGrid.Columns[i-1].Width div 5;

CopyToWorkbook(ds,aFieldCount);
  finally
ds.Free;
  end;
end;

procedure TExcelWorkbook.CopyToWorkbook(ds: TDataSet; aFieldCount: integer);
var
  {$IF FPC_FULLVERSION >= 20700 }
  bk: TBookmark;
  {$ELSE}
  bk: TBookmarkStr;
  {$ENDIF}
row: integer;
begin
  row := 2;
  with ds do
  begin
bk := Bookmark;
DisableControls;
try
  if aFieldCount = 0 then
 aFieldCount := FieldCount;
  Last;
  WriteFieldList(Fields,aFieldCount);
  First;
  while not EOF do
  begin
WriteRecord(ds,row,aFieldCount);
Next;
Inc(row);
  end;
finally
  Bookmark := bk;
  EnableControls;
end;
  end
end;

procedure TExcelWorkbook.SetCell(Row, Col: integer; aText: string);
var w: WideString;
begin
  w := UTF8Decode(aText);
  FWorksheet.Cells.Item(Row,Col).Value := w;
end;

procedure TExcelWorkbook.WriteFieldList(Fields: TFields; FieldCount: 
integer);

var I: integer;
begin
  for I := 0 to FieldCount - 1 do
SetCell(1,I+1,Fields[I].FieldName);
end;

procedure TExcelWorkbook.WriteRecord(DataSet: TDataSet; row, 
aFieldCount: integer);

var I: integer;
begin
  with DataSet do
  begin
for I := 0 to aFieldCount - 1 do
begin
  case Fields[I].DataType of
  ftUnknown:  raise Exception.Create(sUnknownField);
  ftString:   SetCell(row,I+1,Fields[I].AsString);
  ftSmallint,
  ftInteger,
  ftWord,
  ftLargeInt,
  ftBoolean:  SetCell(row,I+1,Fields[I].DisplayText);
  ftFloat,
  ftCurrency,
  ftFmtBCD,
  ftBCD:  SetCell(row,I+1,Fields[I].AsString);
  ftDate,
  ftTime: SetCell(row,I+1,DateTimeToStr(Fields[I].AsDateTime));
  ftDateTime: SetCell(row,I+1,Fields[I].AsString);
  ftBytes,
  ftVarBytes,
  ftBlob,
  ftAutoInc: SetCell(row,I+1,Fields[I].AsString);
  ftMemo: SetCell(row,I+1,Fields[I].AsString);
  ftGraphic:  raise Exception.Create(sBadGraphic);
  ftFmtMemo:  SetCell(row,I+1,Fields[I].AsString);
  ftParadoxOle: raise Exception.Create(sBadParadox);
  ftDBaseOle:   raise Exception.Create(sBadDBase);
  ftTypedBinary:raise Exception.Create(sBadBinary);
  ftCursor:raise Exception.Create(sBadCursor);
 end
end;
  end;
end;

constructor TExcelWorkbook.Create;
begin
  try
FServer := CreateOleObject(ServerName);
  except
raise Exception.Create('Unable to start Excel.');
   end;
  FWorkbook := FServer.Workbooks.Add;
  FWorksheet := FWorkbook.Worksheets.Add;
end;

destructor TExcelWorkbook.Destroy;
begin
  if not FServer.Visible then
  begin
   if not VarIsEmpty(FWorkbook) then
  FWorkbook.Close(0); {Do not save Changes}
FServer.Quit;
  end;
  inherited Destroy;
end;

procedure TExcelWorkbook.SaveAs(DBGrid: