home

about

license

support

K/Base

Indy
HomeContactsSite Map


Misc Standards

Be extremely careful about dependencies

There are several types of problematic dependencies we have to avoid in Indy. They are:

  1. Win32 VCL GUI Units such as ExtrCtrls, Forms, Graphics, FileCtrl, Dialogs - The only place where there use is permitted is in property and component editors and the IdAntiFreeze unit. This is important because unit directly or indirectly linked will include initialization code which is not always needed or even desired.
  2. CLX Units - They are only permitted in Linux property and component editors and the IdAntiFreeze unit if it is IFDEF'ed. The reason is that CLX is only available in a small handlful of Delphi and C++Builder versions. Even in Delphi/C++Builder 6, CLX usage may not be desired by the developer if they have no plans to use it in their programs.
  3. SyncObjs - We can only use the TCriticalSection class. The reason is that Delphi 4 Standard does not include SyncObjs at all. For Delphi 4 Standard units, we have a dummy unit with TCriticalSection.
  4. Math - This unit does not come with the Standard Editions of Delphi.
  5. Operating system specific units such as Libc, Registry, ShellAPI, Windows are only used in IdGlobals, operating-system-specific units (IdStack..., IdWinsock, IdSSLOpenSSL, and IdSSLOpenSSLHeaders) and operating system specific property editors. The Indy code has to be portable to multiple platforms. We often can write equivalent code for individual operating systems if necessary and IFDEF appropriately in IdGlobal. Any low level socket function has to be used from the Global instance of TIdStack (GStack) and it has to be defined in TIdStack... units.
  6. All the uses clauses are alphabetized so we identify the units a component depends on and maintain them over time.

Use only routines and features which are available in the various development environments we support or provide equivalents

This is extremely important as we expect Indy to be used with various versions of Borland/CodeGear/Embarcadero products. Not all products include specific things and functionality is added with each new version and some functionality is not included in Standard and Professional Editions of C++Builder and Delphi. To achieve this end, we do the following:

  1. Avoid using Frames (those are not available in the 4.0 versions of C++Builder and Delphi).
  2. Restrict ourselves to using TCriticalSection in SyncObjs because that is not included in Borland Delphi 4 Standard Edition. We can use TCriticalSection only because Kudzu had provided a SyncObjs unit for Delphi 4 Standard with his own implementation of TCriticalSection.
  3. We define AnsiSameText, IncludeTrailingBackSlash, FreeAndNil and IFDEF them so they are only compiled if the developer is using Delphi 4. This permits us to use them in our code while avoiding incompatibilities.

Internationalization

Supporting internationalization requires two things. It requires that certain hard-coded strings be placed in resource strings and that Unicode and Multi-Byte Character Support (MCBS) compatible string routines be used.  In Delphi and C++Builder 2009+, the VCL and RTL are all Unicode now, so all string handling must be capable of handing Unicode, and use appropriate Ansi encodings when needed (socket transmissions, file I/O, etc).

In Indy, there are two types of hard-coded strings and it is important to understand the difference as the strings in either category are treated differently. The first type of string is a typical message for human convenience. These include exception Message text such as "No OnExecute specified" or human readable text parts of replies such as "Command not supported". These are defined as constants in the IdResourceStrings unit which has a resourceString directive which causes those strings to placed in resources. The second type of hard-coded string is a protocol-specific string such a protocol command such as "'QUIT" or sometimes a specific reply code as "-ERR ". When using these strings, you add the comment, {Do not Localize} on the same line as the string. This is necessary to accommodate a translation which scans source-code files for hard-coded strings.

MCBS support is done by using routines such as AnsiSameText to compare two strings and IndyPos instead of the standard Pos function. These functions can make accurate usage of MCBS when needed. This is necessary because some languages such as Chinese and Japanese require two or more bytes to accommodate individual characters instead of one byte for English, Romance Languages (French, Spanish, etc) and other European languages. We use IndyPos so that MCBS support can be used if needed or performance is gained if MCBS support is not needed on the end-user's computer. IdGlobals has initialization code which determines if MCBS support is required. Thus using IndyPos transparently handles things

Meeting Specific Borland Requirements

  1. All arguments in procedures/functions must start with A. This distinguishes them as arguments. This is important for many methods that have local variables and for distinguishing from Internal variables used with properties.
  2. Borland requires an easy way for an developer to identify the version of Indy so their support staff can easily obtain information over the phone. We accommodate this need by requiring that all Indy components descend from TIdBaseComponent. There is very little to this but we have a component editor which adds a Right-Click menu item that indicates the Indy version. Selecting this shows the Indy About box.
  3. TBitButtons should not be used in component editors. They have to comply with Microsoft's Guidelines.
  4. All exceptions given to the developer must never be an ancestor class. This is requires so developers can test for specific types of exceptions. By convention, all Indy exceptions are descended from EIdException so they can be distinguished from other developer problems.
  5. All Design-Time code must be separated from the run-time code. This means that all property and component editors, and registration code is placed in a design-time only only package which depends upon a run-time package that contains the core Indy functionality that is provided to the developer's program. The reason this is necessary is Borland has removed some design-time interface units from Borland products and did some restructuring in Delphi 6. The Borland license did not permit developers to include design-time code in their end-user applications. Unfortunately, there were some component authors who were putting the design-time code units in their component unit's uses clause. This caused the design-time code to be linked to an end-user application in an inadvertent violation of Borland's license.
  6. All published properties except for strings and certain objects (TStrings) have to have default values that will match the initial values in properties. This is necessary because default values which are in DFM's would be included in DFM's even if it was the initial value. To accommodate this, we define constants for both the default value definition and in the initial component constructor. Using constants prevents errors such as a default value being defined one way while the initial value in a component is totally different creating bugs.

