]> git.saurik.com Git - wxWidgets.git/blobdiff - src/richtext/richtextbuffer.cpp
Fix crash when accessing clipboard before entering the main loop.
[wxWidgets.git] / src / richtext / richtextbuffer.cpp
index eb0b15d417e825f685cd799d972e91a0f9029ded..eccbc7dfb008026da4907d4278235bbee037102d 100644 (file)
@@ -66,6 +66,7 @@ inline void wxCheckSetFont(wxDC& dc, const wxFont& font)
             font1.GetStyle() == font.GetStyle() &&
             font1.GetWeight() == font.GetWeight() &&
             font1.GetUnderlined() == font.GetUnderlined() &&
+            font1.GetFamily() == font.GetFamily() &&
             font1.GetFaceName() == font.GetFaceName())
             return;
     }
@@ -682,7 +683,7 @@ bool wxRichTextParagraphLayoutBox::Layout(wxDC& dc, const wxRect& rect, int styl
         // Assume this box only contains paragraphs
 
         wxRichTextParagraph* child = wxDynamicCast(node->GetData(), wxRichTextParagraph);
-        wxCHECK_MSG( child, false, _T("Unknown object in layout") );
+        wxCHECK_MSG( child, false, wxT("Unknown object in layout") );
 
         // TODO: what if the child hasn't been laid out (e.g. involved in Undo) but still has 'old' lines
         if ( !forceQuickLayout &&
@@ -1988,6 +1989,23 @@ bool wxRichTextParagraphLayoutBox::CollectStyle(wxTextAttr& currentStyle, const
             }
         }
 
+        if (style.HasFontFamily() && !wxHasStyle(multipleStyleAttributes|absentStyleAttributes, wxTEXT_ATTR_FONT_FAMILY))
+        {
+            if (currentStyle.HasFontFamily())
+            {
+                if (currentStyle.GetFontFamily() != style.GetFontFamily())
+                {
+                    // Clash of style - mark as such
+                    multipleStyleAttributes |= wxTEXT_ATTR_FONT_FAMILY;
+                    currentStyle.SetFlags(currentStyle.GetFlags() & ~wxTEXT_ATTR_FONT_FAMILY);
+                }
+            }
+            else
+            {
+                currentStyle.SetFontFamily(style.GetFontFamily());
+            }
+        }
+
         if (style.HasFontWeight() && !wxHasStyle(multipleStyleAttributes|absentStyleAttributes, wxTEXT_ATTR_FONT_WEIGHT))
         {
             if (currentStyle.HasFontWeight())
@@ -2451,7 +2469,7 @@ bool wxRichTextParagraphLayoutBox::HasCharacterAttributes(const wxRichTextRange&
         {
             // Stop searching if we're beyond the range of interest
             if (para->GetRange().GetStart() > range.GetEnd())
-                return foundCount == matchingCount;
+                return foundCount == matchingCount && foundCount != 0;
 
             if (!para->GetRange().IsOutside(range))
             {
@@ -2460,7 +2478,12 @@ bool wxRichTextParagraphLayoutBox::HasCharacterAttributes(const wxRichTextRange&
                 while (node2)
                 {
                     wxRichTextObject* child = node2->GetData();
-                    if (!child->GetRange().IsOutside(range) && child->IsKindOf(CLASSINFO(wxRichTextPlainText)))
+                    // Allow for empty string if no buffer
+                    wxRichTextRange childRange = child->GetRange();
+                    if (childRange.GetLength() == 0 && GetRange().GetLength() == 1)
+                        childRange.SetEnd(childRange.GetEnd()+1);
+
+                    if (!childRange.IsOutside(range) && child->IsKindOf(CLASSINFO(wxRichTextPlainText)))
                     {
                         foundCount ++;
                         wxTextAttr textAttr = para->GetCombinedAttributes(child->GetAttributes());
@@ -2477,7 +2500,7 @@ bool wxRichTextParagraphLayoutBox::HasCharacterAttributes(const wxRichTextRange&
         node = node->GetNext();
     }
 
-    return foundCount == matchingCount;
+    return foundCount == matchingCount && foundCount != 0;
 }
 
 /// Test if this whole range has paragraph attributes of the specified kind. If any
@@ -2499,7 +2522,7 @@ bool wxRichTextParagraphLayoutBox::HasParagraphAttributes(const wxRichTextRange&
         {
             // Stop searching if we're beyond the range of interest
             if (para->GetRange().GetStart() > range.GetEnd())
-                return foundCount == matchingCount;
+                return foundCount == matchingCount && foundCount != 0;
 
             if (!para->GetRange().IsOutside(range))
             {
@@ -2515,7 +2538,7 @@ bool wxRichTextParagraphLayoutBox::HasParagraphAttributes(const wxRichTextRange&
 
         node = node->GetNext();
     }
-    return foundCount == matchingCount;
+    return foundCount == matchingCount && foundCount != 0;
 }
 
 void wxRichTextParagraphLayoutBox::Clear()
@@ -2836,7 +2859,7 @@ bool wxRichTextParagraphLayoutBox::DoNumberList(const wxRichTextRange& range, co
 
     bool withUndo = ((flags & wxRICHTEXT_SETSTYLE_WITH_UNDO) != 0);
     // bool applyMinimal = ((flags & wxRICHTEXT_SETSTYLE_OPTIMIZE) != 0);
-#ifdef __WXDEBUG__
+#if wxDEBUG_LEVEL
     bool specifyLevel = ((flags & wxRICHTEXT_SETSTYLE_SPECIFY_LEVEL) != 0);
 #endif
 
@@ -3155,7 +3178,7 @@ bool wxRichTextParagraph::Draw(wxDC& dc, const wxRichTextRange& range, const wxR
             }
 
             // Get line height from first line, if any
-            wxRichTextLine* line = m_cachedLines.GetFirst() ? (wxRichTextLine* ) m_cachedLines.GetFirst()->GetData() : (wxRichTextLine*) NULL;
+            wxRichTextLine* line = m_cachedLines.GetFirst() ? (wxRichTextLine* ) m_cachedLines.GetFirst()->GetData() : NULL;
 
             wxPoint linePos;
             int lineHeight wxDUMMY_INITIALIZE(0);
@@ -3337,8 +3360,8 @@ bool wxRichTextParagraph::Layout(wxDC& dc, const wxRect& rect, int style)
     wxPoint currentPosition(0, spaceBeforePara); // We will calculate lines relative to paragraph
     int lineHeight = 0;
     int maxWidth = 0;
+    int maxAscent = 0;
     int maxDescent = 0;
-
     int lineCount = 0;
 
     wxRichTextObjectList::compatibility_iterator node;
@@ -3453,6 +3476,10 @@ bool wxRichTextParagraph::Layout(wxDC& dc, const wxRect& rect, int style)
             wxSize actualSize;
             wxRichTextRange actualRange(lastCompletedEndPos+1, wrapPosition);
 
+            /// Use previous descent, not the wrapping descent we just found, since this may be too big
+            /// for the fragment we're about to add.
+            childDescent = maxDescent;
+
 #if wxRICHTEXT_USE_PARTIAL_TEXT_EXTENTS
             // Get height only, then the width using the partial extents
             GetRangeSize(actualRange, actualSize, childDescent, dc, wxRICHTEXT_UNFORMATTED|wxRICHTEXT_HEIGHT_ONLY);
@@ -3462,8 +3489,9 @@ bool wxRichTextParagraph::Layout(wxDC& dc, const wxRect& rect, int style)
 #endif
 
             currentWidth = actualSize.x;
-            lineHeight = wxMax(lineHeight, actualSize.y);
             maxDescent = wxMax(childDescent, maxDescent);
+            maxAscent = wxMax(actualSize.y-childDescent, maxAscent);
+            lineHeight = maxDescent + maxAscent;
 
             // Add a new line
             wxRichTextLine* line = AllocateLine(lineCount);
@@ -3479,6 +3507,7 @@ bool wxRichTextParagraph::Layout(wxDC& dc, const wxRect& rect, int style)
             currentPosition.y += lineSpacing;
             currentWidth = 0;
             maxDescent = 0;
+            maxAscent = 0;
             maxWidth = wxMax(maxWidth, currentWidth);
 
             lineCount ++;
@@ -3502,8 +3531,9 @@ bool wxRichTextParagraph::Layout(wxDC& dc, const wxRect& rect, int style)
         {
             // We still fit, so don't add a line, and keep going
             currentWidth += childSize.x;
-            lineHeight = wxMax(lineHeight, childSize.y);
             maxDescent = wxMax(childDescent, maxDescent);
+            maxAscent = wxMax(childSize.y-childDescent, maxAscent);
+            lineHeight = maxDescent + maxAscent;
 
             maxWidth = wxMax(maxWidth, currentWidth);
             lastEndPos = child->GetRange().GetEnd();
@@ -3550,7 +3580,7 @@ bool wxRichTextParagraph::Layout(wxDC& dc, const wxRect& rect, int style)
     ClearUnusedLines(lineCount);
 
     // Apply styles to wrapped lines
-    ApplyParagraphStyle(attr, rect);
+    ApplyParagraphStyle(attr, rect, dc);
 
     SetCachedSize(wxSize(maxWidth, currentPosition.y + spaceBeforePara + spaceAfterPara));
 
@@ -3602,7 +3632,7 @@ bool wxRichTextParagraph::Layout(wxDC& dc, const wxRect& rect, int style)
 }
 
 /// Apply paragraph styles, such as centering, to wrapped lines
-void wxRichTextParagraph::ApplyParagraphStyle(const wxTextAttr& attr, const wxRect& rect)
+void wxRichTextParagraph::ApplyParagraphStyle(const wxTextAttr& attr, const wxRect& rect, wxDC& dc)
 {
     if (!attr.HasAlignment())
         return;
@@ -3618,12 +3648,14 @@ void wxRichTextParagraph::ApplyParagraphStyle(const wxTextAttr& attr, const wxRe
         // centering, right-justification
         if (attr.HasAlignment() && GetAttributes().GetAlignment() == wxTEXT_ALIGNMENT_CENTRE)
         {
-            pos.x = (rect.GetWidth() - size.x)/2 + pos.x;
+            int rightIndent = ConvertTenthsMMToPixels(dc, attr.GetRightIndent());
+            pos.x = (rect.GetWidth() - pos.x - rightIndent - size.x)/2 + pos.x;
             line->SetPosition(pos);
         }
         else if (attr.HasAlignment() && GetAttributes().GetAlignment() == wxTEXT_ALIGNMENT_RIGHT)
         {
-            pos.x = pos.x + rect.GetWidth() - size.x;
+            int rightIndent = ConvertTenthsMMToPixels(dc, attr.GetRightIndent());
+            pos.x = rect.GetWidth() - size.x - rightIndent;
             line->SetPosition(pos);
         }
 
@@ -4228,7 +4260,7 @@ bool wxRichTextParagraph::FindWrapPosition(const wxRichTextRange& range, wxDC& d
             widthBefore = 0;
 
         size_t i;
-        for (i = (size_t) range.GetStart(); i < (size_t) range.GetEnd(); i++)
+        for (i = (size_t) range.GetStart(); i <= (size_t) range.GetEnd(); i++)
         {
             int widthFromStartOfThisRange = (*partialExtents)[i - GetRange().GetStart()] - widthBefore;
 
@@ -4643,7 +4675,9 @@ bool wxRichTextPlainText::Draw(wxDC& dc, const wxRichTextRange& range, const wxR
             int s1 = selectionRange.GetStart()-1;
             int fragmentLen = s1 - r1 + 1;
             if (fragmentLen < 0)
+            {
                 wxLogDebug(wxT("Mid(%d, %d"), (int)(r1 - offset), (int)fragmentLen);
+            }
             wxString stringFragment = str.Mid(r1 - offset, fragmentLen);
 
             DrawTabbedString(dc, textAttr, rect, stringFragment, x, y, false);
@@ -4674,7 +4708,9 @@ bool wxRichTextPlainText::Draw(wxDC& dc, const wxRichTextRange& range, const wxR
 
             int fragmentLen = s2 - s1 + 1;
             if (fragmentLen < 0)
+            {
                 wxLogDebug(wxT("Mid(%d, %d"), (int)(s1 - offset), (int)fragmentLen);
+            }
             wxString stringFragment = str.Mid(s1 - offset, fragmentLen);
 
             DrawTabbedString(dc, textAttr, rect, stringFragment, x, y, true);
@@ -4705,7 +4741,9 @@ bool wxRichTextPlainText::Draw(wxDC& dc, const wxRichTextRange& range, const wxR
 
             int fragmentLen = r2 - s2 + 1;
             if (fragmentLen < 0)
+            {
                 wxLogDebug(wxT("Mid(%d, %d"), (int)(s2 - offset), (int)fragmentLen);
+            }
             wxString stringFragment = str.Mid(s2 - offset, fragmentLen);
 
             DrawTabbedString(dc, textAttr, rect, stringFragment, x, y, false);
@@ -4766,6 +4804,7 @@ bool wxRichTextPlainText::DrawTabbedString(wxDC& dc, const wxTextAttr& attr, con
             dc.SetBackgroundMode(wxBRUSHSTYLE_TRANSPARENT);
     }
 
+    wxCoord x_orig = x;
     while (hasTabs)
     {
         // the string has a tab
@@ -4777,7 +4816,7 @@ bool wxRichTextPlainText::DrawTabbedString(wxDC& dc, const wxTextAttr& attr, con
         bool not_found = true;
         for (int i = 0; i < tabCount && not_found; ++i)
         {
-            nextTabPos = tabArray.Item(i);
+            nextTabPos = tabArray.Item(i) + x_orig;
 
             // Find the next tab position.
             // Even if we're at the end of the tab array, we must still draw the chunk.
@@ -5473,7 +5512,7 @@ wxTextAttr wxRichTextBuffer::GetStyleForNewParagraph(long pos, bool caretPositio
                 if (para->GetAttributes().HasBulletNumber())
                     attr.SetBulletNumber(para->GetAttributes().GetBulletNumber());
             }
-               }
+        }
 
         if (!foundAttributes)
         {
@@ -5658,7 +5697,7 @@ void wxRichTextBuffer::ClearStyleStack()
 bool wxRichTextBuffer::BeginBold()
 {
     wxTextAttr attr;
-    attr.SetFontWeight(wxBOLD);
+    attr.SetFontWeight(wxFONTWEIGHT_BOLD);
 
     return BeginStyle(attr);
 }
@@ -5667,7 +5706,7 @@ bool wxRichTextBuffer::BeginBold()
 bool wxRichTextBuffer::BeginItalic()
 {
     wxTextAttr attr;
-    attr.SetFontStyle(wxITALIC);
+    attr.SetFontStyle(wxFONTSTYLE_ITALIC);
 
     return BeginStyle(attr);
 }
@@ -5903,7 +5942,7 @@ wxRichTextFileHandler *wxRichTextBuffer::FindHandlerFilenameOrType(const wxStrin
     else if (!filename.IsEmpty())
     {
         wxString path, file, ext;
-        wxSplitPath(filename, & path, & file, & ext);
+        wxFileName::SplitPath(filename, & path, & file, & ext);
         return FindHandler(ext, imageType);
     }
     else
@@ -6460,10 +6499,10 @@ bool wxRichTextStdRenderer::DrawBitmapBullet(wxRichTextParagraph* WXUNUSED(parag
 /// Enumerate the standard bullet names currently supported
 bool wxRichTextStdRenderer::EnumerateStandardBulletNames(wxArrayString& bulletNames)
 {
-    bulletNames.Add(wxT("standard/circle"));
-    bulletNames.Add(wxT("standard/square"));
-    bulletNames.Add(wxT("standard/diamond"));
-    bulletNames.Add(wxT("standard/triangle"));
+    bulletNames.Add(wxTRANSLATE("standard/circle"));
+    bulletNames.Add(wxTRANSLATE("standard/square"));
+    bulletNames.Add(wxTRANSLATE("standard/diamond"));
+    bulletNames.Add(wxTRANSLATE("standard/triangle"));
 
     return true;
 }
@@ -6925,8 +6964,12 @@ void wxRichTextAction::UpdateAppearance(long caretPosition, bool sendUpdateEvent
                         // Detect last line in the buffer
                         else if (!node2->GetNext() && para->GetRange().Contains(m_buffer->GetRange().GetEnd()))
                         {
-                            foundEnd = true;
-                            lastY = pt.y + line->GetSize().y;
+                            // If deleting text, make sure we refresh below as well as above
+                            if (positionOffset >= 0)
+                            {
+                                foundEnd = true;
+                                lastY = pt.y + line->GetSize().y;
+                            }
 
                             node2 = wxRichTextLineList::compatibility_iterator();
                             node = wxRichTextObjectList::compatibility_iterator();
@@ -7301,7 +7344,7 @@ bool wxRichTextFileHandler::SaveFile(wxRichTextBuffer *buffer, const wxString& f
 bool wxRichTextFileHandler::CanHandle(const wxString& filename) const
 {
     wxString path, file, ext;
-    wxSplitPath(filename, & path, & file, & ext);
+    wxFileName::SplitPath(filename, & path, & file, & ext);
 
     return (ext.Lower() == GetExtension());
 }
@@ -7422,12 +7465,10 @@ bool wxRichTextImageBlock::MakeImageBlock(const wxString& filename, wxBitmapType
 
     if ((imageType != wxBITMAP_TYPE_JPEG) && convertToJPEG)
     {
-        wxString tempFile;
-        bool success = wxGetTempFileName(_("image"), tempFile) ;
-
-        wxASSERT(success);
+        wxString tempFile =
+            wxFileName::CreateTempFileName(_("image"));
 
-        wxUnusedVar(success);
+        wxASSERT(!tempFile.IsEmpty());
 
         image.SaveFile(tempFile, wxBITMAP_TYPE_JPEG);
         filenameToRead = tempFile;
@@ -7462,11 +7503,8 @@ bool wxRichTextImageBlock::MakeImageBlock(wxImage& image, wxBitmapType imageType
     if (imageType == wxBITMAP_TYPE_INVALID)
         return false; // Could not determine image type
 
-    wxString tempFile;
-    bool success = wxGetTempFileName(_("image"), tempFile) ;
-
-    wxASSERT(success);
-    wxUnusedVar(success);
+    wxString tempFile = wxFileName::CreateTempFileName(_("image")) ;
+    wxASSERT(!tempFile.IsEmpty());
 
     if (!image.SaveFile(tempFile, m_imageType))
     {
@@ -7533,9 +7571,8 @@ bool wxRichTextImageBlock::Load(wxImage& image)
     wxMemoryInputStream mstream(m_data, m_dataSize);
     bool success = image.LoadFile(mstream, GetImageType());
 #else
-    wxString tempFile;
-    bool success = wxGetTempFileName(_("image"), tempFile) ;
-    wxASSERT(success);
+    wxString tempFile = wxFileName::CreateTempFileName(_("image"));
+    wxASSERT(!tempFile.IsEmpty());
 
     if (!WriteBlock(tempFile, m_data, m_dataSize))
     {