Subversion Repositories fastphp

Rev

Rev 61 | Rev 75 | Go to most recent revision | Blame | Compare with Previous | Last modification | View Log | RSS feed

  1. unit Functions;
  2.  
  3. interface
  4.  
  5. uses
  6.   Windows, Messages, SysUtils, StrUtils, IniFiles, Classes, Forms, Variants, MsHTML,
  7.   StdCtrls, SynEdit, ActiveX;
  8.  
  9. type
  10.   TContentCallBack = procedure(Content: string) of object;
  11.  
  12. function GetDosOutput(CommandLine: string; Work: string = ''; ContentCallBack: TContentCallBack=nil): string;
  13. function StrIPos(const SubStr, S: string): Integer;
  14. function LoadFileToStr(const FileName: TFileName): AnsiString;
  15. function LastPos(const SubStr, S: string): integer;
  16. function IsTextHTML(s: string): boolean;
  17. function GetWordUnderPos(AMemo: TSynEdit; Line, Column: integer): string;
  18. function GetWordUnderCaret(AMemo: TSynEdit): string;
  19. function MyVarToStr(v: Variant): string;
  20. function FileSystemCaseSensitive: boolean;
  21. function HighColorWindows: boolean;
  22. function GetTempDir: string;
  23. function GetSpecialFolder(const aCSIDL: Integer): string;
  24. function GetMyDocumentsFolder: string;
  25. function StrHash(const st:string): cardinal;
  26.  
  27. implementation
  28.  
  29. uses
  30.   ShlObj; // Needed for the CSIDL constants
  31.  
  32. function GetDosOutput(CommandLine: string; Work: string = ''; ContentCallBack: TContentCallBack=nil): string;
  33. var
  34.   SA: TSecurityAttributes;
  35.   SI: TStartupInfo;
  36.   PI: TProcessInformation;
  37.   StdOutPipeRead, StdOutPipeWrite: THandle;
  38.   WasOK: Boolean;
  39.   Buffer: array[0..255] of AnsiChar;
  40.   BytesRead: Cardinal;
  41.   WorkDir: string;
  42.   Handle: Boolean;
  43. begin
  44.   if Work = '' then Work := ExtractFilePath(ParamStr(0));
  45.  
  46.   Result := '';
  47.   with SA do begin
  48.     nLength := SizeOf(SA);
  49.     bInheritHandle := True;
  50.     lpSecurityDescriptor := nil;
  51.   end;
  52.   CreatePipe(StdOutPipeRead, StdOutPipeWrite, @SA, 0);
  53.   try
  54.     with SI do
  55.     begin
  56.       FillChar(SI, SizeOf(SI), 0);
  57.       cb := SizeOf(SI);
  58.       dwFlags := STARTF_USESHOWWINDOW or STARTF_USESTDHANDLES;
  59.       wShowWindow := SW_HIDE;
  60.       hStdInput := GetStdHandle(STD_INPUT_HANDLE); // don't redirect stdin
  61.       hStdOutput := StdOutPipeWrite;
  62.       hStdError := StdOutPipeWrite;
  63.     end;
  64.     WorkDir := Work;
  65.     Handle := CreateProcess(nil, PChar('cmd.exe /C "' + CommandLine + '"'),
  66.                             nil, nil, True, 0, nil,
  67.                             PChar(WorkDir), SI, PI);
  68.     CloseHandle(StdOutPipeWrite);
  69.     if Handle then
  70.       try
  71.         repeat
  72.           WasOK := ReadFile(StdOutPipeRead, Buffer, 255, BytesRead, nil);
  73.           if BytesRead > 0 then
  74.           begin
  75.             Buffer[BytesRead] := #0;
  76.             Result := Result + Buffer;
  77.             if Assigned(ContentCallBack) then ContentCallBack(Buffer);
  78.           end;
  79.         until not WasOK or (BytesRead = 0);
  80.         WaitForSingleObject(PI.hProcess, INFINITE);
  81.       finally
  82.         CloseHandle(PI.hThread);
  83.         CloseHandle(PI.hProcess);
  84.       end;
  85.   finally
  86.     CloseHandle(StdOutPipeRead);
  87.   end;
  88. end;
  89.  
  90. function StrIPos(const SubStr, S: string): Integer;
  91. begin
  92.   Result := Pos(UpperCase(SubStr), UpperCase(S));
  93. end;
  94.  
  95. function LoadFileToStr(const FileName: TFileName): AnsiString;
  96. var
  97.   FileStream : TFileStream;
  98.  
  99. begin
  100.   Result:= '';
  101.   FileStream:= TFileStream.Create(FileName, fmOpenRead or fmShareDenyWrite);
  102.   try
  103.     if FileStream.Size>0 then begin
  104.       SetLength(Result, FileStream.Size);
  105.       FileStream.Read(Result[1], FileStream.Size);
  106.     end;
  107.   finally
  108.     FileStream.Free;
  109.   end;
  110. end;
  111.  
  112. function LastPos(const SubStr, S: string): integer;
  113. var
  114.   I, J, K: integer;
  115. begin
  116.   Result := 0;
  117.   I := Length(S);
  118.   K := Length(SubStr);
  119.   if (K = 0) or (K > I) then
  120.     Exit;
  121.   while (Result = 0) and (I >= K) do
  122.   begin
  123.     J := K;
  124.     if S[I] = SubStr[J] then
  125.     begin
  126.       while (J > 1) and (S[I + J - K - 1] = SubStr[J - 1]) do
  127.         Dec(J);
  128.       if J = 1 then
  129.         Result := I - K + 1;
  130.     end;
  131.     Dec(I);
  132.   end;
  133. end;
  134.  
  135. function IsTextHTML(s: string): boolean;
  136.  
  137.   function _Tag(const tag: string): integer;
  138.   begin
  139.     result := 0;
  140.     if (StrIPos('<'+tag+'>', s) > 0) then Inc(result);
  141.     if (StrIPos('</'+tag+'>', s) > 0) then Inc(result);
  142.     if (StrIPos('<'+tag+' />', s) > 0) then Inc(result);
  143.     if (StrIPos('<'+tag+' ', s) > 0) then Inc(result);
  144.   end;
  145.  
  146.   procedure _Check(const tag: string; pair: boolean);
  147.   begin
  148.     if (pair and (_Tag(tag) >= 2)) or (not pair and (_Tag(tag) >= 1)) then result := true;
  149.   end;
  150.  
  151. begin
  152.   result := false;
  153.   _Check('html', true);
  154.   _Check('body', true);
  155.   _Check('p', false{end tag optional});
  156.   _Check('a', true);
  157.   _Check('b', true);
  158.   _Check('i', true);
  159.   _Check('u', true);
  160.   _Check('li', false{end tag optional});
  161.   _Check('ol', true);
  162.   _Check('ul', true);
  163.   _Check('img', false);
  164.   _Check('div', false);
  165.   _Check('hr', false);
  166.   _Check('code', true);
  167.   _Check('pre', true);
  168.   _Check('blockquote', true);
  169.   _Check('span', true);
  170.   _Check('br', false);
  171. end;
  172.  
  173. // Template: http://stackoverflow.com/questions/6339446/delphi-get-the-whole-word-where-the-caret-is-in-a-memo
  174. function GetWordUnderPos(AMemo: TSynEdit; Line, Column: integer): string;
  175.  
  176.   function ValidChar(c: char): boolean;
  177.   begin
  178.     {$IFDEF UNICODE}
  179.     result := CharInSet(c, ['a'..'z', 'A'..'Z', '0'..'9', '_']);
  180.     {$ELSE}
  181.     result := c in ['a'..'z', 'A'..'Z', '0'..'9', '_'];
  182.     {$ENDIF}
  183.   end;
  184.  
  185. var
  186.    LineText: string;
  187.    InitPos : Integer;
  188.    EndPos  : Integer;
  189. begin
  190.    //Validate the line number
  191.    if AMemo.Lines.Count-1 < Line then Exit;
  192.  
  193.    //Get the text of the line
  194.    LineText := AMemo.Lines[Line];
  195.  
  196.    if LineText = '' then
  197.    begin
  198.      result := '';
  199.      exit;
  200.    end;
  201.  
  202.    // Column zeigt auf das Zeichen LINKS vom Cursor!
  203.  
  204.    InitPos := Column;
  205.    if not ValidChar(LineText[InitPos]) then Inc(InitPos);
  206.    while (InitPos-1 >= 1) and ValidChar(LineText[InitPos-1]) do Dec(InitPos);
  207.  
  208.    EndPos := Column;
  209.    while (EndPos+1 <= Length(LineText)) and ValidChar(LineText[EndPos+1]) do Inc(EndPos);
  210.  
  211.    //Get the text
  212.    Result := Copy(LineText, InitPos, EndPos - InitPos + 1);
  213. end;
  214.  
  215. function GetWordUnderCaret(AMemo: TSynEdit): string;
  216. var
  217.    Line    : Integer;
  218.    Column  : Integer;
  219. begin
  220.    //Get the caret position
  221.    (*
  222.    if AMemo is TMemo then
  223.    begin
  224.      Line   := AMemo.Perform(EM_LINEFROMCHAR,AMemo.SelStart, 0);
  225.      Column := AMemo.SelStart - AMemo.Perform(EM_LINEINDEX, Line, 0);
  226.    end;
  227.    if AMemo is TSynEdit then
  228.    begin
  229.    *)
  230.      Line := AMemo.CaretY-1;
  231.      Column := AMemo.CaretX-1;
  232.    (*
  233.    end;
  234.    *)
  235.  
  236.    result := GetWordUnderPos(AMemo, Line, Column);
  237. end;
  238.  
  239. function MyVarToStr(v: Variant): string;
  240. var
  241.   _Lo, _Hi, i: integer;
  242. begin
  243.   if VarIsNull(v) then
  244.   begin
  245.     result := '';
  246.   end
  247.   else if VarIsArray(v) then
  248.   begin
  249.     _Lo := VarArrayLowBound(v, 1);
  250.     _Hi := VarArrayHighBound(v, 1);
  251.     result := '';
  252.     for i := _Lo to _Hi do
  253.     begin
  254.       if v[i] = 0 then break;
  255.       result := result + chr(integer(v[i]));
  256.     end;
  257.   end
  258.   else
  259.   begin
  260.     // At least try it...
  261.     result := VarToStr(v);
  262.   end;
  263. end;
  264.  
  265. function FileSystemCaseSensitive: boolean;
  266. begin
  267.   // TODO: This code is not very reliable. At MAC OSX, the file system HFS can be switched
  268.   //       between case sensitivity and insensitivity.
  269.   {$IFDEF LINUX}
  270.   exit(true);
  271.   {$ELSE}
  272.   result := false;
  273.   exit;
  274.   {$ENDIF}
  275. end;
  276.  
  277. function HighColorWindows: boolean;
  278. var
  279.   ver: Cardinal;
  280.   dwMajorVersion, dwMinorVersion: integer;
  281. begin
  282.   ver := GetVersion();
  283.   dwMajorVersion := Lo(ver);
  284.   dwMinorVersion := Hi(ver);
  285.  
  286.   // Gradient fitting in:
  287.   // 5.1 = XP
  288.   // 5.2 = Windows Server 2003
  289.   // 6.0 = Vista
  290.   // 6.1 = Win7
  291.  
  292.   result := ((dwMajorVersion = 5) and (dwMinorVersion >= 1)) or
  293.             ((dwMajorVersion = 6) and (dwMinorVersion <= 1));
  294. end;
  295.  
  296. function GetTempDir: string;
  297. var
  298.   Dir: string;
  299.   Len: DWord;
  300. begin
  301.   SetLength(Dir,MAX_PATH);
  302.   Len:=GetTempPath(MAX_PATH, PChar(Dir));
  303.   if Len>0 then
  304.   begin
  305.     SetLength(Dir,Len);
  306.     Result:=Dir;
  307.   end
  308.   else
  309.     RaiseLastOSError;
  310. end;
  311.  
  312. function SHGetFolderPath(hwnd: HWND; csidl: Integer; hToken: THandle;
  313.   dwFlags: DWord; pszPath: LPWSTR): HRESULT; stdcall;
  314.   external 'SHFolder.dll' name 'SHGetFolderPathW';
  315.  
  316. function GetSpecialFolder(const aCSIDL: Integer): string;
  317. var
  318.   FolderPath: array[0 .. MAX_PATH] of Char;
  319. begin
  320.   SetLastError(ERROR_SUCCESS);
  321.   if SHGetFolderPath(0, aCSIDL, 0, 0, @FolderPath) = S_OK then
  322.     Result := FolderPath;
  323. end;
  324.  
  325. function GetMyDocumentsFolder: string;
  326. begin
  327.   Result := GetSpecialFolder(CSIDL_PERSONAL);
  328. end;
  329.  
  330. function StrHash(const st:string): cardinal;
  331. var
  332.   i:integer;
  333. begin
  334.   // https://stackoverflow.com/a/41400477/488539
  335.   result := 0;
  336.   for i := 1 to length(st) do
  337.     result := result*$20844 xor byte(st[i]);
  338. end;
  339.  
  340. end.
  341.