Archive

Archive for November, 2014

Delphi outdated? Says who!

November 28, 2014 20 comments

A couple of days ago I posted a funny meme picture on Google + and Delphi Developer. In the first instance a user commented that “Delphi is outdated”, which seems to be the general consensus for non-delphi programmers around the world.

I mean I did post the image below as double-fun, meaning that yes it’s normally the other way around – so that makes the joke funny, and also funny because the roles are reversed for me (I have always had jobs given to me, I rarely ask for a job). So¬†for me it’s actually true.

I laughed :D

I laughed ūüėÄ

I have seen so many Java guys who just did not make the cut when things got “low-level”, ending up losing their jobs because they were not prepared for¬†the reality of how a computer works.¬†So while the rest of us¬†dived head-first into winAPI services to make our RPC servers and load-balancers go faster, the Java crew silently retracted into their office, pondering why tomcat was unable to catch up with Delphi; Avoiding eye contact and stopping all the foolish¬†“java is best” talk. Which was funny because the same gang of Java coders were initially¬†a loud and condescending group of smocks, giggling¬†in amusement when they heard the word “Delphi”. Only to be out-smarted, out-performed and ultimately just¬†OUT.

When I showed the boss that creating a service took less than 5 minutes to build, and that adding a server to the win32 service was a matter of dropping a component on the data module,¬†he just shook his head and said “Had I met you when we started this company, I would never have wasted my money on Java. I would have hired you full-time and done this in Delphi

Some two years later and the company went bankrupt. The Java crew had eaten up years worth of unexpected salaries and built a product which was unable to cope with reality. Even though I fixed the damn thing it was too late. They ran out of road and went belly up. That would not have happened had I been allowed to do this in Delphi from day one.

Delphi not cool enough?

So.. did I miss something? When exactly did the world at large decide that Delphi is not allowed to be cool anymore? So a scripting toy like python, which could easily be written in Delphi — that’s cool. But a full on OOP compiler toolchain which produces native code for all modern platforms, that’s not cool. Where exactly is the logic in that?

Having googled around for a bit, trying to find some substance to this claim, all I find are rumors. Actually not even rumors, but more along the lines of childish thrash talk behind someones back or “name dropping” to fit in with the popular group. Yet when you try to examine where this aversion for Delphi is coming from -or if there exists¬†any solid evidence behind this puzzling attitude¬†at all,¬†you find nothing.

Is object pascal about to go the way of the dinosaurs? And if so, who sat down and decided that a language en-par with the most popular and widely used language in the world, namely C/C++, suddenly has no place in the market?

Object pascal as a language compiles for nearly 20 platforms, including Nintendo and Ouya. The majority of these platforms are delivered through FreePascal, which is compatible with Delphi on almost all accounts.

With a market share in the hundreds of thousands (remember, there are only 18 million developers in the world, divided amongst all programming languages) Delphi still out-ranks python, pearl, ruby and all dialects of basic combined. Not to mention objective C which saw a sudden rise due to the fact that Apple forced people to learn that cursed dialect. And if you want an old outdated language, then Objective C is the mother-load!

Let’s face it: no-one would use Objective-C of their own free will had it not been for Apple’s nazi regime for iOS back in the day.¬†It is the bastard love child between Modula II messaging and C, with roots so far back in time that Cobol was pushing pimples and smiling¬†over hair appearing on its genitals. It is an atrocity cooked up in the labs at neXT and pushed in the back-door by Steve Jobs.

Statistical faggottery

And then there is TIOBE, which every year runs a statistical analysis on language popularity. And it does this by searching for keywords in source-code committed to SVN, Github and various websites around the internet.

The problem? Well right from the start TIOBE decided that our language needed special treatment and rules, so instead of using keywords that would reflect reality, like “delphi”, “freepascal”, “lazarus”,”oxygene pascal”, “smart pascal” and “object pascal” and then combining this¬†into a score which reasonably represents reality ¬†— TIOBE in its infinite wisdom decided that the word “pascal” should cover it.

TIOBE represents "selective" facts, not real facts

TIOBE represents “selective” facts, not real facts

This means that for the past decade TIOBE has reported only a fraction of the actual use and activity-level of our language, giving potential users a completely wrong impression.

Lately they have decided to add “Delphi/Object pascal” to their list (due to heavy complaints for years), but only as a separate language¬†to “pascal”, which once again misrepresents the Delphi, Smart Mobile Studio, Remobjects Oxygene and Freepascal community. We all know that these different takes on object pascal represents the same user-base, with only slight alterations in dialect and features. Smart Pascal for instance have adopted several features from Remobjects Oxygene, as well as C#, but it’s still 100% object pascal. And our customers are ultimately object pascal programmers with a background in Delphi or Freepascal.

Completely wrong. What about freepascal, TMT pascal and Smart Pascal? These represents the same language and should be combined into a single score

As you can see the word “Delphi” and “Object Pascal” is on the rise. But even here the statistics is only catching a fraction of the real activity online, because freepascal, oxygene pascal and smart pascal is not even taken account for

Now what kind of impression do you think this is sending to kids who want to learn programming? Object Pascal was architected to be taught in schools, with strict attention to types and syntax Рin order to make sure students learn the ropes from the ground up; producing better developers and better quality code.

Even if you learn object pascal at school and decide to work with C# later, you will still have benefitted greatly from learning how to program through object pascal. You will quite frankly have a better understanding of how .net works behind the scenes, and thus be a better dot net programmer as a result.

Sadly, the impression beginners are getting from TIOBE is that Delphi and Freepascal is dead and have been steadily declining for the past decade. Which is simply not true. Hundreds of thousands of kids are learning object pascal at school in Russia for instance. We are also seeing a proverbial explosion of use in South-America, the balkans and Asia. Which means that in a couple of years time there will be a wave of developers who build, sell and provide object pascal software and services.

The fall from grace

While I can only speculate on the rumor mill,¬†I do have¬†a firm grasp on the “fall from grace” subject¬†and know precisely how the¬†impression of Delphi being outdated struck root in the IT community. And it goes all the way back to the last epoch¬†of Borland, the former owner and publisher of Delphi.

To make a long story short, Delphi and C++ builder was the only real threat to Microsoft back in those days, and unlike the rest Borland refused to bend its knee. The end result, as we all know, was that Bill Gates personally head-hunted Anders Hejlsberg (and I mean personally) which is the author and brain behind both Delphi and dot net. Back then there was little doubt that Borland was under attack, and considering the amount of financial force Microsoft represents –¬†the war would be lost. Everyone knew that Borland would lose and everyone was scared for the future of the language, their jobs and income.

Borland DevStudio: C++, Java and Delphi in one massive catastrophe

Borland DevStudio: C++, Java and Delphi in one massive catastrophe

Either way, faced with the option to die or convert to Microsoft,¬†Anders did what most sensible people would do, and accepted the substancial (read: millions) parachute package from Microsoft; And he now works as *the* chief software¬†architect at that very company. He is not just the author of Turbo Pascal and Delphi but also the guy behind the dot net framework, which incidentally was a Borland project – cleverly called “portable Delphi” before that.

Just stop and think about that for a moment. Every single argument you have for C#, Visual Basic dot net and the whole dot net eco-system comes from Delphi and represents the next step in Delphi evolution. What happened instead is that Microsoft killed Borland, dismantled it and in classical warlord style – brought back the most learned to work for them.

So people who say Delphi is outdated in comparison with dot net should watch it, because there is a lot of Delphi in the dot net framework and CIL architecture. That’s because it is Delphi, taken and released under the Microsoft banner.¬†The initial specs for portable Delphi included pointers from what I remember of the article on it, but I guess that went out the window in favour or byte-code uniformity.

And the rest is history. Borland was dismantled and forced to give up its software development division, which they sold to Embarcadero. A company who inherited the monumental task of (more or less) re-building Delphi from scratch, along with a very angry user base of hundreds of thousands of Delphi and C++ Builder developers.

“I have always held the human race in high regard, until i saw a whole generation of kids ruined by java and hanna-montana.. now i genuinely believe that only a small fraction of the human race should be allowed to reproduce”

But Borland was no innocent little goddie-two-shoe¬†company without blemish. They made some spectacular¬†bloopers before Microsoft bitch-slapped them out of existance, like Delphi for Linux (Kylix) which turned out to be¬†a financial disaster for both¬†Borland and it’s technology partners. A disaster which ultimately hurt component writers¬†more than it did Borland. Because while Borland had the finances to recover from the loss, component authors did not. They all lost money, many went bankrupt, and larger component providers like Developer Express simply decided it was enough, and stopped developing new components for Delphi after that. They still maintain their older products, but as far as new products are concerned – they are out for good.

Kylix, Delphi for Linux, years ahead of it's time - but ultimately a failure

Kylix, Delphi for Linux, a decade ahead of its time Рbut ultimately a failure

Next there were the Delphi for dot net releases (mostly 2000 labeled variations of the product, like 2004, 2005 and 2006). These editions of Delphi were slow, sluggish and in my view – a complete waste of time. Invented only for spite in trying to out-do Microsoft at what they do best. A foolish endeavor which only served to enrage¬†the user-base¬†accustomed¬†to Ander’s fast native execution philosophy even further.

Introducing the dot net framework into the product rendered it close to useless and was seen by us developers as a “capitulation to lower-standards”.

After the sale to Embarcadero, the product still lingered without any real updates while EMB built up competence in their development department, not to mention getting rid of the dot net rubbish which had turned a once lean, mean and ultra fast language into a fat, bloated ex-quarterback living on memories.

The change

Embarcadero have in my view held their promises. Delphi as it exists now is once again a fast, lean and mean compiler toolkit – with all the bells and whistles you would expect from a top of the line programming suite.

Personally I feel Embarcadero is doing a monumental disservice to themselves and their user base¬†in its continuing¬†promotion of Delphi as a¬†RAD (rapid application development) system, because RAD in our day and age means “shallow and superficial” rather than “well thought out and robust” (like RAD once used to mean).

Rad Studio XE6/7 represents 20 years of C++ and Object Pascal exellence

