diff options
Diffstat (limited to 'UCoreUtils.pas')
| -rw-r--r-- | UCoreUtils.pas | 153 |
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 + '<' else if Str[i] = '>' then Result := Result + '>' else if Str[i] = '&' then Result := Result + '&' 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; |
