514 lines
9.1 KiB
C++
514 lines
9.1 KiB
C++
#include "rar.hpp"
|
|
|
|
#if defined(_EMX) && !defined(_DJGPP)
|
|
#include "unios2.cpp"
|
|
#endif
|
|
|
|
bool WideToChar(const wchar *Src,char *Dest,size_t DestSize)
|
|
{
|
|
bool RetCode=true;
|
|
#ifdef _WIN_32
|
|
if (WideCharToMultiByte(CP_ACP,0,Src,-1,Dest,(int)DestSize,NULL,NULL)==0)
|
|
RetCode=false;
|
|
#else
|
|
#ifdef _APPLE
|
|
WideToUtf(Src,Dest,DestSize);
|
|
#else
|
|
#ifdef MBFUNCTIONS
|
|
|
|
size_t ResultingSize=wcstombs(Dest,Src,DestSize);
|
|
if (ResultingSize==(size_t)-1)
|
|
RetCode=false;
|
|
if (ResultingSize==0 && *Src!=0)
|
|
RetCode=false;
|
|
|
|
if ((!RetCode || *Dest==0 && *Src!=0) && DestSize>NM && strlenw(Src)<NM)
|
|
{
|
|
/* Workaround for strange Linux Unicode functions bug.
|
|
Some of wcstombs and mbstowcs implementations in some situations
|
|
(we are yet to find out what it depends on) can return an empty
|
|
string and success code if buffer size value is too large.
|
|
*/
|
|
return(WideToChar(Src,Dest,NM));
|
|
}
|
|
|
|
#else
|
|
if (UnicodeEnabled())
|
|
{
|
|
#if defined(_EMX) && !defined(_DJGPP)
|
|
int len=Min(strlenw(Src)+1,DestSize-1);
|
|
if (uni_fromucs((UniChar*)Src,len,Dest,(size_t*)&DestSize)==-1 ||
|
|
DestSize>len*2)
|
|
RetCode=false;
|
|
Dest[DestSize]=0;
|
|
#endif
|
|
}
|
|
else
|
|
for (int I=0;I<DestSize;I++)
|
|
{
|
|
Dest[I]=(char)Src[I];
|
|
if (Src[I]==0)
|
|
break;
|
|
}
|
|
#endif
|
|
#endif
|
|
#endif
|
|
return(RetCode);
|
|
}
|
|
|
|
|
|
bool CharToWide(const char *Src,wchar *Dest,size_t DestSize)
|
|
{
|
|
bool RetCode=true;
|
|
#ifdef _WIN_32
|
|
if (MultiByteToWideChar(CP_ACP,0,Src,-1,Dest,(int)DestSize)==0)
|
|
RetCode=false;
|
|
#else
|
|
#ifdef _APPLE
|
|
UtfToWide(Src,Dest,DestSize);
|
|
#else
|
|
#ifdef MBFUNCTIONS
|
|
|
|
size_t ResultingSize=mbstowcs(Dest,Src,DestSize);
|
|
if (ResultingSize==(size_t)-1)
|
|
RetCode=false;
|
|
if (ResultingSize==0 && *Src!=0)
|
|
RetCode=false;
|
|
|
|
if ((!RetCode || *Dest==0 && *Src!=0) && DestSize>NM && strlen(Src)<NM)
|
|
{
|
|
/* Workaround for strange Linux Unicode functions bug.
|
|
Some of wcstombs and mbstowcs implementations in some situations
|
|
(we are yet to find out what it depends on) can return an empty
|
|
string and success code if buffer size value is too large.
|
|
*/
|
|
return(CharToWide(Src,Dest,NM));
|
|
}
|
|
#else
|
|
if (UnicodeEnabled())
|
|
{
|
|
#if defined(_EMX) && !defined(_DJGPP)
|
|
int len=Min(strlen(Src)+1,DestSize-1);
|
|
if (uni_toucs((char*)Src,len,(UniChar*)Dest,(size_t*)&DestSize)==-1 ||
|
|
DestSize>len)
|
|
DestSize=0;
|
|
RetCode=false;
|
|
#endif
|
|
}
|
|
else
|
|
for (int I=0;I<DestSize;I++)
|
|
{
|
|
Dest[I]=(wchar_t)Src[I];
|
|
if (Src[I]==0)
|
|
break;
|
|
}
|
|
#endif
|
|
#endif
|
|
#endif
|
|
return(RetCode);
|
|
}
|
|
|
|
|
|
byte* WideToRaw(const wchar *Src,byte *Dest,size_t DestSize)
|
|
{
|
|
for (size_t I=0;I<DestSize;I++,Src++)
|
|
{
|
|
Dest[I*2]=(byte)*Src;
|
|
Dest[I*2+1]=(byte)(*Src>>8);
|
|
if (*Src==0)
|
|
break;
|
|
}
|
|
return(Dest);
|
|
}
|
|
|
|
|
|
wchar* RawToWide(const byte *Src,wchar *Dest,size_t DestSize)
|
|
{
|
|
for (size_t I=0;I<DestSize;I++)
|
|
if ((Dest[I]=Src[I*2]+(Src[I*2+1]<<8))==0)
|
|
break;
|
|
return(Dest);
|
|
}
|
|
|
|
|
|
void WideToUtf(const wchar *Src,char *Dest,size_t DestSize)
|
|
{
|
|
long dsize=(long)DestSize;
|
|
dsize--;
|
|
while (*Src!=0 && --dsize>=0)
|
|
{
|
|
uint c=*(Src++);
|
|
if (c<0x80)
|
|
*(Dest++)=c;
|
|
else
|
|
if (c<0x800 && --dsize>=0)
|
|
{
|
|
*(Dest++)=(0xc0|(c>>6));
|
|
*(Dest++)=(0x80|(c&0x3f));
|
|
}
|
|
else
|
|
if (c<0x10000 && (dsize-=2)>=0)
|
|
{
|
|
*(Dest++)=(0xe0|(c>>12));
|
|
*(Dest++)=(0x80|((c>>6)&0x3f));
|
|
*(Dest++)=(0x80|(c&0x3f));
|
|
}
|
|
else
|
|
if (c < 0x200000 && (dsize-=3)>=0)
|
|
{
|
|
*(Dest++)=(0xf0|(c>>18));
|
|
*(Dest++)=(0x80|((c>>12)&0x3f));
|
|
*(Dest++)=(0x80|((c>>6)&0x3f));
|
|
*(Dest++)=(0x80|(c&0x3f));
|
|
}
|
|
}
|
|
*Dest=0;
|
|
}
|
|
|
|
|
|
void UtfToWide(const char *Src,wchar *Dest,size_t DestSize)
|
|
{
|
|
long dsize=(long)DestSize;
|
|
dsize--;
|
|
while (*Src!=0)
|
|
{
|
|
uint c=(byte)*(Src++),d;
|
|
if (c<0x80)
|
|
d=c;
|
|
else
|
|
if ((c>>5)==6)
|
|
{
|
|
if ((*Src&0xc0)!=0x80)
|
|
break;
|
|
d=((c&0x1f)<<6)|(*Src&0x3f);
|
|
Src++;
|
|
}
|
|
else
|
|
if ((c>>4)==14)
|
|
{
|
|
if ((Src[0]&0xc0)!=0x80 || (Src[1]&0xc0)!=0x80)
|
|
break;
|
|
d=((c&0xf)<<12)|((Src[0]&0x3f)<<6)|(Src[1]&0x3f);
|
|
Src+=2;
|
|
}
|
|
else
|
|
if ((c>>3)==30)
|
|
{
|
|
if ((Src[0]&0xc0)!=0x80 || (Src[1]&0xc0)!=0x80 || (Src[2]&0xc0)!=0x80)
|
|
break;
|
|
d=((c&7)<<18)|((Src[0]&0x3f)<<12)|((Src[1]&0x3f)<<6)|(Src[2]&0x3f);
|
|
Src+=3;
|
|
}
|
|
else
|
|
break;
|
|
if (--dsize<0)
|
|
break;
|
|
if (d>0xffff)
|
|
{
|
|
if (--dsize<0 || d>0x10ffff)
|
|
break;
|
|
*(Dest++)=((d-0x10000)>>10)+0xd800;
|
|
*(Dest++)=(d&0x3ff)+0xdc00;
|
|
}
|
|
else
|
|
*(Dest++)=d;
|
|
}
|
|
*Dest=0;
|
|
}
|
|
|
|
|
|
bool UnicodeEnabled()
|
|
{
|
|
#ifdef UNICODE_SUPPORTED
|
|
#ifdef _EMX
|
|
return(uni_ready);
|
|
#else
|
|
return(true);
|
|
#endif
|
|
#else
|
|
return(false);
|
|
#endif
|
|
}
|
|
|
|
|
|
size_t strlenw(const wchar *str)
|
|
{
|
|
size_t length=0;
|
|
while (*(str++)!=0)
|
|
length++;
|
|
return(length);
|
|
}
|
|
|
|
|
|
wchar* strcpyw(wchar *dest,const wchar *src)
|
|
{
|
|
do {
|
|
*(dest++)=*src;
|
|
} while (*(src++)!=0);
|
|
return(dest);
|
|
}
|
|
|
|
|
|
wchar* strncpyw(wchar *dest,const wchar *src,size_t n)
|
|
{
|
|
do {
|
|
*(dest++)=*src;
|
|
} while (*(src++)!=0 && (int)(--n) > 0);
|
|
return(dest);
|
|
}
|
|
|
|
|
|
wchar* strcatw(wchar *dest,const wchar *src)
|
|
{
|
|
return(strcpyw(dest+strlenw(dest),src));
|
|
}
|
|
|
|
|
|
#ifndef SFX_MODULE
|
|
wchar* strncatw(wchar *dest,const wchar *src,size_t n)
|
|
{
|
|
dest+=strlenw(dest);
|
|
while (true)
|
|
if ((int)(--n)<0)
|
|
{
|
|
*dest=0;
|
|
break;
|
|
}
|
|
else
|
|
if ((*(dest++)=*(src++))==0)
|
|
break;
|
|
return(dest);
|
|
}
|
|
#endif
|
|
|
|
|
|
int strcmpw(const wchar *s1,const wchar *s2)
|
|
{
|
|
while (*s1==*s2)
|
|
{
|
|
if (*s1==0)
|
|
return(0);
|
|
s1++;
|
|
s2++;
|
|
}
|
|
return(*s1<*s2 ? -1:1);
|
|
}
|
|
|
|
|
|
int strncmpw(const wchar *s1,const wchar *s2,size_t n)
|
|
{
|
|
while ((int)(n--)>0)
|
|
{
|
|
if (*s1<*s2)
|
|
return(-1);
|
|
if (*s1>*s2)
|
|
return(-1);
|
|
if (*s1==0)
|
|
break;
|
|
s1++;
|
|
s2++;
|
|
}
|
|
return(0);
|
|
}
|
|
|
|
|
|
#ifndef SFX_MODULE
|
|
int stricmpw(const wchar *s1,const wchar *s2)
|
|
{
|
|
char Ansi1[NM*sizeof(wchar)],Ansi2[NM*sizeof(wchar)];
|
|
WideToChar(s1,Ansi1,sizeof(Ansi1));
|
|
WideToChar(s2,Ansi2,sizeof(Ansi2));
|
|
return(stricomp(Ansi1,Ansi2));
|
|
}
|
|
#endif
|
|
|
|
|
|
#if !defined(SFX_MODULE) && !defined(_WIN_CE)
|
|
inline int strnicmpw_w2c(const wchar *s1,const wchar *s2,size_t n)
|
|
{
|
|
wchar Wide1[NM*2],Wide2[NM*2];
|
|
strncpyw(Wide1,s1,sizeof(Wide1)/sizeof(Wide1[0])-1);
|
|
strncpyw(Wide2,s2,sizeof(Wide2)/sizeof(Wide2[0])-1);
|
|
Wide1[Min(sizeof(Wide1)/sizeof(Wide1[0])-1,n)]=0;
|
|
Wide2[Min(sizeof(Wide2)/sizeof(Wide2[0])-1,n)]=0;
|
|
char Ansi1[NM*2],Ansi2[NM*2];
|
|
WideToChar(Wide1,Ansi1,sizeof(Ansi1));
|
|
WideToChar(Wide2,Ansi2,sizeof(Ansi2));
|
|
return(stricomp(Ansi1,Ansi2));
|
|
}
|
|
#endif
|
|
|
|
|
|
#ifndef SFX_MODULE
|
|
int strnicmpw(const wchar *s1,const wchar *s2,size_t n)
|
|
{
|
|
return(strnicmpw_w2c(s1,s2,n));
|
|
}
|
|
#endif
|
|
|
|
|
|
wchar* strchrw(const wchar *s,int c)
|
|
{
|
|
while (*s)
|
|
{
|
|
if (*s==c)
|
|
return((wchar *)s);
|
|
s++;
|
|
}
|
|
return(NULL);
|
|
}
|
|
|
|
|
|
wchar* strrchrw(const wchar *s,int c)
|
|
{
|
|
for (int I=(int)(strlenw(s)-1);I>=0;I--)
|
|
if (s[I]==c)
|
|
return((wchar *)(s+I));
|
|
return(NULL);
|
|
}
|
|
|
|
|
|
wchar* strpbrkw(const wchar *s1,const wchar *s2)
|
|
{
|
|
while (*s1)
|
|
{
|
|
if (strchrw(s2,*s1)!=NULL)
|
|
return((wchar *)s1);
|
|
s1++;
|
|
}
|
|
return(NULL);
|
|
}
|
|
|
|
|
|
#ifndef SFX_MODULE
|
|
wchar* strlowerw(wchar *Str)
|
|
{
|
|
for (wchar *ChPtr=Str;*ChPtr;ChPtr++)
|
|
if (*ChPtr<128)
|
|
*ChPtr=loctolower((byte)*ChPtr);
|
|
return(Str);
|
|
}
|
|
#endif
|
|
|
|
|
|
#ifndef SFX_MODULE
|
|
wchar* strupperw(wchar *Str)
|
|
{
|
|
for (wchar *ChPtr=Str;*ChPtr;ChPtr++)
|
|
if (*ChPtr<128)
|
|
*ChPtr=loctoupper((byte)*ChPtr);
|
|
return(Str);
|
|
}
|
|
#endif
|
|
|
|
|
|
#ifndef SFX_MODULE
|
|
wchar* strdupw(const wchar *Str)
|
|
{
|
|
if (Str==NULL)
|
|
return(NULL);
|
|
wchar *n=(wchar *)malloc((strlenw(Str)+1)*sizeof(wchar));
|
|
if (n==NULL)
|
|
return(NULL);
|
|
strcpyw(n,Str);
|
|
return(n);
|
|
}
|
|
#endif
|
|
|
|
|
|
int toupperw(int ch)
|
|
{
|
|
return((ch<128) ? loctoupper(ch):ch);
|
|
}
|
|
|
|
|
|
int atoiw(const wchar *s)
|
|
{
|
|
int n=0;
|
|
while (*s>='0' && *s<='9')
|
|
{
|
|
n=n*10+(*s-'0');
|
|
s++;
|
|
}
|
|
return(n);
|
|
}
|
|
|
|
|
|
#ifdef DBCS_SUPPORTED
|
|
SupportDBCS gdbcs;
|
|
|
|
SupportDBCS::SupportDBCS()
|
|
{
|
|
Init();
|
|
}
|
|
|
|
|
|
void SupportDBCS::Init()
|
|
{
|
|
CPINFO CPInfo;
|
|
GetCPInfo(CP_ACP,&CPInfo);
|
|
DBCSMode=CPInfo.MaxCharSize > 1;
|
|
for (uint I=0;I<ASIZE(IsLeadByte);I++)
|
|
IsLeadByte[I]=IsDBCSLeadByte(I)!=0;
|
|
}
|
|
|
|
|
|
char* SupportDBCS::charnext(const char *s)
|
|
{
|
|
return (char *)(IsLeadByte[(byte)*s] ? s+2:s+1);
|
|
}
|
|
|
|
|
|
size_t SupportDBCS::strlend(const char *s)
|
|
{
|
|
size_t Length=0;
|
|
while (*s!=0)
|
|
{
|
|
if (IsLeadByte[(byte)*s])
|
|
s+=2;
|
|
else
|
|
s++;
|
|
Length++;
|
|
}
|
|
return(Length);
|
|
}
|
|
|
|
|
|
char* SupportDBCS::strchrd(const char *s, int c)
|
|
{
|
|
while (*s!=0)
|
|
if (IsLeadByte[(byte)*s])
|
|
s+=2;
|
|
else
|
|
if (*s==c)
|
|
return((char *)s);
|
|
else
|
|
s++;
|
|
return(NULL);
|
|
}
|
|
|
|
|
|
void SupportDBCS::copychrd(char *dest,const char *src)
|
|
{
|
|
dest[0]=src[0];
|
|
if (IsLeadByte[(byte)src[0]])
|
|
dest[1]=src[1];
|
|
}
|
|
|
|
|
|
char* SupportDBCS::strrchrd(const char *s, int c)
|
|
{
|
|
const char *found=NULL;
|
|
while (*s!=0)
|
|
if (IsLeadByte[(byte)*s])
|
|
s+=2;
|
|
else
|
|
{
|
|
if (*s==c)
|
|
found=s;
|
|
s++;
|
|
}
|
|
return((char *)found);
|
|
}
|
|
#endif
|