Archive of January 2019

Progress 20190129

The worker module has been translated. This actually includes a considerable amount of text spread out in loads of files, and so represents a lot more work than 'the worker module has been translated' leads to believe.

Doing this actually allowed me to strike TWO items off the TODO list.

Incredible.

(and when you click 'publish' instead of 'save' the post becomes considerably more visible...)

Sanity checks

So, since i have (currently) 5 working and 1 WIP DLL for the backup system, and since four of these share the exact same interface,, i thought it would be a proverbial Good Idea (tm) to force compliance - force the signature of all exported functions to conform to a predefined type.

Let me explain. I can have a function called MyFunc, it looks like this: function MyFunc(inP: Integer) : String;

so it takes an integer and returns a string. Why not.

What I wanted to do was define a type : type TMyFunc = function(inP: Integer) : String;

then define the real functions in each DLL as conforming to the type TMyFunc. That way if I change the definition of TMyFunc, the compiler will let me know because the functions are no longer defined correctly.

Well, to cut a long story short, you can't. You cannot define a function according to a type. Which is a bit of a pain really. Wouldn't be useful to very many people I suppose, but in my case, it would have been great.

So to work around this, I did it another way. In the initialization section of the DLL, I now have a little but of code:

var lMyFunc : TMyFunc;
begin
{$HINTS OFF}
  lMyFunc := MyFunc;
end;

(I turn off the hints so that the compiler won't tell me i have a variable to which I assign a value and then never use it).

So I have a variable of type TMyFunc - a variable which is a function. And I assign a real function (MyFunc) to that variable.

Works perfectly, and if I change the definition of TMyFunc (which is in a shared unit), the compiler will complain that "parameter lists differ". I have to do this manually for all exported functions from my DLL, but it is better than nothing!

Now to continue implementing the stuff. Doing this added quite a few items to my TODO list...and doing this wasn't even ON the TODO list! But having a caller fail because the DLL was compiled with an old version of the interface is not really "cool". I prefer to have the compiler tell me, rather than users...

Progress (20190110)

Quick update. Translations for the following modules are done into French (including of course the modifications in the modules to use the translations):

  • Restore (even though this module is not 'finished'
  • ABLocal (save to a local directory)
  • ABS3 (save to amazon S3)
  • ABFTP (save to an ftp site)

I want to make changes to the translation system to have this handled by configdll, right now each module will have its own copy of all the translation texts, which is not ideal. It won't make any difference to the API interface from the caller, though, which is great.

I've also updated the copyright texts in all modules' build configuration to 2019, fixed a couple of cosmetic bugs I found in those (this is stuff I haven't really looked at for ages). Also made a post-build tool file. And discovered that the service module doesn't have a build file, and the trayicon module needs some work.

I now have a fairly good idea of exactly what is in an unfinished state, as well as the functionalities I need to implement. Since this is a glorified TODO list, I'm working through it slowly, but real progress is being made.

Finally

Translation & Restore

In the time the site was offline, I did quite a bit of work on the restore module.

So now, you can choose which files to restore, either the whole of a directory and its subdirectories, or individual files, or a mixture of both. There's a ice Windows Explorer-like display, which also had an icon next to each directory and filename, showing if this particular item is selected for restore. I'm quite happy with how things are turning out, and especially with the performance of the functions - there's quite a lot of work going on in the background for file selection, so it was important that these functions work quickly.

I've also implemented (for the second time...) a translation system. I didn't like any of the "solutions" I could find on the net, nor the inbuilt translation facilities of Delphi, so I devised my own. Translations are held in a simple ini-style file, and one call will load the file for the current system language, and try to translate a whole form. If the current system language is English, then nothing is done, as all texts are natively in English. Additionally, if no translation is available for a language, then the fallback is English. If not, then the system loads the file and tries to translate everything. Of course this means that translations can be added on the fly, and will just be used if available, with no code changes necessary. It also means that the only tool needed to translate the whole of the system is a simple text editor.