]> git.saurik.com Git - wxWidgets.git/blobdiff - src/common/docview.cpp
warning (in Unicode only) fix
[wxWidgets.git] / src / common / docview.cpp
index a88869b84fd01fff1ee10c2f3be0e9ff220bfc54..8714a27a8535c0bccde4b0b1e88caf38592dfdb5 100644 (file)
@@ -101,6 +101,7 @@ IMPLEMENT_DYNAMIC_CLASS(wxFileHistory, wxObject)
 // ----------------------------------------------------------------------------
 
 static inline wxString FindExtension(const wxChar *path);
+static wxWindow* wxFindSuitableParent(void);
 
 // ----------------------------------------------------------------------------
 // local constants
@@ -274,8 +275,6 @@ bool wxDocument::SaveAs()
     SetFilename(fileName);
     SetTitle(wxFileNameFromPath(fileName));
 
-    GetDocumentManager()->AddFileToHistory(fileName);
-
     // Notify the views that the filename has changed
     wxNode *node = m_documentViews.GetFirst();
     while (node)
@@ -285,7 +284,22 @@ bool wxDocument::SaveAs()
         node = node->GetNext();
     }
 
-    return OnSaveDocument(m_documentFile);
+    // Files that were not saved correctly are not added to the FileHistory.
+    if (!OnSaveDocument(m_documentFile))
+        return FALSE;
+
+   // A file that doesn't use the default extension of its document template cannot be opened 
+   // via the FileHistory, so we do not add it.
+   if (docTemplate->FileMatchesTemplate(fileName))
+   {
+       GetDocumentManager()->AddFileToHistory(fileName);
+   }
+   else
+   {
+       // The user will probably not be able to open the file again, so
+       // we could warn about the wrong file-extension here.
+   }
+   return TRUE;
 }
 
 bool wxDocument::OnSaveDocument(const wxString& file)
@@ -774,6 +788,24 @@ wxDocManager::~wxDocManager()
     sm_docManager = (wxDocManager*) NULL;
 }
 
