1 ///////////////////////////////////////////////////////////////////////////// 
   3 // Purpose:     Document/view classes 
   4 // Author:      Julian Smart 
   8 // Copyright:   (c) Julian Smart and Markus Holzem 
   9 // Licence:     wxWindows licence 
  10 ///////////////////////////////////////////////////////////////////////////// 
  12 // ============================================================================ 
  14 // ============================================================================ 
  16 // ---------------------------------------------------------------------------- 
  18 // ---------------------------------------------------------------------------- 
  21     #pragma implementation "docview.h" 
  24 // For compilers that support precompilation, includes "wx.h". 
  25 #include "wx/wxprec.h" 
  31 #if wxUSE_DOC_VIEW_ARCHITECTURE 
  34     #include "wx/string.h" 
  38     #include "wx/dialog.h" 
  41     #include "wx/filedlg.h" 
  50 #if wxUSE_PRINTING_ARCHITECTURE 
  51   #include "wx/prntbase.h" 
  52   #include "wx/printdlg.h" 
  55 #include "wx/msgdlg.h" 
  56 #include "wx/choicdlg.h" 
  57 #include "wx/docview.h" 
  58 #include "wx/confbase.h" 
  64 #if wxUSE_STD_IOSTREAM 
  65   #include "wx/ioswrap.h" 
  72   #include "wx/wfstream.h" 
  75 // ---------------------------------------------------------------------------- 
  77 // ---------------------------------------------------------------------------- 
  79 #if !USE_SHARED_LIBRARY 
  80     IMPLEMENT_ABSTRACT_CLASS(wxDocument
, wxEvtHandler
) 
  81     IMPLEMENT_ABSTRACT_CLASS(wxView
, wxEvtHandler
) 
  82     IMPLEMENT_ABSTRACT_CLASS(wxDocTemplate
, wxObject
) 
  83     IMPLEMENT_DYNAMIC_CLASS(wxDocManager
, wxEvtHandler
) 
  84     IMPLEMENT_CLASS(wxDocChildFrame
, wxFrame
) 
  85     IMPLEMENT_CLASS(wxDocParentFrame
, wxFrame
) 
  87     #if wxUSE_PRINTING_ARCHITECTURE 
  88         IMPLEMENT_DYNAMIC_CLASS(wxDocPrintout
, wxPrintout
) 
  91     IMPLEMENT_CLASS(wxCommand
, wxObject
) 
  92     IMPLEMENT_DYNAMIC_CLASS(wxCommandProcessor
, wxObject
) 
  93     IMPLEMENT_DYNAMIC_CLASS(wxFileHistory
, wxObject
) 
  96 // ---------------------------------------------------------------------------- 
  97 // function prototypes 
  98 // ---------------------------------------------------------------------------- 
 100 static inline wxString 
FindExtension(const wxChar 
*path
); 
 102 // ---------------------------------------------------------------------------- 
 104 // ---------------------------------------------------------------------------- 
 106 static const wxChar 
*s_MRUEntryFormat 
= wxT("&%d %s"); 
 108 // ============================================================================ 
 110 // ============================================================================ 
 112 // ---------------------------------------------------------------------------- 
 114 // ---------------------------------------------------------------------------- 
 116 static wxString 
FindExtension(const wxChar 
*path
) 
 119     wxSplitPath(path
, NULL
, NULL
, &ext
); 
 121     // VZ: extensions are considered not case sensitive - is this really a good 
 123     return ext
.MakeLower(); 
 126 // ---------------------------------------------------------------------------- 
 127 // Definition of wxDocument 
 128 // ---------------------------------------------------------------------------- 
 130 wxDocument::wxDocument(wxDocument 
*parent
) 
 132     m_documentModified 
= FALSE
; 
 133     m_documentParent 
= parent
; 
 134     m_documentTemplate 
= (wxDocTemplate 
*) NULL
; 
 138 bool wxDocument::DeleteContents() 
 143 wxDocument::~wxDocument() 
 147     if (m_commandProcessor
) 
 148         delete m_commandProcessor
; 
 150     GetDocumentManager()->RemoveDocument(this); 
 152     // Not safe to do here, since it'll invoke virtual view functions 
 153     // expecting to see valid derived objects: and by the time we get here, 
 154     // we've called destructors higher up. 
 158 bool wxDocument::Close() 
 160     if (OnSaveModified()) 
 161         return OnCloseDocument(); 
 166 bool wxDocument::OnCloseDocument() 
 173 // Note that this implicitly deletes the document when the last view is 
 175 bool wxDocument::DeleteAllViews() 
 177     wxNode 
*node 
= m_documentViews
.First(); 
 180         wxView 
*view 
= (wxView 
*)node
->Data(); 
 184         wxNode 
*next 
= node
->Next(); 
 186         delete view
; // Deletes node implicitly 
 192 wxView 
*wxDocument::GetFirstView() const 
 194     if (m_documentViews
.Number() == 0) 
 195         return (wxView 
*) NULL
; 
 196     return (wxView 
*)m_documentViews
.First()->Data(); 
 199 wxDocManager 
*wxDocument::GetDocumentManager() const 
 201     return m_documentTemplate
->GetDocumentManager(); 
 204 bool wxDocument::OnNewDocument() 
 206     if (!OnSaveModified()) 
 209     if (OnCloseDocument()==FALSE
) return FALSE
; 
 212     SetDocumentSaved(FALSE
); 
 215     GetDocumentManager()->MakeDefaultName(name
); 
 217     SetFilename(name
, TRUE
); 
 222 bool wxDocument::Save() 
 226     if (!IsModified()) return TRUE
; 
 227     if (m_documentFile 
== wxT("") || !m_savedYet
) 
 230         ret 
= OnSaveDocument(m_documentFile
); 
 232         SetDocumentSaved(TRUE
); 
 236 bool wxDocument::SaveAs() 
 238     wxDocTemplate 
*docTemplate 
= GetDocumentTemplate(); 
 242     wxString tmp 
= wxFileSelector(_("Save as"), 
 243             docTemplate
->GetDirectory(), 
 245             docTemplate
->GetDefaultExtension(), 
 246             docTemplate
->GetFileFilter(), 
 247             wxSAVE 
| wxOVERWRITE_PROMPT
, 
 248             GetDocumentWindow()); 
 253     wxString 
fileName(tmp
); 
 254     wxString path
, name
, ext
; 
 255     wxSplitPath(fileName
, & path
, & name
, & ext
); 
 257     if (ext
.IsEmpty() || ext 
== wxT("")) 
 260         fileName 
+= docTemplate
->GetDefaultExtension(); 
 263     SetFilename(fileName
); 
 264     SetTitle(wxFileNameFromPath(fileName
)); 
 266     GetDocumentManager()->AddFileToHistory(fileName
); 
 268     // Notify the views that the filename has changed 
 269     wxNode 
*node 
= m_documentViews
.First(); 
 272         wxView 
*view 
= (wxView 
*)node
->Data(); 
 273         view
->OnChangeFilename(); 
 277     return OnSaveDocument(m_documentFile
); 
 280 bool wxDocument::OnSaveDocument(const wxString
& file
) 
 286     if (wxTheApp
->GetAppName() != wxT("")) 
 287         msgTitle 
= wxTheApp
->GetAppName(); 
 289         msgTitle 
