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

389 lines
11 KiB
C++

//----------------------------------------------------------------------------
// ObjectWindows
// (C) Copyright 1992, 1994 by Borland International, All Rights Reserved
//
// Definition of print preview classes
//----------------------------------------------------------------------------
#include <owl/owlpch.h>
#include <owl/preview.h>
#include <owl/printer.h>
#include <owl/gdiobjec.h>
#include <owl/dc.h>
#include <owl/printdia.h>
#include <math.h>
//
// Some inlines to provide platform independence since we drop directly to API
// calls to implement some of TPrintPreviewDC.
//
#if defined(BI_PLAT_WIN32)
inline bool SetWindowExt(HDC hdc, int w, int h) {return ::SetWindowExtEx(hdc, w, h, 0);}
inline bool SetWindowOrg(HDC hdc, int w, int h) {return ::SetWindowOrgEx(hdc, w, h, 0);}
inline bool SetViewportExt(HDC hdc, int w, int h) {return ::SetViewportExtEx(hdc, w, h, 0);}
inline bool SetViewportOrg(HDC hdc, int x, int y) {return ::SetViewportOrgEx(hdc, x, y, 0);}
#endif
TPrintPreviewDC::TPrintPreviewDC(TDC& screen,
TPrintDC& printdc,
const TRect& client,
const TRect& clip)
:
TPrintDC(screen),
PrnDC(printdc),
PrnFont(0),
CurrentPreviewFont(0)
{
//
// Set the initial mode & extents for the screen dc
//
::SetMapMode(GetHDC(), MM_ANISOTROPIC);
::SetWindowExt(GetHDC(), client.Width(), client.Height());
::SetViewportExt(GetHDC(), client.Width(), client.Height());
//
// Static call to virtual method, but some mapping must be done now.
//
ReScale();
//
// Assume clip rect is in device points - DPs are same in new viewport
//
SelectClipRgn(clip);
PrnFont = (HFONT)PrnDC.GetCurrentObject(OBJ_FONT);
SyncFont();
}
TPrintPreviewDC::~TPrintPreviewDC()
{
// cleanup screen dc
//
::DeleteObject(::SelectObject(GetHDC(), ::GetStockObject(SYSTEM_FONT)));
delete CurrentPreviewFont;
}
HDC
TPrintPreviewDC::GetAttributeHDC() const
{
return PrnDC;
}
//
// Intercept setting of the printer font, making & keeping a copy of it and
// calling SyncFont if needed to recreate the preview font.
//
void
TPrintPreviewDC::SelectObject(const TFont& newFont)
{
if ((HFONT)newFont) {
LOGFONT lf;
newFont.GetObject(lf);
TFont* oldPreviewF = CurrentPreviewFont;
CurrentPreviewFont = new TFont(&lf);
PrnDC.SelectObject(*CurrentPreviewFont);
delete oldPreviewF;
if ((HFONT)(*CurrentPreviewFont) != PrnFont) {
PrnFont = (HFONT)(*CurrentPreviewFont);
SyncFont();
}
}
}
void
TPrintPreviewDC::SelectStockObject(int index)
{
PrnDC.SelectStockObject(index);
switch (index) {
case ANSI_FIXED_FONT:
case ANSI_VAR_FONT:
case DEVICE_DEFAULT_FONT:
case OEM_FIXED_FONT:
case SYSTEM_FONT:
case SYSTEM_FIXED_FONT: {
HFONT stockFont = (HFONT)GetStockObject(index);
if (stockFont != PrnFont) {
PrnFont = stockFont;
SyncFont();
}
break;
}
default:
TPrintDC::SelectStockObject(index);
}
}
void
TPrintPreviewDC::RestoreFont()
{
PrnDC.RestoreFont();
PrnFont = (HFONT)PrnDC.GetCurrentObject(OBJ_FONT);
TPrintDC::RestoreFont();
SyncFont();
}
int
TPrintPreviewDC::GetDeviceCaps(int index) const
{
switch (index) {
case CLIPCAPS:
case RASTERCAPS:
case CURVECAPS:
case LINECAPS:
case POLYGONALCAPS:
case TEXTCAPS: // report capabilities supported on both devices
return PrnDC.GetDeviceCaps(index) & TPrintDC::GetDeviceCaps(index);
// otherwise, report printer caps and let GDI sort out differences
default:
return PrnDC.GetDeviceCaps(index);
}
}
inline int
GlyphHeight(TEXTMETRIC& tm)
{
return tm.tmHeight < 0
? tm.tmHeight
: -(tm.tmHeight - tm.tmInternalLeading);
}
//
// SyncFont performs a simple font match attempt, with a retry option if
// the GDI selected match is too different from the selected printer font.
// In print preview, matching the size of the characters is more important
// than matching their appearance. In most cases, the print preview will
// barely be legible anyway. Size is most important because you don't
// want character size differences to change the line breaks or page
// breaks of the on-screen document from what they would be on the
// printed page. This effect is minimized in this TPrintPreviewDC object,
// since info reports such as GetTextMetrics and GetTextExtent are always
// reported from the printer dc using the real font. Internal calculations
// should be the same for preview as for printing, but the output accuracy
// will depend upon the accuracy of font selection.
//
// It is also possible to take over control of the text output functions
// through this DC object - the TextOut and other text methods are virtual.
// You can place each character on the preview screen yourself, if you
// desire more precision in character placement than GDI's font matching
// can provide. That's a lot of work, and a lot of code, and isn't
// necessary to meet the needs of most applications.
//
// SyncFont is virtual so that you may substitute your own font matching
// algorythm with more font matching heuristics.
//
void
TPrintPreviewDC::SyncFont()
{
//
// set screen font to match current printer font.
//
LOGFONT lf;
::GetObject(PrnFont, sizeof(lf), &lf);
TEXTMETRIC tm;
PrnDC.GetTextMetrics(tm);
lf.lfHeight = GlyphHeight(tm);
lf.lfWidth = tm.tmAveCharWidth;
lf.lfWeight = tm.tmWeight;
lf.lfItalic = tm.tmItalic;
lf.lfUnderline = tm.tmUnderlined;
lf.lfStrikeOut = tm.tmStruckOut;
lf.lfCharSet = tm.tmCharSet;
lf.lfOutPrecision = OUT_TT_PRECIS;
lf.lfClipPrecision = CLIP_DEFAULT_PRECIS;
lf.lfQuality = DRAFT_QUALITY;
// Keep just the pitch (low 2 bits). Ignore the family
//
lf.lfPitchAndFamily = uint8((tm.tmPitchAndFamily & 0x0003) | FF_DONTCARE);
PrnDC.GetTextFace(sizeof(lf.lfFaceName), lf.lfFaceName);
::DeleteObject(::SelectObject(GetHDC(), ::CreateFontIndirect(&lf)));
//
// if height isn't right, relax the font pitch and facename requirements
//
GetTextMetrics(tm);
if (abs(abs(lf.lfHeight) - abs(GlyphHeight(tm))) > 2) {
if (lf.lfPitchAndFamily & FF_DECORATIVE)
lf.lfPitchAndFamily = DEFAULT_PITCH | FF_DECORATIVE;
else
lf.lfPitchAndFamily = DEFAULT_PITCH | FF_DONTCARE;
lf.lfFaceName[0] = 0;
::DeleteObject(::SelectObject(GetHDC(), CreateFontIndirect(&lf)));
}
}
//
// Rescale the preview DC by adjusting its window & viewport
//
// Assume the viewport extent (scrve) is set to the size of the window
// client area. All we have to do to map the addressable points of the
// printer DC into the screen DC, then, is set the screen window extent
// equal to the maximum addressable logical point of the printer dc.
// PrnDC.DPtoLP will pull the device point through the printer's mapping
// mode conversions, giving us the maximum point we should allow on the
// screen dc.
//
void
TPrintPreviewDC::ReScale()
{
TSize scrve;
::GetViewportExtEx(GetHDC(), &scrve);
TPoint scrwe(PrnDC.GetDeviceCaps(HORZRES), PrnDC.GetDeviceCaps(VERTRES));
PrnDC.DPtoLP(&scrwe);
::SetMapMode(GetHDC(), MM_ANISOTROPIC);
::SetWindowExt(GetHDC(), scrwe.x, scrwe.y);
::SetViewportExt(GetHDC(), scrve.cx, scrve.cy);
ReOrg();
}
//
// Reset the DC's origin
//
void
TPrintPreviewDC::ReOrg()
{
TPoint origin = PrnDC.GetViewportOrg();
PrnDC.DPtoLP(&origin);
LPtoSDP(&origin);
::SetViewportOrg(GetHDC(), origin.x, origin.y);
PrnDC.GetWindowOrg(origin);
::SetWindowOrg(GetHDC(), origin.x, origin.y);
}
TColor
TPrintPreviewDC::SetBkColor(TColor color)
{
TColor result = PrnDC.SetBkColor(color);
::SetBkColor(GetHDC(), PrnDC.GetBkColor());
return result;
}
TColor
TPrintPreviewDC::SetTextColor(TColor color)
{
TColor result = PrnDC.SetTextColor(color);
::SetTextColor(GetHDC(), PrnDC.GetTextColor());
return result;
}
int
TPrintPreviewDC::SetMapMode(int mode)
{
int result = PrnDC.SetMapMode(mode);
ReScale();
return result;
}
bool
TPrintPreviewDC::SetViewportOrg(const TPoint& origin, TPoint far* oldOrg)
{
bool result = PrnDC.SetViewportOrg(origin, oldOrg);
ReOrg();
return result;
}
bool
TPrintPreviewDC::OffsetViewportOrg(const TPoint& delta, TPoint far* oldOrg)
{
bool result = PrnDC.OffsetViewportOrg(delta, oldOrg);
ReOrg();
return result;
}
bool
TPrintPreviewDC::SetViewportExt(const TSize& extent, TSize far* oldExtent)
{
bool result = PrnDC.SetViewportExt(extent, oldExtent);
ReScale();
return result;
}
bool
TPrintPreviewDC::ScaleViewportExt(int xNum, int xDenom, int yNum, int yDenom,
TSize far* oldExtent)
{
bool result = PrnDC.ScaleViewportExt( xNum, xDenom, yNum, yDenom, oldExtent);
ReScale();
return result;
}
bool
TPrintPreviewDC::SetWindowExt(const TSize& extent, TSize far* oldExtent)
{
bool result = PrnDC.SetWindowExt(extent, oldExtent);
ReScale();
return result;
}
bool
TPrintPreviewDC::ScaleWindowExt(int xNum, int xDenom, int yNum, int yDenom,
TSize far* oldExtent)
{
bool result = PrnDC.ScaleWindowExt(xNum, xDenom, yNum, yDenom, oldExtent);
ReScale();
return result;
}
DEFINE_RESPONSE_TABLE1(TPreviewPage, TWindow)
EV_WM_SIZE,
END_RESPONSE_TABLE;
IMPLEMENT_CASTABLE(TPreviewPage);
TPreviewPage::TPreviewPage(TWindow* parent, TPrintout& printout,
TPrintDC& prndc, TSize& printExtent, int pagenum)
: TWindow(parent),
Printout(printout),
PrintDC(prndc),
PrintExtent(printExtent),
PageNum(pagenum)
{
Attr.Style = WS_CHILD | WS_BORDER | WS_VISIBLE;
SetBkgndColor(TColor::White);
}
//
// Using a TPrintPreviewDC, 'print' the current page (PageNum) of Printout
// onto the window DC provided,
//
void
TPreviewPage::Paint(TDC& dc, bool, TRect& clip)
{
TPrintPreviewDC pdc(dc, PrintDC, GetClientRect(), clip);
Printout.SetPrintParams(&pdc, PrintExtent);
if (Printout.HasPage(PageNum)) {
Printout.BeginPrinting();
Printout.BeginDocument(PageNum, PageNum, pfBoth);
// Change clip rect into the shared logical coordinate space, & print
//
pdc.SDPtoLP(clip);
Printout.PrintPage(PageNum, clip, pfBoth);
Printout.EndDocument();
Printout.EndPrinting();
}
else
dc.PatBlt(0, 0, Attr.W, Attr.H, WHITENESS);
}
//
// Always repaint whole window if size is changed
//
void
TPreviewPage::EvSize(uint sizeType, TSize& size)
{
Invalidate();
TWindow::EvSize(sizeType, size);
}