+// closes the specified document
+bool wxDocManager::CloseDocument(wxDocument* doc, bool force)
+{
+    if (doc->Close() || force)
+    {
+        // Implicitly deletes the document when
+        // the last view is deleted
+        doc->DeleteAllViews();
+
+        // Check we're really deleted
+        if (m_docs.Member(doc))
+            delete doc;
+        
+        return TRUE;
+    }
+    return FALSE;
+}
+
 bool wxDocManager::CloseDocuments(bool force)
 {
     wxNode *node = m_docs.GetFirst();
@@ -781,18 +813,10 @@ bool wxDocManager::CloseDocuments(bool force)
     {
         wxDocument *doc = (wxDocument *)node->GetData();
         wxNode *next = node->GetNext();
-
-        if (!doc->Close() && !force)
+        
+        if (!CloseDocument(doc, force))
             return FALSE;
 
-        // Implicitly deletes the document when the last
-        // view is removed (deleted)
-        doc->DeleteAllViews();
-
-        // Check document is deleted
-        if (m_docs.Member(doc))
-            delete doc;
-
         // This assumes that documents are not connected in
         // any way, i.e. deleting one document does NOT
         // delete another.
@@ -940,22 +964,26 @@ void wxDocManager::OnPreview(wxCommandEvent& WXUNUSED(event))
 #endif // wxUSE_PRINTING_ARCHITECTURE
 }
 
-void wxDocManager::OnUndo(wxCommandEvent& WXUNUSED(event))
+void wxDocManager::OnUndo(wxCommandEvent& event)
 {
     wxDocument *doc = GetCurrentDocument();
     if (!doc)
         return;
     if (doc->GetCommandProcessor())
         doc->GetCommandProcessor()->Undo();
+    else
+        event.Skip();
 }
 
-void wxDocManager::OnRedo(wxCommandEvent& WXUNUSED(event))
+void wxDocManager::OnRedo(wxCommandEvent& event)
 {
     wxDocument *doc = GetCurrentDocument();
     if (!doc)
         return;
     if (doc->GetCommandProcessor())
         doc->GetCommandProcessor()->Redo();
+    else
+        event.Skip();
 }
 
 // Handlers for UI update commands
@@ -997,17 +1025,29 @@ void wxDocManager::OnUpdateFileSaveAs(wxUpdateUIEvent& event)
 void wxDocManager::OnUpdateUndo(wxUpdateUIEvent& event)
 {
     wxDocument *doc = GetCurrentDocument();
-    event.Enable( (doc && doc->GetCommandProcessor() && doc->GetCommandProcessor()->CanUndo()) );
-    if (doc && doc->GetCommandProcessor())
+    if (!doc)
+        event.Enable(FALSE);
+    else if (!doc->GetCommandProcessor())
+        event.Skip();
+    else
+    {
+        event.Enable( doc->GetCommandProcessor()->CanUndo() );
         doc->GetCommandProcessor()->SetMenuStrings();
+    }
 }
 
 void wxDocManager::OnUpdateRedo(wxUpdateUIEvent& event)
 {
     wxDocument *doc = GetCurrentDocument();
-    event.Enable( (doc && doc->GetCommandProcessor() && doc->GetCommandProcessor()->CanRedo()) );
-    if (doc && doc->GetCommandProcessor())
+    if (!doc)
+        event.Enable(FALSE);
+    else if (!doc->GetCommandProcessor())
+        event.Skip();
+    else
+    {
+        event.Enable( doc->GetCommandProcessor()->CanRedo() );
         doc->GetCommandProcessor()->SetMenuStrings();
+    }
 }
 
 void wxDocManager::OnUpdatePrint(wxUpdateUIEvent& event)
@@ -1070,27 +1110,15 @@ wxDocument *wxDocManager::CreateDocument(const wxString& path, long flags)
         delete[] templates;
         return (wxDocument *) NULL;
     }
+    
+    wxDocument* docToClose = NULL;
 
     // If we've reached the max number of docs, close the
     // first one.
     if ( (int)GetDocuments().GetCount() >= m_maxDocsOpen )
     {
         wxDocument *doc = (wxDocument *)GetDocuments().GetFirst()->GetData();
-        if (doc->Close())
-        {
-            // Implicitly deletes the document when
-            // the last view is deleted
-            doc->DeleteAllViews();
-
-            // Check we're really deleted
-            if (m_docs.Member(doc))
-                delete doc;
-        }
-        else
-        {
-            delete[] templates;
-            return (wxDocument *) NULL;
-        }
+        docToClose = doc;
     }
 
     // New document: user chooses a template, unless there's only one.
