- BORLAND/: Borland C++ 4.52 (chosen over 4.5 by byte-match: CODE/RP/CW32.LIB
is identical to 4.52's install lib). BCC32/TLINK32/TLIB/MAKE run natively on
Win11; CODE/BT/OPT.MAK is the shipped BTL4OPT.EXE's exact flag recipe
(extender = Borland PowerPack DPMI32, not Phar Lap TNT).
- restoration/source410/: the literal 1995-form reconstruction of the missing
BT game source (never mixed into CODE/). Round 1-3 state:
* 6 of 10 surviving original TUs COMPILE CLEAN under the period toolchain
(BTMSSN, BTCNSL, BTSCNRL, BTTEAM, BTL4MODE, BTL4ARND) - first builds
since 1996.
* BT_L4/BTL4APP.CPP pilot reconstruction: 12/12 functions, Fail() lands on
its binary-recorded line 400 exactly.
* BT/BTCNSL.HPP: console wire IDs recovered from the binary's ctors
(Killed=9, Damaged=10, ScoreUpdate=13, DeathWithoutHonor=15 [T1];
TeamScore=12 flagged [T4]).
* MUNGA/: 8 engine-header backfills back-dated from the BT412 WinTesla tree
(VDATA numbering decomp-verified; AUDREND's OpenAL-era virtual removed -
the period compiler is the drift detector).
* Tooling: backdate.py (WinTesla->1995 header transform), compile410.sh
(per-TU verification sweep under authentic OPT.MAK flags).
* README: corrected roadmap - MECH.HPP is the capstone grown with the mech
TU reconstructions; BTREG.CPP green = the header-family milestone.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
469 lines
10 KiB
C++
469 lines
10 KiB
C++
//----------------------------------------------------------------------------
|
|
// (C) Copyright 1994 by Borland International, All Rights Reserved
|
|
//
|
|
// TUString implementation (others functions are inline)
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
#if !defined(_Windows)
|
|
# define _Windows // pretend we are in windows to get the headers we need
|
|
#endif
|
|
#if !defined(INC_OLE2)
|
|
# define INC_OLE2 // Make sure we get Ole2 headers
|
|
#endif
|
|
#include <osl/ustring.h>
|
|
#include <osl/inlines.h>
|
|
#include <string.h>
|
|
|
|
TUString TUString::Null; // null TAutoStrings reference this object
|
|
|
|
#if defined(BI_HAS_WCHAR)
|
|
//
|
|
// Take a wide char string & return an ANSI string in a new'd char[] buffer
|
|
//
|
|
char* TUString::ConvertWtoA(const wchar_t* src, size_t len)
|
|
{
|
|
size_t size = WideCharToMultiByte(CP_ACP, 0, src, len, 0, 0, 0, 0);
|
|
char* dst = new char[size + (len != -1)]; // room for null if fixed size
|
|
size = WideCharToMultiByte(CP_ACP, 0, src, len, dst, size, 0, 0);
|
|
if (len != -1)
|
|
dst[size] = 0;
|
|
return dst;
|
|
}
|
|
|
|
//
|
|
// Take an ANSI char string & return a wide string in a new'd wchar_t[] buffer
|
|
//
|
|
wchar_t* TUString::ConvertAtoW(const char* src, size_t len)
|
|
{
|
|
size_t size = MultiByteToWideChar(CP_ACP, 0, src, len, 0, 0);
|
|
wchar_t* dst = new wchar_t[size + (len != -1)];
|
|
size = MultiByteToWideChar(CP_ACP, 0, src, len, dst, size);
|
|
if (len != -1)
|
|
dst[size] = 0;
|
|
return dst;
|
|
}
|
|
#endif
|
|
|
|
//------------------------------------------------------------------------
|
|
|
|
//
|
|
// Change UString to isCopy regardless of current type
|
|
//
|
|
char* TUString::ChangeToCopy()
|
|
{
|
|
char* dst = 0;
|
|
const char far* src;
|
|
int len;
|
|
switch (Kind) {
|
|
case isNull:
|
|
return 0;
|
|
case isConst:
|
|
src = Const;
|
|
len = strlen(Const);
|
|
break;
|
|
case isCopy:
|
|
return Copy;
|
|
#if defined(BI_HAS_WCHAR)
|
|
case isWConst:
|
|
dst = ConvertWtoA(WConst);
|
|
break;
|
|
case isWCopy:
|
|
dst = ConvertWtoA(WCopy);
|
|
delete [] WCopy;
|
|
break;
|
|
#endif
|
|
#if defined(BI_OLECHAR_WIDE)
|
|
case isBstr:
|
|
case isExtBstr:
|
|
dst = ConvertWtoA(Bstr, ::SysStringLen(Bstr));
|
|
break;
|
|
#else
|
|
case isBstr:
|
|
case isExtBstr:
|
|
src = Bstr;
|
|
len = ::SysStringLen(Bstr);
|
|
break;
|
|
#endif
|
|
case isString:
|
|
src = ((string*)&String)->c_str();
|
|
len = ((string*)&String)->length();
|
|
}
|
|
if (!dst) {
|
|
dst = new char[len+1];
|
|
memcpy(dst, src, len+1);
|
|
}
|
|
if (Kind == isBstr)
|
|
::SysFreeString(Bstr);
|
|
Kind = isCopy;
|
|
Copy = dst;
|
|
return Copy;
|
|
}
|
|
|
|
#if defined(BI_HAS_WCHAR)
|
|
//
|
|
// Change UString to isWCopy regardless of current type
|
|
//
|
|
wchar_t* TUString::ChangeToWCopy()
|
|
{
|
|
wchar_t* dst = 0;
|
|
const wchar_t* src;
|
|
int len;
|
|
switch (Kind) {
|
|
case isNull:
|
|
return 0;
|
|
case isConst:
|
|
dst = ConvertAtoW(Const);
|
|
break;
|
|
case isCopy:
|
|
dst = ConvertAtoW(Copy);
|
|
delete [] Copy;
|
|
break;
|
|
case isWConst:
|
|
src = WConst;
|
|
len = strlen(WConst);
|
|
break;
|
|
case isWCopy:
|
|
return WCopy;
|
|
#if defined(BI_OLECHAR_WIDE)
|
|
case isBstr:
|
|
case isExtBstr:
|
|
src = Bstr;
|
|
len = ::SysStringLen(Bstr);
|
|
if (Kind == isBstr)
|
|
::SysFreeString(Bstr);
|
|
break;
|
|
#else // This case probably never happens
|
|
case isBstr:
|
|
case isExtBstr:
|
|
dst = ConvertAtoW(Bstr, ::SysStringLen(Bstr));
|
|
if (Kind == isBstr)
|
|
::SysFreeString(Bstr);
|
|
break;
|
|
#endif
|
|
case isString:
|
|
dst = ConvertAtoW(((string*)&String)->c_str(), ((string*)&String)->length());
|
|
}
|
|
if (!dst) {
|
|
dst = new wchar_t[len+1];
|
|
memcpy(dst, src, (len+1) * sizeof(wchar_t));
|
|
}
|
|
Kind = isWCopy;
|
|
WCopy = dst;
|
|
return WCopy;
|
|
}
|
|
#endif
|
|
|
|
//------------------------------------------------------------------------
|
|
// inline ctors used by Create functions
|
|
|
|
inline TUString::TUString(const char far& str)
|
|
:
|
|
Kind(isConst), Const(&str), RefCnt(1), Lang(0)
|
|
{
|
|
}
|
|
|
|
inline TUString::TUString(char& str)
|
|
:
|
|
Kind(isCopy), RefCnt(1), Lang(0)
|
|
{
|
|
Copy = new char[strlen(&str)+1];
|
|
strcpy(Copy, &str);
|
|
}
|
|
|
|
#if defined(BI_HAS_WCHAR)
|
|
inline TUString::TUString(const wchar_t& str)
|
|
:
|
|
Kind(isWConst), WConst(&str), RefCnt(1), Lang(0)
|
|
{
|
|
}
|
|
|
|
inline TUString::TUString(wchar_t& str)
|
|
:
|
|
Kind(isWCopy), RefCnt(1), Lang(0)
|
|
{
|
|
WCopy = new wchar_t[strlen(&str)+1];
|
|
strcpy(WCopy, &str);
|
|
}
|
|
#endif
|
|
|
|
inline TUString::TUString(BSTR str, bool loan, TLangId lang)
|
|
:
|
|
Kind(loan ? isExtBstr : isBstr), Bstr(str), RefCnt(loan ? 2 : 1), Lang(lang)
|
|
{
|
|
}
|
|
|
|
inline void* operator new(size_t, TStringRef** p) {return p;}
|
|
|
|
inline TUString::TUString(const string& str)
|
|
:
|
|
Kind(isString), RefCnt(1), Lang(0)
|
|
{
|
|
new(&String) string(str);
|
|
}
|
|
|
|
//------------------------------------------------------------------------
|
|
|
|
TUString* TUString::Create(const char far* str)
|
|
{
|
|
return str && *str ? new TUString(*str) : &++Null;
|
|
}
|
|
|
|
TUString* TUString::Create(char* str)
|
|
{
|
|
return str && *str ? new TUString(*str) : &++Null;
|
|
}
|
|
|
|
#if defined(BI_HAS_WCHAR)
|
|
TUString* TUString::Create(const wchar_t* str)
|
|
{
|
|
return str && *str ? new TUString(*str) : &++Null;
|
|
}
|
|
|
|
TUString* TUString::Create(wchar_t* str)
|
|
{
|
|
return str && *str ? new TUString(*str) : &++Null;
|
|
}
|
|
#endif
|
|
|
|
TUString* TUString::Create(BSTR str, bool loan, TLangId lang)
|
|
{
|
|
if (str && ::SysStringLen(str))
|
|
return new TUString(str, loan, lang);
|
|
if (!loan)
|
|
::SysFreeString(str);
|
|
return &++Null;
|
|
}
|
|
|
|
TUString* TUString::Create(const string& str)
|
|
{
|
|
return str.length() ? new TUString(str) : &++Null;
|
|
}
|
|
|
|
TUString* TUString::Assign(const TUString& s)
|
|
{
|
|
if (RefCnt == 1 && Kind != isNull && Kind != isExtBstr)
|
|
Free();
|
|
else
|
|
--*this;
|
|
|
|
CONST_CAST(TUString&,s).RefCnt++;
|
|
return &CONST_CAST(TUString&,s);
|
|
}
|
|
|
|
TUString* TUString::Assign(const string& s)
|
|
{
|
|
if (s.length() && RefCnt == 1 && Kind != isNull && Kind != isExtBstr) {
|
|
Free();
|
|
Kind = isString;
|
|
new(&String) string(s);
|
|
return this;
|
|
}
|
|
else {
|
|
--*this;
|
|
return Create(s);
|
|
}
|
|
}
|
|
|
|
TUString* TUString::Assign(const char far* s)
|
|
{
|
|
if (s && *s && RefCnt == 1 && Kind != isNull && Kind != isExtBstr) {
|
|
Free();
|
|
Kind = isConst;
|
|
Const = s;
|
|
return this;
|
|
}
|
|
else {
|
|
--*this;
|
|
return Create(s);
|
|
}
|
|
}
|
|
|
|
TUString* TUString::Assign(char* s)
|
|
{
|
|
if (s && *s && RefCnt == 1 && Kind != isNull && Kind != isExtBstr) {
|
|
Free();
|
|
Kind = isCopy;
|
|
Copy = new char[strlen(s)+1];
|
|
strcpy(Copy, s);
|
|
return this;
|
|
}
|
|
else {
|
|
--*this;
|
|
return Create(s);
|
|
}
|
|
}
|
|
|
|
#if defined(BI_HAS_WCHAR)
|
|
TUString* TUString::Assign(const wchar_t* s)
|
|
{
|
|
if (s && *s && RefCnt == 1 && Kind != isNull && Kind != isExtBstr) {
|
|
Free();
|
|
Kind = isWConst;
|
|
WConst = s;
|
|
return this;
|
|
}
|
|
else {
|
|
--*this;
|
|
return Create(s);
|
|
}
|
|
}
|
|
|
|
TUString* TUString::Assign(wchar_t* s)
|
|
{
|
|
if (s && *s && RefCnt == 1 && Kind != isNull && Kind != isExtBstr) {
|
|
Free();
|
|
Kind = isWCopy;
|
|
WCopy = new wchar_t[strlen(s)+1];
|
|
strcpy(WCopy, s);
|
|
return this;
|
|
}
|
|
else {
|
|
--*this;
|
|
return Create(s);
|
|
}
|
|
}
|
|
#endif
|
|
|
|
TUString* TUString::Assign(BSTR str, TLangId lang)
|
|
{
|
|
if (RefCnt==1 && Kind != isNull && Kind != isExtBstr) {
|
|
Free();
|
|
Kind = isBstr;
|
|
Bstr = str;
|
|
Lang = lang;
|
|
if (Bstr && ::SysStringLen(Bstr))
|
|
return this;
|
|
delete this;
|
|
return &++Null;
|
|
}
|
|
else {
|
|
--*this;
|
|
return Create(str, false, lang);
|
|
}
|
|
}
|
|
|
|
TUString::operator const char far*() const
|
|
{
|
|
switch (Kind) {
|
|
case isNull: return 0;
|
|
case isConst: return Const;
|
|
case isCopy: return Copy;
|
|
case isString: return ((string*)&String)->c_str();
|
|
#if defined(BI_OLECHAR_WIDE)
|
|
case isBstr:
|
|
case isExtBstr: return CONST_CAST(TUString*,this)->ChangeToCopy();
|
|
#else
|
|
case isBstr:
|
|
case isExtBstr: return Bstr;
|
|
#endif
|
|
case isWConst:
|
|
case isWCopy: return CONST_CAST(TUString*,this)->ChangeToCopy();
|
|
}
|
|
return 0; // suppress warning
|
|
}
|
|
|
|
TUString::operator char*()
|
|
{
|
|
return ChangeToCopy();
|
|
}
|
|
|
|
#if defined(BI_HAS_WCHAR)
|
|
TUString::operator const wchar_t*() const
|
|
{
|
|
switch (Kind) {
|
|
case isNull: return 0;
|
|
case isWConst: return WConst;
|
|
case isWCopy: return WCopy;
|
|
#if defined(BI_OLECHAR_WIDE)
|
|
case isBstr:
|
|
case isExtBstr: return Bstr;
|
|
#else
|
|
case isBstr:
|
|
case isExtBstr: return CONST_CAST(TUString*,this)->ChangeToWCopy();
|
|
#endif
|
|
case isConst:
|
|
case isCopy:
|
|
case isString: return CONST_CAST(TUString*,this)->ChangeToWCopy();
|
|
}
|
|
return 0; // suppress warning
|
|
}
|
|
|
|
TUString::operator wchar_t*()
|
|
{
|
|
return ChangeToWCopy();
|
|
}
|
|
#endif
|
|
|
|
//
|
|
//
|
|
//
|
|
int TUString::Length() const
|
|
{
|
|
switch (Kind) {
|
|
case isNull: return 0;
|
|
#if defined(BI_HAS_WCHAR)
|
|
case isWConst: return strlen(WConst);
|
|
case isWCopy: return strlen(WCopy);
|
|
#endif
|
|
case isBstr:
|
|
case isExtBstr: return ::SysStringLen(Bstr);
|
|
case isConst: return strlen(Const);
|
|
case isCopy: return strlen(Copy);
|
|
case isString: return ((string*)&String)->length();
|
|
}
|
|
return 0; // suppress warning
|
|
}
|
|
|
|
//
|
|
// Revokes BSTR ownership from this UString
|
|
//
|
|
void TUString::RevokeBstr(BSTR s)
|
|
{
|
|
if (Kind != isExtBstr || Bstr != s)
|
|
return;
|
|
if (RefCnt == 1) {
|
|
Kind = isNull;
|
|
delete this;
|
|
return;
|
|
}
|
|
Kind = isCopy;
|
|
#if defined(BI_OLECHAR_WIDE)
|
|
WCopy = new wchar_t[strlen(s)+1];
|
|
strcpy(WCopy, s);
|
|
#else
|
|
Copy = new char[strlen(s)+1];
|
|
strcpy(Copy, s);
|
|
#endif
|
|
}
|
|
|
|
//
|
|
// Passes BSTR ownership to this UString
|
|
//
|
|
void TUString::ReleaseBstr(BSTR s)
|
|
{
|
|
if (Kind == isExtBstr && Bstr == s) {
|
|
Kind = isBstr;
|
|
--*this;
|
|
}
|
|
else // has been overwritten with converted type
|
|
::SysFreeString(Bstr);
|
|
}
|
|
|
|
//
|
|
// Free any resources held by this UString. Union & Kind left in random state;
|
|
// must be reinitialized before use.
|
|
//
|
|
void TUString::Free()
|
|
{
|
|
switch (Kind) {
|
|
case isCopy: delete [] Copy; break;
|
|
#if defined(BI_HAS_WCHAR)
|
|
case isWCopy: delete [] WCopy; break;
|
|
#endif
|
|
case isBstr: ::SysFreeString(Bstr); break;
|
|
case isString: ((string*)&String)->string::~string();
|
|
}
|
|
Lang = 0;
|
|
//Kind = isNull; // for safety, not really needed
|
|
}
|