= wxString(_("File error")); 
 291 #if wxUSE_STD_IOSTREAM 
 292     ofstream 
store(wxString(file
.fn_str())); 
 293     if (store
.fail() || store
.bad()) 
 295     wxFileOutputStream 
store(wxString(file
.fn_str())); 
 296     if (store
.LastError() != 0) 
 299         (void)wxMessageBox(_("Sorry, could not open this file for saving."), msgTitle
, wxOK 
| wxICON_EXCLAMATION
, 
 300                            GetDocumentWindow()); 
 304     if (!SaveObject(store
)) 
 306         (void)wxMessageBox(_("Sorry, could not save this file."), msgTitle
, wxOK 
| wxICON_EXCLAMATION
, 
 307                            GetDocumentWindow()); 
 316 bool wxDocument::OnOpenDocument(const wxString
& file
) 
 318     if (!OnSaveModified()) 
 322     if (wxTheApp
->GetAppName() != wxT("")) 
 323         msgTitle 
= wxTheApp
->GetAppName(); 
 325         msgTitle 
= wxString(_("File error")); 
 327 #if wxUSE_STD_IOSTREAM 
 328     ifstream 
store(wxString(file
.fn_str())); 
 329     if (store
.fail() || store
.bad()) 
 331     wxFileInputStream 
store(wxString(file
.fn_str())); 
 332     if (store
.LastError() != 0) 
 335         (void)wxMessageBox(_("Sorry, could not open this file."), msgTitle
, wxOK
|wxICON_EXCLAMATION
, 
 336                            GetDocumentWindow()); 
 339     if (!LoadObject(store
)) 
 341         (void)wxMessageBox(_("Sorry, could not open this file."), msgTitle
, wxOK
|wxICON_EXCLAMATION
, 
 342                            GetDocumentWindow()); 
 345     SetFilename(file
, TRUE
); 
 354 #if wxUSE_STD_IOSTREAM 
 355 istream
& wxDocument::LoadObject(istream
& stream
) 
 357 wxInputStream
& wxDocument::LoadObject(wxInputStream
& stream
) 
 363 #if wxUSE_STD_IOSTREAM 
 364 ostream
& wxDocument::SaveObject(ostream
& stream
) 
 366 wxOutputStream
& wxDocument::SaveObject(wxOutputStream
& stream
) 
 372 bool wxDocument::Revert() 
 378 // Get title, or filename if no title, else unnamed 
 379 bool wxDocument::GetPrintableName(wxString
& buf
) const 
 381     if (m_documentTitle 
!= wxT("")) 
 383         buf 
= m_documentTitle
; 
 386     else if (m_documentFile 
!= wxT("")) 
 388         buf 
= wxFileNameFromPath(m_documentFile
); 
 398 wxWindow 
*wxDocument::GetDocumentWindow() const 
 400     wxView 
*view 
= GetFirstView(); 
 402         return view
->GetFrame(); 
 404         return wxTheApp
->GetTopWindow(); 
 407 wxCommandProcessor 
*wxDocument::OnCreateCommandProcessor() 
 409     return new wxCommandProcessor
; 
 412 // TRUE if safe to close 
 413 bool wxDocument::OnSaveModified() 
 418         GetPrintableName(title
); 
 421         if (wxTheApp
->GetAppName() != wxT("")) 
 422             msgTitle 
= wxTheApp
->GetAppName(); 
 424             msgTitle 
= wxString(_("Warning")); 
 427         prompt
.Printf(_("Do you want to save changes to document %s?"), 
 428                 (const wxChar 
*)title
); 
 429         int res 
= wxMessageBox(prompt
, msgTitle
, 
 430                 wxYES_NO
|wxCANCEL
|wxICON_QUESTION
, 
 431                 GetDocumentWindow()); 
 437         else if (res 
== wxYES
) 
 439         else if (res 
== wxCANCEL
) 
 445 bool wxDocument::Draw(wxDC
& WXUNUSED(context
)) 
 450 bool wxDocument::AddView(wxView 
*view
) 
 452     if (!m_documentViews
.Member(view
)) 
 454         m_documentViews
.Append(view
); 
 460 bool wxDocument::RemoveView(wxView 
*view
) 
 462     (void)m_documentViews
.DeleteObject(view
); 
 467 bool wxDocument::OnCreate(const wxString
& WXUNUSED(path
), long flags
) 
 469     if (GetDocumentTemplate()->CreateView(this, flags
)) 
 475 // Called after a view is added or removed. 
 476 // The default implementation deletes the document if 
 477 // there are no more views. 
 478 void wxDocument::OnChangedViewList() 
 480     if (m_documentViews
.Number() == 0) 
 482         if (OnSaveModified()) 
 489 void wxDocument::UpdateAllViews(wxView 
*sender
, wxObject 
*hint
) 
 491     wxNode 
*node 
= m_documentViews
.First(); 
 494         wxView 
*view 
= (wxView 
*)node
->Data(); 
 495         view
->OnUpdate(sender
, hint
); 
 500 void wxDocument::SetFilename(const wxString
& filename
, bool notifyViews
) 
 502     m_documentFile 
= filename
; 
 505         // Notify the views that the filename has changed 
 506         wxNode 
*node 
= m_documentViews
.First(); 
 509             wxView 
*view 
= (wxView 
*)node
->Data(); 
 510             view
->OnChangeFilename(); 
 516 // ---------------------------------------------------------------------------- 
 518 // ---------------------------------------------------------------------------- 
 523     m_viewDocument 
= (wxDocument
*) NULL
; 
 526     m_viewFrame 
= (wxFrame 
*) NULL
; 
 531 //    GetDocumentManager()->ActivateView(this, FALSE, TRUE); 
 532     m_viewDocument
->RemoveView(this); 
 535 // Extend event processing to search the document's event table 
 536 bool wxView::ProcessEvent(wxEvent
& event
) 
 538     if ( !GetDocument() || !GetDocument()->ProcessEvent(event
) ) 
 539         return wxEvtHandler::ProcessEvent(event
); 
 544 void wxView::OnActivateView(bool WXUNUSED(activate
), wxView 
*WXUNUSED(activeView
), wxView 
*WXUNUSED(deactiveView
)) 
 548 void wxView::OnPrint(wxDC 
*dc
, wxObject 
*WXUNUSED(info
)) 
 553 void wxView::OnUpdate(wxView 
*WXUNUSED(sender
), wxObject 
*WXUNUSED(hint
)) 
 557 void wxView::OnChangeFilename() 
 559     if (GetFrame() && GetDocument()) 
 562         GetDocument()->GetPrintableName(name
); 
 564         GetFrame()->SetTitle(name
); 
 568 void wxView::SetDocument(wxDocument 
*doc
) 
 570     m_viewDocument 
= doc
; 
 575 bool wxView::Close(bool deleteWindow
) 
 577     if (OnClose(deleteWindow
)) 
 583 void wxView::Activate(bool activate
) 
 585     if (GetDocumentManager()) 
 587         OnActivateView(activate
, this, GetDocumentManager()->GetCurrentView()); 
 588         GetDocumentManager()->ActivateView(this, activate
); 
 592 bool wxView::OnClose(bool WXUNUSED(deleteWindow
)) 
 594     return GetDocument() ? GetDocument()->Close() : TRUE
; 
 597 #if wxUSE_PRINTING_ARCHITECTURE 
 598 wxPrintout 
