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