Monday, January 14, 2013

Reentrancy of events

Not very long ago, I encountered a weird situation which took lots of time to resolve (yes, call me stupid): a measurement device delivered data to my program at irregular intervals by triggering an event which took the new value, added it to a FIFO structure and redrew the corresponding graph.

This worked nice, however, every now and then parts of the drawing disappeared (I used RChart for displaying the graph). The problem was, of course, that the glitch occurred only infrequently, so debugging was in fact almost impossible (how can you the detect the condition of not drawing parts of a graph?).

In such situations, I did what I call "debugging by meditation" (;-): I slept over it, hoping that my brain finds a solution while being asleep.....

And the solution was simple enough: the event to redraw the graph was called a second time before the previous call had been finished (re-entrant call), clearing parts of the graph. So I simply created the following program structure to block re-entrant calls of the drawing routine:


var
  IsProcessing: boolean; // (private variable of the form)

...
...
...

procedure OnDataTrigger (Sender: TObject; newdat: double);

begin
.... // collect the data (not shown here)

if not Processing then
  begin
  IsProcessing := true;

  .... // display the data

  IsProcessing := false;
  end;
end;
... and the glitches were gone!

A final remark: in my case it was a little bit more complicated, because of additional restrictions of the measurement device. So I used the event to collect the data in an array and called the drawing routine only when enough data were available...

Yes, and the very last remark: do not forget to initialize the "IsProcessing" variable to FALSE.

Thursday, January 10, 2013

Lifetime of Older Delphi Versions

Did you ever wonder how long it takes that most of the users of an older Delphi version switch to the newer one?

Well, this question could be answered simply by looking at the sales figures of Embarcadero; however I doubt that Embarcadero will make the sales figures available to the public. An idea to get some insight to this question would be to exploit the search statistics of Google. These numbers are publicly available (at least the relative numbers) and certainly provide an indication of how many people are (still) working with a particular version of Delphi.

Here are the results of this approach (the data points are weekly averages scaled to a maximum of 100%):

So what I did, was to visit Google Trends, enter the following keywords, and download the data provided by Google. Search keywords: "Delphi 2009", "Delphi 2010", "Delphi XE", "Delphi XE2", and "Delphi XE3".

The results clearly show that the decay of a particular search keyword immediately starts after the launch of a new release. The interest in the old release drops within a few months to half of the initial interest. Only Delphi 2010 needed almost a year to drop to 50% - which may be an indication that the move to XE was judged excessively cautious by the users.

Wednesday, January 9, 2013

Regular Expressions in Delphi

If you ever have a need for regular expressions in your Delphi programs, here's a Web site (not to say the WebSite) which provides all necessary explanations (including code to download):

regular-expressions.info

Delphi/RadStudio XE or higher supports PCRE. PCRE has been developed by Philip Hazel, University of Cambridge, and is a library of regex functions whose syntax and semantics are close to those of the Perl 5 language.

Tuesday, January 8, 2013

When was Easter Sunday in 1953?

Did you ever try to implement a calendar? If so, you already know that this is one of the most intricate tasks a programmer can come upon (;-))). More on the background of that can be found, for example, in Wikipedia.

To make things short, here's the Delphi code of the formula developed by Carl Gauss, including the correction of Lichtenberg (the code snippet is taken from the calendar component of the SDL Component Suite):
procedure CalcEasterSunday (Year: integer; var Day, Mon: integer); (**************************************************** ENTRY: Year ....... year to be calculated EXIT: Day, Mon ... day and month of Easter Sunday ****************************************************) var kx, mk, sk : integer; ax : integer; dam : integer; rda : integer; sz : integer; og,oe : integer; begin kx := Year div 100; mk := 15 + (3*kx + 3) div 4 - (8*kx + 13) div 25; sk := 2 - (3*kx + 3) div 4; ax := Year mod 19; dam := (19*ax + mk) mod 30; rda := (dam + ax div 11) div 29; og := 21 + dam - rda; sz := 7 - (Year + Year div 4 + sk) mod 7; oe := 7 - (og - sz) mod 7; Mon := 3; Day := og + oe; if Day > 31 then begin Mon := 4; Day := Day-31; end; end;
The date is calculated for the Gregorian calendar (which is the most widely used one in the Western hemisphere). As you can easily calculate, Easter Sunday in 1953 was the 5th of April....

Sunday, January 6, 2013

Selected Items of a TTreeView Component

Did you ever try to programmatically select a particular node in a TTreeView component? I thought this should be simple enough. Assuming that the particular node to be selected is given by Items[i] we could simply write the following statement:
TreeView1.Items[i].Selected := true;
Well that works; if we check whether the node is selected we get back a TRUE value. However the selection is not indicated visually, the display of the TTreeView component clears all previous selections, and that's all.... no indication of the new selection.

After hours of tedious experiments I finally found the solution: in order to make the component indicate the selection, you have to set the focus to the component (even if it already had the focus before selecting the node). So the following two-liner will do the job:

TreeView1.Items[i].Selected := true;
TreeView1.SetFocus;