Rad Studio XE6/7 represents 20 years of C++ and Object Pascal exellence

Either way, modern language features such as generics was added years ago, as was support for iOS, Android and OS X compiler targets. Not to mention a spanking new RTL called Firemonkey which makes use of the GPU to render modern UI’s everywhere.

I must admit that I have a love/hate relationship with Delphi. Roughly 4 years ago the frustration I felt culminated in me creating Smart Mobile Studio, quite frankly because I found that to be a faster and more direct path to building mobile applications. Smart Mobile Studio is doing very well and the Smart Pascal dialect makes JavaScript a dream to work with.

But just like dot net is written in C/C++, Smart Mobile Studio is written in Delphi and is 100% dependent on the native capabilities Delphi provides. This may change quite soon as a re-write to freepascal is imminent, but Delphi is still the product we use to create our alternative path.

I wont cite the complete list of changes to Delphi as a product, because the list would fill a medium size book. But for anyone to say that Delphi is “outdated and old” would be to utterly surrender all faculties of reason. If old means “more years than dot net” then at least recognize that old in this case means wisdom and experience, not death and disability.

C++ Builder, Delphi's sister product, lean mean and hungry

C++ Builder, Delphi’s sister product, lean mean and hungry

There can be little doubt that Delphi has lost friends over the years, and I personally believe this is the source of the “Delphi is outdated and old” rumors. But heck –if you want an old language then C++ is the oldest and most cryptic of them all (!) So how can people applaud C/C++ and at the same time say that object pascal is outdated? C/C++ outdates object pascal by nearly a decade (!) Yet object pascal was created exactly to replace C/C++. Object Pascal was also engineered to be easy to learn – that’s why Turbo Pascal and Delphi has been used in universities, to be a safe path for people to learn OOP programming.

So for those of you that prefer or like to believe that Delphi is outdated, that is simply your personal pipe-dream. It is not based on fact and has no roots in reality. You are in fact suffering from a mild case of insanity.

Delphi is growing steadily and the language is just as excellent today as it was 15 years ago. Thousands of small and large computer programs¬†are made with Delphi every month. Many of them quite famous. Here is a list of those I know about if you don’t believe me.

Turning the tide

A lot of Delphi developers have grown lazy. I still find repositories online that needs a facelift and perhaps some updated content. In most cases the repositories are very much alive, updated less than a 12 months ago — but the author’s doesn’t bother to update the text.

This is sending a wrong signal to people of less intelligence. Stupid people believe that unless something was updated yesterday, then the code must be unusable. The idea of timeless code, like a cipher routine which follows standards and principles, is sadly lost to them. I have code I wrote 12 years ago that works perfectly fine to this day. There is nothing you can do to make it more modern, because what it does and how it does it is efficient, portable and requires little maintenance.

Do your part, ruin  java setup every week!

Do your part, step on java coder every week!

But fact is fact: People are reacting to what they label as “old code” lingering around the internet, and they are to some extent right. So we need to clean it up (!)

If you have a repo of code somewhere that has remained idle for a couple of years, why not update it a bit? Or at least do a checkout/in to make sure the dates reflect reality.

And if you have an old Delphi website that you no longer maintain — either give it to someone who will maintain it, or¬†spend an hour giving it a run over.

The same goes for websites that promotes Delphi. Torry’s is more than overdue for a face-lift, as is Delphitools.

Do your part —¬†show these adolescent imbeciles just what they are missing¬†out on! I feel so sorry for the past two generations of kids, growing up with Java and JavaScript¬†and believing they have the right to call themselves programmers. Java is a toy. Bytecode compilers is what we do when we are bored and want to play.

Object Pascal is not just Delphi

Another factor that seems to be to complex for Java, dot net and script programmers (if we can use that title in this context) is that Delphi is a product. Delphi is not object pascal, but rather just one compiler toolchain of many which uses the object pascal language.

So when people are touting that Delphi is outdated what exactly are they referring to?

Freepascal running on Ubuntu

Freepascal running on Ubuntu

For instance, freepascal and Lazarus which are both free and open-source initiatives can be downloaded and installed on every Linux, Unix and whatever distribution known to mankind. You can target Nintendo, Playstation, Aros, Linux, Spark Solaris — heck, even the Amiga and the Raspberry PI for that matter.

And this is what people don’t seem to understand: try installing mono on the Raspberry PI, just try it. If you are lucky it will have downloaded and installed over the course of a week, and which point it will take roughly 60 minutes just to start the IDE. And this is if you can even download it and use it at all (!)

What people don’t seem to get is that programming on devices with so little CPU and memory requires a language that can scale well. C/C++ scales down just fine, as does Object Pascal. But more importantly: the code you generate for these devices must be compact and as fast as humanly possible.

If you compile your Java and mono code to a single binary (read: machine code) then that should run fine as well, but they wont be fast! Java pushes so much crap up the stack that it’s¬†practically¬†raping the hardware — and while mono is much better than Java, the amount of code it produces is sometimes ridicules.

Freepascal on the other hand is a Ninja on these systems. Blazing fast and with full access to 20 years of pascal evolution, you have thousands of libraries available out of the box. No other language except C/C++ can compare with this.

Smart Mobile Studio

And then there is the browser and nodeJS. You would think that JavaScript and object pascal were mortal enemies, and that under no circumstance could object pascal give JavaScript a competing edge. Well you could not be more wrong.

Smart Pascal gives you full VMT inheritance in the browser. That’s right. The compiler sculpts a VMT (virtual method table) allowing you to enjoy classical OOP where no such concept exists. You also get support for interfaces, sets (not just enums), virtual and abstract methods and classes — the works!

Smart Pascal is especially suited for HTML5/JS

Smart Pascal is especially suited for HTML5/JS

And just like its native origin, Smart Pascal compiles into lean, mean and tight JavaScript. Compatible and easy to use from other JavaScript libraries – and also capable of using raw JavaScript libraries from the pascal side.

The result is that you can finish an application which would otherwise take 3 weeks to make — in just 3 days! With top quality code generated and full support for nodeJS and even hardware controllers.

Again — object pascal is where this is happening. Typescript came afterwards and it has no where near the amount of features Smart Pascal is offering.

Typical misconceptions

Below are some typical comments written by people who believe that C# and Java is so much better than Delphi and C/C++, and my reply.

“In what world is it modern to handle memory directly” (read: pointers and freeing object).

In the world where computers have memory. What reality are you living in?

“Delphi is ancient, the memory manager itself is ridicules”

Really? You obviously have worked very little on embedded systems. Being able to write your own memory manager if you so desire has nothing to do with age, but rather with flexibility and choice. When writing code for embedded systems, you dont have the luxury of retaining objects or using reference counting. Try installing mono on the Raspberry PI. Perhaps it will boot up sometime next week, if it’s able to compile at all.

“Pointers are dangerous and old-fashioned!”

A knife is dangerous in the hands of a child, but if you use it with respect and write proper code, then pointers are safe. CPU and memory is the reality of how a computer words, and just because you have been fooled into thinking an abstraction layer is reality Рthat is your loss. You are confusing the map with the landscape.

Have you ever written code that runs on a Nintendo DS? I have. Did you know that the screen on these devices is a file on the CF memory card? So to write a pixel you actually write a 16 bit word to a file. Try doing that without memory mapping. I feel sorry for your lack of insight.

“Having to free objects manually is a waste of time, face it, object pascal is ancient”

You seem to forget that dot net and java are written in C/C++. And if you have a look at the code written by Microsoft themselves you will see pointer types used in roughly 90% of their C# code. You should ask yourself why Microsoft is telling everyone that pointers are unsafe and should be avoided, yet they themselves use it extensively. Besides, implementing IDisposable in your object pascal objects takes 3 seconds. So your argument is childish and infantile.

“Having no support of interfaces in TObject is ridicules!”

Then you don’t understand interfaces, reference counting or how it came into being. Using interfaces is not a must, it’s an option. A programming technique which¬†was introduced as a standard way of de-coupling access from entrypoint. There is no reason for¬†adding the overhead of reference counting and¬†garbage collection in object types which¬†don’t benefit from them. And if you find it hard to write the 8+ lines of code which gives you IDisposable in your codebase, then you are either mentally challenged or lazy.

Final words

So the next time you feel the urge to say that Delphi is outdated, or that object pascal is old and has no place anymore — at least try it before you jump on the teenage bandwagon and thrash talk something you know nothing about.

Object pascal has stood the test of time, just like it’s sister product C++. It was here before Ruby and whatnot came into being – and it will be here long after these hyped up products are dead and buried.

What is old anyway? How can we say that something is outdated?

Here is what I would define as out-dated:

  • When the code no-longer match the hardware and OS (read: 16 bit code)
  • When datatypes no longer exist except for legacy support
  • When you can no longer buy hardware (read: Amiga computers are out-dated, Commodore 64 is outdated)
  • When code no longer runs without special attention (read: execute as windows 95, XP etc.. )
  • Code that does not take height for widestring

So there is a lot of outdated code out there, loads of it, but the majority of Delphi code online runs just fine. But yes, there is a lot of code that needs an update in the world of Delphi — but that goes for C++ and Java as well. Loads of java code written back in the day which no longer compiles, especially code written for early swing widget sets.

As for C#, I love it! So I’m not against C# or Visual Basic at all. I love to play around with these languages, and I have written a lot of C# code for serious applications (and will work extensively with C# for the foreseeable future). But I never lose sight of the fact that without C++ running the show behind the scene, C# would be useless.

Loading a DLL from memory

November 25, 2014 2 comments

Once in a while you come across a unit which is just fantastic, like how to load a dll from memory (read: loaded from a stream, a resource or even re-assembled from a text dump). I remember vividly looking for a way to load a DLL from memory ages ago, preferably a DLL i had stored in my application as a form-resource.

While I cannot for the life of me remember why this was so important at the time (probably wanted to embed some some third party library and register it in real-time), the question still remains: can a DLL be loaded from memory? And the answer apparently .. is yes.

Here is the code. Sadly I have no idea who wrote it, but I cannot take credit for this one.

