mirror of
https://github.com/doublecmd/doublecmd.git
synced 2026-06-21 09:58:13 +00:00
FIX #1680: Internal Viewer crashes on macOS
in FPC 3.2.2, there are some bugs in Iconvert(). use the fixed Iconvert() instead of the FPC version on macOS.
This commit is contained in:
parent
044706b658
commit
01c8c0c81b
5 changed files with 190 additions and 21 deletions
|
|
@ -68,11 +68,11 @@ implementation
|
|||
|
||||
uses
|
||||
{$IF DEFINED(UNIX)}
|
||||
iconvenc_dyn, LazUTF8
|
||||
LazUTF8
|
||||
{$IF DEFINED(DARWIN)}
|
||||
, MacOSAll, CocoaAll, StrUtils
|
||||
, dc_iconvenc_dyn, MacOSAll, CocoaAll, StrUtils
|
||||
{$ELSE}
|
||||
, UnixCP
|
||||
, iconvenc_dyn, UnixCP
|
||||
{$ENDIF}
|
||||
{$ELSEIF DEFINED(MSWINDOWS)}
|
||||
Windows
|
||||
|
|
|
|||
|
|
@ -8,6 +8,8 @@
|
|||
<Version Value="11"/>
|
||||
<PathDelim Value="\"/>
|
||||
<SearchPaths>
|
||||
<IncludeFiles Value="iconvenc"/>
|
||||
<OtherUnitFiles Value="iconvenc"/>
|
||||
<UnitOutputDirectory Value="lib\$(TargetCPU)-$(TargetOS)"/>
|
||||
</SearchPaths>
|
||||
<Conditionals Value="if (TargetCPU <> 'arm') then
|
||||
|
|
@ -35,7 +37,7 @@ end"/>
|
|||
<Description Value="Common units for Double Commander"/>
|
||||
<License Value="GNU GPL 2"/>
|
||||
<Version Minor="4" Release="1"/>
|
||||
<Files Count="12">
|
||||
<Files Count="14">
|
||||
<Item1>
|
||||
<Filename Value="dcclassesutf8.pas"/>
|
||||
<UnitName Value="DCClassesUtf8"/>
|
||||
|
|
@ -84,6 +86,14 @@ end"/>
|
|||
<Filename Value="dcjsonconfig.pas"/>
|
||||
<UnitName Value="DCJsonConfig"/>
|
||||
</Item12>
|
||||
<Item13>
|
||||
<Filename Value="iconvenc\dc_iconvert.inc"/>
|
||||
<Type Value="Include"/>
|
||||
</Item13>
|
||||
<Item14>
|
||||
<Filename Value="iconvenc\dc_iconvenc_dyn.pas"/>
|
||||
<UnitName Value="dc_iconvenc_dyn"/>
|
||||
</Item14>
|
||||
</Files>
|
||||
<CompatibilityMode Value="True"/>
|
||||
<RequiredPkgs Count="2">
|
||||
|
|
|
|||
|
|
@ -1,17 +1,17 @@
|
|||
{ This file was automatically created by Lazarus. Do not edit!
|
||||
This source is only used to compile and install the package.
|
||||
}
|
||||
|
||||
unit doublecmd_common;
|
||||
|
||||
{$warn 5023 off : no warning about unused units}
|
||||
interface
|
||||
|
||||
uses
|
||||
DCClassesUtf8, DCOSUtils, DCStrUtils, DCBasicTypes, DCFileAttributes,
|
||||
DCConvertEncoding, DCDateTimeUtils, DCXmlConfig, DCProcessUtf8,
|
||||
DCUnicodeUtils, DCStringHashListUtf8, DCJsonConfig;
|
||||
|
||||
implementation
|
||||
|
||||
end.
|
||||
{ This file was automatically created by Lazarus. Do not edit!
|
||||
This source is only used to compile and install the package.
|
||||
}
|
||||
|
||||
unit doublecmd_common;
|
||||
|
||||
{$warn 5023 off : no warning about unused units}
|
||||
interface
|
||||
|
||||
uses
|
||||
DCClassesUtf8, DCOSUtils, DCStrUtils, DCBasicTypes, DCFileAttributes,
|
||||
DCConvertEncoding, DCDateTimeUtils, DCXmlConfig, DCProcessUtf8,
|
||||
DCUnicodeUtils, DCStringHashListUtf8, DCJsonConfig, dc_iconvenc_dyn;
|
||||
|
||||
implementation
|
||||
|
||||
end.
|
||||
|
|
|
|||
106
components/doublecmd/iconvenc/dc_iconvenc_dyn.pas
Normal file
106
components/doublecmd/iconvenc/dc_iconvenc_dyn.pas
Normal file
|
|
@ -0,0 +1,106 @@
|
|||
{
|
||||
This file is part of the Free Pascal run time library.
|
||||
Copyright (c) 2000 by Marco van de Voort(marco@freepascal.org)
|
||||
member of the Free Pascal development team
|
||||
|
||||
libiconv header translation + a helper routine
|
||||
http://wiki.freepascal.org/iconvenc Dynamic version
|
||||
|
||||
See the file COPYING.FPC, included in this distribution,
|
||||
for details about the copyright. (LGPL)
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
||||
|
||||
}
|
||||
unit dc_iconvenc_dyn;
|
||||
|
||||
interface
|
||||
{$mode objfpc}{$H+}
|
||||
|
||||
uses
|
||||
ctypes,unixtype,baseunix,
|
||||
dl,
|
||||
initc;
|
||||
|
||||
const
|
||||
n = 1;
|
||||
|
||||
{$ifdef beos}
|
||||
ESysEILSEQ = EILSEQ;
|
||||
{$endif}
|
||||
|
||||
type
|
||||
piconv_t = ^iconv_t;
|
||||
iconv_t = pointer;
|
||||
|
||||
Ticonv_open = function(__tocode: pchar; __fromcode: pchar): iconv_t; cdecl;
|
||||
Ticonv = function(__cd: iconv_t; __inbuf: ppchar; __inbytesleft: psize_t; __outbuf: ppchar; __outbytesleft: psize_t): size_t; cdecl;
|
||||
Ticonv_close = function(__cd: iconv_t): cint; cdecl;
|
||||
|
||||
var
|
||||
iconv_lib: pointer;
|
||||
iconv_open: Ticonv_open;
|
||||
iconv: Ticonv;
|
||||
iconv_close: Ticonv_close;
|
||||
IconvLibFound: boolean = False;
|
||||
|
||||
function TryLoadLib(LibName: string; var error: string): boolean; // can be used to load non standard libname
|
||||
function Iconvert(s: string; var res: string; const FromEncoding, ToEncoding: string): cint;
|
||||
function InitIconv(var error: string): boolean;
|
||||
|
||||
implementation
|
||||
|
||||
function TryLoadLib(LibName: string; var error: string): boolean;
|
||||
|
||||
function resolvesymbol (var funcptr; symbol: string): Boolean;
|
||||
begin
|
||||
pointer(funcptr) := pointer(dlsym(iconv_lib, pchar(symbol)));
|
||||
result := assigned(pointer(funcptr));
|
||||
if not result then
|
||||
error := error+#13#10+dlerror();
|
||||
end;
|
||||
|
||||
var
|
||||
res: boolean;
|
||||
begin
|
||||
result := false;
|
||||
Error := Error+#13#10'Trying '+LibName;
|
||||
iconv_lib := dlopen(pchar(libname), RTLD_NOW);
|
||||
if Assigned(iconv_lib) then
|
||||
begin
|
||||
result := true;
|
||||
result := result and resolvesymbol(pointer(iconv),'iconv');
|
||||
result := result and resolvesymbol(pointer(iconv_open),'iconv_open');
|
||||
result := result and resolvesymbol(pointer(iconv_close),'iconv_close');
|
||||
if not result then
|
||||
begin
|
||||
result:=true;
|
||||
result := result and resolvesymbol(pointer(iconv),'libiconv');
|
||||
result := result and resolvesymbol(pointer(iconv_open),'libiconv_open');
|
||||
result := result and resolvesymbol(pointer(iconv_close),'libiconv_close');
|
||||
end;
|
||||
// if not res then
|
||||
// dlclose(iconv_lib);
|
||||
end else
|
||||
error:=error+#13#10+dlerror();
|
||||
end;
|
||||
|
||||
|
||||
function InitIconv(var error: string): boolean;
|
||||
begin
|
||||
result := true;
|
||||
error := '';
|
||||
if not TryLoadLib('libc.so.6', error) then
|
||||
if not TryLoadLib('libiconv.so', error) then
|
||||
{$if defined(haiku)}
|
||||
if not TryLoadLib('libtextencoding.so', error) then
|
||||
{$ifend}
|
||||
result := false;
|
||||
iconvlibfound := iconvlibfound or result;
|
||||
end;
|
||||
|
||||
{$i dc_iconvert.inc}
|
||||
|
||||
end.
|
||||
53
components/doublecmd/iconvenc/dc_iconvert.inc
Normal file
53
components/doublecmd/iconvenc/dc_iconvert.inc
Normal file
|
|
@ -0,0 +1,53 @@
|
|||
function Iconvert(S: string; var Res: string; const FromEncoding, ToEncoding: string): cint;
|
||||
var
|
||||
InLen, OutLen, Offset: size_t;
|
||||
Src, Dst: pchar;
|
||||
H: iconv_t;
|
||||
lerr: cint;
|
||||
iconvres: size_t;
|
||||
begin
|
||||
H := iconv_open(PChar(ToEncoding), PChar(FromEncoding));
|
||||
if h=Iconv_t(-1) then
|
||||
begin
|
||||
Res := S;
|
||||
exit(-1);
|
||||
end;
|
||||
|
||||
try
|
||||
InLen:=Length(s);
|
||||
outlen:=InLen;
|
||||
setlength(res,outlen);
|
||||
|
||||
Src := PChar(S);
|
||||
Dst := PChar(Res);
|
||||
|
||||
while InLen > 0 do
|
||||
begin
|
||||
iconvres := iconv(H, @Src, @InLen, @Dst, @OutLen);
|
||||
if iconvres = size_t(-1) then
|
||||
begin
|
||||
lerr := cerrno;
|
||||
if lerr = ESysEILSEQ then // unknown char, skip
|
||||
begin
|
||||
Inc(Src);
|
||||
Dec(InLen);
|
||||
end
|
||||
else
|
||||
if lerr = ESysE2BIG then
|
||||
begin
|
||||
Offset := Dst - PChar(Res);
|
||||
SetLength(Res, Length(Res)+InLen*2+5); // 5 is minimally one utf-8 char
|
||||
Dst := PChar(Res) + Offset;
|
||||
OutLen := Length(Res) - Offset;
|
||||
end
|
||||
else
|
||||
exit(-1)
|
||||
end;
|
||||
end;
|
||||
finally
|
||||
setlength(Res,Length(Res) - Outlen);
|
||||
iconv_close(H);
|
||||
end;
|
||||
|
||||
Result := 0;
|
||||
end;
|
||||
Loading…
Add table
Add a link
Reference in a new issue