@@ -1098,9 +1126,19 @@ wxDocument *wxDocManager::CreateDocument(const wxString& path, long flags)
     {
         if (n == 1)
         {
+            if (docToClose)
+            {
+                if (!CloseDocument(docToClose, FALSE))
+                {
+                    delete[] templates;
+                    return NULL;
+                }
+            }
+            
             wxDocTemplate *temp = templates[0];
             delete[] templates;
             wxDocument *newDoc = temp->CreateDocument(path, flags);
+            
             if (newDoc)
             {
                 newDoc->SetDocumentName(temp->GetDocumentName());
@@ -1114,7 +1152,16 @@ wxDocument *wxDocManager::CreateDocument(const wxString& path, long flags)
         delete[] templates;
         if (temp)
         {
+            if (docToClose)
+            {
+                if (!CloseDocument(docToClose, FALSE))
+                {
+                    return NULL;
+                }
+            }
+            
             wxDocument *newDoc = temp->CreateDocument(path, flags);
+
             if (newDoc)
             {
                 newDoc->SetDocumentName(temp->GetDocumentName());
@@ -1135,7 +1182,17 @@ wxDocument *wxDocManager::CreateDocument(const wxString& path, long flags)
         path2 = path;
 
     if (flags & wxDOC_SILENT)
+    {
         temp = FindTemplateForPath(path2);
+        if (!temp)
+        {
+            // Since we do not add files with non-default extensions to the FileHistory this 
+            // can only happen if the application changes the allowed templates in runtime.
+            (void)wxMessageBox(_("Sorry, the format for this file is unknown."),
+                                _("Open File"), 
+                               wxOK | wxICON_EXCLAMATION, wxFindSuitableParent());
+        }
+    }
     else
         temp = SelectDocumentPath(templates, n, path2, flags);
 
@@ -1143,6 +1200,14 @@ wxDocument *wxDocManager::CreateDocument(const wxString& path, long flags)
 
     if (temp)
     {
+        if (docToClose)
+        {
+            if (!CloseDocument(docToClose, FALSE))
+            {
+                return NULL;
+            }
+        }
+        
         wxDocument *newDoc = temp->CreateDocument(path2, flags);
         if (newDoc)
         {
@@ -1154,7 +1219,11 @@ wxDocument *wxDocManager::CreateDocument(const wxString& path, long flags)
                 // delete newDoc; // Implicitly deleted by DeleteAllViews
                 return (wxDocument *) NULL;
             }
-            AddFileToHistory(path2);
+            // A file that doesn't use the default extension of its document
+            // template cannot be opened via the FileHistory, so we do not
+            // add it.
+            if (temp->FileMatchesTemplate(path2))
+                AddFileToHistory(path2);
         }
         return newDoc;
     }
@@ -1321,12 +1390,9 @@ void wxDocManager::FileHistoryAddFilesToMenu()
         m_fileHistory->AddFilesToMenu();
 }
 
-size_t wxDocManager::GetNoHistoryFiles() const
+size_t wxDocManager::GetHistoryFilesCount() const
 {
-    if (m_fileHistory)
-        return m_fileHistory->GetNoHistoryFiles();
-    else
-        return 0;
+    return m_fileHistory ? m_fileHistory->GetCount() : 0;
 }
 
 
@@ -1372,9 +1438,8 @@ static wxWindow* wxFindSuitableParent()
 }
 
 // Prompts user to open a file, using file specs in templates.
-// How to implement in wxWindows? Must extend the file selector
-// dialog or implement own; OR match the extension to the
-// template extension.
+// Must extend the file selector dialog or implement own; OR
+// match the extension to the template extension.
 
 wxDocTemplate *wxDocManager::SelectDocumentPath(wxDocTemplate **templates,
 #if defined(__WXMSW__) || defined(__WXGTK__) || defined(__WXMAC__)
@@ -1447,6 +1512,14 @@ wxDocTemplate *wxDocManager::SelectDocumentPath(wxDocTemplate **templates,
             theTemplate = templates[FilterIndex];
         if ( !theTemplate )
             theTemplate = FindTemplateForPath(path);
+        if ( !theTemplate )
+        {
+            // Since we do not add files with non-default extensions to the FileHistory this 
+            // can only happen if the application changes the allowed templates in runtime.
+            (void)wxMessageBox(_("Sorry, the format for this file is unknown."),
+                                _("Open File"), 
+                                wxOK | wxICON_EXCLAMATION, wxFindSuitableParent());
+        }
     }
     else
     {
@@ -1801,7 +1874,14 @@ void wxDocParentFrame::OnMRUFile(wxCommandEvent& event)
         if ( wxFile::Exists(filename) )
         {
             // try to open it
-            (void)m_docManager->CreateDocument(filename, wxDOC_SILENT);
+            if (!m_docManager->CreateDocument(filename, wxDOC_SILENT))
+            {
+                // remove the file from the MRU list. The user should already be notified.
+                m_docManager->RemoveFileFromHistory(n);
+                
+                wxLogError(_("The file '%s' couldn't be opened.\nIt has been removed from the most recently used files list."),
+                       filename.c_str());
+            }
         }
         else
         {
@@ -1908,6 +1988,18 @@ void wxDocPrintout::GetPageInfo(int *minPage, int *maxPage, int *selPageFrom, in
 // File history processor
 // ----------------------------------------------------------------------------
 
+static inline wxChar* MYcopystring(const wxString& s)
+{
+    wxChar* copy = new wxChar[s.length() + 1];
+    return wxStrcpy(copy, s.c_str());
+}
+
+static inline wxChar* MYcopystring(const wxChar* s)
+{
+    wxChar* copy = new wxChar[wxStrlen(s) + 1];
+    return wxStrcpy(copy, s);
+}
+
 wxFileHistory::wxFileHistory(size_t maxFiles, wxWindowID idBase)
 {
     m_fileMaxFiles = maxFiles;
@@ -1932,7 +2024,14 @@ void wxFileHistory::AddFileToHistory(const wxString& file)
     // Check we don't already have this file
     for (i = 0; i < m_fileHistoryN; i++)
     {
-        if ( m_fileHistory[i] && (file == m_fileHistory[i]) )
+#if defined( __WXMSW__ ) // Add any other OSes with case insensitive file names
+        wxString testString;
+        if ( m_fileHistory[i] )
+            testString = m_fileHistory[i];
+        if ( m_fileHistory[i] && ( file.Lower() == testString.Lower() ) )
+#else
+        if ( m_fileHistory[i] && ( file == m_fileHistory[i] ) )
+#endif
         {
             // we do have it, move it to the top of the history
             RemoveFileFromHistory (i);
@@ -1971,7 +2070,7 @@ void wxFileHistory::AddFileToHistory(const wxString& file)
     {
         m_fileHistory[i] = m_fileHistory[i-1];
     }
-    m_fileHistory[0] = copystring(file);
+    m_fileHistory[0] = MYcopystring(file);
 
     // this is the directory of the last opened file
     wxString pathCurrent;
@@ -2028,7 +2127,6 @@ void wxFileHistory::RemoveFileFromHistory(size_t i)
     {
          wxMenu* menu = (wxMenu*) node->GetData();
 
-
          // shuffle filenames up
          wxString buf;
          for ( j = i; j < m_fileHistoryN - 1; j++ )
@@ -2097,13 +2195,13 @@ void wxFileHistory::Load(wxConfigBase& config)
 {
     m_fileHistoryN = 0;
     wxString buf;
-    buf.Printf(wxT("file%d"), m_fileHistoryN+1);
+    buf.Printf(wxT("file%d"), (int)m_fileHistoryN+1);
     wxString historyFile;
     while ((m_fileHistoryN < m_fileMaxFiles) && config.Read(buf, &historyFile) && (historyFile != wxT("")))
     {
-        m_fileHistory[m_fileHistoryN] = copystring((const wxChar*) historyFile);
+        m_fileHistory[m_fileHistoryN] = MYcopystring((const wxChar*) historyFile);
         m_fileHistoryN ++;
-        buf.Printf(wxT("file%d"), m_fileHistoryN+1);
+        buf.Printf(wxT("file%d"), (int)m_fileHistoryN+1);
         historyFile = wxT("");
     }
     AddFilesToMenu();
@@ -2112,11 +2210,14 @@ void wxFileHistory::Load(wxConfigBase& config)
 void wxFileHistory::Save(wxConfigBase& config)
 {
     size_t i;
-    for (i = 0; i < m_fileHistoryN; i++)
+    for (i = 0; i < m_fileMaxFiles; i++)
     {
         wxString buf;
-        buf.Printf(wxT("file%d"), i+1);
-        config.Write(buf, wxString(m_fileHistory[i]));
+        buf.Printf(wxT("file%d"), (int)i+1);
+        if (i < m_fileHistoryN)
+            config.Write(buf, wxString(m_fileHistory[i]));
+        else
+            config.Write(buf, wxEmptyString);            
     }
 }
 #endif // wxUSE_CONFIG