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