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