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:
Binary file not shown.
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;
|
||||
}
|
||||
Binary file not shown.
@@ -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);
|
||||
Binary file not shown.
@@ -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);
|
||||
Binary file not shown.
@@ -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);
|
||||
|
||||
Binary file not shown.
@@ -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;
|
||||
}
|
||||
Binary file not shown.
@@ -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);
|
||||
|
||||
Binary file not shown.
@@ -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)
|
||||
Reference in New Issue
Block a user