Following specific standards for unit and component names

To permit consistency within Indy, we prefix all Indy units with the Id. This is important for many vendors to do so users can identify the package the unit is from in case they have to be removed, avoid conflict with other vendors (permitting users to use a product from both Vendor A and vendor B). All Components have the Prefix "TId". All Servers have a suffix of "Server" to avoid confusion particularly as Indy often includes both a server and client implementing a protocol (e.g. TIdEcho and TIdEchoServer which implement the Echo protocol).  In addition, all Server IOHandlers have a name such as TIdServerIOHandlerSSL while the client IO Handlers have names such as TIdSSLIOHandlerSocket.

Another requirement for Linux portability is that all Unit file-names must match the name given in a uses clause including case. This is important because unlike Win32, Linux's file system is case sensitive.

ThreadClass property instead of AThread.Data

When writing server components with descendant thread classes, do not use AThread.Data. AThread.Data should ALWAYS be reserved for use by the application programmer. Instead a descendant thread class should be created and used with the ThreadClass property.

DCR Bitmap Standards

The objective with the Indy icons you see on the component palette are to make the icons distinctive while providing consistancy and accommodating specific needs (some older video cards and color blindness). This is the key to making the Indy bitmaps intuitive is making the component bitmaps follow standardized conventions in a disciplined manner.

There are basically two sets of Indy DCR bitmaps. The first set is high-color (24 bit colors) bitmaps which are the default icons in Indy. The other set of icons is a standard 16 color bitmaps (The ones that ship with Delphi/Kylix).

Let's first address the high-color icons. The icon conventions are basically these. Every protocol has a graphic which we impose on a background image. All client components have a standard yellow background like this:

Basic client bitmap

We then impose a graphic representing the protocol on this background image such as:

TIdEcho bitmap

All server components have a different background image like this:

Basic server bitmap

We then impose a graphic representing the protocol on this background image such as:

TIdEcho bitmap

If you have not noticed, the image on the both component bitmaps have the same foreground image. That foreground image represents the Echo protocol. The original image representing the protocol does not have to be 24x24 pixels in size. We shrink it down with a graphics program such as PaintShop Pro and it will anti-alias graphics.

We do something similar for the IOHandlers and the server IOHandlers.  The IOHandlers for Indy 9.0 clients have a foreground image over a light-purple background such as this:

TIdSSLIOHandlerSocket

while we impose the foreground image on a purple background such as this:

TIdServerIOHandlerOpenSSL

The icons for coders are basically a blue background such as:

Basic coder background

However, there are two types of coders (encoders and decoders). For encoders, we use the blue background with two black lines at the top such as:

and than impose an image for the protocol such as

For the decoders, we use a blue background with two white lines at the bottom such as:

Decoder background

and then impose an image for the protocol such as:

TIdXXDecoder bitmap

Thus, you can easily distinguish between the TIdXXEncoder and TIdXXDecoder even though they have the same basic background color.

For all other components which are neither clients, servers, encoders, and decoders, we use a green background image such as:

Basic miscelanious component background

which we impose a protocol image on such as:

TIdVCard bitmap

For Intercept components, we take this a step further by using an additional convention. For connection intercept components, we impose a protocol image on a background such as:

Basic Connection Intercept bitmap

For server intercept classes, we impose a protocol image on a background such as:

Basic Server Intercept bitmap

Thus, for SSL intercept classes, we have the connection bitmap which is

TIdConnectionInterceptOpenSSL bitmap

and a server intercept which is

TIdServerInterceptOpenSSL bitmap

For the 16 color alternative bitmaps, we do not have as many elaborate conventions because we are under more limitations and the 16 color bitmaps were developed much earlier when Indy was not as elaborate. The basic convention for client and server components is that the server component has a computer in the upper left hand corner. The intercept and IOHandler classes also follow this as the server intercepts also have a computer in the upper left hand corner while connection intercepts do not the computer at all.

Here is the TIdSSLIOHandlerSocket bitmap which does not have the computer on the left-hand corner:

TIdConnectionInterceptOpenSSL bitmap

Here is the TIdServerIOHandlerSSL bitmap which has the computer in the upper left-hand corner:

TIdServerInterceptOpenSSL bitmap

For the coders, we use a different convention. All encoders have a red-stripe at the top such as this:

TIDXXEncoder bitmap

While the decoders have a blue stripe at the bottom such as this:

TIdXXDecoder bitmap


Corporate Sponsors

Atozed







home

about

license

support

K/Base

site map

links

Copyright © 1993 - 2008 Chad Z. Hower (Kudzu) and the Indy Pit Crew.          Website design by RuInternet.ru