*wxView::OnCreatePrintout() 
 600     return new wxDocPrintout(this); 
 602 #endif // wxUSE_PRINTING_ARCHITECTURE 
 604 // ---------------------------------------------------------------------------- 
 606 // ---------------------------------------------------------------------------- 
 608 wxDocTemplate::wxDocTemplate(wxDocManager 
*manager
, 
 609                              const wxString
& descr
, 
 610                              const wxString
& filter
, 
 613                              const wxString
& docTypeName
, 
 614                              const wxString
& viewTypeName
, 
 615                              wxClassInfo 
*docClassInfo
, 
 616                              wxClassInfo 
*viewClassInfo
, 
 619     m_documentManager 
= manager
; 
 620     m_description 
= descr
; 
 623     m_fileFilter 
= filter
; 
 625     m_docTypeName 
= docTypeName
; 
 626     m_viewTypeName 
= viewTypeName
; 
 627     m_documentManager
->AssociateTemplate(this); 
 629     m_docClassInfo 
= docClassInfo
; 
 630     m_viewClassInfo 
= viewClassInfo
; 
 633 wxDocTemplate::~wxDocTemplate() 
 635     m_documentManager
->DisassociateTemplate(this); 
 638 // Tries to dynamically construct an object of the right class. 
 639 wxDocument 
*wxDocTemplate::CreateDocument(const wxString
& path
, long flags
) 
 642         return (wxDocument 
*) NULL
; 
 643     wxDocument 
*doc 
= (wxDocument 
*)m_docClassInfo
->CreateObject(); 
 644     doc
->SetFilename(path
); 
 645     doc
->SetDocumentTemplate(this); 
 646     GetDocumentManager()->AddDocument(doc
); 
 647     doc
->SetCommandProcessor(doc
->OnCreateCommandProcessor()); 
 649     if (doc
->OnCreate(path
, flags
)) 
 654         return (wxDocument 
*) NULL
; 
 658 wxView 
*wxDocTemplate::CreateView(wxDocument 
*doc
, long flags
) 
 660     if (!m_viewClassInfo
) 
 661         return (wxView 
*) NULL
; 
 662     wxView 
*view 
= (wxView 
*)m_viewClassInfo
->CreateObject(); 
 663     view
->SetDocument(doc
); 
 664     if (view
->OnCreate(doc
, flags
)) 
 671         return (wxView 
*) NULL
; 
 675 // The default (very primitive) format detection: check is the extension is 
 676 // that of the template 
 677 bool wxDocTemplate::FileMatchesTemplate(const wxString
& path
) 
 679     return GetDefaultExtension().IsSameAs(FindExtension(path
)); 
 682 // ---------------------------------------------------------------------------- 
 684 // ---------------------------------------------------------------------------- 
 686 BEGIN_EVENT_TABLE(wxDocManager
, wxEvtHandler
) 
 687     EVT_MENU(wxID_OPEN
, wxDocManager::OnFileOpen
) 
 688     EVT_MENU(wxID_CLOSE
, wxDocManager::OnFileClose
) 
 689     EVT_MENU(wxID_REVERT
, wxDocManager::OnFileRevert
) 
 690     EVT_MENU(wxID_NEW
, wxDocManager::OnFileNew
) 
 691     EVT_MENU(wxID_SAVE
, wxDocManager::OnFileSave
) 
 692     EVT_MENU(wxID_SAVEAS
, wxDocManager::OnFileSaveAs
) 
 693     EVT_MENU(wxID_UNDO
, wxDocManager::OnUndo
) 
 694     EVT_MENU(wxID_REDO
, wxDocManager::OnRedo
) 
 695 #if wxUSE_PRINTING_ARCHITECTURE 
 696     EVT_MENU(wxID_PRINT
, wxDocManager::OnPrint
) 
 697     EVT_MENU(wxID_PRINT_SETUP
, wxDocManager::OnPrintSetup
) 
 698     EVT_MENU(wxID_PREVIEW
, wxDocManager::OnPreview
) 
 702 wxDocManager::wxDocManager(long flags
, bool initialize
) 
 704     m_defaultDocumentNameCounter 
= 1; 
 706     m_currentView 
= (wxView 
*) NULL
; 
 707     m_maxDocsOpen 
= 10000; 
 708     m_fileHistory 
= (wxFileHistory 
*) NULL
; 
 713 wxDocManager::~wxDocManager() 
 717         delete m_fileHistory
; 
 720 bool wxDocManager::Clear(bool force
) 
 722     wxNode 
*node 
= m_docs
.First(); 
 725         wxDocument 
*doc 
= (wxDocument 
*)node
->Data(); 
 726         wxNode 
*next 
= node
->Next(); 
 728         if (!doc
->Close() && !force
) 
 731         // Implicitly deletes the document when the last 
 732         // view is removed (deleted) 
 733         doc
->DeleteAllViews(); 
 735         // Check document is deleted 
 736         if (m_docs
.Member(doc
)) 
 739         // This assumes that documents are not connected in 
 740         // any way, i.e. deleting one document does NOT 
 744     node 
= m_templates
.First(); 
 747         wxDocTemplate 
*templ 
= (wxDocTemplate
*) node
->Data(); 
 748         wxNode
* next 
= node
->Next(); 
 755 bool wxDocManager::Initialize() 
 757     m_fileHistory 
= OnCreateFileHistory(); 
 761 wxFileHistory 
*wxDocManager::OnCreateFileHistory() 
 763     return new wxFileHistory
; 
 766 void wxDocManager::OnFileClose(wxCommandEvent
& WXUNUSED(event
)) 
 768     wxDocument 
*doc 
= GetCurrentDocument(); 
 773         doc
->DeleteAllViews(); 
 774         if (m_docs
.Member(doc
)) 
 779 void wxDocManager::OnFileNew(wxCommandEvent
& WXUNUSED(event
)) 
 781     CreateDocument(wxString(""), wxDOC_NEW
); 
 784 void wxDocManager::OnFileOpen(wxCommandEvent
& WXUNUSED(event
)) 
 786     CreateDocument(wxString(""), 0); 
 789 void wxDocManager::OnFileRevert(wxCommandEvent
& WXUNUSED(event
)) 
 791     wxDocument 
*doc 
= GetCurrentDocument(); 
 797 void wxDocManager::OnFileSave(wxCommandEvent
& WXUNUSED(event
)) 
 799     wxDocument 
*doc 
= GetCurrentDocument(); 
 805 void wxDocManager::OnFileSaveAs(wxCommandEvent
& WXUNUSED(event
)) 
 807     wxDocument 
*doc 
= GetCurrentDocument(); 
 813 void wxDocManager::OnPrint(wxCommandEvent
& WXUNUSED(event
)) 
 815 #if wxUSE_PRINTING_ARCHITECTURE 
 816     wxView 
*view 
= GetCurrentView(); 
 820     wxPrintout 
*printout 
= view
->OnCreatePrintout(); 
 824         printer
.Print(view
->GetFrame(), printout
, TRUE
); 
 828 #endif // wxUSE_PRINTING_ARCHITECTURE 
 831 void wxDocManager::OnPrintSetup(wxCommandEvent
& WXUNUSED(event
)) 
 833 #if wxUSE_PRINTING_ARCHITECTURE 
 834     wxWindow 
*parentWin 
= wxTheApp
->GetTopWindow(); 
 835     wxView 
*view 
= GetCurrentView(); 
 837         parentWin 
= view
->GetFrame(); 
 839     wxPrintDialogData data
; 
 841     wxPrintDialog 
printerDialog(parentWin
, &data
); 
 842     printerDialog
.GetPrintDialogData().SetSetupDialog(TRUE
); 
 843     printerDialog
.ShowModal(); 
 844 #endif // wxUSE_PRINTING_ARCHITECTURE 
 847 void wxDocManager::OnPreview(wxCommandEvent
& WXUNUSED(event
)) 
 849 #if wxUSE_PRINTING_ARCHITECTURE 
 850     wxView 
*view 
= GetCurrentView(); 
 854     wxPrintout 
*printout 
= view
->OnCreatePrintout(); 
 857         // Pass two printout objects: for preview, and possible printing. 
 858         wxPrintPreviewBase 
*preview 
= (wxPrintPreviewBase 
*) NULL
; 
 859         preview 
= new wxPrintPreview(printout
, view
->OnCreatePrintout()); 
 861         wxPreviewFrame 
*frame 
= new wxPreviewFrame(preview
, (wxFrame 
*)wxTheApp
->GetTopWindow(), _("Print Preview"), 
 862                 wxPoint(100, 100), wxSize(600, 650)); 
 863         frame
->Centre(wxBOTH
); 
 867 #endif // wxUSE_PRINTING_ARCHITECTURE 
 870 void wxDocManager::OnUndo(wxCommandEvent
& WXUNUSED(event
)) 
 872     wxDocument 
*doc 
= GetCurrentDocument(); 
 875     if (doc
->GetCommandProcessor()) 
 876         doc
->GetCommandProcessor()->Undo(); 
 879 void wxDocManager::OnRedo(wxCommandEvent
& WXUNUSED(event
)) 
 881     wxDocument 
*doc 
= GetCurrentDocument(); 
 884     if (doc
->GetCommandProcessor()) 
 885         doc
->GetCommandProcessor()->Redo(); 
 888 wxView 
*wxDocManager::GetCurrentView() const 
 891         return m_currentView
; 
 892     if (m_docs
.Number() == 1) 
 894         wxDocument
* doc 
= (wxDocument
*) m_docs
.First()->Data(); 
 895         return doc
->GetFirstView(); 
 897     return (wxView 
*) NULL
; 
 900 // Extend event processing to search the view's event table 
 901 bool wxDocManager::ProcessEvent(wxEvent
& event
) 
 903     wxView
* view 
= GetCurrentView(); 
 906         if (view
->ProcessEvent(event
)) 
 909     return wxEvtHandler::ProcessEvent(event
); 
 912 wxDocument 
*wxDocManager::CreateDocument(const wxString
& path
, long flags
) 
 914     wxDocTemplate 
**templates 
= new wxDocTemplate 
*[m_templates
.Number()]; 
 917     for (i 
= 0; i 
< m_templates
.Number(); i
++) 
 919         wxDocTemplate 
*temp 
= (wxDocTemplate 
*)(m_templates
.Nth(i
)->Data()); 
 920         if (temp
->IsVisible()) 
 929         return (wxDocument 
*) NULL
; 
 932     // If we've reached the max number of docs, close the 
 934     if (GetDocuments().Number() >= m_maxDocsOpen
) 
 936         wxDocument 
*doc 
= (wxDocument 
*)GetDocuments().First()->Data(); 
 939             // Implicitly deletes the document when 
 940             // the last view is deleted 
 941             doc
->DeleteAllViews(); 
 943             // Check we're really deleted 
 944             if (m_docs
.Member(doc
)) 
 948             return (wxDocument 
*) NULL
; 
 951     // New document: user chooses a template, unless there's only one. 
 952     if (flags 
& wxDOC_NEW
) 
 956             wxDocTemplate 
*temp 
= templates
[0]; 
 958             wxDocument 
*newDoc 
= temp
->CreateDocument(path
, flags
); 
 961                 newDoc
->SetDocumentName(temp
->GetDocumentName()); 
 962                 newDoc
->SetDocumentTemplate(temp
); 
 963                 newDoc
->OnNewDocument(); 
 968         wxDocTemplate 
*temp 
= SelectDocumentType(templates
, n
); 
 972             wxDocument 
*newDoc 
= temp
->CreateDocument(path
, flags
); 
 975                 newDoc
->SetDocumentName(temp
->GetDocumentName()); 
 976                 newDoc
->SetDocumentTemplate(temp
); 
 977                 newDoc
->OnNewDocument(); 
 982             return (wxDocument 
*) NULL
; 
 986     wxDocTemplate 
*temp 
= (wxDocTemplate 
*) NULL
; 
 988     wxString 
path2(wxT("")); 
 992     if (flags 
& wxDOC_SILENT
) 
 993         temp 
= FindTemplateForPath(path2
); 
 995         temp 
= SelectDocumentPath(templates
, n
, path2
, flags
); 
1001         wxDocument 
*newDoc 
= temp
->CreateDocument(path2
, flags
); 
1004             newDoc
->SetDocumentName(temp
->GetDocumentName()); 
1005             newDoc
->SetDocumentTemplate(temp
); 
1006             if (!newDoc
->OnOpenDocument(path2
)) 
1009                 return (wxDocument 
*) NULL
; 
1011             AddFileToHistory(path2
); 
1016         return (wxDocument 
*) NULL
; 
1019 wxView 
*wxDocManager::CreateView(wxDocument 
*doc
, long flags
) 
1021     wxDocTemplate 
**templates 
= new wxDocTemplate 
*[m_templates
.Number()]; 
1024     for (i 
= 0; i 
< m_templates
.Number(); i
++) 
1026         wxDocTemplate 
*temp 
= (wxDocTemplate 
*)(m_templates
.Nth(i
)->Data()); 
1027         if (temp
->IsVisible()) 
1029             if (temp
->GetDocumentName() == doc
->GetDocumentName()) 
1031                 templates
[n
] = temp
; 
1039         return (wxView 
*) NULL
; 
1043         wxDocTemplate 
*temp 
= templates
[0]; 
1045         wxView 
*view 
= temp
->CreateView(doc
, flags
); 
1047             view
->SetViewName(temp
->GetViewName()); 
1051     wxDocTemplate 
*temp 
= SelectViewType(templates
, n
); 
1055         wxView 
*view 
= temp
->CreateView(doc
, flags
); 
1057             view
->SetViewName(temp
->GetViewName()); 
1061         return (wxView 
*) NULL
; 
1064 // Not yet implemented 
1065 void wxDocManager::DeleteTemplate(wxDocTemplate 
*WXUNUSED(temp
), long WXUNUSED(flags
)) 
1069 // Not yet implemented 
1070 bool wxDocManager::FlushDoc(wxDocument 
*WXUNUSED(doc
)) 
1075 wxDocument 
*wxDocManager::GetCurrentDocument() const 
1078         return m_currentView
->GetDocument(); 
1080         return (wxDocument 
*) NULL
; 
1083 // Make a default document name 
1084 bool wxDocManager::MakeDefaultName(wxString
& name
) 
1086     name
.Printf(_("unnamed%d"), m_defaultDocumentNameCounter
); 
1087     m_defaultDocumentNameCounter
++; 
1092 // Not yet implemented 
1093 wxDocTemplate 
*wxDocManager::MatchTemplate(const wxString
& WXUNUSED(path
)) 
1095     return (wxDocTemplate 
*) NULL
; 
1098 // File history management 
1099 void wxDocManager::AddFileToHistory(const wxString
& file
) 
1102         m_fileHistory
->AddFileToHistory(file
); 
1105 void wxDocManager::RemoveFileFromHistory(int i
) 
1108         m_fileHistory
->RemoveFileFromHistory(i
); 
1111 wxString 
wxDocManager::GetHistoryFile(int i
) const 
1116         histFile 
= m_fileHistory
->GetHistoryFile(i
); 
1121 void wxDocManager::FileHistoryUseMenu(wxMenu 
*menu
) 
1124         m_fileHistory
->UseMenu(menu
); 
1127 void wxDocManager::FileHistoryRemoveMenu(wxMenu 
*menu
) 
1130         m_fileHistory
->RemoveMenu(menu
); 
1134 void wxDocManager::FileHistoryLoad(wxConfigBase
& config
) 
1137         m_fileHistory
->Load(config
); 
1140 void wxDocManager::FileHistorySave(wxConfigBase
& config
) 
1143         m_fileHistory
->Save(config
); 
1147 void wxDocManager::FileHistoryAddFilesToMenu(wxMenu
* menu
) 
1150         m_fileHistory
->AddFilesToMenu(menu
); 
1153 void wxDocManager::FileHistoryAddFilesToMenu() 
1156         m_fileHistory
->AddFilesToMenu(); 
1159 int wxDocManager::GetNoHistoryFiles() const 
1162         return m_fileHistory
->GetNoHistoryFiles(); 
1168 // Find out the document template via matching in the document file format 
1169 // against that of the template 
1170 wxDocTemplate 
*wxDocManager::FindTemplateForPath(const wxString
& path
) 
1172     wxDocTemplate 
*theTemplate 
= (wxDocTemplate 
*) NULL
; 
1174     // Find the template which this extension corresponds to 
1176     for (i 
= 0; i 
< m_templates
.Number(); i
++) 
1178         wxDocTemplate 
*temp 
= (wxDocTemplate 
*)m_templates
.Nth(i
)->Data(); 
1179         if ( temp
->FileMatchesTemplate(path
) ) 
1188 // Prompts user to open a file, using file specs in templates. 
1189 // How to implement in wxWindows? Must extend the file selector 
1190 // dialog or implement own; OR match the extension to the 
1191 // template extension. 
1193 wxDocTemplate 
*wxDocManager::SelectDocumentPath(wxDocTemplate 
**templates
, 
1197                                                 int WXUNUSED(noTemplates
), 
1200                                                 long WXUNUSED(flags
), 
1201                                                 bool WXUNUSED(save
)) 
1203     // We can only have multiple filters in Windows 
1208     for (i 
= 0; i 
< noTemplates
; i
++) 
1210         if (templates
[i
]->IsVisible()) 
1212             // add a '|' to separate this filter from the previous one 
1213             if ( !descrBuf
.IsEmpty() ) 
1214                 descrBuf 
<< wxT('|'); 
1216             descrBuf 
<< templates
[i
]->GetDescription() 
1217                 << wxT(" (") << templates
[i
]->GetFileFilter() << wxT(") |") 
1218                 << templates
[i
]->GetFileFilter(); 
1222     wxString descrBuf 
= wxT("*.*"); 
1225     int FilterIndex 
= 0; 
1226     wxString pathTmp 
= wxFileSelectorEx(_("Select a file"), 
1232                                         wxTheApp
->GetTopWindow()); 
1234     if (!pathTmp
.IsEmpty()) 
1236         m_lastDirectory 
= wxPathOnly(pathTmp
); 
1239         wxString theExt 
= FindExtension(path
); 
1241             return (wxDocTemplate 
*) NULL
; 
1243         // This is dodgy in that we're selecting the template on the 
1244         // basis of the file extension, which may not be a standard 
1245         // one. We really want to know exactly which template was 
1246         // chosen by using a more advanced file selector. 
1247         wxDocTemplate 
*theTemplate 
= FindTemplateForPath(path
); 
1249             theTemplate 
= templates
[FilterIndex
]; 
1256         return (wxDocTemplate 
*) NULL
; 
1259     // In all other windowing systems, until we have more advanced 
1260     // file selectors, we must select the document type (template) first, and 
1261     // _then_ pop up the file selector. 
1262     wxDocTemplate 
*temp 
= SelectDocumentType(templates
, noTemplates
); 
1264         return (wxDocTemplate 
*) NULL
; 
1266     wxChar 
*pathTmp 
= wxFileSelector(_("Select a file"), wxT(""), wxT(""), 
1267             temp
->GetDefaultExtension(), 
1268             temp
->GetFileFilter(), 
1269             0, wxTheApp
->GetTopWindow()); 
1277         return (wxDocTemplate 
*) NULL
; 
1281 wxDocTemplate 
*wxDocManager::SelectDocumentType(wxDocTemplate 
**templates
, 
1284     wxChar 
**strings 
= new wxChar 
*[noTemplates
]; 
1285     wxChar 
**data 
= new wxChar 
*[noTemplates
]; 
1288     for (i 
= 0; i 
< noTemplates
; i
++) 
1290         if (templates
[i
]->IsVisible()) 
1292             strings
[n
] = (wxChar 
*)templates
[i
]->m_description
.c_str(); 
1293             data
[n
] = (wxChar 
*)templates
[i
]; 
1301         return (wxDocTemplate 
*) NULL
; 
1305         wxDocTemplate 
*temp 
= (wxDocTemplate 
*)data
[0]; 
1311     wxDocTemplate 
*theTemplate 
= (wxDocTemplate 
*)wxGetSingleChoiceData(_("Select a document template"), _("Templates"), n
, 
1312             strings
, (void **)data
); 
1318 wxDocTemplate 
*wxDocManager::SelectViewType(wxDocTemplate 
**templates
, 
1321     wxChar 
**strings 
= new wxChar 
*[noTemplates
]; 
1322     wxChar 
**data 
= new wxChar 
*[noTemplates
]; 
1325     for (i 
= 0; i 
< noTemplates
; i
++) 
1327         if (templates
[i
]->IsVisible() && (templates
[i
]->GetViewName() != wxT(""))) 
1329             strings
[n
] = (wxChar 
*)templates
[i
]->m_viewTypeName
.c_str(); 
1330             data
[n
] = (wxChar 
*)templates
[i
]; 
1334     wxDocTemplate 
*theTemplate 
= (wxDocTemplate 
*)wxGetSingleChoiceData(_("Select a document view"), _("Views"), n
, 
1335             strings
, (void **)data
); 
1341 void wxDocManager::AssociateTemplate(wxDocTemplate 
*temp
) 
1343     if (!m_templates
.Member(temp
)) 
1344         m_templates
.Append(temp
); 
1347 void wxDocManager::DisassociateTemplate(wxDocTemplate 
*temp
) 
1349     m_templates
.DeleteObject(temp
); 
1352 // Add and remove a document from the manager's list 
1353 void wxDocManager::AddDocument(wxDocument 
*doc
) 
1355     if (!m_docs
.Member(doc
)) 
1359 void wxDocManager::RemoveDocument(wxDocument 
*doc
) 
1361     m_docs
.DeleteObject(doc
); 
1364 // Views or windows should inform the document manager 
1365 // when a view is going in or out of focus 
1366 void wxDocManager::ActivateView(wxView 
*view
, bool activate
, bool WXUNUSED(deleting
)) 
1368     // If we're deactiving, and if we're not actually deleting the view, then 
1369     // don't reset the current view because we may be going to 
1370     // a window without a view. 
1371     // WHAT DID I MEAN BY THAT EXACTLY? 
1375        if (m_currentView == view) 
1376        m_currentView = NULL; 
1382             m_currentView 
= view
; 
1384             m_currentView 
= (wxView 
*) NULL
; 
1388 // ---------------------------------------------------------------------------- 
1389 // Default document child frame 
1390 // ---------------------------------------------------------------------------- 
1392 BEGIN_EVENT_TABLE(wxDocChildFrame
, wxFrame
) 
1393     EVT_ACTIVATE(wxDocChildFrame::OnActivate
) 
1394     EVT_CLOSE(wxDocChildFrame::OnCloseWindow
) 
1397 wxDocChildFrame::wxDocChildFrame(wxDocument 
*doc
, 
1401                                  const wxString
& title
, 
1405                                  const wxString
& name
) 
1406                : wxFrame(frame
, id
, title
, pos
, size
, style
, name
) 
1408     m_childDocument 
= doc
; 
1411         view
->SetFrame(this); 
1414 wxDocChildFrame::~wxDocChildFrame() 
1418 // Extend event processing to search the view's event table 
1419 bool wxDocChildFrame::ProcessEvent(wxEvent
& event
) 
1422         m_childView
->Activate(TRUE
); 
1424     if ( !m_childView 
|| ! m_childView
->ProcessEvent(event
) ) 
1426         // Only hand up to the parent if it's a menu command 
1427         if (!event
.IsKindOf(CLASSINFO(wxCommandEvent
)) || !GetParent() || !GetParent()->ProcessEvent(event
)) 
1428             return wxEvtHandler::ProcessEvent(event
); 
1436 void wxDocChildFrame::OnActivate(wxActivateEvent
& event
) 
1438     wxFrame::OnActivate(event
); 
1441         m_childView
->Activate(event
.GetActive()); 
1444 void wxDocChildFrame::OnCloseWindow(wxCloseEvent
& event
) 
1449         if (!event
.CanVeto()) 
1450             ans 
= TRUE
; // Must delete. 
1452             ans 
= m_childView
->Close(FALSE
); // FALSE means don't delete associated window 
1456             m_childView
->Activate(FALSE
); 
1458             m_childView 
= (wxView 
*) NULL
; 
1459             m_childDocument 
= (wxDocument 
*) NULL
; 
1470 // ---------------------------------------------------------------------------- 
1471 // Default parent frame 
1472 // ---------------------------------------------------------------------------- 
1474 BEGIN_EVENT_TABLE(wxDocParentFrame
, wxFrame
) 
1475     EVT_MENU(wxID_EXIT
, wxDocParentFrame::OnExit
) 
1476     EVT_MENU_RANGE(wxID_FILE1
, wxID_FILE9
, wxDocParentFrame::OnMRUFile
) 
1477     EVT_CLOSE(wxDocParentFrame::OnCloseWindow
) 
1480 wxDocParentFrame::wxDocParentFrame(wxDocManager 
*manager
, 
1483                                    const wxString
& title
, 
1487                                    const wxString
& name
) 
1488                 : wxFrame(frame
, id
, title
, pos
, size
, style
, name
) 
1490     m_docManager 
= manager
; 
1493 void wxDocParentFrame::OnExit(wxCommandEvent
& WXUNUSED(event
)) 
1498 void wxDocParentFrame::OnMRUFile(wxCommandEvent
& event
) 
1500     int n 
= event
.GetSelection() - wxID_FILE1
;  // the index in MRU list 
1501     wxString 
filename(m_docManager
->GetHistoryFile(n
)); 
1502     if ( !filename
.IsEmpty() ) 
1504         // verify that the file exists before doing anything else 
1505         if ( wxFile::Exists(filename
) ) 
1508             (void)m_docManager
->CreateDocument(filename
, wxDOC_SILENT
); 
1512             // remove the bogus filename from the MRU list and notify the user 
1514             m_docManager
->RemoveFileFromHistory(n
); 
1516             wxLogError(_("The file '%s' doesn't exist and couldn't be opened.\n" 
1517                          "It has been also removed from the MRU files list."), 
1523 // Extend event processing to search the view's event table 
1524 bool wxDocParentFrame::ProcessEvent(wxEvent
& event
) 
1526     // Try the document manager, then do default processing 
1527     if (!m_docManager 
|| !m_docManager
->ProcessEvent(event
)) 
1528         return wxEvtHandler::ProcessEvent(event
); 
1533 // Define the behaviour for the frame closing 
1534 // - must delete all frames except for the main one. 
1535 void wxDocParentFrame::OnCloseWindow(wxCloseEvent
& event
) 
1537     if (m_docManager
->Clear(!event
.CanVeto())) 
1545 #if wxUSE_PRINTING_ARCHITECTURE 
1547 wxDocPrintout::wxDocPrintout(wxView 
*view
, const wxString
& title
) 
1550     m_printoutView 
= view
; 
1553 bool wxDocPrintout::OnPrintPage(int WXUNUSED(page
)) 
1557     // Get the logical pixels per inch of screen and printer 
1558     int ppiScreenX
, ppiScreenY
; 
1559     GetPPIScreen(&ppiScreenX
, &ppiScreenY
); 
1560     int ppiPrinterX
, ppiPrinterY
; 
1561     GetPPIPrinter(&ppiPrinterX
, &ppiPrinterY
); 
1563     // This scales the DC so that the printout roughly represents the 
1564     // the screen scaling. The text point size _should_ be the right size 
1565     // but in fact is too small for some reason. This is a detail that will 
1566     // need to be addressed at some point but can be fudged for the 
1568     float scale 
= (float)((float)ppiPrinterX
/(float)ppiScreenX
); 
1570     // Now we have to check in case our real page size is reduced 
1571     // (e.g. because we're drawing to a print preview memory DC) 
1572     int pageWidth
, pageHeight
; 
1574     dc
->GetSize(&w
, &h
); 
1575     GetPageSizePixels(&pageWidth
, &pageHeight
); 
1577     // If printer pageWidth == current DC width, then this doesn't 
1578     // change. But w might be the preview bitmap width, so scale down. 
1579     float overallScale 
= scale 
* (float)(w
/(float)pageWidth
); 
1580     dc
->SetUserScale(overallScale
, overallScale
); 
1584         m_printoutView
->OnDraw(dc
); 
1589 bool wxDocPrintout::HasPage(int pageNum
) 
1591     return (pageNum 
== 1); 
1594 bool wxDocPrintout::OnBeginDocument(int startPage
, int endPage
) 
1596     if (!wxPrintout::OnBeginDocument(startPage
, endPage
)) 
1602 void wxDocPrintout::GetPageInfo(int *minPage
, int *maxPage
, int *selPageFrom
, int *selPageTo
) 
1610 #endif // wxUSE_PRINTING_ARCHITECTURE 
1612 // ---------------------------------------------------------------------------- 
1613 // Command processing framework 
1614 // ---------------------------------------------------------------------------- 
1616 wxCommand::wxCommand(bool canUndoIt
, const wxString
& name
) 
1618     m_canUndo 
= canUndoIt
; 
1619     m_commandName 
= name
; 
1622 wxCommand::~wxCommand() 
1626 // Command processor 
1627 wxCommandProcessor::wxCommandProcessor(int maxCommands
) 
1629     m_maxNoCommands 
= maxCommands
; 
1630     m_currentCommand 
= (wxNode 
*) NULL
; 
1631     m_commandEditMenu 
= (wxMenu 
*) NULL
; 
1634 wxCommandProcessor::~wxCommandProcessor() 
1639 // Pass a command to the processor. The processor calls Do(); 
1640 // if successful, is appended to the command history unless 
1641 // storeIt is FALSE. 
1642 bool wxCommandProcessor::Submit(wxCommand 
*command
, bool storeIt
) 
1644     bool success 
= command
->Do(); 
1645     if (success 
&& storeIt
) 
1647         if (m_commands
.Number() == m_maxNoCommands
) 
1649             wxNode 
*firstNode 
= m_commands
.First(); 
1650             wxCommand 
*firstCommand 
= (wxCommand 
*)firstNode
->Data(); 
1651             delete firstCommand
; 
1655         // Correct a bug: we must chop off the current 'branch' 
1656         // so that we're at the end of the command list. 
1657         if (!m_currentCommand
) 
1661             wxNode 
*node 
= m_currentCommand
->Next(); 
1664                 wxNode 
*next 
= node
->Next(); 
1665                 delete (wxCommand 
*)node
->Data(); 
1671         m_commands
.Append(command
); 
1672         m_currentCommand 
= m_commands
.Last(); 
1678 bool wxCommandProcessor::Undo() 
1680     if (m_currentCommand
) 
1682         wxCommand 
*command 
= (wxCommand 
*)m_currentCommand
->Data(); 
1683         if (command
->CanUndo()) 
1685             bool success 
= command
->Undo(); 
1688                 m_currentCommand 
= m_currentCommand
->Previous(); 
1697 bool wxCommandProcessor::Redo() 
1699     wxCommand 
*redoCommand 
= (wxCommand 
*) NULL
; 
1700     wxNode 
*redoNode 
= (wxNode 
*) NULL
; 
1701     if (m_currentCommand 
&& m_currentCommand
->Next()) 
1703         redoCommand 
= (wxCommand 
*)m_currentCommand
->Next()->Data(); 
1704         redoNode 
= m_currentCommand
->Next(); 
1708         if (m_commands
.Number() > 0) 
1710             redoCommand 
= (wxCommand 
*)m_commands
.First()->Data(); 
1711             redoNode 
= m_commands
.First(); 
1717         bool success 
= redoCommand
->Do(); 
1720             m_currentCommand 
= redoNode
; 
1728 bool wxCommandProcessor::CanUndo() const 
1730     if (m_currentCommand
) 
1731         return ((wxCommand 
*)m_currentCommand
->Data())->CanUndo(); 
1735 bool wxCommandProcessor::CanRedo() const 
1737     if ((m_currentCommand 
!= (wxNode
*) NULL
) && (m_currentCommand
->Next() == (wxNode
*) NULL
)) 
1740     if ((m_currentCommand 
!= (wxNode
*) NULL
) && (m_currentCommand
->Next() != (wxNode
*) NULL
)) 
1743     if ((m_currentCommand 
== (wxNode
*) NULL
) && (m_commands
.Number() > 0)) 
1749 void wxCommandProcessor::Initialize() 
1751     m_currentCommand 
= m_commands
.Last(); 
1755 void wxCommandProcessor::SetMenuStrings() 
1757     if (m_commandEditMenu
) 
1760         if (m_currentCommand
) 
1762             wxCommand 
*command 
= (wxCommand 
*)m_currentCommand
->Data(); 
1763             wxString 
commandName(command
->GetName()); 
1764             if (commandName 
== wxT("")) commandName 
= _("Unnamed command"); 
1765             bool canUndo 
= command
->CanUndo(); 
1767                 buf 
= wxString(_("&Undo ")) + commandName
; 
1769                 buf 
= wxString(_("Can't &Undo ")) + commandName
; 
1771             m_commandEditMenu
->SetLabel(wxID_UNDO
, buf
); 
1772             m_commandEditMenu
->Enable(wxID_UNDO
, canUndo
); 
1774             // We can redo, if we're not at the end of the history. 
1775             if (m_currentCommand
->Next()) 
1777                 wxCommand 
*redoCommand 
= (wxCommand 
*)m_currentCommand
->Next()->Data(); 
1778                 wxString 
redoCommandName(redoCommand
->GetName()); 
1779                 if (redoCommandName 
== wxT("")) redoCommandName 
= _("Unnamed command"); 
1780                 buf 
= wxString(_("&Redo ")) + redoCommandName
; 
1781                 m_commandEditMenu
->SetLabel(wxID_REDO
, buf
); 
1782                 m_commandEditMenu
->Enable(wxID_REDO
, TRUE
); 
1786                 m_commandEditMenu
->SetLabel(wxID_REDO
, _("&Redo")); 
1787                 m_commandEditMenu
->Enable(wxID_REDO
, FALSE
); 
1792             m_commandEditMenu
->SetLabel(wxID_UNDO
, _("&Undo")); 
1793             m_commandEditMenu
->Enable(wxID_UNDO
, FALSE
); 
1795             if (m_commands
.Number() == 0) 
1797                 m_commandEditMenu
->SetLabel(wxID_REDO
, _("&Redo")); 
1798                 m_commandEditMenu
->Enable(wxID_REDO
, FALSE
); 
1802                 // currentCommand is NULL but there are commands: this means that 
1803                 // we've undone to the start of the list, but can redo the first. 
1804                 wxCommand 
*redoCommand 
= (wxCommand 
*)m_commands
.First()->Data(); 
1805                 wxString 
redoCommandName(redoCommand
->GetName()); 
1806                 if (redoCommandName 
== wxT("")) redoCommandName 
= _("Unnamed command"); 
1807                 buf 
= wxString(_("&Redo ")) + redoCommandName
; 
1808                 m_commandEditMenu
->SetLabel(wxID_REDO
, buf
); 
1809                 m_commandEditMenu
->Enable(wxID_REDO
, TRUE
); 
1815 void wxCommandProcessor::ClearCommands() 
1817     wxNode 
*node 
= m_commands
.First(); 
1820         wxCommand 
*command 
= (wxCommand 
*)node
->Data(); 
1823         node 
= m_commands
.First(); 
1825     m_currentCommand 
= (wxNode 
*) NULL
; 
1828 // ---------------------------------------------------------------------------- 
1829 // File history processor 
1830 // ---------------------------------------------------------------------------- 
1832 wxFileHistory::wxFileHistory(int maxFiles
) 
1834     m_fileMaxFiles 
= maxFiles
; 
1836     m_fileHistory 
= new wxChar 
*[m_fileMaxFiles
]; 
1839 wxFileHistory::~wxFileHistory() 
1842     for (i 
= 0; i 
< m_fileHistoryN
; i
++) 
1843         delete[] m_fileHistory
[i
]; 
1844     delete[] m_fileHistory
; 
1847 // File history management 
1848 void wxFileHistory::AddFileToHistory(const wxString
& file
) 
1851     // Check we don't already have this file 
1852     for (i 
= 0; i 
< m_fileHistoryN
; i
++) 
1854         if (m_fileHistory
[i
] && wxString(m_fileHistory
[i
]) == file
) 
1858     // Add to the project file history: 
1859     // Move existing files (if any) down so we can insert file at beginning. 
1861     // First delete filename that has popped off the end of the array (if any) 
1862     if (m_fileHistoryN 
== m_fileMaxFiles
) 
1864         delete[] m_fileHistory
[m_fileMaxFiles
-1]; 
1865         m_fileHistory
[m_fileMaxFiles
-1] = (wxChar 
*) NULL
; 
1867     if (m_fileHistoryN 
< m_fileMaxFiles
) 
1869         wxNode
* node 
= m_fileMenus
.First(); 
1872             wxMenu
* menu 
= (wxMenu
*) node
->Data(); 
1873             if (m_fileHistoryN 
== 0) 
1874                 menu
->AppendSeparator(); 
1875             menu
->Append(wxID_FILE1
+m_fileHistoryN
, _("[EMPTY]")); 
1876             node 
= node
->Next(); 
1880     // Shuffle filenames down 
1881     for (i 
= (m_fileHistoryN
-1); i 
> 0; i
--) 
1883         m_fileHistory
[i
] = m_fileHistory
[i
-1]; 
1885     m_fileHistory
[0] = copystring(file
); 
1887     for (i 
= 0; i 
< m_fileHistoryN
; i
++) 
1888         if (m_fileHistory
[i
]) 
1891             buf
.Printf(s_MRUEntryFormat
, i
+1, m_fileHistory
[i
]); 
1892             wxNode
* node 
= m_fileMenus
.First(); 
1895                 wxMenu
* menu 
= (wxMenu
*) node
->Data(); 
1896                 menu
->SetLabel(wxID_FILE1
+i
, buf
); 
1897                 node 
= node
->Next(); 
1902 void wxFileHistory::RemoveFileFromHistory(int i
) 
1904     wxCHECK_RET( i 
< m_fileHistoryN
, 
1905                  wxT("invalid index in wxFileHistory::RemoveFileFromHistory") ); 
1907     wxNode
* node 
= m_fileMenus
.First(); 
1910         wxMenu
* menu 
= (wxMenu
*) node
->Data(); 
1912         // delete the element from the array (could use memmove() too...) 
1913         delete [] m_fileHistory
[i
]; 
1916         for ( j 
= i
; j 
< m_fileHistoryN 
- 1; j
++ ) 
1918             m_fileHistory
[j
] = m_fileHistory
[j 
+ 1]; 
1921         // shuffle filenames up 
1923         for ( j 
= i
; j 
< m_fileHistoryN 
- 1; j
++ ) 
1925             buf
.Printf(s_MRUEntryFormat
, j 
+ 1, m_fileHistory
[j
]); 
1926             menu
->SetLabel(wxID_FILE1 
+ j
, buf
); 
1929         node 
= node
->Next(); 
1931         // delete the last menu item which is unused now 
1932         menu
->Delete(wxID_FILE1 
+ m_fileHistoryN 
- 1); 
1934         // delete the last separator too if no more files are left 
1935         if ( m_fileHistoryN 
== 1 ) 
1937             wxMenuItemList::Node 
*node 
= menu
->GetMenuItems().GetLast(); 
1940                 wxMenuItem 
*menuItem 
= node
->GetData(); 
1941                 if ( menuItem
->IsSeparator() ) 
1943                     menu
->Delete(menuItem
); 
1945                 //else: should we search backwards for the last separator? 
1947             //else: menu is empty somehow 
1954 wxString 
wxFileHistory::GetHistoryFile(int i
) const 
1957     if ( i 
< m_fileHistoryN 
) 
1959         s 
= m_fileHistory
[i
]; 
1963         wxFAIL_MSG( wxT("bad index in wxFileHistory::GetHistoryFile") ); 
1969 void wxFileHistory::UseMenu(wxMenu 
*menu
) 
1971     if (!m_fileMenus
.Member(menu
)) 
1972         m_fileMenus
.Append(menu
); 
1975 void wxFileHistory::RemoveMenu(wxMenu 
*menu
) 
1977     m_fileMenus
.DeleteObject(menu
); 
1981 void wxFileHistory::Load(wxConfigBase
& config
) 
1985     buf
.Printf(wxT("file%d"), m_fileHistoryN
+1); 
1986     wxString historyFile
; 
1987     while ((m_fileHistoryN 
<= m_fileMaxFiles
) && config
.Read(buf
, &historyFile
) && (historyFile 
!= wxT(""))) 
1989         m_fileHistory
[m_fileHistoryN
] = copystring((const wxChar
*) historyFile
); 
1991         buf
.Printf(wxT("file%d"), m_fileHistoryN
+1); 
1997 void wxFileHistory::Save(wxConfigBase
& config
) 
2000     for (i 
= 0; i 
< m_fileHistoryN
; i
++) 
2003         buf
.Printf(wxT("file%d"), i
+1); 
2004         config
.Write(buf
, wxString(m_fileHistory
[i
])); 
2007 #endif // wxUSE_CONFIG 
2009 void wxFileHistory::AddFilesToMenu() 
2011     if (m_fileHistoryN 
> 0) 
2013         wxNode
* node 
= m_fileMenus
.First(); 
2016             wxMenu
* menu 
= (wxMenu
*) node
->Data(); 
2017             menu
->AppendSeparator(); 
2019             for (i 
= 0; i 
< m_fileHistoryN
; i
++) 
2021                 if (m_fileHistory
[i
]) 
2024                     buf
.Printf(s_MRUEntryFormat
, i
+1, m_fileHistory
[i
]); 
2025                     menu
->Append(wxID_FILE1
+i
, buf
); 
2028             node 
= node
->Next(); 
2033 void wxFileHistory::AddFilesToMenu(wxMenu
* menu
) 
2035     if (m_fileHistoryN 
> 0) 
2037         menu
->AppendSeparator(); 
2039         for (i 
= 0; i 
< m_fileHistoryN
; i
++) 
2041             if (m_fileHistory
[i
]) 
2044                 buf
.Printf(s_MRUEntryFormat
, i
+1, m_fileHistory
[i
]); 
2045                 menu
->Append(wxID_FILE1
+i
, buf
); 
2051 // ---------------------------------------------------------------------------- 
2052 // Permits compatibility with existing file formats and functions that 
2053 // manipulate files directly 
2054 // ---------------------------------------------------------------------------- 
2056 #if wxUSE_STD_IOSTREAM 
2057 bool wxTransferFileToStream(const wxString
& filename
, ostream
& stream
) 
2062     if ((fd1 
= fopen (filename
.fn_str(), "rb")) == NULL
) 
2065     while ((ch 
= getc (fd1
)) != EOF
) 
2066         stream 
<< (unsigned char)ch
; 
2072 bool wxTransferStreamToFile(istream
& stream
, const wxString
& filename
) 
2077     if ((fd1 
= fopen (filename
.fn_str(), "wb")) == NULL
) 
2082     while (!stream
.eof()) 
2093 #endif // wxUSE_DOC_VIEW_ARCHITECTURE