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>
This commit is contained in:
Cyd
2026-07-19 07:33:26 -05:00
co-authored by Claude Fable 5
parent 599b2388a1
commit 63312e07f9
5913 changed files with 756089 additions and 0 deletions
Binary file not shown.
@@ -0,0 +1,299 @@
//----------------------------------------------------------------------------
// ObjectWindows - (C) Copyright 1993 by Borland International
// Example of a minimal doc/view application. Doc/views must be linked in.
// NOTE: this example interprets command line flags to select frame type.
//----------------------------------------------------------------------------
#include <owl\owlpch.h>
#include <owl\docmanag.h>
#include <owl\decmdifr.h>
#include <owl\statusba.h>
#include "docviewx.rc"
class MyDVApp : public TApplication {
public:
MyDVApp() {}
TMDIClient* Client;
int DocMode;
void InitInstance();
void InitMainWindow();
void EvNewView (TView& view);
void EvCloseView(TView& view);
void EvDropFiles(TDropInfo dropInfo);
void CmDeskClear();
void CmDeskSave();
void CmDeskRestore();
void CmHideView();
void CmShowViews();
void CmDisableView();
void CmEnableViews();
DECLARE_RESPONSE_TABLE(MyDVApp);
DECLARE_STREAMABLE(, MyDVApp, 1);
};
DEFINE_RESPONSE_TABLE1(MyDVApp, TApplication)
EV_OWLVIEW(dnCreate, EvNewView),
EV_OWLVIEW(dnClose, EvCloseView),
EV_WM_DROPFILES,
EV_COMMAND(CM_DESKCLEAR, CmDeskClear),
EV_COMMAND(CM_DESKSAVE, CmDeskSave),
EV_COMMAND(CM_DESKRESTORE, CmDeskRestore),
EV_COMMAND(CM_HIDEVIEW, CmHideView),
EV_COMMAND(CM_SHOWVIEWS, CmShowViews),
EV_COMMAND(CM_DISABLEVIEW, CmDisableView),
EV_COMMAND(CM_ENABLEVIEWS, CmEnableViews),
END_RESPONSE_TABLE;
IMPLEMENT_CASTABLE1(MyDVApp, TApplication);
IMPLEMENT_STREAMABLE1(MyDVApp, TApplication);
const char sSDIStream[] = "C:\\DOCVIEWX.SDI";
const char sMDIStream[] = "C:\\DOCVIEWX.MDI";
_OWLLINK(rTMDIChild); // force TMDIChild::Streamer to be linked in
_OWLLINK(rTMDIClient); // force TMDIClient::Streamer to be linked in
_OWLLINK(rTFileDocument); // force TMDIClient::Streamer to be linked in
void MyDVApp::EvDropFiles(TDropInfo dropInfo)
{
int fileCount = dropInfo.DragQueryFileCount();
int index = 0;
while (index < fileCount) {
int fileLength = dropInfo.DragQueryFileNameLen(index)+1;
char* filePath = new char [fileLength];
dropInfo.DragQueryFile(index++, filePath, fileLength);
TDocTemplate* tpl = GetDocManager()->MatchTemplate(filePath);
#if 0 // obsolete code
if (tpl) {
tpl->CreateDoc(filePath);
}
#else // new code
GetDocManager()->CreateDoc(tpl, filePath);
#endif
delete filePath;
}
dropInfo.DragFinish();
}
void MyDVApp::InitInstance()
{
TApplication::InitInstance();
MainWindow->DragAcceptFiles(TRUE);
}
void MyDVApp::InitMainWindow()
{
BOOL decorate;
switch ((_argc>1 && _argv[1][0]=='-' ? _argv[1][1] : (char)0) | ('S'^'s')) {
case 's': DocMode = dmSDI; decorate = FALSE; break; // command line: -s
case 'm': DocMode = dmMDI; decorate = FALSE; break; // command line: -m
case 'd': DocMode = dmSDI; decorate = TRUE; break; // command line: -d
default : DocMode = dmMDI; decorate = TRUE; break; // no command line
}
DocManager = new TDocManager(DocMode | dmMenu);
if (decorate) {
TDecoratedFrame* frame = (DocMode == dmSDI
? new TDecoratedFrame(0, "SDI DocView Example", 0,TRUE)
: new TDecoratedMDIFrame("MDI DocView Example", 0,
*(Client=new TMDIClient), TRUE));
TStatusBar* sb = new TStatusBar(frame, TGadget::Recessed,
TStatusBar::CapsLock | TStatusBar::NumLock | TStatusBar::Overtype);
frame->Insert(*sb, TDecoratedFrame::Bottom);
MainWindow = frame;
} else { // !decorate
MainWindow = (DocMode == dmSDI
? new TFrameWindow(0, "SDI DocView Example")
: new TMDIFrame("MDI DocView Example", 0, *(Client=new TMDIClient)));
}
MainWindow->SetMenuDescr(TMenuDescr(DocMode==dmSDI ? IDM_DVSDI : IDM_DVMDI));
MainWindow->SetIcon(this, IDI_DOCVIEW);
}
void MyDVApp::EvNewView(TView& view)
{
if (DocMode == dmSDI) {
MainWindow->SetClientWindow(view.GetWindow());
if (!view.IsOK())
MainWindow->SetClientWindow(0);
else if (view.GetViewMenu())
MainWindow->MergeMenu(*view.GetViewMenu());
} else { // DocMode == dmMDI
TMDIChild* child = new TMDIChild(*Client, 0, view.GetWindow());
if (view.GetViewMenu())
child->SetMenuDescr(*view.GetViewMenu());
child->Create();
}
}
void MyDVApp::EvCloseView(TView& /*view*/)
{
if (DocMode == dmSDI) {
MainWindow->SetClientWindow(0);
MainWindow->RestoreMenu();
MainWindow->SetCaption("SDI DocView Example");
}
}
void MyDVApp::CmDeskClear()
{
delete DocManager; // delete existing document manager, and doc/views
DocManager = new TDocManager(DocMode | dmMenu);
}
void MyDVApp::CmDeskSave()
{
ofpstream os(DocMode == dmMDI ? sMDIStream : sSDIStream);
os << *this; // start stream with application
os.close();
if (os.bad()) {
unlink(DocMode == dmMDI ? sMDIStream : sSDIStream);
MainWindow->MessageBox("Unable to write desktop file.", "File error",
MB_OK | MB_ICONEXCLAMATION);
}
}
void MyDVApp::CmDeskRestore()
{
char* errorMsg = 0;
ifpstream is(DocMode == dmMDI ? sMDIStream : sSDIStream);
if (is.bad())
errorMsg = "Unable to open desktop file.";
else {
delete DocManager; // delete existing document manager, and doc/views
DocManager = new TDocManager(DocMode | dmMenu);
is >> *this; // stream in documents, views, windows
if (is.bad())
errorMsg = "Error reading desktop file.";
is.close();
}
if (errorMsg)
MainWindow->MessageBox(errorMsg, "Error", MB_OK | MB_ICONEXCLAMATION);
}
void MyDVApp::Streamer::Write(opstream& os) const
{
MyDVApp* o = GetObject();
TFrameWindow* mainWnd = o->MainWindow;
WriteBaseObject((TApplication*)o, os);
os <<mainWnd->Attr.X <<mainWnd->Attr.Y <<mainWnd->Attr.W <<mainWnd->Attr.H;
if (o->DocMode == dmMDI) {
os << *o->Client;// stream out object reference only, no children streamed
os << *o->DocManager;
os << o->Client->GetActiveMDIChild();
} else {
TWindow* client = mainWnd->SetClientWindow(0); // unhook view
if (client) {
client->ShowWindow(SW_HIDE);
client->SetParent(0);
os << *o->DocManager;
os << client; // save pointer to client window
mainWnd->SetClientWindow(client);
}
}
}
void* MyDVApp::Streamer::Read(ipstream& is, uint32 /*version*/ ) const
{
MyDVApp* o = GetObject();
TFrameWindow* mainWnd = o->MainWindow;
ReadBaseObject((TApplication*)o, is);
is >>mainWnd->Attr.X >>mainWnd->Attr.Y >>mainWnd->Attr.W >>mainWnd->Attr.H;
mainWnd->MoveWindow(mainWnd->Attr.X, mainWnd->Attr.Y,
mainWnd->Attr.W, mainWnd->Attr.H, TRUE);
if (o->DocMode == dmMDI) {
is >> *o->Client; // skip stream top ref, no data or children read in
is >> *o->DocManager; // streams in all templates, docs, views, windows
o->Client->CreateChildren(); // create MDI children and descendents
TMDIChild* active;
is >> active;
if (active)
GetObject()->Client->HandleMessage(WM_MDIACTIVATE,(UINT)active->HWindow);
} else {
TWindow* client;
is >> *o->DocManager; // streams in all templates, docs, views, windows
is >> client; // streams in pointer to constructed client window
if (client) {
mainWnd->SetClientWindow(client);
TDocument* doc;
TView* view;
if ((doc = o->DocManager->DocList.Next(0)) != 0 &&
(view = doc->NextView(0)) != 0)
mainWnd->MergeMenu(*view->GetViewMenu());
}
}
return GetObject();
}
void MyDVApp::CmHideView()
{
TMDIChild* child = Client->GetActiveMDIChild();
if (child)
child->ShowWindow(SW_HIDE);
}
void sUnHide(TWindow* win, void*)
{
TMDIChild* child = TYPESAFE_DOWNCAST(win, TMDIChild);
if (child && !child->IsWindowVisible())
child->ShowWindow(SW_RESTORE);
}
void MyDVApp::CmShowViews()
{
Client->ForEach(sUnHide);
}
void MyDVApp::CmDisableView()
{
TMDIChild* child = Client->GetActiveMDIChild();
if (child)
child->EnableWindow(FALSE);
}
void sUnDisable(TWindow* win, void*)
{
TMDIChild* child = TYPESAFE_DOWNCAST(win, TMDIChild);
if (child && !child->IsWindowEnabled())
child->EnableWindow(TRUE);
}
void MyDVApp::CmEnableViews()
{
Client->ForEach(sUnDisable);
}
int OwlMain(int /*argc*/, char* /*argv*/ [])
{
MyDVApp* app;
int status;
int done;
do {
try {
app = new MyDVApp;
status = app->Run();
done = 1;
if (status) {
char buf[40];
wsprintf(buf, "Run returned %i", status);
done = HandleGlobalException(xmsg(string(buf)),
"Abnormal Termination","RunAgain?");
}
}
catch (xmsg& x) {
done = status = HandleGlobalException(x,
"Abnormal Termination, uncaught xmsg","RunAgain?");
}
catch(...) {
done = status = HandleGlobalException(xmsg(string()),
"Abnormal Termination, uncaught ...","RunAgain?");
}
delete app;
} while (!done);
return status;
}
@@ -0,0 +1,131 @@
//----------------------------------------------------------------------------
// ObjectWindows - (C) Copyright 1993 by Borland International
// Resources for use with doc/view example
//----------------------------------------------------------------------------
#ifndef WS_POPUP
#include <windows.h>
#endif
#include <owl\docview.rc>
#include <owl\except.rc>
#include <owl\mdi.rh>
#define IDI_DOCVIEW 22201
#define IDM_DVSDI 22201
#define IDM_DVMDI 22202
#define CM_DESKCLEAR 22202
#define CM_DESKSAVE 22203
#define CM_DESKRESTORE 22204
#define CM_HIDEVIEW 22205
#define CM_SHOWVIEWS 22206
#define CM_DISABLEVIEW 22207
#define CM_ENABLEVIEWS 22208
#if defined(RC_INVOKED)
#include <owl\statusba.rc>
#include <owl\owlapp.rc>
IDM_DVSDI MENU LOADONCALL MOVEABLE PURE DISCARDABLE
{
MenuItem "File", 0,GRAYED ;placeholder for File menu from DocManager
MenuItem Separator
MenuItem Separator
POPUP "&Desktop"
{
MenuItem "&Clear Desktop", CM_DESKCLEAR
; MenuItem "&Save Desktop", CM_DESKSAVE
; MenuItem "&Restore Desktop",CM_DESKRESTORE
}
}
IDM_DVMDI MENU LOADONCALL MOVEABLE PURE DISCARDABLE
{
MenuItem "File", 0,GRAYED ;placeholder for File menu from DocManager
MenuItem Separator
MenuItem Separator
POPUP "&Desktop"
{
MenuItem "&Clear Desktop", CM_DESKCLEAR
; MenuItem "&Save Desktop", CM_DESKSAVE
; MenuItem "&Restore Desktop",CM_DESKRESTORE
MenuItem "&Hide View", CM_HIDEVIEW
MenuItem "&Unhide Views", CM_SHOWVIEWS
MenuItem "&Disable View", CM_DISABLEVIEW
MenuItem "&Enable Views", CM_ENABLEVIEWS
}
MenuItem Separator
MenuItem Separator
POPUP "&Window"
{
MenuItem "&Cascade", CM_CASCADECHILDREN
MenuItem "&Tile", CM_TILECHILDREN
MenuItem "Arrange &Icons", CM_ARRANGEICONS
MenuItem "C&lose All", CM_CLOSECHILDREN
MenuItem "Add &View", CM_VIEWCREATE
}
}
STRINGTABLE LOADONCALL MOVEABLE DISCARDABLE
{
CM_DESKCLEAR, "Clear desktop"
CM_DESKSAVE, "Save desktop"
CM_DESKRESTORE, "Restore desktop"
CM_HIDEVIEW, "Hide current view"
CM_SHOWVIEWS, "Unhide hidden views"
CM_DISABLEVIEW, "Disable current view"
CM_ENABLEVIEWS, "Enable disabled views"
}
IDI_DOCVIEW ICON
{
'00 00 01 00 01 00 20 20 10 00 00 00 00 00 E8 02'
'00 00 16 00 00 00 28 00 00 00 20 00 00 00 40 00'
'00 00 01 00 04 00 00 00 00 00 80 02 00 00 00 00'
'00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00'
'00 00 00 00 BF 00 00 BF 00 00 00 BF BF 00 BF 00'
'00 00 BF 00 BF 00 BF BF 00 00 C0 C0 C0 00 80 80'
'80 00 00 00 FF 00 00 FF 00 00 00 FF FF 00 FF 00'
'00 00 FF 00 FF 00 FF FF 00 00 FF FF FF 00 CC CC'
'CC CC CC CC CC 00 00 00 00 00 00 00 00 00 C0 00'
'00 00 00 00 0C 00 00 00 00 00 00 00 00 00 CF FF'
'0F FF F0 FF FC 00 0C CC CC CC CC CC CC C0 CF FF'
'0F FF F0 FF FC 00 0C FF FF FF FF FF FF C0 C0 00'
'00 00 00 00 0C 00 0C F0 00 00 00 00 00 C0 CF FF'
'0A AA A0 FF FC 00 0C F0 22 FF FF FF FF C0 CF FF'
'0A AA A0 FF FC 00 0C F0 FF 2F FF FF FF C0 C0 00'
'00 00 00 00 0C 00 0C F0 FF F2 FF FF F9 C0 CF FF'
'0F FF F0 FF FC 00 0C F0 FF FF 2F FF 9F C0 CF FF'
'0F FF F0 FF FC 00 0C F0 FF FF F2 F9 FF C0 C0 00'
'00 00 00 00 0C 00 0C F0 9F FF F2 F9 FF C0 CF FF'
'FF FF FF FF FC 00 0C F0 F9 FF FF 29 FF C0 C7 7F'
'FF 77 FF F7 7C 00 0C F0 FF 99 FF 92 FF C0 CC CC'
'CC CC CC CC CC 00 0C F0 FF FF 99 FF 22 C0 00 00'
'99 90 00 00 00 00 9C F0 FF FF FF FF FF C0 00 00'
'99 90 00 00 00 09 9C CC CC CC CC CC CC C0 00 00'
'99 90 00 00 00 99 99 00 00 00 00 00 00 00 BB BB'
'BB BB BB BB B9 99 90 00 00 00 00 00 00 00 B0 00'
'00 00 BB BB B9 99 00 CC CC CC CC CC CC CC BB BB'
'BB BB BB BB B9 90 00 CF FF FF FF FF FF FC B0 00'
'00 00 00 0B B0 00 00 CF 0F 0F 0F 0F 0F FC BB BB'
'BB BB BB BB B0 00 00 CF FF FF FF FF FF FC B0 00'
'00 00 0B BB B0 00 00 CC CC FC CC FC CC CC BB BB'
'BB BB BB BB B0 00 00 CC FC CC FC CC FC CC B0 00'
'00 00 00 0B B0 00 00 CF FF FF FF FF FF FC BB BB'
'BB BB BB BB B0 00 00 CF 0F 0F 0F 0F 0F FC B0 00'
'00 00 00 BB B9 99 99 CF FF FF FF FF FF FC BB BB'
'BB BB BB BB B9 99 99 CF 0F 0F 0F 0F 0F FC B0 00'
'00 00 BB BB B9 99 99 CF FF FF FF FF FF FC BB BB'
'BB BB BB BB B0 00 00 CF 0F 0F 0F 0F 0F FC B0 00'
'00 00 00 00 B0 00 00 CF FF FF FF FF FF FC BB BB'
'BB BB BB BB B0 00 00 CC CC CC CC CC CC CC 00 03'
'FF FF 00 03 FF FF 00 03 80 01 00 03 80 01 00 03'
'80 01 00 03 80 01 00 03 80 01 00 03 80 01 00 03'
'80 01 00 03 80 01 00 03 80 01 00 03 80 01 00 03'
'80 01 00 03 80 01 F1 FF 00 01 F1 FE 00 01 F1 FC'
'3F FF 00 00 7F FF 00 00 C0 00 00 01 C0 00 00 07'
'C0 00 00 07 C0 00 00 07 C0 00 00 07 C0 00 00 07'
'C0 00 00 07 C0 00 00 00 00 00 00 00 00 00 00 00'
'00 00 00 07 C0 00 00 07 C0 00 00 07 C0 00'
}
#endif // defined(RC_INVOKED)
@@ -0,0 +1,549 @@
//----------------------------------------------------------------------------
// ObjectWindows - (C) Copyright 1993 by Borland International
// Implements class TDumpView
//----------------------------------------------------------------------------
#include <owl\owlpch.h>
#include <owl\docmanag.h>
#include <owl\filedoc.h>
#include <owl\listbox.h>
#include <owl\inputdia.h>
#include <owl\dc.h>
#include "dumpview.rc"
struct TDumpData;
class _DOCVIEWCLASS TDumpView : public TListBox, public TView {
public:
TDumpView(TDocument& doc, TWindow* parent = 0);
~TDumpView();
static LPCSTR StaticName() {return "Dump View";} // put in resource
//
// overridden virtuals from TView
//
LPCSTR GetViewName(){return StaticName();}
// const char far* GetViewName(){return StaticName();}
TWindow* GetWindow() {return (TWindow*)this;}
BOOL SetDocTitle(LPCSTR docname, int index)
// BOOL SetDocTitle(const char far* docname, int index)
{return TListBox::SetDocTitle(docname, index);}
//
// overridden virtuals from TWindow
//
BOOL Create();
BOOL CanClose() {return TListBox::CanClose() && Doc->CanClose();}
int MaxWidth; // maximum horizontal extent
protected:
long Origin;
long FileSize;
int UpdateMode; // 0=NotEditing, 1=HighNibble, 2=LowNibble, -1=Flushing
int CharWidth;
int CharHeight;
int EditByte;
int EditLine;
TDumpData* Changes;
void Init();
BOOL LoadData(int top, int sel);
void FormatLine(int index, TDumpData* data);
BOOL NewEditLine(int line, int byte);
void EndEditLine();
void KillChanges();
private:
//
// message response functions
//
BOOL VnCommit(BOOL force);
BOOL VnRevert(BOOL clear);
BOOL VnIsWindow(HWND hWnd) {return HWindow == hWnd;}
BOOL VnIsDirty();
BOOL VnDocClosed(int omode);
void CmEditUndo();
void CmEditItem();
void EvPaint();
void EvKeyDown(UINT key, UINT repeatCount, UINT flags);
void EvLButtonDown(UINT modKeys, TPoint& point);
void EvLButtonDblClk(UINT modKeys, TPoint& point);
void CmSelChange(){} // to prevent interpreting as unprocessed accelerator
DECLARE_RESPONSE_TABLE(TDumpView);
DECLARE_STREAMABLE(,TDumpView,1);
};
DIAG_DECLARE_GROUP(OwlDocView); // General Doc/View diagnostic group
const int DisplayLines = 16; // initial list box size
const int ListBoxMax = 100; // max number of lines stored in list box
const int DataWidth = 8; // number of data bytes per line
const int AddrWidth = 2; // number of bytes in address
const int LineWidth = AddrWidth*2 + 1 + DataWidth*3 + DataWidth;
struct TDumpData {
long Addr;
char Old[DataWidth];
char New[DataWidth];
int Count;
TDumpData* Next;
};
DEFINE_RESPONSE_TABLE1(TDumpView, TListBox)
EV_WM_KEYDOWN,
EV_COMMAND(CM_DUMPUNDO, CmEditUndo),
EV_COMMAND(CM_DUMPEDIT, CmEditItem),
EV_WM_PAINT,
EV_WM_LBUTTONDOWN,
EV_WM_LBUTTONDBLCLK,
EV_VN_DOCCLOSED,
EV_VN_ISWINDOW,
EV_VN_ISDIRTY,
EV_VN_COMMIT,
EV_VN_REVERT,
EV_NOTIFY_AT_CHILD(LBN_SELCHANGE, CmSelChange),
END_RESPONSE_TABLE;
TDumpView::TDumpView(TDocument& doc, TWindow* parent)
: TView(doc), TListBox(parent, GetNextViewId(), 0,0,0,0)
{
Init();
// Attr.Style &= ~(WS_BORDER | LBS_SORT);
Attr.Style &= ~(LBS_SORT);
Attr.Style |= LBS_DISABLENOSCROLL | LBS_NOINTEGRALHEIGHT;
Attr.AccelTable = IDA_DUMPVIEW;
SetViewMenu(new TMenuDescr(IDM_DUMPVIEW,0,1,0,0,0,1));
}
void
TDumpView::Init()
{
Origin = 0;
UpdateMode = 0;
Changes = 0;
}
BOOL
TDumpView::VnDocClosed(int omode)
{
if (UpdateMode == -1 || !(omode & ofWrite)) // make sure someone else's write
return FALSE;
int top = GetTopIndex();
int sel = GetSelIndex();
ClearList();
LoadData(top, sel);
return TRUE;
}
static char HexDigit(int i)
{
char c = char((i & 15) + '0');
if (c > '9')
c += char('A' - ('9' + 1));
return c;
}
void
TDumpView::FormatLine(int line, TDumpData* data)
{
char buf[LineWidth + 2];
int index;
char* pbuf;
char* pasc;
unsigned char chr;
long addr = data->Addr;
for (index = AddrWidth*2; --index >= 0; addr >>= 4)
buf[index] = HexDigit((int)addr);
pbuf = buf + AddrWidth*2;
*pbuf++ = ' ';
pasc = pbuf + DataWidth*3;
for (index = 0; index < DataWidth; index++) {
if (index < data->Count) {
chr = data->New[index];
*pbuf++ = HexDigit(chr >> 4);
*pbuf++ = HexDigit(chr);
pasc[index] = char((chr >= 0x20 && chr < 0x7F) ? chr : 0x7F);
} else {
*pbuf++ = ' ';
*pbuf++ = ' ';
pasc[index] = ' ';
}
*pbuf++ = ' ';
}
pasc[DataWidth] = 0; // null terminate buffer
InsertString(buf, line);
}
static long GetAddr(int index)
{
return index * DataWidth;
// need to add origin!
}
static int GetIndex(long addr)
{
return int(addr / DataWidth);
// need to subtract origin!
}
BOOL
TDumpView::LoadData(int top, int sel)
{
TDumpData data;
istream* inStream;
int count;
if ((inStream = Doc->InStream(ofRead | ofBinary)) == 0)
return FALSE;
for (count=0, data.Addr=0; count<ListBoxMax; count++,data.Addr+=DataWidth) {
inStream->read(data.New, DataWidth);
if ((data.Count = inStream->gcount()) == 0)
break;
FormatLine(-1, &data);
if (data.Count != DataWidth)
break;
}
SetTopIndex(top);
SetSelIndex(sel);
delete inStream; // close file in case process switch
return TRUE;
}
BOOL
TDumpView::Create()
{
TRect rect;
LOGFONT fontinfo;
HGDIOBJ font = GetStockObject(SYSTEM_FIXED_FONT);
TListBox::Create(); // throws exception TXInvalidWindow
SendMessage(WM_SETFONT, (UINT)font, 0L);
GetObject(font, sizeof(LOGFONT), &fontinfo);
CharWidth = fontinfo.lfWidth;
CharHeight = fontinfo.lfHeight;
GetClientRect(rect); // created with 0,0 size, .right is -scroll bar size
if (rect.right < 0) { // if new view, else streaming in presized window
rect.right = LineWidth * CharWidth + (-rect.right+2) + CharWidth/2;
rect.bottom = CharHeight * DisplayLines;
MoveWindow(rect);
//if (!Parent->IsFlagSet(wfMainWindow))// prevent parent shrink if main window
Parent->SetFlag(wfShrinkToClient);
}
if (!Doc->GetDocPath())
return TRUE; // new file, no data to display
if (!LoadData(0, 0))
NotOK();
return TRUE;
}
BOOL
TDumpView::VnCommit(BOOL /*force*/)
{
TDumpData* edit;
ostream* outStream;
EndEditLine();
if (!Changes)
return TRUE;
if ((outStream = Doc->OutStream(ofReadWrite | ofBinary)) == 0)
return FALSE;
while ((edit = Changes) != 0) {
outStream->seekp(edit->Addr);
outStream->write(edit->New, edit->Count);
// test goodbit
Changes = Changes->Next;
delete edit;
}
UpdateMode = -1; // to detect our own close notification
outStream->seekp(0,ios::end);
delete outStream;
return TRUE;
}
BOOL
TDumpView::VnRevert(BOOL clear)
{
EndEditLine();
KillChanges();
ClearList();
return (!clear && Doc->GetDocPath() != 0) ? LoadData(0, 0) : TRUE;
}
TDumpView::~TDumpView()
{
KillChanges();
}
BOOL
TDumpView::NewEditLine(int line, int byte)
{
istream* inStream;
TDumpData* edit;
TRect rect;
BOOL stat = TRUE;
if (line < 0)
return FALSE;
SetSelIndex(line); // restore index in case changes
if (UpdateMode > 0) {
return FALSE;
}
if ((inStream = Doc->InStream(ofRead | ofBinary)) == 0)
return FALSE;
if ((edit = new TDumpData) == 0)
return FALSE;
edit->Addr = GetAddr(line);
inStream->seekg(edit->Addr);
// test goodbit
inStream->read(edit->Old, DataWidth);
if ((edit->Count = inStream->gcount()) > 0) {
memcpy(edit->New, edit->Old, edit->Count);
UpdateMode = 1;
GetItemRect(line, rect);
InvalidateRect(rect);
edit->Next = Changes;
Changes = edit;
while (byte >= edit->Count)
byte--;
EditByte = byte;
EditLine = line;
} else {
delete edit;
stat = FALSE;
}
delete inStream;
return stat;
}
BOOL
TDumpView::VnIsDirty()
{
return (Changes
&& (Changes->Next
|| memcmp(Changes->New, Changes->Old, Changes->Count) != 0));
}
void
TDumpView::EndEditLine()
{
TDumpData* edit = Changes;
if (UpdateMode > 0) {
TRect rect;
GetItemRect(EditLine, rect);
InvalidateRect(rect);
if (memcmp(edit->New, edit->Old, edit->Count) == 0) {
Changes = Changes->Next;
delete edit;
}
}
UpdateMode = 0;
}
void
TDumpView::KillChanges()
{
TDumpData* edit;
while ((edit = Changes) != 0) {
Changes = Changes->Next;
delete edit;
}
}
void
TDumpView::EvLButtonDown(UINT modKeys, TPoint& point)
{
if (UpdateMode > 0) {
int line = point.y/CharHeight + GetTopIndex();
if (line != EditLine) {
EndEditLine();
TListBox::EvLButtonDown(modKeys, point);
return;
}
int index = ((point.x*2 - CharWidth)/(CharWidth*2) - AddrWidth*2)/3;
if (index >= 0 && index < Changes->Count) {
EditByte = index;
UpdateMode = 1;
TRect rect;
GetItemRect(EditLine, rect);
InvalidateRect(rect);
}
} else
TListBox::EvLButtonDown(modKeys, point);
}
void
TDumpView::EvLButtonDblClk(UINT /*modKeys*/, TPoint& point)
{
int index = ((point.x*2 - CharWidth)/(CharWidth*2) - AddrWidth*2)/3;
if (index < 0 || index >= DataWidth)
index = 0;
int line = point.y/CharHeight + GetTopIndex();
if (UpdateMode <= 0 || line != EditLine) {
// EndEditLine();
NewEditLine(line, index);
}
}
void
TDumpView::EvKeyDown(UINT key, UINT repeatCount, UINT flags)
{
char oldchr, newchr;
MSG msg;
if (UpdateMode <= 0) {
if (key != VK_LEFT && key != VK_RIGHT)
TListBox::EvKeyDown(key, repeatCount, flags);
return;
}
switch (key) {
case VK_ESCAPE: // abort changes to current line
CmEditUndo();
return;
case VK_RETURN: // enter changes for current line, not committed yet
EndEditLine();
break;
case 'A': case 'B': case 'C': case 'D': case 'E': case 'F':
key += ('0' + 10) - 'A'; // fall through to digit cases
case '0': case '1': case '2': case '3': case '4':
case '5': case '6': case '7': case '8': case '9':
newchr = char(key - '0');
oldchr = Changes->New[EditByte];
::PeekMessage(&msg, HWindow, WM_CHAR, WM_CHAR, PM_REMOVE);
switch(UpdateMode) {
case 1:
newchr = char((oldchr & 0x0F) + (newchr<<4));
break;
case 2:
newchr = char((oldchr & 0xF0) + newchr);
break;
default:
return;
}
Changes->New[EditByte] = newchr;
DeleteString(EditLine);
FormatLine(EditLine, Changes);
SetSelIndex(EditLine);
if (UpdateMode++ == 2 && EditByte < Changes->Count-1) {
EditByte++;
UpdateMode = 1;
}
break;
case VK_UP:
case VK_DOWN:
case VK_PRIOR:
case VK_NEXT:
case VK_END:
case VK_HOME:
if (UpdateMode > 0)
return;
break;
case VK_LEFT:
if (UpdateMode <= 0 || EditByte == 0)
return;
UpdateMode = 1;
EditByte--;
break;
case VK_RIGHT:
if (UpdateMode <= 0 || EditByte >= (Changes->Count-1))
return;
UpdateMode = 1;
EditByte++;
break;
default:
break;
}
TRect rect;
GetItemRect(EditLine, rect);
InvalidateRect(rect);
}
void
TDumpView::EvPaint()
{
TRegion updateRgn;
GetUpdateRgn(updateRgn);
DefaultProcessing(); // predefined listbox class will paint, don't call TWindow
if (UpdateMode <= 0)
return;
if (GetSelIndex() != EditLine) {
//::MessageBeep(MB_ICONEXCLAMATION);
return;
}
if (GetTopIndex() > EditLine || (GetTopIndex()+DisplayLines) <= EditLine)
return;
TRect rect;
GetItemRect(EditLine, rect);
rect.left += CharWidth * (AddrWidth*2+1+EditByte*3) + 1;
rect.right = rect.left + CharWidth * 2;
// should check if in update region!
TClientDC dc(HWindow);
// dc.SelectClipRgn(updateRgn);
// dc.IntersectClipRect(rect);
// dc.InvertRgn(updateRgn);
dc.InvertRgn(updateRgn &= rect);
}
void
TDumpView::CmEditUndo()
{
TRect rect;
TDumpData* edit;
UpdateMode = 0;
if (!Changes)
return;
int index = GetIndex(Changes->Addr);
DeleteString(index);
memcpy(Changes->New, Changes->Old, Changes->Count);
FormatLine(index, Changes);
SetSelIndex(index);
edit = Changes;
Changes = Changes->Next;
delete edit;
GetItemRect(index, rect);
InvalidateRect(rect);
}
void
TDumpView::CmEditItem()
{
int line = GetSelIndex();
if (UpdateMode > 0) {
if (line == EditLine)
return;
EndEditLine();
}
NewEditLine(line, 0);
}
IMPLEMENT_STREAMABLE2(TDumpView, TListBox, TView);
void*
TDumpView::Streamer::Read(ipstream& is, uint32 /*version*/) const
{
ReadBaseObject((TListBox*)GetObject(), is);
ReadBaseObject((TView*)GetObject(), is);
is >> GetObject()->Origin;
GetObject()->Init();
return GetObject();
}
void
TDumpView::Streamer::Write(opstream &os) const
{
WriteBaseObject((TListBox*)GetObject(), os);
WriteBaseObject((TView*)GetObject(), os);
os << GetObject()->Origin;
}
DEFINE_DOC_TEMPLATE_CLASS(TFileDocument, TDumpView, DumpTemplate);
DumpTemplate dumpTpl("DumpView, Binary files", "*.obj;*.res", 0, 0,
dtAutoDelete | dtUpdateDir);
@@ -0,0 +1,59 @@
//----------------------------------------------------------------------------
// ObjectWindows - (C) Copyright 1993 by Borland International
// Menu and accelerators for use with TDumpView
//----------------------------------------------------------------------------
#define CM_DUMPUNDO 24681
#define CM_DUMPCUT 24682
#define CM_DUMPCOPY 24683
#define CM_DUMPPASTE 24684
#define CM_DUMPEDIT 24688
#define IDM_DUMPVIEW 32382
#define IDA_DUMPVIEW 32382
#define IDS_DUMPNUM 32382
#if defined(RC_INVOKED)
IDM_DUMPVIEW MENU LOADONCALL MOVEABLE PURE DISCARDABLE
BEGIN
POPUP "&Edit"
BEGIN
MenuItem "&Undo\aCtrl+Z", CM_DUMPUNDO
MenuItem SEPARATOR
MenuItem "&Cut\aCtrl+X", CM_DUMPCUT
MenuItem "C&opy\aCtrl+C", CM_DUMPCOPY
MenuItem "&Paste\aCtrl+V", CM_DUMPPASTE
MenuItem "&Edit Item\aAlt+Enter",CM_DUMPEDIT
END
POPUP "&Help"
BEGIN
MenuItem "OWL DumpView", 0, INACTIVE
END
END
IDA_DUMPVIEW ACCELERATORS
BEGIN
"^z", CM_DUMPUNDO,
"^x", CM_DUMPCUT,
"^c", CM_DUMPCOPY,
"^v", CM_DUMPPASTE,
VK_DELETE, CM_DUMPCUT, VIRTKEY, SHIFT
VK_INSERT, CM_DUMPCOPY, VIRTKEY, CONTROL
VK_INSERT, CM_DUMPPASTE, VIRTKEY, SHIFT
VK_BACK, CM_DUMPUNDO, VIRTKEY, ALT
VK_RETURN, CM_DUMPEDIT, VIRTKEY
END
STRINGTABLE LOADONCALL MOVEABLE DISCARDABLE
BEGIN
CM_DUMPUNDO, "Reverses the last operation"
CM_DUMPCUT, "Cuts the selection and puts it on the Clipboard"
CM_DUMPCOPY, "Copies the selection to the Clipboard"
CM_DUMPPASTE, "Inserts the Clipboard contents at the caret"
CM_DUMPEDIT, "Edit the current line"
IDS_DUMPNUM, "Address %d"
END
#endif // defined(RC_INVOKED)
@@ -0,0 +1,108 @@
//----------------------------------------------------------------------------
// ObjectWindows - (C) Copyright 1993 by Borland International
// Provides TModuleDoc class to dynamically load new document/view classes
//----------------------------------------------------------------------------
#include <owl\owlpch.h>
#include <owl\docmanag.h>
#include "dvloader.rc"
class TModuleDocument : public TDocument {
public:
TModuleDocument(TDocument* parent=0) : TDocument(parent), Module(0) {}
~TModuleDocument() { Close(); }
BOOL Open(int mode, const char far* path=0);
BOOL Close();
BOOL IsOpen() { return Module != 0; }
protected:
TModule* Module;
DECLARE_STREAMABLE(, TModuleDocument,1);
};
class TModuleView : public TView {
public:
TModuleView(TDocument& doc, TWindow* parent = 0) : TView(doc) {
doc.GetDocManager().PostDocError(doc, IDS_DVLOADED);
NotOK();
}
static LPCSTR StaticName() {return "Module View";}
LPCSTR GetViewName() {return StaticName();}
};
BOOL TModuleDocument::Open(int /*mode*/, const char far* path)
{
if (IsOpen())
return TRUE;
if (path)
SetDocPath(path);
if (!GetDocPath())
return FALSE;
try {
Module = new TModule(GetDocPath());
}
catch(TXOwl&) {
return FALSE;
}
TDocTemplate** tplhead;
TDocTemplate** PASCAL(*entry)(int version);
(FARPROC)entry = Module->GetProcAddress("GetDocTemplateHead");
if (!entry || (tplhead = entry(OWLVersion)) == 0) {
delete Module;
Module = 0;
return FALSE;
}
TDocTemplate* tpl = *tplhead;
for (; tpl; tpl = GetDocManager().GetNextTemplate(tpl))
tpl->Clone(Module)->SetDocManager(&GetDocManager());
return TRUE;
}
BOOL TModuleDocument::Close()
{
if (!IsOpen())
return TRUE;
TDocTemplate* tpl;
TDocTemplate* next;
for (tpl = GetDocManager().GetNextTemplate(0); tpl; tpl = next) {
next = GetDocManager().GetNextTemplate(tpl);
if (*tpl->GetModule() == *Module) {
// must remove any remaining associated documents before freeing module
TDocument* doc;
TDocument* next;
for (doc = GetDocManager().DocList.Next(0); doc; doc = next) {
next = GetDocManager().DocList.Next(doc);
if (doc->GetTemplate() == tpl){
doc->Close();
delete doc;
}
}
GetDocManager().DeleteTemplate(*tpl); // RefCnt should go to 0 now
}
}
delete Module;
Module = 0;
return TRUE;
}
IMPLEMENT_STREAMABLE1(TModuleDocument, TDocument);
void*
TModuleDocument::Streamer::Read(ipstream& is, uint32 /*version*/) const
{
ReadBaseObject((TDocument*)GetObject(), is);
is >> GetObject()->Module;
return GetObject();
}
void
TModuleDocument::Streamer::Write(opstream& os) const
{
WriteBaseObject((TDocument*)GetObject(), os);
os << GetObject()->Module;
}
DEFINE_DOC_TEMPLATE_CLASS(TModuleDocument, TModuleView, LoadTemplate);
LoadTemplate loadTpl("DocView Components (*.DVC)","*.dvc",0,0,
dtAutoOpen|dtUpdateDir|dtReadOnly|dtHideReadOnly);
@@ -0,0 +1,14 @@
//----------------------------------------------------------------------------
// ObjectWindows - (C) Copyright 1993 by Borland International
// Resources for doc/view loader document
//----------------------------------------------------------------------------
#define IDS_DVLOADED 25880
#ifdef RC_INVOKED
STRINGTABLE
{
IDS_DVLOADED, "Document/view loaded"
}
#endif
@@ -0,0 +1,20 @@
//----------------------------------------------------------------------------
// ObjectWindows - (C) Copyright 1993 by Borland International
// Provides templates and DLL access to TEditView and TListView
//----------------------------------------------------------------------------
#include <owl\owlpch.h>
#include <owl\listview.h>
#include <owl\editview.h>
#include <owl\filedoc.h>
#include <owl\docmanag.h>
DEFINE_DOC_TEMPLATE_CLASS(TFileDocument, TListView, ListTemplate);
DEFINE_DOC_TEMPLATE_CLASS(TFileDocument, TEditView, EditTemplate);
_OWLLINK(rTListView); // force TListView::Streamer to be linked in
_OWLLINK(rTEditView); // force TEditView::Streamer to be linked in
EditTemplate atpl("Text files, EditView", "*.txt", 0, "TXT", dtAutoDelete|dtUpdateDir);
ListTemplate btpl("Text files, ListView", "*.txt", 0, "TXT", dtAutoDelete|dtUpdateDir);
ListTemplate ctpl("Batch files, ListView", "*.bat", 0, "BAT", dtAutoDelete|dtUpdateDir);
EditTemplate dtpl("Source files, EditView", "*.cpp;*.h",0,0,dtAutoDelete|dtUpdateDir);
@@ -0,0 +1,5 @@
//----------------------------------------------------------------------------
// ObjectWindows - (C) Copyright 1993 by Borland International
//----------------------------------------------------------------------------
#include <owl\listview.rc>
#include <owl\editview.rc>
@@ -0,0 +1,205 @@
//----------------------------------------------------------------------------
// ObjectWindows - (C) Copyright 1993 by Borland International
// Implements class TInfoView
//----------------------------------------------------------------------------
#include <owl\owlpch.h>
#include <owl\docmanag.h>
#include <owl\filedoc.h>
#include <owl\dc.h>
#include "infoview.rc"
class _DOCVIEWCLASS TInfoView : public TWindowView {
public:
struct Data {
const char* PropName;
char* PropData;
int PropSize;
int PropFlags;
};
TInfoView(TDocument& doc, TWindow* parent = 0);
~TInfoView();
static LPCSTR StaticName() {return "Info View";} // put in resource
LPCSTR GetViewName() {return StaticName();}
BOOL SetDocTitle(LPCSTR docname, int index)
{ Invalidate(); return TWindow::SetDocTitle(docname, index); }
void Paint(TDC&, BOOL, TRect&);
protected:
Data* PropList;
int PropCount;
int YLoc;
int OpenCount; //temp
int CloseCount; //temp
void GetInfo();
void Init();
//
// event handlers
//
void CmInfoOpen();
BOOL VnViewOpened(TView*);
BOOL VnViewClosed(TView*);
BOOL VnDocOpened(int omode);
BOOL VnDocClosed(int omode);
BOOL VnIsWindow(HWND hWnd) {return HWindow == hWnd;}
DECLARE_RESPONSE_TABLE(TInfoView);
DECLARE_STREAMABLE(,TInfoView,1);
};
DEFINE_RESPONSE_TABLE1(TInfoView, TWindow)
EV_COMMAND(CM_INFOOPEN, CmInfoOpen),
EV_VN_DOCOPENED,
EV_VN_DOCCLOSED,
EV_VN_VIEWOPENED,
EV_VN_VIEWCLOSED,
EV_VN_ISWINDOW,
END_RESPONSE_TABLE;
TInfoView::TInfoView(TDocument& doc,TWindow* parent) : TWindowView(doc,parent)
{
Attr.Style &= ~(WS_BORDER);
SetViewMenu(new TMenuDescr(IDM_INFOVIEW,0,1,0,0,0,1));
Init();
}
void TInfoView::Init()
{
PropCount = Doc->PropertyCount();
PropList = new Data[PropCount];
for (int i = 0; i < PropCount; i++) {
PropList[i].PropName = Doc->PropertyName(i+1);
PropList[i].PropFlags = Doc->PropertyFlags(i+1);
PropList[i].PropData = 0;
}
OpenCount = CloseCount = 0; //temp
GetInfo();
}
TInfoView::~TInfoView()
{
for (int i = 0; i < PropCount; i++) {
delete PropList[i].PropData;
}
delete PropList;
}
void TInfoView::GetInfo()
{
BOOL changed = FALSE;
int prop;
int len;
char buf[256+1];
for (prop = 0; prop < PropCount; prop++) {
int flags = PropList[prop].PropFlags;
if ((flags & pfGetText) && !(flags & pfHidden)
&& (len = Doc->GetProperty(prop+1, buf, sizeof(buf)-1)) != 0) {
if (PropList[prop].PropData) {
if (flags & pfConstant)
continue;
if (len == PropList[prop].PropSize) {
if (strcmp(buf, PropList[prop].PropData) != 0) {
strcpy(PropList[prop].PropData, buf);
changed = TRUE;
}
continue;
}
delete PropList[prop].PropData;
}
PropList[prop].PropData = strnewdup(buf);
PropList[prop].PropSize = len;
changed = TRUE;
}
}
if (changed)
Invalidate();
}
// len = wsprintf(buf, "Document State: %s (Opens=%d Closes=%d)", (char far*)(Doc->IsOpen() ? "Open" : "Closed"),OpenCount,CloseCount);
void TInfoView::Paint(TDC& dc, BOOL /*erase*/, TRect&)
{
TSize size;
static char separator[] = " = ";
int sepsize;
int prop;
YLoc = 0;
dc.GetTextExtent(separator, sizeof(separator)-1, size);
sepsize = size.cx;
for (prop = 0; prop < PropCount; prop++) {
if (!PropList[prop].PropData)
continue;
int len = strlen(PropList[prop].PropName);
dc.GetTextExtent( PropList[prop].PropName, len, size);
dc.TextOut(0, YLoc, PropList[prop].PropName, len);
dc.TextOut(size.cx, YLoc, separator, sizeof(separator)-1);
dc.TextOut(size.cx+sepsize, YLoc, PropList[prop].PropData,
strlen(PropList[prop].PropData));
YLoc += size.cy;
}
}
void
TInfoView::CmInfoOpen()
{
if (!Doc->IsOpen()
&& Doc->GetDocPath() != 0
&& Doc->Open(ofRead | shReadWrite | ofNoCreate | ofPriority)) {
// GetInfo();
Doc->Close();
OpenCount--; CloseCount--;
}
}
BOOL
TInfoView::VnViewOpened(TView*)
{
GetInfo();
return TRUE;
}
BOOL
TInfoView::VnViewClosed(TView*)
{
GetInfo();
return TRUE;
}
BOOL
TInfoView::VnDocOpened(int)
{
++OpenCount;
GetInfo();
return TRUE;
}
BOOL
TInfoView::VnDocClosed(int)
{
++CloseCount;
GetInfo();
return TRUE;
}
IMPLEMENT_STREAMABLE1(TInfoView, TWindowView);
void*
TInfoView::Streamer::Read(ipstream& is, uint32 /*version*/) const
{
ReadBaseObject((TWindowView*)GetObject(), is);
GetObject()->Init();
return GetObject();
}
void
TInfoView::Streamer::Write(opstream &os) const
{
WriteBaseObject((TWindowView*)GetObject(), os);
}
DEFINE_DOC_TEMPLATE_CLASS(TFileDocument, TInfoView, InfoTemplate);
InfoTemplate infoTpl("InfoView, All files", "*.*", 0, 0,dtAutoDelete|dtReadOnly);
@@ -0,0 +1,28 @@
//----------------------------------------------------------------------------
// ObjectWindows - (C) Copyright 1993 by Borland International
// Menu and accelerators for use with TInfoView
//----------------------------------------------------------------------------
#define CM_INFOOPEN 24521
#define IDM_INFOVIEW 31521
#if defined(RC_INVOKED)
IDM_INFOVIEW MENU LOADONCALL MOVEABLE PURE DISCARDABLE
BEGIN
POPUP "&Edit"
BEGIN
MenuItem "&Open", CM_INFOOPEN
END
POPUP "&Help"
BEGIN
MenuItem "OWL InfoView", 0, INACTIVE
END
END
STRINGTABLE LOADONCALL MOVEABLE DISCARDABLE
BEGIN
CM_INFOOPEN, "Opens the file to get info"
END
#endif // defined(RC_INVOKED)
@@ -0,0 +1,836 @@
//----------------------------------------------------------------------------
// ObjectWindows - (C) Copyright 1991, 1993 by Borland International
// Implements classes TDrawDocument, TDrawView, TDrawListView
//----------------------------------------------------------------------------
#include <owl\owlpch.h>
#include <owl\docmanag.h>
#include <owl\filedoc.h>
#include <owl\dc.h>
#include <owl\inputdia.h>
#include <owl\chooseco.h>
#include <owl\gdiobjec.h>
#include <owl\listbox.h>
#include <owl\docview.h>
#include <classlib\arrays.h>
#include "linedoc.rc"
typedef TArray<TPoint> TPoints;
typedef TArrayIterator<TPoint> TPointsIterator;
class TLine : public TPoints {
public:
// Constructor to allow construction from a color and a pen size.
// Also serves as default constructor.
TLine(const TColor &color = TColor(0), int penSize = 1)
: TPoints(10, 0, 10), PenSize(penSize), Color(color) {}
// Functions to modify and query pen attributes.
int QueryPenSize() const { return PenSize; }
const TColor& QueryColor() const { return Color; }
void SetPen(TColor &newColor, int penSize = 0);
void SetPen(int penSize);
BOOL GetPenSize();
BOOL GetPenColor();
// TLine draws itself. Returns TRUE if everything went OK.
virtual BOOL Draw(TDC &) const;
// The == operator must be defined for the container class, even if unused
BOOL operator ==(const TLine& other) const { return &other == this; }
friend ostream& operator <<(ostream& os, const TLine& line);
friend istream& operator >>(istream& is, TLine& line);
protected:
int PenSize;
TColor Color;
};
typedef TArray<TLine> TLines;
typedef TArrayIterator<TLine> TLinesIterator;
class _DOCVIEWCLASS TDrawDocument : public TFileDocument
{
public:
enum {
PrevProperty = TFileDocument::NextProperty-1,
LineCount,
Description,
NextProperty,
};
enum {
UndoNone,
UndoDelete,
UndoAppend,
UndoModify
};
TDrawDocument(TDocument* parent = 0)
: TFileDocument(parent), Lines(0), UndoLine(0), UndoState(UndoNone) {}
~TDrawDocument() { delete Lines; delete UndoLine; }
// implement virtual methods of TDocument
BOOL Open(int mode, const char far* path=0);
BOOL Close();
BOOL IsOpen() { return Lines != 0; }
BOOL Commit(BOOL force = FALSE);
BOOL Revert(BOOL clear = FALSE);
int FindProperty(const char far* name); // return index
int PropertyFlags(int index);
const char* PropertyName(int index);
int PropertyCount() {return NextProperty - 1;}
int GetProperty(int index, void far* dest, int textlen=0);
// data access functions
const TLine* GetLine(unsigned int index);
int AddLine(TLine& line);
void DeleteLine(unsigned int index);
void ModifyLine(TLine& line, unsigned int index);
void Clear();
void Undo();
protected:
TLines* Lines;
TLine* UndoLine;
int UndoState;
int UndoIndex;
string FileInfo;
DECLARE_STREAMABLE(, TDrawDocument,1);
};
class _DOCVIEWCLASS TDrawView : public TWindowView
{
public:
TDrawView(TDrawDocument& doc, TWindow *parent = 0);
~TDrawView() {delete DragDC; delete Line;}
static const char far* StaticName() {return "Draw View";}
const char far* GetViewName(){return StaticName();}
protected:
TDrawDocument* DrawDoc; // same as Doc member, but cast to derived class
TDC *DragDC;
TPen *Pen;
TLine *Line; // To hold a single line sent or received from document
// Message response functions
void EvLButtonDown(UINT, TPoint&);
void EvRButtonDown(UINT, TPoint&);
void EvMouseMove(UINT, TPoint&);
void EvLButtonUp(UINT, TPoint&);
void Paint(TDC&, BOOL, TRect&);
void CmPenSize();
void CmPenColor();
void CmClear();
void CmUndo();
// Document notifications
BOOL VnCommit(BOOL force);
BOOL VnRevert(BOOL clear);
BOOL VnAppend(unsigned int index);
BOOL VnDelete(unsigned int index);
BOOL VnModify(unsigned int index);
DECLARE_RESPONSE_TABLE(TDrawView);
DECLARE_STREAMABLE(,TDrawView,1);
};
class _DOCVIEWCLASS TDrawListView : public TListBox, public TView {
public:
TDrawListView(TDrawDocument& doc, TWindow* parent = 0);
~TDrawListView(){}
static const char far* StaticName() {return "DrawList View";}
// Overridden virtuals from TView
//
const char far* GetViewName(){return StaticName();}
TWindow* GetWindow() {return (TWindow*)this;}
BOOL SetDocTitle(const char far* docname, int index)
{return TListBox::SetDocTitle(docname, index); }
// Overridden virtuals from TWindow
//
BOOL CanClose() {return TListBox::CanClose() && Doc->CanClose();}
BOOL Create();
protected:
TDrawDocument* DrawDoc; // same as Doc member, but cast to derived class
void LoadData();
void FormatData(const TLine* line, unsigned int index);
// Message response functions
void CmPenSize();
void CmPenColor();
void CmClear();
void CmUndo();
void CmDelete();
// Document notifications
BOOL VnIsWindow(HWND hWnd) {return HWindow == hWnd;}
BOOL VnCommit(BOOL force);
BOOL VnRevert(BOOL clear);
BOOL VnAppend(unsigned int index);
BOOL VnDelete(unsigned int index);
BOOL VnModify(unsigned int index);
DECLARE_RESPONSE_TABLE(TDrawListView);
DECLARE_STREAMABLE(,TDrawListView,1);
};
const int vnDrawAppend = vnCustomBase+0;
const int vnDrawDelete = vnCustomBase+1;
const int vnDrawModify = vnCustomBase+2;
NOTIFY_SIG(vnDrawAppend, unsigned int)
NOTIFY_SIG(vnDrawDelete, unsigned int)
NOTIFY_SIG(vnDrawModify, unsigned int)
#define EV_VN_DRAWAPPEND VN_DEFINE(vnDrawAppend, VnAppend, int)
#define EV_VN_DRAWDELETE VN_DEFINE(vnDrawDelete, VnDelete, int)
#define EV_VN_DRAWMODIFY VN_DEFINE(vnDrawModify, VnModify, int)
DEFINE_DOC_TEMPLATE_CLASS(TDrawDocument, TDrawView, DrawTemplate);
DEFINE_DOC_TEMPLATE_CLASS(TDrawDocument, TDrawListView, DrawListTemplate);
DrawTemplate drawTpl("Draw Line Files (*.PTS)","*.pts",0,"PTS",dtAutoDelete|dtUpdateDir);
DrawListTemplate drawListTpl("Line List"," *.pts",0,"PTS",dtAutoDelete|dtHidden);
void TLine::SetPen(int penSize)
{
if (penSize < 1)
PenSize = 1;
else
PenSize = penSize;
}
void TLine::SetPen(TColor &newColor, int penSize)
{
// If penSize isn't the default (0), set PenSize to the new size.
if (penSize)
PenSize = penSize;
Color = newColor;
}
BOOL TLine::Draw(TDC &dc) const
{
// Set pen for the dc to the values for this line
TPen pen(Color, PenSize);
dc.SelectObject(pen);
// Iterates through the points in the line i.
TPointsIterator j(*this);
BOOL first = TRUE;
while (j) {
TPoint p = j++;
if (!first)
dc.LineTo(p);
else {
dc.MoveTo(p);
first = FALSE;
}
}
dc.RestorePen();
return TRUE;
}
ostream& operator <<(ostream& os, const TLine& line)
{
// Write the number of points in the line
os << line.GetItemsInContainer();
// Get and write pen attributes.
os << ' ' << line.Color << ' ' << line.PenSize;
// Get an iterator for the array of points
TPointsIterator j(line);
// While the iterator is valid (i.e. we haven't run out of points)
while(j)
// Write the point from the iterator and increment the array.
os << j++;
os << '\n';
// return the stream object
return os;
}
istream& operator >>(istream& is, TLine& line)
{
unsigned numPoints;
is >> numPoints;
COLORREF color;
int penSize;
is >> color >> penSize;
line.SetPen(TColor(color), penSize);
while (numPoints--) {
TPoint point;
is >> point;
line.Add(point);
}
// return the stream object
return is;
}
BOOL TDrawDocument::Commit(BOOL force)
{
if (!IsDirty() && !force)
return TRUE;
TOutStream* os = OutStream(ofWrite);
if (!os)
return FALSE;
// Write the number of lines in the figure
*os << Lines->GetItemsInContainer();
// Append a description using a resource string
*os << ' ' << FileInfo << '\n';
// Get an iterator for the array of lines
TLinesIterator i(*Lines);
// While the iterator is valid (i.e. we haven't run out of lines)
while (i) {
// Copy the current line from the iterator and increment the array.
*os << i++;
}
delete os;
SetDirty(FALSE);
return TRUE;
}
BOOL TDrawDocument::Revert(BOOL clear)
{
if (!TFileDocument::Revert(clear))
return FALSE;
if (!clear)
Open(0);
return TRUE;
}
BOOL TDrawDocument::Open(int /*mode*/, const char far* path)
{
char fileinfo[100];
Lines = new TLines(5, 0, 5);
if (path)
SetDocPath(path);
if (GetDocPath()) {
TInStream* is = InStream(ofRead);
if (!is)
return FALSE;
unsigned numLines;
*is >> numLines;
is->getline(fileinfo, sizeof(fileinfo));
while (numLines--) {
TLine line;
*is >> line;
Lines->Add(line);
}
delete is;
FileInfo = fileinfo;
} else {
FileInfo = string(*::Module,IDS_FILEINFO);
}
SetDirty(FALSE);
UndoState = UndoNone;
return TRUE;
}
BOOL TDrawDocument::Close()
{
delete Lines;
Lines = 0;
return TRUE;
}
const TLine* TDrawDocument::GetLine(unsigned int index)
{
if (!IsOpen() && !Open(ofRead | ofWrite))
return 0;
return index < Lines->GetItemsInContainer() ? &(*Lines)[index] : 0;
}
int TDrawDocument::AddLine(TLine& line)
{
int index = Lines->GetItemsInContainer();
Lines->Add(line);
SetDirty(TRUE);
NotifyViews(vnDrawAppend, index);
UndoState = UndoAppend;
return index;
}
void TDrawDocument::DeleteLine(unsigned int index)
{
const TLine* oldLine = GetLine(index);
if (!oldLine)
return;
delete UndoLine;
UndoLine = new TLine(*oldLine);
Lines->Detach(index);
SetDirty(TRUE);
NotifyViews(vnDrawDelete, index);
UndoState = UndoDelete;
}
void TDrawDocument::ModifyLine(TLine& line, unsigned int index)
{
delete UndoLine;
UndoLine = new TLine((*Lines)[index]);
SetDirty(TRUE);
(*Lines)[index] = line;
NotifyViews(vnDrawModify, index);
UndoState = UndoModify;
UndoIndex = index;
}
void TDrawDocument::Clear()
{
Lines->Flush();
NotifyViews(vnRevert, TRUE);
}
void TDrawDocument::Undo()
{
switch (UndoState) {
case UndoAppend:
DeleteLine(Lines->GetItemsInContainer()-1);
return;
case UndoDelete:
AddLine(*UndoLine);
delete UndoLine;
UndoLine = 0;
return;
case UndoModify:
TLine* temp = UndoLine;
UndoLine = 0;
ModifyLine(*temp, UndoIndex);
delete temp;
}
}
BOOL TLine::GetPenSize()
{
char inputText[6];
wsprintf(inputText, "%d", PenSize);
if (TInputDialog(0, "Line Thickness",
"Input a new thickness:",
inputText,
sizeof(inputText),::Module).Execute() != IDOK)
return FALSE;
PenSize = atoi(inputText);
if (PenSize < 1)
PenSize = 1;
return TRUE;
}
BOOL TLine::GetPenColor()
{
TChooseColorDialog::TData colors;
static TColor custColors[16] =
{
0x010101L, 0x101010L, 0x202020L, 0x303030L,
0x404040L, 0x505050L, 0x606060L, 0x707070L,
0x808080L, 0x909090L, 0xA0A0A0L, 0xB0B0B0L,
0xC0C0C0L, 0xD0D0D0L, 0xE0E0E0L, 0xF0F0F0L
};
colors.Flags = CC_RGBINIT;
colors.Color = TColor(QueryColor());
colors.CustColors = custColors;
if (TChooseColorDialog(0, colors).Execute() != IDOK)
return FALSE;
SetPen(colors.Color);
return TRUE;
}
DEFINE_RESPONSE_TABLE1(TDrawView, TWindowView)
EV_WM_LBUTTONDOWN,
EV_WM_RBUTTONDOWN,
EV_WM_MOUSEMOVE,
EV_WM_LBUTTONUP,
EV_COMMAND(CM_PENSIZE, CmPenSize),
EV_COMMAND(CM_PENCOLOR, CmPenColor),
EV_COMMAND(CM_CLEAR, CmClear),
EV_COMMAND(CM_UNDO, CmUndo),
EV_VN_COMMIT,
EV_VN_REVERT,
EV_VN_DRAWAPPEND,
EV_VN_DRAWDELETE,
EV_VN_DRAWMODIFY,
END_RESPONSE_TABLE;
TDrawView::TDrawView(TDrawDocument& doc,TWindow *parent)
: TWindowView(doc,parent), DrawDoc(&doc)
{
DragDC = 0;
Line = new TLine(TColor::Black, 1);
SetViewMenu(new TMenuDescr(IDM_DRAWVIEW,0,2,0,0,0,1));
}
void TDrawView::EvLButtonDown(UINT, TPoint& point)
{
if (!DragDC) {
SetCapture();
DragDC = new TClientDC(*this);
Pen = new TPen(Line->QueryColor(), Line->QueryPenSize());
DragDC->SelectObject(*Pen);
DragDC->MoveTo(point);
Line->Add(point);
}
}
void TDrawView::EvRButtonDown(UINT, TPoint&)
{
CmUndo();
}
void TDrawView::EvMouseMove(UINT, TPoint& point)
{
if (DragDC) {
DragDC->LineTo(point);
Line->Add(point);
}
}
void TDrawView::EvLButtonUp(UINT, TPoint&)
{
if (DragDC) {
ReleaseCapture();
if (Line->GetItemsInContainer() > 1)
DrawDoc->AddLine(*Line);
Line->Flush();
delete DragDC;
delete Pen;
DragDC = 0;
}
}
void TDrawView::CmPenSize()
{
Line->GetPenSize();
}
void TDrawView::CmPenColor()
{
Line->GetPenColor();
}
void TDrawView::CmClear()
{
DrawDoc->Clear();
}
void TDrawView::CmUndo()
{
DrawDoc->Undo();
}
void TDrawView::Paint(TDC& dc, BOOL, TRect&)
{
// Iterates through the array of line objects.
int i = 0;
const TLine* line;
while ((line = DrawDoc->GetLine(i++)) != 0)
line->Draw(dc);
}
BOOL TDrawView::VnCommit(BOOL /*force*/)
{
// nothing to do here, no data held in view
return TRUE;
}
BOOL TDrawView::VnRevert(BOOL /*clear*/)
{
Invalidate(); // force full repaint
return TRUE;
}
BOOL TDrawView::VnAppend(unsigned int index)
{
TClientDC dc(*this);
const TLine* line = DrawDoc->GetLine(index);
line->Draw(dc);
return TRUE;
}
BOOL TDrawView::VnModify(unsigned int /*index*/)
{
Invalidate(); // force full repaint
return TRUE;
}
BOOL TDrawView::VnDelete(unsigned int /*index*/)
{
Invalidate(); // force full repaint
return TRUE;
}
DEFINE_RESPONSE_TABLE1(TDrawListView, TListBox)
EV_COMMAND(CM_PENSIZE, CmPenSize),
EV_COMMAND(CM_PENCOLOR, CmPenColor),
EV_COMMAND(CM_CLEAR, CmClear),
EV_COMMAND(CM_UNDO, CmUndo),
EV_COMMAND(CM_DELETE, CmDelete),
EV_VN_ISWINDOW,
EV_VN_COMMIT,
EV_VN_REVERT,
EV_VN_DRAWAPPEND,
EV_VN_DRAWDELETE,
EV_VN_DRAWMODIFY,
END_RESPONSE_TABLE;
TDrawListView::TDrawListView(TDrawDocument& doc,TWindow *parent)
: TView(doc), TListBox(parent, GetNextViewId(), 0,0,0,0), DrawDoc(&doc)
{
Attr.Style &= ~(WS_BORDER | LBS_SORT);
Attr.AccelTable = IDA_DRAWLISTVIEW;
SetViewMenu(new TMenuDescr(IDM_DRAWLISTVIEW,0,1,0,0,0,1));
}
BOOL TDrawListView::Create()
{
TListBox::Create();
LoadData();
return TRUE;
}
void TDrawListView::LoadData()
{
ClearList();
int i = 0;
const TLine* line;
while ((line = DrawDoc->GetLine(i)) != 0)
FormatData(line, i++);
SetSelIndex(0);
}
void TDrawListView::FormatData(const TLine* line, int unsigned index)
{
char buf[80];
TColor color(line->QueryColor());
wsprintf(buf, "Color = R%d G%d B%d, Size = %d, Points = %d",
color.Red(), color.Green(), color.Blue(),
line->QueryPenSize(), line->GetItemsInContainer());
DeleteString(index);
InsertString(buf, index);
SetSelIndex(index);
}
void TDrawListView::CmPenSize()
{
int index = GetSelIndex();
const TLine* line = DrawDoc->GetLine(index);
if (line) {
TLine* newline = new TLine(*line);
if (newline->GetPenSize())
DrawDoc->ModifyLine(*newline, index);
delete newline;
}
}
void TDrawListView::CmPenColor()
{
int index = GetSelIndex();
const TLine* line = DrawDoc->GetLine(index);
if (line) {
TLine* newline = new TLine(*line);
if (newline->GetPenColor())
DrawDoc->ModifyLine(*newline, index);
delete newline;
}
}
void TDrawListView::CmClear()
{
DrawDoc->Clear();
}
void TDrawListView::CmUndo()
{
DrawDoc->Undo();
}
void TDrawListView::CmDelete()
{
DrawDoc->DeleteLine(GetSelIndex());
}
BOOL TDrawListView::VnCommit(BOOL /*force*/)
{
return TRUE;
}
BOOL TDrawListView::VnRevert(BOOL /*clear*/)
{
LoadData();
return TRUE;
}
BOOL TDrawListView::VnAppend(unsigned int index)
{
const TLine* line = DrawDoc->GetLine(index);
FormatData(line, index);
SetSelIndex(index);
return TRUE;
}
BOOL TDrawListView::VnDelete(unsigned int index)
{
DeleteString(index);
HandleMessage(WM_KEYDOWN,VK_DOWN); // force selection
return TRUE;
}
BOOL TDrawListView::VnModify(unsigned int index)
{
const TLine* line = DrawDoc->GetLine(index);
FormatData(line, index);
return TRUE;
}
static char* PropNames[] = {
"Line Count", // LineCount
"Description", // Description
};
static int PropFlags[] = {
pfGetBinary|pfGetText, // LineCount
pfGetText, // Description
};
const char*
TDrawDocument::PropertyName(int index)
{
if (index <= PrevProperty)
return TFileDocument::PropertyName(index);
else if (index < NextProperty)
return PropNames[index-PrevProperty-1];
else
return 0;
}
int
TDrawDocument::PropertyFlags(int index)
{
if (index <= PrevProperty)
return TFileDocument::PropertyFlags(index);
else if (index < NextProperty)
return PropFlags[index-PrevProperty-1];
else
return 0;
}
int
TDrawDocument::FindProperty(const char far* name)
{
for (int i=0; i < NextProperty-PrevProperty-1; i++)
if (strcmp(PropNames[i], name) == 0)
return i+PrevProperty+1;
return 0;
}
int
TDrawDocument::GetProperty(int prop, void far* dest, int textlen)
{
if (IsOpen())
switch(prop)
{
case LineCount:
{
int count = Lines->GetItemsInContainer();
if (!textlen) {
*(int far*)dest = count;
return sizeof(int);
}
return wsprintf((char far*)dest, "%d", count);
}
case Description:
char* temp = new char[textlen]; // need local copy for medium model
int len = FileInfo.copy(temp, textlen);
strcpy((char far*)dest, temp);
return len;
}
return TFileDocument::GetProperty(prop, dest, textlen);
}
IMPLEMENT_STREAMABLE1(TDrawDocument, TFileDocument);
void*
TDrawDocument::Streamer::Read(ipstream& is, uint32 /*version*/) const
{
TDrawDocument* o = GetObject();
o->UndoState = UndoNone;
o->UndoLine = 0;
o->Lines = 0;
ReadBaseObject((TFileDocument*)o, is);
return o;
}
void
TDrawDocument::Streamer::Write(opstream& os) const
{
WriteBaseObject((TFileDocument*)GetObject(), os);
}
IMPLEMENT_STREAMABLE1(TDrawView, TWindowView);
void*
TDrawView::Streamer::Read(ipstream& is, uint32 /*version*/) const
{
TDrawView* o = GetObject();
ReadBaseObject((TWindowView*)o, is);
is >> o->DrawDoc;
int width;
COLORREF color;
is >> width >> color;
o->Line = new TLine(TColor(color), width);
o->DragDC = 0;
return o;
}
void
TDrawView::Streamer::Write(opstream &os) const
{
TDrawView* o = GetObject();
WriteBaseObject((TWindowView*)o, os);
os << o->DrawDoc;
os << o->Line->QueryPenSize();
os << COLORREF(o->Line->QueryColor());
}
IMPLEMENT_STREAMABLE2(TDrawListView, TListBox, TView);
void*
TDrawListView::Streamer::Read(ipstream& is, uint32 /*version*/) const
{
TDrawListView* o = GetObject();
ReadBaseObject((TListBox*)o, is);
ReadBaseObject((TView*)o, is);
is >> o->DrawDoc;
return o;
}
void
TDrawListView::Streamer::Write(opstream &os) const
{
TDrawListView* o = GetObject();
WriteBaseObject((TListBox*)o, os);
WriteBaseObject((TView*)o, os);
os << o->DrawDoc;
}