Due to the messy output and overdone end else endif use my money is on a verbatim re-write of a C/C++ example somewhere.

Well, here it is!

unit uDllfromMem;

interface

uses sysutils, windows;

const
IMAGE_REL_BASED_HIGHLOW = 3;
IMAGE_ORDINAL_FLAG32 = DWORD($80000000);

type
PImageBaseRelocation = ^TImageBaseRelocation;

_IMAGE_BASE_RELOCATION = packed record
    VirtualAddress: DWORD;
    SizeOfBlock: DWORD;
end;

{$EXTERNALSYM _IMAGE_BASE_RELOCATION}
  TImageBaseRelocation = _IMAGE_BASE_RELOCATION;
  IMAGE_BASE_RELOCATION = _IMAGE_BASE_RELOCATION;
{$EXTERNALSYM IMAGE_BASE_RELOCATION}

PImageImportDescriptor = ^TImageImportDescriptor;
TImageImportDescriptor = packed record
  OriginalFirstThunk: dword;
  TimeDateStamp: dword;
  ForwarderChain: dword;
  Name: dword;
  FirstThunk: dword;
end;

PImageImportByName = ^TImageImportByName;
TImageImportByName = packed record
  Hint : WORD;
  Name : array[0..255] of Char;
end;

PImageThunkData = ^TImageThunkData;
TImageThunkData = packed record
  case integer of
  0 : (ForwarderString: PBYTE);
  1 : (FunctionPtr    : PDWORD);
  2 : (Ordinal        : DWORD);
  3 : (AddressOfData  : PImageImportByName);
end;

TDllEntryProc = function (hinstdll: THandle;
  fdwReason: DWORD;
  lpReserved: Pointer): BOOL; stdcall;

function memLoadLibrary(FileBase : Pointer) : Pointer;
function memGetProcAddress(Physbase : Pointer; NameOfFunction : String) : Pointer;
function memFreeLibrary(physbase : Pointer) : Boolean;

var
DllentryProc : TDLLEntryProc;

implementation

function GetSectionProtection(ImageScn: cardinal): cardinal;
begin
  Result := 0;
  if (ImageScn and IMAGE_SCN_MEM_NOT_CACHED) <> 0 then
  Result := Result or PAGE_NOCACHE;

  if (ImageScn and IMAGE_SCN_MEM_EXECUTE) <> 0 then
  begin
    if (ImageScn and IMAGE_SCN_MEM_READ)<> 0 then
    begin
      if (ImageScn and IMAGE_SCN_MEM_WRITE)<> 0 then
      Result := Result or PAGE_EXECUTE_READWRITE else
      Result := Result or PAGE_EXECUTE_READ
    end else
    if (ImageScn and IMAGE_SCN_MEM_WRITE) <> 0 then
    Result := Result or PAGE_EXECUTE_WRITECOPY else
    Result := Result or PAGE_EXECUTE;
  end else
  if (ImageScn and IMAGE_SCN_MEM_READ)<> 0 then
  begin
    if (ImageScn and IMAGE_SCN_MEM_WRITE) <> 0 then
    Result := Result or PAGE_READWRITE else
    Result := Result or PAGE_READONLY
  end else
  if (ImageScn and IMAGE_SCN_MEM_WRITE) <> 0 then
  Result := Result or PAGE_WRITECOPY else
  Result := Result or PAGE_NOACCESS;
end;

function memLoadLibrary(FileBase : Pointer) : Pointer;
var
pfilentheader : PIMAGENTHEADERS;
pfiledosheader: PIMAGEDOSHEADER;
pphysntheader : PIMAGENTHEADERS;
pphysdosheader: PIMAGEDOSHEADER;
physbase  : Pointer;
pphyssectionheader : PIMAGESECTIONHEADER;
i : Integer;
importsDir : PImageDataDirectory;
importsBase: Pointer;
importDesc :  PImageImportDescriptor;
importThunk: PImageThunkData;
dll_handle : Cardinal;
importbyname : pimageimportbyname;
relocbase : Pointer;
relocdata : PIMAGeBaseRElocation;
relocitem : PWORD;
reloccount : Integer;
dllproc : TDLLEntryProc;
begin
result := 0;

pfiledosheader := filebase;
pfilentheader  := Pointer(Cardinal(filebase) + pfiledosheader^._lfanew);

physbase := VirtualAlloc(Pointer(pfilentheader^.OptionalHeader.ImageBase),pfilentheader^.OptionalHeader.SizeOfImage,MEM_RESERVE,PAGE_READWRITE);
if Cardinal(physbase) = 0 Then begin
physbase := VirtualAlloc(0,pfilentheader^.OptionalHeader.SizeOfImage,MEM_RESERVE Or Mem_COMMIT,PAGE_READWRITE);
end;

CopyMemory(physbase,filebase,pfilentheader^.OptionalHeader.SizeOfHeaders);

pphysdosheader := physbase;
pphysntheader := Pointer(Cardinal(physbase) + pphysdosheader^._lfanew);
pphysntheader^.OptionalHeader.ImageBase := Cardinal(physbase);

pphyssectionheader := Pointer(Cardinal(pphysntheader) + SizeOf(TIMAGENTHEADERS));
for i := 0 To (pphysntheader^.FileHeader.NumberOfSections - 1) do begin
  if pphyssectionheader^.SizeOfRawData = 0 Then begin
    //keine raw data
    ZeroMemory(Pointer(Cardinal(physbase) + pphyssectionheader^.VirtualAddress),pphyssectionheader^.Misc.VirtualSize);
  end else begin
    //raw data vorhanden
    CopyMemory(Pointer(Cardinal(physbase) + pphyssectionheader^.VirtualAddress),Pointer(Cardinal(filebase) + pphyssectionheader^.PointerToRawData),pphyssectionheader^.SizeOfRawData);
  end;
  pphyssectionheader^.Misc.PhysicalAddress :=  Cardinal(physbase) + pphyssectionheader^.VirtualAddress;

  //next one please
  pphyssectionheader :=  Pointer(Cardinal(pphyssectionheader) + SizeOf(TIMAGESECTIONHEADER));
end;

importsBase := Pointer(Cardinal(physbase) + pphysntheader^.OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT].VirtualAddress);
importDesc := importsBase;
while (importDesc.Name) <> 0 Do begin
  dll_handle := LoadLibrary(pchar(Cardinal(physbase) + importdesc.Name));
  importDesc.ForwarderChain := dll_handle;
  importThunk := Pointer(Cardinal(physbase) +  importDesc.FirstThunk);
  while importThunk.Ordinal <> 0 Do begin
    importbyname := Pointer(Cardinal(physbase) + importThunk.Ordinal);
    //Sp√ɬ§ter noch √ɬľberpr√ɬľfen ob OriginalFirstThunk = 0
    if (importThunk.Ordinal and IMAGE_ORDINAL_FLAG32) <> 0 Then
    begin //ordinal
      importThunk.FunctionPtr := GetProcaddress(dll_handle,pchar(importThunk.Ordinal and $ffff))
    end else begin //normal
      importThunk.FunctionPtr := GetProcAddress(dll_handle,importByname.name);
    end;
  //next one, please
  importThunk := Pointer(Cardinal(importThunk) + SizeOf(TIMAGETHUNKDATA));
  end;
//next one, please
importDesc := Pointer(Cardinal(importDesc) + sizeOf(TIMAGEIMPORTDESCRIPTOR));
end;

relocbase := Pointer(Cardinal(physbase)
  + pphysntheader.OptionalHeader.DataDirectory
  [IMAGE_DIRECTORY_ENTRY_BASERELOC].VirtualAddress);
relocData := RElocbase;

while (Cardinal(relocdata) -  Cardinal(relocbase)) < pphysntheader.OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_BASERELOC].Size do begin
  reloccount := trunc((relocdata.SizeOfBlock - 8) / 2);
  relocitem  := Pointer(Cardinal(relocdata) + 8);
  For i := 0 To (reloccount - 1) do
  begin
    if (relocitem^ shr 12) = IMAGE_REL_BASED_HIGHLOW Then begin
      Inc(PDWord(Cardinal(physbase) + relocdata.VirtualAddress
      + (relocitem^ and $FFF))^,(Cardinal(physbase) - pfilentheader.OptionalHeader.ImageBase));
    end;
    relocitem := Pointer(Cardinal(relocitem) + SizeOf(WORD));
  end;

  //next one please
  relocdata := Pointer(Cardinal(relocdata) + relocdata.SizeOfBlock);
end;

pphyssectionheader := Pointer(Cardinal(pphysntheader) + SizeOf(TIMAGENTHEADERS));
For i := 0 To (pphysntheader^.FileHeader.NumberOfSections - 1) do
begin
  VirtualProtect(Pointer(Cardinal(physbase)
    + pphyssectionheader^.VirtualAddress),pphyssectionheader^.Misc.VirtualSize,
  GetSectionProtection(pphyssectionheader.Characteristics),nil);
  pphyssectionheader := Pointer(Cardinal(pphyssectionheader)
    + SizeOf(TIMAGESECTIONHEADER));
end;

dllEntryproc := Pointer(Cardinal(physbase) + pphysntheader.OptionalHeader.AddressOfEntryPoint);
dllEntryproc(cardinal(physbase),DLL_PROCESS_ATTACH,nil);

result := physbase;
end;

function memGetProcAddress(Physbase : Pointer; NameOfFunction : String) : Pointer;
var
  pdosheader: PIMAGEDOSHEADER;
  pntheader : PIMAGENTHEADERS;
  pexportdir: PImageExportDirectory;
  i : Integer;
  pexportname : PDWORD;
  pexportordinal : PWORD;
  pexportFunction : PDWORD;
