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