home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
C Programming Starter Kit 2.0
/
SamsPublishing-CProgrammingStarterKit-v2.0-Win31.iso
/
bc45
/
owlsrc.pak
/
DOCMANAG.CPP
< prev
next >
Wrap
C/C++ Source or Header
|
1997-07-23
|
29KB
|
1,063 lines
//----------------------------------------------------------------------------
// ObjectWindows
// (C) Copyright 1993, 1994 by Borland International, All Rights Reserved
//
// Implements class TDocManager
//----------------------------------------------------------------------------
#pragma hdrignore SECTION
#include <owl/owlpch.h>
#include <owl/docmanag.h>
#include <owl/appdict.h>
#include <owl/docview.rh>
#include <string.h>
#include <dlgs.h> // cmb1 for file open dialog box
#include <dir.h> // MAXEXT for file open dialog default extension
#if defined(SECTION) && SECTION != 1
DIAG_DECLARE_GROUP(OwlDocView); // General Doc/View diagnostic group
#endif
#if !defined(SECTION) || SECTION == 1
DIAG_DEFINE_GROUP_INIT(OWL_INI, OwlDocView, 1, 0);
//
// class TPickList
// ----- ---------
//
class TPickList : public TWindow {
public:
TPickList(const char far* title, TWindow* parent);
TPickList(uint sid, TWindow* parent);
~TPickList();
int AddString(const char far* str);
int Execute(); // returns pick index (1 based), 0 if cancelled
private:
LRESULT EvCommand(uint id, HWND hWndCtl, uint notifyCode);
HMENU Popup;
int Count;
int Index;
};
TPickList::TPickList(const char far* title, TWindow* parent)
:
TWindow(parent, 0, 0),
Count(0)
{
Popup = ::CreatePopupMenu();
if (title) {
::AppendMenu(Popup, MF_GRAYED, 0, title);
::AppendMenu(Popup, MF_SEPARATOR, 0, 0);
}
}
TPickList::TPickList(uint sid, TWindow* parent)
:
TWindow(parent, 0, 0),
Count(0)
{
char buf[256];
Popup = ::CreatePopupMenu();
if (!sid || !GetApplication()->LoadString(sid, buf, sizeof(buf)))
return;
::AppendMenu(Popup, MF_GRAYED, 0, buf);
::AppendMenu(Popup, MF_SEPARATOR, 0, 0);
}
TPickList::~TPickList()
{
if (Popup)
::DestroyMenu(Popup);
}
int
TPickList::AddString(const char far* str)
{
::AppendMenu(Popup, MF_ENABLED, ++Count, str);
return Count;
}
int
TPickList::Execute()
{
TPoint loc;
GetCursorPos(loc);
Create();
Index = 0;
::TrackPopupMenu(Popup, 0, loc.x, loc.y, 0, HWindow, 0);
GetApplication()->PumpWaitingMessages(); // WM_COMMAND may be in queue
::DestroyMenu(Popup);
Popup = 0;
return Index;
}
LRESULT
TPickList::EvCommand(uint id, HWND /*hWndCtl*/, uint /*notifyCode*/)
{
WARNX(OwlDocView, id > Count, 0, "TPickList index invalid");
Index = id;
return 0;
}
//----------------------------------------------------------------------------
// class TDocManager
//
DEFINE_RESPONSE_TABLE (TDocManager)
EV_WM_CANCLOSE,
EV_WM_PREPROCMENU,
EV_WM_WAKEUP,
EV_COMMAND(CM_FILENEW, CmFileNew),
EV_COMMAND(CM_FILEOPEN, CmFileOpen),
EV_COMMAND(CM_FILESAVE, CmFileSave),
EV_COMMAND(CM_FILESAVEAS, CmFileSaveAs),
EV_COMMAND(CM_FILEREVERT, CmFileRevert),
EV_COMMAND(CM_FILECLOSE, CmFileClose),
EV_COMMAND(CM_VIEWCREATE, CmViewCreate),
EV_COMMAND_ENABLE(CM_FILENEW, CeFileNew),
EV_COMMAND_ENABLE(CM_FILEOPEN, CeFileOpen),
EV_COMMAND_ENABLE(CM_FILESAVE, CeFileSave),
EV_COMMAND_ENABLE(CM_FILESAVEAS, CeFileSaveAs),
EV_COMMAND_ENABLE(CM_FILEREVERT, CeFileRevert),
EV_COMMAND_ENABLE(CM_FILECLOSE, CeFileClose),
EV_COMMAND_ENABLE(CM_VIEWCREATE, CeViewCreate),
END_RESPONSE_TABLE;
TDocManager::TDocManager(int mode, TDocTemplate*& templateHead)
:
Mode(mode),
TemplateHead(&templateHead)
{
TDocTemplate* ptpl;
TemplateList = templateHead; // catch up with any statics
for (ptpl = TemplateList; ptpl; ptpl = ptpl->GetNextTemplate())
ptpl->DocManager = this;
Application = GetApplicationObject();
// setup backward compatibility entry points
//
TDocTemplate::SelectSave_ = SelectSave;
TDocTemplate::InitDoc_ = InitDoc;
TDocTemplate::InitView_ = InitView;
}
TDocManager::TDocManager(int mode, TApplication* app, TDocTemplate*& templateHead)
:
Mode(mode),
Application(app),
TemplateHead(&templateHead)
{
TDocTemplate* ptpl;
TemplateList = templateHead; // catch up with any statics
for (ptpl = TemplateList; ptpl; ptpl = ptpl->GetNextTemplate())
ptpl->DocManager = this;
// setup backward compatibility entry points
//
TDocTemplate::SelectSave_ = SelectSave;
TDocTemplate::InitDoc_ = InitDoc;
TDocTemplate::InitView_ = InitView;
}
TDocManager::~TDocManager()
{
TDocument* doc;
while ((doc = DocList.Next(0)) != 0) {
if (doc->IsOpen())
doc->Close();
delete doc; // removes view, unlinks template and doc manager
Application->PumpWaitingMessages(); // force out posted MDI child destroy
}
while (TemplateList) {
TDocTemplate* ptpl = TemplateList;
TemplateList = ptpl->GetNextTemplate();
if (ptpl->RefCnt & 0x8000) // skip over statics
ptpl->DocManager = 0;
else
delete ptpl;
}
}
//
// prompts user to select a document class for a new document
// returns the template index used for the selection (1-based), 0 if failure
//
int
TDocManager::SelectDocType(TDocTemplate** tpllist, int tplcount)
{
TPickList* pickl = new TPickList(IDS_DOCLIST, Application->GetMainWindow());
while (tplcount--)
pickl->AddString((*tpllist++)->GetDescription());
int index = pickl->Execute();
delete pickl;
return index;
}
//
// prompts user to select a view class for a new view on existing document
// returns the template index used for the selection (1-based), 0 if failure
//
int
TDocManager::SelectViewType(TDocTemplate** tpllist, int tplcount)
{
TPickList* pickl = new TPickList(IDS_VIEWLIST, Application->GetMainWindow());
while (tplcount--)
pickl->AddString((*tpllist++)->GetViewName());
int index = pickl->Execute();
delete pickl;
return index;
}
//
// struct to pass data to the dialog hook function via OPENFILENAME.lCustData
// under Win32s the OPENFILENAME passed to WM_INITDIALOG is a temporary copy
//
struct TplHookData { // pointer to this struct passed as lCustData
long Flags; // original flags passed to SelectDocPath
unsigned long far* DlgFlags; // pointer to dialog flags in OPENFILENAME
char far* ExtBuf; // pointer to buffer holding the default extension
TDocTemplate** TplList; // template pointer array
int InitIndex; // starting index, ofn.nFilterIndex is inconsistent
bool Save; // true if saving
};
//
// dialog hook function to catch template selection changes
//
uint CALLBACK __export
TplHook(HWND hDlg, uint msg, uint wParam, int32 lParam)
{
static TplHookData* hookData; // !!update to store in dialog property
TDocTemplate** tpllist;
OPENFILENAME* ofnHook;
int idx;
switch(msg) {
case WM_COMMAND:
#if defined(BI_PLAT_WIN32)
if (LOWORD(wParam) != cmb1 || HIWORD(wParam) != CBN_SELCHANGE)
#else
if (wParam != cmb1 || HIWORD(lParam) != CBN_SELCHANGE)
#endif
return 0;
idx = (int)::SendMessage((HWND)(uint)lParam, CB_GETCURSEL, 0, 0L);
break;
case WM_INITDIALOG:
ofnHook = (OPENFILENAME*)lParam;
hookData = (TplHookData*)ofnHook->lCustData;
idx = hookData->InitIndex; // can't rely upon ofnHook->nFilterIndex
break;
default:
return 0;
}
tpllist = hookData->TplList;
long flags = tpllist[idx]->GetFlags() | hookData->Flags;
if (hookData->Save)
flags = (flags | dtNoReadOnly) & ~dtFileMustExist;
*hookData->DlgFlags = flags & ~dtProhibited;
if (tpllist[idx]->GetDefaultExt())
strcpy(hookData->ExtBuf, tpllist[idx]->GetDefaultExt());
else
hookData->ExtBuf[0] = 0;
::SendDlgItemMessage(hDlg, chx1, BM_SETCHECK, ((flags&dtReadOnly) != 0), 0);
::ShowWindow(GetDlgItem(hDlg, chx1), (flags&dtHideReadOnly)?SW_HIDE:SW_SHOW);
return 0; // flag as unprocessed
}
// prompts user with one or all templates to select file to open
// returns the template index used for the selection (1-based), 0 if failure
// this is Windows-specific, using the system-defined file open dialog box
//
int
TDocManager::SelectDocPath(TDocTemplate** tpllist, int tplcount,
char far* path, int buflen, long flags, bool save)
{
char extbuf[MAXEXT-1]; // writable buffer for default file extension
OPENFILENAME ofn; // local openfilename structure
int index, count, len;
char* filtbuf;
char* pbuf;
memset(&ofn, 0, sizeof(ofn));
TDocTemplate* ptpl;
TProcInstance TplHookProcInstance((FARPROC)TplHook);
// Concatenate description and filters into a single string
//
for (len=2, count=0; count < tplcount; count++) {
ptpl = tpllist[count];
len += (strlen(ptpl->GetFileFilter())+2); // space for two null separators
if (ptpl->GetDescription())
len += strlen(ptpl->GetDescription());
}
filtbuf = new char[len];
for (pbuf = filtbuf, count=0; count < tplcount; count++) {
ptpl = tpllist[count];
if ((len = strlen(ptpl->GetDescription())) != 0) {
strcpy(pbuf, ptpl->GetDescription());
pbuf += len + 1;
}
else {
*pbuf++ = 0;
}
strcpy(pbuf, ptpl->GetFileFilter());
pbuf += strlen(pbuf) + 1;
}
*pbuf = 0; // double null to signify end
// set selection to previously selected template if present
//
for (index = count = 0; count < tplcount; count++)
if (tpllist[count]->IsFlagSet(dtSelected)) {
index = count;
break;
}
struct TplHookData hookData = {flags,&ofn.Flags,extbuf,tpllist,index,save};
ofn.nFilterIndex = index + 1; // Note: Windows *might* decrement this by one
ofn.lpstrInitialDir = tpllist[index]->GetDirectory();
ofn.lpstrDefExt = (LPCSTR)&extbuf; // receives string from hook function
ofn.lStructSize = sizeof(OPENFILENAME);
ofn.hwndOwner = Application->GetMainWindow()->HWindow;
ofn.lpstrFilter = filtbuf;
ofn.lpstrFile = path;
ofn.nMaxFile = buflen;
ofn.Flags = OFN_ENABLEHOOK /* | OFN_NOCHANGEDIR */;
ofn.lCustData = (LPARAM)&hookData;
(DLGPROC)ofn.lpfnHook = (DLGPROC)(FARPROC)TplHookProcInstance;
Application->EnableCtl3dAutosubclass(true);
if ((save ? ::GetSaveFileName(&ofn) : ::GetOpenFileName(&ofn)) == 0) {
uint32 err = ::CommDlgExtendedError(); // temp for debugging use
if (err != 0)
TRACEX(OwlDocView, 0, "OpenFileName error:" << err);
ofn.nFilterIndex = 0;
}
else {
TDocument* doc;
if (ofn.lpstrFile && (doc = FindDocument(ofn.lpstrFile)) != 0) {
PostDocError(*doc, IDS_DUPLICATEDOC);
return 0;
}
// Set flag to remember template which was selected
//
for (index=(int)ofn.nFilterIndex-1, count=0; count < tplcount; count++) {
if (count == index)
tpllist[count]->SetFlag(dtSelected);
else
tpllist[count]->ClearFlag(dtSelected);
}
// Update template with directory from dialog if flag set
//
ptpl = tpllist[(int)ofn.nFilterIndex - 1];
if (ofn.nFileOffset && (ptpl->IsFlagSet(dtUpdateDir))
&& (ptpl->GetDirectory()==0
|| memcmp(ptpl->GetDirectory(), ofn.lpstrFile,ofn.nFileOffset) != 0))
ptpl->SetDirectory(ofn.lpstrFile, ofn.nFileOffset);
}
delete [] filtbuf;
Application->EnableCtl3dAutosubclass(false);
return (int)ofn.nFilterIndex;
}
void
TDocManager::AttachTemplate(TDocTemplate& tpl)
{
tpl.DocManager = this;
TDocTemplate::AddLink((TRegLink*&)TemplateList, tpl);
}
void
TDocManager::DeleteTemplate(TDocTemplate& tpl)
{
if (tpl.RefCnt & 0x8000) // check for static templates
return;
if (!tpl.DocManager) // check if has owner
return;
if (TDocTemplate::RemoveLink((TRegLink*&)TemplateList, tpl)) {
UnRefTemplate(tpl); // will delete unless documents still reference it
return;
}
TRACEX(OwlDocView, 0, "TDocManager::DeleteTemplate(), not in app list");
}
// initialize document using its specific doc template
// prompts for pathname if none supplied and not creating a new document
//
TDocument*
TDocManager::InitDoc(TDocument* doc, const char far* path, long flags)
{
TDocTemplate* tpl = doc->GetTemplate();
if (!tpl)
return 0;
flags ^= tpl->GetFlags(); // alter template's flags using caller's mask
if (flags & dtNewDoc) {
doc->SetDocPath(0);
if (!doc->InitDoc()) { // Give doc a chance to do its own initialization
PostDocError(*doc, IDS_UNABLEOPEN);
delete doc;
return 0;
}
}
else {
if (!path) {
char filepath[256];
if (!tpl->GetFileFilter())
return 0;
filepath[0] = 0; // no initial file path
int index = SelectDocPath(&tpl, 1, filepath, sizeof(filepath), flags);
if (!index) {
delete doc;
return 0;
}
path = filepath;
}
doc->SetDocPath(path);
if (!doc->InitDoc()) { // Give doc a chance to do its own initialization
PostDocError(*doc, IDS_UNABLEOPEN);
delete doc;
return 0;
}
if ((flags & dtAutoOpen)
&& !doc->Open((flags & dtNoReadOnly) ? ofReadWrite : ofRead)) {
PostDocError(*doc, IDS_UNABLEOPEN);
delete doc;
return 0;
}
}
PostEvent(dnCreate, *doc);
if (!(flags & dtNoAutoView)) {
if (!doc->InitView(tpl->ConstructView(*doc))) {
if (flags & dtAutoDelete) {
if (doc->IsOpen())
doc->Close();
delete doc;
}
return 0;
}
}
return doc;
}
// create and initialize document using a specific doc template
//
TDocument*
TDocManager::CreateDoc(TDocTemplate* tpl, const char far* path,
TDocument* parent, long flags)
{
if (!tpl)
return 0;
TDocument dummyDoc(this);
if (parent == 0)
parent = &dummyDoc;
TDocument* doc = tpl->ConstructDoc(parent);
if (!doc)
return 0;
doc->SetTemplate(tpl);
return InitDoc(doc, path, flags);
}
TView*
TDocManager::CreateView(TDocument& doc)
{
return doc.InitView(doc.GetTemplate()->ConstructView(doc)); // tests view==0
}
bool
TDocManager::SelectSave(TDocument& doc)
{
TDocTemplate* ptpl = doc.GetTemplate();
if (!ptpl || !ptpl->GetFileFilter())
return false;
char filepath[256];
if (doc.GetDocPath())
strcpy(filepath, doc.GetDocPath());
else
filepath[0] = 0; // no initial file path
int index = SelectDocPath(&ptpl,1, filepath,sizeof(filepath), 0, true);
return index ? doc.SetDocPath(filepath) : false;
}
TDocument*
TDocManager::FindDocument(const char far* path)
{
TDocument* doc = 0;
while ((doc = DocList.Next(doc)) != 0)
if (path) {
if (doc->GetDocPath() && strcmp(doc->GetDocPath(), path) == 0)
break;
}
else {
if (doc->GetDocPath() == 0)
break;
}
return doc;
}
void
TDocManager::PostEvent(int id, TDocument& doc)
{
TWindow* win = Application->GetMainWindow();
if (win && win->HWindow)
win->SendMessage(WM_OWLDOCUMENT, id, (LPARAM)&doc);
}
void
TDocManager::PostEvent(int id, TView& view)
{
TWindow* win = Application->GetMainWindow();
if (win && win->HWindow)
win->SendMessage(WM_OWLVIEW, id, (LPARAM)&view);
}
bool
TDocManager::EvCanClose()
{
TDocument* doc = 0;
while ((doc = DocList.Next(doc)) != 0) {
if (!doc->CanClose()) // normally calls back to FlushDoc()
return false;
}
return true;
}
//
// Preprocess the app frame's menu to replace the file menu with one managed
// by this docmanager
//
void
TDocManager::EvPreProcessMenu(HMENU hMenuBar)
{
if (Mode & dmMenu) {
HMENU hMenu = Application->LoadMenu(IDM_DOCMANAGERFILE);
if (!hMenu)
hMenu = ::Module->LoadMenu(IDM_DOCMANAGERFILE);
if (hMenu) {
char buf[40];
Application->LoadString(IDS_DOCMANAGERFILE, buf, sizeof buf);
if (Mode & dmNoRevert)
::DeleteMenu(hMenu, CM_FILEREVERT, MF_BYCOMMAND);
::DeleteMenu(hMenuBar, 0, MF_BYPOSITION);
::InsertMenu(hMenuBar, 0, MF_BYPOSITION|MF_POPUP, (uint)hMenu, buf);
}
}
}
void
TDocManager::EvWakeUp()
{
TDocument* doc = 0;
while ((doc = DocList.Next(doc)) != 0)
doc->ReindexFrames();
}
bool
TDocManager::FlushDoc(TDocument& doc)
{
while (doc.IsDirty()) {
int saveOrNot = doc.IsEmbedded() ?
IDYES :
PostDocError(doc, IDS_DOCCHANGED, MB_YESNOCANCEL);
switch (saveOrNot) {
case IDYES:
// Prompt the user for filename in save-as situation
//
if (!doc.IsEmbedded() && doc.GetDocPath() == 0) {
TDocTemplate* tpl = SelectAnySave(doc, false);
if (!tpl)
continue;
if (tpl != doc.Template)
doc.SetTemplate(tpl);
}
if (doc.Commit())
return true;
continue;
case IDNO:
if (doc.Revert(true))
return true;
return false;
case IDCANCEL:
return false;
}
}
return true;
}
TDocument*
TDocManager::GetCurrentDoc()
{
TDocument* doc = 0;
HWND hwnd = GetApplication()->GetMainWindow()->GetCommandTarget();
while ((doc = DocList.Next(doc)) != 0 && !doc->HasFocus(hwnd))
;
return doc;
}
//
// event handlers
//
void
TDocManager::CeFileNew(TCommandEnabler& ce)
{
ce.Enable(TemplateList != 0);
}
void
TDocManager::CmFileNew()
{
CreateAnyDoc(0, dtNewDoc);
}
void
TDocManager::CeFileOpen(TCommandEnabler& ce)
{
ce.Enable(TemplateList != 0);
}
void
TDocManager::CmFileOpen()
{
CreateAnyDoc(0, 0);
}
void
TDocManager::CeFileClose(TCommandEnabler& ce)
{
ce.Enable(GetCurrentDoc() != 0);
}
void
TDocManager::CmFileClose()
{
TDocument* doc = GetCurrentDoc();
if (doc && doc->CanClose()) { // normally calls back to FlushDoc()
if (!doc->Close())
PostDocError(*doc, IDS_UNABLECLOSE);
else
delete doc;
}
}
void
TDocManager::CeFileSaveAs(TCommandEnabler& ce)
{
TDocument* doc = GetCurrentDoc();
ce.Enable(doc != 0);
}
void
TDocManager::CmFileSaveAs()
{
TDocument* doc = GetCurrentDoc();
if (doc) {
TDocTemplate* tpl = SelectAnySave(*doc, false);
if (tpl) {
if (tpl != doc->Template)
doc->SetTemplate(tpl); // replace existing template
doc->Commit(true); // force rewrite to new path
}
}
}
void
TDocManager::CeFileSave(TCommandEnabler& ce)
{
TDocument* doc = GetCurrentDoc();
ce.Enable(doc && (doc->IsDirty() || (Mode & dmSaveEnable)));
}
void
TDocManager::CmFileSave()
{
TDocument* doc = GetCurrentDoc();
if (doc) {
if (doc->GetDocPath() == 0) {
CmFileSaveAs();
return;
}
if (!(Mode & dmSaveEnable) && !doc->IsDirty()) {
PostDocError(*doc, IDS_NOTCHANGED);
return;
}
doc->Commit(); // should force write here?
}
}
void
TDocManager::CeFileRevert(TCommandEnabler& ce)
{
TDocument* doc = GetCurrentDoc();
ce.Enable(doc && doc->IsDirty() && doc->GetDocPath());
}
void
TDocManager::CmFileRevert()
{
TDocument* doc = GetCurrentDoc();
if (doc && doc->GetDocPath()) {
if (!doc->IsDirty()) {
PostDocError(*doc, IDS_NOTCHANGED);
return;
}
doc->Revert();
}
}
void
TDocManager::CeViewCreate(TCommandEnabler& hndlr)
{
TDocument* doc = GetCurrentDoc();
hndlr.Enable(doc != 0);
}
void
TDocManager::CmViewCreate()
{
TDocument* doc = GetCurrentDoc();
if (doc)
CreateAnyView(*doc);
}
uint
TDocManager::PostDocError(TDocument& doc, uint sid, uint choice)
{
char buf[256];
if (Application->LoadString(sid, buf, sizeof buf) == 0)
strcpy(buf, "Error: Message not found"); // should throw exception?
if (choice != MB_OK)
choice |= MB_ICONQUESTION;
return Application->GetMainWindow()->MessageBox(buf, doc.GetTitle(), choice);
}
//
// CreateAnyDoc - selects from list of attached non-hidden doc templates
//
TDocument*
TDocManager::CreateAnyDoc(const char far* path, long flags)
{
TDocTemplate* ptpl;
TDocument* doc;
char filepath[256];
int index;
TDocTemplate* tpllist[40]; // increase number to display more templates
int tplcount = 0;
// compose list of visible templates
//
for (ptpl = TemplateList; ptpl; ptpl = ptpl->GetNextTemplate()) {
if (ptpl->IsVisible() &&
!(ptpl->IsFlagSet(dtReadOnly) && (flags & dtNewDoc)))
tpllist[tplcount++] = ptpl;
// prevent overflowing array
if (tplcount >= sizeof(tpllist)/sizeof(tpllist[0]))
break;
}
if (!tplcount)
return 0; // no usable templates
if (flags & dtNewDoc) { // creat empty doc from any registered template
index = tplcount==1 ? 1 : SelectDocType(tpllist, tplcount);
}
else { // select doc using filters from all registered templates
if (path)
strcpy(filepath, path);
else
filepath[0] = 0; // no initial file path
index = SelectDocPath(tpllist, tplcount, filepath, sizeof(filepath), flags);
WARNX(OwlDocView, index > tplcount, 0,
"Invalid template index from SelectDocPath");
}
if (!index)
return 0; // user cancel or dialog error
if (filepath && (doc = FindDocument(filepath)) != 0) {
PostDocError(*doc, IDS_DUPLICATEDOC);
return 0;
}
ptpl = tpllist[index-1];
if ((Mode & dmSDI) && (doc = DocList.Next(0)) != 0) { // one at a time if SDI
if (!doc->CanClose()) // normally calls back to FlushDoc()
return 0;
if (!doc->Close()) {
PostDocError(*doc, IDS_UNABLECLOSE);
return 0;
}
delete doc;
}
doc = ptpl->ConstructDoc(&TDocument(this)); // pass a dummy doc
doc->SetTemplate(ptpl);
return InitDoc(doc, filepath, flags);
}
//
// SelectAnySave - selects from registered templates supporting this doc
//
TDocTemplate*
TDocManager::SelectAnySave(TDocument& doc, bool samedoc)
{
TDocTemplate* ptpl;
char filepath[256];
int index;
TDocTemplate* tpllist[40];
int tplcount;
if (!TemplateList)
return 0; // if no templates are registered
for (tplcount = 0, ptpl = TemplateList; ptpl; ptpl = ptpl->GetNextTemplate()) {
if (ptpl->IsVisible() && (!samedoc || ptpl->IsMyKindOfDoc(doc))
&& !ptpl->IsFlagSet(dtReadOnly) )
tpllist[tplcount++] = ptpl;
}
if (!tplcount)
return 0; // no usable templates
if (doc.GetDocPath())
strcpy(filepath, doc.GetDocPath());
else
filepath[0] = 0; // no initial file path
index = SelectDocPath(tpllist, tplcount, filepath, sizeof(filepath),0,true);
if (!index)
return 0; // user cancel or dialog error
ptpl = tpllist[index-1];
if (!doc.SetDocPath(filepath))
return 0;
return ptpl;
}
//
// CreateAnyView - selects from registered templates supporting this doc
//
TView*
TDocManager::CreateAnyView(TDocument& doc, long /*flags*/)
{
const int MaxViewCount = 25;
TDocTemplate* tplList[MaxViewCount];
int tplCount;
TDocTemplate* ptpl;
int index;
const char far* viewName;
for (ptpl=TemplateList, tplCount=0; ptpl != 0; ptpl = ptpl->GetNextTemplate()) {
if (ptpl->IsMyKindOfDoc(doc)) {
viewName = ptpl->GetViewName();
for (index = 0; index < tplCount; index++)
if (tplList[index]->GetViewName() == viewName)
break;
if (ptpl->IsFlagSet(dtSingleView)) {
TView* pview = 0;
while ((pview = doc.NextView(pview)) != 0)
if (ptpl->IsMyKindOfView(*pview))
index = -1; // force continue in outer loop
}
if (index == tplCount) {
tplList[tplCount++] = ptpl;
}
}
}
index = (tplCount > 1) ? SelectViewType(tplList, tplCount) : tplCount;
if (index == 0) // check if user cancelled or no valid templates
return 0;
ptpl = tplList[index - 1];
return doc.InitView(ptpl->ConstructView(doc)); // call virtual create
}
#define ANSITOUPPER(c) ( (char)(unsigned)(unsigned long)\
::AnsiUpper((char far*)(unsigned long)(c)) )
TDocTemplate*
TDocManager::MatchTemplate(const char far* path)
{
TDocTemplate* ptpl;
char name[256];
if (FindDocument(path))
return 0; // prevent reload of same document
if (::GetFileTitle(path, name, sizeof(name)) != 0)
return 0; // invalid name or buffer too small
::AnsiUpper(name);
for (ptpl = TemplateList; ptpl != 0; ptpl = ptpl->GetNextTemplate()) {
const char far* pp = ptpl->GetFileFilter();
if (!pp || ptpl->IsFlagSet(dtHidden))
continue;
char* pn = name;
char cp;
do {
if ((cp = *pp++) != '?') {
if (cp == '*') {
while (*pn != '.' && *pn != 0)
pn++;
if (*pp == '.' && *pn == 0) // check for missing extension
pp++;
continue;
}
if (*pn != ANSITOUPPER(cp)) { // if mismatch
if (!(cp == ';' && *pn == 0)) { // check for successful case
while (cp != ';' && cp != 0) // check if more patterns
cp = *pp++;
pn = name; // rescan name
continue;
}
}
}
if (*pn++ == 0) // reached end of name OK
return ptpl;
} while (cp != 0);
}
return 0; // returns 0 if loop terminates with no matching templates
}
#endif
#if !defined(SECTION) || SECTION == 2
IMPLEMENT_STREAMABLE(TDocManager);
void*
TDocManager::Streamer::Read(ipstream& is, uint32 /*version*/) const
{
TDocManager* o = GetObject();
TDocTemplate* ptpl = o->TemplateList;
for (;;) {
int isStatic;
is >> isStatic;
if (isStatic == -1)
break;
if (isStatic) {
if (ptpl) { // if static templates available
is >> *ptpl; // update static template data
ptpl = o->GetNextTemplate(ptpl);
}
else { // have run out of static templates
char tbuf[sizeof(TDocTemplate)]; // sink for unused template data
memset(tbuf,0,sizeof(tbuf)); // force static flag off
is >> *(TDocTemplate*)tbuf;
}
}
else { // if dynamic template, object will be constructed
TModule* module;
is >> module;
is >> ptpl;
ptpl->SetModule(module);
o->AttachTemplate(*ptpl);
}
}
int count;
is >> count; // document count
while (count--) {
TDocument* doc;
is >> doc;
doc->SetDocManager(*o); // inserts properly into list
}
// Get application, & post ourselves a wakeup message to finish things up
// once all windows have been created, etc.
//
o->Application = GetApplicationObject();
TWindow* win = o->Application->GetMainWindow();
if (win && win->HWindow)
win->PostMessage(WM_OWLWAKEUP);
return o;
}
void
TDocManager::Streamer::Write(opstream& os) const
{
TDocManager* o = GetObject();
TDocTemplate* ptpl = 0;
while ((ptpl = o->GetNextTemplate(ptpl)) != 0) {
int flag = ptpl->IsStatic();
os << flag;
if (flag) {
os << *ptpl; // write reference to static template
}
else {
os << ptpl->GetModule(); // write template's module pointer first
os << ptpl; // write pointer to static template
}
}
os << -1; // template list terminator
TDocument* doc = 0;
int count;
for (count = 0; (doc = o->DocList.Next(doc))!=0; count++) ;
os << count;
// Must write documents out in order created, i.e. from end of list forward
//
while (count) {
int i = count--;
for (doc = 0; i--; doc = o->DocList.Next(doc)) ;
os << doc;
}
}
//
// TDocTemplate backward compatibility code
//
bool TDocManager::SelectSave(TDocTemplate* ptpl, TDocument& doc)
{
TDocManager* mgr = ptpl->GetDocManager();
if (!mgr || !ptpl || !ptpl->GetFileFilter())
return false;
char filepath[256];
if (doc.GetDocPath())
strcpy(filepath, doc.GetDocPath());
else
filepath[0] = 0; // no initial file path
int index = mgr->SelectDocPath(&ptpl,1, filepath,sizeof(filepath), 0, true);
return index ? doc.SetDocPath(filepath) : false;
}
TView* TDocManager::InitView(TView* view)
{
if (!view) // test in case new TView failed
return 0;
return view->GetDocument().InitView(view);
}
TDocument* TDocManager::InitDoc(TDocTemplate& tpl, TDocument* doc,
const char far* path, long flags)
{
TDocManager* mgr = tpl.GetDocManager();
if (!mgr || !doc)
return 0;
doc->SetTemplate(&tpl);
return mgr->InitDoc(doc, path, flags);
}
static void Obsolete() {TRACEX(OwlDocView, 0, "Obsolete function called");}
void TDocTemplate::SetFileFilter(const char far*) {Obsolete();}
void TDocTemplate::SetDescription(const char far*){Obsolete();}
void TDocTemplate::SetDefaultExt(const char far*) {Obsolete();}
#endif