Files
TeslaRel410/BORLAND/BC45/SOURCE/OWL/SCROLLER.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

396 lines
9.0 KiB
C++

//----------------------------------------------------------------------------
// ObjectWindows
// (C) Copyright 1991, 1994 by Borland International, All Rights Reserved
//
// Implementation of class TScroller.
//----------------------------------------------------------------------------
#pragma hdrignore SECTION
#include <owl/owlpch.h>
#include <owl/scroller.h>
#include <owl/window.h>
#include <owl/dc.h>
#include <stdlib.h>
#define max(a,b) (((a) > (b)) ? (a) : (b))
#define min(a,b) (((a) < (b)) ? (a) : (b))
#define abs(a) ((a) >= 0 ? (a) : -(a))
#if !defined(SECTION) || SECTION == 1
//
// constructs a TScroller object
//
TScroller::TScroller(TWindow* window,
int xUnit,
int yUnit,
long xRange,
long yRange)
{
Window = window;
XPos = YPos = 0;
XUnit = xUnit;
YUnit = yUnit;
XRange = xRange;
YRange = yRange;
XLine = 1; YLine = 1;
XPage = 1; YPage = 1;
AutoMode = true;
TrackMode = true;
AutoOrg = true;
HasHScrollBar = ToBool(Window && (Window->Attr.Style&WS_HSCROLL));
HasVScrollBar = ToBool(Window && (Window->Attr.Style&WS_VSCROLL));
}
//
// destructs a TScroller object
//
// sets owning Window's Scroller member to 0
//
TScroller::~TScroller()
{
if (Window)
Window->Scroller = 0;
}
//
// sets the number of units per page (amount by which to scroll on a page
// scroll request) according to the current size of the Window's client area
//
void
TScroller::SetPageSize()
{
if (Window) {
TRect clientRect;
Window->GetClientRect(clientRect);
int width = clientRect.Width();
int height = clientRect.Height();
if (width && XUnit > 0)
XPage = max(1, (width+1) / XUnit - 1);
if (height && YUnit > 0)
YPage = max(1, (height+1) / YUnit - 1);
}
}
//
// sets the range of the TScroller and also sets the range of its
// Window's scrollbars
//
void
TScroller::SetRange(long xRange, long yRange)
{
XRange = xRange;
YRange = yRange;
SetSBarRange();
ScrollTo(XPos, YPos);
}
//
// resets the X and Y scroll unit size (in device units) to the passed
// parameters
//
// calls SetPageSize to update the X and Y page size, which are specified
// in scroll units
//
void
TScroller::SetUnits(int xUnit, int yUnit)
{
XUnit = xUnit;
YUnit = yUnit;
SetPageSize();
}
//
// sets the range of the Window's scrollbars & repaints as necessary
//
void
TScroller::SetSBarRange()
{
if (Window) {
if (HasHScrollBar) {
int curMin, curMax;
Window->GetScrollRange(SB_HORZ, curMin, curMax);
int newMax = max(0, (int)min(XRange, SHRT_MAX));
if (newMax != curMax || curMin != 0)
Window->SetScrollRange(SB_HORZ, 0, newMax, true);
}
if (HasVScrollBar) {
int curMin, curMax;
Window->GetScrollRange(SB_VERT, curMin, curMax);
int newMax = max(0, (int)min(YRange, SHRT_MAX));
if (newMax != curMax || curMin != 0)
Window->SetScrollRange(SB_VERT, 0, newMax, true);
}
}
}
//
// sets the origin for the paint display context according to XPos, YPos
//
void
TScroller::BeginView(TDC& dc, TRect& rect)
{
long xOrg = XPos * XUnit;
long yOrg = YPos * YUnit;
if (AutoOrg && xOrg <= SHRT_MAX && yOrg <= SHRT_MAX) {
TPoint offset(int(-xOrg), int(-yOrg));
dc.SetViewportOrg(offset);
rect -= offset;
}
}
//
// updates the position of the Window's scrollbar(s)
//
void
TScroller::EndView()
{
if (Window) {
if (HasHScrollBar) {
int newPos = XRange > SHRT_MAX ? XScrollValue(XPos) : (int)XPos;
if (newPos != Window->GetScrollPos(SB_HORZ))
Window->SetScrollPos(SB_HORZ, newPos, true);
}
if (HasVScrollBar) {
int newPos = YRange > SHRT_MAX ? YScrollValue(YPos) : (int)YPos;
if (newPos != Window->GetScrollPos(SB_VERT))
Window->SetScrollPos(SB_VERT, newPos, true);
}
}
}
//
// scrolls vertically according to scroll action and thumb position
//
void
TScroller::VScroll(uint scrollEvent, int thumbPos)
{
switch (scrollEvent) {
case SB_LINEDOWN:
ScrollBy(0, YLine);
break;
case SB_LINEUP:
ScrollBy(0, -YLine);
break;
case SB_PAGEDOWN:
ScrollBy(0, YPage);
break;
case SB_PAGEUP:
ScrollBy(0, -YPage);
break;
case SB_TOP:
ScrollTo(XPos, 0);
break;
case SB_BOTTOM:
ScrollTo(XPos, YRange);
break;
case SB_THUMBPOSITION:
if (YRange > SHRT_MAX)
ScrollTo(XPos, YRangeValue(thumbPos));
else
ScrollTo(XPos, thumbPos);
break;
case SB_THUMBTRACK:
if (TrackMode)
if (YRange > SHRT_MAX)
ScrollTo(XPos, YRangeValue(thumbPos));
else
ScrollTo(XPos, thumbPos);
if (Window && HasVScrollBar)
Window->SetScrollPos(SB_VERT, thumbPos, true);
break;
}
}
//
// scrolls horizontally according to scroll action and thumb position
//
void
TScroller::HScroll(uint scrollEvent, int thumbPos)
{
switch (scrollEvent) {
case SB_LINEDOWN:
ScrollBy(XLine, 0);
break;
case SB_LINEUP:
ScrollBy(-XLine, 0);
break;
case SB_PAGEDOWN:
ScrollBy(XPage, 0);
break;
case SB_PAGEUP:
ScrollBy(-XPage, 0);
break;
case SB_TOP:
ScrollTo(0, YPos);
break;
case SB_BOTTOM:
ScrollTo(XRange, YPos);
break;
case SB_THUMBPOSITION:
if (XRange > SHRT_MAX)
ScrollTo(XRangeValue(thumbPos), YPos);
else
ScrollTo(thumbPos, YPos);
break;
case SB_THUMBTRACK:
if (TrackMode)
if (XRange > SHRT_MAX)
ScrollTo(XRangeValue(thumbPos), YPos);
else
ScrollTo(thumbPos, YPos);
if (Window && HasHScrollBar)
Window->SetScrollPos(SB_HORZ, thumbPos, true);
break;
}
}
//
// scrolls to an (x,y) position, after checking boundary conditions
// causes a WM_PAINT message to be sent
//
// first scrolls the contents of the client area, if a portion of the client
// area will remain visible
//
void
TScroller::ScrollTo(long x, long y)
{
if (Window) {
long newXPos = max(0, min(x, XRange));
long newYPos = max(0, min(y, YRange));
if (newXPos != XPos || newYPos != YPos) {
//
// scaling isn't needed here. if condition is met, ScrollWindow()
// will succeed since XPage and YPage are ints
//
// if condition isn't met, ScrollWindow() is called in EndScroll()
// as a result of calling UpdateWindow()
//
// EndScroll() performs the necessary scaling
//
if (AutoOrg || abs(YPos-newYPos) < YPage && abs(XPos-newXPos) < XPage)
Window->ScrollWindow((int)(XPos - newXPos) * XUnit,
(int)(YPos - newYPos) * YUnit, 0, 0);
else
Window->Invalidate();
XPos = newXPos;
YPos = newYPos;
Window->UpdateWindow();
}
}
}
//
//
//
bool
TScroller::IsAutoMode()
{
return AutoMode;
}
//
// performs "auto-scrolling" (dragging the mouse from within the client
// client area of the Window to without results in auto-scrolling when
// the AutoMode data member of the Scroller is true)
//
void
TScroller::AutoScroll()
{
if (AutoMode && Window) {
TRect clientRect;
TPoint cursorPos;
long dx = 0, dy = 0;
GetCursorPos(&cursorPos);
Window->ScreenToClient(cursorPos);
Window->GetClientRect(clientRect);
if (cursorPos.y < 0)
dy = min(-YLine, max(-YPage, cursorPos.y / 10 * YLine));
else if (cursorPos.y > clientRect.bottom)
dy = max(YLine, min(YPage, (cursorPos.y-clientRect.bottom)/10 * YLine));
if (cursorPos.x < 0)
dx = min(-XLine, max(-XPage, cursorPos.x / 10 * XLine));
else if (cursorPos.x > clientRect.right)
dx = max(XLine, min(XPage, (cursorPos.x-clientRect.right)/10 * XLine));
ScrollBy(dx, dy);
}
}
#endif
#if !defined(SECTION) || SECTION == 2
IMPLEMENT_STREAMABLE(TScroller);
//
// reads an instance of TScroller from the passed ipstream
//
void*
TScroller::Streamer::Read(ipstream& is, uint32 /*version*/) const
{
TScroller* o = GetObject();
is >> o->XPos >> o->YPos >>
o->XUnit >> o->YUnit >>
o->XRange >> o->YRange >>
o->XLine >> o->YLine >>
o->XPage >> o->YPage >>
o->AutoMode >> o->TrackMode >>
o->AutoOrg >>
o->HasHScrollBar >> o->HasVScrollBar;
o->Window = 0;
return o;
}
//
// writes the TScroller to the passed opstream
//
void
TScroller::Streamer::Write(opstream& os) const
{
TScroller* o = GetObject();
os << o->XPos << o->YPos <<
o->XUnit << o->YUnit <<
o->XRange << o->YRange <<
o->XLine << o->YLine <<
o->XPage << o->YPage <<
o->AutoMode << o->TrackMode <<
o->AutoOrg <<
o->HasHScrollBar << o->HasVScrollBar;
}
#endif