begin
  result := 0;
  pdosheader := physbase;
  pntheader := Pointer(Cardinal(physbase) + pdosheader._lfanew);

  pexportdir := Pointer(Cardinal(physbase)
    + pntheader.OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT].VirtualAddress);

  if pexportdir.NumberOfFunctions Or pexportdir.NumberOfNames  >0 then
  Begin
    pexportName    := Pointer(Cardinal(physbase) + Cardinal(pexportDir.AddressOfNames));
    pexportordinal := Pointer(Cardinal(physbase) + Cardinal(pexportDir.AddressOfNameOrdinals));
    pexportFunction:= Pointer(Cardinal(physbase) + Cardinal(pexportDir.AddressOfFunctions));

    For i := 0 To (pexportdir.NumberOfNames - 1) do
    begin
      if StrComp(pchar(Pointer(Cardinal(physbase) + pexportName^)),
      pchar(NameOfFunction)) = 0 Then
      begin
        result := pchar(Pointer(Cardinal(physbase) + pexportFunction^));
        break;
      end;

      //next one, please
      Inc(pexportFunction);
      Inc(pexportName);
      Inc(pexportOrdinal);
    end;
  end;
end;

function memFreeLibrary(physbase : Pointer) : Boolean;
begin
  try
    result := true;
    dllEntryProc(Cardinal(physbase),DLL_PROCESS_DETACH,0);
    VirtualFree(physbase,0,MEM_RELEASE);
  except
    result := false;
  end;
end;

end.

Numbers to human words

November 19, 2014 Leave a comment

This is a great little function for converting numbers (10, 191, 20000 etc) into human readable words. An absolute must have for any program which counts something. A good way to avoid the typical “you have 1 files remaining” display text ūüôā

Params and their meaning:

NTW(ChkER: Boolean; ER: String; D: Double): String;
ChkER = True for  Using Currency Format, False for math format
ER = Currency Name eg: 'Dollar'
D = Numeric Value

Typical use:


procedure TForm1.Button1Click(Sender
: TObject); //Currency Format
begin
     Memo1.Clear;
     Memo1.Text := NTW(True, 'Dollar', 185012,345020); 
     //Result : one hundred and eighty five thousand, and twelve dollar and thirty four cents
end;

procedure TForm1.Button2Click(Sender: TObject); //Math Format
begin
     Memo1.Clear;
     Memo1.Text := NTW(False, '', 185012,345020); 
     //Result : one hundred and eighty five thousand, and twelve point three four five zero two
end;

And last but not least, the actual code:

function NTW(ChkER: boolean; ER: string; D: double): string;
const
  Ones: array[0..9] of string = ('Zero', 'One', 'Two', 'Three', 'Four', 'Five', 'Six', 'Seven', 'Eight', 'Nine');
  Teens: array[10..19] of string = ('Ten', 'Eleven', 'Twelve', 'Thirteen', 'Fourteen', 'Fifteen', 'Sixteen', 'Seventeen', 'Eighteen', 'Nineteen');
  Tens: array[2..9] of string = ('Twenty', 'Thirty', 'Forty', 'Fifty', 'Sixty', 'Seventy', 'Eighty', 'Ninety');
  Suffix: array[0..5] of string = ('Hundred', 'Thousand', 'Million', 'Billion', 'Trillion', 'Quadrillion');
var RStr, sDec, sFrac: string;
    vFrac: double;
    I, vDec : integer;
    TruncTens, TruncHund, TruncThou, TruncMio, TruncBio, TruncTril, iD: Int64;
    ReadFrac: boolean;
    function fTensENG(xD: integer): string;
    var BTStr: string;
    begin
       if (xD >= 0) and (xD <= 9) then BTStr := Ones[xD] else
       if (xD >= 10) and (xD <= 19) then BTStr := Teens[xD] else
       if (xD >= 20) and (xD <= 99) then
       begin
          if (StrToInt(RightStr(IntToStr(xD), 1)) = 0) then
             BTStr := Tens[StrToInt(LeftStr(IntToStr(xD), 1))]
          else
             BTStr := Tens[StrToInt(LeftStr(IntToStr(xD), 1))] + ' ' +
                      Ones[StrToInt(RightStr(IntToStr(xD), 1))]
       end;
       Result := BTStr;
    end;
    function fHundENG(xD: integer): string;
    var BTStr: string;
    begin
       BTStr := Ones[StrToInt(LeftStr(IntToStr(xD), 1))] + ' ' + Suffix[0];
       TruncTens := StrToInt(RightStr(IntToStr(xD), 2));
       if (TruncTens <> 0) then
          BTStr := BTStr + ' and ' + fTensENG(TruncTens);
       Result := BTStr;
    end;
    function fThouENG(xD: Integer): string;
    var BTStr: string;
    begin
       if (xD >= 1000) and (xD <= 9999) then
       begin
          BTStr := Ones[StrToInt(LeftStr(IntToStr(xD), 1))] + ' ' + Suffix[1];
          TruncHund := StrToInt(RightStr(IntToStr(xD), 3));
          TruncTens := StrToInt(RightStr(IntToStr(xD), 2));
          if (TruncHund <> 0) and (TruncTens = 0) then
             BTStr := BTStr + 'and ' + Ones[StrToInt(LeftStr(IntToStr(xD), 1))] + ' ' + Suffix[0]
          else
          if (TruncHund <> 0) and (TruncTens <> 0) then
             BTStr := BTStr + ', ' + fHundENG(TruncHund);
       end
       else
       if (Trunc(xD) >= 10000) and (Trunc(xD) <= 19999) then
       begin
          BTStr := Teens[StrToInt(LeftStr(IntToStr(xD), 2))] + ' ' + Suffix[1];
          TruncHund := StrToInt(RightStr(IntToStr(xD), 3));
          TruncTens := StrToInt(RightStr(IntToStr(xD), 2));
          if (TruncHund <> 0) and (TruncTens = 0) then
             BTStr := BTStr + ' and ' + Ones[StrToInt(LeftStr(IntToStr(TruncHund), 1))] + ' ' + Suffix[0]
          else
          if (TruncHund <> 0) and (TruncTens <> 0) then
             BTStr := BTStr + ', ' + fHundENG(TruncHund);
       end
       else
       if (Trunc(xD) >= 20000) and (Trunc(xD) <= 99999) then
       begin
          if (StrToInt(MidStr(IntToStr(xD), 2, 1)) = 0) then
             BTStr := Tens[StrToInt(LeftStr(IntToStr(xD), 1))] + ' ' + Suffix[1]
          else
             BTStr := Tens[StrToInt(LeftStr(IntToStr(xD), 1))] + ' ' +
                      Ones[StrToInt(MidStr(IntToStr(xD), 2, 1))] + ' ' + Suffix[1];
          TruncHund := StrToInt(RightStr(IntToStr(xD), 3));
          TruncTens := StrToInt(RightStr(IntToStr(xD), 2));
          if (TruncHund <> 0) and (TruncTens = 0) then
             BTStr := BTStr + 'and ' + Ones[StrToInt(LeftStr(IntToStr(TruncHund), 1))] + ' ' + Suffix[0]
          else
          if (TruncHund <> 0) and (TruncTens <> 0) then
             BTStr := BTStr + ', ' + fHundENG(TruncHund);
       end
       else
       if (xD >= 100000) and (xD <= 9999999) then
       begin
          BTStr := fHundENG(StrToInt(LeftStr(IntToStr(xD), 3))) + ' ' + Suffix[1];
          TruncHund := StrToInt(RightStr(IntToStr(xD), 3));
          TruncTens := StrToInt(RightStr(IntToStr(xD), 2));
          if (TruncHund <> 0) and (TruncTens = 0) then
             BTStr := BTStr + 'and ' + Ones[StrToInt(LeftStr(IntToStr(xD), 1))] + ' ' + Suffix[0]
          else
          if (TruncHund <> 0) and (TruncTens <> 0) then
             BTStr := BTStr + ', ' + fHundENG(TruncHund);
       end;
       Result := BTStr;
    end;
    function fMioENG(xD: Int64): string;
    var BTStr: string;
    begin
       if (xD >= 1000000) and (xD <= 9999999) then
       begin
          BTStr := Ones[StrToInt(LeftStr(IntToStr(xD), 1))] + ' ' + Suffix[2];
          TruncThou := StrToInt(RightStr(IntToStr(xD), 6));
          if (TruncThou <> 0) then
             BTStr := BTStr + ', ' + fThouENG(TruncThou);
       end
       else
       if (xD >= 10000000) and (xD <= 19999999) then
       begin
          BTStr := Teens[StrToInt(LeftStr(IntToStr(xD), 2))] + ' ' + Suffix[2];
          TruncThou := StrToInt(RightStr(IntToStr(xD), 6));
          if (TruncThou <> 0) then
             BTStr := BTStr + ', ' + fThouENG(TruncThou);
       end
       else
       if (xD >= 20000000) and (xD <= 99999999) then
       begin
          if (StrToInt(LeftStr(IntToStr(xD), 2)) = 0) then
             BTStr := Tens[StrToInt(LeftStr(IntToStr(xD), 2))] + ' ' + Suffix[2]
          else
             BTStr := Tens[StrToInt(LeftStr(IntToStr(xD), 2))] + ' ' +
                      Ones[StrToInt(LeftStr(IntToStr(xD), 2))] + ' ' + Suffix[2];
          TruncThou := StrToInt(RightStr(IntToStr(xD), 6));
          if (TruncThou <> 0) then
             BTStr := BTStr + ', ' + fThouENG(TruncThou);
       end
       else
       if (xD >= 100000000) and (xD <= 999999999) then
       begin
          BTStr := fHundENG(StrToInt(LeftStr(IntToStr(xD), 3))) + ' ' + Suffix[2];
          TruncThou := StrToInt(RightStr(IntToStr(xD), 6));
          if (TruncThou <> 0) then
             BTStr := BTStr + ', ' + fThouENG(TruncThou);
       end
       else
       begin
          TruncThou := StrToInt(RightStr(IntToStr(xD), 6));
          if (TruncThou <> 0) then
             BTStr := BTStr + fThouENG(TruncThou);
       end;
       Result := BTStr;
    end;
    function fBioENG(xD: Int64): string;
    var BTStr: string;
    begin
       if (xD >= 1000000000) and (xD <= 9999999999) then
       begin
          BTStr := Ones[StrToInt64(LeftStr(IntToStr(xD), 1))] + ' ' + Suffix[3];
          TruncMio := StrToInt64(RightStr(IntToStr(xD), 9));
          if (TruncMio <> 0) then
             BTStr := BTStr + ', ' + fMioENG(TruncMio);
       end
       else
       if (xD >= 10000000000) and (xD <= 19999999999) then
       begin
          BTStr := Teens[StrToInt64(LeftStr(IntToStr(xD), 2))] + ' ' + Suffix[3];
          TruncMio := StrToInt64(RightStr(IntToStr(xD), 9));
          if (TruncMio <> 0) then
             BTStr := BTStr + ', ' + fMioENG(TruncMio);
       end
       else
       if (xD >= 20000000000) and (xD <= 99999999999) then
       begin
          if (StrToInt64(LeftStr(IntToStr(xD), 2)) = 0) then
             BTStr := Tens[StrToInt64(LeftStr(IntToStr(xD), 2))] + ' ' + Suffix[3]
          else
             BTStr := Tens[StrToInt64(LeftStr(IntToStr(xD), 2))] + ' ' +
                      Ones[StrToInt64(LeftStr(IntToStr(xD), 2))] + ' ' + Suffix[3];
          TruncMio := StrToInt64(RightStr(IntToStr(xD), 9));
          if (TruncMio <> 0) then
             BTStr := BTStr + ', ' + fMioENG(TruncMio);
       end
       else
       if (xD >= 100000000000) and (xD <= 999999999999) then
       begin
          BTStr := fHundENG(StrToInt64(LeftStr(IntToStr(xD), 3))) + ' ' + Suffix[3];
          TruncMio := StrToInt64(RightStr(IntToStr(xD), 9));
          if (TruncMio <> 0) then
             BTStr := BTStr + ', ' + fMioENG(TruncMio);
       end
       else
       begin
          TruncMio := StrToInt64(RightStr(IntToStr(xD), 9));
          if (TruncMio <> 0) then
             BTStr := BTStr + fMioENG(TruncMio);
       end;
       Result := BTStr;
    end;
    function fTrilENG(xD: Int64): string;
    var BTStr: string;
    begin
       if (xD >= 1000000000000) and (xD <= 9999999999999) then
       begin
          BTStr := Ones[StrToInt(LeftStr(IntToStr(xD), 1))] + ' ' + Suffix[4];
          TruncBio := StrToInt64(RightStr(IntToStr(xD), 12));
          if (TruncBio <> 0) then
             BTStr := BTStr + ', ' + fBioENG(TruncBio);
       end
       else
       if (xD >= 10000000000000) and (xD <= 19999999999999) then
       begin
          BTStr := Teens[StrToInt(LeftStr(IntToStr(xD), 2))] + ' ' + Suffix[4];
          TruncBio := StrToInt64(RightStr(IntToStr(xD), 12));
          if (TruncBio <> 0) then
             BTStr := BTStr + ', ' + fBioENG(TruncBio);
       end
       else
       if (xD >= 20000000000000) and (xD <= 99999999999999) then
       begin
          if (StrToInt64(LeftStr(IntToStr(xD), 2)) = 0) then
             BTStr := Tens[StrToInt64(LeftStr(IntToStr(xD), 2))] + ' ' + Suffix[4]
          else
             BTStr := Tens[StrToInt64(LeftStr(IntToStr(xD), 2))] + ' ' +
                      Ones[StrToInt64(LeftStr(IntToStr(xD), 2))] + ' ' + Suffix[4];
          TruncBio := StrToInt64(RightStr(IntToStr(xD), 12));
          if (TruncBio <> 0) then
             BTStr := BTStr + ', ' + fBioENG(TruncBio);
       end
       else
       if (xD >= 100000000000000) and (xD <= 999999999999999) then
       begin
          BTStr := fHundENG(StrToInt64(LeftStr(IntToStr(xD), 3))) + ' ' + Suffix[4];
          TruncBio := StrToInt64(RightStr(IntToStr(xD), 12));
          if (TruncBio <> 0) then
             BTStr := BTStr + ', ' + fBioENG(TruncBio);
       end
       else
       begin
          TruncBio := StrToInt64(RightStr(IntToStr(xD), 12));
          if (TruncBio <> 0) then
             BTStr := BTStr + fBioENG(TruncBio);
       end;
       Result := BTStr;
    end;
    function fQuadENG(xD: Int64): string;
    var BTStr: string;
    begin
       if (xD >= 1000000000000000) and (xD <= 9999999999999999) then
       begin
          BTStr := Ones[StrToInt(LeftStr(IntToStr(xD), 1))] + ' ' + Suffix[5];
          TruncTril := StrToInt64(RightStr(IntToStr(xD), 15));
          if (TruncTril <> 0) then
             BTStr := BTStr + ', ' + fTrilENG(TruncTril);
       end
       else
       if (xD >= 10000000000000000) and (xD <= 19999999999999999) then
       begin
          BTStr := Teens[StrToInt(LeftStr(IntToStr(xD), 2))] + ' ' + Suffix[5];
          TruncTril := StrToInt64(RightStr(IntToStr(xD), 15));
          if (TruncTril <> 0) then
             BTStr := BTStr + ', ' + fTrilENG(TruncTril);
       end
       else
       if (xD >= 20000000000000000) and (xD <= 99999999999999999) then
       begin
          if (StrToInt64(LeftStr(IntToStr(xD), 2)) = 0) then
             BTStr := Tens[StrToInt64(LeftStr(IntToStr(xD), 2))] + ' ' + Suffix[5]
          else
             BTStr := Tens[StrToInt64(LeftStr(IntToStr(xD), 2))] + ' ' +
                      Ones[StrToInt64(LeftStr(IntToStr(xD), 2))] + ' ' + Suffix[5];
          TruncTril := StrToInt64(RightStr(IntToStr(xD), 15));
          if (TruncTril <> 0) then
             BTStr := BTStr + ', ' + fTrilENG(TruncTril);
       end
       else
       if (xD >= 100000000000000000) and (xD <= 999999999999999999) then
       begin
          BTStr := fHundENG(StrToInt64(LeftStr(IntToStr(xD), 3))) + ' ' + Suffix[5];
          TruncTril := StrToInt64(RightStr(IntToStr(xD), 15));
          if (TruncTril <> 0) then
             BTStr := BTStr + ', ' + fTrilENG(TruncTril);
       end;;
       Result := BTStr;
    end;
