]> git.saurik.com Git - wxWidgets.git/blame - src/common/docview.cpp
I had to remove (Robin's) makefile creation clause
[wxWidgets.git] / src / common / docview.cpp
CommitLineData
c801d85f
KB
1/////////////////////////////////////////////////////////////////////////////
2// Name: docview.cpp
3// Purpose: Document/view classes
4// Author: Julian Smart
5// Modified by:
6// Created: 01/02/97
7// RCS-ID: $Id$
8// Copyright: (c) Julian Smart and Markus Holzem
3f4a0c5b 9// Licence: wxWindows licence
c801d85f
KB
10/////////////////////////////////////////////////////////////////////////////
11
0fb67cd1
VZ
12// ============================================================================
13// declarations
14// ============================================================================
15
16// ----------------------------------------------------------------------------
17// headers
18// ----------------------------------------------------------------------------
19
c801d85f 20#ifdef __GNUG__
0fb67cd1 21 #pragma implementation "docview.h"
c801d85f
KB
22#endif
23
24// For compilers that support precompilation, includes "wx.h".
25#include "wx/wxprec.h"
26
27#ifdef __BORLANDC__
2df7be7f 28 #pragma hdrstop
c801d85f
KB
29#endif
30
47d67540 31#if wxUSE_DOC_VIEW_ARCHITECTURE
c801d85f
KB
32
33#ifndef WX_PRECOMP
0fb67cd1
VZ
34 #include "wx/string.h"
35 #include "wx/utils.h"
36 #include "wx/app.h"
37 #include "wx/dc.h"
d0bdc3ca 38 #include "wx/dialog.h"
0fb67cd1
VZ
39 #include "wx/menu.h"
40 #include "wx/list.h"
41 #include "wx/filedlg.h"
6de2f8b9 42 #include "wx/intl.h"
f7bd2698
JS
43#endif
44
45#ifdef __WXGTK__
0fb67cd1 46 #include "wx/mdi.h"
c801d85f
KB
47#endif
48
ce4169a4
RR
49#if wxUSE_PRINTING_ARCHITECTURE
50 #include "wx/prntbase.h"
51 #include "wx/printdlg.h"
52#endif
53
c801d85f
KB
54#include "wx/msgdlg.h"
55#include "wx/choicdlg.h"
56#include "wx/docview.h"
7f555861 57#include "wx/confbase.h"
c801d85f 58
c801d85f
KB
59#include <stdio.h>
60#include <string.h>
61
a533f5c1
RR
62#if wxUSE_STD_IOSTREAM
63 #include "wx/ioswrap.h"
64 #if wxUSE_IOSTREAMH
3f4a0c5b 65 #include <fstream.h>
a533f5c1 66 #else
3f4a0c5b 67 #include <fstream>
a533f5c1
RR
68 #endif
69#else
70 #include "wx/wfstream.h"
c801d85f
KB
71#endif
72
0fb67cd1
VZ
73// ----------------------------------------------------------------------------
74// wxWindows macros
75// ----------------------------------------------------------------------------
76
c801d85f 77#if !USE_SHARED_LIBRARY
0fb67cd1
VZ
78 IMPLEMENT_ABSTRACT_CLASS(wxDocument, wxEvtHandler)
79 IMPLEMENT_ABSTRACT_CLASS(wxView, wxEvtHandler)
80 IMPLEMENT_ABSTRACT_CLASS(wxDocTemplate, wxObject)
81 IMPLEMENT_DYNAMIC_CLASS(wxDocManager, wxEvtHandler)
82 IMPLEMENT_CLASS(wxDocChildFrame, wxFrame)
83 IMPLEMENT_CLASS(wxDocParentFrame, wxFrame)
84
85 #if wxUSE_PRINTING_ARCHITECTURE
86 IMPLEMENT_DYNAMIC_CLASS(wxDocPrintout, wxPrintout)
87 #endif
88
89 IMPLEMENT_CLASS(wxCommand, wxObject)
90 IMPLEMENT_DYNAMIC_CLASS(wxCommandProcessor, wxObject)
91 IMPLEMENT_DYNAMIC_CLASS(wxFileHistory, wxObject)
c801d85f
KB
92#endif
93
0fb67cd1
VZ
94// ----------------------------------------------------------------------------
95// function prototypes
96// ----------------------------------------------------------------------------
97
50920146 98static inline wxString FindExtension(const wxChar *path);
0fb67cd1
VZ
99
100// ============================================================================
101// implementation
102// ============================================================================
103
104// ----------------------------------------------------------------------------
105// local functions
106// ----------------------------------------------------------------------------
107
50920146 108static wxString FindExtension(const wxChar *path)
0fb67cd1
VZ
109{
110 wxString ext;
111 wxSplitPath(path, NULL, NULL, &ext);
112
113 // VZ: extensions are considered not case sensitive - is this really a good
114 // idea?
115 return ext.MakeLower();
116}
117
118// ----------------------------------------------------------------------------
119// Definition of wxDocument
120// ----------------------------------------------------------------------------
c801d85f
KB
121
122wxDocument::wxDocument(wxDocument *parent)
123{
0fb67cd1
VZ
124 m_documentModified = FALSE;
125 m_documentParent = parent;
126 m_documentTemplate = (wxDocTemplate *) NULL;
127 m_savedYet = FALSE;
c801d85f
KB
128}
129
0fb67cd1 130bool wxDocument::DeleteContents()
c801d85f 131{
0fb67cd1 132 return TRUE;
c801d85f
KB
133}
134
0fb67cd1 135wxDocument::~wxDocument()
c801d85f 136{
0fb67cd1 137 DeleteContents();
c801d85f 138
0fb67cd1
VZ
139 if (m_commandProcessor)
140 delete m_commandProcessor;
c801d85f 141
0fb67cd1 142 GetDocumentManager()->RemoveDocument(this);
c801d85f 143
0fb67cd1
VZ
144 // Not safe to do here, since it'll invoke virtual view functions
145 // expecting to see valid derived objects: and by the time we get here,
146 // we've called destructors higher up.
147 //DeleteAllViews();
c801d85f 148}
0fb67cd1
VZ
149
150bool wxDocument::Close()
c801d85f 151{
0fb67cd1
VZ
152 if (OnSaveModified())
153 return OnCloseDocument();
154 else
155 return FALSE;
c801d85f 156}
0fb67cd1
VZ
157
158bool wxDocument::OnCloseDocument()
c801d85f 159{
0fb67cd1
VZ
160 DeleteContents();
161 Modify(FALSE);
162 return TRUE;
c801d85f
KB
163}
164
0fb67cd1
VZ
165// Note that this implicitly deletes the document when the last view is
166// deleted.
167bool wxDocument::DeleteAllViews()
c801d85f 168{
0fb67cd1
VZ
169 wxNode *node = m_documentViews.First();
170 while (node)
171 {
172 wxView *view = (wxView *)node->Data();
173 if (!view->Close())
174 return FALSE;
c801d85f 175
0fb67cd1
VZ
176 wxNode *next = node->Next();
177
178 delete view; // Deletes node implicitly
179 node = next;
180 }
181 return TRUE;
c801d85f
KB
182}
183
6de2f8b9 184wxView *wxDocument::GetFirstView() const
c801d85f 185{
0fb67cd1
VZ
186 if (m_documentViews.Number() == 0)
187 return (wxView *) NULL;
188 return (wxView *)m_documentViews.First()->Data();
c801d85f
KB
189}
190
6de2f8b9 191wxDocManager *wxDocument::GetDocumentManager() const
c801d85f 192{
0fb67cd1 193 return m_documentTemplate->GetDocumentManager();
c801d85f
KB
194}
195
0fb67cd1 196bool wxDocument::OnNewDocument()
c801d85f 197{
0fb67cd1
VZ
198 if (!OnSaveModified())
199 return FALSE;
c801d85f 200
0fb67cd1
VZ
201 if (OnCloseDocument()==FALSE) return FALSE;
202 DeleteContents();
203 Modify(FALSE);
204 SetDocumentSaved(FALSE);
c801d85f 205
0fb67cd1
VZ
206 wxString name;
207 GetDocumentManager()->MakeDefaultName(name);
208 SetTitle(name);
209 SetFilename(name, TRUE);
210
211 return TRUE;
c801d85f
KB
212}
213
0fb67cd1 214bool wxDocument::Save()
c801d85f 215{
0fb67cd1 216 bool ret = FALSE;
c801d85f 217
0fb67cd1 218 if (!IsModified()) return TRUE;
d0bdc3ca 219 if (m_documentFile == _T("") || !m_savedYet)
0fb67cd1
VZ
220 ret = SaveAs();
221 else
222 ret = OnSaveDocument(m_documentFile);
223 if ( ret )
224 SetDocumentSaved(TRUE);
225 return ret;
c801d85f 226}
0fb67cd1
VZ
227
228bool wxDocument::SaveAs()
c801d85f 229{
ba681060
VZ
230 wxDocTemplate *docTemplate = GetDocumentTemplate();
231 if (!docTemplate)
232 return FALSE;
0fb67cd1 233
ba681060 234 wxString tmp = wxFileSelector(_("Save as"),
0fb67cd1
VZ
235 docTemplate->GetDirectory(),
236 GetFilename(),
237 docTemplate->GetDefaultExtension(),
238 docTemplate->GetFileFilter(),
239 wxSAVE | wxOVERWRITE_PROMPT,
240 GetDocumentWindow());
241
ba681060
VZ
242 if (tmp.IsEmpty())
243 return FALSE;
244
2bb0cd28 245 wxString fileName(tmp);
88ac883a 246 wxString path, name, ext;
2bb0cd28
JS
247 wxSplitPath(fileName, & path, & name, & ext);
248
d0bdc3ca 249 if (ext.IsEmpty() || ext == _T(""))
2bb0cd28
JS
250 {
251 fileName += ".";
252 fileName += docTemplate->GetDefaultExtension();
253 }
254
255 SetFilename(fileName);
256 SetTitle(wxFileNameFromPath(fileName));
0fb67cd1 257
2bb0cd28 258 GetDocumentManager()->AddFileToHistory(fileName);
c801d85f
KB
259
260 // Notify the views that the filename has changed
261 wxNode *node = m_documentViews.First();
262 while (node)
263 {
0fb67cd1
VZ
264 wxView *view = (wxView *)node->Data();
265 view->OnChangeFilename();
266 node = node->Next();
c801d85f 267 }
ba681060
VZ
268
269 return OnSaveDocument(m_documentFile);
c801d85f 270}
0fb67cd1 271
c801d85f
KB
272bool wxDocument::OnSaveDocument(const wxString& file)
273{
0fb67cd1
VZ
274 if ( !file )
275 return FALSE;
c801d85f 276
0fb67cd1 277 wxString msgTitle;
d0bdc3ca 278 if (wxTheApp->GetAppName() != _T(""))
0fb67cd1
VZ
279 msgTitle = wxTheApp->GetAppName();
280 else
281 msgTitle = wxString(_("File error"));
282
a533f5c1 283#if wxUSE_STD_IOSTREAM
11aab0d0 284 ofstream store(FNSTRINGCAST file.fn_str());
0fb67cd1 285 if (store.fail() || store.bad())
a533f5c1 286#else
11aab0d0 287 wxFileOutputStream store(FNSTRINGCAST file.fn_str());
56d7679d 288 if (store.LastError() != 0)
a533f5c1 289#endif
0fb67cd1
VZ
290 {
291 (void)wxMessageBox(_("Sorry, could not open this file for saving."), msgTitle, wxOK | wxICON_EXCLAMATION,
292 GetDocumentWindow());
293 // Saving error
294 return FALSE;
295 }
296 if (SaveObject(store)==FALSE)
297 {
298 (void)wxMessageBox(_("Sorry, could not save this file."), msgTitle, wxOK | wxICON_EXCLAMATION,
299 GetDocumentWindow());
300 // Saving error
301 return FALSE;
302 }
303 Modify(FALSE);
304 SetFilename(file);
305 return TRUE;
c801d85f 306}
0fb67cd1 307
c801d85f
KB
308bool wxDocument::OnOpenDocument(const wxString& file)
309{
0fb67cd1
VZ
310 if (!OnSaveModified())
311 return FALSE;
c801d85f 312
0fb67cd1 313 wxString msgTitle;
d0bdc3ca 314 if (wxTheApp->GetAppName() != _T(""))
0fb67cd1
VZ
315 msgTitle = wxTheApp->GetAppName();
316 else
317 msgTitle = wxString(_("File error"));
318
a533f5c1 319#if wxUSE_STD_IOSTREAM
11aab0d0 320 ifstream store(FNSTRINGCAST file.fn_str());
0fb67cd1 321 if (store.fail() || store.bad())
a533f5c1 322#else
11aab0d0 323 wxFileInputStream store(FNSTRINGCAST file.fn_str());
56d7679d 324 if (store.LastError() != 0)
a533f5c1 325#endif
0fb67cd1
VZ
326 {
327 (void)wxMessageBox(_("Sorry, could not open this file."), msgTitle, wxOK|wxICON_EXCLAMATION,
328 GetDocumentWindow());
329 return FALSE;
330 }
331 if (LoadObject(store)==FALSE)
332 {
333 (void)wxMessageBox(_("Sorry, could not open this file."), msgTitle, wxOK|wxICON_EXCLAMATION,
334 GetDocumentWindow());
335 return FALSE;
336 }
337 SetFilename(file, TRUE);
338 Modify(FALSE);
339 m_savedYet = TRUE;
340
341 UpdateAllViews();
c801d85f 342
0fb67cd1 343 return TRUE;
c801d85f 344}
0fb67cd1 345
a533f5c1 346#if wxUSE_STD_IOSTREAM
c801d85f
KB
347istream& wxDocument::LoadObject(istream& stream)
348{
0fb67cd1 349 return stream;
c801d85f
KB
350}
351
352ostream& wxDocument::SaveObject(ostream& stream)
353{
0fb67cd1 354 return stream;
c801d85f 355}
a533f5c1
RR
356#else
357bool wxDocument::LoadObject(wxInputStream& stream)
358{
359 return TRUE;
360}
361
362bool wxDocument::SaveObject(wxOutputStream& stream)
363{
364 return TRUE;
365}
366#endif
c801d85f 367
0fb67cd1 368bool wxDocument::Revert()
c801d85f 369{
0fb67cd1 370 return FALSE;
c801d85f
KB
371}
372
373
374// Get title, or filename if no title, else unnamed
375bool wxDocument::GetPrintableName(wxString& buf) const
376{
d0bdc3ca 377 if (m_documentTitle != _T(""))
0fb67cd1
VZ
378 {
379 buf = m_documentTitle;
380 return TRUE;
381 }
d0bdc3ca 382 else if (m_documentFile != _T(""))
0fb67cd1
VZ
383 {
384 buf = wxFileNameFromPath(m_documentFile);
385 return TRUE;
386 }
387 else
388 {
389 buf = _("unnamed");
390 return TRUE;
391 }
c801d85f
KB
392}
393
6de2f8b9 394wxWindow *wxDocument::GetDocumentWindow() const
c801d85f 395{
0fb67cd1
VZ
396 wxView *view = GetFirstView();
397 if (view)
398 return view->GetFrame();
399 else
400 return wxTheApp->GetTopWindow();
c801d85f
KB
401}
402
0fb67cd1 403wxCommandProcessor *wxDocument::OnCreateCommandProcessor()
c801d85f 404{
0fb67cd1 405 return new wxCommandProcessor;
c801d85f
KB
406}
407
408// TRUE if safe to close
0fb67cd1 409bool wxDocument::OnSaveModified()
c801d85f 410{
0fb67cd1 411 if (IsModified())
c801d85f 412 {
0fb67cd1
VZ
413 wxString title;
414 GetPrintableName(title);
415
416 wxString msgTitle;
d0bdc3ca 417 if (wxTheApp->GetAppName() != _T(""))
0fb67cd1
VZ
418 msgTitle = wxTheApp->GetAppName();
419 else
420 msgTitle = wxString(_("Warning"));
421
422 wxString prompt;
423 prompt.Printf(_("Do you want to save changes to document %s?"),
50920146 424 (const wxChar *)title);
0fb67cd1
VZ
425 int res = wxMessageBox(prompt, msgTitle,
426 wxYES_NO|wxCANCEL|wxICON_QUESTION,
427 GetDocumentWindow());
428 if (res == wxNO)
429 {
430 Modify(FALSE);
431 return TRUE;
432 }
433 else if (res == wxYES)
434 return Save();
435 else if (res == wxCANCEL)
436 return FALSE;
c801d85f 437 }
0fb67cd1 438 return TRUE;
c801d85f
KB
439}
440
441bool wxDocument::Draw(wxDC& WXUNUSED(context))
442{
0fb67cd1 443 return TRUE;
c801d85f
KB
444}
445
446bool wxDocument::AddView(wxView *view)
447{
0fb67cd1
VZ
448 if (!m_documentViews.Member(view))
449 {
450 m_documentViews.Append(view);
451 OnChangedViewList();
452 }
453 return TRUE;
c801d85f
KB
454}
455
456bool wxDocument::RemoveView(wxView *view)
457{
0fb67cd1
VZ
458 (void)m_documentViews.DeleteObject(view);
459 OnChangedViewList();
460 return TRUE;
c801d85f
KB
461}
462
463bool wxDocument::OnCreate(const wxString& WXUNUSED(path), long flags)
464{
0fb67cd1
VZ
465 if (GetDocumentTemplate()->CreateView(this, flags))
466 return TRUE;
467 else
468 return FALSE;
c801d85f
KB
469}
470
471// Called after a view is added or removed.
472// The default implementation deletes the document if
473// there are no more views.
0fb67cd1 474void wxDocument::OnChangedViewList()
c801d85f 475{
0fb67cd1 476 if (m_documentViews.Number() == 0)
c801d85f 477 {
0fb67cd1
VZ
478 if (OnSaveModified())
479 {
480 delete this;
481 }
c801d85f 482 }
c801d85f
KB
483}
484
485void wxDocument::UpdateAllViews(wxView *sender, wxObject *hint)
486{
0fb67cd1
VZ
487 wxNode *node = m_documentViews.First();
488 while (node)
489 {
490 wxView *view = (wxView *)node->Data();
491 view->OnUpdate(sender, hint);
492 node = node->Next();
493 }
c801d85f
KB
494}
495
496void wxDocument::SetFilename(const wxString& filename, bool notifyViews)
497{
0fb67cd1
VZ
498 m_documentFile = filename;
499 if ( notifyViews )
c801d85f 500 {
0fb67cd1
VZ
501 // Notify the views that the filename has changed
502 wxNode *node = m_documentViews.First();
503 while (node)
504 {
505 wxView *view = (wxView *)node->Data();
506 view->OnChangeFilename();
507 node = node->Next();
508 }
c801d85f 509 }
c801d85f
KB
510}
511
0fb67cd1
VZ
512// ----------------------------------------------------------------------------
513// Document view
514// ----------------------------------------------------------------------------
c801d85f 515
dbdb39b2 516wxView::wxView()
c801d85f 517{
0fb67cd1
VZ
518 // SetDocument(doc);
519 m_viewDocument = (wxDocument*) NULL;
520
521 m_viewTypeName = "";
522 m_viewFrame = (wxFrame *) NULL;
c801d85f
KB
523}
524
0fb67cd1 525wxView::~wxView()
c801d85f 526{
0fb67cd1
VZ
527 GetDocumentManager()->ActivateView(this, FALSE, TRUE);
528 m_viewDocument->RemoveView(this);
c801d85f
KB
529}
530
531// Extend event processing to search the document's event table
532bool wxView::ProcessEvent(wxEvent& event)
533{
0fb67cd1
VZ
534 if ( !GetDocument() || !GetDocument()->ProcessEvent(event) )
535 return wxEvtHandler::ProcessEvent(event);
536 else
537 return TRUE;
c801d85f
KB
538}
539
540void wxView::OnActivateView(bool WXUNUSED(activate), wxView *WXUNUSED(activeView), wxView *WXUNUSED(deactiveView))
541{
542}
543
544void wxView::OnPrint(wxDC *dc, wxObject *WXUNUSED(info))
545{
0fb67cd1 546 OnDraw(dc);
c801d85f
KB
547}
548
549void wxView::OnUpdate(wxView *WXUNUSED(sender), wxObject *WXUNUSED(hint))
550{
551}
552
0fb67cd1 553void wxView::OnChangeFilename()
c801d85f 554{
0fb67cd1
VZ
555 if (GetFrame() && GetDocument())
556 {
557 wxString name;
558 GetDocument()->GetPrintableName(name);
c801d85f 559
0fb67cd1
VZ
560 GetFrame()->SetTitle(name);
561 }
c801d85f
KB
562}
563
564void wxView::SetDocument(wxDocument *doc)
565{
0fb67cd1
VZ
566 m_viewDocument = doc;
567 if (doc)
568 doc->AddView(this);
c801d85f
KB
569}
570
571bool wxView::Close(bool deleteWindow)
572{
0fb67cd1
VZ
573 if (OnClose(deleteWindow))
574 return TRUE;
575 else
576 return FALSE;
c801d85f
KB
577}
578
579void wxView::Activate(bool activate)
580{
0fb67cd1
VZ
581 if (GetDocumentManager())
582 {
583 OnActivateView(activate, this, GetDocumentManager()->GetCurrentView());
584 GetDocumentManager()->ActivateView(this, activate);
585 }
c801d85f
KB
586}
587
588bool wxView::OnClose(bool WXUNUSED(deleteWindow))
589{
0fb67cd1 590 return GetDocument() ? GetDocument()->Close() : TRUE;
c801d85f
KB
591}
592
47d67540 593#if wxUSE_PRINTING_ARCHITECTURE
0fb67cd1 594wxPrintout *wxView::OnCreatePrintout()
c801d85f 595{
0fb67cd1 596 return new wxDocPrintout(this);
c801d85f 597}
6de2f8b9 598#endif // wxUSE_PRINTING_ARCHITECTURE
c801d85f 599
0fb67cd1
VZ
600// ----------------------------------------------------------------------------
601// wxDocTemplate
602// ----------------------------------------------------------------------------
c801d85f 603
0fb67cd1
VZ
604wxDocTemplate::wxDocTemplate(wxDocManager *manager,
605 const wxString& descr,
606 const wxString& filter,
607 const wxString& dir,
608 const wxString& ext,
609 const wxString& docTypeName,
610 const wxString& viewTypeName,
611 wxClassInfo *docClassInfo,
612 wxClassInfo *viewClassInfo,
613 long flags)
c801d85f 614{
0fb67cd1 615 m_documentManager = manager;
0fb67cd1
VZ
616 m_description = descr;
617 m_directory = dir;
618 m_defaultExt = ext;
619 m_fileFilter = filter;
620 m_flags = flags;
621 m_docTypeName = docTypeName;
622 m_viewTypeName = viewTypeName;
623 m_documentManager->AssociateTemplate(this);
c801d85f 624
0fb67cd1
VZ
625 m_docClassInfo = docClassInfo;
626 m_viewClassInfo = viewClassInfo;
c801d85f
KB
627}
628
0fb67cd1 629wxDocTemplate::~wxDocTemplate()
c801d85f 630{
0fb67cd1 631 m_documentManager->DisassociateTemplate(this);
c801d85f 632}
0fb67cd1
VZ
633
634// Tries to dynamically construct an object of the right class.
c801d85f
KB
635wxDocument *wxDocTemplate::CreateDocument(const wxString& path, long flags)
636{
0fb67cd1
VZ
637 if (!m_docClassInfo)
638 return (wxDocument *) NULL;
639 wxDocument *doc = (wxDocument *)m_docClassInfo->CreateObject();
640 doc->SetFilename(path);
641 doc->SetDocumentTemplate(this);
642 GetDocumentManager()->AddDocument(doc);
643 doc->SetCommandProcessor(doc->OnCreateCommandProcessor());
644
645 if (doc->OnCreate(path, flags))
646 return doc;
647 else
648 {
649 delete doc;
650 return (wxDocument *) NULL;
651 }
c801d85f
KB
652}
653
654wxView *wxDocTemplate::CreateView(wxDocument *doc, long flags)
655{
0fb67cd1
VZ
656 if (!m_viewClassInfo)
657 return (wxView *) NULL;
658 wxView *view = (wxView *)m_viewClassInfo->CreateObject();
659 view->SetDocument(doc);
660 if (view->OnCreate(doc, flags))
661 {
662 return view;
663 }
664 else
665 {
666 delete view;
667 return (wxView *) NULL;
668 }
c801d85f
KB
669}
670
6de2f8b9
VZ
671// The default (very primitive) format detection: check is the extension is
672// that of the template
673bool wxDocTemplate::FileMatchesTemplate(const wxString& path)
674{
675 return GetDefaultExtension().IsSameAs(FindExtension(path));
676}
677
0fb67cd1
VZ
678// ----------------------------------------------------------------------------
679// wxDocManager
680// ----------------------------------------------------------------------------
681
c801d85f
KB
682BEGIN_EVENT_TABLE(wxDocManager, wxEvtHandler)
683 EVT_MENU(wxID_OPEN, wxDocManager::OnFileOpen)
684 EVT_MENU(wxID_CLOSE, wxDocManager::OnFileClose)
685 EVT_MENU(wxID_REVERT, wxDocManager::OnFileRevert)
686 EVT_MENU(wxID_NEW, wxDocManager::OnFileNew)
687 EVT_MENU(wxID_SAVE, wxDocManager::OnFileSave)
688 EVT_MENU(wxID_SAVEAS, wxDocManager::OnFileSaveAs)
689 EVT_MENU(wxID_UNDO, wxDocManager::OnUndo)
690 EVT_MENU(wxID_REDO, wxDocManager::OnRedo)
ce4169a4 691#if wxUSE_PRINTING_ARCHITECTURE
c801d85f
KB
692 EVT_MENU(wxID_PRINT, wxDocManager::OnPrint)
693 EVT_MENU(wxID_PRINT_SETUP, wxDocManager::OnPrintSetup)
694 EVT_MENU(wxID_PREVIEW, wxDocManager::OnPreview)
ce4169a4 695#endif
c801d85f
KB
696END_EVENT_TABLE()
697
698wxDocManager::wxDocManager(long flags, bool initialize)
699{
0fb67cd1
VZ
700 m_defaultDocumentNameCounter = 1;
701 m_flags = flags;
702 m_currentView = (wxView *) NULL;
703 m_maxDocsOpen = 10000;
704 m_fileHistory = (wxFileHistory *) NULL;
705 if (initialize)
706 Initialize();
c801d85f
KB
707}
708
0fb67cd1 709wxDocManager::~wxDocManager()
c801d85f 710{
0fb67cd1
VZ
711 Clear();
712 if (m_fileHistory)
713 delete m_fileHistory;
c801d85f
KB
714}
715
716bool wxDocManager::Clear(bool force)
717{
0fb67cd1
VZ
718 wxNode *node = m_docs.First();
719 while (node)
720 {
721 wxDocument *doc = (wxDocument *)node->Data();
722 wxNode *next = node->Next();
723
724 if (!doc->Close() && !force)
725 return FALSE;
726
727 // Implicitly deletes the document when the last
728 // view is removed (deleted)
729 doc->DeleteAllViews();
730
731 // Check document is deleted
732 if (m_docs.Member(doc))
733 delete doc;
734
735 // This assumes that documents are not connected in
736 // any way, i.e. deleting one document does NOT
737 // delete another.
738 node = next;
739 }
740 node = m_templates.First();
741 while (node)
742 {
c801d85f
KB
743 wxDocTemplate *templ = (wxDocTemplate*) node->Data();
744 wxNode* next = node->Next();
745 delete templ;
746 node = next;
0fb67cd1
VZ
747 }
748 return TRUE;
c801d85f
KB
749}
750
0fb67cd1 751bool wxDocManager::Initialize()
c801d85f 752{
0fb67cd1
VZ
753 m_fileHistory = OnCreateFileHistory();
754 return TRUE;
c801d85f
KB
755}
756
0fb67cd1 757wxFileHistory *wxDocManager::OnCreateFileHistory()
c801d85f 758{
0fb67cd1 759 return new wxFileHistory;
c801d85f
KB
760}
761
762void wxDocManager::OnFileClose(wxCommandEvent& WXUNUSED(event))
763{
0fb67cd1
VZ
764 wxDocument *doc = GetCurrentDocument();
765 if (!doc)
766 return;
767 if (doc->Close())
768 {
769 doc->DeleteAllViews();
770 if (m_docs.Member(doc))
771 delete doc;
772 }
c801d85f
KB
773}
774
775void wxDocManager::OnFileNew(wxCommandEvent& WXUNUSED(event))
776{
0fb67cd1 777 CreateDocument(wxString(""), wxDOC_NEW);
c801d85f
KB
778}
779
780void wxDocManager::OnFileOpen(wxCommandEvent& WXUNUSED(event))
781{
0fb67cd1 782 CreateDocument(wxString(""), 0);
c801d85f
KB
783}
784
785void wxDocManager::OnFileRevert(wxCommandEvent& WXUNUSED(event))
786{
0fb67cd1
VZ
787 wxDocument *doc = GetCurrentDocument();
788 if (!doc)
789 return;
790 doc->Revert();
c801d85f
KB
791}
792
793void wxDocManager::OnFileSave(wxCommandEvent& WXUNUSED(event))
794{
0fb67cd1
VZ
795 wxDocument *doc = GetCurrentDocument();
796 if (!doc)
797 return;
798 doc->Save();
c801d85f
KB
799}
800
801void wxDocManager::OnFileSaveAs(wxCommandEvent& WXUNUSED(event))
802{
0fb67cd1
VZ
803 wxDocument *doc = GetCurrentDocument();
804 if (!doc)
805 return;
806 doc->SaveAs();
c801d85f
KB
807}
808
809void wxDocManager::OnPrint(wxCommandEvent& WXUNUSED(event))
810{
88ac883a 811#if wxUSE_PRINTING_ARCHITECTURE
0fb67cd1
VZ
812 wxView *view = GetCurrentView();
813 if (!view)
814 return;
c801d85f 815
0fb67cd1
VZ
816 wxPrintout *printout = view->OnCreatePrintout();
817 if (printout)
818 {
819 wxPrinter printer;
820 printer.Print(view->GetFrame(), printout, TRUE);
c801d85f 821
0fb67cd1
VZ
822 delete printout;
823 }
88ac883a 824#endif // wxUSE_PRINTING_ARCHITECTURE
c801d85f
KB
825}
826
827void wxDocManager::OnPrintSetup(wxCommandEvent& WXUNUSED(event))
828{
ce4169a4 829#if wxUSE_PRINTING_ARCHITECTURE
0fb67cd1
VZ
830 wxWindow *parentWin = wxTheApp->GetTopWindow();
831 wxView *view = GetCurrentView();
832 if (view)
833 parentWin = view->GetFrame();
c801d85f 834
0fb67cd1 835 wxPrintDialogData data;
c801d85f 836
0fb67cd1
VZ
837 wxPrintDialog printerDialog(parentWin, & data);
838 printerDialog.GetPrintDialogData().SetSetupDialog(TRUE);
839 printerDialog.ShowModal();
ce4169a4 840#endif // wxUSE_PRINTING_ARCHITECTURE
c801d85f
KB
841}
842
843void wxDocManager::OnPreview(wxCommandEvent& WXUNUSED(event))
844{
88ac883a 845#if wxUSE_PRINTING_ARCHITECTURE
0fb67cd1
VZ
846 wxView *view = GetCurrentView();
847 if (!view)
848 return;
c801d85f 849
0fb67cd1
VZ
850 wxPrintout *printout = view->OnCreatePrintout();
851 if (printout)
852 {
853 // Pass two printout objects: for preview, and possible printing.
854 wxPrintPreviewBase *preview = (wxPrintPreviewBase *) NULL;
855 preview = new wxPrintPreview(printout, view->OnCreatePrintout());
856
857 wxPreviewFrame *frame = new wxPreviewFrame(preview, (wxFrame *)wxTheApp->GetTopWindow(), _("Print Preview"),
858 wxPoint(100, 100), wxSize(600, 650));
859 frame->Centre(wxBOTH);
860 frame->Initialize();
861 frame->Show(TRUE);
862 }
88ac883a 863#endif // wxUSE_PRINTING_ARCHITECTURE
c801d85f
KB
864}
865
866void wxDocManager::OnUndo(wxCommandEvent& WXUNUSED(event))
867{
0fb67cd1
VZ
868 wxDocument *doc = GetCurrentDocument();
869 if (!doc)
870 return;
871 if (doc->GetCommandProcessor())
872 doc->GetCommandProcessor()->Undo();
c801d85f
KB
873}
874
875void wxDocManager::OnRedo(wxCommandEvent& WXUNUSED(event))
876{
0fb67cd1
VZ
877 wxDocument *doc = GetCurrentDocument();
878 if (!doc)
879 return;
880 if (doc->GetCommandProcessor())
881 doc->GetCommandProcessor()->Redo();
c801d85f
KB
882}
883
6de2f8b9 884wxView *wxDocManager::GetCurrentView() const
637f467a
JS
885{
886 if (m_currentView)
887 return m_currentView;
888 if (m_docs.Number() == 1)
889 {
890 wxDocument* doc = (wxDocument*) m_docs.First()->Data();
891 return doc->GetFirstView();
892 }
c67daf87 893 return (wxView *) NULL;
637f467a
JS
894}
895
896// Extend event processing to search the view's event table
897bool wxDocManager::ProcessEvent(wxEvent& event)
898{
899 wxView* view = GetCurrentView();
900 if (view)
901 {
902 if (view->ProcessEvent(event))
903 return TRUE;
904 }
905 return wxEvtHandler::ProcessEvent(event);
906}
907
c801d85f
KB
908wxDocument *wxDocManager::CreateDocument(const wxString& path, long flags)
909{
0fb67cd1
VZ
910 wxDocTemplate **templates = new wxDocTemplate *[m_templates.Number()];
911 int i;
912 int n = 0;
913 for (i = 0; i < m_templates.Number(); i++)
c801d85f 914 {
0fb67cd1
VZ
915 wxDocTemplate *temp = (wxDocTemplate *)(m_templates.Nth(i)->Data());
916 if (temp->IsVisible())
917 {
918 templates[n] = temp;
919 n ++;
920 }
c801d85f 921 }
0fb67cd1 922 if (n == 0)
c801d85f 923 {
0fb67cd1
VZ
924 delete[] templates;
925 return (wxDocument *) NULL;
c801d85f 926 }
0fb67cd1
VZ
927
928 // If we've reached the max number of docs, close the
929 // first one.
930 if (GetDocuments().Number() >= m_maxDocsOpen)
c801d85f 931 {
0fb67cd1
VZ
932 wxDocument *doc = (wxDocument *)GetDocuments().First()->Data();
933 if (doc->Close())
934 {
935 // Implicitly deletes the document when
936 // the last view is deleted
937 doc->DeleteAllViews();
938
939 // Check we're really deleted
940 if (m_docs.Member(doc))
941 delete doc;
942 }
943 else
944 return (wxDocument *) NULL;
c801d85f
KB
945 }
946
0fb67cd1
VZ
947 // New document: user chooses a template, unless there's only one.
948 if (flags & wxDOC_NEW)
c801d85f 949 {
0fb67cd1
VZ
950 if (n == 1)
951 {
952 wxDocTemplate *temp = templates[0];
953 delete[] templates;
954 wxDocument *newDoc = temp->CreateDocument(path, flags);
955 if (newDoc)
956 {
957 newDoc->SetDocumentName(temp->GetDocumentName());
958 newDoc->SetDocumentTemplate(temp);
959 newDoc->OnNewDocument();
960 }
961 return newDoc;
962 }
963
964 wxDocTemplate *temp = SelectDocumentType(templates, n);
965 delete[] templates;
966 if (temp)
967 {
968 wxDocument *newDoc = temp->CreateDocument(path, flags);
969 if (newDoc)
970 {
971 newDoc->SetDocumentName(temp->GetDocumentName());
972 newDoc->SetDocumentTemplate(temp);
973 newDoc->OnNewDocument();
974 }
975 return newDoc;
976 }
977 else
978 return (wxDocument *) NULL;
c801d85f 979 }
c801d85f 980
0fb67cd1
VZ
981 // Existing document
982 wxDocTemplate *temp = (wxDocTemplate *) NULL;
c801d85f 983
d0bdc3ca
OK
984 wxString path2(_T(""));
985 if (path != _T(""))
0fb67cd1 986 path2 = path;
c801d85f 987
0fb67cd1
VZ
988 if (flags & wxDOC_SILENT)
989 temp = FindTemplateForPath(path2);
990 else
991 temp = SelectDocumentPath(templates, n, path2, flags);
c801d85f 992
0fb67cd1 993 delete[] templates;
c801d85f 994
0fb67cd1 995 if (temp)
c801d85f 996 {
0fb67cd1
VZ
997 wxDocument *newDoc = temp->CreateDocument(path2, flags);
998 if (newDoc)
999 {
1000 newDoc->SetDocumentName(temp->GetDocumentName());
1001 newDoc->SetDocumentTemplate(temp);
1002 if (!newDoc->OnOpenDocument(path2))
1003 {
1004 delete newDoc;
1005 return (wxDocument *) NULL;
1006 }
1007 AddFileToHistory(path2);
1008 }
1009 return newDoc;
c801d85f 1010 }
0fb67cd1
VZ
1011 else
1012 return (wxDocument *) NULL;
c801d85f
KB
1013}
1014
1015wxView *wxDocManager::CreateView(wxDocument *doc, long flags)
1016{
0fb67cd1
VZ
1017 wxDocTemplate **templates = new wxDocTemplate *[m_templates.Number()];
1018 int n =0;
1019 int i;
1020 for (i = 0; i < m_templates.Number(); i++)
1021 {
1022 wxDocTemplate *temp = (wxDocTemplate *)(m_templates.Nth(i)->Data());
1023 if (temp->IsVisible())
1024 {
1025 if (temp->GetDocumentName() == doc->GetDocumentName())
1026 {
1027 templates[n] = temp;
1028 n ++;
1029 }
1030 }
1031 }
1032 if (n == 0)
1033 {
1034 delete[] templates;
1035 return (wxView *) NULL;
1036 }
1037 if (n == 1)
1038 {
1039 wxDocTemplate *temp = templates[0];
1040 delete[] templates;
1041 wxView *view = temp->CreateView(doc, flags);
1042 if (view)
1043 view->SetViewName(temp->GetViewName());
1044 return view;
1045 }
1046
1047 wxDocTemplate *temp = SelectViewType(templates, n);
c801d85f 1048 delete[] templates;
0fb67cd1
VZ
1049 if (temp)
1050 {
1051 wxView *view = temp->CreateView(doc, flags);
1052 if (view)
1053 view->SetViewName(temp->GetViewName());
1054 return view;
1055 }
1056 else
1057 return (wxView *) NULL;
c801d85f
KB
1058}
1059
1060// Not yet implemented
1061void wxDocManager::DeleteTemplate(wxDocTemplate *WXUNUSED(temp), long WXUNUSED(flags))
1062{
1063}
1064
1065// Not yet implemented
1066bool wxDocManager::FlushDoc(wxDocument *WXUNUSED(doc))
1067{
0fb67cd1 1068 return FALSE;
c801d85f
KB
1069}
1070
6de2f8b9 1071wxDocument *wxDocManager::GetCurrentDocument() const
c801d85f 1072{
0fb67cd1
VZ
1073 if (m_currentView)
1074 return m_currentView->GetDocument();
1075 else
1076 return (wxDocument *) NULL;
c801d85f
KB
1077}
1078
1079// Make a default document name
1080bool wxDocManager::MakeDefaultName(wxString& name)
1081{
0fb67cd1
VZ
1082 name.Printf(_("unnamed%d"), m_defaultDocumentNameCounter);
1083 m_defaultDocumentNameCounter++;
53c6e7cc 1084
0fb67cd1 1085 return TRUE;
c801d85f
KB
1086}
1087
1088// Not yet implemented
1089wxDocTemplate *wxDocManager::MatchTemplate(const wxString& WXUNUSED(path))
1090{
0fb67cd1 1091 return (wxDocTemplate *) NULL;
c801d85f
KB
1092}
1093
1094// File history management
1095void wxDocManager::AddFileToHistory(const wxString& file)
1096{
0fb67cd1
VZ
1097 if (m_fileHistory)
1098 m_fileHistory->AddFileToHistory(file);
c801d85f
KB
1099}
1100
1101wxString wxDocManager::GetHistoryFile(int i) const
1102{
0fb67cd1
VZ
1103 wxString histFile;
1104
1105 if (m_fileHistory)
1106 histFile = m_fileHistory->GetHistoryFile(i);
1107
1108 return histFile;
c801d85f
KB
1109}
1110
1111void wxDocManager::FileHistoryUseMenu(wxMenu *menu)
1112{
0fb67cd1
VZ
1113 if (m_fileHistory)
1114 m_fileHistory->UseMenu(menu);
c801d85f
KB
1115}
1116
7f555861 1117void wxDocManager::FileHistoryRemoveMenu(wxMenu *menu)
c801d85f 1118{
0fb67cd1
VZ
1119 if (m_fileHistory)
1120 m_fileHistory->RemoveMenu(menu);
c801d85f
KB
1121}
1122
702ca7c0 1123#if wxUSE_CONFIG
7f555861 1124void wxDocManager::FileHistoryLoad(wxConfigBase& config)
c801d85f 1125{
0fb67cd1
VZ
1126 if (m_fileHistory)
1127 m_fileHistory->Load(config);
7f555861
JS
1128}
1129
1130void wxDocManager::FileHistorySave(wxConfigBase& config)
1131{
0fb67cd1
VZ
1132 if (m_fileHistory)
1133 m_fileHistory->Save(config);
7f555861 1134}
ac57418f 1135#endif
7f555861
JS
1136
1137void wxDocManager::FileHistoryAddFilesToMenu(wxMenu* menu)
1138{
0fb67cd1
VZ
1139 if (m_fileHistory)
1140 m_fileHistory->AddFilesToMenu(menu);
7f555861
JS
1141}
1142
1143void wxDocManager::FileHistoryAddFilesToMenu()
1144{
0fb67cd1
VZ
1145 if (m_fileHistory)
1146 m_fileHistory->AddFilesToMenu();
c801d85f
KB
1147}
1148
6de2f8b9 1149int wxDocManager::GetNoHistoryFiles() const
c801d85f 1150{
0fb67cd1
VZ
1151 if (m_fileHistory)
1152 return m_fileHistory->GetNoHistoryFiles();
c801d85f 1153 else
0fb67cd1 1154 return 0;
c801d85f
KB
1155}
1156
1157
6de2f8b9
VZ
1158// Find out the document template via matching in the document file format
1159// against that of the template
c801d85f
KB
1160wxDocTemplate *wxDocManager::FindTemplateForPath(const wxString& path)
1161{
0fb67cd1 1162 wxDocTemplate *theTemplate = (wxDocTemplate *) NULL;
c801d85f 1163
0fb67cd1
VZ
1164 // Find the template which this extension corresponds to
1165 int i;
1166 for (i = 0; i < m_templates.Number(); i++)
c801d85f 1167 {
0fb67cd1 1168 wxDocTemplate *temp = (wxDocTemplate *)m_templates.Nth(i)->Data();
6de2f8b9 1169 if ( temp->FileMatchesTemplate(path) )
0fb67cd1
VZ
1170 {
1171 theTemplate = temp;
1172 break;
1173 }
c801d85f 1174 }
0fb67cd1 1175 return theTemplate;
c801d85f
KB
1176}
1177
1178// Prompts user to open a file, using file specs in templates.
1179// How to implement in wxWindows? Must extend the file selector
1180// dialog or implement own; OR match the extension to the
1181// template extension.
df875e59 1182
c801d85f 1183wxDocTemplate *wxDocManager::SelectDocumentPath(wxDocTemplate **templates,
f6147cfc 1184#ifdef __WXMSW__
0fb67cd1 1185 int noTemplates,
f6147cfc
VZ
1186#else
1187 int WXUNUSED(noTemplates),
1188#endif
0fb67cd1
VZ
1189 wxString& path,
1190 long WXUNUSED(flags),
1191 bool WXUNUSED(save))
c801d85f 1192{
0fb67cd1 1193 // We can only have multiple filters in Windows
2049ba38 1194#ifdef __WXMSW__
ba681060
VZ
1195 wxString descrBuf;
1196
1197 int i;
1198 for (i = 0; i < noTemplates; i++)
c801d85f 1199 {
ba681060
VZ
1200 if (templates[i]->IsVisible())
1201 {
1202 // add a '|' to separate this filter from the previous one
1203 if ( !descrBuf.IsEmpty() )
50920146 1204 descrBuf << _T('|');
ba681060
VZ
1205
1206 descrBuf << templates[i]->GetDescription()
50920146 1207 << _T(" (") << templates[i]->GetFileFilter() << _T(") |")
0fb67cd1 1208 << templates[i]->GetFileFilter();
ba681060 1209 }
c801d85f 1210 }
a4294b78 1211#else
50920146 1212 wxString descrBuf = _T("*.*");
a4294b78 1213#endif
c801d85f 1214
6de2f8b9
VZ
1215 int FilterIndex = 0;
1216 wxString pathTmp = wxFileSelectorEx(_("Select a file"),
caf0debf
VZ
1217 _T(""),
1218 _T(""),
6de2f8b9 1219 &FilterIndex,
caf0debf
VZ
1220 descrBuf,
1221 0,
1222 wxTheApp->GetTopWindow());
ba681060 1223
0fb67cd1
VZ
1224 if (!pathTmp.IsEmpty())
1225 {
1226 path = pathTmp;
1227 wxString theExt = FindExtension(path);
1228 if (!theExt)
1229 return (wxDocTemplate *) NULL;
1230
1231 // This is dodgy in that we're selecting the template on the
1232 // basis of the file extension, which may not be a standard
1233 // one. We really want to know exactly which template was
1234 // chosen by using a more advanced file selector.
1235 wxDocTemplate *theTemplate = FindTemplateForPath(path);
6de2f8b9
VZ
1236 if ( !theTemplate )
1237 theTemplate = templates[FilterIndex];
1238
0fb67cd1
VZ
1239 return theTemplate;
1240 }
1241 else
1242 {
d0bdc3ca 1243 path = _T("");
0fb67cd1
VZ
1244 return (wxDocTemplate *) NULL;
1245 }
a4294b78 1246#if 0
0fb67cd1
VZ
1247 // In all other windowing systems, until we have more advanced
1248 // file selectors, we must select the document type (template) first, and
1249 // _then_ pop up the file selector.
1250 wxDocTemplate *temp = SelectDocumentType(templates, noTemplates);
1251 if (!temp)
1252 return (wxDocTemplate *) NULL;
1253
d0bdc3ca 1254 wxChar *pathTmp = wxFileSelector(_("Select a file"), _T(""), _T(""),
0fb67cd1
VZ
1255 temp->GetDefaultExtension(),
1256 temp->GetFileFilter(),
1257 0, wxTheApp->GetTopWindow());
1258
1259 if (pathTmp)
1260 {
1261 path = pathTmp;
1262 return temp;
1263 }
1264 else
1265 return (wxDocTemplate *) NULL;
1266#endif // 0
c801d85f
KB
1267}
1268
1269wxDocTemplate *wxDocManager::SelectDocumentType(wxDocTemplate **templates,
0fb67cd1
VZ
1270 int noTemplates)
1271{
50920146
OK
1272 wxChar **strings = new wxChar *[noTemplates];
1273 wxChar **data = new wxChar *[noTemplates];
0fb67cd1
VZ
1274 int i;
1275 int n = 0;
1276 for (i = 0; i < noTemplates; i++)
1277 {
1278 if (templates[i]->IsVisible())
1279 {
1280 strings[n] = WXSTRINGCAST templates[i]->m_description;
50920146 1281 data[n] = (wxChar *)templates[i];
0fb67cd1
VZ
1282 n ++;
1283 }
1284 }
1285 if (n == 0)
1286 {
1287 delete[] strings;
1288 delete[] data;
1289 return (wxDocTemplate *) NULL;
1290 }
1291 else if (n == 1)
1292 {
1293 wxDocTemplate *temp = (wxDocTemplate *)data[0];
1294 delete[] strings;
1295 delete[] data;
1296 return temp;
1297 }
1298
1299 wxDocTemplate *theTemplate = (wxDocTemplate *)wxGetSingleChoiceData(_("Select a document template"), _("Templates"), n,
c980c992 1300 strings, (char **)data);
c801d85f
KB
1301 delete[] strings;
1302 delete[] data;
0fb67cd1 1303 return theTemplate;
c801d85f
KB
1304}
1305
1306wxDocTemplate *wxDocManager::SelectViewType(wxDocTemplate **templates,
0fb67cd1 1307 int noTemplates)
c801d85f 1308{
50920146
OK
1309 wxChar **strings = new wxChar *[noTemplates];
1310 wxChar **data = new wxChar *[noTemplates];
0fb67cd1
VZ
1311 int i;
1312 int n = 0;
1313 for (i = 0; i < noTemplates; i++)
c801d85f 1314 {
d0bdc3ca 1315 if (templates[i]->IsVisible() && (templates[i]->GetViewName() != _T("")))
0fb67cd1
VZ
1316 {
1317 strings[n] = WXSTRINGCAST templates[i]->m_viewTypeName;
50920146 1318 data[n] = (wxChar *)templates[i];
0fb67cd1
VZ
1319 n ++;
1320 }
c801d85f 1321 }
0fb67cd1 1322 wxDocTemplate *theTemplate = (wxDocTemplate *)wxGetSingleChoiceData(_("Select a document view"), _("Views"), n,
c980c992 1323 strings, (char **)data);
0fb67cd1
VZ
1324 delete[] strings;
1325 delete[] data;
1326 return theTemplate;
c801d85f
KB
1327}
1328
1329void wxDocManager::AssociateTemplate(wxDocTemplate *temp)
1330{
0fb67cd1
VZ
1331 if (!m_templates.Member(temp))
1332 m_templates.Append(temp);
c801d85f
KB
1333}
1334
1335void wxDocManager::DisassociateTemplate(wxDocTemplate *temp)
1336{
0fb67cd1 1337 m_templates.DeleteObject(temp);
c801d85f
KB
1338}
1339
1340// Add and remove a document from the manager's list
1341void wxDocManager::AddDocument(wxDocument *doc)
1342{
0fb67cd1
VZ
1343 if (!m_docs.Member(doc))
1344 m_docs.Append(doc);
c801d85f
KB
1345}
1346
1347void wxDocManager::RemoveDocument(wxDocument *doc)
1348{
0fb67cd1 1349 m_docs.DeleteObject(doc);
c801d85f
KB
1350}
1351
1352// Views or windows should inform the document manager
1353// when a view is going in or out of focus
1354void wxDocManager::ActivateView(wxView *view, bool activate, bool WXUNUSED(deleting))
1355{
0fb67cd1
VZ
1356 // If we're deactiving, and if we're not actually deleting the view, then
1357 // don't reset the current view because we may be going to
1358 // a window without a view.
1359 // WHAT DID I MEAN BY THAT EXACTLY?
1360 /*
1361 if (deleting)
1362 {
1363 if (m_currentView == view)
1364 m_currentView = NULL;
1365 }
1366 else
1367 */
1368 {
1369 if (activate)
1370 m_currentView = view;
1371 else
1372 m_currentView = (wxView *) NULL;
1373 }
c801d85f
KB
1374}
1375
0fb67cd1
VZ
1376// ----------------------------------------------------------------------------
1377// Default document child frame
1378// ----------------------------------------------------------------------------
c801d85f
KB
1379
1380BEGIN_EVENT_TABLE(wxDocChildFrame, wxFrame)
1381 EVT_ACTIVATE(wxDocChildFrame::OnActivate)
387a3b02 1382 EVT_CLOSE(wxDocChildFrame::OnCloseWindow)
c801d85f
KB
1383END_EVENT_TABLE()
1384
0fb67cd1
VZ
1385wxDocChildFrame::wxDocChildFrame(wxDocument *doc,
1386 wxView *view,
1387 wxFrame *frame,
1388 wxWindowID id,
1389 const wxString& title,
1390 const wxPoint& pos,
1391 const wxSize& size,
1392 long style,
1393 const wxString& name)
1394 : wxFrame(frame, id, title, pos, size, style, name)
1395{
1396 m_childDocument = doc;
1397 m_childView = view;
1398 if (view)
1399 view->SetFrame(this);
c801d85f
KB
1400}
1401
0fb67cd1 1402wxDocChildFrame::~wxDocChildFrame()
c801d85f
KB
1403{
1404}
1405
1406// Extend event processing to search the view's event table
1407bool wxDocChildFrame::ProcessEvent(wxEvent& event)
1408{
1409 if (m_childView)
1410 m_childView->Activate(TRUE);
1411
0fb67cd1 1412 if ( !m_childView || ! m_childView->ProcessEvent(event) )
c801d85f
KB
1413 {
1414 // Only hand up to the parent if it's a menu command
1415 if (!event.IsKindOf(CLASSINFO(wxCommandEvent)) || !GetParent() || !GetParent()->ProcessEvent(event))
0fb67cd1 1416 return wxEvtHandler::ProcessEvent(event);
c801d85f
KB
1417 else
1418 return TRUE;
1419 }
0fb67cd1
VZ
1420 else
1421 return TRUE;
c801d85f
KB
1422}
1423
c801d85f
KB
1424void wxDocChildFrame::OnActivate(wxActivateEvent& event)
1425{
0fb67cd1 1426 wxFrame::OnActivate(event);
c801d85f 1427
0fb67cd1
VZ
1428 if (m_childView)
1429 m_childView->Activate(event.GetActive());
c801d85f
KB
1430}
1431
387a3b02 1432void wxDocChildFrame::OnCloseWindow(wxCloseEvent& event)
c801d85f 1433{
0fb67cd1 1434 if (m_childView)
c801d85f 1435 {
0fb67cd1
VZ
1436 bool ans = FALSE;
1437 if (!event.CanVeto())
1438 ans = TRUE; // Must delete.
1439 else
1440 ans = m_childView->Close(FALSE); // FALSE means don't delete associated window
387a3b02 1441
0fb67cd1
VZ
1442 if (ans)
1443 {
1444 m_childView->Activate(FALSE);
1445 delete m_childView;
1446 m_childView = (wxView *) NULL;
1447 m_childDocument = (wxDocument *) NULL;
1448
1449 this->Destroy();
1450 }
1451 else
1452 event.Veto();
c801d85f 1453 }
387a3b02 1454 else
0fb67cd1 1455 event.Veto();
c801d85f
KB
1456}
1457
0fb67cd1
VZ
1458// ----------------------------------------------------------------------------
1459// Default parent frame
1460// ----------------------------------------------------------------------------
c801d85f
KB
1461
1462BEGIN_EVENT_TABLE(wxDocParentFrame, wxFrame)
1463 EVT_MENU(wxID_EXIT, wxDocParentFrame::OnExit)
f7bd2698 1464 EVT_MENU_RANGE(wxID_FILE1, wxID_FILE9, wxDocParentFrame::OnMRUFile)
387a3b02 1465 EVT_CLOSE(wxDocParentFrame::OnCloseWindow)
c801d85f
KB
1466END_EVENT_TABLE()
1467
0fb67cd1
VZ
1468wxDocParentFrame::wxDocParentFrame(wxDocManager *manager,
1469 wxFrame *frame,
1470 wxWindowID id,
1471 const wxString& title,
1472 const wxPoint& pos,
1473 const wxSize& size,
1474 long style,
1475 const wxString& name)
1476 : wxFrame(frame, id, title, pos, size, style, name)
c801d85f 1477{
0fb67cd1 1478 m_docManager = manager;
c801d85f
KB
1479}
1480
1481void wxDocParentFrame::OnExit(wxCommandEvent& WXUNUSED(event))
1482{
1483 Close();
1484}
1485
1486void wxDocParentFrame::OnMRUFile(wxCommandEvent& event)
1487{
0fb67cd1 1488 wxString f(m_docManager->GetHistoryFile(event.GetSelection() - wxID_FILE1));
d0bdc3ca 1489 if (f != _T(""))
c801d85f
KB
1490 (void)m_docManager->CreateDocument(f, wxDOC_SILENT);
1491}
1492
1493// Extend event processing to search the view's event table
1494bool wxDocParentFrame::ProcessEvent(wxEvent& event)
1495{
1496 // Try the document manager, then do default processing
1497 if (!m_docManager || !m_docManager->ProcessEvent(event))
1498 return wxEvtHandler::ProcessEvent(event);
1499 else
1500 return TRUE;
1501}
1502
c801d85f
KB
1503// Define the behaviour for the frame closing
1504// - must delete all frames except for the main one.
387a3b02 1505void wxDocParentFrame::OnCloseWindow(wxCloseEvent& event)
c801d85f 1506{
0fb67cd1
VZ
1507 if (m_docManager->Clear(!event.CanVeto()))
1508 {
1509 this->Destroy();
1510 }
1511 else
1512 event.Veto();
c801d85f
KB
1513}
1514
47d67540 1515#if wxUSE_PRINTING_ARCHITECTURE
c801d85f 1516
0fb67cd1
VZ
1517wxDocPrintout::wxDocPrintout(wxView *view, const wxString& title)
1518 : wxPrintout(WXSTRINGCAST title)
c801d85f 1519{
0fb67cd1 1520 m_printoutView = view;
c801d85f
KB
1521}
1522
1523bool wxDocPrintout::OnPrintPage(int WXUNUSED(page))
1524{
0fb67cd1
VZ
1525 wxDC *dc = GetDC();
1526
1527 // Get the logical pixels per inch of screen and printer
1528 int ppiScreenX, ppiScreenY;
1529 GetPPIScreen(&ppiScreenX, &ppiScreenY);
1530 int ppiPrinterX, ppiPrinterY;
1531 GetPPIPrinter(&ppiPrinterX, &ppiPrinterY);
1532
1533 // This scales the DC so that the printout roughly represents the
1534 // the screen scaling. The text point size _should_ be the right size
1535 // but in fact is too small for some reason. This is a detail that will
1536 // need to be addressed at some point but can be fudged for the
1537 // moment.
1538 float scale = (float)((float)ppiPrinterX/(float)ppiScreenX);
1539
1540 // Now we have to check in case our real page size is reduced
1541 // (e.g. because we're drawing to a print preview memory DC)
1542 int pageWidth, pageHeight;
1543 int w, h;
1544 dc->GetSize(&w, &h);
1545 GetPageSizePixels(&pageWidth, &pageHeight);
1546
1547 // If printer pageWidth == current DC width, then this doesn't
1548 // change. But w might be the preview bitmap width, so scale down.
1549 float overallScale = scale * (float)(w/(float)pageWidth);
1550 dc->SetUserScale(overallScale, overallScale);
1551
1552 if (m_printoutView)
1553 {
1554 m_printoutView->OnDraw(dc);
1555 }
1556 return TRUE;
c801d85f
KB
1557}
1558
1559bool wxDocPrintout::HasPage(int pageNum)
1560{
0fb67cd1 1561 return (pageNum == 1);
c801d85f
KB
1562}
1563
1564bool wxDocPrintout::OnBeginDocument(int startPage, int endPage)
1565{
0fb67cd1
VZ
1566 if (!wxPrintout::OnBeginDocument(startPage, endPage))
1567 return FALSE;
c801d85f 1568
0fb67cd1 1569 return TRUE;
c801d85f
KB
1570}
1571
1572void wxDocPrintout::GetPageInfo(int *minPage, int *maxPage, int *selPageFrom, int *selPageTo)
1573{
0fb67cd1
VZ
1574 *minPage = 1;
1575 *maxPage = 1;
1576 *selPageFrom = 1;
1577 *selPageTo = 1;
c801d85f
KB
1578}
1579
0fb67cd1 1580#endif // wxUSE_PRINTING_ARCHITECTURE
c801d85f 1581
0fb67cd1
VZ
1582// ----------------------------------------------------------------------------
1583// Command processing framework
1584// ----------------------------------------------------------------------------
c801d85f
KB
1585
1586wxCommand::wxCommand(bool canUndoIt, const wxString& name)
1587{
0fb67cd1
VZ
1588 m_canUndo = canUndoIt;
1589 m_commandName = name;
c801d85f
KB
1590}
1591
0fb67cd1 1592wxCommand::~wxCommand()
c801d85f
KB
1593{
1594}
1595
1596// Command processor
1597wxCommandProcessor::wxCommandProcessor(int maxCommands)
1598{
0fb67cd1
VZ
1599 m_maxNoCommands = maxCommands;
1600 m_currentCommand = (wxNode *) NULL;
1601 m_commandEditMenu = (wxMenu *) NULL;
c801d85f
KB
1602}
1603
0fb67cd1 1604wxCommandProcessor::~wxCommandProcessor()
c801d85f 1605{
0fb67cd1 1606 ClearCommands();
c801d85f
KB
1607}
1608
1609// Pass a command to the processor. The processor calls Do();
1610// if successful, is appended to the command history unless
1611// storeIt is FALSE.
1612bool wxCommandProcessor::Submit(wxCommand *command, bool storeIt)
1613{
0fb67cd1
VZ
1614 bool success = command->Do();
1615 if (success && storeIt)
c801d85f 1616 {
0fb67cd1
VZ
1617 if (m_commands.Number() == m_maxNoCommands)
1618 {
1619 wxNode *firstNode = m_commands.First();
1620 wxCommand *firstCommand = (wxCommand *)firstNode->Data();
1621 delete firstCommand;
1622 delete firstNode;
1623 }
c801d85f 1624
0fb67cd1
VZ
1625 // Correct a bug: we must chop off the current 'branch'
1626 // so that we're at the end of the command list.
1627 if (!m_currentCommand)
1628 ClearCommands();
1629 else
1630 {
1631 wxNode *node = m_currentCommand->Next();
1632 while (node)
1633 {
1634 wxNode *next = node->Next();
1635 delete (wxCommand *)node->Data();
1636 delete node;
1637 node = next;
1638 }
1639 }
1640
1641 m_commands.Append(command);
1642 m_currentCommand = m_commands.Last();
1643 SetMenuStrings();
c801d85f 1644 }
0fb67cd1 1645 return success;
c801d85f
KB
1646}
1647
0fb67cd1 1648bool wxCommandProcessor::Undo()
c801d85f 1649{
0fb67cd1 1650 if (m_currentCommand)
c801d85f 1651 {
0fb67cd1
VZ
1652 wxCommand *command = (wxCommand *)m_currentCommand->Data();
1653 if (command->CanUndo())
1654 {
1655 bool success = command->Undo();
1656 if (success)
1657 {
1658 m_currentCommand = m_currentCommand->Previous();
1659 SetMenuStrings();
1660 return TRUE;
1661 }
1662 }
c801d85f 1663 }
0fb67cd1 1664 return FALSE;
c801d85f
KB
1665}
1666
0fb67cd1 1667bool wxCommandProcessor::Redo()
c801d85f 1668{
0fb67cd1
VZ
1669 wxCommand *redoCommand = (wxCommand *) NULL;
1670 wxNode *redoNode = (wxNode *) NULL;
1671 if (m_currentCommand && m_currentCommand->Next())
1672 {
1673 redoCommand = (wxCommand *)m_currentCommand->Next()->Data();
1674 redoNode = m_currentCommand->Next();
1675 }
1676 else
c801d85f 1677 {
0fb67cd1
VZ
1678 if (m_commands.Number() > 0)
1679 {
1680 redoCommand = (wxCommand *)m_commands.First()->Data();
1681 redoNode = m_commands.First();
1682 }
c801d85f 1683 }
c801d85f 1684
0fb67cd1 1685 if (redoCommand)
c801d85f 1686 {
0fb67cd1
VZ
1687 bool success = redoCommand->Do();
1688 if (success)
1689 {
1690 m_currentCommand = redoNode;
1691 SetMenuStrings();
1692 return TRUE;
1693 }
c801d85f 1694 }
0fb67cd1 1695 return FALSE;
c801d85f
KB
1696}
1697
6de2f8b9 1698bool wxCommandProcessor::CanUndo() const
c801d85f 1699{
0fb67cd1
VZ
1700 if (m_currentCommand)
1701 return ((wxCommand *)m_currentCommand->Data())->CanUndo();
1702 return FALSE;
c801d85f
KB
1703}
1704
6de2f8b9 1705bool wxCommandProcessor::CanRedo() const
7f555861 1706{
f97c9854
JS
1707 if ((m_currentCommand != (wxNode*) NULL) && (m_currentCommand->Next() == (wxNode*) NULL))
1708 return FALSE;
1709
1710 if ((m_currentCommand != (wxNode*) NULL) && (m_currentCommand->Next() != (wxNode*) NULL))
1711 return TRUE;
1712
1713 if ((m_currentCommand == (wxNode*) NULL) && (m_commands.Number() > 0))
1714 return TRUE;
1715
1716 return FALSE;
7f555861
JS
1717}
1718
0fb67cd1 1719void wxCommandProcessor::Initialize()
c801d85f 1720{
0fb67cd1
VZ
1721 m_currentCommand = m_commands.Last();
1722 SetMenuStrings();
c801d85f
KB
1723}
1724
0fb67cd1 1725void wxCommandProcessor::SetMenuStrings()
c801d85f 1726{
0fb67cd1 1727 if (m_commandEditMenu)
c801d85f 1728 {
0fb67cd1
VZ
1729 wxString buf;
1730 if (m_currentCommand)
1731 {
1732 wxCommand *command = (wxCommand *)m_currentCommand->Data();
1733 wxString commandName(command->GetName());
d0bdc3ca 1734 if (commandName == _T("")) commandName = _("Unnamed command");
0fb67cd1
VZ
1735 bool canUndo = command->CanUndo();
1736 if (canUndo)
1737 buf = wxString(_("&Undo ")) + commandName;
1738 else
1739 buf = wxString(_("Can't &Undo ")) + commandName;
1740
1741 m_commandEditMenu->SetLabel(wxID_UNDO, buf);
1742 m_commandEditMenu->Enable(wxID_UNDO, canUndo);
1743
1744 // We can redo, if we're not at the end of the history.
1745 if (m_currentCommand->Next())
1746 {
1747 wxCommand *redoCommand = (wxCommand *)m_currentCommand->Next()->Data();
1748 wxString redoCommandName(redoCommand->GetName());
d0bdc3ca 1749 if (redoCommandName == _T("")) redoCommandName = _("Unnamed command");
0fb67cd1
VZ
1750 buf = wxString(_("&Redo ")) + redoCommandName;
1751 m_commandEditMenu->SetLabel(wxID_REDO, buf);
1752 m_commandEditMenu->Enable(wxID_REDO, TRUE);
1753 }
1754 else
1755 {
1756 m_commandEditMenu->SetLabel(wxID_REDO, _("&Redo"));
1757 m_commandEditMenu->Enable(wxID_REDO, FALSE);
1758 }
1759 }
1760 else
1761 {
1762 m_commandEditMenu->SetLabel(wxID_UNDO, _("&Undo"));
1763 m_commandEditMenu->Enable(wxID_UNDO, FALSE);
c801d85f 1764
0fb67cd1
VZ
1765 if (m_commands.Number() == 0)
1766 {
1767 m_commandEditMenu->SetLabel(wxID_REDO, _("&Redo"));
1768 m_commandEditMenu->Enable(wxID_REDO, FALSE);
1769 }
1770 else
1771 {
1772 // currentCommand is NULL but there are commands: this means that
1773 // we've undone to the start of the list, but can redo the first.
1774 wxCommand *redoCommand = (wxCommand *)m_commands.First()->Data();
1775 wxString redoCommandName(redoCommand->GetName());
d0bdc3ca 1776 if (redoCommandName == _T("")) redoCommandName = _("Unnamed command");
0fb67cd1
VZ
1777 buf = wxString(_("&Redo ")) + redoCommandName;
1778 m_commandEditMenu->SetLabel(wxID_REDO, buf);
1779 m_commandEditMenu->Enable(wxID_REDO, TRUE);
1780 }
1781 }
c801d85f 1782 }
c801d85f
KB
1783}
1784
0fb67cd1 1785void wxCommandProcessor::ClearCommands()
c801d85f 1786{
0fb67cd1
VZ
1787 wxNode *node = m_commands.First();
1788 while (node)
1789 {
1790 wxCommand *command = (wxCommand *)node->Data();
1791 delete command;
1792 delete node;
1793 node = m_commands.First();
1794 }
1795 m_currentCommand = (wxNode *) NULL;
c801d85f
KB
1796}
1797
0fb67cd1
VZ
1798// ----------------------------------------------------------------------------
1799// File history processor
1800// ----------------------------------------------------------------------------
c801d85f
KB
1801
1802wxFileHistory::wxFileHistory(int maxFiles)
1803{
0fb67cd1
VZ
1804 m_fileMaxFiles = maxFiles;
1805 m_fileHistoryN = 0;
50920146 1806 m_fileHistory = new wxChar *[m_fileMaxFiles];
c801d85f
KB
1807}
1808
0fb67cd1 1809wxFileHistory::~wxFileHistory()
c801d85f 1810{
0fb67cd1
VZ
1811 int i;
1812 for (i = 0; i < m_fileHistoryN; i++)
1813 delete[] m_fileHistory[i];
1814 delete[] m_fileHistory;
c801d85f
KB
1815}
1816
1817// File history management
1818void wxFileHistory::AddFileToHistory(const wxString& file)
1819{
0fb67cd1
VZ
1820 int i;
1821 // Check we don't already have this file
1822 for (i = 0; i < m_fileHistoryN; i++)
7f555861 1823 {
0fb67cd1
VZ
1824 if (m_fileHistory[i] && wxString(m_fileHistory[i]) == file)
1825 return;
7f555861 1826 }
0fb67cd1
VZ
1827
1828 // Add to the project file history:
1829 // Move existing files (if any) down so we can insert file at beginning.
1830
1831 // First delete filename that has popped off the end of the array (if any)
1832 if (m_fileHistoryN == m_fileMaxFiles)
1833 {
1834 delete[] m_fileHistory[m_fileMaxFiles-1];
50920146 1835 m_fileHistory[m_fileMaxFiles-1] = (wxChar *) NULL;
c801d85f 1836 }
0fb67cd1
VZ
1837 if (m_fileHistoryN < m_fileMaxFiles)
1838 {
1839 wxNode* node = m_fileMenus.First();
1840 while (node)
1841 {
1842 wxMenu* menu = (wxMenu*) node->Data();
1843 if (m_fileHistoryN == 0)
1844 menu->AppendSeparator();
1845 menu->Append(wxID_FILE1+m_fileHistoryN, _("[EMPTY]"));
1846 node = node->Next();
1847 }
1848 m_fileHistoryN ++;
1849 }
1850 // Shuffle filenames down
1851 for (i = (m_fileHistoryN-1); i > 0; i--)
1852 {
1853 m_fileHistory[i] = m_fileHistory[i-1];
1854 }
1855 m_fileHistory[0] = copystring(file);
1856
1857 for (i = 0; i < m_fileHistoryN; i++)
1858 if (m_fileHistory[i])
1859 {
1860 wxString buf;
50920146 1861 buf.Printf(_T("&%d %s"), i+1, m_fileHistory[i]);
0fb67cd1
VZ
1862 wxNode* node = m_fileMenus.First();
1863 while (node)
1864 {
1865 wxMenu* menu = (wxMenu*) node->Data();
1866 menu->SetLabel(wxID_FILE1+i, buf);
1867 node = node->Next();
1868 }
1869 }
c801d85f
KB
1870}
1871
1872wxString wxFileHistory::GetHistoryFile(int i) const
1873{
0fb67cd1
VZ
1874 if (i < m_fileHistoryN)
1875 return wxString(m_fileHistory[i]);
1876 else
1877 return wxString("");
c801d85f
KB
1878}
1879
7f555861 1880void wxFileHistory::UseMenu(wxMenu *menu)
c801d85f 1881{
0fb67cd1
VZ
1882 if (!m_fileMenus.Member(menu))
1883 m_fileMenus.Append(menu);
c801d85f
KB
1884}
1885
7f555861
JS
1886void wxFileHistory::RemoveMenu(wxMenu *menu)
1887{
0fb67cd1 1888 m_fileMenus.DeleteObject(menu);
7f555861
JS
1889}
1890
702ca7c0 1891#if wxUSE_CONFIG
7f555861 1892void wxFileHistory::Load(wxConfigBase& config)
c801d85f 1893{
0fb67cd1
VZ
1894 m_fileHistoryN = 0;
1895 wxString buf;
50920146 1896 buf.Printf(_T("file%d"), m_fileHistoryN+1);
0fb67cd1 1897 wxString historyFile;
d0bdc3ca 1898 while ((m_fileHistoryN <= m_fileMaxFiles) && config.Read(buf, &historyFile) && (historyFile != _T("")))
0fb67cd1 1899 {
50920146 1900 m_fileHistory[m_fileHistoryN] = copystring((const wxChar*) historyFile);
0fb67cd1 1901 m_fileHistoryN ++;
50920146 1902 buf.Printf(_T("file%d"), m_fileHistoryN+1);
0fb67cd1
VZ
1903 historyFile = "";
1904 }
1905 AddFilesToMenu();
c801d85f
KB
1906}
1907
7f555861 1908void wxFileHistory::Save(wxConfigBase& config)
c801d85f 1909{
0fb67cd1
VZ
1910 int i;
1911 for (i = 0; i < m_fileHistoryN; i++)
1912 {
1913 wxString buf;
50920146 1914 buf.Printf(_T("file%d"), i+1);
0fb67cd1
VZ
1915 config.Write(buf, wxString(m_fileHistory[i]));
1916 }
7f555861 1917}
0fb67cd1 1918#endif // wxUSE_CONFIG
7f555861
JS
1919
1920void wxFileHistory::AddFilesToMenu()
1921{
1922 if (m_fileHistoryN > 0)
1923 {
1924 wxNode* node = m_fileMenus.First();
1925 while (node)
1926 {
1927 wxMenu* menu = (wxMenu*) node->Data();
1928 menu->AppendSeparator();
1929 int i;
1930 for (i = 0; i < m_fileHistoryN; i++)
1931 {
1932 if (m_fileHistory[i])
1933 {
1934 wxString buf;
50920146 1935 buf.Printf(_T("&%d %s"), i+1, m_fileHistory[i]);
7f555861
JS
1936 menu->Append(wxID_FILE1+i, buf);
1937 }
1938 }
1939 node = node->Next();
1940 }
1941 }
1942}
1943
1944void wxFileHistory::AddFilesToMenu(wxMenu* menu)
1945{
1946 if (m_fileHistoryN > 0)
1947 {
1948 menu->AppendSeparator();
1949 int i;
1950 for (i = 0; i < m_fileHistoryN; i++)
1951 {
1952 if (m_fileHistory[i])
1953 {
1954 wxString buf;
50920146 1955 buf.Printf(_T("&%d %s"), i+1, m_fileHistory[i]);
7f555861
JS
1956 menu->Append(wxID_FILE1+i, buf);
1957 }
1958 }
1959 }
c801d85f
KB
1960}
1961
0fb67cd1
VZ
1962// ----------------------------------------------------------------------------
1963// Permits compatibility with existing file formats and functions that
1964// manipulate files directly
1965// ----------------------------------------------------------------------------
c801d85f 1966
a533f5c1 1967#if wxUSE_STD_IOSTREAM
c801d85f
KB
1968bool wxTransferFileToStream(const wxString& filename, ostream& stream)
1969{
0fb67cd1
VZ
1970 FILE *fd1;
1971 int ch;
c801d85f 1972
50920146 1973 if ((fd1 = fopen (filename.fn_str(), "rb")) == NULL)
0fb67cd1 1974 return FALSE;
c801d85f 1975
0fb67cd1
VZ
1976 while ((ch = getc (fd1)) != EOF)
1977 stream << (unsigned char)ch;
c801d85f 1978
0fb67cd1
VZ
1979 fclose (fd1);
1980 return TRUE;
c801d85f
KB
1981}
1982
1983bool wxTransferStreamToFile(istream& stream, const wxString& filename)
1984{
0fb67cd1
VZ
1985 FILE *fd1;
1986 int ch;
c801d85f 1987
50920146 1988 if ((fd1 = fopen (filename.fn_str(), "wb")) == NULL)
c801d85f 1989 {
0fb67cd1 1990 return FALSE;
c801d85f
KB
1991 }
1992
0fb67cd1
VZ
1993 while (!stream.eof())
1994 {
1995 ch = stream.get();
1996 if (!stream.eof())
1997 putc (ch, fd1);
1998 }
1999 fclose (fd1);
2000 return TRUE;
c801d85f 2001}
a533f5c1 2002#endif
c801d85f 2003
0fb67cd1
VZ
2004#endif // wxUSE_DOC_VIEW_ARCHITECTURE
2005