Hi,
In the topic "[solved] LoadFromFile : Load a UTF8 file content as a string" I made a function to load a file (UTF8) into a string.
It works but is very slow : 58 seconds for a file of 400Ko.

I made the same in C# (and call it from MVD), the job is done in less than 1s (?!).

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.IO;
using System.Text;

namespace ConsoleApplication1
{
    class Program
    {
        static void Main(string[] args)
        {
            var utf8 = File.ReadAllText("rss.xml");
            using (StreamWriter sw = new StreamWriter(File.Open("rss.out", FileMode.Create), Encoding.Unicode))
            {
                sw.WriteLine(utf8);
            }
        }
    }
}

Dmitry could you, please, include fast native functions to encode/decode UTF8 string (previously loaded with TFileStream) ?

Regards,
jihem

Hi,

Now, with the update (36b), I have the same result with HTTPGetFile and WriteLnFile, so the first point is solved.
Thanks :-)

I didn't find a function to decode the UTF8 file so I wrote my own.
Sample of use : ShowMessage(LoadFromFileUTF8('rss.xml'));

Regards,
jihem

function DecodeUTF8(const s:string):string;
var
  c0,c1,c2,c3,c,i,n,m,p:Integer;
  o0,o1,o2:Integer;
  b1,b2,b3:Boolean;
begin
  Result:='';

  if (Ord(s[p]) and 255)=0 then
  begin
    i:=2;
  end
  else
  begin
    i:=1;
  end;

  n:=Length(s);
  while i<=n do
  begin
    p:=i shr 1;
    m:=i and 1;

    o0:=Ord(s[p]);
    o1:=Ord(s[p+1]);
    if m=0 then
    begin
      c0:=o0 and 255;
      c1:=o0 shr 8;
      c2:=o1 and 255;
      c3:=o1 shr 8;
    end
    else
    begin
      o2:=Ord(s[p+2]);
      c0:=o0 shr 8;
      c1:=o1 and 255;
      c2:=o1 shr 8;
      c3:=o2 and 255;
    end;
    b1:=c1>=128;
    b2:=c2>=128;
    b3:=c3>=128;

    if (c0>=240) and b1 and b2 and b3 then
    begin
      c:=(((c0 and 15) shl 6) or ((c1 and 127)) shr 12) or ((c2 and 127) shl 6) or (c3 and 127);
      inc(i,4);
    end
    else
    begin
      if (c0>=224) and b1 and b2 then
      begin
        c:=((c0 and 31) shr 12) or ((c1 and 127) shl 6) or (c2 and 127);
        inc(i,3);
      end
      else
      begin
        if (c0>=192) and b1 then
        begin
          c:=((c0 and 63) shl 6) or (c1 and 127);
          inc(i,2);
        end
        else
        begin
          c:=c0 and 127;
          inc(i);
        end;
      end;
    end;
    Result:=Result+Chr(c);
  end;
end;

function LoadFromFileUTF8 (FileName: string):string;
var
  l:integer;
  s:string;
  fs:TFileStream;
begin
  l:=GetFileSize(FileName);
  if l>0 then
  begin
    fs:=TFileStream.Create(FileName,fmOpenRead );
    fs.Position := 0;
    SetLength(s,l); // l div 2+1);
    fs.Read(s, l);
    fs.Free;
    Result:=DecodeUTF8(s);
  end
  else
    Result:='';
end;

Hi,

1°) The two following commands download a file. The content isn't the same (characters encoding problem?)

HTTPGetFile('http://radiofrance-podcast.net/podcast09/rss_10175.xml','rss.xml',false);

WriteLnToFile('rss.xml',HTTPGet('http://radiofrance-podcast.net/podcast09/rss_10175.xml'));

2°) When I try to load the content of the file with :

sl:=TStringList.Create;
sl.LoadFromFile('rss.xml');

The content (UTF-8) isn't properly decoded. Sample:
'D├®bat de quarante minutes abordant les grandes questions actuelles'
instead of
'Débat de quarante minutes abordant les grandes questions actuelles'