begin
   iD := abs(Trunc(D));
   if (iD >= 0) and (iD <= 99) then RStr := fTensENG(iD) else
   if (iD >= 100) and (iD <= 999) then Rstr := RStr + fHundENG(iD) else
   if (iD >= 1000) and (iD <= 999999) then RStr := RStr + fThouENG(iD) else
   if (iD >= 1000000) and (iD <= 999999999) then RStr := RStr + fMioENG(iD) else
   if (iD >= 1000000000) and (iD <= 999999999999) then RStr := RStr + fBioENG(iD) else
   if (iD >= 1000000000000) and (iD <= 999999999999999) then RStr := RStr + fTrilENG(iD) else
   if (iD >= 1000000000000000) and (iD <= 999999999999999999) then RStr := RStr + fQuadENG(iD);
   if ChkER then RStr := RStr + ' ' + ER;
   vFrac := Frac(D);
   if (vFrac <> 0) then
   begin
      sDec := FormatFloat('0.000000', vFrac);
      if ChkER then
      begin
         sDec := MidStr(sDec, 3, 2);
         vDec := StrToInt(sDec);
         if (vDec > 0) then RStr := RStr + ' and ' + fTensENG(vDec) + ' cents.';
      end
      else
      begin
         RStr := RStr + ' point ';
         ReadFrac := False;
         sFrac := '';
         for I := Length(sDec) downto 3 do
         begin
            if (sDec[I] <> '0') then ReadFrac := True;
            if ReadFrac then sFrac := Ones[StrToInt(sDec[I])] + ' ' + sFrac;
         end;
         RStr := RStr + sFrac;
      end;
   end;
   Result := RStr;
end;

USB device detection

November 19, 2014 5 comments

This is a cool unit for USB device detection. Simply create an instance of the object and catch the events. Very cool for dealing with external disks.

 

unit uUsb;

interface

uses Windows, Messages, Classes;

type
  PDevBroadcastHdr  = ^DEV_BROADCAST_HDR;
  DEV_BROADCAST_HDR = packed record
    dbch_size: DWORD;
    dbch_devicetype: DWORD;
    dbch_reserved: DWORD;
  end;
  TDevBroadcastHdr = DEV_BROADCAST_HDR;

type
  PDevBroadcastDeviceInterface  = ^DEV_BROADCAST_DEVICEINTERFACE;
  DEV_BROADCAST_DEVICEINTERFACE = record
    dbcc_size: DWORD;
    dbcc_devicetype: DWORD;
    dbcc_reserved: DWORD;
    dbcc_classguid: TGUID;
    dbcc_name: Char;
  end;
  TDevBroadcastDeviceInterface = DEV_BROADCAST_DEVICEINTERFACE;

const
  GUID_DEVINTERFACE_USB_DEVICE: TGUID = '{A5DCBF10-6530-11D2-901F-00C04FB951ED}';
  DBT_DEVICEARRIVAL          = $8000;
  DBT_DEVICEREMOVECOMPLETE   = $8004;
  DBT_DEVTYP_DEVICEINTERFACE = $00000005;

type
  TUsbNotifyProc = procedure(Sender: TObject; const DeviceName: String) of Object;
  TUsbNotifier = class
  private
    FWindowHandle: HWND;
    FNotificationHandle: Pointer;
    FOnUsbArrival: TUsbNotifyProc;
    FOnUsbRemoval: TUsbNotifyProc;
    procedure WndProc(var Msg: TMessage);
  public
    constructor Create;
    property OnUsbArrival: TUsbNotifyProc read FOnUsbArrival write FOnUsbArrival;
    property OnUsbRemoval: TUsbNotifyProc read FOnUsbRemoval write FOnUsbRemoval;
    destructor Destroy; override;
  end;


implementation

constructor TUsbNotifier.Create;
var
  Size: Cardinal;
  Dbi: TDevBroadcastDeviceInterface;
