Files
TeslaRel410/BORLAND/BC45/SOURCE/OWL/STATUSBA.CPP
T
CydandClaude Fable 5 63312e07f9 source410: literal 4.10 source reconstruction + BC++ 4.52 fleet toolchain archived
- 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>
2026-07-19 07:33:26 -05:00

343 lines
9.1 KiB
C++

//----------------------------------------------------------------------------
// ObjectWindows
// (C) Copyright 1992, 1994 by Borland International, All Rights Reserved
//
// Implementation of TStatusBar
//----------------------------------------------------------------------------
#include <owl/owlpch.h>
#include <owl/statusba.h>
#include <owl/statusba.rh>
//
// Local class to manage the mode indicator strings
//
class TModeStrings {
public:
// constructor
TModeStrings() : ModeBuff(0), ModeStrings(0), NumModes(0) {}
~TModeStrings()
{
delete [] ModeBuff;
delete [] ModeStrings;
}
void Init(TModule* module, uint16 resId, const char* defaultModes);
// access
int Count() const { return NumModes; }
const char* operator [](int i) const { return ModeStrings[i]; }
private:
int NumModes;
char* ModeBuff;
char** ModeStrings;
};
//
// Gets the mode string array from a single resource string, like:
// "EXT|CAPS|NUM|SCRL|OVR|REC"
// using the provided default string if resource not found.
//
void
TModeStrings::Init(TModule* module, uint16 resId, const char* defaultModes)
{
if (!ModeStrings) {
string modeResString(module->LoadString(resId));
ModeBuff = strnewdup(modeResString.length() > 0 ?
modeResString.c_str() :
defaultModes);
NumModes = 1;
for (char* p = ModeBuff; *p; p++)
if (*p == '|') {
*p = 0;
NumModes++;
}
typedef char* pchar;
ModeStrings = new pchar[NumModes];
p = ModeBuff;
for (int i = 0; i < NumModes; i++) {
ModeStrings[i] = p;
p += strlen(p) + 1;
}
}
}
//
// Static mode string object, & default mode indicator strings
//
static TModeStrings ModeOnStrings;
static TModeStrings ModeOffStrings;
static char DefOnModes[] = "EXT|CAPS|NUM|SCRL|OVR|REC";
static char DefOffModes[] = " | | | | | ";
IMPLEMENT_CASTABLE(TStatusBar);
TStatusBar::TStatusBar(TWindow* parent,
TGadget::TBorderStyle borderStyle,
uint modeIndicators,
TFont* font,
TModule* module)
:
TMessageBar(parent, font, module)
{
BorderStyle = borderStyle;
ModeIndicators = modeIndicators;
ModeIndicatorState = 0;
NumModeIndicators = 0;
ModeOnStrings.Init(GetModule(), IDS_MODES, DefOnModes);
ModeOffStrings.Init(GetModule(), IDS_MODESOFF, DefOffModes);
if (BorderStyle == TGadget::Plain || BorderStyle == TGadget::Embossed)
HighlightLine = false;
else
Spacing.Value = 2; // Hilight line + 1/4-em margin on raised & recessed
switch (BorderStyle) {
case TGadget::Raised:
case TGadget::Recessed:
//
// we want one border height along the top and bottom and 1/2 an em quad
// along the left and right so we will set pixels and compute the lengths
// ourselves
//
Margins.Units = TMargins::Pixels;
Margins.Left = Margins.Right = LayoutUnitsToPixels(4);
Margins.Top = Margins.Bottom = GetSystemMetrics(SM_CYBORDER);
break;
case TGadget::Plain:
Margins.Units = TMargins::BorderUnits;
Margins.Left = Margins.Top = Margins.Right = Margins.Bottom = -1;
break;
}
Gadgets->SetBorderStyle(BorderStyle); // Set border style for first gadget
//
// create text gadgets for any mode indicators the user requested,
// using provided border style.
//
TScreenDC dc;
dc.SelectObject(*Font);
for (int i = 0; i < ModeOnStrings.Count(); i++)
if (ModeIndicators & (1 << i)) {
const int SMALL_MARGIN = 1;
int maxLen = max(strlen(ModeOnStrings[i]), strlen(ModeOffStrings[i]));
TTextGadget* gadget = new TTextGadget(0, BorderStyle,
TTextGadget::Left, maxLen,
ModeOffStrings[i]);
TMargins margins = gadget->GetMargins();
//
// use small left and right margins
//
margins.Left = margins.Right = SMALL_MARGIN;
gadget->SetMargins(margins);
//
// turn off shrink wrapping for the width and choose a width that is
// custom fit for the string
//
gadget->SetShrinkWrap(false, true);
TMessageBar::Insert(*gadget);
TSize onExtent;
dc.GetTextExtent(ModeOnStrings[i], strlen(ModeOnStrings[i]), onExtent);
TSize offExtent;
dc.GetTextExtent(ModeOffStrings[i], strlen(ModeOffStrings[i]), offExtent);
TSize extent(max(onExtent.cx, offExtent.cx), onExtent.cy);
int left, top, right, bottom;
gadget->GetOuterSizes(left, right, top, bottom);
extent.cx += left + right;
gadget->SetSize(extent);
NumModeIndicators++;
}
}
bool
TStatusBar::IsModeIndicator(TGadget* gadget)
{
int nonModeIndicators = NumGadgets - NumModeIndicators;
TGadget* g = Gadgets;
for (int i = 0; i < nonModeIndicators; i++) {
if (gadget == g)
return false;
g = g->NextGadget();
}
return true;
}
//
//
//
void
TStatusBar::PositionGadget(TGadget*, TGadget* next, TPoint& origin)
{
int cxBorder = GetSystemMetrics(SM_CXBORDER);
if (BorderStyle == TGadget::Plain)
origin.x -= cxBorder; // overlap the borders
//
// leave extra spacing between the mode indicators
//
if (IsModeIndicator(next))
switch (Spacing.Units) {
case TMargins::Pixels:
origin.x += Spacing.Value;
break;
case TMargins::LayoutUnits:
origin.x += LayoutUnitsToPixels(Spacing.Value);
break;
case TMargins::BorderUnits:
origin.x += Spacing.Value * cxBorder;
break;
}
}
//
// insert a gadget. default placement is just after the gadget to the left of
// the status mode indicators
//
void
TStatusBar::Insert(TGadget& gadget, TPlacement placement, TGadget* sibling)
{
gadget.SetBorderStyle(BorderStyle);
if (!sibling)
sibling = operator[](NumGadgets - NumModeIndicators - 1);
TMessageBar::Insert(gadget, placement, sibling);
}
//
// return gadget at a given index, except mode indicator gadgets
//
TGadget*
TStatusBar::operator [](uint index)
{
PRECONDITION(index < NumGadgets - NumModeIndicators);
for (TGadget* g = Gadgets; index > 0; index--)
g = g->NextGadget();
return g;
}
//
// Get the text gadget & the mode string associated with a mode indicator
//
bool
TStatusBar::GetGadgetAndStrings(TModeIndicator mode, TTextGadget*& gadget,
const char*& strOn, const char*& strOff)
{
if ((ModeIndicators & mode) == 0) {
return false; // tracing
}
else {
uint slot = NumGadgets - 1;
for (int index = ModeOnStrings.Count() - 1; (1 << index) > mode; index--)
if (ModeIndicators & (1 << index))
slot--;
strOn = ModeOnStrings[index];
strOff = ModeOffStrings[index];
for (gadget = (TTextGadget*)Gadgets; slot > 0; slot--)
gadget = (TTextGadget*)gadget->NextGadget();
return true;
}
}
void
TStatusBar::ToggleModeIndicator(TModeIndicator mode)
{
SetModeIndicator(mode, !GetModeIndicator(mode));
}
void
TStatusBar::SetModeIndicator(TModeIndicator mode, bool on)
{
TTextGadget* gadget;
const char* strOn;
const char* strOff;
if (GetGadgetAndStrings(mode, gadget, strOn, strOff))
gadget->SetText(on ? strOn : strOff);
if (on)
ModeIndicatorState |= mode;
else
ModeIndicatorState &= ~mode;
}
bool
TStatusBar::PreProcessMsg(MSG& msg)
{
if (msg.message == WM_KEYDOWN) {
switch (msg.wParam) {
case VK_SCROLL:
if (ModeIndicators & ScrollLock) {
//ScrollLockModeChange();
ToggleModeIndicator(ScrollLock);
}
break;
case VK_INSERT:
if (ModeIndicators & Overtype) {
//
// Skip if CTRL+INS or SHIFT+INS
//
if (((::GetKeyState(VK_CONTROL) & 0x8000) == 0) &&
((::GetKeyState(VK_SHIFT) & 0x8000) == 0))
//OvertypeModeChange();
ToggleModeIndicator(Overtype);
}
break;
case VK_CAPITAL:
if (ModeIndicators & CapsLock)
ToggleModeIndicator(CapsLock);
break;
case VK_NUMLOCK:
if (ModeIndicators & NumLock)
ToggleModeIndicator(NumLock);
break;
}
}
return false;
}
//
// Make sure that we are in sync with the physical KB indicators
//
bool
TStatusBar::IdleAction(long idleCount)
{
if (idleCount == 0) {
if ((::GetKeyState(VK_SCROLL) & 0x0001) != GetModeIndicator(ScrollLock))
ToggleModeIndicator(ScrollLock);
if ((::GetKeyState(VK_CAPITAL) & 0x0001) != GetModeIndicator(CapsLock))
ToggleModeIndicator(CapsLock);
if ((::GetKeyState(VK_NUMLOCK) & 0x0001) != GetModeIndicator(NumLock))
ToggleModeIndicator(NumLock);
}
return TMessageBar::IdleAction(idleCount);
}