- 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>
246 lines
5.7 KiB
C++
246 lines
5.7 KiB
C++
//----------------------------------------------------------------------------
|
|
// ObjectWindows
|
|
// (C) Copyright 1991, 1994 by Borland International, All Rights Reserved
|
|
//
|
|
// Implementation of class TMenuDescr
|
|
//----------------------------------------------------------------------------
|
|
#pragma hdrignore SECTION
|
|
#include <owl/owlpch.h>
|
|
#include <owl/menu.h>
|
|
#include <owl/module.h>
|
|
|
|
#if !defined(SECTION) || SECTION == 1
|
|
|
|
//
|
|
// Construct a default, empty menu descriptor
|
|
//
|
|
TMenuDescr::TMenuDescr()
|
|
:
|
|
TMenu()
|
|
{
|
|
Id = 0;
|
|
Module = ::Module;
|
|
for (int i = 0; i < NumGroups; i++)
|
|
GroupCount[i] = 0;
|
|
}
|
|
|
|
//
|
|
// Construct a menu descriptor from an existing one
|
|
//
|
|
TMenuDescr::TMenuDescr(const TMenuDescr& other)
|
|
:
|
|
TMenu(other)
|
|
{
|
|
Id = other.Id;
|
|
Module = other.Module;
|
|
for (int i = 0; i < NumGroups; i++)
|
|
GroupCount[i] = other.GroupCount[i];
|
|
}
|
|
|
|
//
|
|
// Construct a menu descriptor from a normal menu resource, supplying group
|
|
// counts here. If the resource has seperators, use those instead of the counts
|
|
//
|
|
TMenuDescr::TMenuDescr(TResId id,
|
|
int fg, int eg, int cg, int og, int wg, int hg,
|
|
TModule* module)
|
|
:
|
|
TMenu(*module, id),
|
|
Module(module),
|
|
Id(id)
|
|
{
|
|
if (!ExtractGroups()) {
|
|
GroupCount[FileGroup] = fg;
|
|
GroupCount[EditGroup] = eg;
|
|
GroupCount[ContainerGroup] = cg;
|
|
GroupCount[ObjectGroup] = og;
|
|
GroupCount[WindowGroup] = wg;
|
|
GroupCount[HelpGroup] = hg;
|
|
}
|
|
}
|
|
|
|
//
|
|
// Construct a menu descriptor from a menu resource with group separators
|
|
// built in (using MF_SEPARATOR)
|
|
//
|
|
TMenuDescr::TMenuDescr(TResId id, TModule* module)
|
|
:
|
|
TMenu(*module, id),
|
|
Module(module),
|
|
Id(id)
|
|
{
|
|
ExtractGroups();
|
|
}
|
|
|
|
//
|
|
// Construct a menu descriptor that is an alias for an existing menu with group
|
|
// information. If the menu has seperators, use those instead of the counts
|
|
//
|
|
TMenuDescr::TMenuDescr(HMENU hMenu,
|
|
int fg, int eg, int cg, int og, int wg, int hg,
|
|
TModule* module)
|
|
:
|
|
TMenu(hMenu, NoAutoDelete),
|
|
Module(module)
|
|
{
|
|
if (!ExtractGroups()) {
|
|
GroupCount[FileGroup] = fg;
|
|
GroupCount[EditGroup] = eg;
|
|
GroupCount[ContainerGroup] = cg;
|
|
GroupCount[ObjectGroup] = og;
|
|
GroupCount[WindowGroup] = wg;
|
|
GroupCount[HelpGroup] = hg;
|
|
}
|
|
}
|
|
|
|
//
|
|
// destructor
|
|
//
|
|
TMenuDescr::~TMenuDescr()
|
|
{
|
|
}
|
|
|
|
//
|
|
// Assign another menu descriptor on to this one
|
|
//
|
|
TMenuDescr&
|
|
TMenuDescr::operator =(const TMenuDescr& other)
|
|
{
|
|
*static_cast<TMenu*>(this) = *static_cast<const TMenu*>(&other);
|
|
Id = other.Id;
|
|
Module = other.Module;
|
|
for (int i = 0; i < NumGroups; i++)
|
|
GroupCount[i] = other.GroupCount[i];
|
|
return *this;
|
|
}
|
|
|
|
//
|
|
// Scan menu looking for separators that signify group divisions
|
|
// return whether we found any at all
|
|
//
|
|
bool
|
|
TMenuDescr::ExtractGroups()
|
|
{
|
|
if (!Handle)
|
|
return false; // no menu to extract from...
|
|
|
|
// walk menu & remove separators, setting up count as we go.
|
|
//
|
|
int itemCount = GetMenuItemCount();
|
|
int g = 0;
|
|
int count = 0;
|
|
for (int i = 0; i < itemCount; ) {
|
|
uint s = GetMenuState(i, MF_BYPOSITION);
|
|
if ((s & MF_SEPARATOR) && !(s & MF_POPUP)) {
|
|
if (g < NumGroups)
|
|
GroupCount[g++] = count;
|
|
count = 0;
|
|
RemoveMenu(i, MF_BYPOSITION);
|
|
itemCount--;
|
|
}
|
|
else {
|
|
i++;
|
|
count++;
|
|
}
|
|
}
|
|
// Leave if no separators were found
|
|
//
|
|
if (!g)
|
|
return false;
|
|
|
|
// Get trailing group
|
|
//
|
|
if (g < NumGroups)
|
|
GroupCount[g++] = count;
|
|
|
|
// Finish zeroing groups
|
|
//
|
|
for (; g < NumGroups; g++)
|
|
GroupCount[g] = 0;
|
|
return true;
|
|
}
|
|
|
|
//
|
|
// Merge another menu descriptor into this menu descriptor
|
|
// Popups are DeepCopied and are then owned by this menu
|
|
// Group counts are merged too.
|
|
//
|
|
bool
|
|
TMenuDescr::Merge(const TMenuDescr& srcMenuDescr)
|
|
{
|
|
int thisOffset = 0;
|
|
int srcOffset = 0;
|
|
|
|
for (int i = 0; i < NumGroups; i++) {
|
|
if (srcMenuDescr.GroupCount[i] != 0) {
|
|
// Delete same menu group in the dest. menudescr.
|
|
for (int j = GroupCount[i] - 1; j >= 0; j--) {
|
|
DeleteMenu(thisOffset+j, MF_BYPOSITION);
|
|
}
|
|
GroupCount[i] = 0;
|
|
|
|
if (srcMenuDescr.GroupCount[i] > 0) {
|
|
DeepCopy(*this, thisOffset, srcMenuDescr, srcOffset, srcMenuDescr.GroupCount[i]);
|
|
srcOffset += srcMenuDescr.GroupCount[i];
|
|
GroupCount[i] += srcMenuDescr.GroupCount[i];
|
|
}
|
|
}
|
|
|
|
if (GroupCount[i] > 0)
|
|
thisOffset += GroupCount[i];
|
|
}
|
|
return true;
|
|
}
|
|
|
|
//
|
|
// Merge another menu descriptor, with this menu descriptor into a third menu
|
|
// Popups are DeepCopied and are then owned by the destMenu.
|
|
//
|
|
bool
|
|
TMenuDescr::Merge(const TMenuDescr& srcMenuDescr, TMenu& dstMenu)
|
|
{
|
|
int thisOffset = 0;
|
|
int srcOffset = 0;
|
|
|
|
for (int i = 0; i < NumGroups; i++) {
|
|
if (srcMenuDescr.GroupCount[i] > 0) {
|
|
DeepCopy(dstMenu, srcMenuDescr, srcOffset, srcMenuDescr.GroupCount[i]);
|
|
srcOffset += srcMenuDescr.GroupCount[i];
|
|
}
|
|
else if (srcMenuDescr.GroupCount[i] == 0 && GroupCount[i] > 0) {
|
|
DeepCopy(dstMenu, *this, thisOffset, GroupCount[i]);
|
|
}
|
|
// else don't copy either
|
|
|
|
if (GroupCount[i] > 0)
|
|
thisOffset += GroupCount[i];
|
|
}
|
|
return true;
|
|
}
|
|
|
|
#endif
|
|
#if !defined(SECTION) || SECTION == 2
|
|
|
|
ipstream& _OWLFUNC
|
|
operator >>(ipstream& is, TMenuDescr& m)
|
|
{
|
|
is >> m.Id;
|
|
is >> m.Module;
|
|
for (int i = 0; i < TMenuDescr::NumGroups; i++)
|
|
is >> m.GroupCount[i];
|
|
return is;
|
|
}
|
|
|
|
opstream& _OWLFUNC
|
|
operator <<(opstream& os, const TMenuDescr& m)
|
|
{
|
|
os << m.Id;
|
|
os << m.Module;
|
|
for (int i = 0; i < TMenuDescr::NumGroups; i++)
|
|
os << m.GroupCount[i];
|
|
return os;
|
|
}
|
|
|
|
|
|
#endif
|