OWLNext    7.0
Borland's Object Windows Library for the modern age
Loading...
Searching...
No Matches
docmanag.cpp
Go to the documentation of this file.
1//----------------------------------------------------------------------------
2// ObjectWindows
3// Copyright (c) 1993, 1996 by Borland International, All Rights Reserved
4//
5/// \file
6/// Implementation of class TDocManager
7//----------------------------------------------------------------------------
8#include <owl/pch.h>
9
10#include <owl/docmanag.h>
11#include <owl/appdict.h>
12#include <owl/opensave.h>
13#include <owl/picklist.h>
14#include <owl/system.h>
15#include <owl/filename.h>
16#include <owl/docview.rh>
17#include <string.h>
18#include <stdio.h>
19#include <dlgs.h>
20#include <memory>
21
22#if defined(__BORLANDC__)
23# pragma option -w-ccc // Disable "Condition is always true/false"
24#endif
25
26namespace owl {
27
28//
29// (Readable versions of) IDs of controls used by CommonDialogs
30//
31#define IDC_FILENAMETXT stc3
32#define IDC_FILENAME edt1
33#define IDC_FILELIST lst1
34#define IDC_CURDIR stc1
35#define IDC_DIRLIST lst2
36#define IDC_FILETYPEEXT stc2
37#define IDC_FILETYPES cmb1
38#define IDC_DRIVESTEXT stc4
39#define IDC_DRIVES cmb2
40#define IDC_HELPF pshHelp
41#define IDC_READONLY chx1
42
44
46
47
49
50//---------------------------------------------------------------------------
51// class TDvOpenSaveData
52//
53
54//
55/// Constructor of class representing the data to be displayed in the
56/// Open/Save dialogs used by the DocManager.
57//
62 int tmplCount)
63:
64 TOpenSaveDialog::TData(flags, filter, 0/*customFilter*/,
65 initialDir, defExt, 0/*maxPath*/, filterIndex),
66 TmplCount(tmplCount),
67 TmplList(tmplList)
68{
69}
70
71//
72/// Constructor of mixin. class used by the DocManager's version of the
73/// Open/Save dialogs.
74//
80
81//
82/// 'HandleTemplateChanged' is invoked whenever the user switches the
83/// file type in the FileOpen or FileSave dialog. The function updates
84/// the internal OPENFILENAME structure based on the properties of the
85/// new template selected.
86//
87static void
88handleTemplateChanged(TDialog& dialog,
90 OPENFILENAME& ofn)
91{
92 int index = static_cast<int>(dialog.SendDlgItemMessage(IDC_FILETYPES, CB_GETCURSEL));
93 if (index >= 0) {
94 CHECK(index < dataOwner.GetTmplCount());
95 TDocTemplate* tpl = dataOwner.GetTmplList()[index];
96
97 // Update default extension in OFN structure
98 //
99 CHECK(ofn.lpstrDefExt);
100 ofn.lpstrDefExt = tpl->GetDefaultExt();
101 }
102}
103
104//---------------------------------------------------------------------------
105// class TDvFileOpenDialog
106//
107
108//
109/// Constructor of object encapsulating the Open File dialog used by the
110/// DocManager.
111//
113 LPCTSTR title, TModule* module)
114:
115 TFileOpenDialog(parent, data, 0/*templateId*/, title, module),
117{
118}
119
120//
121/// Overriden virtual function of TFileOpenDialog to allow us to detect when
122/// the user switches between file types [i.e. DocView templates].
123//
126{
127 if (message == WM_COMMAND && LOWORD(p1) == IDC_FILETYPES &&
128 HIWORD(p1) == CBN_SELCHANGE) {
129 handleTemplateChanged(*this, *this, GetOFN());
130 }
131
133}
134
135//---------------------------------------------------------------------------
136// class TDvFileSaveDialog
137//
138
139//
140/// Constructor of object encapsulating the FileSave dialog used by the
141/// DocManager.
142//
144 LPCTSTR title, TModule* module)
145:
146 TFileSaveDialog(parent, data, 0/*templateId*/, title, module),
148{
149}
150
151//
152/// Overriden virtual function of TFileOpenDialog to allow us to detect when
153/// the user switches between file types [i.e. DocView templates].
154//
157{
158 if (message == WM_COMMAND && LOWORD(p1) == IDC_FILETYPES &&
159 HIWORD(p1) == CBN_SELCHANGE) {
160 handleTemplateChanged(*this, *this, GetOFN());
161 }
162
164}
165
166//----------------------------------------------------------------------------
167// class TDocManager
168//
169
177 EV_COMMAND(CM_FILESAVEAS, CmFileSaveAs),
178 EV_COMMAND(CM_FILEREVERT, CmFileRevert),
180 EV_COMMAND(CM_VIEWCREATE, CmViewCreate),
189
190//
191// Constructor of DocManager
192//
193/// The constructor performs the same operations as the first constructor. The
194/// additional app parameter, however, points to the application associated with
195/// this document.
196//
201
202//
203/// Helper routine used by constructors.
204///
205/// Common initialization for TDocManager constructors (above constructor, &
206/// compatable constructor below)
207//
208void
210{
211 Mode = mode;
212 TemplateList = templateHead;
213 TemplateHead = &templateHead;
214 UntitledIndex= 0;
215 AdditionalFileDialogFlags = 0;
216
218 Application = app;
219
220 // Update docmanger pointer members of static templates
221 for (TDocTemplate* tpl = TemplateList; tpl; tpl = tpl->GetNextTemplate())
222 tpl->DocManager = this;
223}
224
225//
226/// Destruct this DocManager. Close all open documents (views close with them),
227/// and delete all non-static doc templates
228///
229/// Destroys a TDocManager object removes attached documents templates. The
230/// constructor resets TDocTemplate::DocTemplateStaticHead to point to the head of
231/// the static template list.
232//
234{
235 // Iterate through document list, closing and deleting each
236 //
237 TDocument* doc;
238 while ((doc = DocList.Next(nullptr)) != nullptr) {
239 if (doc->IsOpen())
240 doc->Close();
241
242 // NOTE: deleting the document deletes all attached views, and unlinks
243 // the document from the docmanager's document list
244 //
245 delete doc;
246
247 // Flush (dispatch) any pending MDI-Child-destroy messages
248 //
250 }
251
252 // Reset the 'Docmanager' pointer of static templates and delete
253 // dynamic ones...
254 //
255 while (TemplateList) {
256 TDocTemplate* tpl = TemplateList;
257 TemplateList = tpl->GetNextTemplate();
258 if (tpl->IsStatic())
259 tpl->SetDocManager(nullptr);
260 else
261 delete tpl;
262 }
263}
264
265//----------------------------------------------------------------------------
266
267//
268/// Count the number of templates, filtering by document type and/or view type as
269/// indicated.
270//
271int
273{
274 // No registered templates!!
275 //
276 if (!TemplateList) {
277 TRACEX(OwlDocView, 0, _T("GetTemplateCount(): No registered templates!"));
278 return 0;
279 }
280
281 // Walk through template list matching doc/view types as indicated
282 //
283 int tplCount = 0;
284 for (TDocTemplate* tpl = TemplateList; tpl; tpl = tpl->GetNextTemplate()) {
285 if (ofDocType && !tpl->IsMyKindOfDoc(*ofDocType))
286 continue;
287
288 if (ofViewType && !tpl->IsMyKindOfView(*ofViewType))
289 continue;
290
291 tplCount++;
292 }
293 return tplCount;
294}
295
296//
297/// Build a list of templates for creating new documents or opening existing
298/// documents. Return the number of templates in the list. Passing 0 for tplList
299/// skips the actual creation of the list, useful for pre-counting. size is only
300/// used in the debug version.
301//
302#if __DEBUG < 2
303int
305#else
306int
308#endif
309{
310 // Check for no registered templates
311 //
312 if (!TemplateList) {
313 TRACEX(OwlDocView, 0, _T("GetNewTemplates(): No registered templates!"));
314 return 0;
315 }
316
317 // Walk thru all of the templates looking for visible ones, and if a new
318 // doc, non-dtReadOnly and non-dtForbidNew ones.
319 //
320 int tplCount = 0;
321 for (TDocTemplate* tpl = TemplateList; tpl; tpl = tpl->GetNextTemplate()) {
322 if (tpl->IsVisible() &&
323 !((tpl->IsFlagSet(dtReadOnly) || tpl->IsFlagSet(dtForbidNew))
324 && newDoc)){
325 if (tplList) {
326 CHECK(tplCount < size);
328 }
329 tplCount++;
330 }
331 }
332 return tplCount;
333}
334
335//
336/// Build a list of templates for saving documents. Return the number of templates
337/// in the list. Passing 0 for tplList skips the actual creation of the list, useful
338/// for pre-counting. size is only used in the debug version.
339//
340#if __DEBUG < 2
341int
343 TDocument& doc, bool sameDoc)
344#else
345int
347 TDocument& doc, bool sameDoc)
348#endif
349{
350 // Check for no registered templates
351 //
352 if (!TemplateList) {
353 TRACEX(OwlDocView, 0, _T("GetSaveTemplates(): No registered templates!"));
354 return 0;
355 }
356
357 // Walk thru all of the templates looking for visible, non-dtReadOnly ones,
358 // and if the same doc, ones that match the document
359 //
360 int tplCount = 0;
361 for (TDocTemplate* tpl = TemplateList; tpl; tpl = tpl->GetNextTemplate()) {
362 if (tpl->IsVisible() && !tpl->IsFlagSet(dtReadOnly)
363 && (!sameDoc || tpl->IsMyKindOfDoc(doc))) {
364 if (tplList) {
365 CHECK(tplCount < size);
367 }
368 tplCount++;
369 }
370 }
371 return tplCount;
372}
373
374//
375/// Build a list of templates for creating views. Return the number of templates in
376/// the list. size is only used in the debug version.
377///
378/// \note To find out ahead of time how many templates match a particular document
379/// type, use 'GetTemplateCount(docType);'
380//
381#if __DEBUG < 2
382int
384 TDocument& doc)
385#else
386int
388 TDocument& doc)
389#endif
390{
391 // Check for no registered templates
392 //
393 if (!TemplateList) {
394 TRACEX(OwlDocView, 0, _T("GetViewTemplates(): No registered templates!"));
395 return 0;
396 }
397
398 // Grab a list of templates for creating views
399 //
400 int tplCount = 0;
401 for (TDocTemplate* tpl = TemplateList; tpl; tpl = tpl->GetNextTemplate()) {
402 if (tpl->IsMyKindOfDoc(doc)) {
403
404 // Don't grab the same view more than once
405 //
406 LPCTSTR viewName = tpl->GetViewName();
407 int index;
408 for (index = 0; index < tplCount; index++) {
409 if (tplList[index]->GetViewName() == viewName)
410 break;
411 }
412
413 // Skip a view if the document already has one and the template
414 // specifies 'SingleView'.
415 //
416 if (tpl->IsFlagSet(dtSingleView)) {
417 TView* pview = 0;
418 while ((pview = doc.NextView(pview)) != nullptr)
419 if (tpl->IsMyKindOfView(*pview))
420 index = -1;
421 }
422
423 // Store the template if we have a match...
424 //
425 if (index == tplCount) {
426
427 CHECK(tplList);
428 CHECK(tplCount < size);
429
430 tplList[tplCount++] = tpl;
431 }
432 }
433 }
434 return tplCount;
435}
436
437//
438/// Build up a long string containing the template descriptions and file filters for
439/// every template in the given list. Return the length of the buffer needed.
440/// Passing 0 for buffer skips actual buffer writing. size is only used in the debug
441/// version. String will be in the form:
442/// \code
443/// "<descr1> (<filter1>)|(<filter1>)|<descr2> (<filter2>)|(<filter2>)|"
444/// \endcode
445//
446#if __DEBUG < 2
447int
449 LPTSTR buffer, int)
450#else
451int
453 LPTSTR buffer, int size)
454#endif
455{
456
457 int len = 0;
458
459 // If buffer is 0, then simply compute the length the template description(s)
460 // and filter(s)
461 //
462 if (!buffer) {
463 for (int count=0; count < tplcount; count++) {
464 TDocTemplate* tpl = tpllist[count];
465 CHECK(tpl);
466
467 LPCTSTR p = tpl->GetDescription();
468 int descLen = (p && *p) ? static_cast<int>(::_tcslen(p)) : 0;
469
470 p = tpl->GetFileFilter();
471 int fltrLen = (p && *p) ? static_cast<int>(::_tcslen(p)) : 0;
472
473 // Description + " (" + filter + ") " + filter +"|"
474 //
475 len += (descLen + 2 + fltrLen + 2 + fltrLen + 1);
476 }
477 }
478 else {
479
480 // Check that buffer is big enough
481 //
482 CHECK(GetTemplateDescription(tpllist, tplcount) < size);
483
484 // Put together a string of description and filters
485 //
486 buffer[0] = 0;
487 for (int count = 0; count < tplcount; count++ ) {
488 TDocTemplate* tpl = tpllist[count];
489 CHECK(tpl);
490
491 LPCTSTR p = tpl->GetDescription();
492 if (p && *p)
493 _tcscat(buffer, p);
494
495 p = tpl->GetFileFilter();
496 if (p && *p) {
497 _tcscat(buffer, _T(" ("));
498 _tcscat(buffer, p);
499 _tcscat(buffer, _T(")|"));
500 _tcscat(buffer, p);
501 }
502 _tcscat(buffer, _T("|"));
503 }
504 len = static_cast<int>(::_tcslen(buffer));
505 }
506
507 return len;
508}
509
510//----------------------------------------------------------------------------
511
512//
513/// Creates a document based on the directory path and the specified template. The
514/// parameter flags, one of the document template constants, determines how the
515/// document template is created. If path is 0 and this is not a new document (the
516/// flag dtNewDoc is not set), it displays a dialog box. If path is 0 and dtNewDoc
517/// is not set and more than one template exists, CreateAnyDoc displays a dialog box
518/// and a list of templates.
519//
522{
523 // Are we creating a new document?
524 //
525 bool newDoc = (flags & dtNewDoc) ? true : false;
526
527 // Get a count and list of templates
528 //
529 int tplcount = GetNewTemplates(nullptr, 0, newDoc);
530
531 // Return of there are no usable templates
532 //
533 if (!tplcount) {
534 TRACEX(OwlDocView, 0, _T("No usable templates found in CreateAnyDoc()"));
535 return nullptr;
536 }
537
538 // Allocate memory and get templates
539 //
543
545 filepath[0] = 0;
546
547 // Find the index of the template to be used
548 //
549 int index;
550 if (newDoc) {
551
552 // If there's only one template, use it - otherwise prompt user
553 // to select the document type
554 //
555 if (tplcount == 1)
556 index = 1;
557 else
559 }
560 else {
561
562 // Select the doctemplate using the doc template filters
563 // !CQ might be nice to skip UI if path is already known, and maybe only
564 // !CQ if there is just one template
565 //
566 if (path)
568 else
569 filepath[0] = 0;
570
572
573 WARNX(OwlDocView, index > tplcount, 0,
574 _T("Invalid template index from SelectDocPath"));
575 }
576
577 // No index implies user cancelled or error
578 //
579 if (!index)
580 return nullptr;
581
582 // If opening a document, check that document is not already opened
583 //
584 if (filepath[0]) {
586 if (doc != nullptr) {
588 return nullptr;
589 }
590 }
591
592 // We have a template, now create the document & return it if successful
593 //
594 return CreateDoc(tpllist[index-1], filepath, nullptr, flags);
595}
596
597//
598/// CreateDoc creates a document based on the directory path and the specified
599/// template. The flags parameter contains one of the document template constants
600/// that determines how the document is created.
601//
604 TDocument* parent, long flags)
605{
606 if (!tpl) {
607 TRACEX(OwlDocView, 0, _T("CreateDoc(): NULL template specified!"));
608 return nullptr;
609 }
610
611 // Creation step 0: Inform docmanager that we're about to create a document
612 // and allow docmanager to veto
613 //
614 if (!CreatingDoc(tpl)) {
615 TRACEX(OwlDocView, 1, _T("CreateDoc(): Creation vetoed."));
616 return nullptr;
617 }
618
619 // Creation step 1: Construct the document, passing in the parent document
620 // Put together a dummy parent document if no parent doc was specified in
621 // order to allow us to pass in the DocManager pointer hidden in the parent.
622 //
623 auto constructDoc = [&]
624 {
625 if (parent)
626 return tpl->ConstructDoc(parent);
627 else
628 {
629 TDocument dummy{this};
630 return tpl->ConstructDoc(&dummy);
631 }
632 };
633 auto d = std::unique_ptr<TDocument>{constructDoc()};
634 if (!d) {
635 TRACEX(OwlDocView, 0, _T("CreateDoc(): ConstructDoc call failed"));
636 return nullptr;
637 }
638
639 // Creation step2: Initialize the document
640 //
641 d->SetTemplate(tpl);
642 if (!InitDoc(d.get(), path, flags)) {
643 TRACEX(OwlDocView, 0, _T("CreateDoc: InitDoc failed"));
644 d.release(); // InitDoc failed and deleted the document.
645 return nullptr;
646 }
647 return d.release(); // Pass ownership to caller.
648}
649
650//
651/// Initializes the document, using the given path for the document and the given document flags.
652///
653/// Prompts for pathname using TDocManager::SelectDocPath, if no path is supplied and not creating
654/// a new document (i.e. the dtNewDoc flag is not set). If the user cancels the dialog, the
655/// document is deleted and `nullptr` is returned.
656///
657/// \sa See \ref docview for valid flags, such as dtAutoDelete and dtNewDoc.
658///
659/// \note Unless an exception is thrown, ownership of the given TDocument is taken on failure.
660/// In particular, the document will be deleted if it cannot be properly initialized, if it cannot
661/// be opened successfully (for dtAutoOpen), and unless dtNoAutoView is set, if creation of the
662/// view fails. In these cases the function deletes the document and returns `nullptr`.
663//
666{
668
669 TDocTemplate* tpl = doc->GetTemplate();
670 CHECKX(tpl, _T("TDocManager::InitDoc: No template"));
671
672 // Alter flags with template's flags
673 //
674 flags ^= tpl->GetFlags();
675
676 // Initialize new document
677 //
678 if (flags & dtNewDoc) {
679 doc->SetDocPath(nullptr);
680
681 // Allow document to initialize and cleanup if unsuccessful
682 //
683 if (!doc->InitDoc()){
684 TRACEX(OwlDocView, 0, _T("TDocManager::InitDoc: Initialization failed"));
686 delete doc;
687 return nullptr;
688 }
689 }
690 else {
691 if (!path) {
692 CHECKX(tpl->GetFileFilter(), _T("TDocManager::InitDoc: No file filter"));
693
694 // Prompt user for document's path
695 //
697 filepath[0] = 0;
698 int index = SelectDocPath(&tpl, 1, filepath, COUNTOF(filepath), flags);
699
700 // if user cancelled UI, cleanup document
701 //
702 if (!index) {
703 TRACEX(OwlDocView, 0, _T("TDocManager::InitDoc: User cancellation"));
704 delete doc;
705 return nullptr;
706 }
707
708 path = filepath;
709 }
710
711 // Update document's path
712 //
713 doc->SetDocPath(path);
714
715 // Allow document to initialize and cleanup if unsuccessful
716 //
717 if (!doc->InitDoc()) {
718 TRACEX(OwlDocView, 0, _T("TDocManager::InitDoc: Initialization failed"));
720 doc->SetDocPath(nullptr); // fix by suggested Greg Chicares 06/04/98
721 delete doc;
722 return nullptr;
723 }
724
725 // Attempt to open document if 'dtAutoOpen' is enabled. Cleanup if
726 // unsuccessful.
727 //
728 if (flags & dtAutoOpen) {
729 if (!doc->Open((flags & dtNoReadOnly) ? ofReadWrite : ofRead, path)) {
730 TRACEX(OwlDocView, 0, _T("TDocManager::InitDoc: Cannot open the document"));
732 doc->SetDocPath(nullptr); // fix by suggested Greg Chicares 06/04/98
733 delete doc;
734 return nullptr;
735 }
736 }
737 }
738
739 // Create a view unless 'dtNoAutoView' flag is set. Cleanup on failure.
740 //
741 if (!(flags & dtNoAutoView)) {
742 if (!CreateView(*doc)) {
743 TRACEX(OwlDocView, 0, _T("TDocManager::InitDoc: Cannot create a view"));
744 if (doc->IsOpen())
745 doc->Close();
746 doc->SetDocPath(nullptr);
747 delete doc;
748 return nullptr;
749 }
750 }
751
752 // Post event that document has been created
753 //
754 PostEvent(dnCreate, *doc); // WM_OWLDOCUMENT
755
756 return doc;
757}
758
759//
760/// Creates a document view based on the directory path and specified template. The
761/// parameter flags, one of the document template constants, determines how the
762/// document template is created.
763///
764/// Create (Construct and Init) a view from registered templates supporting
765/// a given doc.
766///
767/// This implementation allows user intervention if there is more than one
768/// template available, by calling SelectViewType()
769//
770TView*
772{
774
775 // Abort if there are no usable templates
776 //
777 if (!tplCount) {
778 WARNX(OwlDocView, !tplCount, 0, _T("CreateAnyView(): no usable template"));
779 return nullptr;
780 }
781
782 // Allocate memory for templates and get 'em
783 //
787
788 int index;
789 if (tplCount > 1)
791 else
792 index = tplCount;
793
794 if (index <= 0) {
795 WARNX(OwlDocView, !tplCount, 0, _T("CreateAnyView(): no usable template"));
796 WARNX(OwlDocView, tplCount, 0, _T("CreateAnyView(): invalid template index"));
797 return nullptr;
798 }
799
800 CHECK(index > 0);
801 //CHECK(index < tplCount);//?????????
802 CHECK(index <= tplCount);
803
804
805 // Now create the view on the document using the selected template
806 //
807 return CreateView(doc, tplList[index-1]);
808}
809
810//
811/// Create a view on a given document using the given tempalte, or document's
812/// template if none given, and then initialize the view. Return the view if
813/// all was OK, or 0 if something failed.
814//
815TView*
817{
818 // Default to the document's template if none provided
819 //
820 if (!tpl)
821 tpl = doc.GetTemplate();
822 CHECK(tpl);
823
824 TView* view = tpl->ConstructView(doc);
825 WARNX(OwlDocView, !view, 0, _T("CreateView(): ConstructView call failed"));
826
827 view = doc.InitView(view);
828 WARNX(OwlDocView, !view, 0, _T("CreateView(): InitView call failed"));
829
830 return view;
831}
832
833//----------------------------------------------------------------------------
834
835//
836/// Displays FileSave dialog prompting the user to select a file name for savinng the document.
837/// Filters out read-only files.
838//
839bool
841{
842 TDocTemplate* tpl = doc.GetTemplate();
843
844 if (!tpl || !tpl->GetFileFilter())
845 return false;
846
848 if (doc.GetDocPath())
849 ::_tcscpy(filepath, doc.GetDocPath());
850 else
851 filepath[0] = 0; // no initial file path
852
853 int index = SelectDocPath(&tpl, 1, filepath, COUNTOF(filepath), 0, true, &doc);
854 return index ? doc.SetDocPath(filepath) : false;
855}
856
857//
858/// Select a new docpath for a document from the registered templates
859/// supporting the doc.
860//
863{
864 int tplcount = GetSaveTemplates(nullptr, 0, doc, samedoc);
865
866 // Abort if there are no usable templates
867 //
868 if (!tplcount) {
869 WARNX(OwlDocView, !tplcount, 0, _T("SelectAnySave(): no usable templates"));
870 return nullptr;
871 }
872
873 // Allocate memory for templates and get 'em
874 //
878
879 // Grab the file name, if there's one
880 //
882 if (doc.GetDocPath())
883 ::_tcscpy(filepath, doc.GetDocPath());
884 else
885 filepath[0] = 0;
886
887 // Allow UI for user input
888 //
889 int index;
890 index = SelectDocPath(tpllist, tplcount, filepath, COUNTOF(filepath), 0, true, &doc);
891 if (!index)
892 return nullptr;
893
894 CHECK(index >= 1);
895 CHECK(index <= tplcount);
896
897 // Perform save by setting the new path into the doc
898 // !CQ Also notify doc of save somehow?
899 //
900 if (!doc.SetDocPath(filepath))
901 return nullptr;
902
903 return tpllist[index-1];
904}
905
906//
907/// Method invoked when specified document is about to be closed.
908/// Updates the document with any changes and prompts the user for confirmation of
909/// updates.
910/// Returns 'true' if DocManager should proceed with the closing
911/// stages of the document, or 'false' otherwise.
912//
913bool
915{
916 while (doc.IsDirty()) {
917 int saveOrNot = doc.IsEmbedded() ?
918 IDYES :
920
921 switch (saveOrNot) {
922 case IDYES:
923 // Prompt the user for filename in save-as situation
924 //
925 if (!doc.IsEmbedded() && doc.GetDocPath() == nullptr) {
926
927 // !BB
928 // !BB It does not make sense to invoke SelectAnySave
929 // !BB with false here... This would allow the user
930 // !BB to switch to any available template when saving the
931 // !BB document. In other words, a user would be allowed to
932 // !BB save a .TXT file as a .PTS file although they are
933 // !BB not related whatsoever...
934 // !BB
935 // !BB I'm switching this to use true - let me know if you
936 // !BB know of a reason for the prior behaviour.
937 // !BB
938
939#if defined(OLD_DOCVIEW)
941#else
943#endif
944 if (!tpl)
945 continue;
946
947 // !BB
948 // !BB The following is suspicious: Is there a reason
949 // !BB to allow the user to switch the template in the first
950 // !BB place?? OK, if everyone agrees that same TDocument-derived
951 // !BB type implies compatible document, that would be OK.
952 // !BB However, that's not what we've encouraged. Our own
953 // !BB examples use the same TFileDocument for incompatible
954 // !BB document types. Hence, if an app. has a
955 // !BB TBitmapView/TFileDocument and a TTextView/TFileDocument pair,
956 // !BB the following would allow the user to save a text file as a .BMP
957 // !BB Ack!!
958 // !BB If the following is really the intent, then DV users must be
959 // !BB conscious that they will more often than not be using TFileDocument-
960 // !BB derived documents as a method to specify compatible and incompatible
961 // !BB document types.
962 //
963 if (tpl != doc.Template)
964 doc.SetTemplate(tpl);
965 }
966 if (doc.Commit())
967 return true;
968 continue;
969
970 case IDNO:
971 if (doc.Revert(true))
972 return true;
973 return false;
974
975 case IDCANCEL:
976 return false;
977 }
978 }
979 return true;
980}
981
982//----------------------------------------------------------------------------
983
984//
985/// Returns the first registered template whose pattern matches the given file name.
986/// If no template is compatible with the supplied file name, or if the template is
987/// open already, it returns 0.
988///
989/// This implementation compares the path's extension with the ';' separated
990/// filter lists in each template looking for a case-insensitive match. Allows
991/// '?'s in the template filters to match any character in the path's extension
992///
993/// Example:
994///
995/// The path: "documents.1995\accounts_receivable.plan"
996///
997/// Would match the filter: "*.xls;*.wk?;*.plan"
998//
1001{
1002
1003 // !BB if (FindDocument(path))
1004 // !BB return 0;
1005
1006 // Iterate through templates
1007 //
1008 for (TDocTemplate* tpl = TemplateList; tpl != nullptr; tpl = tpl->GetNextTemplate()) {
1009
1010 // Skip hidden templates or templates without filters specified
1011 //
1012 LPCTSTR tplFilter = tpl->GetFileFilter();
1013 if (!tplFilter || tpl->IsFlagSet(dtHidden))
1014 continue;
1015
1017 return tpl;
1018 }
1019 return nullptr;
1020}
1021
1022//
1023/// Helper function used by 'MatchTemplate'. Returns true if the specified file name
1024/// (path) matches any of the patterns of the 'filters' parameter. Returns false otherwise.
1025//
1026bool
1028{
1029 // Make locale copy of filter
1030 //
1034
1035 // For each template, try each wilcard specified
1036 //
1037 while (fltr) {
1038 // Is there another wildcard following - Null terminate at ';'
1039 //
1040 nxtFltr = _tcschr(fltr, _T(';'));
1041 if (nxtFltr)
1042 *nxtFltr++ = 0;
1043
1044 if (IsAMatch(path, fltr))
1045 return true;
1046
1047 // Try next filter
1048 //
1049 fltr = (nxtFltr && *nxtFltr) ? nxtFltr : nullptr;
1050 }
1051
1052 return false;
1053}
1054
1055//
1056/// Internal routine used to match a portion of a filename (i.e. name or
1057/// extension) to a wilcard pattern.
1058//
1059static bool
1060nameMatch(LPCTSTR name, LPCTSTR wc)
1061{
1062 while (true) {
1063 //if (*wc == _T('*') || (!*wc && !*name))
1064 // Greg Bullock suggestion
1065 if ((*wc == _T('*') && (wc[1] == _T('\0'))) || (!*wc && !*name))
1066 return true;
1067 if (*wc == _T('*')) {
1068 // The wildcard string begins with '*' but ends with something else (e.g., "*~")
1069 // We'll need to verify that the ending of name matches the wildcard string.
1070 wc++;
1071 size_t namelen = _tcslen(name);
1072 size_t wclen = _tcslen(wc);
1073 if (namelen > wclen)
1074 name += namelen - wclen;
1075 }
1076#if defined(BI_DBCS_SUPPORT)
1077 int n = CharSize(name);
1078 if (*wc == _T('?') && *name) {
1079 wc++;
1080 name += n;
1081 continue;
1082 }
1083 else if (n > 1) { // if double byte character
1084 if (_tcsncmp(name, wc, n) == 0) {
1085 wc += n;
1086 name += n;
1087 continue;
1088 }
1089 }
1090 else if (_totupper(*name) == _totupper(*wc)) {
1091#else
1092 if ((*wc == _T('?') && *name) || (_totupper(*name) == _totupper(*wc))) {
1093#endif
1094 wc++;
1095 name++;
1096 continue;
1097 }
1098 break;
1099 }
1100 return false;
1101}
1102
1103//
1104/// Helper function used by 'MatchTemplate'. Returns true if the specified file name
1105/// (path) matches the pattern of the 'filter' parameter. Returns false otherwise.
1106//
1107bool
1109{
1112
1113 // Ensure path has at least a valid file name
1114 //
1116 if (!fname.HasParts(TFileName::File)) {
1117 TRACEX(OwlDocView, 0, _T("IsAMatch: Invoked with invalid path"));
1118 return false;
1119 }
1120
1121 // Retrieve name/extension from path
1122 //
1123 tstring name = fname.GetParts(TFileName::File);
1124 tstring ext = fname.GetParts(TFileName::Ext);
1125
1126 // Get pointers to path's name and extension
1127 //
1128 LPCTSTR ppn = name.c_str();
1129 LPCTSTR ppe = fname.HasParts(TFileName::Ext) ? ext.c_str() : _T("");
1130 if (*ppe == _T('.'))
1131 ppe++;
1132
1133 // Get pointers to filter's name and extension
1134 //
1136 tchar* pfn = filter;
1137 tchar* pfe = _tcsrchr(filter, _T('.'));
1138
1139 // Skip past '.' separator of filter
1140 //
1141 if (pfe)
1142 *pfe++ = 0;
1143 const tchar* const cpfe = pfe ? pfe : _T("");
1144
1145 // Match the name and extension
1146 //
1147 return nameMatch(ppn, pfn) && nameMatch(ppe, cpfe);
1148}
1149
1150//
1151/// Calls TWindow::GetFocus() to determine the window with the focus. Searches the
1152/// list of documents and returns the document that contains the view with the
1153/// focus. Returns 0 if no document has a view with focus.
1154//
1155TDocument*
1157{
1159 PRECONDITION(GetApplication()->GetMainWindow());
1160
1162 TDocument* doc = 0;
1163
1164#if defined(OLD_DOCVIEW)
1165 // !BB This older implementation of GetCurrentDoc relies on the
1166 // !BB document's HasFocus method which does not allow 'GetCurrentDoc'
1167 // !BB to return child documents....
1168 // !BB
1169 // !BB This obviously causes some problems (for example, closing a view
1170 // !BB associated with a child document closes the whole document and
1171 // !BB all their associated views!).
1172 // !BB
1173 // !BB However is there code that relies on this behaviour - Investigate
1174 // !BB
1175
1176 if (hWnd && ::IsWindow(hWnd)) {
1177 while ((doc = DocList.Next(doc)) != 0 && !doc->HasFocus(hWnd))
1178 ;
1179 }
1180
1181#else
1182 if (hWnd && ::IsWindow(hWnd)) {
1183 while ((doc = DocList.Next(doc)) != nullptr ) {
1184 TDocument* childDoc = doc->DocWithFocus(hWnd);
1185 if (childDoc) {
1186 doc = childDoc;
1187 break;
1188 }
1189 }
1190 }
1191#endif
1192 return doc;
1193}
1194
1195//
1196/// Returns a pointer to the TDocument object if the specified document
1197/// is currently opened and manager by the DocManager. Returns 0 otherwise.
1198//
1199TDocument*
1201{
1202 TDocument* doc = 0;
1203 while ((doc = DocList.Next(doc)) != nullptr)
1204 if (path) {
1205 if (doc->GetDocPath() && _tcsicmp(doc->GetDocPath(), path) == 0)
1206 break;
1207 }
1208 else {
1209 if (doc->GetDocPath() == nullptr)
1210 break;
1211 }
1212 return doc;
1213}
1214
1215//----------------------------------------------------------------------------
1216
1217//
1218/// Adds a template to the template list managed by the DocManager.
1219//
1220void
1222{
1223 tpl.SetDocManager(this);
1224 TDocTemplate::AddLink(reinterpret_cast<TRegLink**>(&TemplateList), &tpl);
1225}
1226
1227//
1228/// Removes a template from the list of templates currently managed by
1229/// the DocManager.
1230//
1231void
1233{
1234 // Skip static templates
1235 //
1236 if (tpl.IsStatic()) {
1237 TRACEX(OwlDocView, 0, _T("TDocManager::DeleteTemplate() invoked for static"));
1238 return;
1239 }
1240
1241 // Check if it has an owner
1242 //
1243 if (!tpl.GetDocManager()) {
1244 TRACEX(OwlDocView, 0, _T("TDocManager::DeleteTemplate(), templ. has no owner"));
1245 return;
1246 }
1247
1248 // Unreference the template - will be deleted unless documents
1249 // still reference template.
1250 //
1251 if (TDocTemplate::RemoveLink(reinterpret_cast<TRegLink**>(&TemplateList), &tpl)) {
1253 return;
1254 }
1255
1256 TRACEX(OwlDocView, 0, _T("TDocManager::DeleteTemplate(), not in app list"));
1257}
1258
1259//----------------------------------------------------------------------------
1260
1261//
1262/// Displays a message box with the error message passed as a string resource ID in
1263/// sid. By default, the message box contains either an OK push button or a question
1264/// mark icon. If an error message can't be found, PostDocError displays a "Message
1265/// not found" message. choice can be one or more of the MB_Xxxx message style
1266/// constants. This function can be overridden.
1267///
1268/// Returns an integer
1269/// identifying the MessageBox option (push-button) selected by the user.
1270//
1271uint
1273{
1275 PRECONDITION(GetApplication()->GetMainWindow());
1276
1277 tchar buf[256];
1278 if (GetApplication()->LoadString(sid, buf, sizeof(buf) / sizeof(tchar)) == 0)
1279#if BI_MSG_LANGUAGE == 0x0411
1280 _stprintf(buf, "´×°: •¶Žš—ñ ID %u ‚ªŒ©‚‚©‚è‚Ü‚¹‚ñ", sid);
1281#else
1282 _stprintf(buf, _T("Error: Message [string ID %u] not found"), sid);
1283#endif
1284
1285 if (choice != MB_OK)
1287 return GetApplication()->GetMainWindow()->MessageBox(buf, doc.GetTitle(), choice);
1288}
1289
1290//
1291/// Post a OWL-defined message regarding an event [identified by the 'id'
1292/// parameter] related to the specified document ('doc').
1293//
1294/// If the current document changes, posts a WM_OWLDOCUMENT message to indicate a
1295/// change in the status of the document.
1296//
1297void
1299{
1301 if (win && win->GetHandle())
1303}
1304
1305//
1306/// Post a OWL-defined message regarding an event [identified by the 'id'
1307/// parameter] related to the specified view ('view').
1308//
1309/// If the current view changes, posts a WM_OWLVIEW message to indicate a change in
1310/// the status of the view.
1311//
1312void
1314{
1316 if (win && win->GetHandle())
1317 win->SendMessage(WM_OWLVIEW, id, TParam2(&view));
1318}
1319
1320//----------------------------------------------------------------------------
1321
1322//
1323/// Given a list of templates, lets the user select a document type from a list of document templates. Returns
1324/// the template index used for the selection, or 0 if unsuccessful. SelectDocType
1325/// can be overridden.
1326//
1327int
1329{
1330 TPickListPopup pickl(GetApplication()->GetMainWindow(), IDS_DOCLIST);
1331 while (tplcount--) {
1332 CHECK(*tpllist);
1333 pickl.AddString((*tpllist++)->GetDescription());
1334 }
1335 int index = pickl.Execute() + 1;
1336 if (index == -1)
1337 return 0;
1338 return index;
1339///TH This does not look right, crashes when user cancels twice
1340// return pickl.Execute() + 1;
1341}
1342
1343//
1344/// Given a list of templates, prompts the user to select one of the templates to use for the file to be
1345/// opened. Returns the template index used for the selection, or 0 if unsuccessful.
1346/// For a file open operation, save is false. For a file save operation, save is
1347/// true. This function can be overridden to provide a customized user interface.
1348///
1349/// \note This is Windows-specific, using the system-provided file open dialog box
1350//
1351int
1353 LPTSTR path, int buflen, long flags,
1354 bool save, TDocument* doc)
1355{
1356 // Compute length of description(s) and filter(s)
1357 //
1359
1360 // Put together a string of description and filters
1361 //
1364
1365 // Find the (default) template to select
1366 //
1367 int index, count;
1368 TDocument* curDoc = save ? (doc ? doc : GetCurrentDoc()) : nullptr;
1369 CHECK(!save || curDoc);
1370 if (save) {
1371 for (index = count = 0; count < tplcount; count++) {
1372 if (tpllist[count] == curDoc->GetTemplate()) {
1373 index = count;
1374 break;
1375 }
1376 }
1377 }
1378 else {
1379 for (index = count = 0; count < tplcount; count++) {
1380 if (tpllist[count]->IsFlagSet(dtSelected)) {
1381 index = count;
1382 break;
1383 }
1384 }
1385 }
1386
1387 // Initialize data structure used for launching Common Dialog
1388 //
1389 flags = (tpllist[index]->GetFlags() | flags);
1390 flags &= 0x000FFFFF; // Clear Doc/View related flags.
1391 flags |= AdditionalFileDialogFlags; // Add extended flags, e.g. OFN_ENABLESIZING.
1392 flags &= ~dtProhibited; // Clear unsupported flags, e.g. OFN_ENABLETEMPLATE.
1393 TDvOpenSaveData data(flags, // flags
1394 filtbuf, // filter
1395 CONST_CAST(LPTSTR, tpllist[index]->GetDirectory()), // initDir.
1396 CONST_CAST(LPTSTR, tpllist[index]->GetDefaultExt()), // defExt.
1397 index ? index+1 : 0, // filterIndex
1398 tpllist, // template list
1399 tplcount); // template count
1400
1401 //--- Sirma (Krasi)
1402 {
1403 LPCTSTR fName = path && *path ? path : (doc ? doc->GetTitle() : nullptr);
1404 if (fName && *fName)
1405 _tcsncpy(data.FileName, fName, buflen);
1406 }
1407 //--- Sirma (Krasi) ---
1408
1409 // Execute dialog
1410 //
1411 int result;
1412 TWindow* parent = GetApplication()->GetMainWindow();
1413 if (save)
1414 result = TDvFileSaveDialog(parent, data).Execute();
1415 else
1416 result = TDvFileOpenDialog(parent, data).Execute();
1417 WARNX(OwlDocView, data.Error != 0, 0, _T("Common dialog error: ") << data.Error << _T(" in SelectDocPath()"));
1418 if (result != IDOK || data.Error != 0) return 0; // Dialog was cancelled or failed.
1419
1420 // !BB
1421 // Here, there's a major dilemma! How, do we know the user did not
1422 // mislead us? For example, the user may have selected the *wrong*
1423 // template for saving a particular document... This is crucial when
1424 // saving documents!!!
1425 //
1426
1427 // Update templates to 'remember' the template last used
1428 //
1429 for (count = 0; count < tplcount; count++) {
1430 if (count == index-1)
1431 tpllist[count]->SetFlag(dtSelected);
1432 else
1433 tpllist[count]->ClearFlag(dtSelected);
1434 }
1435
1436 // Update selected template with directory
1437 //
1438 // // !BB Yeah! Where's the meat?
1439
1440
1441 // Copy file name over
1442 //
1443 CHECK(path);
1444 if (data.FileName && data.FileName[0]) {
1445 WARNX(OwlDocView, ::_tcslen(data.FileName) < (size_t)buflen, 0,
1446 _T("SelectDocPath: Specified buffer is too small"));
1447 _tcsncpy(path, data.FileName, buflen);
1448 }
1449 else
1450 *path = 0;
1451
1452 // Return index [1-based] of selected template
1453 //
1454 CHECK(data.FilterIndex >= 1);
1455 CHECK(data.FilterIndex <= tplcount);
1456 return data.FilterIndex;
1457}
1458
1459//
1460/// Given a list of templates, lets the user select a view name for a new view from a list of view names.
1461/// Returns the template index used for the selection or 0 if unsuccessful.
1462/// SelectViewType can be overridden,
1463//
1464int
1466{
1467 TPickListPopup pickl(GetApplication()->GetMainWindow(), IDS_VIEWLIST);
1468 while (tplcount--) {
1469 CHECK(*tpllist);
1470 pickl.AddString((*tpllist++)->GetViewName());
1471 }
1472 return pickl.Execute() + 1;
1473}
1474
1475//
1476/// Overrideable method invoked just before the DocumentManager creates a new
1477/// document. The default behaviour is to close and delete the current
1478/// document if we're in SDI mode.
1479//
1480bool
1482{
1483 if (Mode & dmSDI) {
1484 TDocument* doc = DocList.Next(nullptr);
1485 if (doc) {
1486 if (!doc->CanClose())
1487 return false;
1488 if (!doc->Close()) {
1490 return false;
1491 }
1492 delete doc;
1493 }
1494 }
1495 return true;
1496}
1497
1498//
1499/// Update the specified menu bar by removing the current '&File' popup menu [assumed
1500/// to be the first popup of the menubar] and replacing it with the ObjectWindows'
1501/// standard File popup menu resource.
1502//
1503void
1505{
1507
1509 if (!hMenu)
1511 if (hMenu) {
1512 tchar menuTitle[40];
1514
1516 if (Mode & dmNoRevert)
1518
1519 // Assumes '&File' popup is first entry of menubar...
1520 //
1521 menubar.DeleteMenu(0, MF_BYPOSITION);
1522 menubar.InsertMenu(0, MF_BYPOSITION|MF_POPUP, reinterpret_cast<TMenuItem>(hMenu), menuTitle);
1523 }
1524 WARNX(OwlDocView, !hMenu, 0, _T("Cannot load DocManager's File Menu"));
1525}
1526
1527//
1528/// Notifies the views of all documents and the views of any child documents
1529/// of a change. Returns true if all views returned a true result.
1530//
1532{
1533 bool answer = true;
1534
1535 TDocument* doc = 0;
1536 while ((doc = DocList.Next(doc)) != nullptr)
1537 {
1538 bool r = doc->NotifyViews(event, item, exclude);
1539 answer = answer && r;
1540 }
1541
1542 return answer;
1543}
1544
1545//----------------------------------------------------------------------------
1546
1547//
1548/// Checks to see if all child documents can be closed before closing the current
1549/// document. If any child returns false, returns false and aborts the process. If
1550/// all children return true, EvCanClose calls TDocManager::FlushDoc for each
1551/// document. If FlushDoc finds that the document is dirty, it displays a message
1552/// asking the user to save the document, discard any changes, or cancel the
1553/// operation. If the document is not dirty and CanClose returns true, EvCanClose
1554/// returns true.
1555//
1556bool
1558{
1559 TDocument* doc = 0;
1560 while ((doc = DocList.Next(doc)) != nullptr) {
1561 if (!doc->CanClose()) // normally calls back to FlushDoc()
1562 return false;
1563 }
1564 return true;
1565}
1566
1567//
1568/// Preprocess the app frame's menu to replace the file menu with one managed
1569/// by this docmanager
1570//
1571/// Called from MainWindow, EvPreProcessMenu loads and deletes a menu at the
1572/// position specified by MF_POSITION or MF_POPUP. Your application can call
1573/// EvPreProcessMenu to process the main window's menu before it is displayed.
1574//
1575void
1577{
1578 if (Mode & dmMenu){
1579 TMenu menu(hMenuBar);
1580 UpdateFileMenu(menu);
1581 }
1582}
1583
1584//
1585/// Used only after streaming in the doc manager, EvWakeUp allows for the windows to
1586/// be created after the streaming has occurred.
1587//
1588void
1590{
1591 TDocument* doc = 0;
1592 while ((doc = DocList.Next(doc)) != nullptr)
1593 doc->ReindexFrames();
1594}
1595
1596//----------------------------------------------------------------------------
1597// Command event handlers
1598//
1599
1600//
1601/// Command enabler for CmFileNew.
1602//
1603void
1604TDocManager::CeFileNew(TCommandEnabler& ce)
1605{
1606 ce.Enable(TemplateList != nullptr);
1607}
1608
1609//
1610//
1611//
1612void
1614{
1615 CreateAnyDoc(nullptr, dtNewDoc);
1616}
1617
1618//
1619/// Command enabler for CmFileOpen.
1620//
1621void
1622TDocManager::CeFileOpen(TCommandEnabler& ce)
1623{
1624 ce.Enable(TemplateList != nullptr);
1625}
1626
1627//
1628//
1629//
1630void
1632{
1633 CreateAnyDoc(nullptr, 0);
1634}
1635
1636//
1637/// Command enabler for CmFileClose.
1638//
1639void
1640TDocManager::CeFileClose(TCommandEnabler& ce)
1641{
1642 ce.Enable(GetCurrentDoc() != nullptr);
1643}
1644
1645//
1646/// If the document can be closed it is closed.
1647//
1648void
1650{
1652 if (doc && doc->CanClose()) { // normally calls back to FlushDoc()
1653 if (!doc->Close())
1655 else
1656 delete doc;
1657 }
1658 WARNX(OwlDocView, !doc, 0, _T("FileClose invoked with no current doc"));
1659}
1660
1661//
1662/// Command enabler for CmFileSaveAs.
1663//
1664void
1665TDocManager::CeFileSaveAs(TCommandEnabler& ce)
1666{
1668 ce.Enable(doc != nullptr);
1669}
1670
1671//
1672/// SelectAnySave() is called to get a template. Then the Commit() function is called
1673/// for the current document.
1674//
1675void
1677{
1679 if (doc) {
1680 TDocTemplate* tpl = SelectAnySave(*doc, true);
1681 if (tpl) {
1682 if (tpl != doc->Template)
1683 doc->SetTemplate(tpl); // replace existing template
1684 if (doc->Commit(true)) // force rewrite to new path
1685 PostEvent(dnRename, *doc); // WM_OWLDOCUMENT
1686 }
1687 }
1688}
1689
1690//
1691/// Command enabler for CmFileSave.
1692//
1693void
1694TDocManager::CeFileSave(TCommandEnabler& ce)
1695{
1697 ce.Enable(doc && (doc->IsDirty() || (Mode & dmSaveEnable)));
1698}
1699
1700//
1701//
1702//
1703void
1705{
1707 if (doc) {
1708 if (!doc->GetDocPath()) {
1709 CmFileSaveAs();
1710 return;
1711 }
1712 if (!(Mode & dmSaveEnable) && !doc->IsDirty()) {
1714 return;
1715 }
1716 doc->Commit(); // No force of write here since is just to same file
1717 }
1718}
1719
1720//
1721/// Command enabler for CmFileRevert.
1722//
1723void
1724TDocManager::CeFileRevert(TCommandEnabler& ce)
1725{
1727 ce.Enable(doc && doc->IsDirty() && doc->GetDocPath());
1728}
1729
1730//
1731//
1732//
1733void
1735{
1737 if (doc && doc->GetDocPath()) {
1738 if (!doc->IsDirty()) {
1740 return;
1741 }
1742 doc->Revert();
1743 }
1744}
1745
1746//
1747/// Command enabler for CmViewCreate.
1748//
1749void
1750TDocManager::CeViewCreate(TCommandEnabler& hndlr)
1751{
1753 hndlr.Enable(doc != nullptr);
1754}
1755
1756//
1757/// Calls CreateAnyView(*doc) where doc is the current document.
1758//
1759void
1761{
1763 if (doc)
1765}
1766
1767
1769
1770#if OWL_PERSISTENT_STREAMS
1771
1772//
1773//
1774//
1775void*
1776TDocManager::Streamer::Read(ipstream& is, uint32 /*version*/) const
1777{
1778 TDocManager* o = GetObject();
1779
1780 TDocTemplate* tpl = o->TemplateList;
1781 for (;;) {
1782 int isStatic;
1783
1784 is >> isStatic;
1785 if (isStatic == -1)
1786 break;
1787
1788 if (isStatic) {
1789 if (tpl) { // if static templates available
1790 is >> *tpl; // update static template data
1791 tpl = o->GetNextTemplate(tpl);
1792 }
1793 else { // have run out of static templates
1794 char tbuf[sizeof(TDocTemplate)]; // sink for unused template data
1795 memset(tbuf, 0, sizeof tbuf); // force static flag off
1796 is >> *(TDocTemplate*)tbuf;
1797 }
1798 }
1799 else { // if dynamic template, object will be constructed
1800 TModule* module;
1801 is >> module;
1802 is >> tpl;
1803 tpl->SetModule(module);
1804 o->AttachTemplate(*tpl);
1805 }
1806 }
1807
1808 int count;
1809 is >> count; // document count
1810 while (count--) {
1811 TDocument* doc;
1812 is >> doc;
1813 doc->SetDocManager(*o); // inserts properly into list
1814 }
1815
1816 // Get application, & post ourselves a wakeup message to finish things up
1817 // once all windows have been created, etc.
1818 //
1819 o->Application = OWLGetAppDictionary().GetApplication(0);
1820 TWindow* win = o->Application->GetMainWindow();
1821 if (win && win->GetHandle())
1822 win->PostMessage(WM_OWLWAKEUP);
1823
1824 return o;
1825}
1826
1827//
1828//
1829//
1830void
1831TDocManager::Streamer::Write(opstream& os) const
1832{
1833 TDocManager* o = GetObject();
1834
1835 TDocTemplate* tpl = 0;
1836 while ((tpl = o->GetNextTemplate(tpl)) != 0) {
1837 int flag = tpl->IsStatic();
1838 os << flag;
1839 if (flag) {
1840 os << *tpl; // write reference to static template
1841 }
1842 else {
1843 os << tpl->GetModule(); // write template's module pointer first
1844 os << tpl; // write pointer to static template
1845 }
1846 }
1847 os << -1; // template list terminator
1848
1849 TDocument* doc = 0;
1850 int count;
1851 for (count = 0; (doc = o->DocList.Next(doc))!=0; count++) ;
1852 os << count;
1853
1854 // Must write documents out in order created, i.e. from end of list forward
1855 //
1856 while (count) {
1857 int i = count--;
1858 for (doc = 0; i--; doc = o->DocList.Next(doc)) ;
1859 os << doc;
1860 }
1861}
1862
1863#endif
1864
1865
1866} // OWL namespace
1867
Definition of class TAppDictionary.
#define CHECK(condition)
Definition checks.h:239
#define WARNX(group, condition, level, message)
Definition checks.h:277
#define PRECONDITION(condition)
Definition checks.h:227
#define CHECKX(condition, message)
Definition checks.h:245
#define TRACEX(group, level, message)
Definition checks.h:263
#define DIAG_DEFINE_GROUP_INIT(f, g, e, l)
Definition checks.h:429
TApplication * GetApplication(uint pid=0)
Looks up and returns the application associated with a given process ID.
Definition appdict.cpp:192
Derived from TModule and TMsgThread and virtually derived from TEventHandler, TApplication acts as an...
Definition applicat.h:141
TFrameWindow * GetMainWindow()
Return the current main window.
Definition applicat.h:592
Base class for an extensible interface for auto enabling/disabling of commands (menu items,...
Definition window.h:209
Typically used to obtain information from a user, a dialog box is a window inside of which other cont...
Definition dialog.h:85
auto Execute() -> int override
Creates and executes a modal dialog box interface element associated with the TDialog object.
Definition dialog.cpp:595
virtual INT_PTR DialogFunction(TMsgId, TParam1, TParam2)
Override this to process messages within the dialog function.
Definition dialog.cpp:353
TDocManager creates a document manager object that manages the list of current documents and register...
Definition docmanag.h:100
virtual void ViewCreate()
Calls CreateAnyView(*doc) where doc is the current document.
void CmFileSaveAs()
Public to allow direct invocation from app; for backward compatibility.
Definition docmanag.h:510
TView * CreateView(TDocument &doc, TDocTemplate *tpl=nullptr)
Create a view on a given document using the given tempalte, or document's template if none given,...
Definition docmanag.cpp:816
bool EvCanClose()
Checks to see if all child documents can be closed before closing the current document.
virtual void PostEvent(int id, TDocument &doc)
changed doc status
virtual void FileSave()
virtual uint PostDocError(TDocument &doc, uint sid, uint choice=MB_OK)
Displays a message box with the error message passed as a string resource ID in sid.
int GetTemplateCount(TDocument *ofDocType=nullptr, TView *ofViewType=nullptr)
Count the number of templates, filtering by document type and/or view type as indicated.
Definition docmanag.cpp:272
virtual int SelectViewType(TDocTemplate **tpllist, int tplcount)
Given a list of templates, lets the user select a view name for a new view from a list of view names.
static bool MatchFilter(LPCTSTR path, LPCTSTR filters)
Helper function used by 'MatchTemplate'.
void EvWakeUp()
Used only after streaming in the doc manager, EvWakeUp allows for the windows to be created after the...
virtual bool FlushDoc(TDocument &doc)
Method invoked when specified document is about to be closed.
Definition docmanag.cpp:914
bool IsFlagSet(int flag) const
Returns true if the specified flag is currently enabled by the DocManager or false otherwise.
Definition docmanag.h:399
bool NotifyAllDocs(int event, long item, TView *exclude)
Notifies the views of all documents and the views of any child documents of a change.
virtual int GetNewTemplates(TDocTemplate **tplList, int size, bool newDoc)
Build a list of templates for creating new documents or opening existing documents.
Definition docmanag.cpp:304
virtual void UpdateFileMenu(TMenu &menubar)
Update the specified menu bar by removing the current '&File' popup menu [assumed to be the first pop...
virtual void FileSaveAs()
SelectAnySave() is called to get a template.
virtual ~TDocManager()
Destruct this DocManager.
Definition docmanag.cpp:233
virtual void FileOpen()
virtual TView * CreateAnyView(TDocument &doc, long flags=0)
Creates a document view based on the directory path and specified template.
Definition docmanag.cpp:771
int UntitledIndex
Index of last untitled document.
Definition docmanag.h:212
TApplication * GetApplication() const
Returns the TApplication* object associated with this DocManager.
Definition docmanag.h:390
TDocument * InitDoc(TDocument *doc, LPCTSTR path, long flags)
Initializes the document, using the given path for the document and the given document flags.
Definition docmanag.cpp:665
virtual TDocument * CreateDoc(TDocTemplate *tpl, LPCTSTR path, TDocument *parent=nullptr, long flags=0)
CreateDoc creates a document based on the directory path and the specified template.
Definition docmanag.cpp:603
virtual int GetTemplateDescription(TDocTemplate **tpllist, int tplcount, tchar *buff=nullptr, int size=0)
Build up a long string containing the template descriptions and file filters for every template in th...
Definition docmanag.cpp:448
TDocument * FindDocument(LPCTSTR path)
0 if not found
void UnRefTemplate(TDocTemplate &)
drop template ref
Definition docmanag.h:381
virtual bool CreatingDoc(TDocTemplate *tpl)
Overrideable method invoked just before the DocumentManager creates a new document.
virtual int GetSaveTemplates(TDocTemplate **tplList, int size, TDocument &doc, bool sameDoc)
Build a list of templates for saving documents.
Definition docmanag.cpp:342
void Init(int mode, TApplication *app, TDocTemplate *&templateHead)
Helper routine used by constructor(s)
Definition docmanag.cpp:209
virtual TDocument * CreateAnyDoc(LPCTSTR path, long flags=0)
Creates a document based on the directory path and the specified template.
Definition docmanag.cpp:521
static bool IsAMatch(LPCTSTR path, LPCTSTR fltr)
Helper function used by 'MatchTemplate'.
virtual void FileNew()
bool SelectSave(TDocument &doc)
Displays FileSave dialog prompting the user to select a file name for savinng the document.
Definition docmanag.cpp:840
void EvPreProcessMenu(HMENU hMenu)
Preprocess the app frame's menu to replace the file menu with one managed by this docmanager.
virtual TDocument * GetCurrentDoc()
Return doc with focus, else 0.
void DeleteTemplate(TDocTemplate &)
remove from list
virtual void FileClose()
If the document can be closed it is closed.
virtual void FileRevert()
virtual TDocTemplate * MatchTemplate(LPCTSTR path)
Returns the first registered template whose pattern matches the given file name.
virtual TDocTemplate * SelectAnySave(TDocument &doc, bool samedoc=true)
Select a new docpath for a document from the registered templates supporting the doc.
Definition docmanag.cpp:862
virtual int SelectDocPath(TDocTemplate **tpllist, int tplcount, tchar *path, int buflen, long flags, bool save=false, TDocument *doc=nullptr)
Given a list of templates, prompts the user to select one of the templates to use for the file to be ...
virtual int SelectDocType(TDocTemplate **tpllist, int tplcount)
Given a list of templates, lets the user select a document type from a list of document templates.
virtual int GetViewTemplates(TDocTemplate **tplList, int size, TDocument &doc)
Build a list of templates for creating views.
Definition docmanag.cpp:383
void AttachTemplate(TDocTemplate &)
append to list
TDocTemplate is an abstract base class that contains document template functionality.
Definition doctpl.h:54
TDocument * Next(const TDocument *doc)
If the doc parameter is 0, Next returns the first document in the list of documents.
Definition document.cpp:819
An abstract base class, TDocument is the base class for all document objects and serves as an interfa...
Definition docview.h:187
TDvFileOpenDialog encapsulates the FileOpen dialog used by the DocView manager.
Definition docmanag.h:323
TDvFileOpenDialog(TWindow *parent, TDvOpenSaveData &data, LPCTSTR title=nullptr, TModule *module=nullptr)
Constructor of object encapsulating the Open File dialog used by the DocManager.
Definition docmanag.cpp:112
virtual INT_PTR DialogFunction(TMsgId, TParam1, TParam2)
Overriden virtual function of TFileOpenDialog to allow us to detect when the user switches between fi...
Definition docmanag.cpp:125
TDvFileSaveDialog encapsulates the FileSave dialog used by the DocView manager.
Definition docmanag.h:339
TDvFileSaveDialog(TWindow *parent, TDvOpenSaveData &data, LPCTSTR title=nullptr, TModule *module=nullptr)
Constructor of object encapsulating the FileSave dialog used by the DocManager.
Definition docmanag.cpp:143
virtual INT_PTR DialogFunction(TMsgId, TParam1, TParam2)
Overriden virtual function of TFileOpenDialog to allow us to detect when the user switches between fi...
Definition docmanag.cpp:156
TDvOpenSaveData encapsulates the information used to initialized the Open or Save As dialog box by Ob...
Definition docmanag.h:278
TDvOpenSaveData(uint32 flags, tchar *filter, tchar *initialDir, tchar *defExt, int filterIndex, TDocTemplate **tmplList, int tmplCount)
Constructor of class representing the data to be displayed in the Open/Save dialogs used by the DocMa...
Definition docmanag.cpp:58
TDvOpenSaveDataOwner is a mixin class used by the DocView encapsulation of the FileOpen and FileSave ...
Definition docmanag.h:304
TDvOpenSaveDataOwner(TDvOpenSaveData &data)
Constructor of mixin.
Definition docmanag.cpp:75
The TFileName class constructs filenames.
Definition filename.h:37
@ Ext
Extension.
Definition filename.h:130
@ File
Filename part without the extension.
Definition filename.h:129
TFileOpenDialog is a modal dialog box that lets you specify the name of a file to open.
Definition opensave.h:264
TFileSaveDialog is a modal dialog box that lets you enter the name of a file to save.
Definition opensave.h:311
virtual HWND GetCommandTarget()
Locates and returns the child window that is the target of the command and command enable messages.
Definition framewin.cpp:328
The TMenu class encapsulates window menus.
Definition menu.h:77
ObjectWindows dynamic-link libraries (DLLs) construct an instance of TModule, which acts as an object...
Definition module.h:75
bool PumpWaitingMessages()
The inner message loop.
Definition msgthred.cpp:123
TOpenSaveDialog is the base class for modal dialogs that let you open and save a file under a specifi...
Definition opensave.h:34
OPENFILENAME & GetOFN()
Returns the OPENFILENAME structure.
Definition opensave.h:384
The PickList allows selection of an item from a popup list.
Definition picklist.h:37
Abstract base class for view access from document.
Definition docview.h:397
TWindow, derived from TEventHandler and TStreamableBase, provides window-specific behavior and encaps...
Definition window.h:414
int MessageBox(LPCTSTR text, LPCTSTR caption=0, uint flags=MB_OK) const
Creates and displays a message box that contains a message (text), a title (caption),...
Definition window.cpp:4284
TResult SendMessage(TMsgId, TParam1=0, TParam2=0) const
Sends a message (msg) to a specified window or windows.
Definition window.cpp:3288
HWND GetHandle() const
Returns the handle of the window.
Definition window.h:2020
ipstream, a specialized input stream derivative of pstream, is the base class for reading (extracting...
Definition objstrm.h:391
#define _tcscat
Definition cygwin.h:83
#define _tcscpy
Definition cygwin.h:79
#define _tcsncpy
Definition cygwin.h:80
#define _stprintf
Definition cygwin.h:88
#define _MAX_PATH
Definition cygwin.h:97
#define _tcsncmp
Definition cygwin.h:78
#define _totupper
Definition cygwin.h:73
#define _tcslen
Definition cygwin.h:74
#define _tcsicmp
Definition cygwin.h:76
#define _T(x)
Definition cygwin.h:51
#define _tcschr
Definition cygwin.h:85
#define _tcsrchr
Definition cygwin.h:86
#define WM_OWLVIEW
Definition dispatch.h:4106
#define WM_OWLWAKEUP
Definition dispatch.h:4113
#define WM_OWLDOCUMENT
Definition dispatch.h:4105
#define IDC_FILETYPES
Definition docmanag.cpp:37
Definition of class TDocManager.
#define DEFINE_RESPONSE_TABLE(cls)
Macro to define a response table for a class with no base response tables.
Definition eventhan.h:479
#define IMPLEMENT_STREAMABLE(cls)
Definition objstrm.h:1724
const uint dtNewDoc
create new document, no path used
Definition doctpl.h:218
const uint dtNoReadOnly
Definition doctpl.h:240
const uint dtNoAutoView
no automatic create of default view
Definition doctpl.h:220
const uint dtAutoOpen
open document upon creation
Definition doctpl.h:222
const uint dtForbidNew
forbids creating new document
Definition doctpl.h:229
const uint dmNoRevert
Disable FileRevert menu item.
Definition docmanag.h:36
const uint dmSDI
Does not support multiple open documents.
Definition docmanag.h:32
const uint dmMenu
Set IDs for file menu.
Definition docmanag.h:34
const uint dtHidden
hide template from user selection
Definition doctpl.h:224
const uint dmSaveEnable
Enable FileSave even if doc is unmodified.
Definition docmanag.h:35
const uint dtSelected
indicates template last selected
Definition doctpl.h:225
const uint dtSingleView
only a single view per document
Definition doctpl.h:221
const uint dtReadOnly
Definition doctpl.h:234
@ dnRename
Document has been renamed.
Definition docmanag.h:54
@ dnCreate
New document or view has been created.
Definition docmanag.h:52
@ ofRead
ios::in, open for reading
Definition docview.h:63
@ ofReadWrite
Definition docview.h:65
int LoadString(uint id, TCHAR *buf, int maxChars) const
Loads a string resource identified by id into the buffer pointed to by buff.
Definition module.cpp:586
HMENU LoadMenu(TResId id) const
Wrapper for the Windows API.
Definition module.cpp:854
UINT CharSize(const TCHAR *s)
Return the number of bytes of the first character of the passed string.
Definition memory.h:56
#define nstrnewdup
Definition memory.h:403
Object Windows Library (OWLNext Core)
Definition animctrl.h:22
UINT TMsgId
Message ID type.
Definition dispatch.h:53
EV_WM_WAKEUP
Definition docmanag.cpp:173
TDocTemplate * TDocTemplatePtr
Definition docmanag.cpp:43
unsigned long uint32
Definition number.h:34
EV_WM_PREPROCMENU
Definition docmanag.cpp:172
char tchar
Definition defs.h:77
LPARAM TParam2
Second parameter type.
Definition dispatch.h:55
WPARAM TParam1
First parameter type.
Definition dispatch.h:54
TAppDictionary & OWLGetAppDictionary()
Global exported TAppDictionary in Owl.
Definition appdict.cpp:35
OWL_DIAGINFO
Definition animctrl.cpp:14
END_RESPONSE_TABLE
Definition button.cpp:26
std::string tstring
Definition defs.h:79
EV_WM_CANCLOSE
Definition docmanag.cpp:171
unsigned int uint
Definition number.h:25
TModule & GetGlobalModule()
Definition global.cpp:48
Definition of TOpenSave abstract, TFileOpen, TFileSave common Dialog classes.
#define OWL_INI
Definition defs.h:170
#define CONST_CAST(targetType, object)
Definition defs.h:273
#define COUNTOF(s)
Array element count Important: Only use this with an argument of array type.
Definition defs.h:376
Definition of classes TPickListPopup & TPickListDialog.
Definition of class TString, a flexible universal string envelope class.
Definition of TSystem, a system information provider class.
#define EV_COMMAND_ENABLE(id, method)
Response table entry for enabling a command.
Definition windowev.h:193
#define EV_COMMAND(id, method)
Response table entry for a menu/accelerator/push button message.
Definition windowev.h:171