begin
  inherited;
  FWindowHandle := AllocateHWnd(WndProc);

  Size := SizeOf(Dbi);
  ZeroMemory(@Dbi, Size);

  Dbi.dbcc_size := Size;
  Dbi.dbcc_devicetype := DBT_DEVTYP_DEVICEINTERFACE;
  Dbi.dbcc_classguid := GUID_DEVINTERFACE_USB_DEVICE;

  FNotificationHandle := RegisterDeviceNotification(FWindowHandle, @Dbi,
                                              DEVICE_NOTIFY_WINDOW_HANDLE);
end;

procedure TUsbNotifier.WndProc(var Msg: TMessage);
var
  Dbi: PDevBroadcastDeviceInterface;
begin
  with Msg do
  if (Msg = WM_DEVICECHANGE)
      and ((WParam = DBT_DEVICEARRIVAL)
        or (WParam = DBT_DEVICEREMOVECOMPLETE)) then
  try
    Dbi := PDevBroadcastDeviceInterface(LParam);
    if Dbi.dbcc_devicetype = DBT_DEVTYP_DEVICEINTERFACE then
    begin
      if WParam = DBT_DEVICEARRIVAL then
      begin
        if Assigned(FOnUsbArrival) then
          FOnUsbArrival(Self, PChar(@Dbi.dbcc_name));
      end
      else
      begin
        if Assigned(FOnUsbRemoval) then
          FOnUsbRemoval(Self, PChar(@Dbi.dbcc_name));
      end;
    end;
  except
    Result := DefWindowProc(FWindowHandle, Msg, WParam, LParam);
  end
  else
    Result := DefWindowProc(FWindowHandle, Msg, WParam, LParam);
end;

destructor TUsbNotifier.Destroy;
begin
  UnregisterDeviceNotification(FNotificationHandle);
  DeallocateHWnd(FWindowHandle);
  inherited;
end;

end.

Hacks, cracks and your community

November 18, 2014 Leave a comment

In the past week there has been a kind of airy atmosphere over at Delphi developer (Facebook group). The general theme has been dealing with piracy and hackers, which led to members of the group standing up for each other and becoming more public.

Software Piracy

Software Piracy

The week began by Slobodan¬†(of Delphi 1-2-3) catching another member in actively promoting and pushing cracked copies of his work (as well as TMS, Mitov and other¬†software houses). As expected he was furious. Especially since the guy doing this was also chatting and talking to him like he was a friend. The phrase “two-faced crook”¬†fit’s the bill here.

Some piracy is to be expected, but when it get’s up close and personal the objective view is quickly replaced with a subjective and personal experience.

At the same time I found a crack for Smart Mobile Studio online, which made me very sad. I mean, we have set the prices as low as you can possibly go – and we did this exactly to avoid piracy. Who in their right mind would go to the trouble of hacking $100-$300 software? Especially when it’s a development platform which gives you so much productivity in return for so little investment.

And to make matters worse, we have free licenses for students – so the whole “oh i cant afford it” argument is null and void. If it’s good enough to crack, download and use – then it should be good enough for people to buy and support. I can understand why people pirate software that costs thousands of dollars – but pirating $300? Seriously?

Outrageous Software Prices

Outrageous Software Prices

I mean, Adobe could very well lower the price on their software, because the astronomic price tag leads to piracy, even by medium size companies. I’m using an ancient version that I picked up for $100 on a store sale many years ago – and I wont upgrade either because I have no use for all the fancy effects in modern Photoshop. So it would be better for Adobe¬†to even out the number of sales vs. price and earn the same or more amount of money – but diversified over a larger user base.

The same can be said about Embarcadero. I have met plenty of companies with 3-5 developers that are using cracks. To avoid awkward moments where they fall over themselves to hide this fact, I tend to calculate a new Delphi license into my project price, listing Delphi or Smart Mobile Studio as a project dependency. So if we use Delphi then they have to buy a license unless they already have a valid EDN registered version. If only Embarcadero knew how many Delphi versions I had sold for them..

Either way – the theory of price vs. piracy is true, but also not true. Hackers will crack your product because they like the challenge. But most users will prefer a valid product if they can afford it. Although I must admit that even that theory (in the scientific sense) is overdue for a fresh peer-review after this.

What made my week sad and dim was the fact that, in the comment section of the piracy download, another known member of Delphi developer had commented. A person I had talked to quite frequently and that I regarded as trustworthy.

In the end I simply had no choice but to kick both individuals from the group. We can’t have a group where people openly pirates your hard work – only to socialize with their victims on top of stealing from them.

People are people

On the positive side of things people really engaged in these cases. Programmers that are otherwise silent on most¬†subjects all came out to say their piece regarding the situation. The Delphi and object pascal community has always been one of the best programming groups in the world, but this time I was proud of¬†my group – because the people in the group are helpful, insightful, responsible and warm. There is a reason why the group is bigger then the official Embarcadero group ūüôā

Our community is growing

Our community is growing

Peter (lieutenant admin) had a meetup with Glenn (second lieutenant admin) in Coventry, UK face to face. I really wished I could have attended, but with the damage¬†to my lower back, 3 kids and loads of stuff to do – I will have to wait until next time. But once again the forum turned “personal” and we all ended up discussing cognac and having a laugh ūüôā

But the fact that we have now moved on from a purely “digital forum” onto¬†meeting face to face and building a real and tangible community is noteworthy. I hope to organize a full group meeting in the future, much like pasCON or IT Dev-con. But this time purely for pascal programmers.

Co-operation

The Delphi developer group has become a place of co-operation, a place where solid programmers go to find like-minded and establish co-operation across nationality. We have job listings every week (more or less) and a very active forum.

One of the things I look forward to is Peter’s multi-lingual projects. He has been working for quite a while on a new way to deal with in-app translation. So it’s going to be quite exciting trying this out later.

We also have X number of projects initiated by members, with other members from around the globe working together with great results.

Come join us!

If you havent joined the group yet, be sure to head over to Facebook and join our group. We are now 2.400 people and counting — all object pascal users with a healthy mix between Delphi, Smart Mobile Studio, Oxygene and freepascal ūüôā

 

Opensource dot net, Delphi and the future

November 15, 2014 9 comments

A seemingly unsuspected move from software giant Microsoft, announcing that they are truly and whole-heartedly open-sourcing “dot net” in total. Which means that dot net both as a software platform, framework and virtual machine technology can now be downloaded, altered, inspected, deployed and used en-mass by anyone.

The question we should be asking however, is “what is the motivation behind” such a seemingly open¬†action by an otherwise closed software production company?

If I have learnt anything over the past 30 years, it’s that Microsoft never does anything which doesn’t ultimately provide a benefit for themselves. And while people are falling over themselves to congratulate Microsoft on this, I like to view the decision with a solid dose of cynicism rooted in facts; facts regarding their previous actions, their business methods and their utter ruthlessness towards any one person or company which does not yield to their will.

Rent a PC

Some 16 years ago (or there about) I remember reading in a local newspaper an interview with Steve Ballmer. The interview was not planned in any way, the journalists were just lucky to catch him at the airport waiting for a plane to New York.

In this short but informative interview there was one segment that I found very peculiar. While I don’t remember his¬†words verbatim, Steve was talking about the future of software – which to him was a model where you rented software rather than buying it. So the final section of the interview was completely dedicated to this “future business model”.

I remember a cold chill going down my spine after reading it, because if the biggest software company in the world adopts such a model – it means the end of helping people. Never again will you be able to help someone who can’t afford a PC by giving them your old laptop — because that will invalidate your license. And never again will you be able to fully buy a piece of software, you will be bound to a rent model where you simply buy the right to use something within a very restricted field of activity.

The same thing can be said about the move to purely digital methods of payment. Never again can you help out a friend in need without leaving a digital trail. And you can forget about supporting a cause without leaving digital fingerprints. You can’t borrow money from anyone should you need help either — and giving money to help the poor will be made illegal. In fact it has become illegal to give money to the poor (and food) in some places.

Is this a society that you find appealing?

Lets never forget that Microsoft rode Netscape so hard, that one of its developers committed suicide from going personally bankrupt. Microsoft peppered Netscape employees with frivolous lawsuits in order to bully them into submission. It took several years before the EU commission labeled Microsoft’s actions as illegal – prohibiting Microsoft¬†from killing it’s competition; quite literally in that particular case.

Cui bono?

Without sounding like a conspiracy nutter: the benefit of open-sourcing dot net should be recognized for what it is. In this case it’s a call to eliminating the competition. The dot net framework has already grown roots on¬†the Linux and OS X operative systems – and with this move to open source, the integration of essential cloud services designed to fill Microsoft’s already cornucopic¬†pockets will become even deeper ingrained.

What Microsoft is doing here is to eliminate the competition, meaning minority languages and small businesses; they are also making sure dot net will be a part of all major operative systems -and your right to choose is eliminated by design, rather than a healthy choice between equal competitors.

Winning the election is not hard with only one political party on the menu.

I find this to be very dangerous, especially for Linux which is presently the only real contender to Microsoft in the field of desktop and server software. The world needs alternatives because if any one single economic entity dominates Рremoving it from the throne will be next to impossible for the coming decades.

The only company who ultimately gains anything from this move, is Microsoft themselves. Superficially it may seem like an act of kindness, but you don’t have to be a deep thinker to see the factors match up – with a final outcome where Microsoft strengthens its position.

Why fight over OS when you can own the server-park?

Why fight over OS when you can own the server-park?

But it’s free

As programmers it’s important to keep up with modern technology — but there is a difference in being up-to-date¬†and becoming inoculated. As programmers we should think what is best for us, not where we should be in order to reap the benefits of Microsoft.

There can be little doubt that Microsoft has planned this for quite some time. It may seem spontaneous, but taking into account Microsoft’s earlier strategies – and the fact that they have openly debated their “cloud based access model” for nearly two decades;

Well, I think we can safely say that this move was not polled out of a hat in the 11’th hour, but rather carefully and meticulously orchestrated.

And it can only mean one thing to minority programming languages and platform: adopt our way of doing things or die out.