How can I solve this problem? Is there a way to specify the encoding of the loaded file (ie. sl.LoadFromFile('rss.xml','utf-8') ?

Kind regards,
jihem

29

(1 replies, posted in Script)

Hi,
ShowMessage(IntToStr(MonthsBetween(EncodeDate(2017,1,1),EncodeDate(2016,1,1))));  ==> 12
ShowMessage(IntToStr(MonthsBetween(EncodeDate(2017,2,1),EncodeDate(2016,2,1))));  ==> 12
ShowMessage(IntToStr(MonthsBetween(EncodeDate(2017,3,1),EncodeDate(2016,3,1))));  ==> 11
...
ShowMessage(IntToStr(MonthsBetween(EncodeDate(2017,12,1),EncodeDate(2016,12,1))));  ==> 11

That's weird... but
ShowMessage(IntToStr(MonthsBetween(EncodeDate(2017,1,2),EncodeDate(2016,1,1))));  ==> 12
...
ShowMessage(IntToStr(MonthsBetween(EncodeDate(2017,12,2),EncodeDate(2016,1,1))));  ==> 12

So if you want to count the month add a day to the ANow parameter.

This occurs because : MonthsBetween returns the number of whole months between ANow and AThen. This number is an approximation, based on an average number of days of 30.4375 per month (average over 4 years). This means the fractional part of a month is dropped (==> https://www.freepascal.org/docs-html/rt … tween.html.

Use this function (==> http://www.delphigroups.info/2/5b/290654.html) :

function MonthsBetweenEx(date1, date2: TDateTime): integer;
var
  y1, m1, d1, y2, m2, d2, year: word;
  dt1, dt2: TDateTime;
begin 
  If date1 > date2 then begin
    dt1 := date2; 
    dt2 := date1; 
  end else begin 
    dt1 := date1; 
    dt2 := date2; 
  end; 
  DecodeDate(dt1, y1, m1, d1); 
  DecodeDate(dt2, y2, m2, d2); 
  Result := 0; 
  if y1 = y2 then begin 
    // Same year 
    if m1 = m2 then begin 
      // Same month 
      Result := 0; 
    end else begin 
      Result := m2 - m1; 
      // More days in month 1 than 2, decrement by one. 
      if d1 > d2 then inc(Result, -1); 
    end; 
  end else begin
    // Years not equal.
    Result := m2 - m1 + ((y2 - y1) * 12);
    if d1 > d2 then inc(Result, -1); 
  end; 
end;


Kind regards,
jihem

30

(4 replies, posted in General)

Hi,
Usually the usb barcode scanners are recognised as keyboards (or have a keyboard driver). In this case, the only thing you have to do is to create a form with an edit field. It must have the focus when you scan (Form1.Edit1.SetFocus in the Form1_OnShow event). Sometime the scanner use a special character before sending the barcode value. You can test it using OnKeyDown event on the form and all its components to set focus on the appropriate edit field. You can use the same procedure for all the OnShow properties.
Kind regards,
jihem

31

(7 replies, posted in General)

@manixs2013
Hi,
This works here (azerty keyboard / w10). While editing I can move the selected column back and forth. I'm stuck on the dblclick. I don't know how to send it to the TableGrid.
Kind regards,
jihem

32

(1 replies, posted in General)

Hi,
As far as I know you can't use assembly code in a MVD script.
Regards,
jihem

33

(7 replies, posted in General)

procedure Form1_TableGrid1_OnKeyDown (Sender: string; var Key: Word; Shift, Alt, Ctrl: boolean);
begin
    if (Key=112) then
    begin
        if ((Form1.TableGrid1.SelectedColumn)>0) then
        begin
            Form1.TableGrid1.SelectedColumn:=Form1.TableGrid1.SelectedColumn-1;
        end
    end;
    if (Key=113) then
    begin
        if ((Form1.TableGrid1.SelectedColumn+2)<Form1.TableGrid1.Columns.Count) then
        begin
            Form1.TableGrid1.SelectedColumn:=Form1.TableGrid1.SelectedColumn+1;
        end;
    end
end;

This function (to add in the script) allows to go from one cell :
- to the next with [F2]
- to the previous with [F1]

[Tab] key doesn't trigger the KeyDown event.

I was looking how to switch the target cell in edit mode without success.
I would like to send a dblclick windows message but SendMessage doesn't exist...

34

(6 replies, posted in General)

Hi Yann,
Thanks for all these advices. I began to read a lot of posts in the script section (and to download the provided projects).
I found a lot of things I'm interested in: database encryption, how to use grids with our own SQL statements, ...
That sounds good for me.
Kind regards,
jihem

35

(6 replies, posted in General)

Very nice :-) I'm an old delphi user (delphi 1, 2, 3 and 4). I switched to WinDev (because I was tired to rewrite or buy components because each version came with its own report editor and tcp/ip components). I wrote some apps in LiveCode (until the incredible price rise). I was looking for a good IDE with local (sqlite) and remote database access (mariadb) using a compiled language (without having to eat noddles for months). And I found MVD. I tried it some days and finally bought a licence ($99). I hope I could change to lifetime later when I save more money (we all have a fridge to fill and kids to feed). I found your documentation very useful. Is there a french website or blog somewhere (about MVD) ? In the next coming weeks, I may have scripts to share (oldies from delphi, translated from LiveCode and WinDev). Thanks Yann (If you're near Nantes may be we can drink a beer ?)