Binary file not shown.
@@ -0,0 +1,71 @@
//----------------------------------------------------------------------------
// ObjectWindows - (C) Copyright 1991, 1993 by Borland International
// Resources for TDrawView and TDrawListView
//----------------------------------------------------------------------------
#define CM_PENSIZE 206
#define CM_PENCOLOR 207
#define CM_UNDO 208
#define CM_CLEAR 209
#define CM_DELETE 210
#define IDM_DRAWVIEW 212
#define IDM_DRAWLISTVIEW 213
#define IDA_DRAWLISTVIEW 213
#define IDS_FILEINFO 215
#ifdef RC_INVOKED
#include <owl\inputdia.rc>
IDM_DRAWVIEW MENU
{
POPUP "&Edit"
{
MENUITEM "&Undo", CM_UNDO
MENUITEM "&Clear", CM_CLEAR
}
POPUP "&Tools"
{
MENUITEM "Pen &Size", CM_PENSIZE
MENUITEM "Pen &Color", CM_PENCOLOR
}
POPUP "&Help"
{
MENUITEM "OWL Line Draw", 0, INACTIVE
}
}
IDM_DRAWLISTVIEW MENU
{
POPUP "&Edit"
{
MENUITEM "Pen &Size", CM_PENSIZE
MENUITEM "Pen &Color", CM_PENCOLOR
MENUITEM "&Delete Line",CM_DELETE
MENUITEM "&Undo", CM_UNDO
MENUITEM "Clear All", CM_CLEAR
}
POPUP "&Help"
{
MENUITEM "OWL Line Draw List", 0, INACTIVE
}
}
IDA_DRAWLISTVIEW ACCELERATORS
BEGIN
VK_DELETE, CM_DELETE, VIRTKEY, SHIFT
VK_BACK, CM_UNDO, VIRTKEY, ALT
END
STRINGTABLE
{
CM_PENSIZE, "Changes the pen width"
CM_PENCOLOR, "Changes the pen color"
CM_DELETE, "Erase selected line"
CM_CLEAR, "Erase all lines"
CM_UNDO, "Undo last action"
IDS_FILEINFO, "Lines from TLineDocument"
}
#endif // RC_INVOKED
@@ -0,0 +1,62 @@
#----------------------------------------------------------------------------
# ObjectWindows - (C) Copyright 1993 by Borland International
# Use MODEL=m|l|d|f to statically link documents and viewers to application
# Use MODEL=x to build dynamically loaded document/view components
#
# This example combines an empty desktop with a variety of documents/views.
# The list of document/view modules is specified below by DOCVIEW = {obj list}.
# Document/view object files may be added or removed as desired from this list.
# Each document/view file must include document template(s) for their classes.
# The following document/view files are included in this examples:
# editlist.cpp - templates only, uses ObjectWindows TListView and TEditView
# dumpview.cpp - hex dump viewer/editor using TFileDocument
# odlistvw.cpp - owner-draw listbox viewer derived from example TODListBox
# infoview.cpp - viewer which displays all properties from any document
# xcptview.cpp - view which generates and logs a variety of exceptions
# linedoc.cpp - graphic line document with graphic and listbox viewers
# dvloader.cpp - pseudo-document & template used to load doc/view components
# These modules may be statically linked with the base application, or may be
# linked as DLL's for dynamic loading (dvloader must be statically linked).
#
# This application uses command-line switches to select the main frame class:
# -s SDI plain main window (TFrameWindow)
# -m MDI plain main window (TDecoratedFrame)
# -d SDI main window with status bar (TDecoratedFrame)
# (no switch) MDI main window with status bar (TDecoratedMDIFrame)
#
# Drag and drop from the file manager is supported by creating a document and
# view from the first document template with a matching file filter. Template
# order is dependent on the link ordering. In the dynmically built doc/view
# model, doc/view components (*.DVC) may be dropped or loaded from FileOpen.
#----------------------------------------------------------------------------
MODELS = mldfx
EXE = docviewx
DOCVIEW= editlist.obj dumpview.obj linedoc.obj xcptview.obj infoview.obj odlistvw.obj
!if "$(MODEL)" != "x" # static link of all document/view modules
OBJEXE = docviewx.obj odlistbx.obj $(DOCVIEW)
RESEXE = docviewx.res $(DOCVIEW:obj=res)
!include $(BCEXAMPLEDIR)\owlmake.gen
EXERULE = $(EXERULE) @echo Ignore previous warning about duplicate resource
!else # build each document/view module into a DLL, static link of dvloader
EXEBIN = docviewc.exe
OBJEXE = docviewx.obj dvloader.obj
RESEXE = docviewx.res dvloader.res
DLLRES = editlist
DLLBIN = editlist.dvc
DLLALL = $(DOCVIEW:obj=dvc)
DLLMAKE= $(EDITLIST) $(INFOVIEW) $(LINEDOC) $(XCPTVIEW) $(DUMPVIEW) $(ODLISTVW)
EDITLIST = $(DLLRULE:editlist.res=)
XCPTVIEW = $(DLLRULE:editlist=xcptview)
DUMPVIEW = $(DLLRULE:editlist=dumpview)
INFOVIEW = $(DLLRULE:editlist=infoview)
LINEDOC = $(DLLRULE:editlist=linedoc)
ODLISTX = $(DLLRULE:editlist=odlistvw)
ODLISTVW = $(ODLISTX:odlistvw.obj=odlistbx.obj odlistvw.obj)
!include $(BCEXAMPLEDIR)\owlmake.gen
!endif
@@ -0,0 +1,159 @@
//----------------------------------------------------------------------------
// ObjectWindows - (C) Copyright 1992, 1993 by Borland International
// Implements class TODListBox
//----------------------------------------------------------------------------
#include <owl\owlpch.h>
#include "odlistbx.h"
TODListBox::TODListBox(int id)
: TControl(0, id, 0, 0,0, 100,100), BufTemp(0), BufLen(0), MaxWidth(0)
{
Attr.Style &= ~(LBS_SORT | LBS_HASSTRINGS | LBS_MULTIPLESEL);
Attr.Style |= (LBS_NOTIFY | WS_VSCROLL | WS_HSCROLL | WS_BORDER | LBS_OWNERDRAWVARIABLE);
}
char far *
TODListBox::GetClassName()
{
return "LISTBOX";
}
void TODListBox::ItemRedraw(int index) // force item to be redrawn
{
TRect rect;
if (GetItemRect(index, rect) <= 0)
return; // return 1 if OK, -1 if error
InvalidateRect(rect);
}
void TODListBox::DrawItem(DRAWITEMSTRUCT far & dis)
{
ODItemInfo item;
UINT action = dis.itemAction;
item.Hdc = dis.hDC;
item.State = dis.itemState;
item.Data = (void far*) dis.itemData;
item.Index = dis.itemID;
item.Bound.Set(dis.rcItem.left, dis.rcItem.top,
dis.rcItem.right,dis.rcItem.bottom);
if (item.Index < 0)
return; // ignore if empty listbox, no focus rect?
GetItemInfo(item); // must fill in: Extent,Text,TextLen,Offset
if (action & ODA_DRAWENTIRE){
// // shift the item rect to account for horizontal scrolling
//if (item.Bound.right > clientrect.right)
// item.Bound.left = -(item.Bound.right - clientrect.right);
if (item.Extent.cx > MaxWidth) {
SetHorizontalExtent(MaxWidth = item.Extent.cx);
}
DrawItemData(item);
action = 0; // redraw destoys previous focus and selection painting
if (item.State & ODS_SELECTED) action |= ODA_SELECT;
if (item.State & ODS_FOCUS) action |= ODA_FOCUS;
}
if (action & ODA_SELECT) {
ChangeHilight(item);
}
if (action & ODA_FOCUS){
item.Bound.right = item.Extent.cx; // focus drawn around entire item
ChangeFocus(item);
}
}
void TODListBox::MeasureItem (MEASUREITEMSTRUCT far& mis)
{
ODItemInfo item;
item.Hdc = ::GetDC(*this);
item.Data = (void far*) mis.itemData;
item.Index = mis.itemID;
item.State = 0;
GetItemInfo(item);
mis.itemHeight = item.Extent.cy;
mis.itemWidth = item.Extent.cx;
if (item.Extent.cx > MaxWidth) {
SetHorizontalExtent(MaxWidth = item.Extent.cx);
}
::ReleaseDC(*this, item.Hdc);
}
// The following methods are defaults for use with text string items only.
// These must be overridden if for data items that are not standard text.
// If the style LBS_HASSTRINGS is set, strings are stored within the list box.
// Otherwise only the pointers are stored; data must be managed by the caller.
BOOL TODListBox::GetItemInfo(ODItemInfo& item) {
LPSTR str;
int len;
if (Attr.Style & LBS_HASSTRINGS) { // strings stored in list box
len = GetStringLen(item.Index);
if (len == 0) {
str = 0;
} else {
if (len >= BufLen){ // check temporary buffer size
if (BufTemp) delete BufTemp;
BufTemp = new char[BufLen = len+1];
}
GetString(str = BufTemp, item.Index);
}
} else { // assume text pointer is allocated data stored in item data
str = (char far*)item.Data;
len = str ? lstrlen(str) : 0;
}
item.TextLen = len;
item.Text = str;
if (!len) {
str = " "; // must have text to measure
len++;
}
GetTextExtentPoint(item.Hdc, str, len, &item.Extent);
item.Extent.cx += 2; // room for focus rectangle
item.Extent.cy += 2; // room for focus rectangle
item.Offset.x = 1; // room for focus rectangle, no indentation
item.Offset.y = 1; // room for focus rectangle
return TRUE; // OK to draw
}
void TODListBox::ChangeHilight(ODItemInfo& item)
{
InvertRect(item.Hdc, &item.Bound); // need to fix to do nicer!!
}
void TODListBox::ChangeFocus(ODItemInfo& item)
{
int brushtype = item.State & ODS_FOCUS ? LTGRAY_BRUSH
:(item.State & ODS_SELECTED ? BLACK_BRUSH : WHITE_BRUSH);
FrameRect(item.Hdc, &item.Bound, (HBRUSH)GetStockObject(brushtype));
}
void TODListBox::DrawItemData(ODItemInfo& item)
{
//HFONT oldfont = SelectObject(item.Hdc, StdFont); // need member HFONT StdFont
ExtTextOut(item.Hdc,
item.Bound.left + item.Offset.x,
item.Bound.top + item.Offset.y,
ETO_CLIPPED | ETO_OPAQUE,
&item.Bound,
item.Text, item.TextLen,
(LPINT) NULL); /* default char spacing */
//SelectObject(item.Hdc, oldfont);
}
IMPLEMENT_STREAMABLE1(TODListBox, TControl);
void*
TODListBox::Streamer::Read(ipstream& is, uint32 /*version*/) const
{
ReadBaseObject((TControl*)GetObject(), is);
is >> GetObject()->MaxWidth;
GetObject()->BufTemp = 0;
GetObject()->BufLen = 0;
return GetObject();
}
void
TODListBox::Streamer::Write(opstream& os) const
{
WriteBaseObject((TControl*)GetObject(), os);
os << GetObject()->MaxWidth;
}
@@ -0,0 +1,200 @@
//----------------------------------------------------------------------------
// ObjectWindows - (C) Copyright 1992, 1993 by Borland International
// Defines class TODListBox
//----------------------------------------------------------------------------
#ifndef __OWL_ODLISTBX_H
#define __OWL_ODLISTBX_H
#ifndef __OWL_CONTROL_H
#include <owl\control.h>
#endif
class TODListBox : public TControl {
public:
struct ODItemInfo { // temporary information about current item
// the following are supplied to the GetItemInfo function:
HDC Hdc; // display context for listbox
int Index; // index of current item, set by Draw/MeasureItem
void far* Data; // user item data value, set by Draw/MeasureItem
UINT State; // ODS_xxxx flags for new state, set by Draw/MeasureItem
TRect Bound; // actual drawing area bounds
// the following are to be set by the GetItemInfo function:
TSize Extent; // cell size to display entire data
TPoint Offset; // offset in rect of drawn data
char far* Text; // pointer to text data to draw
int TextLen; // length of text data
};
TODListBox(int id);
~TODListBox();
//
// list box wrappers
//
virtual void ClearList();
virtual int GetCount() const;
int GetTopIndex() const;
int SetTopIndex(int index);
int GetHorizontalExtent() const;
void SetHorizontalExtent(int horzExtent);
virtual int GetStringLen(int index) const;
virtual int GetString(char far* str, int index) const;
virtual DWORD GetItemData(int index) const;
virtual int SetItemData(int index, DWORD itemData);
int GetItemRect(int index, TRect& rect) const;
virtual int GetItemHeight(int index) const;
virtual int SetItemHeight(int index, int height);
virtual int AddString(const char far* str);
virtual int InsertString(const char far* str, int index);
virtual int DeleteString(int index);
virtual int GetSelIndex() const;
virtual int SetSelIndex(int index);
//
// Override TWindow virtual member functions
//
char far *GetClassName();
virtual void ItemRedraw(int index); // force item to be redrawn
protected:
int MaxWidth; // maximum horizontal extent
char far* BufTemp; // temporary buffer for returning strings
int BufLen; // allocated length of temporary buffer
// calls eminating from TControl for WM_DRAWITEM and WM_MEASUREITEM
virtual void DrawItem (DRAWITEMSTRUCT far &);
virtual void MeasureItem (MEASUREITEMSTRUCT far &);
// calls from TODListBox::DrawItem() which must be overridden if not text
virtual BOOL GetItemInfo (ODItemInfo& item); // fill Offset, Text, TextLen
virtual void ChangeHilight(ODItemInfo& item);
virtual void ChangeFocus (ODItemInfo& item);
virtual void DrawItemData (ODItemInfo& item);
private:
//
// hidden to prevent accidental copying or assignment
//
TODListBox(const TODListBox&);
TODListBox& operator=(const TODListBox&);
DECLARE_STREAMABLE(, TODListBox, 1);
};
//----------------------------------------------------------------------------
// Inlines
//----------------------------------------------------------------------------
inline TODListBox::~TODListBox() {
if (BufTemp) delete BufTemp;
}
inline int TODListBox::GetTopIndex() const {
return (int)CONST_CAST(TODListBox*,this)->HandleMessage(LB_GETTOPINDEX);
}
inline int TODListBox::SetTopIndex(int index) {
return (int)HandleMessage(LB_SETTOPINDEX, index);
}
inline int TODListBox::GetHorizontalExtent() const {
return (int)CONST_CAST(TODListBox*,this)->HandleMessage(LB_GETHORIZONTALEXTENT);
}
inline void TODListBox::SetHorizontalExtent(int horzExtent) {
HandleMessage(LB_SETHORIZONTALEXTENT, horzExtent);
}
inline DWORD TODListBox::GetItemData(int index) const {
return CONST_CAST(TODListBox*,this)->HandleMessage(LB_GETITEMDATA, index);
}
inline int TODListBox::SetItemData(int index, DWORD itemData) {
return (int)HandleMessage(LB_SETITEMDATA, index, itemData);
}
inline int TODListBox::GetItemRect(int index, TRect& rect) const {
return (int)CONST_CAST(TODListBox*,this)->
HandleMessage(LB_GETITEMRECT, index, (LPARAM)(TRect FAR*)&rect);
}
inline int TODListBox::GetItemHeight(int index) const {
return (int)CONST_CAST(TODListBox*,this)->
HandleMessage(LB_GETITEMHEIGHT, index);
}
inline int TODListBox::SetItemHeight(int index, int height) {
return (int)HandleMessage(LB_SETITEMHEIGHT, index, MAKELPARAM(height, 0));
}
// Adds a string to an associated listbox
// Returns index of the string in the list(the first entry is at index 0),
// a negative if an error occurs.
//
inline int TODListBox::AddString(const char far* str) {
return (int)HandleMessage(LB_ADDSTRING, 0, (LPARAM)str);
}
// Inserts a string in the associated listbox at the passed index,
// returns the index of the string in the list, a negative if an error occurs
//
inline int TODListBox::InsertString(const char far* str, int index) {
return (int)HandleMessage(LB_INSERTSTRING, index, (LPARAM)str);
}
// Deletes the string at the passed index in the associated listbox
// Returns a count of the entries remaining in the list, a negative
// value if an error occurs
//
inline int TODListBox::DeleteString(int index) {
return (int)HandleMessage(LB_DELETESTRING, index);
}
// Clears all the entries in the associated listbox
//
inline void TODListBox::ClearList() {
HandleMessage(LB_RESETCONTENT);
}
// Returns the number of entries in the associated listbox, a negative
// value if an error occurs
//
inline int TODListBox::GetCount() const {
return (int)CONST_CAST(TODListBox*,this)->HandleMessage(LB_GETCOUNT);
}
// Retrieves the contents of the string at the passed index of the
// associated listbox. Returns the length of the string (in bytes
// excluding the terminating 0), a negative if the passed index is not valid
//
// The buffer must be large enough for the string and the terminating 0
//
inline int TODListBox::GetString(char far* str, int index) const {
return (int)CONST_CAST(TODListBox*,this)->
HandleMessage(LB_GETTEXT, index, (LPARAM)str);
}
// Returns the length of the string at the passed index in the associated
// listbox excluding the terminating 0, a negative if an error occurs
//
inline int TODListBox::GetStringLen(int index) const {
return (int)CONST_CAST(TODListBox*,this)->HandleMessage(LB_GETTEXTLEN, index);
}
inline int TODListBox::GetSelIndex() const {
return (int)CONST_CAST(TODListBox*,this)->HandleMessage(LB_GETCURSEL);
}
// selects the string at passed index in the associated listbox and
// forces the string into view
//
// clears selection when -1 is passed as the index. a negative value is
// returned if an error occurs
//
inline int TODListBox::SetSelIndex(int index) {
return (int)HandleMessage(LB_SETCURSEL, index);
}
#endif // __OWL_ODLISTBX_H
@@ -0,0 +1,437 @@
//----------------------------------------------------------------------------
// ObjectWindows - (C) Copyright 1992, 1993 by Borland International
// Implements class TODListView
//----------------------------------------------------------------------------
#include <owl\owlpch.h>
#include <owl\docmanag.h>
#include <owl\filedoc.h>
#include <owl\inputdia.h>
#include "odlistbx.h"
#include "odlistvw.rc"
// class TODListView
// ----- -----------
//
class _DOCVIEWCLASS TODListView : public TODListBox, public TView {
public:
TODListView(TDocument& doc, TWindow* parent = 0);
~TODListView();
static const char far* StaticName() {return "OD List View";} // put in resource
BOOL DirtyFlag;
//
// overridden virtuals from TView
//
const char far* GetViewName() {return StaticName();}
TWindow* GetWindow() {return (TWindow*)this;}
BOOL SetDocTitle(const char far* docname, int index)
{return TODListBox::SetDocTitle(docname, index); }
//
// overridden virtuals from TWindow
//
BOOL Create();
UINT EvGetDlgCode(MSG far*);
BOOL CanClose() {return TODListBox::CanClose() && Doc->CanClose();}
protected:
long Origin;
BOOL LoadData(int top, int sel);
//
// message response functions
//
void CmEditUndo();
void CmEditCut();
void CmEditCopy();
void CmEditPaste();
void CmEditDelete();
void CmEditClear();
void CmEditAdd();
void CmEditItem();
// void CmLineIndent();
// void CmLineUnindent();
BOOL VnCommit(BOOL force);
BOOL VnRevert(BOOL clear);
BOOL VnIsWindow(HWND hWnd) {return HWindow == hWnd;}
BOOL VnIsDirty() {return DirtyFlag;}
BOOL VnDocClosed(int omode);
void EvDestroy();
void CmSelChange() {} // to prevent interpreting as unprocessed accelerator
DECLARE_RESPONSE_TABLE(TODListView);
DECLARE_STREAMABLE(,TODListView,1);
};
const char VirtualLastLineStr[] = "---"; // Last virtual line appended to list
DEFINE_RESPONSE_TABLE1(TODListView, TODListBox)
EV_COMMAND(CM_ODLISTUNDO, CmEditUndo),
EV_COMMAND(CM_ODLISTCUT, CmEditCut),
EV_COMMAND(CM_ODLISTCOPY, CmEditCopy),
EV_COMMAND(CM_ODLISTPASTE, CmEditPaste),
EV_COMMAND(CM_ODLISTCLEAR, CmEditClear),
EV_COMMAND(CM_ODLISTDELETE, CmEditDelete),
EV_COMMAND(CM_ODLISTADD, CmEditAdd),
EV_COMMAND(CM_ODLISTEDIT, CmEditItem),
EV_WM_GETDLGCODE,
EV_WM_DESTROY,
EV_NOTIFY_AT_CHILD(LBN_DBLCLK, CmEditItem),
EV_NOTIFY_AT_CHILD(LBN_SELCHANGE, CmSelChange),
EV_VN_DOCCLOSED,
EV_VN_ISWINDOW,
EV_VN_ISDIRTY,
EV_VN_COMMIT,
EV_VN_REVERT,
END_RESPONSE_TABLE;
DEFINE_DOC_TEMPLATE_CLASS(TFileDocument, TODListView, ODLBTemplate);
ODLBTemplate odBinTpl("ODListBox, All files","*.*", 0, "TXT",dtAutoDelete);
ODLBTemplate odTxtTpl("ODStrings, All files","*.*", 0, "TXT",dtAutoDelete);
TODListView::TODListView(TDocument& doc, TWindow* /*parent*/)
: TView(doc), TODListBox(GetNextViewId()),
Origin(0), DirtyFlag(FALSE)
{
Attr.Style &= ~(WS_BORDER | LBS_SORT);
Attr.Style |= (WS_HSCROLL | LBS_NOINTEGRALHEIGHT);
if (doc.GetTemplate() == &odTxtTpl)
Attr.Style |= LBS_HASSTRINGS;
Attr.AccelTable = IDA_ODLISTVIEW;
SetViewMenu(new TMenuDescr(IDM_ODLISTVIEW,0,1,0,0,0,1));
}
BOOL
TODListView::LoadData(int top, int sel)
{
CmEditClear();
DeleteString(0);
DirtyFlag = FALSE;
istream* inStream;
if ((inStream = Doc->InStream(ios::in)) == 0)
return FALSE;
for (;;) {
char buf[100+1];
inStream->getline(buf, sizeof(buf)-1);
if (!inStream->gcount() && !inStream->good())
break; // if EOF or error
char* str;
if (Attr.Style & LBS_HASSTRINGS) { // strings stored in list box
str = buf;
} else {
str = new char[strlen(buf)+1];
strcpy(str, buf);
}
AddString(str);
}
AddString(VirtualLastLineStr);
SetSelIndex(top);
SetSelIndex(sel);
delete inStream; // close file in case process switch
return TRUE;
}
BOOL
TODListView::Create()
{
DirtyFlag = FALSE;
TODListBox::Create(); // throws exception TXInvalidWindow
if (Doc->GetDocPath() == 0) {
CmEditClear(); // perform any clearing initialization
return TRUE; // new file, no data to display
}
if (!LoadData(0, 0))
NotOK();
return TRUE;
}
BOOL
TODListView::VnDocClosed(int omode)
{
int top;
int sel;
if (DirtyFlag == 2 || !(omode & ofWrite)) // make sure someone else's write
return FALSE;
top = GetTopIndex();
sel = GetSelIndex();
LoadData(top, sel);
return TRUE;
}
BOOL
TODListView::VnCommit(BOOL force)
{
if (!force && !DirtyFlag)
return TRUE;
ostream* outStream;
if ((outStream = Doc->OutStream(ios::out)) == 0)
return FALSE;
outStream->seekp(Origin);
char* buf = 0; // initialized only to prevent warning about use before def
int buflen = 0;
int count = GetCount();
for (int index = 0; index < count-1; index++) { // don't write last virtual line
int len;
char far* str;
if (Attr.Style & LBS_HASSTRINGS) {
len = GetStringLen(index);
} else {
str = (char far*)GetItemData(index);
len = str ? strlen(str) : 0;
}
if (len != 0) {
if (len >= buflen) {
if (buflen != 0)
delete buf;
buf = new char[buflen = len+1];
}
if (Attr.Style & LBS_HASSTRINGS)
GetString(buf, index);
else
strcpy(buf, str);
*outStream << buf;
}
*outStream << '\n';
}
if (buflen != 0)
delete buf;
DirtyFlag = 2; // to detect our own close notification
delete outStream;
DirtyFlag = FALSE;
return TRUE;
}
BOOL
TODListView::VnRevert(BOOL clear)
{
if (!clear && Doc->GetDocPath() != 0)
return LoadData(0,0);
CmEditClear();
DirtyFlag = FALSE;
return TRUE;
}
UINT
TODListView::EvGetDlgCode(MSG far*)
{
UINT retVal = (UINT)DefaultProcessing();
retVal |= DLGC_WANTCHARS;
return retVal;
}
void
TODListView::CmEditUndo()
{
MessageBox("Feature not implemented", "Undo", MB_OK);
}
void
TODListView::CmEditCut()
{
CmEditCopy();
CmEditDelete();
}
void
TODListView::CmEditCopy()
{
int index = GetSelIndex();
int count = GetCount();
if (count <= 1 || index >= count-1)
return;
char far* str;
int len;
if (Attr.Style & LBS_HASSTRINGS) { // strings stored in list box
len = GetStringLen(index);
} else {
str = (char far*)GetItemData(index);
len = strlen(str);
}
TClipboard cb(*this);
if (cb.EmptyClipboard()) {
HANDLE cbhdl = ::GlobalAlloc(GHND, len+0+1);
char far* gbuf = (char far*)::GlobalLock(cbhdl);
if (Attr.Style & LBS_HASSTRINGS) { // strings stored in list box
GetString(gbuf, index);
} else {
strcpy(gbuf, str);
}
::GlobalUnlock(cbhdl);
cb.SetClipboardData(CF_TEXT, cbhdl);
}
}
void
TODListView::CmEditPaste()
{
int index = GetSelIndex();
if (index < 0)
index = 0;
TClipboard cb(*this);
if (!cb)
return; // clipboard open by another window
HANDLE cbhdl = cb.GetClipboardData(CF_TEXT);
if (cbhdl) {
char far* text = (char far*)::GlobalLock(cbhdl);
char far* str;
if (Attr.Style & LBS_HASSTRINGS) { // strings stored in list box
str = text;
} else {
str = new char[strlen(text)+1];
strcpy(str, text);
}
InsertString(str, index);
SetSelIndex(index+1);
DirtyFlag = TRUE;
::GlobalUnlock(cbhdl);
}
}
void
TODListView::CmEditDelete()
{
int count = GetCount();
int index = GetSelIndex();
if (count <= 1 || index >= count-1)
return;
ODItemInfo item;
item.Hdc = ::GetDC(*this);
item.Index = index;
item.Data = (void far*)GetItemData(index);
item.State = 0;
GetItemInfo(item);
::ReleaseDC(*this, item.Hdc);
if (item.Extent.cx == MaxWidth)
SetHorizontalExtent(MaxWidth = 0); // force recalculate max width
if (!(Attr.Style & LBS_HASSTRINGS)) // strings not stored in list box
delete item.Data;
DeleteString(index);
SetSelIndex(index);
DirtyFlag = TRUE;
}
void
TODListView::CmEditClear()
{
int count = GetCount();
if (count == 1)
return;
if (count) {
if (!(Attr.Style & LBS_HASSTRINGS)) // strings not stored in list box
for (int index = 0; index < count-1; index++)
delete (char far*)GetItemData(index);
ClearList();
DirtyFlag = TRUE;
SetHorizontalExtent(MaxWidth = 0);
}
AddString(VirtualLastLineStr);
}
TODListView::~TODListView()
{
if (HWindow)
CmEditClear();
}
void
TODListView::EvDestroy()
{
CmEditClear();
TWindow::EvDestroy();
}
static int linePrompt(TWindow* parent, int index, UINT id, char far* buf,int buflen)
{
char msg[41];
wsprintf(msg, string(*parent->GetModule(), IDS_ODLISTNUM).c_str(), index);
const char far* prompt = string(*parent->GetModule(), id).c_str();
return TInputDialog(parent, msg, prompt, buf, buflen).Execute();
}
void
TODListView::CmEditAdd()
{
char inputText[80];
*inputText = 0;
int index = GetSelIndex();
if (index < 0)
index = 0;
if (linePrompt(this,index+1,CM_ODLISTADD,inputText,sizeof(inputText))==IDOK) {
char far* str;
if (Attr.Style & LBS_HASSTRINGS) { // strings stored in list box
str = inputText;
} else {
str = new char[strlen(inputText)+1];
strcpy(str, inputText);
}
InsertString(str, index);
SetSelIndex(index+1);
DirtyFlag = TRUE;
}
}
void
TODListView::CmEditItem()
{
int index = GetSelIndex();
if (index < 0 || index >= GetCount()-1)
return;
int len;
char* inputText;
if (Attr.Style & LBS_HASSTRINGS) { // strings stored in list box
len = GetStringLen(index);
inputText = new char[len + 81];
GetString(inputText, index);
} else {
char far* str = (char far*)GetItemData(index);
len = strlen(str);
inputText = new char[len + 81];
strcpy(inputText, str);
}
if (linePrompt(this,index+1,CM_ODLISTEDIT,inputText, len + 81)==IDOK) {
char far* str;
if (Attr.Style & LBS_HASSTRINGS) { // strings stored in list box
str = inputText;
} else {
delete (char far*)GetItemData(index);
str = strnewdup(inputText);
}
DeleteString(index);
InsertString(str, index);
SetSelIndex(index);
DirtyFlag = TRUE;
}
delete inputText;
}
IMPLEMENT_STREAMABLE2(TODListView, TODListBox, TView);
void *
TODListView::Streamer::Read(ipstream &is, uint32 /* version */) const
{
ReadBaseObject((TODListBox*)GetObject(), is);
ReadBaseObject((TView*)GetObject(), is);
is >> GetObject()->Origin;
GetObject()->DirtyFlag = FALSE;
return GetObject();
}
void
TODListView::Streamer::Write(opstream &os) const
{
WriteBaseObject((TODListBox*)GetObject(), os);
WriteBaseObject((TView*)GetObject(), os);
os << GetObject()->Origin;
}
@@ -0,0 +1,72 @@
//----------------------------------------------------------------------------
// ObjectWindows - (C) Copyright 1993 by Borland International
// Menu and accelerators for use with TODListView
//----------------------------------------------------------------------------
#include <owl\inputdia.rh>
#define CM_ODLISTUNDO 27381
#define CM_ODLISTCUT 27382
#define CM_ODLISTCOPY 27383
#define CM_ODLISTPASTE 27384
#define CM_ODLISTDELETE 27385
#define CM_ODLISTCLEAR 27386
#define CM_ODLISTADD 27387
#define CM_ODLISTEDIT 27388
#define IDS_ODLISTNUM 32583
#define IDM_ODLISTVIEW 32583
#define IDA_ODLISTVIEW 32584
#if defined(RC_INVOKED)
IDM_ODLISTVIEW MENU LOADONCALL MOVEABLE PURE DISCARDABLE
BEGIN
POPUP "&Edit"
BEGIN
MenuItem "&Undo\aCtrl+Z", CM_ODLISTUNDO
MenuItem SEPARATOR
MenuItem "&Cut\aCtrl+X", CM_ODLISTCUT
MenuItem "C&opy\aCtrl+C", CM_ODLISTCOPY
MenuItem "&Paste\aCtrl+V", CM_ODLISTPASTE
MenuItem "&Delete\aDel", CM_ODLISTDELETE
MenuItem "&Add Item\aIns", CM_ODLISTADD
MenuItem "&Edit Item\aEnter", CM_ODLISTEDIT
MenuItem "C&lear All\aCtrl+Del", CM_ODLISTCLEAR
END
POPUP "&Help"
BEGIN
MenuItem "OWL Owner-draw ListView", 0, INACTIVE
END
END
IDA_ODLISTVIEW ACCELERATORS
BEGIN
"^z", CM_ODLISTUNDO,
"^x", CM_ODLISTCUT,
"^c", CM_ODLISTCOPY,
"^v", CM_ODLISTPASTE,
VK_DELETE, CM_ODLISTDELETE VIRTKEY
VK_DELETE, CM_ODLISTCUT, VIRTKEY, SHIFT
VK_DELETE, CM_ODLISTCLEAR, VIRTKEY, CONTROL
VK_INSERT, CM_ODLISTCOPY, VIRTKEY, CONTROL
VK_INSERT, CM_ODLISTPASTE, VIRTKEY, SHIFT
VK_BACK, CM_ODLISTUNDO, VIRTKEY, ALT
VK_INSERT, CM_ODLISTADD, VIRTKEY
VK_RETURN, CM_ODLISTEDIT, VIRTKEY
END
STRINGTABLE LOADONCALL MOVEABLE DISCARDABLE
BEGIN
CM_ODLISTUNDO, "Reverses the last operation"
CM_ODLISTCUT, "Cuts the selection and puts it on the Clipboard"
CM_ODLISTCOPY, "Copies the selection to the Clipboard"
CM_ODLISTPASTE, "Inserts the Clipboard contents at the caret"
CM_ODLISTDELETE,"Deletes the selection"
CM_ODLISTCLEAR, "Clear the document"
CM_ODLISTADD, "Insert a new line"
CM_ODLISTEDIT, "Edit the current line"
IDS_ODLISTNUM, "Line number %d"
END
#endif /* defined(RC_INVOKED) */
@@ -0,0 +1,485 @@
//----------------------------------------------------------------------------
// ObjectWindows - (C) Copyright 1993 by Borland International
// Implements class TExceptionView
//----------------------------------------------------------------------------
#include <owl\owlpch.h>
#include <owl\docmanag.h>
#include "xcptview.rc"
#include <owl\docview.rc>
#include <owl\inputdia.h>
#include <owl\compat.h>
#include <owl\listbox.h>
#include <owl\filedoc.h>
#include "xcptview.rc"
class XVLink;
class _DOCVIEWCLASS TExceptionView : public TListBox, public TView {
public:
TExceptionView(TDocument& doc, TWindow* parent = 0);
~TExceptionView();
static LPCSTR StaticName() {return "Exception Log";} // put in resource
BOOL DirtyFlag;
int CurIndex;
void LogThrow(char* str);
void Annotate(int index, char chr, BOOL cache = FALSE);
//
// overridden virtuals from TView
//
const char far* GetViewName(){return StaticName();}
// LPCSTR GetViewName(){return StaticName();}
TWindow* GetWindow() {return (TWindow*)this;}
BOOL SetDocTitle(const char far* docname, int index)
// BOOL SetDocTitle(LPCSTR docname, int index)
{return TListBox::SetDocTitle(docname, index); }
//
// overridden virtuals from TWindow
//
BOOL CanClose() {return TListBox::CanClose() && Doc->CanClose();}
BOOL Create();
protected:
long Origin;
int MaxWidth; // maximum horizontal extent
XVLink* Link;
char Cache;
unexpected_function OldUnexpectedHandler;
void Init();
void SetExtent(LPSTR str);
BOOL LoadData(int top, int sel);
//
// message response functions
//
BOOL VnDocClosed(int omode);
BOOL VnCommit(BOOL force);
BOOL VnRevert(BOOL clear);
BOOL VnIsWindow(HWND hWnd) {return HWindow == hWnd;}
BOOL VnIsDirty() {return DirtyFlag;}
void CmSelChange(){} // to prevent interpreting as unprocessed accelerator
void CmTXOwl();
void CmTXTest();
void CmTXComp();
void CmTXMem();
void CmXalloc();
void CmXmsg();
void CmForeign();
void CmUnexpected() throw (xalloc);
void CmBadCast();
void CmBadTypeid();
void CmOwlSend();
void CmClear();
void EvTimeChange();
DECLARE_RESPONSE_TABLE(TExceptionView);
DECLARE_STREAMABLE(,TExceptionView,1);
};
class XVLink{ // access class to prevent calling deleted view
public:
XVLink(TExceptionView* view) : View(view), RefCnt(1), Suspended(FALSE) {}
TExceptionView* View;
int RefCnt;
BOOL Suspended;
void Annotate(int index, char chr)
{if (View) View->Annotate(index, chr, Suspended);}
void AddRef() {RefCnt++;}
void SubRef() {if (--RefCnt == 0) delete this;}
};
class TXTest : public TXOwl {
public:
TXTest(UINT resId, XVLink* view, int index);
TXTest(const TXTest&);
const TXTest& operator = (const TXTest&);
~TXTest();
TXOwl* Clone();
void Throw();
int Unhandled(TModule* app, unsigned promptResId);
XVLink* View;
int Index;
};
DEFINE_RESPONSE_TABLE1(TExceptionView, TListBox)
EV_COMMAND(CM_TXOWL, CmTXOwl),
EV_COMMAND(CM_TXTEST, CmTXTest),
EV_COMMAND(CM_TXCOMP, CmTXComp),
EV_COMMAND(CM_TXMEM, CmTXMem),
EV_COMMAND(CM_XALLOC, CmXalloc),
EV_COMMAND(CM_XMSG, CmXmsg),
EV_COMMAND(CM_FOREIGN, CmForeign),
EV_COMMAND(CM_UNEXPECTED, CmUnexpected),
EV_COMMAND(CM_BADCAST, CmBadCast),
EV_COMMAND(CM_BADTYPEID, CmBadTypeid),
EV_COMMAND(CM_OWLSEND, CmOwlSend),
EV_COMMAND(CM_XCLEAR, CmClear),
EV_NOTIFY_AT_CHILD(LBN_SELCHANGE, CmSelChange),
EV_VN_DOCCLOSED,
EV_VN_ISWINDOW,
EV_VN_ISDIRTY,
EV_VN_COMMIT,
EV_VN_REVERT,
EV_WM_TIMECHANGE,
END_RESPONSE_TABLE;
void XUnexpectedHandler()
{
throw xmsg(string(*::Module,XM_UNEXPECTED));
}
TExceptionView::TExceptionView(TDocument& doc, TWindow* parent)
: TView(doc), TListBox(parent, GetNextViewId(), 0,0,0,0),
Origin(0), MaxWidth(0)
{
Attr.Style &= ~(WS_BORDER | LBS_SORT);
Attr.Style |= (WS_HSCROLL | LBS_NOINTEGRALHEIGHT);
Attr.AccelTable = IDA_XCPTVIEW;
SetViewMenu(new TMenuDescr(IDM_XCPTVIEW,0,2,0,0,0,1));
Init();
}
void TExceptionView::Init()
{
Link = new XVLink(this);
OldUnexpectedHandler = set_unexpected(XUnexpectedHandler);
DirtyFlag = FALSE;
Cache = 0;
}
TExceptionView::~TExceptionView()
{
Link->View = 0; // prevent calling into destructed view
Link->SubRef(); // will destruct when no outstanding exceptions
set_unexpected(OldUnexpectedHandler);
}
struct XTest { // class with destructor for testing TPointer
char* P;
XTest() {P = new char[4];}
virtual ~XTest(); // non inline to allow breakpoint set
};
XTest::~XTest(){delete P;}
struct XTestD : public XTest { // class derived from XTest
XTestD() : XTest(), Q(0) {}
char* Q;
~XTestD() {delete Q;}
};
static ThrowTXOwl() // extra call level to allow TPointer testing
{
throw TXOwl(XM_TXOWL);
}
void TExceptionView::CmTXOwl()
{
TPointer<char> ptr = new char[20];
ptr[0] = 0;
TPointer<XTest> x;
x = new XTest();
LogThrow("TXOwl thrown");
XTest* xt = new XTestD();
delete xt;
ThrowTXOwl();
}
void TExceptionView::CmTXTest()
{
LogThrow("TXTest thrown");
throw TXTest(XM_TXTEST, Link, CurIndex);
}
void TExceptionView::CmTXComp()
{
LogThrow("TXCompatibility throw by setting Status");
Status = EM_INVALIDWINDOW;
}
void TExceptionView::CmTXMem()
{
LogThrow("TXOutOfMemory thrown");
throw TXOutOfMemory();
}
void TExceptionView::CmXalloc()
{
LogThrow("xalloc thrown");
throw xalloc(string(*::Module,XM_XALLOC),1234);
}
void TExceptionView::CmXmsg()
{
LogThrow("xmsg thrown");
throw xmsg(string(*::Module,XM_XMSG));
}
void TExceptionView::CmForeign()
{
LogThrow("int thrown");
throw (int)35;
}
void TExceptionView::CmUnexpected() throw (xalloc)
{
LogThrow("Unexpected xmsg thrown");
throw xmsg(string(*::Module,XM_UNEXPECTED));
}
static xmsg* XVRef(xmsg&) {return 0;}
void TExceptionView::CmBadCast()
{
LogThrow("Failed dynamic_cast<>");
XVRef(dynamic_cast<xmsg&>(*this));
}
void TExceptionView::CmBadTypeid()
{
LogThrow("type_id() called on invalid object");
class __rtti C {int i; virtual ~C(){}};
C* o = 0;
static const char* n;
n = typeid(*o).name();
}
void TExceptionView::CmOwlSend()
{
::SendMessage(HWindow, WM_TIMECHANGE,0,0); // any strange message will do
GetApplication()->ResumeThrow();
}
void TExceptionView::EvTimeChange()
{
LogThrow("TXTest thrown from event handler");
throw TXTest(XM_OWLSEND, Link, CurIndex);
}
void TExceptionView::CmClear()
{
ClearList();
DirtyFlag = FALSE;
SetHorizontalExtent(MaxWidth = 0);
}
void TExceptionView::LogThrow(char* str)
{
SetSelIndex(CurIndex = AddString(str));
SetExtent(str);
DirtyFlag = TRUE;
}
void TExceptionView::Annotate(int index, char chr, BOOL cache)
{
if (Cache) { // check if character logged during exception processing
char chr = Cache;
Cache = 0;
Annotate(index, chr); // we assume here we're still at the same index
}
if (cache && chr == '~') { // check if in destructor with cloned exception
Cache = chr;
return;
}
char buf[100];
int len = GetStringLen(index);
GetString(buf, index);
buf[len] = ' ';
buf[len+1] = chr;
buf[len+2] = 0;
DeleteString(index);
InsertString(buf, index);
SetSelIndex(index);
}
void TExceptionView::SetExtent(LPSTR str)
{
HDC hdc;
int len;
TSize extent;
if ((len = strlen(str)) == 0)
return;
hdc = ::GetDC(HWindow);
::GetTextExtentPoint(hdc, str, len, &extent);
extent.cx += 2; // room for focus rectangle
if (extent.cx > MaxWidth){
SetHorizontalExtent(MaxWidth = extent.cx);
}
::ReleaseDC(HWindow, hdc);
}
BOOL TExceptionView::VnDocClosed(int omode)
{
int top;
int sel;
if (DirtyFlag == 2 || !(omode & ofWrite)) // make sure someone else's write
return FALSE;
top = GetTopIndex();
sel = GetSelIndex();
LoadData(top, sel);
return TRUE;
}
BOOL TExceptionView::LoadData(int top, int sel)
{
char buf[100+1];
istream* inStream;
BOOL status = TRUE;
CmClear();
DirtyFlag = FALSE;
if ((inStream = Doc->InStream(ios::in)) == 0) {
Doc->PostError(IDS_UNABLEOPEN, MB_OK);
return FALSE;
}
for (;;) {
inStream->getline(buf, sizeof(buf)-1);
if (!inStream->gcount() && !inStream->good()) {
status = inStream->eof();
break;
}
AddString(buf);
SetExtent(buf);
}
SetTopIndex(top);
SetSelIndex(sel);
delete inStream; // close file in case process switch
if (!status)
Doc->PostError(IDS_READERROR, MB_OK);
return status;
}
BOOL TExceptionView::Create()
{
try {
TListBox::Create(); // throws exception TWindow::TXWindow
}
catch (TXOwl& x) {
Doc->PostError(IDS_NOMEMORYFORVIEW, MB_OK);
return TRUE; // cannot return FALSE - throws another exception
}
if (Doc->GetDocPath() == 0) {
return TRUE; // new file, no data to display
}
if (!LoadData(0, 0))
NotOK();
return TRUE;
}
BOOL TExceptionView::VnCommit(BOOL force)
{
int count;
int index;
int len;
char* buf;
ostream* outStream;
BOOL status;
if (!force && !DirtyFlag)
return TRUE;
if ((outStream = Doc->OutStream(ios::out)) == 0) {
Doc->PostError(IDS_UNABLEOPEN, MB_OK);
return FALSE;
}
outStream->seekp(Origin);
count = GetCount();
for (index = 0; index < count; index++) {
len = GetStringLen(index);
buf = new char[len+1];
GetString(buf, index);
*outStream << buf << '\n';
delete buf;
}
DirtyFlag = 2; // to detect our own close notification
status = outStream->good();
delete outStream;
DirtyFlag = FALSE;
if (!status)
Doc->PostError(IDS_WRITEERROR, MB_OK);
return status;
}
BOOL TExceptionView::VnRevert(BOOL clear)
{
if (!clear && Doc->GetDocPath() != 0)
return LoadData(0,0);
CmClear();
return TRUE;
}
// Exception class for monitoring exception progress
TXTest::TXTest(UINT resId, XVLink* view, int index)
: TXOwl(resId), View(view), Index(index)
{
View->AddRef();
View->Annotate(Index, '#');
}
TXTest::TXTest(const TXTest& s) : TXOwl(s), View(s.View),Index(s.Index)
{
View->AddRef();
View->Annotate(Index, '+');
}
TXTest::~TXTest()
{
// We cannot do any action here that would cause an exeption to be thrown
// since this object may have just been caught and cloned, a call involving
// messaging through windows would cause the cloned exception to be rethrown
View->Annotate(Index, '~');
View->SubRef();
}
const TXTest& TXTest::operator = (const TXTest& src)
{
*(TXOwl*)this = src;
View = src.View;
Index = src.Index;
View->AddRef();
View->Annotate(Index, '=');
return *this;
}
TXOwl* TXTest::Clone()
{
View->Suspended = TRUE; // prevent rethrow during logging Windows call
View->Annotate(Index, '&');
return new TXTest(*this); // will do the AddRef
}
void TXTest::Throw()
{
View->Suspended = FALSE;
View->Annotate(Index, '!');
throw *this;
}
int TXTest::Unhandled(TModule* app, unsigned promptResId)
{
View->Annotate(Index, '?');
return TXOwl::Unhandled(app, promptResId);
}
IMPLEMENT_STREAMABLE2(TExceptionView, TListBox, TView);
void* TExceptionView::Streamer::Read(ipstream& is, uint32 /*version*/) const
{
TExceptionView* o = GetObject();
ReadBaseObject((TListBox*)o, is);
ReadBaseObject((TView*)o, is);
o->Init();
is >> o->Origin;
is >> o->MaxWidth;
return o;
}
void TExceptionView::Streamer::Write(opstream &os) const
{
WriteBaseObject((TListBox*)GetObject(), os);
WriteBaseObject((TView*)GetObject(), os);
os << GetObject()->Origin;
os << GetObject()->MaxWidth;
}
DEFINE_DOC_TEMPLATE_CLASS(TFileDocument, TExceptionView, XcptTemplate);
XcptTemplate xcptTpl("Exception Log File","*.xlg", 0, "XLG",dtAutoDelete|dtUpdateDir);
@@ -0,0 +1,109 @@
//----------------------------------------------------------------------------
// ObjectWindows - (C) Copyright 1993 by Borland International
// Menu and strings for use with TExceptionView
//----------------------------------------------------------------------------
#include <owl\inputdia.rh>
//#include <owl\except.rc>
#define CM_TXOWL 30380
#define CM_TXTEST 30381
#define CM_TXCOMP 30382
#define CM_TXMEM 30383
#define CM_XALLOC 30384
#define CM_XMSG 30385
#define CM_FOREIGN 30386
#define CM_UNEXPECTED 30387
#define CM_BADCAST 30388
#define CM_BADTYPEID 30389
#define CM_OWLSEND 30390
#define CM_XCLEAR 30391
#define XM_TXOWL 30480
#define XM_TXTEST 30481
#define XM_XALLOC 30482
#define XM_XMSG 30483
#define XM_UNEXPECTED 30484
#define XM_OWLSEND 30485
#define IDM_XCPTVIEW 30300
#define IDA_XCPTVIEW 30300
#if defined(RC_INVOKED)
#include <owl\inputdia.rc>
#define NO_IDD_INPUTDIALOG
#if !defined(NO_IDM_XCPTVIEW) && !defined(__IDM_XCPTVIEW)
#define __IDM_XCPTVIEW
IDM_XCPTVIEW MENU LOADONCALL MOVEABLE PURE DISCARDABLE
BEGIN
POPUP "&Edit"
BEGIN
MenuItem "&Clear Data\aCtrl+Del",CM_XCLEAR
END
POPUP "&Throw Exception"
BEGIN
MenuItem "TX&Owl Exception", CM_TXOWL
MenuItem "TX&Test Exception", CM_TXTEST
MenuItem "TX&Compatibility", CM_TXCOMP
MenuItem "TXOutOf&Memory", CM_TXMEM
MenuItem "x&alloc Exception", CM_XALLOC
MenuItem "&xmsg Exception", CM_XMSG
MenuItem "&Foreign Exception", CM_FOREIGN
MenuItem "&Unexpected Violation",CM_UNEXPECTED
MenuItem "Bad &Dynamic Cast", CM_BADCAST
MenuItem "typeid() Bad Object", CM_BADTYPEID
MenuItem "TXTest &SendMessage", CM_OWLSEND
END
POPUP "&Help"
BEGIN
MenuItem "OWL ExceptionView", 0, INACTIVE
MenuItem "TXTest Annotations:", 0, INACTIVE
MenuItem "# TXTest constructor",0, INACTIVE
MenuItem "+ copy constructor", 0, INACTIVE
MenuItem "~ destructor", 0, INACTIVE
MenuItem "= assignment", 0, INACTIVE
MenuItem "&& clone function", 0, INACTIVE
MenuItem "! throw function", 0, INACTIVE
MenuItem "? unhandled function",0, INACTIVE
END
END
#endif
#undef NO_IDM_XCPTVIEW
#if !defined(NO_IDA_XCPTVIEW) && !defined(__IDA_XCPTVIEW)
#define __IDA_XCPTVIEW
IDA_XCPTVIEW ACCELERATORS
BEGIN
VK_DELETE, CM_XCLEAR, VIRTKEY, CONTROL
END
#endif
#undef NO_IDA_XCPTVIEW
#if !defined(NO_IDS_XCPTVIEW) && !defined(__IDS_XCPTVIEW)
#define __IDS_XCPTVIEW
STRINGTABLE LOADONCALL MOVEABLE DISCARDABLE
BEGIN
CM_TXOWL, "Throw a TXOwl exception"
CM_TXTEST, "Throw a TXTest exception, monitor progress"
CM_TXCOMP, "Throw a TXCompatibility by setting Status"
CM_TXMEM, "Throw a TXOutOfMemory exception"
CM_XALLOC, "Throw an xalloc exception"
CM_XMSG, "Throw an xmsg exception"
CM_FOREIGN, "Throw a foreign exception"
CM_UNEXPECTED,"Throw an unexpected xmsg"
CM_BADCAST, "Perform an invalid dynamic cast to a reference"
CM_BADTYPEID, "Call typeid() on a non-rtti object"
CM_OWLSEND, "Throw a TXTest exception from SendMessage callback"
CM_XCLEAR, "Clear data from view"
XM_TXOWL, "TXOwl from TExceptionView"
XM_TXTEST, "TXTest from TExceptionView"
XM_XALLOC, "xalloc from TExceptionView"
XM_XMSG, "xmsg from TExceptionView"
XM_UNEXPECTED,"Unexpected xmsg forced"
XM_OWLSEND, "TXTest from SendMessage callback to TExceptionView"
END
#endif
#undef NO_IDS_XCPTVIEW
#endif // defined(RC_INVOKED)