What about Delphi?

You don’t have to be a rocket-scientist to figure out that this is not a good thing for Delphi. I think we can expect to see Embarcadero putting more emphasis on OS X and Firemonkey from now on, since the Mac market has a natural fear of all things Microsoft – and thus will accept a native Delphi for their platform. Or at least be more open for influence.

But OS X and, if Embarcadero so wish, Linux is most likely the only markets where Delphi can continue to grow in the traditional way. Embarcadero will no doubt sing along with Microsoft on cloud computing – but the growth factor will no doubt start to shift in favour of OS X and Linux in the next 5-6 years.

Competing on equal footing

Smart Mobile Studio and other compiler-toolkits that target JavaScript is where you will see the most growth. JavaScript is something which Microsoft had to adopt when they killed Netscape, and in the world of browsers and JavaScript-based hardware, the dot net framework is like shooting sparrows with a canon. It’s to big, to bloated and to resource hungry.

But lean, mean and juiced up JavaScript powered by nodeJS will deliver a cloud based alternative which will be hard for Microsoft to take ownership of. They tried to take over Java from Sun, but that was an undisputed defeat. And we all know how Microsoft’s variation of JavaScript ended up.

It will be extremely interesting to see how Google responds to Microsoft’s move. As of writing, Google is the company who stands to lose the most.

Either way, JavaScript is going places where Microsoft simply does not exist. And it will enjoy the role of a free agent for decades to come.

TDBF, your free, open source, Delphi database engine!

November 7, 2014 6 comments
We need a light database

We need a light database

One of Delphi’s strengths has always been it’s support for databases. Even back in the day I remember C++ users looking over my shoulders at how easy it was for me to create a database application, while they themselves had to commit proverbial warfare on some bulky, esoteric API just to store lists. So when it comes to databases Delphi programmers have been spoiled rotten with an impressive menu of drivers and native engines.

But as always there is a catch, and that catch used to be that you had to ship the BDE with your applications (which at the time was “wow, that simple?” factor. The basic and C guys had it much worse) if you were going to work with Interbase, Paradox or DBase – which were the heroes back then.

Like many others I decided to skip the whole BDE and opt for a native, embedded database engine. Meaning a full database system written in Delphi itself as opposed to C/C++ (which really is the paradox here, since working with databases under C++ was a bit like shaving with a cheese grinder: slightly amusing but mostly painful). And I mean no disrespect to any Delphi database engine author, but DBISAM was king, only topped by ElevateDB which is¬†it’s successor (and very much alive and kicking to this day). So if you want a solid database engine which is embedded (meaning: compiled into your program) ElevateDB is worth every penny.

At the end of the day, what Delphi had (and still has to some extent) to offer is:

  • Pretty much the best support for popular databases out of the box (read: drivers)
  • A wide variety of database engines written in Delphi

As you probably guess, none of these options are really free. And those that are free, like FireBird, requires a lot of reading or studying of code to get working. Now please don’t get me wrong, I really¬†want to avoid any debate situation where some Firebird guy wants to protect his favorite database. The point is simply this: if you know absolutely nothing about Firebird or Interbase and you just want a quick “drop in” component which gives you database capabilities, then Firebird can be pretty daunting. It’s a serious piece of software engineering which means you should know what you are doing and have the time to learn exactly that.

Take myself as an example: I spent a whole day trying to connect to a FB database, only to discover way into the dark hours that there were in fact two different FB versions. Had this been explained in right at the start I could have spent my day making my actual database rather than googling for error codes and exception identifiers. Secondly, the Firebird team should ship a simple Delphi demo complete with the embedded version Рready to be used by anyone.

And last but not least, FireBird doesn’t always play nice with Interbase components – and getting everything to work out of the box (I ended up with Zeos component set)¬†can’t really be compared to the smooth sailing that is ElevateDB or DBISAM. There you just install, drop the components on a form or datamodule — voila, that’s it.

Shooting sparrows with a canons

While all of this is well and good, with plenty of drivers and support for popular technology from mySQL to MSSQL to Firebird and whatnot, dont you find it to be overkill? I mean for small projects?

For instance, I was writing a simple movie¬†collection program a few years back, which downloaded the movie cover online¬†and figured out things like what year the movie was made etc. based on name and online sources. My database needs very humble to say the least, something between 5¬†to 100¬†megabytes maximum. My first “test” database did not take up more than 30 megabytes (using TClientDataset which bloats everything by storing data as variant no matter what).

So where is the alternative? Do I really need to fork out $300 for a native Delphi engine just to store between 5 and 100 megabytes of data in a sequential, indexed and searchable way? And if I go for the “free” alternatives, how many hours do I have to work just to get the database engine working in the first place?¬†Having played around with mySQL embedded, SQL Server light and Firebird –¬†sticking to Windows and using ElevateDB seemed like the best option.

But having seen what ships with Visual Studio, Mono C# and even Lazarus/FreePascal I felt outright annoyed that Embarcadero had absolutely no free, built-in (so to speak) alternative. The only possible alternative was TClientDataset, which is perfect in terms of functionality (you rarely need SQL when dealing with such a small amount of non-complex data)¬†— but it’s not a disk based table and quickly eats up memory once you start stuffing blobs into it.

I wanted a small, compact and humble database¬†solution that may not be the fastest gun in the west, but at least you could trust it to scale properly and be written in such a way that it’s portable.

TDBF to the rescue

For the past couple of years I have held an eye on the database segment of Delphi, hoping that someone out there had either written a native Delphi database engine which was free and open-source, or that someone had taken the time to compile SQLite to .lib files and turned it into a TDataset descendant. The closest thing I came to a good clean production of SQLite was from Synopse — but just when I thought I had finally found what I was looking for, they decided to include it in their mORMot framework — adding a lot of dependencies which I quite frankly did not want.

As my search continued, I finally stumbled across a project¬†which fit my needs! It’s a very small piece of database kit called TDBF, written in Delphi and compiles straight into your exe file.

To quote the Sourceforge website:

TDBF is a freeware native data access component for Borland Delphi, C++Builder and Kylix, and for FreePascal.¬†It allows you to create very compact database programs that don’t need any special installer programs.¬†In fact the code to access your database is compiled in your project executable file.
It takes only a few kilobytes in your executable and doesn’t need any other external files to run.

That is spot on perfect for my needs, and I’m guessing others as well. Having a simple “drop in” database which can be used for anything, speed not withstanding, should be considered a primer for any native¬†programming language. I sincerely hope that Embarcadero either pick up this open-source project as a low-end alternative to Interbase Embedded (or perhaps¬†sqLite would be more suitable).

If you visit the website you will find that it has quite a few years of development behind it. Secondly, if you check the SVN you will see that it was updated in 2013 (last year) so you should probably check out the code via SVN, since the website havent been updated in 7 years. But that doesn’t necessarily¬†mean anything bad, there are plenty of components which doesn’t need updates because they work just fine. But I know many people regard “recent updates” as a sign of quality, so I’ll just mention this — the website havent been updated, but the code has (!)

The author has done a great job in keeping it backwards compatible with earlier Delphi releases (all the way to Delphi 3), but¬†personally my absolute lowest possible limit would be Delphi 7, which I consider “classic object pascal” but even that can be discussed right now since we just moved to XE6. Either way, I will probably do a little cleanup of the code to get rid of legacy support and assembler segments.

And that’s another positive point: it’s platform independent from the ground up, designed to compile under both Delphi and freepascal. That is very nice because I am moving more and more code to Linux these days, and having a small and compact database engine which is portable and free is most welcome!

So if you are looking for a simple, clean, functional and free database engine written in object pascal which you can use anywhere — then I¬†sincerely urge you to download and give TDBF a try. I also hope someone out there takes the time to fork this project and keep it alive (I only have time for my own stuff right now) because it’s something the Delphi community needs!

Although it ships with some 15 units, the content of the units is surprisingly small – so you could easily pack it all into a single unit without turning it into a mess. I love it when cool technology fits nicely inside a single unit with no dependencies ūüôā

Im actually hoping to port some of it to Smart Mobile Studio later !

Highlights

  • Ships with several localization units (French, English, German, Spanish, Italian and more)
  • Compiles under Delphi and Freepascal
  • Platform independent (Windows, Linux and Unix)
  • No dependencies or external drivers, compiles into your program
  • Very small footprint, only adds a few KB to your exe file
  • Perfect for small projects and mobile applications
  • Compatible with DBase
  • Memo field support (dynamic size fields)
  • Indexing supported, fast lookup and searching
  • Derives from TDataset (standard Delphi database framework)

¬†Click here to visit the website. See the “SF Project Page” link to view the sourceforge SVN repository

Famous software made with Delphi

November 6, 2014 47 comments
Delphi is used in thousands of titles

Delphi is used in thousands of titles

Once in a while I meet some programmer, typically Java, Python or C++ developer who have absolutely no knowledge of Delphi. The only thing he knows is that it looks like something between Basic and Modula, and as such he blurts out comments like “Delphi? What the hell, who uses Delphi anyways! I have never used a program written in Delphi! Have you ever seen a Delphi program that actually works!“.

The latter is a direct quote from the React OS forums [an older thread I admit, but true non-the-less] where several users asked for prioritized Delphi support (to be able to run Delphi on the free ReactOS system, which is basically an open-source re-make of Windows NT). The response came from one of React OS engineers, a very well known C++ programmer, who for some reason hates Delphi. Why we will never know.

I wish I could have been a part of that¬†conversation because I would have set him straight about a number of things; but by the time I came into in this (by asking about Delphi of course)¬†the comment section was muted and the thread left for dead. Which is a great shame, because I am willing to bet that he indeed has used a program written in Delphi. He simply did not know that it was a Delphi application — or the fact that Delphi rivals C/C++ in almost every field. In some cases it even surpasses C/C++ in terms of speed, but C++ programmers dont like to talk about that ūüôā

Famous Delphi titles

Anyways,¬†below is a short list of applications written in Delphi, just those that I can think about on top of my head (and with a little help of my friends over at Delphi Developer on Facebook). Some may come as a surprise, other not. But there is a lot of Delphi code out there that people don’t know about! And this is just a drop in the proverbial ocean of Delphi software titles.

