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