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