So if you are new to object pascal, introduced by Smart Mobile Studio, Delphi or FreePascal, then I hope this list will at least give you a taste of what our language can do. You will find highly versatile, friendly, advanced, scalable and productive language which grows with you. No matter how good you get at programming, object pascal will never leave you lacking in features. Well, here is the list of the titles I know:

Anti spyware and system tools

File and disk

Authoring and help

Database

Multimedia, print and web

Networking

Scientific

  • Altium Designer Board
  • Orca Flex,¬†design and analysis of offshore marine systems
  • SOFIA, Nasa software project
  • Orca Lay,¬†planning and optimization of pipeline and umbilical lay procedures
  • Orca Bend,¬†design tool for efficient optimization of elastomeric bend stiffeners
  • Diptrace, Schematic capture software

Misc titles

Programming languages and IDE’s

Commercial gaming

Emulators

  • nesTen, Nintendo emulator written in Delphi
  • winNes, Nintendo emulator written in Delphi
  • ulTee, Another Nintendo emulator also written in Delphi
  • DSP, Arcade emulator written in Delphi
  • Dolphin, Nintendo Gamecube and WII emulator written in Delphi
  • DxBx, XBox emulator written in Delphi

As mentioned,¬†there are thousands of titles created in Delphi and freepascal which are available in the global marketplace. Many of them completely free of charge just like freepascal and Lazarus. Applications that are very well known and used — which means it’s a shame that people (especially programmers using different languages) dont give Delphi and object pascal the credit it deserves. Delphi is not basic, and pascal was the language designed to replace C/C++ all those years ago. So it’s no push-over or lightweight. The code produced by Delphi is en-par with C++ Builder (it’s companion “sister” product) with support for generics, inline assembler, anonymous procedures, templates (FPC) and much, much more.

Scene from Abra Academy, Game written in Delphi by Big Fish games

Scene from Abra Academy, game written in Delphi

So the next time someone goes “What? Object Pascal? Delphi?” then give them this list and ask them if they have ever used¬†one of these programs. I havent even scratched the surface with this tiny list, but im pretty sure most people have used or at least heard about Skype. And Nero Burning Rom is also very, very well known – so odds are they have used that at some point.

Pascal is a “real” language. It’s not a basic compiler with an intermediate bytecode format that requires a truck-load of bloated DLL files to run. It’s not a script runtime or juiced up state machine. Object Pascal compilers produce real machine code and the language supports inline assembly straight out of the box. The executables you get have NO dependencies. As for Delphi, which is regarded as the “trend setter”, it’s sister and companion product is C++ builder which it is binary compatible with; Meaning that you can use compiled units between them without change. What you compile in C/C++ you can use in pascal, and what you create in pascal you can link and use in C without special treatment.

Besides that you can link to .lib and .obj files to your heart content, write header files for dll’s or imported code segments — heck, operative systems have been written from scratch in object pascal (so you Java boys can chill out, we did it decades before you – and we did it better).

And programmers (even Microsoft) use InnoSetup or there is something wrong with them ūüėČ

 

Smart Pascal dialect

November 5, 2014 2 comments

Ever since I posted the “Smart Pascal now an official dialect” post, I have gotten a fair share of negative comments on the subject.

Article

Article

First, I am open to the choice of words perhaps being “off” the mark. It was written at the spur of the moment as just a quick message to those that read my blog. So I didn’t exactly sit down and meditate of 2 days beforehand, trying to find the exact right words to use – nor is English my native language, so unless I focus a bit – my style of writing will always have a Norwegian flavor to it.

What does official mean

For some odd reason people have reacted to the word “official”, as if that requires some form of consortium or establishment behind it. It’s a word open for translation perhaps, but for me it simply means:

Publicly available, publicly accessible – and ultimately: publicly open for scrutiny.

I mean, when BattleField III and IV was announced it was done via a public announcement which is often termed “official”. When you google websites which has a lot of fans, it’s often required to add the word “official” to the query – just to filter out all the fan-sites from the actual site (especially for movies and bands). So how people can react to the word “official”, like I have somehow mis-represented Smart Mobile Studio and whatever articles have been written about it online; well, it could not be further from the truth.

And when it comes to the term “dialect” and Smart Pascal now being an “official dialect” of object pascal, consider this: On paper American English and British English can be tough¬†to distinguish, yet everyone in the world recognizes the difference between British, American, Irish and Scottish. There is very little linguistic¬†difference in the vocabulary¬†between, say, an Irishman and someone born and raised in London with a purely “brit”¬†accent. But the moment you get a chance to hear how they pronounce and use words — you will recognize that one is from Ireland and the other from London. You should also have no problems telling a man from Texas USA apart from a¬†Scottish Highlander based on their dialect.

Smart Pascal is especially suited for HTML5/JS

Smart Pascal is especially suited for HTML5/JS

A dialect simply means that:

  • There is enough in common to recognize it¬†belongs to a group (English)
  • There is enough differences¬†to recognize that it stands apart (Scottish, British, American, Australian, Irish and so on)

Looking at how other programming languages deal with this very problem: is Blitz Basic something completely new or is it regarded as a dialect of Basic? And why is it recognized as a dialect as opposed to a whole new language?

It is recognized as a dialect because, naturally, there are key elements in the syntax which follows the “basic language” style. The same can be said of Wacom C in context with Borland or¬†Gnu C. They are all recognized as C compilers, implementing a variation of the C language. In fact most vendors are quite proud when they finally support the official, latest C¬†language specification. But this is also where things become paradoxical.

If a dialect is supposed to strictly follow a defined standard, then we would have no American English, no Irish English, no British Columbia, no South African English and absolutely no Scottish English. We would only have British. Forever and ever and under no circumstances would the language expand or evolve to absorb new elements and realities without a group meeting? Thats not gonna work.

The problem? The problem is that the pascal specification (ISO 7185) is bloody ancient! It was first envisioned¬†back in 1977 (!) And I would feel deeply sorry for the entire IT community if the extent of our technological reach begins and ends with a paper. That would to a large extent invalidate most of the changes added by Embarcadero since it bought Delphi and C++ builder, and indeed any changes after Anders Hejlsberg left Borland (because he defined the standard for object pascal). It would also utterly condemn Remobjects for creating Oxygene — and freepascal would never exist in the first place.

FreePascal and Lazarus is just as in power as Delphi is

FreePascal and Lazarus is just as in power as Delphi is

So to make it crystal clear:¬†modern pascal has no group or controlling entity (legal or otherwise) which is in charge of “pascal” and what that means. C/C++ on the other hand has a vibrant and very much active group of thinkers and specification thumpers, led by the author of C++Bjarne Stroustrup (which I guess we should regard as an lawless rebel because he dared invent something not yet defined by a standard); A group which keeps on knocking out standards for the C++ language. But it’s up to each compiler author¬†and/or company to implement and follow these standards. The key here is choice and what lingo is better suited for a particular task. And this has nothing to do with academia, that’s not their job.

So once again¬†for pascal, there is no such organ. People have somewhat fallen into line automatically behind Embarcadero as “the trend setter” for object pascal, but in reality it has no more authority on the subject than Remobjects or myself. The sad reality is that object pascal sort or died when Anders Hejlsberg jumped ship and defected to Microsoft. It is a very sad story, but it’s none-the-less true. And in his absence the pascal community has had to make due. And after many years of loom and doom Delphi, FreePascal, Smart Pascal and Oxygene Pascal is standing on their own feet, evolving without the guiding hand of the grandfather of object pascal: Anders Hejlsberg.

And it should also be mentioned that Anders produced object pascal in his room, living with his parents back in Denmark– utterly violating the existing pascal specification. Something which was a necessity in order to create something new. A rule of life: the old must be destroyed for something new to be created (there is a limited amount of particles in the universe after all).

Tools of the trade?

Let’s face facts: There is no board, organ or philosophical entity in the world from which developer’s must seek a blessing in order for something to be official, although Apple is sure as hell playing the role of emperor without clothes pretty well. RemObjects Oxygene for instance, does that need the approval of Embarcadero to be an official dialect of pascal? I sure consider it an official dialect, nor was there ever a time when it was not official except for the incubation period. The moment Oxygene went from beta to public release, it was an official dialect.

The exact same thing can be said about Smart Pascal.

The tools of the trade in this case is probably university type mentality meets reality. People with a higher degree of education tends to pick up concepts along the way which quite often goes¬†against the reality of nature and the mother of necessity. Things are created and built out of personal need, adapting to a situation or technology. Nature doesn’t write a paper on it, subject it to a panel of peers for review, until it finally jumps into gear and builds it. Nope, if you can envision it, built it and drag that idea from the realm of thought to our human, factual plane — nature will back you up and provide momentum. That is the law of the jungle, and bitching about it is not gonna help.

Is Remobjects Oxygene not a proper dialect? Ofcourse it is

Is Remobjects Oxygene not a proper dialect? Ofcourse it is

And it’s been like that for thousands of years. It amuses me to some degree how few of our human¬†practical inventions that we enjoy were created in a funded, managed environment. The wast majority were in fact incubated and forged in personal “hobby” type labs by people of¬†passion. Apple and Google started out in a garage for pete sake.

I have higher education myself, but I also recognize that inspiration and motivation can just as easily be murdered by academics as it can be polished and perfected.

Final words

So what makes something official? Well it depends on who you ask perhaps. My observation is that languages can die out just as quickly as they appear, but those that “make it” into history are typically those with a book or two dedicated to them. There is also a high level of persistence involved (or required) for the inventors¬†and initiative-takers. But there is never a guarantee that one idea will win over the other. If VHS vs. BETAMAX taught us anything, it was that (or Windows vs. OS/2 for that matter).

In the meantime, I will continue to use the best tool for a job. I have no intention of putting in a nail with a screwdriver, or a screw with a hammer. Programming the browser is in my view best done with Smart Pascal, and the benefits of true OOP under JavaScript far outweighs whatever concerns some may have over a spec violation from the late seventies.