Archive
Delphi outdated? Says who!
Edit: This is an old article from 2014, so the facts are more than a little outdated. I should also underline that I was quite upset when writing this, having just come home from a rather unpleasant debate with some Java developers. The VERY tasteless meme below was not created by me. It was originally a meme about Delphi from a Java perspective — so i reversed the roles, which kickstarted an avalanche of criticism from Java developers at the time. So please keep in mind that this post would never have been posted in its current form today. Never blog when you are upset, it never looks good.
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 more funny (you should see some of the anti-delphi memes, they are far worse than this. Seriously), 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.

While utterly tasteless, this was originally a Java meme about Delphi. I simply reversed it, which caused total panic in Java land.
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” locker-room talk. Which was funny because the same gang of Java coders were initially a loud and condescending group of lamers, giggling in amusement when they heard the word “Delphi”. Only to be outsmarted, outperformed 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 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 runway 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 millions Delphi still out-ranks python, pearl, ruby, GoLang and all dialects of basic combined (it has seen a steady rise on ranking systems like Tiobe). 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. It is an atrocity cooked up in the labs at NeXT and pushed in the back-door by Steve Jobs.
Yes, I am angry. Really angry.
Statistical tomfoolery
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 repositories 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”, “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 (edit: this has been fixed in recent times, 2018).
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 newcomers 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 as a whole. We all know that these different takes on object pascal represents one large userbase, 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.

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 benefited 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 by proxy.
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.
Either way, faced with the option to die or convert to Microsoft, Anders did what most sensible people would do, and accepted the substantial 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 .Net and the whole dot net ecosystem comes from Delphi and represents a Borland skunkworks project. 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 CLR architecture. That’s because it grew from Delphi, taken and released under the Microsoft banner. The initial specs for portable Delphi included pointers from what I remember of the post 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 millions 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 goodie-two-shoe company without blemish. They made some spectacular bloopers before Microsoft slapped them out of existence, 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 innovating their products for Delphi after that. They still maintain their older products, but as far as new products are concerned, that is on pause.
Next there were the Delphi for .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 outdo 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 monstrosity.
The change
Embarcadero have in my view held their promises. Delphi as it exists now is once again a fast, lean and mean development 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 is pretty much the norm.
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 FMX. 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 won’t 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.
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 3 years (!) 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 an intellectual emergency.
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 year. 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 on 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 based on timeless principles.
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?
For instance, freepascal and Lazarus which are both free and open-source initiatives (these are two separate projects but operate as one) 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, at 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 won’t be fast! Java pushes so much crap up the stack that it’s practically abusing the hardware — and while mono is much better than Java, the amount of code it produces is 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.
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 don’t 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 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 decoupling 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 a modern version before you jump on the teenage bandwagon and thrash talk something you know nothing about. Downloading a crack of a Delphi version 15 years our of production does not count. Or should we download Visual Basic 5 and measure the merits of Visual Studio today by that standard?
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.
Here is what I would define as outdated:
- 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 unicode and UTF encoding
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 the early Swing widget sets.
As for C#, it’s ok! 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
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
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
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
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.
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?
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 🙂
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
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.
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!
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
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:
- Nero Burning Rom, CD/DVD burning software
- Skype, network telephony, voIP application
- Macromedia DreamWeaver, HTML website builder [bought by Adobe]
- Embarcadero C++ Builder IDE, Commercial C++ IDE written in Delphi
- Smart Mobile Studio, IDE and compiler toolchain for HTML5/JavaScript
- Homesite, HTML website editor [bought by Adobe, merged with DreamWeaver]
- FL Studio Pro, professional sound sequencer and synthesizer
- InstallAware, software installer
- InnoSetup, software installer
- DBase, rock solid database management application [Delphi & C++]
- WinRAR, compression application
- Partition Magic, Disk partitioning and cloning suite
- The online trader, Live stock exchange and trading application
- Syncback Pro, Brilliant backup application
Anti spyware and system tools
- Panda Titanium Antivirus, commercial antivirus
- Spyware Terminator, Anti spyware suite
- Spybot Search And Destroy, Anti spyware suite
- PC Tools Spyware Doctor, Anti spyware kit for Windows
- TuneUp Utilities, system optimizer
- Aida64, Benchmark software
File and disk
- BeyondCompare, file comparison and merge application
- Total Commander, file management application
- Super Copier, Win32/64 file copy/move dialog replacements
- CloneDVD, DVD copying software
- Ultra ISO, DVD and CD program
Authoring and help
- Help and Manual, Helpfile and book authoring software
- HelpNDoc, HTML help writer application
- SSuite Office Software, full office package written in Delphi
Database
- Oracle SQL Developer, SQL programming software
- Nexus DB, Commercial database engine written in Delphi
- MySQL Admin tools, Database management suite for mySQL
- SQL Navigator, SQL management application
- Toad for Oracle, de-facto SQL management for Oracle DB
- ElevateDB, Commercial database engine written in Delphi
Multimedia, print and web
- RadioBoss, Radio management software
- Ultimate paint, Image editor and drawing program
- IcoFX, icon and glyph editor
- KMplayer, Video and Movie application
- Responsive Layout Maker Pro, HTML WYSIWYG website designer
- Pro Motion, Pixel perfect image editor
- Media Monkey, Music manager application
- Press To Go, high-end printing press layout and management
- Gold Wave, Sound editor
Networking
- Jotta Online Backup, Cloud backup service
- TeamSpeak, network telephony, voIP application
- Hamachi, VPN Software [C++ builder combo]
- Avant browser, web browser written in Delphi
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
- Personal Historian, Ancestry and genealogy program
- Family Atlas, Ancestry and genealogy program
- Basic Premiere, Organ donor software
- Omni Accounts, Accounting software
Programming languages and IDE’s
- Morfik, Ajax native server website builder
- Elevate Web Builder, Javascript RAD IDE
- Dark Basic, game programming language
- PhpED, PHP coding editor
- RapidPHP, PHP coding IDE
- Smart Inspect, In-Depth debugging and log framework
- RAD PHP, Commercial PHP programming IDE and framework
- Finalbuilder, Commercial build management for programmers
- Lazarus, Open Source IDE for freepascal
- Freepascal, Open source object pascal compiler toolchain
Commercial gaming
- Space Rangers, Game written in Delphi
- Abra Academy, Game title by Big Fish games
- Tunngle, global LAN gaming network
- Soldat, online action game
- Age of Wonders, strategy game
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.
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
Ever since I posted the “Smart Pascal now an official dialect” post, I have gotten a fair share of negative comments on the subject.
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.
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.
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.
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.
Recent
The vatican vault
- March 2023
- February 2023
- December 2022
- October 2022
- January 2022
- October 2021
- March 2021
- November 2020
- September 2020
- July 2020
- June 2020
- April 2020
- March 2020
- February 2020
- January 2020
- November 2019
- October 2019
- September 2019
- August 2019
- July 2019
- June 2019
- May 2019
- April 2019
- March 2019
- February 2019
- January 2019
- December 2018
- November 2018
- October 2018
- September 2018
- August 2018
- July 2018
- June 2018
- May 2018
- April 2018
- March 2018
- February 2018
- January 2018
- December 2017
- November 2017
- October 2017
- August 2017
- July 2017
- June 2017
- May 2017
- April 2017
- March 2017
- February 2017
- January 2017
- December 2016
- November 2016
- October 2016
- September 2016
- August 2016
- July 2016
- June 2016
- May 2016
- April 2016
- March 2016
- January 2016
- December 2015
- November 2015
- October 2015
- September 2015
- August 2015
- June 2015
- May 2015
- April 2015
- March 2015
- February 2015
- January 2015
- December 2014
- November 2014
- October 2014
- September 2014
- August 2014
- July 2014
- June 2014
- May 2014
- April 2014
- March 2014
- February 2014
- January 2014
- December 2013
- November 2013
- October 2013
- September 2013
- August 2013
- July 2013
- June 2013
- May 2013
- February 2013
- August 2012
- June 2012
- May 2012
- April 2012
You must be logged in to post a comment.