Pascal Newsletter #47 - 25-MAY-2003
Contents
1. A few words from the editor
2. Interbase Performance Guidelines (Part II)
- Interbase configuration
· Regularly backup and restore
· Interbase Priority Class
· Turn async writes off
· Turn off garbage collection
· Lock hash slots
· Database page size
· Working set
· Database cache
- Development considerations
· Always work with the smallest amount of data possible
· Don't keep transactions open longer than needed
· Large system, lots of traffic, cache your lookup tables
· Program directly to the InterBase API
· Use a remote connection
· Fully populate and test your system during development
· Prepare and parametize your queries
· VCL components
· Think about what you are doing
· Something's will be slow
· Use the client
· See what your application actually does rather than what you
think that it does
· Use native access components
· Searching for records
- Other ways to improve performance
· Upgrade Interbase
· Read-only databases
3. Using Cabinet.dll to create your own cabinet files (.CAB)
4. Detecting right-clicks on your form's title bar
How to prevent the title bar's context menu from popping up
5. High Accuracy Timings/Timer
Utilizing QueryPerformanceCounter to get High Resolution Timings
6. Inline Assembler in Delphi (IX) - 128-bit integer arithmetic (3)
7. Forums / mailing lists
8. Delphi on the Net
- Components, Libraries and Utilities
· Shareware/Commercial
· Freeware
· Delphi updates
- Articles, Tips and Tricks
- Tutorials
- Other Links
- News
________________________________________________________________________
1. A few words from the editor
As usual, I have to apologize for the delay. Well, I guess you all know
how it is...
In the code in the article "Enumerating Network Connections" published
in the last issue, the memory assigned by the call to GlobalAlloc was
not freed by GlobalFree because the pointer was modified in between
since it was used to iterate thru the items of the enumeration. An
auxiliary pointer should be used for that purpose to preserve the value
assigned by GlobalAlloc. Thanks to Wim van Nifterick for finding this
out, and special thanks to Bill Boulton for helping me with Delphi 3
compatibility.
Now it's time to thank the authors who contributed articles for this
issue: Peter Mc Leod, Vimil Saju, James Clements, and Michael Darling,
and I'm pleased to give the prizes for this issue to:
* Vimil Saju (Using Cabinet.dll to create your own cabinet files)
· SDL Component Suite 7.0 - by Software Development Lohninger ($99)
The SDL Component Suite provides a wide range of components for
science and engineering, e.g. math, statistics, chemistry, charts,
data visualization, Fourier transform (FFT), 3D plots, geographic
maps, curve fitting, etc. Available for Delphi 3-7 and BCB 4-6.
http://www.lohninger.com/sdlindex.html
* James Clements (Detecting right-clicks on your form's title bar)
· NTTools 7 For Delphi - by i-tivity (US$39.95)
Stop battling the Windows NT Security API! Get your copy of NTTools 7
for Delphi 4/5/6/7 now and save countless hours with this collection
of 40 VCL components written specifically to deal with the Windows NT
Security functions. Full source code is included.
http://www.i-tivity.biz/nttools.htm
For the next issue, we have available the following prizes for two of
our contributors:
* SMImport v1.75 - by Scalabium Software ($30 standard, $50 with source)
Native VCL suite for importing data into a dataset without external
libraries. Supports import from: Access (using DAO/MS Jet), Excel
(without OLE/DDE), Lotus 123, QuattroPro, text, HTML, XML including
TClientDataset format, Paradox, dBase and any TDataSet descendant.
New in v1.75: visual Expression Builder; import from Word; direct
import for dBase, no BDE required; load BLOB fields for XML; extended
style for wizard dialog; OnCreateStructure event that allows creation
of a dataset with parsed columns before real import; and more.
http://www.scalabium.com/
* EurekaLog v4.1.1 - by Fabio Dell'Aria (Std $24, Pro $49, Ent $99)
EurekaLog gives your application (GUI, Console, Web, etc.) the ability
to catch every exception, generate a detailed log (with unit, class,
method and line #) and send it via email. Fully integrated into the
IDE, you only need a single rebuild to add EurekaLog to your apps.
Does not decrease performance and increases compiled file size by just
0.5% - 4%. Compatible with Delphi 3 - 7 and all Windows platforms.
http://www.eurekalog.com/bannerclick.php?id=15
Delphi Informant Magazine is conducting the traditional annual survey
for their Readers Choice Awards. Please take a moment to select your
favorite Delphi tools: http://www.delphizine.com/ballot2003/
Regards,
Ernesto De Spirito
eds2008 @ latiumsoftware.com
__________________
Collaborated in this issue: Dave Murray and Bill Boulton
________________________________________________________________________
Vote for the Pascal Newsletter in The Programming Pages!
http://www.programmingpages.com/?r=latiumsoftwarecomenpascal
________________________________________________________________________
2. Interbase Performance Guidelines (Part II)
By Peter Mc Leod <PeterMcLeod@practical.com.au>
Interbase configuration
=======================
Regularly backup and restore
----------------------------
Your database is a source of competitive advantage to your customers
because of the information that it contains. Performing regular backups
is essential to ensure the integrity of data for your clients. A
restore is just as important as it optimizes the database by:
- rebuild indices,
- eliminate obsolete record versions (garbage collection),
- defragment database pages,
- rewrite database tables contiguously, and
- recalculates database statistics.
A good tool for performing backups and restores is IBBackup which is
available from www.ibphoenix.com
Note: It is suggested that before restoring your database that you make
a copy of the original, and then perform your restore. This is
since the Restore does Integrity checking of your database, as
this is processor intensive. Essentially this means that it
could be possible to have a faulty backup that cant be restored.
The backup does not do this because the idea of backing up is to
secure your data without impacting on system performance.
Interbase Priority Class
------------------------
The Interbase Priority Class should be set to high (SuperServer version
under Windows) to ensure that Interbase can demand more of the system's
resources. This can be done through IBConsole in the Windows version. Or
edit the ibconfig file and set the SERVER_PRIORITY_CLASS to two to
achieve this (remove the # to uncomment this line otherwise the default
will apply).
Turn async writes off
---------------------
Under Windows NT, Interbase defaults to having forced writes on. This
means that write operations to Interbase, go direct to the database and
not through the Operating System Cache, which is slow. On Linux systems
the reverse occurs. This can result in a performance difference of more
than 300% for some operations.
The problem is that if you turn Async Writes off under Windows, and the
Operating system crashes while Interbase is writing to disk, you run the
risk of losing data, and potentially corrupting your database. As Linux
is inherently more stable this is not so much of a risk. If you wish to
turn Async writes off then make sure that you make lots of backups of
your database and that you have a good UPS on your server (you should do
lots of backups and have a good UPS anyway):
GFIX -WRITE ASYNC/SYNC MYDATABASE.GDB
Turn off garbage collection
---------------------------
Interbase by default performs a sweep of the database to Garbage collect
old records when too many accumulate. This unfortunately can severely
impact on the performance of the client process that caused this
threshold to be reached. To disable automatic Garbage collection, you
issue the following command from Gfix to your database:
gfix -h 0
Note: Regular Backup and Restores will perform Garbage collection on the
Database. This is another reason why the database should be backed
up regularly and restored as often as is practical.
Lock hash slots
---------------
The Lock hash slots parameter is used to determine the size of the hash
table utilized to find locks on a particular database object (this is
true of all systems except VAX/VMS). The number should be a prime number
to help the hash algorithm produce a good distribution. Usually the
first indication that a problem exists with the size of the Lock Hash
Slots configuration is declining performance for the Interbase Server
(where you have lots of users and a large cache pages). To determine if
this is the problem produce a Lock table print out (while the system is
actively being used) and examine the average hash length. If this is
greater than 10 you have a problem. To calculate a new Lock Hash Slot
parameter multiply the average length by the current number of slots and
divide the result by nine. Adjust this up as necessary to ensure that it
is a prime number, but one that is between 101 and 2048 (these are the
limits for this parameter). To change the parameter edit the ibconfig
file and change the value, but remember to remove the '#' from
LOCK_HASH_SLOTS so this setting will take effect. I initially set the
LOCK_HASH_SLOTS to 501 for most Interbase installations that we use. If
you perform this on the Super Server Architecture you should increase
the lock table size as well.
Database page size
------------------
The Database page size determines how much data will be retrieved with
one logical access to the database. Interbase has a default 1Kb page
size, with permitted values being 2Kb, 4Kb, and 8Kb.
For small Databases (less than 4 Gig in size), set the Database Page
size to 4096 (4K) bytes, for large databases this should be set to
8192 (8K). Tests on database performance indicate that a change from
a 1Kb page size to a 4Kb page size can increase database performance
around 20%.
By having a 4Kb, page size for most databases, the database I/O matches
the operating system I/O default sizes, resulting in greater efficiency
and performance. Other advantages of a large page size include:
· Less record fragmentation as more records can be stored on a page
· Fewer pages returned for a given query (as records are stored more
contiguously)
· Index B-trees are shallower
· I/O is more contiguous
The above Database Page sizes are guidelines only; it is recommended
that you perform some testing, to determine what size is most applicable
to your system.
For a change in the database page size to take effect you will need to
perform a backup and restore of your database.
Working set
-----------
The working set configuration parameters are only applicable to
Interbase running under Windows (using the Super Server architecture).
These configuration parameters determine how much RAM is dedicated to
the Interbase process. The minimum Process working set defines the
minimum amount of physical RAM that is guaranteed for the Interbase
process. The maximum working set defines the amount of memory above
which Interbase will start to use the system cache. I recommend that
the minimum working set is determined by taking the allocation for the
Database Cache Pages and adding three megabytes. Leaving the maximum
Process working set to zero will allow the system to determine the
point at which Interbase needs to swap to disk. The maximum working set
should always be higher (or set to zero) than the Database Cache
otherwise the system will continuously page to disk for all operations.
Database cache
--------------
The Database Cache is a Cache of the number of pages of the database
that are cached by the Server's RAM. Some experimentation with setting
the database Cache (in ibconfig) to a value between 256 and 10,000
produces increased performance up to a point. After this point declining
performance is noticed.
It is also a good idea to set the cache for the database using GFIX with
the following command:
Gfix -buffers 10000 -user sysdba -password masterkey mydatabase.gdb
If you have a small database then you should use statistics to find out
how many pages are in the database. You shouldn't set the Cache on the
database to a figure higher than the number of pages in the database,
since any given page from disk will only occupy one page in the cache.
Development considerations
==========================
Always work with the smallest amount of data possible
-----------------------------------------------------
Network traffic is a major factor in the perceived performance of your
application. If you have 100,000 records and you do something like
"Select * from myTable" you will be pulling down all the records. Using
filters to only return a subset of data helps reduce this. If possible
avoid the use of grids that display a large set of records. Use
SQLMonitor (or it's equivalent) to profile your SQL commands and see
what ACTUALLY happens as your application runs.
Don't keep transactions open longer than needed
-----------------------------------------------
Holding a transaction open can lock records in a database. Holding
transactions open for a long period of time will also increase the
amount of memory that Interbase requires to keep track of those
transactions. Instead of starting a transaction as soon as a data input
screen is opened and then committing the transaction when the user
presses Save, it is better to get a copy of the data and then start a
transaction and commit the transaction as soon as the Save button is
pressed. A number of techniques facilitate this approach, such as
ClientDatasets. These techniques have the advantages of:
· Reducing network traffic.
· Reduces the risk of database locks
· Reduces the life of a transaction
· Reducing the amount of memory that Interbase requires keeping track
of those transactions
Large system, lots of traffic, cache your lookup tables
-------------------------------------------------------
If you have any data that does not change (such as States, or
Countries), then you have an opportunity to cache this information in a
ClientDataset on the client machine (rather than retrieve the details
from the Server), then you can simulate a join on the client side by
using a calculated field. This allows you to reduce the number of
fetches that you need to do to the database, and reduces your network
traffic.
Program directly to the InterBase API
-------------------------------------
If speed is an absolute necessity then a program written in C with
embedded SQL performs better than an Interbase client application
running through layers of middleware (such as the BDE etc). This type
of application is programmed directly to the API in GDS32.DLL, which
produces its speed improvement.
Use a remote connection
-----------------------
When developing your application do not use the local connection string
when connecting to your database (c:\path\mydatabase.gdb), as it uses
memory-mapped files to communicate to your database. With some versions
of Interbase the use of local and remote connection strings together
could cause a physical corruption of the database. Use a remote
connection string, as this will give a better indication of your
system's actual performance (servername:c:\path\mydatabase.gdb) and will
allow you to pinpoint problems early on. Better still, actually develop
your application by connecting to a database on another machine across a
network.
Fully populate and test your system during development
------------------------------------------------------
Often developers will use a cut down system during the development and
testing process on their development machine. The disadvantage of this
is that retrieving only a few records (or even a few hundred records)
locally will be extremely fast. The reality is that you are most likely
going to be developing a client-server system which has to run across a
network, and may have many thousands or even millions of transactions in
your system. To test your system, run it across a network, ensuring that
the database is properly populated (and I would recommend populating it
with around 1/3 more records than you would expect that someone would
have in their system). Preferably perform your tests on the minimum
hardware and network environment that you would expect your system to
run on.
Prepare and parametize your queries
-----------------------------------
Wherever possible, write a query statement which can be parameterized
and prepare the query before executing it (it only needs to be prepared
once as it stays prepared until you explicitly unprepare it or you
change the contents of the SQL property). Prepared and parameterized
queries/statements are faster than non-prepared parameterized
queries/statements.
VCL components
--------------
A TQuery component was designed for use in client-server applications,
and should always be used in replace of a TTable component which is for
local database development. When using TQuery, allow the server to
handle updates, deletes and conflicts by having RequestLive=False.
Don't use Locate or RecordCount as these perform a fetchall. Use a where
clause to ensure that the server does the filtering of data for you.
Think about what you are doing
------------------------------
When designing your system remember just because Interbase let's you do
something that does not mean to say that it is a good idea. All actions
have a consequence. Think about how you are designing and developing
your system and what the ramifications are going to be for you, the
network and the clients. Remember it is possible that someone else will
have to maintain this system.
Some things will be slow
------------------------
When developing a system if you have to perform the same task over and
over again, say a million times, it is going to be slow regardless of
how fast your client and server are. If this is the case see if your
design philosophy can allow you to design this type of processing out
of the system. In some cases this is not going to be possible, in which
cases you may need to employ a system where this sort of processing is
performed outside of normal client usage.
Use the client
--------------
In a client-server system, you don't have to send everything back to the
server for processing. You can distribute the load by performing some of
your work on the client machine. If you cache the details of your
calculations then the advantage of this is reduced network traffic,
shorter transactions and not bogging the server down with every single
process. An example of this would be calculating the cost for each item
on a purchase order and the total for the purchase order on the client.
See what your application actually does
rather than what you think that it does
---------------------------------------
Tools such as SQL Monitor give you an insight into the way your
application requests data from Interbase. These tools are invaluable as
they allow you to see things like:
· Connect/Disconnect
· Transactions
· Execute Statements
· Statement Operations
Also various VCL components behave in different ways. Using SQL Monitor
gives you the opportunity to investigate what is going on behind the
scenes with these components, and also what happens when you make design
changes to your application.
Other tools, which should be in your application development arsenal,
include:
· Interbase Performance Monitor by Craig Stuntz
(requires Interbase 7.0 or higher)
· Interbase Plan Analyser by Craig Stuntz
· Sleuth QA Suite by TurboPower Software
(allows you to performance tune your Delphi/C++ Builder application)
Use native access components
----------------------------
The BDE is now a deprecated system and will no longer be supported by
Borland. Components like IBX, FibPlus, and IBObjects provide a
performance increase by around 40%, in comparison to the BDE. These
components also provide access to more of Interbase's internal features.
The use of such components however does tie you to the Interbase
platform. If this is a problem then the dbExpress components, provide
you with the ability to connect to Interbase and other databases, while
still obtaining good performance (not quite as good as IBX etc, but
certainly no where near as slow as the BDE).
Searching for records
---------------------
Soundex is a method of indexing that was developed by the U.S. Census
department, for grouping similar sounding names together. As an example,
performing a search of 300,000 records for the name "smith" could take
around 2.95 to complete, whereas a soundex could yield the result in
around 0.77 seconds, except it would include the name "smith" and names
that sound like "smith". For a good overview on creating and using a
Soundex function refer to the article "Implementing a Soundex Function"
by John Midwinter found at http://www.ibphoenix.com
Other ways to improve performance
=================================
Upgrade Interbase
-----------------
Each new version of Interbase (or Firebird) implements enhancements that
increase the performance of the RDBMS, or increases programmer
flexibility through language extensions. The increased performance and
functionality allows you to build a better client-server system. Due to
the recent enhancements to these products anyone using a version of
Interbase prior to version 7.0 should consider upgrading. If this is not
an option, then consider upgrading to the latest version of Firebird.
Read-only databases
-------------------
A database will normally leave some free space on it's pages (about 25%
is left free) to allow for new record versions. In a database where the
primary purpose for retrieving and viewing data, this means more pages
need to retrieved to view the data. For these read only databases these
pages can be filled up so that the data is more contiguous and less
pages need to be retrieved by using the following GBAK command:
GBAK -C -USE_ALL_SPACE backup.gbk mydatabase.gdb
________________________________________________________________________
Delphi BUGS?
Catch & Log every BUG showing Unit, Class, Method, Line #.
Now with support for command-line compiler and IntraWeb applications.
http://www.eurekalog.com/bannerclick.php?id=15
________________________________________________________________________
3. Using Cabinet.dll to create your own cabinet files (.CAB)
By Vimil Saju vimil@mec.ac.in
I have created a component that enables one to compress files to a
cabinet file. This component requires the cabinet.dll which usually
resides in your system folder. This component consists of two units. The
first unit contains all the structures required by the component.
I have updated the Cabinet unit. Now you can add files by using wild
cards. The Compression now takes place in a separate thread, so that
your program won't freeze. I have fixed the bug in OnStatusEvent, it
shows the progress correctly now. I have also added an abort function
which can be called during the compression process so to cancel
compression. You can now specify the directory in which you want to
decompresss the file using the 'AddFile' function.
I have added a decompress facility, though it is not yet perfected. The
Decompressor and compressor run in separate threads so that the
application does not freeze. You can also get the list of files present
in a cabinet without extracting them. Many bugs were removed. Now there
are two components: TCabCompressor and TCabDecompressor.
To select an individual file to decompress you have to first select it
by calling the funtion CabDecompressor1.Files[0].Select. To select all
files you can call the function CabDecompressor1.SelectAllFiles and to
select files using wildcards use the function
CabDecompressor1.SelectFilesByWildCard.
The BeforeCopyFile event in TCabDecompressor Class has been updated to
include a parameter called Overwrite which indicates whether the file
being decompressed will overwrite an existing file or not.
The two units along with a demo program are attached in the zip archive.
__________________
The latest version of this article and its source code can be found at
Delphi3000.com: http://www.delphi3000.com/articles/article_1820.asp
________________________________________________________________________
TsiLang Components Suite, by SiComponents. A full set of professional
components for building elegant, useful and user friendly multilingual
applications in a snap. http://www.sicomponents.com/tsilang1.html
________________________________________________________________________
4. Detecting right-clicks on your form's title bar
How to prevent the title bar's context menu from popping up
By James Clements <essexboy @ bigfoot.com>
How do I detect a right click and/or kill the menu for my title bar?
This is a relatively simple problem. You just need to know the correct
Windows message to trap. Here's how to do it:
Declaration:
procedure WMNCRButtonDown(var Msg : TWMNCRButtonDown);
message WM_NCRBUTTONDOWN;
Definition:
procedure TMainFrm.WMNCRButtonDown(var Msg : TWMNCRButtonDown);
begin
if (Msg.HitTest = htCaption) then
begin
// your code here
// the next line kills the menu
Msg.HitTest := 0;
end
else
inherited;
end;
Additional information:
* NC stands for non-client
* WMNCLButtonDown or WMNCMButtonDown may be used instead for left or
middle button respectively
* No WM_NCRBUTTONUP message is generated, only a WM_RBUTTONUP when the
mouse button is released
This has been tested with Delphi 5 on Windows 2000, 95, 98 and NT 4.0.
It should also work fine with other versions of Delphi, but these have
not been tested.
________________________________________________________________________
Resource Builder 2.0, by SiComponents. A full-featured tool for visually
building RC scripts and resource files for your apps. Includes powerful
image editors and JPEG support. http://www.sicomponents.com/rbldr.html
________________________________________________________________________
5. High Accuracy Timings/Timer
Utilizing QueryPerformanceCounter to get High Resolution Timings
By Michael Darling <michael.darling @ which.net>
The standard Time and Now functions, and even the TTimer, are only
accurate to 55 milliseconds as they use the PC's clock timer. For higher
accuracy timings, Windows provides a high performance counter which is
accessed through QueryPerformanceCounter and QueryPerformanceFrequency.
This class implements a Delphi interface to these methods.
The attached unit implements a HighResTimer object to simplify use of
the WinAPI QueryPerformanceCounter and QueryPerformanceFrequency high-
resolution counter functions. This can then be extended to provide
WriteToFile, LogToDB functionality, etc.
Just add the unit to your uses clause and then create an instance of
THighResTimer whenever you need it.
Note: The unit contains IFDEFs to handle the change to TLargeInteger in
Delphi versions 3, 4 & 5+.
Once created, the HighResTimer just needs to be started before
performing an action then stopped once the actions been performed. The
time taken can be retrieved as a TDateTime by calling the Time property
or as an integer by calling the Ticks property.
Example:
var
MyHighResTimer: THighResTimer;
i, j: Integer;
begin
MyHighResTimer := THighResTimer.Create;
try
MyHighResTimer.Start;
for i := 0 to 1000 do
begin
j := i;
end;
MyHighResTimer.Stop;
ShowMessage(Format('Operation took'#13'Time: %8.8f'#13'Ticks:%d',
[MyHighResTimer.Time, MyHighResTimer.Ticks]));
finally
MyHighResTimer.Free;
end;
end;
________________________________________________________________________
* LMD StoragePack - by LMD Innovative - Shareware (EUR 59)
Eight components for saving/restoring of configuration data (e.g. at
design time, via extended Property Selection dialog) to/from the
Windows Eegistry or Ini-, XML- and binary files, being easy to switch
between these formats. Full source code and demo projects included.
http://www.lmdinnovative.com/products/vcl/lmdstoragepack/
________________________________________________________________________
6. Inline Assembler in Delphi (IX) - 128-bit integer arithmetic (Part 3)
By Ernesto De Spirito <eds2008 @ latiumsoftware.com>
In this third and last part of the series on 128-bit integers (that we
called huge integers, big integers or large integers) we'll finally get
to see the actual arithmetics, with the four fundamental operations
(addition, subtraction, multiplication and division).
Before getting into them I'd like to say that the procedures and
functions introduced in the preceeding two parts have been corrected
and also further optimized. I still haven't been able to test them as
much as I'd have liked to. If you find any bugs or have any comments
about the source code, please drop me an email.
Addition
========
How do we add two numbers, each made up of four 32-bit integers? Well,
it's actually pretty easy. We simply add them in the same way that we
would add two numbers of four decimal digits (like 3597 and 0015 for
instance), except that here each "digit" can have about 4 billion
different (2^32) values instead of just ten. The algorithm would be
like this:
function AddWithCarry(x: Longint; y: Longint;
var Carry: Boolean): Longint; forward;
function HugeAdd(x: Hugeint; y: Hugeint): Hugeint;
// Result := x + y;
var
Carry: Boolean;
begin
Carry := False;
Result[0] := AddWithCarry(x[0], y[0], Carry);
Result[1] := AddWithCarry(x[1], y[1], Carry);
Result[2] := AddWithCarry(x[2], y[2], Carry);
Result[3] := AddWithCarry(x[3], y[3], Carry);
end;
AddWithCarry is a fictitious function which returns an integer with the
low order 32 bits of the result of the addition of the two arguments,
plus 1 if Carry (the third argument) is True. It also stores True or
False to the Carry (passed by reference) depending on whether the
addition generated a carry or not (or whether the carry is 1 or 0, if
you want to see it that way). Actually, this function doesn't have to be
fictitious:
function AddWithCarry(x: Longint; y: Longint;
var Carry: Boolean): integer;
asm
// if Carry then CF := 1 else CF := 0;
test byte ptr [ecx], -1 // Side-effect: CF := 0;
jz @@NoCarry
stc // CF := 1;
@@NoCarry:
// Result := x + y + CF; CF := GeneratedCarry;
adc eax, edx
// Carry := CF;
setc byte ptr [ecx]
end;
It would be more efficient to have HugeAdd coded entirely in assembler:
function HugeAdd(x: Hugeint; y: Hugeint): Hugeint;
// Result := x + y;
// Parameters: EAX = @x; EDX = @y; ECX = @Result
asm
push esi
mov esi, [eax+_0_] // ESI := x[0];
add esi, [edx+_0_] // ESI := ESI + y[0];
mov [ecx+_0_], esi // Result[0] := ESI;
mov esi, [eax+_1_] // ESI := x[1];
adc esi, [edx+_1_] // ESI := ESI + y[1] + Carry;
mov [ecx+_1_], esi // Result[1] := ESI;
mov esi, [eax+_2_] // ESI := x[2];
adc esi, [edx+_2_] // ESI := ESI + y[2] + Carry;
mov [ecx+_2_], esi // Result[2] := ESI;
mov esi, [eax+_3_] // ESI := x[3];
adc esi, [edx+_3_] // ESI := ESI + y[3] + Carry;
mov [ecx+_3_], esi // Result[3] := ESI;
pop esi
end;
Subtraction
===========
Subtraction works very much like addition, but instead of generating a
carry, the operation generates a borrow (also represented by the Carry
Flag) if the minuend (first operand) is less than the subtrahend (second
operand):
function SubtractWithBorrow(x: Longint; y: Longint;
var Borrow: Boolean): Longint; forward;
function HugeSub(x: Hugeint; y: Hugeint): Hugeint;
// Result := x - y;
var
Borrow: Boolean;
begin
Borrow := False;
Result[0] := SubtractWithBorrow(x[0], y[0], Borrow);
Result[1] := SubtractWithBorrow(x[1], y[1], Borrow);
Result[2] := SubtractWithBorrow(x[2], y[2], Borrow);
Result[3] := SubtractWithBorrow(x[3], y[3], Borrow);
end;
function SubtractWithBorrow(x: Longint; y: Longint;
var Borrow: Boolean): Longint;
asm
// if Borrow then CF := 1 else CF := 0;
test byte ptr [ecx], -1 // Side-effect: CF := 0;
jz @@NoBorrow
stc // CF := 1;
@@NoBorrow:
// Result := x - y - CF; CF := NeededBorrow;
sbb eax, edx
// Borrow := CF;
setc byte ptr [ecx]
end;
You should be ready to write a pure assembler version of HugeSub, since
it's the same as HugeAdd, but all you have to do is replace ADD and ADC
with SUB and SBB respectively.
Opposite number
===============
Given a number, these implementations of HugeNeg return it's opposite
number (two's complement):
function HugeNeg(x: Hugeint): Hugeint;
begin
// Result := (Not x) + 1;
Result := HugeAdd(HugeNot(x), IntToHuge(1));
end;
function HugeNeg(x: Hugeint): Hugeint;
begin
// Result := 0 - x;
Result := HugeSub(IntToHuge(0), x);
end;
The second one is the simplest and fastest because it involves a single
operation, and now that we know how to subtract, we can implement it in
assembler:
function HugeNeg(x: Hugeint): Hugeint;
// Result := -x;
// Parameters: EAX = @x; EDX = @Result
asm
// Result := 0 - x;
push esi
xor esi, esi
mov ecx, [eax+_0_] // x[0]
sub esi, ecx // 0 - x[0]
mov ecx, 0
mov [edx+_0_], esi // Result[0]
mov esi, [eax+_1_] // x[1]
sbb ecx, esi // 0 - x[1] - Borrow
mov esi, 0
mov [edx+_1_], ecx // Result[1]
mov ecx, [eax+_2_] // x[2]
sbb esi, ecx // 0 - x[2] - Borrow
mov ecx, 0
mov [edx+_2_], esi // Result[2]
mov esi, [eax+_3_] // x[3]
sbb ecx, esi // 0 - x[3] - Borrow
mov [edx+_3_], ecx // Result[3]
pop esi
end;
Multiplication
==============
A way of multiplying numbers is by means of an addition loop:
function HugeMul(x: Hugeint; y: Hugeint): Hugeint;
begin
SetZero(Result);
while not HugeIsZero(y) do begin
Result := HugeAdd(Result, x);
HugeSub(y, 1)
end;
end;
Computationally speaking, this algorithm is quite poor. For example, if
the value of "y" was 4 million, the loop would repeat 4 million times!
Anyway, the idea would still good if we could somehow accelerate the
process. Let's play a little bit with algebra:
x * y = x * (y[3]*2^96 + y[2]*2^64 + y[1]*2^32 + y[0]*2^0)
= (x*y[3])*2^96 + (x*y[2])*2^64 + (x*y[1])*2^32 + (x*y[0])*2^0
Now we have reduced the problem of multiplying two Hugeint numbers to
multiplying a Hugeint number by a 32-bit integer. We multiply the first
operand by the four integers that make up the second operand and then
we shift the partial results by 0, 32, 64, and 96 bits (to multiply
them by 2^0, 2^32, 2^64 and 2^96), and finally we add these values to
get the final result.
function HugeMulInt(x: Hugeint; y: Longint): Hugeint; forward;
function HugeMul(x: Hugeint; y: Hugeint): Hugeint;
begin
Result := HugeShl(HugeMulInt(x, y[3]), 96)
+ HugeShl(HugeMulInt(x, y[2]), 64)
+ HugeShl(HugeMulInt(x, y[1]), 32)
+ HugeMulInt(x, y[0]);
end;
This is exactly the way we multiply decimal numbers when performing
caculations on a paper, except that here the base is 2^32 instead of
ten. Let's see now how we can a multiply a Hugeint by an integer:
function MultiplyWithCarry(x: Longint; y: Longint;
var Carry: Longint): Longint; forward;
function HugeMulInt(x: Hugeint; y: Longint): Hugeint;
// Result := x * y;
var
Carry: Longint;
begin
Carry := 0;
Result[0] := MultiplyWithCarry(x[0], y, Carry);
Result[1] := MultiplyWithCarry(x[1], y, Carry);
Result[2] := MultiplyWithCarry(x[2], y, Carry);
Result[3] := MultiplyWithCarry(x[3], y, Carry);
end;
function MultiplyWithCarry(x: Longint; y: Longint;
var Carry: Longint): integer;
// Result := LoDWord(x * y + Carry);
// Carry := HiDWord(x * y + Carry);
asm
// EDX:EAX := EAX * EDX; // x * y
mul edx
// Inc(EDX:EAX, Carry);
add eax, [ecx]
adc edx, 0
// Carry := EDX; // High order 32 bits of the result
mov [ecx], edx;
end;
MultiplyWithCarry is very much like AddWithCarry, but it performs a
multiplication instead of an addition, and it generates a carry of 32
bits instead of just one bit (the multiplication of two 32-bit values
generates a 64-bit result, while the addition of two 32-bit values can
generate a 33-bit result).
MultiplyWithCarry first performs an unsigned multiplication of "x"
(EAX) by "y" (EDX), using the MUL opcode. The result is a 64-bit
unsigned integer in EDX:EAX, to which the function adds the Carry
passed by parameter. The function returns the lower 32 bits of this
final result (located EAX), and the higher 32 bits (EDX) constitute
the carry for the next multiplication, which are stored in the Carry
parameter (passed by reference).
An assembler implementation of HugeMul and HugeMulInt can be found in
the source code attached. For reasons of simplicity, in the examples
above the functions consider the numbers are unsigned, but the
assembler implementations consider signed numbers. Also, the attached
version of HugeMul doesn't call HugeMulInt or HugeShl, and is highly
optimized.
Instead of considering a Huge integer as four 32-bit integers
multiplied by four powers of 2^32, we consider them as 128 1-bit
integers multiplied by 128 powers of 2:
bit127 * 2^127 + bit126 * 2^126 + ... + bit1 * 2^1 + bit0 * 2^0
Since each bit can only be 0 or 1, the algorithm shown above can be
greatly simplified:
function HugeMul(x: Hugeint; y: Hugeint): Hugeint;
// Result := x * y;
var
i: Longint;
begin
SetZero(Result);
for i := 0 to 127 do
if BitTest(y, i) then
Result := HugeAdd(Result, HugeShl(x, i));
end;
The idea is to add different powers of 2 of "x", depending those powers
on the bits set on "y". For example, if "y" was 20, bits 5 and 3 would
be on (20 in decimal is 10100 in binary), so only two additions would be
performed, and the result would be HugeShl(x, 3) plus HugeShl(x, 5).
This algorithm can be coded quite efficiently in assembler, but still
the first algorithm will work faster. The reason why I've shown this is
because it'll make it easier to understand the algorithm we'll use for
divisions.
Division
========
Let's first see the case of a division of a Hugeint by a 32-bit integer,
which should be easy to understand:
function DivideWithRemainder(x: Longint; y: Longint;
var Remainder: Longint): Longint; forward;
function HugeDivInt(x: Hugeint; y: Longint): Hugeint;
// Result := x div y;
var
Remainder: Longint;
begin
Remainder := 0;
Result[0] := DivideWithRemainder(x[3], y, Remainder);
Result[1] := DivideWithRemainder(x[2], y, Remainder);
Result[2] := DivideWithRemainder(x[1], y, Remainder);
Result[3] := DivideWithRemainder(x[0], y, Remainder);
asm
mov edx, Remainder
end;
end;
function DivideWithRemainder(x: Longint; y: Longint;
var Remainder: Longint): Longint;
// Result := Remainder:x div y;
// Remainder := Remainder:x mod y;
asm
push esi
mov esi, edx // y
mov edx, [ecx] // Remainder
// EAX := EDX:EAX div ESI;
// EDX := EDX:EAX mod ESI;
div esi
// Remainder := EDX;
mov [ecx], edx;
pop esi
end;
HugeDivInt leaves the remainder of the division in EDX, so it can be
used in a function returning the remainder of the division:
function HugeModInt(dividend: Hugeint; divisor: Longint): Longint;
// Result := dividend mod divisor;
// Parameters: EAX = @dividend; EDX = @divisor;
asm
sub esp, TYPE(Hugeint) // Make place on the stack for a Hugeint
mov ecx, esp // to hold the result of the division
call HugeDivInt // Perform the division
add esp, TYPE(Hugeint) // Restore the stack pointer
mov eax, edx // Result := Remainder; // was left in EDX
end;
For the case of two huge integers we can think of an algorithm like the
one we would use to divide two numbers of four digits with paper and
pencil, but it turns to be quite complex, plus it isn't actually very
fast since it implies divisions, multiplications, and substractions, and
sometimes you take one step forwards and two steps back. Is there
another possible algorithm? Yes, there is:
function HugeDiv(dividend: Hugeint; divisor: Hugeint): Hugeint;
// Result := dividend div divisor;
begin
if HugeIsZero(divisor) then
raise EDivByZero.CreateRes(@sDivByZero);
Result := 0;
while HugeCmp(dividend, divisor) >= 0 do begin
dividend := HugeSub(dividend, divisor);
Result := HugeAdd(Result, IntToHuge(1));
end;
end;
Of course, this algorithm turns out to be awfully slow (if we divide 12
million by 3, the loop would execute 4 million times), but we can speed
things up if we subtract from the dividend the divisor multiplied by
different powers of 2, from higher to lower, setting the corresponding
bit of the result every time we perform a subtraction (the bit in the
position of the power of 2 that was used). It's the inverse of what we
did in the case of a multiplication shown above. The division process
would then be reduced to just 128 subtractions at most.
In the following example, the dividend is 20 (10100 in binary) and the
divider is 3 (11 in binary):
10100 - 11 * 2^2 = 10100 - 1100 = 1000 Result := 100
1000 - 11 * 2^1 = 1000 - 110 = 10 Result := 110
Initially, 11 * 2^2 is the highest value that is less or equal to the
dividend, so we subtract that value from the dividend and we set bit
2 of the result because we subtracted the divisor multiplied by two
to the power of 2. So far, the remainder is 8 (1000 in binary), and
11 * 2^1 is the highest value that is less than or equal to this
remainder, so we subtract that value from the remainder, and we set bit
1 of the result because we subtracted the divisor multiplied by two to
the power of 1. The remainder is 2 (10 in binary), and since the divisor
is greater than that value, division stops there. The remainder of the
operation would then be 2 (10 in binary) and since bits 2 and 1 of the
result were set, the result is 110 in binary, i.e. 6 in decimal.
function HugeDiv(dividend: Hugeint; divisor: Hugeint): Hugeint;
var
_r_: Hugeint; // remainder
_d_: Hugeint; // divisor
_q_: Hugeint; // quotient
BitPosR, BitPosD, count: integer;
begin
_r_ := dividend;
_d_ := divisor;
HugeSetZero(_q_);
BitPosD := HugeBitScanReverse(_d_);
if BitPosD = -1 then RaiseDivByZero;
BitPosR := HugeBitScanReverse(_r_);
count := BitPosD - BitPosR;
if count > 0 then
_d_ := HugeShl(_d_, count);
repeat
if HugeCmp(_d_, _r_) <= 0 then begin
_r_ := HugeSub(_r_, _d_);
HugeBitSet(_q_, count);
end;
_d_ := HugeShr(_d_, 1);
dec(count);
until count < 0;
Result := _q_;
asm
lea edx, _r_
end;
end;
HugeBitScanReverse is a function that returns the position of the first
non-zero bit, performing the search from bit 127 to bit 0. If all bits
are zero, the result is -1. We use HugeBitScanReverse to determine the
first power of two we should multiply the divisor in order to begin the
iteration.
The assembler implementation of HugeDiv that you can find attached
supports signed numbers. It is just a first approximation, and it can be
heavily optimized.
The function leaves in EDX the address of the remainder, so it can be
used by a function returning the modulus of the division:
function HugeMod(dividend: Hugeint; divisor: Hugeint): Hugeint;
// Result := dividend Mod divisor;
// Parameters: EAX = @dividend; EDX = @divisor; ECX = @Result
asm
push ecx // @Result
call HugeDiv // EDX := @remainder;
pop eax // EAX := @Result;
call HugeMov // EAX^ := EDX^;
end;
________________________________________________________________________
Vote for the Pascal Newsletter in The Programming Pages!
http://www.programmingpages.com/?r=latiumsoftwarecomenpascal
________________________________________________________________________
7. Forums / mailing lists
To join any of our forums, the best way is to subscribe from the web,
since that way you'll be able to access the features available at the
web site (like changing your subscription options, viewing the past
messages, accessing the files section, etc.). A Yahoo! ID is required
for that, and you can get yours free by registering as a Yahoo! user,
but if you don't want to register or if you don't have full Internet
access, you can also subscribe by email (you'll only have email access).
* Delphi: If you know a lot about Delphi but you are still far from
being a guru this forum is for you. This is the only forum for
intermediate-level Delphi programmers on the Web (Delphi experts are
also welcome :-)
http://groups.yahoo.com/group/delphi-en/
Subscription:
http://groups.yahoo.com/group/delphi-en/join
delphi-en-subscribe@yahoogroups.com
* Kylix: Kylix programming.
http://groups.yahoo.com/group/KylixGroup/
Subscription:
http://groups.yahoo.com/group/KylixGroup/join
KylixGroup-subscribe@yahoogroups.com
* Components: This is a forum for searching/recommending software
components (VCL and CLX components, ActiveX objects, DLL libraries,
shared objects, etc.), as well as utilities, tutorials, information,
etc.
http://tech.groups.yahoo.com/group/components/
Subscription:
http://tech.groups.yahoo.com/group/components/join
components-subscribe@yahoogroups.com
* Software Developers: This is a forum for discussions about software
development and to share experience in the work, professional or
commercial environments. It is not a programming forum, matters
treated here are supposed to be more general or language independent.
http://tech.groups.yahoo.com/group/software-developers/
Subscription:
http://tech.groups.yahoo.com/group/software-developers/join
software-developers-subscribe@yahoogroups.com
________________________________________________________________________
Merlin's Delphi Forge
Delphi and Kylix news, FAQ, downloads, links, forums and more.
Accepting uploads and submissions.
http://www.delphifaq.net/
________________________________________________________________________
8. Delphi on the Net
By Dave Murray <irongut @ vodafone.net>
Components, Libraries and Utilities
===================================
Shareware/Commercial
--------------------
* SMImport v1.75 - by Scalabium Software ($30 standard, $50 with source)
Native VCL suite for importing data into a dataset without external
libraries. Supports import from: Access (using DAO/MS Jet), Excel
(without OLE/DDE), Lotus 123, QuattroPro, text, HTML, XML including
TClientDataset format, Paradox, dBase and any TDataSet descendant.
New in v1.75: visual Expression Builder; import from Word; direct
import for dBase, no BDE required; load BLOB fields for XML; extended
style for wizard dialog; OnCreateStructure event that allows creation
of a dataset with parsed columns before real import; and more.
http://www.scalabium.com/
* SMExport v4.30 - by Scalabium Software ($20 standard, $35 with source)
Native VCL suite for exporting data from different sources (dataset,
grids, decision cube, memory, DevExp trees etc). Supports export into:
MS Excel, MS Access, MS Word, PDF, Text/CSV, HTML, XML, dBase, RTF,
SQL, Lotus 1-2-3, QuattroPro and more.
http://www.scalabium.com/
* Storage Library v3.24 - by DeepSoftware.Ru ($39)
Storage Library - elegant way for application settings management.
Supports working with ini files, registry, xml files, TStream objects.
Provides encryption, unicode support, working with published
properties without programming, saving form position and much more...
http://www.deepsoftware.ru/rsllib/index.html
* Delphi Knowledge Base v1.5 ($29)
A unique collection of Delphi tips and articles where Delphi
programmers can find ideas, solutions and share their experience.
The new version contains these new features: fast article search,
integrated flat type interface, added bookmark system, new filtering,
grouping and sorting features in the article grid, multilingual
interface, generally improved article update tool and much more...
http://www.baltsoft.com/product_dkb.htm
Freeware
--------
* IBUtils v0.9.2.4 - by Ales Kahanek
IBUtils is designed to simplify database design for Interbase and
Firebird databases by showing the links between the tables in your
database visually, like some CASE tools do. It does not allow database
editing, it is a read-only tool. The model is saved to INI-like files
or can be exported as an image to a JPG or BMP file. Uses IBObjects.
http://www.alikiwi.com/ibutils/ibutils.htm
* Key Objects Library v1.72 - by Delphree (with source)
Based on experience aquired on eXtreme Class Library project. Main
purpose is to create smaller programs using Delphi environment.
http://delphree.clexpert.com/pages/app_KOL.htm
* GPU 0.788b - by Delphree (with source)
GPU is a Gnutella client for sharing files and CPU-resources. The
objective is to develop a robust framework for distributed computing
on a peer-to-peer grid.
http://delphree.clexpert.com/pages/app_GPU.htm
* TurboPower SysTools for Kylix v1.01 - by TurboPower (source) (KYLIX)
A library of utility routines and algorithms for Borland Kylix. Among
other things, it supports 1-Dimensional bar codes, date time and
string routines, sorting, a regular expression engine and a run-time
math expression analyzer.
https://sourceforge.net/projects/tpsystoolskylix/
Delphi Updates
--------------
* Patch: glibc update for Kylix 3 C++ package loading - by John Kaster
Linux distributions using glibc 2.2.x will probably encounter issues
loading the database and SOAP packages for the Kylix 3 IDE for C++.
This patch resolves that issue.
http://community.borland.com/article/0,1410,29968,00.html
Articles, Tips and Tricks
=========================
* Sip from the Firehose: It all starts with Define! - by David I
In the recent BDN 2003 Survey, David I asked members a question about
what drives their development processes and decisions. In this article
he reports the results.
http://community.borland.com/article/0,1410,30043,00.html
* Interview with Jeff Duntemann - by Clay Shannon
Jeff Duntemann tells about his experiences working for Borland,
writing and editing for Coriolis and Visual Developer, a rigged
programming contest he participated in vs. Bill Gates, what he does
everywhere, and what he's been up to lately.
http://community.borland.com/article/0,1410,30012,00.html
* Interview with Steve Teixeira - by Clay Shannon
Interview with Steve Teixeira, co-author of the classic "Delphi X
Developer's Guide". Among other things, Steve tells about his days at
Borland, how the above tome came about, and "geek" practical jokes.
http://community.borland.com/article/0,1410,29925,00.html
* Using Semaphores in Delphi Part 2: The Connection Pool - Cary Jensen
Semaphores are used to coordinate multiple threads and processes. The
ability of semaphore to provide multiple threads with simultaneous
access to a shared resource is highlighted by the TFixedConnectionPool
class described in this article.
http://community.borland.com/delphi/0,1419,1,00.html
* Binary Serialization with the .NET Framework and Delphi for .NET
- by Marcel van Brakel
This article explains binary serialization, complete with Delphi for
.NET and C# source code.
http://community.borland.com/article/0,1410,29787,00.html
* Simple Programming Tip #1 - by Charlie Calvert
This article describes the first of several simple programming tips.
The discussion and code in this article is generic and applies equally
to C++, C#, Delphi or Java. The tip for this article is: Avoid writing
code that does anything substantial inside a visual container, instead
write code inside separate classes designed for a single purpose.
http://community.borland.com/article/0,1410,30011,00.html
* MessageBox on top of "stay on top" forms - by Zarko Gajic
This tip causes "stay on top" forms to allow a MessageBox to appear on
top. After the message box is closed, the topmost forms are restored
so that they continue to float to the top.
http://delphi.about.com/cs/adptips2003/index.htm
* Mouse moving the contents of a ScrollBox - by Zarko Gajic
How to move a TImage object in a ScrollBox with the mouse, like a drag
and drop operation - without the scroll bars.
http://delphi.about.com/library/weekly/aa050603a.htm
* Sorting records in Delphi DBGrid - by Zarko Gajic
How to sort records in Delphi DbGrid by clicking on the column title.
How to change the appearance of the selected column title to reflect
the sort order. How to change the cursor when moving over the DBGrid
column titles.
http://delphi.about.com/library/weekly/aa042203a.htm
* Choosing a ZIP Library for Delphi - by Mark Steinberg
Describes the pros and cons of several ZIP libraries - VCLZip, ZipTv,
ZipForge, Abbrevia and Delphi Zip.
http://www.delphifaq.net/modules.php?name=FAQ&op=view&id=219
* How to encrypt/decrypt files using NTFS API - by m3rlin
http://www.delphifaq.net/modules.php?name=FAQ&op=view&id=220
* Coding DB2 SQL for Performance: The Basics - by Craig S. Mullins
Poorly coded SQL and application code can cause performance problems.
This article is intended to give the basics of good SQL programming to
application developers, particularly for those who are using Borland
Kylix and Delphi RAD tools.
http://www7b.software.ibm.com/dmdd/library/techarticle/0210mullins/
0210mullins.html
* Create a Reusable Component to Connect Delphi 7 to DB2 with dbExpress
- by Bob Swart
How to use IBM DB2 as the backend database for applications written
with Delphi 7 and dbExpress. Specifically, how to connect the seven
dbExpress components to DB2 and use them to build visual forms on top
of database tables.
http://www7b.software.ibm.com/dmdd/library/techarticle/0210swart/
0210swart.html
* Display and Modify DB2 Master-Detail Data in Delphi 7 Apps - Bob Swart
A typical real world application will involve combining and displaying
data from multiple tables in a usable format for reviewing and
editing. This article shows how to add data and create relationships,
manipulate the data from a Delphi application and get ready to move
the entire package to Linux with Kylix.
http://www7b.software.ibm.com/dmdd/library/techarticle/0211swart/
0211swart.html
* The Big Switch: Moving from Windows to Linux with Kylix 3 - Bob Swart
One of the great things about using tools and databases such as Delphi
IBM DB2 is that moving between platforms is only a matter of a few
changes and a recompile. This article shows how to take the big jump
and move a Delphi 7 application running on Windows to a Linux (Intel)
application using Kylix 3.
http://www7b.software.ibm.com/dmdd/library/techarticle/0211swart/
0211swart2.html
* Build DB2 and Delphi 7 Internet Applications with WebSnap - Bob Swart
With Delphi 7 WebSnap technology, you can quickly take data from an
IBM DB2 database and move it to a Web-based application in a snap.
http://www7b.software.ibm.com/dmdd/library/techarticle/0211swart/
0211swart3.html
* Create Distributed DB2 and Delphi Web Apps with DataSnap - Bob Swart
Enter the world of distributed applications, where you split your
application into two different tiers: a thin client and a database
server tier. This article focuses on the server side, as well as the
communication between the client and the middleware server.
http://www7b.software.ibm.com/dmdd/library/techarticle/0212swart/
0212swart.html
* DB2 and Delphi 7: SOAP and Database Web Services - by Bob Swart
Creating a distributed application based on SOAP as the communication
protocol, where the server (DB2) will be turned into a cross-platform
Web Service. As a consequence, you can compile both the server and the
client with Delphi 7 and Kylix 3 and deploy them on either Windows or
Linux; this is a true cross-platform solution.
http://www7b.software.ibm.com/dmdd/library/techarticle/0212swart1/
0212swart1.html
* Data Entry Input Validation With Delphi and Kylix - by Bob Swart
How to build data entry forms on top of IBM DB2 Universal Database as
database tables and records, and how to perform data entry validation
using Delphi Studio and Kylix. Uses dbExpress and DB2 PE v8.1.
http://www7b.software.ibm.com/dmdd/library/techarticle/0303swart/
0303swart.html
* Drill Into DB2 Tables for Decision Support Using Delphi - by Bob Swart
How to build decision-support functionality by drilling into IBM DB2
tables using the Decision Cube component of Delphi. Uses dbExpress to
connect to the DB2 UDB Personal Edition v7.x database.
http://www7b.software.ibm.com/dmdd/library/techarticle/0304swart/
0304swart.html
* DB2 + SOAP: Database Web Services Follow-up with DataSnap - Bob Swart
This extended DataSnap SOAP example covers deployment issues and some
login and authentication details that help increase security for the
DB2 backend database.
http://www7b.software.ibm.com/dmdd/library/techarticle/0305swart/
0305swart.html
* Building a Web Service in Delphi with a DB2 Backend - by Marco Cantł
To help you get started with Web services this article shows you a
practical SOAP Web service example built with Delphi and a test client
that serves up data from an IBM DB2 Universal Database backend.
http://www7b.software.ibm.com/dmdd/library/techarticle/0212cantu/
0212cantu.html
* Check Efficiency of Oracle Caching with this Report - Donald Burleson
One of the most important areas of Oracle tuning is the management of
the RAM data buffers. Not only is it useful to know the contents of
Oracle data buffers, it's also interesting to watch them move about in
the list. Try this report to check up on your caching effectiveness.
http://builder.com.com/article.jhtml?id=u00320030422brl01.htm
* Ensure data integrity with proper database design - by Susan Harkins
Data is the backbone of application development, so data accuracy is
imperative. Take advantage of referential integrity to protect your
database from invalid data.
http://builder.com.com/article.jhtml?id=u00320030507ssh01.htm
* How to List all files in a directory?
http://www.swissdelphicenter.ch/en/showcode.php?id=1725
* How to export a TStringGrid to a MS Word table?
http://www.swissdelphicenter.ch/en/showcode.php?id=1726
* How to export an Excel Table to a TStringgrid?
http://www.swissdelphicenter.ch/en/showcode.php?id=1728
* How to trap mouse events outside of my application?
http://www.swissdelphicenter.ch/en/showcode.php?id=1729
* How to fill in MS Word Form Fields?
http://www.swissdelphicenter.ch/en/showcode.php?id=1731
* How to read a BlobStream with TADOQuery from an AccessDB?
http://www.swissdelphicenter.ch/en/showcode.php?id=1744
* User list on Windows NT - by Serhiy Perevoznyk
http://www.delphi3000.com/articles/article_3637.asp
* Do you want TWAIN? - by Maarten de Haan
Delphi Scanner Support Framework as a component.
http://www.delphi3000.com/articles/article_3638.asp
* How to convert a Grid's Surfer to a Grid's Arcview - by Camila Pinilla
This code is useful to load a raster Grd file from surfer to ArcView
when you want to interpolate data by using Sufer and then loading the
grid by using Raster Arcview.
http://www.delphi3000.com/articles/article_3639.asp
* Component to calculate a Regression Multiple of set data - C Pinilla
This code was used in a mathematical model to calculate a Regression
Multiple in many points of a computational mesh.
http://www.delphi3000.com/articles/article_3640.asp
* An easy procedure to draw a Vector Field - by Camila Pinilla
Useful if you have to draw a velocity field in a two dimensional mesh.
http://www.delphi3000.com/articles/article_3641.asp
* Choosing a ZIP Library for Delphi - by Mark Steinberg
http://www.delphi3000.com/articles/article_3644.asp
* How to create a dynamic PopUpMenu - by Christoph Otto
Have you ever wanted to Create a PopupMenu at a Position you wanted?
E.g. from a button going up. Here's how using TrackPopupMenuEx.
http://www.delphi3000.com/articles/article_3647.asp
* Secure compression component - by Ronald Douson
A discussion on chosing a component for compressing files with strong
encryption.
http://www.delphi3000.com/articles/article_3648.asp
* Fast Sine and Cosine Calculations - by John Pears
How to really speed up sine and cosine calculations (in degrees).
http://www.delphi3000.com/articles/article_3649.asp
* Understanding pointers: for the amateurs - by Martin Strand
Written for all the beginners out there.
http://www.delphi3000.com/articles/article_3650.asp
* WebSnap III: use of Adapter instead of Html Transparent Tags
- by Eber Irigoyen
The use of adapters to manage content in your web pages. Perhaps
easier to use than html transparent tags?
http://www.delphi3000.com/articles/article_3651.asp
* TreeView control DragDrop Operation helper functions - by Wei Bao
Make Treeview dragdrop operation programming simpler: automatic expand
and collapse, move with children nodes, disable drop to child and
self, auto scroll while the cursor near top or bottom of the control.
http://www.delphi3000.com/articles/article_3652.asp
* INI to XML- by Jim McKeeth
INI was the old way to store settings (outside the registry), now
everything is XML. This routine will convert an INI file into an XML
node of a document.
http://www.delphi3000.com/articles/article_3654.asp
* Moving items in a TListBox using the mouse - by Christophe Geers
A quick example on how to move items in a TListBox using the mouse.
http://www.delphi3000.com/articles/article_3655.asp
* A lot of DLLs with forms, Load dynamically into a PageControl of a
Main-Form - by Manfred Suesens
How to put DLL-Forms as Parent to a MainForm-PageControl-TabSheet.
http://www.delphi3000.com/articles/article_3656.asp
* Internet Explorer Automation - by Teun Spaans
How to integrate IE into your application.
http://www.delphi3000.com/articles/article_3657.asp
* Next or Prev working Day - by Andreas Schmidt
How to calculate the next/prev working day starting from a given date.
http://www.delphi3000.com/articles/article_3658.asp
* Creating a Delphi-Expert (Part I) - by Daniel Wischnewski
The simplest way of creating a Delphi-Expert.
http://www.delphi3000.com/articles/article_3661.asp
* Create "Wait.." panel in design time - Miquel Taule
Quick way to create a panel message.
http://www.delphi3000.com/articles/article_3666.asp
* Reading + Writing System-Wide Environment Variables - Richard Winston
How do you set an environment variable that will apply outside the
process that set the variable or those spawned by it?
http://www.delphi3000.com/articles/article_3669.asp
* Automatically start a service after using /Install or /Uninstall
switch - by Brian Gochnauer
Have you ever wished that the service would also start after
installing the service not just install itself.
http://www.delphi3000.com/articles/article_3671.asp
* Captions in the DBNavigator - by Victor Dalvi
http://www.delphi3000.com/articles/article_3672.asp
* Users Take Open Source Databases for a Spin - by John Cox
A growing number of companies are finding that open source databases
are reaching a state where they can become the latest addition to
their inventory of open source tools.
http://www.networkworld.com/news/2003/0428specialfocus.html
* The Art of Enbugging - by Andy Hunt and Dave Thomas
An article from IEEE Software about reducing the errors in your code
through decoupling techniques.
http://www.ccs.neu.edu/research/demeter/related-work/
pragmatic-programmer/jan_03_enbug.pdf
White Papers
------------
* Cross-platform Development with Borland RAD Tools - by Borland
Traditionally, developers create and maintain separate programs for
Windows and Linux platforms. Borland makes it possible to target both
platforms with a single application. This white paper gives you an
overview of what you can do including multi-tier apps, Web apps, and
integration with Web services.
http://dn.codegear.com/article/29139
* Database Application Development Using Borland Kylix and DB2 UDB v7.2
- by Paul Yip (IBM) and Ramesh Theivendran (Borland)
Kylix is a RAD tool that provides a thin, cross-platform, database-
independent, disconnected data-access model that can be used to
quickly develop database applications for Linux and Windows platforms.
By combining Kylix and DB2, you can write applications once and deploy
them to run natively on both Linux and Windows without code changes.
http://www-3.ibm.com/software/data/pubs/papers/kylix/kylix.pdf
Tutorials
=========
* A Beginner's Guide to Delphi: Chapter 13 - by Zarko Gajic
It's time to learn how to let Delphi help you code faster: start using
code templates, code insight, code completion, shortcut keys, etc.
http://delphi.about.com/od/beginners/a/delphicourse.htm
* Creating Simple User Object Property Dialogs - by Brian Frost
A neat way of creating simple user object property dialogs that avoids
spending ages wiring up controls to object properties.
http://www.thedelphimagazine.com/samples/1614/1614.htm
* Fun With OpenGL - by Dave Jewell
Insights into the OpenGL graphics library and what it can do for your
applications, demonstrating that it's not as difficult as you might
think and it isn't all chocolate teapots, either!
http://www.thedelphimagazine.com/samples/1445/1445.htm
* Relational Databases: Defining Relationships Between Database Tables
- by Susan Harkins
Database normalization is the cornerstone of database theory. Once a
database is normalized, relationships between the data in multiple
tables must be established.
http://builder.com.com/article.jhtml?id=u00320030430ssh01.htm
* How to Program the Lego Mindstorms Robotic Kit - by Geert Barandat
Tutorial of the Lego® Mindstorms® robotics kit and how to program it
with Delphi. Topics include an introduction to ActiveX, PC-RCX
interfacing and building autonomous robots.
http://www.barandat.be/mindstorms/
Other Links
===========
* The Quick Reference Site
The ultimate resource for free IT Quick Reference Cards and e-books.
http://www.digilife.be/quickreferences/indexe.html
* Delphi Informant Magazine Readers Choice Awards 2003
Each year, Delphi Informant Magazine recognizes outstanding products
and vendors in the Delphi add-on market. Please take a moment to
select your favorite Delphi tools. This is your chance to voice your
opinions regarding the tools and products you use in your everyday
development efforts.
http://www.delphizine.com/ballot2003/
News
====
* Borland Janeva
Janeva provides seamless, high-performance interoperability between
the Microsoft .NET Framework applications and the J2EE and CORBA
infrastructures, allowing .NET client- or server-based applications
to access J2EE and CORBA server-side components through the highly
scalable and secure Internet Inter-ORB Protocol (IIOP). Janeva is
tightly integrated with popular development environments for the
Microsoft .NET Framework, including Microsoft Visual Studio for .NET
and Borland C#Builder. Janeva helps accelerate the application
lifecycle at a low total cost of ownership: implementation requires
no expertise with J2EE or CORBA technologies, no change to back-end
systems, and no additional hardware or software investments.
http://www.borland.com/janeva/
Janeva in the news:
- http://www.oreillynet.com/pub/wlg/3167
- http://news.com.com/2100-1012_3-999698.html
- http://zdnet.com.com/2100-1104_2-999698.html
- http://www.businessweek.com/technology/cnet/stories/999698.htm
- http://www.nytimes.com/cnet/CNET_2100-1012_3-999698.html
* Borland C#Builder
The first independent development environment for the .NET Framework.
C#Builder offers a design-driven approach to development that
increases team productivity. C#Builder provides interoperability
between .NET, J2EE and CORBA, so you can integrate different software
systems. It also provides native support for major databases.
http://www.borland.com/csharpbuilder/
* C# Builder box screen shots - by Anders Ohlsson
A first look at the screen shots that are on the product boxes for
Borland's new C# Builder (formerly Project Sidewinder).
http://community.borland.com/article/0,1410,30021,00.html
* Borland Makes .Net 'Life Cycle' Play - by Martin LaMonica
Borland Software will take on software giant Microsoft with a suite
of .Net development tools targeted at companies that program with both
.Net and Java.
http://news.com.com/2100-1012-997684.htm
* Borland: Building Bridges Between Java and .Net - by ZDNet
ZDNet Video interviews Dale Fuller, President and CEO, Borland.
http://zdnet.com.com/1601-2-997475.html
________________________________________________________________________
Vote for the Pascal Newsletter in The Delphi Top 200!
http://top200.jazarsoft.com/delphi/rank.php3?id=latium
________________________________________________________________________
YOU CAN HELP US
We need your help to keep this newsletter going and growing. You can
help by referring the newsletter to your colleagues:
http://www.latiumsoftware.com/en/pascal/delphi-newsletter.php
Or you can help by voting for us in some or all of these rankings to
give more visibility to our web site and thus increase the number of
subscriptions to this newsletter:
http://www.programmingpages.com/?r=latiumsoftwarecomenpascal
http://top100borland.com/in.php?who=20
It's just a few seconds for you that REALLY mean a lot to us.
Don't forget we also need articles for this newsletter and there is a
prize for one of the authors in each issue. All articles will be
considered but we are particularly interested in articles about Kylix
because there is so little available online to help Kylix developers.
Send articles to <eds2008 @ latiumsoftware.com>.
We are also looking for shareware authors who would like to offer their
components or applications as prizes for articles in the newsletter. In
return you will be promoted in this newsletter and the Latium Software
web site. For more information contact Dave <irongut @ vodafone.net>.
________________________________________________________________________
If you haven't received the full source code examples for this issue,
you can get them from http://www.latiumsoftware.com/en/file.php?id=p47
________________________________________________________________________
This newsletter is provided "AS IS" without warranty of any kind. Its
use implies the acceptance of our licensing terms and disclaimer of
warranty you can read at http://www.latiumsoftware.com/en/legal.php
where you will also find a note about legal trademarks. Articles are
copyright of their respective authors and they are reproduced here with
their permission. You can redistribute this newsletter as long as you do
it in full (including copyright notices), without changes, and gratis.
________________________________________________________________________
Main page: http://www.latiumsoftware.com/en/pascal/delphi-newsletter.php
Main page: http://www.latiumsoftware.com/en/pascal/delphi-newsletter.php
Group home page: http://groups.yahoo.com/group/pascal-newsletter/
Subscribe/join: pascal-newsletter-subscribe@yahoogroups.com
Unsubscribe/leave: pascal-newsletter-unsubscribe@yahoogroups.com
Problems with your subscription? eds2008 @ latiumsoftware.com
________________________________________________________________________
Latium Software http://www.latiumsoftware.com/en/index.php
Copyright (c) 2003 by Ernesto De Spirito. All rights reserved.
________________________________________________________________________
|