//----------------------------------------------------------------------------
// ObjectWindows
// Copyright (c) 1993, 1996 by Borland International, All Rights Reserved
//
/// \file
/// Definition of classes TDocument, TView, TWindowView, TStream, TInStream,
/// TOutStream
//----------------------------------------------------------------------------
#if !defined(OWL_DOCVIEW_H)
#define OWL_DOCVIEW_H
#include <owl/private/defs.h>
#if defined(BI_HAS_PRAGMA_ONCE)
# pragma once
#endif
# include <owl/applicat.h>
# include <owl/dialog.h>
# include <owl/framewin.h>
#if !defined(_INC_COMMDLG)
# include <commdlg.h>
#endif
#include <owl/private/strmdefs.h>
namespace owl {
class _OWLCLASS TDocManager;
class _OWLCLASS TDocTemplate;
class _OWLCLASS TMenuDescr;
class _OWLCLASS TBarDescr;
/// \addtogroup docview_group
/// @{
//
// This is a workaround for a compiler issue in BCC64 7.30 (10.3 Rio).
// See TDocMode::ofReadWrite below.
//
enum {ofRead_workaround = std::ios::in, ofWrite_workaround = std::ios::out};
//
/// Document open and sharing modes - used in storage and stream constructors
//
/// Defines the document and open sharing modes used for constructing streams and
/// storing data. Any constants that have the same functionality as those used by
/// OLE 2.0 doc files are indicated in the following table; for example,
/// STGM_TRANSACTED, STGM_CONVERT, STGM_PRIORITY, and STGM_DELETEONRELEASE.
/// Although files are typically used for data storage, databases or spreadsheets
/// can also be used. I/O streams rather than DOS use these bit values. Documents
/// open the object used for storage in one of the following modes:
//
/// \note the bits values are those of file streams, not same as RTL or OLE
//
enum TDocMode {
// ofParent = (IOS_OMODE_LAST << 1), // use open mode of parent storage
ofParent = 0, ///< use open mode of parent storage
ofRead = std::ios::in, ///< ios::in, open for reading
ofWrite = std::ios::out, ///< ios::out, open for writing
ofReadWrite = ofRead_workaround | ofWrite_workaround, // NOTE: (ofRead | ofWrite) gives error E2313 with BCC64 7.30 (10.3 Rio).
ofAtEnd = std::ios::ate, ///< ios::ate, seek to eof upon original open
ofAppend = std::ios::app, ///< ios::app, append mode: all additions at eof
ofTruncate = std::ios::trunc, ///< ios::trunc, truncate file if already exists
// ofNoCreate = (IOS_OMODE_LAST << 2), // ios::nocreate, open fails if file doesn't exist
// ofNoReplace = (IOS_OMODE_LAST << 3), // ios::noreplace, open fails if file already exists
#if defined(_IOS_Nocreate)
ofNoCreate = _IOS_Nocreate, ///< ios::nocreate, open fails if file doesn't exist
#else
ofNoCreate = 0x40, ///< ios::nocreate, open fails if file doesn't exist
#endif
#if defined(_IOS_Noreplace)
ofNoReplace = _IOS_Noreplace, ///< ios::noreplace, open fails if file already exists
#else
ofNoReplace = 0x80, ///< ios::noreplace, open fails if file already exists
#endif
ofBinary = std::ios::binary, // ios::binary, binary (not text) file, no CR stripping
ofIosMask = 0x00FF, // all of the above bits as used by class ios
ofTransacted= 0x1000, ///< STGM_TRANSACTED, supports commit and revert
ofPreserve = 0x2000, ///< STGM_CONVERT, backup old data of same name
ofPriority = 0x4000, ///< STGM_PRIORITY, temporary efficient peeking
ofTemporary = 0x8000, ///< STGM_DELETEONRELEASE, delete when destructed
shCompat = 0x0600, ///< for non-compliant applications, avoid if possible
shNone = 0x0800, ///< EXCLUSIVE functionality
shRead = 0x0A00, ///< DENY_WRITE functionality
shWrite = 0x0C00, ///< DENY_READ functionality
shReadWrite = 0x0E00, ///< DENY_NONE functionality
shDefault = 0, ///< use stream implementation default value
shMask = (shCompat|shNone|shRead|shWrite)
};
#define PREV_OPEN (ofNoCreate|ofNoReplace)
#define IS_PREV_OPEN(omode) ((omode & PREV_OPEN)==PREV_OPEN)
//
/// \name Definitions of WM_OWLNOTIFY event IDs (view notifications)
/// @{
/// event ID's up to vnCustomBase reserved for general doc-view notifications
//
const uint vnViewOpened = 1; ///< a new view has just been constructed
const uint vnViewClosed = 2; ///< another view is about to be destructed
const uint vnDocOpened = 3; ///< document has just been opened
const uint vnDocClosed = 4; ///< document has just been closed
const uint vnCommit = 5; ///< document is committing, flush cached changes
const uint vnRevert = 6; ///< document has reverted, reload data from doc
const uint vnIsDirty = 7; ///< respond true if uncommitted changes present
const uint vnIsWindow = 8; ///< respond true if passed HWND is that of view
const uint vnCustomBase = 100; ///< base of document class specific notifications
/// @}
//
/// \name Document and view property access flags
/// @{
/// Define document and view property attributes. Documents, views, and applications
/// use these attributes to determine how to process a document or view.
//
const uint pfGetText = 1; ///< property accessible as text format
const uint pfGetBinary = 2; ///< property accessible as native non-text format
const uint pfConstant = 4; ///< property is invariant for object instance
const uint pfSettable = 8; ///< property settable as native format
const uint pfUnknown = 16; ///< property defined but unavailable in object
const uint pfHidden = 32; ///< property should be hidden from normal browse
const uint pfUserDef =128; ///< property has been user-defined at run time
/// @}
//
// Classes defined later in this file
//
class _OWLCLASS TStream;
//
// This causes
// fatal error C1001: INTERNAL COMPILER ERROR (compiler file 'f:\vs70builds\3077\vc\Compiler\Utc\src\P2\p2symtab.c', line 4533)
//class _OWLCLASS TInStream;
//class _OWLCLASS TOutStream;
class TInStream;
class TOutStream;
class _OWLCLASS TDocument;
class _OWLCLASS TView;
/// \cond NoSuppressDoxygenWarning
#include <owl/preclass.h>
/// \endcond
//
/// \class TDocument
// ~~~~~ ~~~~~~~~~
/// An abstract base class, TDocument is the base class for all document objects and
/// serves as an interface between the document, its views, and the document manager
/// (TDocManager class). TDocument creates, destroys, and sends messages about the
/// view. For example, if the user changes a document, TDocument tells the view that
/// the document has been updated. The DEFINE_DOC_TEMPLATE_CLASS macro associates a
/// document with its views.
///
/// In order to send messages to its associated views, the document maintains a list
/// of all the views existing for that document and communicates with the views
/// using ObjectWindows event-handling mechanism. Rather than using the function
/// SendMessage(), the document accesses the view's event table. The views can update
/// the document's data by calling the member functions of the particular document.
/// Views can also request streams, which are constructed by the document.
///
/// Both documents and views have lists of properties for their applications to use.
/// When documents and views are created or destroyed, messages are sent to the
/// application, which can then query the properties to determine how to process the
/// document or view. It is the document manager's responsibility to determine if a
/// particular view is appropriate for the given document.
///
/// Because the property attribute functions are virtual, a derived class (which is
/// called first) might override the properties defined in a base class. Each
/// derived class must implement its own property attribute types of either string
/// or binary data. If the derived class duplicates the property names of the parent
/// class, it should provide the same behavior and data type as the parent.
///
/// In order to add persistence to documents, TDocument contains several virtual
/// functions (for example, InStream and OutStream) that support streaming. Your
/// derived classes need to override these functions in order to read and write
/// data.
///
/// Although documents are usually associated with files, they do not necessarily
/// have to be files; they can also consist of database tables, mail systems, fax or
/// modem transmissions, disk directories, and so on.
//
class _OWLCLASS TDocument : public TStreamableBase {
public:
/// These property values, which describe the basic properties of a document, are
/// available in classes derived from TDocument. They can be used to update and
/// query the attributes of a document. PrevProperty and NextProperty are delimiters
/// for every document's property list.
/// See GetProperty() and SetProperty() for more information.
//
enum TDocProp {
PrevProperty = 0, ///< Index of last property in base class (none in this case)
DocumentClass, ///< text Property: Name of C++ class encapsulating document
TemplateName, ///< text property: Name of template attached to document
ViewCount, ///< int property: Number of views displaying this document
StoragePath, ///< text property: Identifies object holding data of this document
DocTitle, ///< text property: Caption of this document
NextProperty, ///< Next index to be used by derived class
};
/// Document list class
//
/// The TDocument::TList nested class encapsulates the chain of documents. It allows
/// addition, removal, and destruction of documents from the document list.
class _OWLCLASS TList {
public:
/// Constructs a TDocument::TList object.
TList() : DocList(0) {}
/// Destroys a TDocument::TList object.
~TList() {Destroy();}
bool Insert(TDocument* doc); ///< Inserts a new document into the document list. Fails if the document already exists.
bool Remove(TDocument* doc); ///< Removes a document from the document list, fails if not there
TDocument* Next(const TDocument* doc); ///< If the doc parameter is 0, Next returns the first document in the list of documents.
void Destroy(); ///< Deletes all documents
bool Contains(TDocument* doc); ///< Checks if doc is contained in the list
private:
TDocument* DocList;
};
typedef TList List; // for compatibility
// Document constructor / destructor
//
TDocument(TDocument* parent = 0);
virtual ~TDocument();
virtual TInStream* InStream(int mode, LPCTSTR strmId=0);
TInStream* InStream(int mode, const tstring& streamId) {return InStream(mode, streamId.c_str());}
virtual TOutStream* OutStream(int mode, LPCTSTR strmId=0);
TOutStream* OutStream(int mode, const tstring& streamId) {return OutStream(mode, streamId.c_str());}
virtual bool Open(int mode, LPCTSTR path=0);
bool Open(int mode, const tstring& path) {return Open(mode, path.c_str());}
virtual bool Close(); ///< close document, does not delete or detach
virtual bool Commit(bool force=false); ///< save current data, force write
virtual bool Revert(bool clear=false); ///< abort changes, no reload if true
virtual TDocument& RootDocument();
TDocManager& GetDocManager();
void SetDocManager(TDocManager& dm);
TDocument* GetParentDoc();
TDocTemplate* GetTemplate();
bool SetTemplate(TDocTemplate* tpl);
LPCTSTR GetDocPath() const;
virtual bool SetDocPath(LPCTSTR path);
bool SetDocPath(const tstring& path) {return SetDocPath(path.c_str());}
LPCTSTR GetTitle() const;
virtual void SetTitle(LPCTSTR title);
void SetTitle(const tstring& title) {SetTitle(title.c_str());}
virtual bool IsDirty(); ///< Also queries doc and view hierarchy
void SetDirty(bool dirty = true);
virtual bool IsOpen();
virtual bool CanClose(); ///< Returns false if unable to close
virtual bool HasFocus(HWND hwnd); ///< Document (or child doc) has Focus
virtual TDocument* DocWithFocus(HWND hwnd); // Doc/ChildDoc with focus
bool NotifyViews(int eventId, TParam2 = 0, TView* exclude = 0);
bool NotifyOwnViews(int eventId, TParam2 = 0, TView* exclude = 0);
TView* QueryViews(int eventId, TParam2 = 0, TView* exclude = 0);
virtual uint PostError(uint sid, uint choice = MB_OK);
// Property access and info
//
virtual int PropertyCount();
virtual int FindProperty(LPCTSTR name); ///< return property index
int FindProperty(const tstring& name) {return FindProperty(name.c_str());}
virtual int PropertyFlags(int index); ///< pfXxxxx bit array
virtual LPCTSTR PropertyName(int index); ///< locale invariant name
virtual int GetProperty(int index, void * dest, int textlen=0);
virtual bool SetProperty(int index, const void * src); ///< native type
TList& GetChildren();
TView* GetViewList() const;
TView* NextView(const TView* view);
TStream* GetStreamList() const;
TStream* NextStream(const TStream* strm);
void * GetTag() const;
void SetTag(void* * tag);
int GetOpenMode() const;
void SetOpenMode(int mode);
TView* InitView(TView* view); ///< called from template InitView
bool IsEmbedded() const;
void SetEmbedded(bool embed);
virtual bool InitDoc();
public:
TDocument(TDocManager* docMan); ///< create a dummy document to hold docmgr
protected:
virtual void AttachStream(TStream& strm);///< called from TStream constructor
virtual void DetachStream(TStream& strm);///< called from TStream destructor
void DestroyViews();
void DestroyChildren();
public_data:
/// Holds a pointer to the application-defined data. Typically, you can use Tag to
/// install a pointer to your own application's associated data structure. Tag,
/// which is initialized to 0 at the time a TDocument object is constructed, is not
/// otherwise used by the document view classes.
void * Tag;
TList ChildDoc; ///< The list of child documents associated with this document.
protected_data:
/// Indicates that unsaved changes have been made to the document. Views can also
/// independently maintain their local disk status.
bool DirtyFlag;
bool Embedded; ///< Indicates whether the document is embedded.
// static int UntitledIndex;// last used index for Untitled document
private:
TDocManager* DocManager; ///< pointer back to document manager
TDocument* ParentDoc; ///< parent document, 0 if this is root document
TDocument* NextDoc; ///< next in linked chain of active documents
int OpenMode; ///< mode and protection flags
tchar * Title; ///< current document title, 0 if untitled
TDocTemplate* Template; ///< template associated with this document
TView* ViewList; ///< head of linked view chain, 0 if no views
TStream* StreamList; ///< head of linked stream chain, 0 if no streams
tchar * DocPath; ///< path used to open/save document
void ReindexFrames(); ///< force view title and index update
void AttachView(TView& view); ///< called from TView constructor
bool DetachView(TView& view); ///< called from TView destructor
friend class _OWLCLASS TDocTemplate; ///< access to InitView()
friend class _OWLCLASS TView; ///< access to Attach/DetatchView()
friend class _OWLCLASS TStream; ///< access to Attach/DetachStream()
friend class _OWLCLASS TDocManager;
friend class _OWLCLASS TList; ///< access to NextDoc
DECLARE_ABSTRACT_STREAMABLE_OWL(TDocument,1);
};
DECLARE_STREAMABLE_INLINES(::owl::TDocument);
//
/// \class TView
// ~~~~~ ~~~~~
/// Abstract base class for view access from document
//
/// Derived virtually from both TEventHandler and TStreamableBase, TView is the
/// interface presented to a document so it can access its client views. Views then
/// call the document functions to request input and output streams. Views own the
/// streams and are responsible for attaching and deleting them.
///
/// Instead of creating an instance of TView, you create a derived class that can
/// implement TView's virtual functions. The derived class must have a way of
/// knowing the associated window (provided by GetWindow()) and of describing the view
/// (provided by GetViewName()). The view must also be able to display the document
/// title in its window (SetDocTitle()).
/// Classes derived from TView may need to handle several notification messages. For
/// example, if a view is associated with a window that can gain focus, then the
/// view should handle the vnIsWindow notification message.
///
/// View classes can take various forms. For example, a view class can be a window
/// (through inheritance), can contain a window (an embedded object), can reference
/// a window, or can be contained within a window object. A view class might not
/// even have a window, as in the case of a voice mail or a format converter. Some
/// remote views (for example, those displayed by DDE servers) might not have local
/// windows.
///
/// Other viewer classes derived from TView include TEditView, TListBoxView, and
/// TWindowView. These classes display different types of data: TEditView displays
/// unformatted text files, TListBoxView displays text information in a list box, and
/// TWindowView is a basic viewer from which you can derive other types of viewers
/// such as hexadecimal file viewers.
///
/// For OLE-enabled applications, use TOleView, which supports views for embedded
/// objects and compound documents.
//
class _OWLCLASS TView : virtual public TEventHandler,
virtual public TStreamableBase {
public:
/// These property values, which describe the basic properties of a view, are
/// available in classes derived from TView. They can be used to update and query
/// the attributes of a view. PrevProperty and NextProperty are delimiters for every
/// view's property list.
enum TViewProp {
PrevProperty = 0, ///< Index of last property in base class.
ViewClass, ///< Name of the C++ class encapsulating the view. (text)
ViewName, ///< Name of the view. (text)
NextProperty, ///< Next index to be used by derived class.
};
TView(TDocument& doc);
virtual ~TView();
TDocument& GetDocument();
void SetDocument(TDocument&); // Added by Vidar Hasfjord, 2007-08-27.
uint GetViewId();
virtual TMenuDescr* GetViewMenu();
virtual TBarDescr* GetViewBar();
void SetViewMenu(TMenuDescr* menu);
void SetViewBar(TBarDescr* bar);
bool IsOK(); ///< true if successfully created
static uint GetNextViewId(); ///< Next global ID to assign
static void BumpNextViewId();
TView* GetNextView();
/// Pure virtual function that returns 0. Override this function in your derived
/// class to return the name of the class.
/// Must implement, used by template manager for selection
/// \code
/// static LPCTSTR StaticName() {return "name of view";}
/// \endcode
virtual LPCTSTR GetViewName() = 0;
/// Returns the TWindow instance associated with the view, or 0 if no view exists.
virtual TWindow* GetWindow(); // if not derived from TWindow
virtual bool SetDocTitle(LPCTSTR docname, int index);
bool SetDocTitle(const tstring& docname, int index) {return SetDocTitle(docname.c_str(), index);}
// Property access and info
//
virtual int PropertyCount();
virtual int FindProperty(LPCTSTR name);///< return property index
int FindProperty(const tstring& name) {return FindProperty(name.c_str());}
virtual int PropertyFlags(int index); ///< pfXxxxx bit array
virtual LPCTSTR PropertyName(int index); ///< locale invariant name
virtual int GetProperty(int index, void * dest, int textlen=0);
virtual bool SetProperty(int index, const void * src);
void * GetTag() const;
void SetTag(void* * tag);
protected:
void NotOK(); ///< To flag errors in creation
protected_data:
TDocument* Doc; ///< Holds the current document.
public_data:
/// Application hook, not used internally
/// Holds a pointer to the application-defined data. Typically, you can use Tag to
/// install a pointer to your own application's associated data structure. TView
/// zeros Tag during construction and does not access it again.
void * Tag;
private:
TView* NextView; ///< Linked view chain, 0 if no more views
uint ViewId; ///< Unique ID for this view, used for controls
TMenuDescr* ViewMenu; ///< Menu descriptor specific for this view or 0
TBarDescr* ViewBar; ///< Bar descriptor specific for this view or 0
static uint NextViewId; ///< Next view ID to be assigned to a view
friend class _OWLCLASS TDocument; ///< needs access to NextView
#if OWL_PERSISTENT_STREAMS
friend class TDocument::Streamer; ///< needs access to NextView
#endif
DECLARE_ABSTRACT_STREAMABLE_OWL(TView,1);
};
DECLARE_STREAMABLE_INLINES(::owl::TView);
//
/// \class TWindowView
// ~~~~~ ~~~~~~~~~~~
/// Derived from both TWindow and TView, TWindowView is a streamable base class that
/// can be used for deriving window-based views. TWindowView's functions override
/// TView's virtual function to provide their own implementation. By deriving a
/// window-view class from TWindow and TView, you add window functionality to the
/// view of your document.
class _OWLCLASS TWindowView : public TWindow, public TView {
public:
TWindowView(TDocument& doc, TWindow* parent = 0);
~TWindowView();
static LPCTSTR StaticName(); ///< put in resource
// Override virtuals from TWindow
//
auto CanClose() -> bool override;
// Override virtuals from TView
//
auto GetViewName() -> LPCTSTR override;
auto GetWindow() -> TWindow* override;
auto SetDocTitle(LPCTSTR docname, int index) -> bool override;
using TView::SetDocTitle; ///< String-aware overload
private:
// Event handlers
//
bool VnIsWindow(HWND hWnd);
DECLARE_RESPONSE_TABLE(TWindowView);
DECLARE_STREAMABLE_OWL(TWindowView, 1);
};
DECLARE_STREAMABLE_INLINES(::owl::TWindowView);
//
/// \class TDialogView
// ~~~~~ ~~~~~~~~~~~
/// Derived from TDialog and TView.
/// Must be overriden, derived class have to define resId
//
class _OWLCLASS TDialogView : public TDialog, public TView {
public:
TDialogView(TDocument& doc, TWindow* parent, TResId resId, TModule* module = &GetGlobalModule());
TDialogView(TDocument& doc, TWindow* parent, const DLGTEMPLATE& dlgTemplate, TAutoDelete = AutoDelete, TModule* module = &GetGlobalModule());
TDialogView(TDocument& doc, TWindow* parent, TModule* module, HGLOBAL hTemplate, TAutoDelete = AutoDelete);
~TDialogView();
static LPCTSTR StaticName(); // put in resource
// Override virtuals from TWindow
//
auto CanClose() -> bool override;
// Override virtuals from TView
//
auto GetViewName() -> LPCTSTR override;
auto GetWindow() -> TWindow* override;
auto SetDocTitle(LPCTSTR docname, int index) -> bool override;
using TView::SetDocTitle; ///< String-aware overload
private:
// Event handlers
//
bool VnIsWindow(HWND hWnd);
DECLARE_RESPONSE_TABLE(TDialogView);
DECLARE_STREAMABLE_OWL(TDialogView,1);
};
DECLARE_STREAMABLE_INLINES( ::owl::TDialogView );
//
/// \class TStream
// ~~~~~ ~~~~~~~
/// An abstract base class, TStream provides links between streams and documents,
/// views, and document files.
//
class _OWLCLASS TStream {
public:
TDocument& GetDocument();
~TStream();
int GetOpenMode();
LPCTSTR GetStreamName();
protected:
TDocument& Doc; ///< Stores the document that owns this stream.
TStream* NextStream; ///< Points to the next stream in the list of active streams.
TStream(TDocument& doc, LPCTSTR name, int mode);
private:
int OpenMode;
LPCTSTR StreamName;
friend class TDocument;
};
//
/// \class TInStream
// ~~~~~ ~~~~~~~~~
/// Derived from TStream and istream, TInStream is a base class used to define input
/// streams for documents.
//
class TInStream : public TStream, public tistream {
public:
TInStream(TDocument& doc, LPCTSTR name, int mode);
};
//
/// \class TOutStream
// ~~~~~ ~~~~~~~~~~
/// Derived from TStream and ostream, TOutStream is a base class used to create
/// output storage streams for a document.
//
class TOutStream : public TStream, public tostream {
public:
TOutStream(TDocument& doc, LPCTSTR name, int mode);
};
/// \cond NoSuppressDoxygenWarning
#include <owl/posclass.h>
/// \endcond
//----------------------------------------------------------------------------
// View Notification Handler Definitions
//
#if defined(OWL5_COMPAT)
//
// DocView aliases to actual dispatchers
//
#define Dispatch_B_void Dispatch_B ///< No parameters
#define Dispatch_B_int Dispatch_B_I ///< TParam2 as int
#define Dispatch_B_pointer Dispatch_B_POINTER ///< TParam2 as void*
//
// Define a DocView notification signature
// 'id' is the vnXxxXxx name of the notification
// 'arg' is the type of the arg passed to the handler
//
#define NOTIFY_SIG(id, arg) \
template <class T> \
inline bool (T::*id##_Sig(bool (T::*pmf)(arg)))(arg) {return pmf;}
NOTIFY_SIG(vnViewOpened, TView*)
NOTIFY_SIG(vnViewClosed, TView*)
NOTIFY_SIG(vnDocOpened, int)
NOTIFY_SIG(vnDocClosed, int)
NOTIFY_SIG(vnCommit, bool)
NOTIFY_SIG(vnRevert, bool)
NOTIFY_SIG(vnIsDirty, void)
NOTIFY_SIG(vnIsWindow, HWND)
#endif
//
// TDispatch specializations for the DocView messages
//
template <> struct TDispatch<WM_OWLDOCUMENT>
{
template <class F>
static void Encode(F sendMessage, HWND wnd, TDocument& d)
{sendMessage(wnd, WM_OWLDOCUMENT, 0, reinterpret_cast<TParam2>(&d));}
#if OWL_EV_SIGNATURE_CHECK
template <class T> struct THandler {typedef void (T::*type)(TDocument&);};
#endif
template <class T, void (T::*M)(TDocument&)>
static TResult Decode(void* i, TParam1, TParam2 p2)
{
PRECONDITION(p2);
return p2 != 0 ? ((static_cast<T*>(i)->*M)(*reinterpret_cast<TDocument*>(p2)), 0) : 0;
}
};
template <> struct TDispatch<WM_OWLVIEW>
{
template <class F>
static void Encode(F sendMessage, HWND wnd, TView& v)
{sendMessage(wnd, WM_OWLVIEW, 0, reinterpret_cast<TParam2>(&v));}
#if OWL_EV_SIGNATURE_CHECK
template <class T> struct THandler {typedef void (T::*type)(TView&);};
#endif
template <class T, void (T::*M)(TView&)>
static TResult Decode(void* i, TParam1, TParam2 p2)
{
PRECONDITION(p2);
return p2 != 0 ? ((static_cast<T*>(i)->*M)(*reinterpret_cast<TView*>(p2)), 0) : 0;
}
};
template <> struct TDispatch<WM_OWLNOTIFY>
{
static const TMsgId MessageId = WM_OWLNOTIFY;
template <class F>
static bool Encode(F sendMessage, HWND wnd, TParam2 p2)
{return static_cast<bool>(sendMessage(wnd, MessageId, 0, p2));}
#if OWL_EV_SIGNATURE_CHECK
template <class T> struct THandler {typedef bool (T::*type)(TParam2);};
#endif
template <class T, bool (T::*M)(TParam2)>
static TResult Decode(void* i, TParam1, TParam2 p2)
{return (static_cast<T*>(i)->*M)(p2) ? TRUE : FALSE;}
template <uint NotificationCode>
struct TNotificationDispatch;
//
// All the standard DocView notifications return 'bool' and have a single (or no) parameter
// passed through TParam2. We can implement this as a common base template.
//
template <uint NotificationCode, class P>
struct TNotificationDispatchBase
{
template <class F>
static bool Encode(F sendMessage, HWND wnd, P p)
{return static_cast<bool>(sendMessage(wnd, MessageId, NotificationCode, (TParam2) p));}
#if OWL_EV_SIGNATURE_CHECK
template <class T> struct THandler {typedef bool (T::*type)(P);};
#endif
template <class T, bool (T::*M)(P)>
static TResult Decode(void* i, TParam1, TParam2 p2)
{return (static_cast<T*>(i)->*M)((P) p2) ? TRUE : FALSE;}
};
//
// Specialization for the void parameter case
//
template <uint NotificationCode>
struct TNotificationDispatchBase<NotificationCode, void>
{
template <class F>
static bool Encode(F sendMessage, HWND wnd)
{return static_cast<bool>(sendMessage(wnd, MessageId, NotificationCode));}
#if OWL_EV_SIGNATURE_CHECK
template <class T> struct THandler {typedef bool (T::*type)();};
#endif
template <class T, bool (T::*M)()>
static TResult Decode(void* i, TParam1, TParam2)
{return (static_cast<T*>(i)->*M)() ? TRUE : FALSE;}
};
};
template <> struct TDispatch<WM_OWLNOTIFY>::TNotificationDispatch<vnDocOpened> : TNotificationDispatchBase<vnDocOpened, int> {};
template <> struct TDispatch<WM_OWLNOTIFY>::TNotificationDispatch<vnDocClosed> : TNotificationDispatchBase<vnDocClosed, int> {};
template <> struct TDispatch<WM_OWLNOTIFY>::TNotificationDispatch<vnViewOpened> : TNotificationDispatchBase<vnViewOpened, TView*> {};
template <> struct TDispatch<WM_OWLNOTIFY>::TNotificationDispatch<vnViewClosed> : TNotificationDispatchBase<vnViewClosed, TView*> {};
template <> struct TDispatch<WM_OWLNOTIFY>::TNotificationDispatch<vnCommit> : TNotificationDispatchBase<vnCommit, bool> {};
template <> struct TDispatch<WM_OWLNOTIFY>::TNotificationDispatch<vnRevert> : TNotificationDispatchBase<vnRevert, bool> {};
template <> struct TDispatch<WM_OWLNOTIFY>::TNotificationDispatch<vnIsDirty> : TNotificationDispatchBase<vnIsDirty, void> {};
template <> struct TDispatch<WM_OWLNOTIFY>::TNotificationDispatch<vnIsWindow> : TNotificationDispatchBase<vnIsWindow, HWND> {};
//
/// Defines a DocView notification response entry.
/// - 'id' is the notification id,
/// - 'method' is the name of the method to be notified, and
/// - 'dispatcher' is the name of the dispatcher to use.
//
#define VN_DEFINE(id, method, dispatcher)\
{{WM_OWLNOTIFY}, static_cast<::owl::uint>(id), OWL_DISPATCH(dispatcher, method)}
#if OWL_EV_SIGNATURE_CHECK
//
// Internal macro using dispatcher lookup in the TDispatch<WM_OWLNOTIFY> specialization
//
#define VN_DEFINE_STANDARD_(id, method)\
{{WM_OWLNOTIFY}, static_cast<::owl::uint>(id),\
(::owl::CheckSignature<TMyClass, WM_OWLNOTIFY, static_cast<::owl::uint>(id), ::owl::TDispatch>(&TMyClass::method),\
OWL_DISPATCH(::owl::TDispatch<WM_OWLNOTIFY>::TNotificationDispatch<static_cast<::owl::uint>(id)>::Decode, method))}
#else
//
// Internal macro using dispatcher lookup in the TDispatch<WM_OWLNOTIFY> specialization
//
#define VN_DEFINE_STANDARD_(id, method)\
{{WM_OWLNOTIFY}, static_cast<::owl::uint>(id),\
OWL_DISPATCH(::owl::TDispatch<WM_OWLNOTIFY>::TNotificationDispatch<static_cast<::owl::uint>(id)>::Decode, method)}
#endif
//
/// \name Standard view notificaton events
/// @{
/// These macros handle view-related messages generated by the document manager.
//
#define EV_VN_VIEWOPENED VN_DEFINE_STANDARD_(::owl::vnViewOpened, VnViewOpened)
#define EV_VN_VIEWCLOSED VN_DEFINE_STANDARD_(::owl::vnViewClosed, VnViewClosed)
#define EV_VN_DOCOPENED VN_DEFINE_STANDARD_(::owl::vnDocOpened, VnDocOpened)
#define EV_VN_DOCCLOSED VN_DEFINE_STANDARD_(::owl::vnDocClosed, VnDocClosed)
#define EV_VN_COMMIT VN_DEFINE_STANDARD_(::owl::vnCommit, VnCommit)
#define EV_VN_REVERT VN_DEFINE_STANDARD_(::owl::vnRevert, VnRevert)
#define EV_VN_ISDIRTY VN_DEFINE_STANDARD_(::owl::vnIsDirty, VnIsDirty)
#define EV_VN_ISWINDOW VN_DEFINE_STANDARD_(::owl::vnIsWindow, VnIsWindow)
/// @}
/// @}
//----------------------------------------------------------------------------
// Inline implementations
//
//
/// Generic input for the particular storage medium, InStream returns a pointer to a
/// TInStream. mode is a combination of the ios bits defined in iostream.h. See the
/// document open mode constants for a list of the open modes. Used for documents
/// that support named streams, strmId is a pointer to the name of a stream.
/// Override this function to provide streaming for your document class.
//
inline TInStream* TDocument::InStream(int /*mode*/, LPCTSTR /*strmId*/) {
return 0;
}
//
/// Generic output for the particular storage medium, OutStream returns a pointer to
/// a TOutStream. mode is a combination of the ios bits defined in iostream.h. Used
/// for documents that support named streams, strmId points to the name of the
/// stream. TDocument::OutStream version always returns 0. Override this function to
/// provide streaming for your document class.
//
inline TOutStream* TDocument::OutStream(int /*mode*/, LPCTSTR /*strmId*/) {
return 0;
}
//
/// Opens the document using the path specified by DocPath. Sets OpenMode to mode.
/// TDocument::Open always returns true and actually performs no actions. Other
/// classes override this function to open specified file documents and views.
//
inline bool TDocument::Open(int /*mode*/, LPCTSTR /*path*/) {
return true;
}
//
/// Returns a pointer to the current document manager.
//
inline TDocManager& TDocument::GetDocManager() {
return *DocManager;
}
//
/// Returns either the parent document of the current document or 0 if there is no
/// parent document.
//
inline TDocument* TDocument::GetParentDoc() {
return ParentDoc;
}
//
/// Gets the template used for document creation. The template can be changed during
/// a SaveAs operation.
//
inline TDocTemplate* TDocument::GetTemplate() {
return Template;
}
//
/// Returns the directory path for the document. This might change the SaveAs
/// operation.
//
inline LPCTSTR TDocument::GetDocPath() const {
return DocPath;
}
//
/// Returns the title of the document.
//
inline LPCTSTR TDocument::GetTitle() const {
return Title;
}
//
/// Updates the document's dirty flag using the specified parameter.
//
inline void TDocument::SetDirty(bool dirty) {
DirtyFlag = dirty;
}
//
/// Checks to see if the document has any streams in its stream list. Returns false
/// if no streams are open; otherwise, returns true.
//
inline bool TDocument::IsOpen() {
return StreamList != 0;
}
//
/// Gets the total number of properties for the TDocument object. Returns
/// NextProperty -1.
//
inline int TDocument::PropertyCount() {
return NextProperty-1;
}
//
/// Returns true if the document is embedded in an OLE 2 container.
//
inline bool TDocument::IsEmbedded() const {
return Embedded;
}
//
/// Marks the document as being embedded in an OLE 2 container. Typically, this
/// happens when the server is created and when the factory template class creates
/// the component.
//
inline void TDocument::SetEmbedded(bool embed) {
Embedded = embed;
}
//
/// A virtual method that is overridden by TOleDocument::InitDoc. You can use this
/// function to prepare the document before the view is constructed and before the
/// dnCreate event, which indicates that the document has been created and is
/// posted.
//
inline bool TDocument::InitDoc() {
return true;
}
//
/// Return reference to the children document list.
//
inline TDocument::TList& TDocument::GetChildren() {
return ChildDoc;
}
//
/// Return pointer to the head of the link list of views associated with this
/// document.
/// \note To iterate through all the views, use the 'NextView' method with
/// the pointer obtained from this method.
//
inline TView* TDocument::GetViewList() const {
return ViewList;
}
//
/// Returns head of the link list of streams associated with this document.
/// \note To iterate through all the streams, use the 'NextStream' method with the
/// pointer returned from this method.
//
inline TStream* TDocument::GetStreamList() const {
return StreamList;
}
//
/// Returns pointer to user-defined data [i.e. tag] attached to this document.
//
inline void * TDocument::GetTag() const {
return Tag;
}
//
/// Attach an arbitrary (user-defined) pointer with this document.
/// \note The 'Tag' is a place-holder. It is not used by the Doc/View subsystem.
//
inline void TDocument::SetTag(void* * tag) {
Tag = tag;
}
//
/// Create a dummy document to hold docmgr.
//
inline TDocument::TDocument(TDocManager* docMan)
:
DocManager(docMan), ParentDoc(this)
{}
//
/// Gets the mode and protection flag values for the current document.
//
inline int
TDocument::GetOpenMode() const
{
return OpenMode;
}
//
/// Sets the mode and protection flag values for the current document.
//
inline void
TDocument::SetOpenMode(int mode)
{
OpenMode = mode;
}
//
/// Returns a reference to the view's document.
//
inline TDocument& TView::GetDocument() {
return *Doc;
}
//
/// Returns the unique ID for this view.
//
inline uint TView::GetViewId() {
return ViewId;
}
//
/// Returns the menu descriptor for this view. This can be any existing TMenuDescr
/// object. If no descriptor exists, ViewMenu is 0.
//
inline TMenuDescr* TView::GetViewMenu() {
return ViewMenu;
}
//
inline TBarDescr* TView::GetViewBar() {
return ViewBar;
}
//
/// Returns a nonzero value if the view is successfully constructed.
//
inline bool TView::IsOK() {
return ViewId != 0;
}
//
/// Returns the next view ID to be assigned.
//
inline uint TView::GetNextViewId() {
return NextViewId;
}
//
/// Returns the next global view ID to be assigned.
//
inline TView* TView::GetNextView() {
return NextView;
}
//
inline TWindow* TView::GetWindow() {
return 0;
}
//
/// Retrieves the user-defined pointer attached to this view.
//
inline void * TView::GetTag() const {
return Tag;
}
//
/// Associates an arbitrary (user-defined) pointer with this view.
/// \note The 'Tag' is not used by the Doc/View subsystem.
//
inline void TView::SetTag(void* * tag) {
Tag = tag;
}
//
/// Stores the document title.
//
inline bool TView::SetDocTitle(LPCTSTR /*docname*/, int /*index*/) {
return false;
}
//
/// Gets the total number of properties for the TDocument object.
//
inline int TView::PropertyCount() {
return NextProperty - 1;
}
//
/// Sets the value of the property, given the index of the property, and src, the
/// data type (either binary or text) to which the property must be set.
//
inline bool TView::SetProperty(int /*index*/, const void * /*src*/) {
return false;
}
//
/// Sets the view to an invalid state, causing IsOK to return 0.
//
inline void TView::NotOK() {
ViewId = 0;
}
//
// class TWindowView
// ~~~~~ ~~~~~~~~~~~
/// Destroys a TWindowView object and calls the associated document's DetachView
/// function (a private TDocument function) to detach the view from the associated
/// document.
//
inline TWindowView::~TWindowView() {
}
//
/// Returns "Window View," the descriptive name of the view. This title is displayed
/// in the user-interface box.
//
inline LPCTSTR TWindowView::StaticName() {
return _T("Window View");
}
//
/// Does a given HWND belong to this view? Yes if it is us, or a child of us
//
inline bool TWindowView::VnIsWindow(HWND hWnd){
return hWnd == GetHandle() || IsChild(hWnd);
}
//
/// Overrides TWindow::CanClose and returns a nonzero value if the window can be
/// closed. CanClose checks all the associated document's CanClose functions. These
/// must return nonzero values before the window view can be closed.
//
/// Only query document if this is the last view open to it.
//
inline bool TWindowView::CanClose() {
return TWindow::CanClose() &&
(Doc->NextView(this) ||
Doc->NextView(0) != this ||
Doc->CanClose());
}
//
/// Overrides TView::GetViewName and returns StaticName, the name of the view.
//
inline LPCTSTR TWindowView::GetViewName() {
return StaticName();
}
//
/// Overrides TView::GetWindow and returns the TWindowView object as a TWindow.
//
inline TWindow* TWindowView::GetWindow() {
return (TWindow*)this;
}
//
/// Overrides TView::SetDocTitle and stores the document title. This name is
/// forwarded up the parent chain until a TFrameWindow object accepts the data and
/// displays it in its caption.
//
inline bool TWindowView::SetDocTitle(LPCTSTR docname, int index) {
return TWindow::SetDocTitle(docname, index);
}
//
/// class TDialogView
// ~~~~~ ~~~~~~~~~~~
inline TDialogView::~TDialogView() {
}
//
inline LPCTSTR TDialogView::StaticName(){
return _T("Dialog View");
}
//
/// Only query document if this is the last view open to it.
//
inline bool TDialogView::CanClose() {
return TDialog::CanClose() &&
(Doc->NextView(this) ||
Doc->NextView(0) != this ||
Doc->CanClose());
}
//
inline LPCTSTR TDialogView::GetViewName() {
return StaticName();
}
//
inline TWindow* TDialogView::GetWindow() {
return (TWindow*)this;
}
//
/// Does a given HWND belong to this view? Yes if it is us, or a child of us
//
inline bool TDialogView::VnIsWindow(HWND hWnd){
return hWnd == GetHandle() || IsChild(hWnd);
}
//
inline bool TDialogView::SetDocTitle(LPCTSTR docname, int index) {
return TDialog::SetDocTitle(docname, index);
}
//
// class TStream
// ~~~~~ ~~~~~~~
//
/// Returns the current document that is open for streaming.
//
inline TDocument& TStream::GetDocument() {
return Doc;
}
//
/// Closes the stream. Derived classes generally close the document if it was opened
/// especially for this stream.
//
inline TStream::~TStream() {
Doc.DetachStream(*this);
}
//
/// Constructs a TStream object.
/// 'name' is the user-defined name of the stream and can be 0.
/// Note: If 'name' is not null, the referenced string must outlive the object. No copy is made.
//
inline TStream::TStream(TDocument& doc, LPCTSTR name, int mode)
:
Doc(doc),
OpenMode(mode),
StreamName(name)
{
Doc.AttachStream(*this);
}
//
/// Gets the name of the stream used for opening the document.
//
inline LPCTSTR TStream::GetStreamName() {
return StreamName;
}
//
/// Gets mode flags used when opening document streams. For example, the stream can
/// be opened in ofRead mode to allow reading, but not changing (writing to) the
/// file.
//
inline int TStream::GetOpenMode() {
return OpenMode;
}
//
// WORK-AROUND: Fix for a bug in the Dinkumware standard library; double-init memory leak.
// Using 0 as the stream initializer in the Dinkumware version of the library sets the stream buffer
// to 0 and also sets an error state of the stream. Also, research on the net indicate that this causes
// a double-init memory leak.
//
// TODO: Research which versions are affected and how, and reliably detect only these.
//
#if defined(_CPPLIB_VER) // Defined by Dinkumware - assume this detects the library.
#define OWL_STREAM_NULL_INITIALIZER std::_Noinit
#else
#define OWL_STREAM_NULL_INITIALIZER 0
#endif
//
/// Constructs a TInStream object.
/// 'name' is the user-defined name of the stream and can be 0.
/// Note: If 'name' is not null, the referenced string must outlive the object. No copy is made.
//
inline TInStream::TInStream(TDocument& doc, LPCTSTR name, int mode)
:
TStream(doc, name, mode),
tistream(OWL_STREAM_NULL_INITIALIZER) // init base to null, don't forget to call init.
{}
//
/// Constructs a TOutStream object.
/// 'name' is the user-defined name of the stream and can be 0.
/// Note: If 'name' is not null, the referenced string must outlive the object. No copy is made.
//
inline TOutStream::TOutStream(TDocument& doc, LPCTSTR name, int mode)
:
TStream(doc, name, mode),
tostream(OWL_STREAM_NULL_INITIALIZER) // init base to null, don't forget to call init.
{}
} // OWL namespace
#endif // OWL_DOCVIEW_H
↑ V730 Not all members of a class are initialized inside the constructor. Consider inspecting: NextStream.
↑ V1003 The macro 'IS_PREV_OPEN' is a dangerous expression. The parameter 'omode' must be surrounded by parentheses.
↑ V730 Not all members of a class are initialized inside the constructor. Consider inspecting: Tag, DirtyFlag, Embedded, NextDoc, OpenMode, Title, ...