summaryrefslogtreecommitdiff
path: root/UCoreUtils.pas
diff options
context:
space:
mode:
Diffstat (limited to 'UCoreUtils.pas')
-rw-r--r--UCoreUtils.pas153
1 files changed, 123 insertions, 30 deletions
diff --git a/UCoreUtils.pas b/UCoreUtils.pas
index 0e12550..1781a41 100644
--- a/UCoreUtils.pas
+++ b/UCoreUtils.pas
@@ -91,7 +91,7 @@ procedure ShowAbout;
procedure TrimCRLFESC(var s: string);
procedure TrimQuotes(var s: string);
function QuoteStr(const Str: string): string;
-function QuoteMarkupStr(const Str: string): string;
+function QuoteMarkupStr(const Str: string; MarkupUnderscore: boolean = False): string;
function QuotePercentStr(const Str: string): string;
function RemoveQuotation(const Str: string): string;
function GetStrSize(s: string): Int64;
@@ -119,6 +119,14 @@ function UnixToDateTime(const AValue: Int64): TDateTime;
procedure SaveItemToHistory(s: string; History: TStringList);
+// All the UTF-8 conversion functions do strdup()
+function StrToUTF8(s: string): string; overload;
+function UTF8ToStr(s: string): string; overload;
+function StrToUTF8(s: PChar): PChar; overload;
+function UTF8ToStr(s: PChar): PChar; overload;
+// function EnsureUTF8String(s: string): string; overload;
+function EnsureUTF8String(s: PChar): PChar; overload;
+
// Calculate CRC32 Checksum, CRC is default $FFFFFFFF,
@@ -149,7 +157,7 @@ uses DateUtils, GTKForms, GTKUtils, GTKView, ULocale, UConfig, UCore, UGnome, UM
(********************************************************************************************************************************)
function GetErrorString(ErrorNo: integer): string;
begin
- if ErrorNo >= 0 then Result := String(strerror(ErrorNo))
+ if ErrorNo >= 0 then Result := StrToUTF8(String(strerror(ErrorNo)))
else
case ErrorNo of
ERRException : Result := LANGUnknownException;
@@ -161,7 +169,7 @@ end;
(********************************************************************************************************************************)
function GetSignalString(SignalNo: integer): string;
begin
- Result := strsignal(SignalNo);
+ Result := StrToUTF8(strsignal(SignalNo));
end;
(********************************************************************************************************************************)
@@ -430,8 +438,8 @@ begin
MaxInputWord := Length(InputStr);
MaxWilds := Length(Wilds);
if IgnoreCase then begin { upcase all letters }
- InputStr := AnsiUpperCase(InputStr);
- Wilds := AnsiUpperCase(Wilds);
+ InputStr := WideUpperCase(InputStr);
+ Wilds := WideUpperCase(Wilds);
end;
if (MaxWilds = 0) or (MaxInputWord = 0) then begin
Result := False;
@@ -639,7 +647,7 @@ var Path : string;
function CaseDirExists(DPath, DFileName: string): boolean;
begin
- if (AnsiCompareStr(Pattern, FileName) <> 0) and (AnsiCompareText(Pattern, FileName) = 0) and Directory and
+ if (WideCompareStr(Pattern, FileName) <> 0) and (WideCompareText(Pattern, FileName) = 0) and Directory and
Engine.TwoSameFiles(DPath + Pattern, DPath + FileName)
then Result := False
else Result := Engine.DirectoryExists(DPath + DFileName);
@@ -765,7 +773,7 @@ begin
end;
(********************************************************************************************************************************)
-function QuoteMarkupStr(const Str: string): string;
+function QuoteMarkupStr(const Str: string; MarkupUnderscore: boolean = False): string;
var i: integer;
begin
Result := '';
@@ -774,7 +782,7 @@ begin
if Str[i] = '<' then Result := Result + '&#60;' else
if Str[i] = '>' then Result := Result + '&#62;' else
if Str[i] = '&' then Result := Result + '&amp;' else
-// if Str[i] = '_' then Result := Result + '__' else
+ if (Str[i] = '_') and MarkupUnderscore then Result := Result + '__' else
Result := Result + Str[i];
end;
end;
@@ -847,7 +855,7 @@ var i: integer;
begin
Result := 0;
x := 0;
- s := AnsiUpperCase(Trim(s));
+ s := WideUpperCase(Trim(s));
if Length(s) = 0 then Exit;
for i := Length(s) downto 1 do
if s[i] in [#32, ThousandSeparator] then Delete(s, i, 1);
@@ -1041,6 +1049,7 @@ begin
Result := False;
try
DebugMsg(['*** Running ExecuteProgram begin']);
+// DebugMsg(['ExecuteProgram: ConfTerminalCommand = "', ConfTerminalCommand, '"']);
s := Trim(AppCMDLine);
ErrorSignal := 0;
Term := RunInTerminal;
@@ -1211,7 +1220,7 @@ begin
end;
Result := Length(s) = 0;
- if not Result then Application.MessageBox(Format('%s%s', [ErrorText, ANSIToUTF8(s)]), [mbOK], mbError, mbOK, mbOK);
+ if not Result then Application.MessageBox(Format('%s%s', [ErrorText, StrToUTF8(s)]), [mbOK], mbError, mbOK, mbOK);
except
on E: Exception do DebugMsg(['***** function HandleSystemCommand(''', Command, '''):Exception: ', E.Message]);
end;
@@ -1262,40 +1271,40 @@ begin
if Data2^.IsDir and (not Data1^.IsDir) then Result := 1*mp else
case SortColumnID of
1, 2 : begin
- Result := CompareTextsEx(Data1^.AName, Data2^.AName);
+ Result := CompareTextsEx(Data1^.FDisplayName, Data2^.FDisplayName);
if Data1^.IsDir and Data2^.IsDir then Result := Result * mp;
end;
- 3 : if Data1^.IsDir and Data2^.IsDir then Result := CompareTextsEx(Data1^.AName, Data2^.AName)*mp else begin
- SeparateExt(String(Data1^.AName), s1, s2);
- SeparateExt(String(Data2^.AName), s3, s4);
- if ANSIUpperCase(s2) <> ANSIUpperCase(s4)
+ 3 : if Data1^.IsDir and Data2^.IsDir then Result := CompareTextsEx(Data1^.FDisplayName, Data2^.FDisplayName)*mp else begin
+ SeparateExt(String(Data1^.FDisplayName), s1, s2);
+ SeparateExt(String(Data2^.FDisplayName), s3, s4);
+ if WideUpperCase(s2) <> WideUpperCase(s4)
then Result := CompareTextsEx(PChar(s2), PChar(s4))
else Result := CompareTextsEx(PChar(s1), PChar(s3));
end;
- 4 : if Data1^.IsDir and Data2^.IsDir then Result := CompareTextsEx(Data1^.AName, Data2^.AName)*mp else
+ 4 : if Data1^.IsDir and Data2^.IsDir then Result := CompareTextsEx(Data1^.FDisplayName, Data2^.FDisplayName)*mp else
if Data1^.Size > Data2^.Size then Result := -1 else
if Data1^.Size < Data2^.Size then Result := 1 else
- Result := CompareTextsEx(Data1^.AName, Data2^.AName);
- 5, 6 : if Data1^.IsDir and Data2^.IsDir then Result := CompareTextsEx(Data1^.AName, Data2^.AName)*mp else
+ Result := CompareTextsEx(Data1^.FDisplayName, Data2^.FDisplayName);
+ 5, 6 : if Data1^.IsDir and Data2^.IsDir then Result := CompareTextsEx(Data1^.FDisplayName, Data2^.FDisplayName)*mp else
if Data1^.ModifyTime > Data2^.ModifyTime then Result := -1 else
if Data1^.ModifyTime < Data2^.ModifyTime then Result := 1 else
- Result := CompareTextsEx(Data1^.AName, Data2^.AName);
- 7 : if Data1^.IsDir and Data2^.IsDir then Result := CompareTextsEx(Data1^.AName, Data2^.AName)*mp else
+ Result := CompareTextsEx(Data1^.FDisplayName, Data2^.FDisplayName);
+ 7 : if Data1^.IsDir and Data2^.IsDir then Result := CompareTextsEx(Data1^.FDisplayName, Data2^.FDisplayName)*mp else
if Frac(Data1^.ModifyTime) > Frac(Data2^.ModifyTime) then Result := -1 else
if Frac(Data1^.ModifyTime) < Frac(Data2^.ModifyTime) then Result := 1 else
- Result := CompareTextsEx(Data1^.AName, Data2^.AName);
- 8 : if Data1^.IsDir and Data2^.IsDir then Result := CompareTextsEx(Data1^.AName, Data2^.AName)*mp else
+ Result := CompareTextsEx(Data1^.FDisplayName, Data2^.FDisplayName);
+ 8 : if Data1^.IsDir and Data2^.IsDir then Result := CompareTextsEx(Data1^.FDisplayName, Data2^.FDisplayName)*mp else
if Data1^.UID > Data2^.UID then Result := -1 else
if Data1^.UID < Data2^.UID then Result := 1 else
- Result := CompareTextsEx(Data1^.AName, Data2^.AName);
- 9 : if Data1^.IsDir and Data2^.IsDir then Result := CompareTextsEx(Data1^.AName, Data2^.AName)*mp else
+ Result := CompareTextsEx(Data1^.FDisplayName, Data2^.FDisplayName);
+ 9 : if Data1^.IsDir and Data2^.IsDir then Result := CompareTextsEx(Data1^.FDisplayName, Data2^.FDisplayName)*mp else
if Data1^.GID > Data2^.GID then Result := -1 else
if Data1^.GID < Data2^.GID then Result := 1 else
- Result := CompareTextsEx(Data1^.AName, Data2^.AName);
- 10 : if Data1^.IsDir and Data2^.IsDir then Result := CompareTextsEx(Data1^.AName, Data2^.AName)*mp else
+ Result := CompareTextsEx(Data1^.FDisplayName, Data2^.FDisplayName);
+ 10 : if Data1^.IsDir and Data2^.IsDir then Result := CompareTextsEx(Data1^.FDisplayName, Data2^.FDisplayName)*mp else
if Data1^.Mode > Data2^.Mode then Result := -1 else
if Data1^.Mode < Data2^.Mode then Result := 1 else
- Result := CompareTextsEx(Data1^.AName, Data2^.AName);
+ Result := CompareTextsEx(Data1^.FDisplayName, Data2^.FDisplayName);
else Result := 0;
end;
end;
@@ -1331,6 +1340,90 @@ begin
QuickSort(0, List.Count - 1);
end;
+
+
+(********************************************************************************************************************************)
+function StrToUTF8(s: string): string;
+begin
+ Result := String(StrToUTF8(PChar(s)));
+end;
+
+function UTF8ToStr(s: string): string;
+var bytes_read, bytes_written: gsize;
+ error: PGError;
+begin
+ error := nil;
+ bytes_read := 0;
+ bytes_written := 0;
+ Result := g_locale_from_utf8(PChar(s), Length(s), @bytes_read, @bytes_written, @error);
+ if error <> nil then begin
+ // fallback to original string to avoid data loss
+ Result := s;
+ DebugMsg(['*** UTF8ToStr: error converting "', s, '" from UTF-8 (read ', bytes_read, ', written ', bytes_written, '): ', error^.message]);
+ g_error_free(error);
+ end;
+end;
+
+function StrToUTF8(s: PChar): PChar;
+var bytes_read, bytes_written: gsize;
+ error: PGError;
+ ns: PChar;
+ m: PChar;
+begin
+ if g_utf8_validate(s, strlen(s), nil) then begin
+ Result := g_strndup(s, strlen(s));
+ Exit;
+ end;
+// DebugMsg(['StrToUTF8: string "', s, '" is not valid UTF-8.']);
+ error := nil;
+ bytes_read := 0;
+ bytes_written := 0;
+ ns := g_locale_to_utf8(s, strlen(s), @bytes_read, @bytes_written, @error);
+ if ns = nil then begin
+ // fallback to original string to avoid data loss
+ ns := g_strdup(s);
+ if error <> nil then m := error^.message
+ else m := 'unknown';
+ DebugMsg(['*** StrToUTF8: error converting "', s, '" to UTF-8 (read ', bytes_read, ', written ', bytes_written, '): ', m]);
+ g_error_free(error);
+ end;
+ if @g_filename_display_name <> nil then begin
+ Result := g_filename_display_name(ns);
+ g_free(ns);
+ end else Result := ns;
+end;
+
+function UTF8ToStr(s: PChar): PChar;
+var bytes_read, bytes_written: gsize;
+ error: PGError;
+begin
+ error := nil;
+ bytes_read := 0;
+ bytes_written := 0;
+ Result := g_locale_from_utf8(s, strlen(s), @bytes_read, @bytes_written, @error);
+ if error <> nil then begin
+ // fallback to original string to avoid data loss
+ Result := s;
+ DebugMsg(['*** UTF8ToStr: error converting "', s, '" from UTF-8 (read ', bytes_read, ', written ', bytes_written, '): ', error^.message]);
+ g_error_free(error);
+ end;
+end;
+
+{
+function EnsureUTF8String(s: string): string;
+begin
+ Result := s;
+ if @g_filename_display_name <> nil then Result := g_filename_display_name(PChar(s));
+end;
+}
+
+function EnsureUTF8String(s: PChar): PChar;
+begin
+ Result := s;
+ if @g_filename_display_name <> nil then Result := g_filename_display_name(s);
+end;
+
+
(********************************************************************************************************************************)
{$IFDEF CPU64}
function CRC32(CRC: LongWord; Data: Pointer; DataSize: LongWord): LongWord;
@@ -1435,10 +1528,10 @@ begin
end;
function THash_MD5.DigestKey: string;
-type TCharArray = array[1..40] of char;
- PCharArray = ^TCharArray;
+type TxCharArray = array[1..40] of char;
+ PxCharArray = ^TxCharArray;
begin
- Result := Copy(PCharArray(@FDigest)^, 1, 16);
+ Result := Copy(PxCharArray(@FDigest)^, 1, 16);
end;
procedure THash_MD5.Init;