diff --git a/configure.ac b/configure.ac index 48228be26..d2d3b2a53 100644 --- a/configure.ac +++ b/configure.ac @@ -616,6 +616,24 @@ if test "$abi_cv_icondir" = "" -o \ fi AC_SUBST(ABIWORD_ICONDIR, "$abi_cv_icondir") +dnl *********************************************************************** +dnl GCC/Clang sanitizer support +dnl *********************************************************************** +AC_ARG_WITH([sanitizer], + [AS_HELP_STRING([--with-sanitizer=@<:@address/undefined/no@:>@], + [Use specific GCC/Clang analyzer])], + [with_sanitizer=$withval], + [with_sanitizer=no]) +AS_IF([test "x$with_sanitizer" != "xno"],[ + AX_CHECK_COMPILE_FLAG([-fsanitize=$withval], + [CFLAGS="$CFLAGS -fsanitize=$withval" + CXXFLAGS="$CXXFLAGS -fsanitize=$withval"], + [AC_MSG_ERROR([-fsanitize=$withval is not supported])]) + AX_APPEND_COMPILE_FLAGS([-fno-omit-frame-pointer]) + AC_LANG_PUSH(C++) + AX_APPEND_COMPILE_FLAGS([-fno-omit-frame-pointer]) + AC_LANG_POP +]) # # Compiler settings (from gnumeric's configure.in) diff --git a/src/af/gr/gtk/gr_UnixCairoGraphics.cpp b/src/af/gr/gtk/gr_UnixCairoGraphics.cpp index 509bd3733..4780154c9 100644 --- a/src/af/gr/gtk/gr_UnixCairoGraphics.cpp +++ b/src/af/gr/gtk/gr_UnixCairoGraphics.cpp @@ -126,8 +126,12 @@ GR_Graphics * GR_UnixCairoGraphics::graphicsAllocator(GR_AllocInfo& info) // UT_return_val_if_fail(!info.isPrinterGraphics(), NULL); GR_UnixCairoAllocInfo &AI = (GR_UnixCairoAllocInfo&)info; - +#if GTK_CHECK_VERSION(3,0,0) + // We disable double buffering on Gtk3 because it doesn't work. + return new GR_UnixCairoGraphics(AI.m_win, false); +#else return new GR_UnixCairoGraphics(AI.m_win, AI.m_double_buffered); +#endif } inline UT_RGBColor _convertGdkColor(const GdkColor &c) @@ -180,7 +184,7 @@ void GR_UnixCairoGraphics::init3dColors(GtkWidget* /*w*/) if (m_styleBg) { g_object_unref(m_styleBg); } - m_styleBg = XAP_GtkStyle_get_style(nullptr, "GtkButton"); // "button" + m_styleBg = XAP_GtkStyle_get_style(NULL, "GtkButton"); // "button" // guess colours // WHITE GdkRGBA rgba2; @@ -566,7 +570,10 @@ void GR_UnixCairoGraphics::_beginPaint() void GR_UnixCairoGraphics::_endPaint() { if (m_CairoCreated) + { + cairo_surface_flush(cairo_get_target(m_cr)); cairo_destroy (m_cr); + } m_cr = NULL; m_Painting = false; @@ -577,9 +584,17 @@ void GR_UnixCairoGraphics::_endPaint() void GR_UnixCairoGraphics::flush(void) { + if (m_Widget) { gtk_widget_queue_draw(m_Widget); } + +/* + if(m_cr) + { + cairo_surface_flush(cairo_get_target(m_cr)); + } +*/ } bool GR_UnixCairoGraphics::queryProperties(GR_Graphics::Properties gp) const @@ -627,7 +642,7 @@ void GR_UnixCairoGraphics::fillRect(GR_Color3D c, UT_sint32 x, UT_sint32 y, _setProps(); cairo_save (m_cr); - GtkStyleContext *context = nullptr; + GtkStyleContext *context = NULL; switch(c) { case GR_Graphics::CLR3D_Background: context = m_styleBg; diff --git a/src/af/gr/gtk/gr_UnixImage.cpp b/src/af/gr/gtk/gr_UnixImage.cpp index be801b939..457646d44 100644 --- a/src/af/gr/gtk/gr_UnixImage.cpp +++ b/src/af/gr/gtk/gr_UnixImage.cpp @@ -244,12 +244,13 @@ bool GR_UnixImage::saveToPNG(const char * szFile) UT_return_val_if_fail(m_image,false); GError * error = NULL; - gboolean res = gdk_pixbuf_save (m_image, szFile, "png", &error,NULL); - if(res != FALSE) - { + gboolean res = gdk_pixbuf_save (m_image, szFile, "png", &error, NULL); + if (res != FALSE) { + if (error) { + g_error_free (error); + } return true; } - delete error; return false; } diff --git a/src/af/gr/xp/gr_Caret.cpp b/src/af/gr/xp/gr_Caret.cpp index 5d5d116d0..3c64e2af5 100644 --- a/src/af/gr/xp/gr_Caret.cpp +++ b/src/af/gr/xp/gr_Caret.cpp @@ -30,6 +30,11 @@ #include "gr_Graphics.h" #include "gr_Painter.h" #include "ut_debugmsg.h" +#include +#include +#include +#include + static const UT_uint32 CURSOR_DELAY_TIME = 10; // milliseconds #ifdef TOOLKIT_GTK_ALL @@ -56,6 +61,11 @@ GR_Caret::GR_Caret(GR_Graphics * pG) m_yPoint2(0), m_pClr(NULL), m_pG(pG), + m_iWindowWidth(0), + m_iWindowHeight(0), + m_worker(NULL), + m_enabler(NULL), + m_blinkTimeout(NULL), m_nDisableCount(1), m_bCursorBlink(true), m_bCursorIsOn(false), @@ -70,7 +80,10 @@ GR_Caret::GR_Caret(GR_Graphics * pG) m_bRemote(false), m_clrRemote(0,0,0), m_sID(""), - m_iCaretNumber(0) + m_iCaretNumber(0), + m_iLastDrawTime(0), + m_iRetry(0), + m_bPendingBlink(false) { UT_WorkerFactory::ConstructMode outMode = UT_WorkerFactory::NONE; m_worker = static_cast(UT_WorkerFactory::static_constructor @@ -97,6 +110,11 @@ GR_Caret::GR_Caret(GR_Graphics * pG, const std::string& sId) m_yPoint2(0), m_pClr(NULL), m_pG(pG), + m_iWindowWidth(0), + m_iWindowHeight(0), + m_worker(NULL), + m_enabler(NULL), + m_blinkTimeout(NULL), m_nDisableCount(1), m_bCursorBlink(true), m_bCursorIsOn(false), @@ -111,7 +129,10 @@ GR_Caret::GR_Caret(GR_Graphics * pG, const std::string& sId) m_bRemote(true), m_clrRemote(0,0,0), m_sID(sId), - m_iCaretNumber(0) + m_iCaretNumber(0), + m_iLastDrawTime(0), + m_iRetry(0), + m_bPendingBlink(false) { UT_WorkerFactory::ConstructMode outMode = UT_WorkerFactory::NONE; m_worker = static_cast(UT_WorkerFactory::static_constructor @@ -145,9 +166,16 @@ GR_Caret::~GR_Caret() void GR_Caret::s_work(UT_Worker * _w) { GR_Caret * c = static_cast(_w->getInstanceData()); - + xxx_UT_DEBUGMSG((" Caret timer called Disable Count = %d \n",c->m_nDisableCount)); if (c->m_nDisableCount == 0) + { +#ifdef TOOLKIT_GTK_ALL + c->setPendingBlink(); + c->m_pG->flush(); // set redraw for wayland +#else c->_blink(false); +#endif + } } /** One-time enabler. */ @@ -170,9 +198,12 @@ void GR_Caret::s_enable(UT_Worker * _w) void GR_Caret::s_blink_timeout(UT_Worker * _w) { + return; + /* GR_Caret * c = static_cast(_w->getInstanceData()); if (c->isEnabled()) c->disable(); + */ } UT_uint32 GR_Caret::_getCursorBlinkTime() const @@ -241,8 +272,6 @@ void GR_Caret::setCoords(UT_sint32 x, UT_sint32 y, UT_uint32 h, UT_sint32 x2, UT_sint32 y2, UT_uint32 h2, bool bPointDirection, const UT_RGBColor * pClr) { - // if visible, then hide while we change positions. - _erase(); m_xPoint = x; m_yPoint = y; m_iPointHeight = h; m_xPoint2 = x2; m_yPoint2 = y2; m_iPointHeight2 = h2; @@ -270,13 +299,17 @@ void GR_Caret::enable() // If the caret is already enabled, just return if (m_nDisableCount == 0) + { + xxx_UT_DEBUGMSG(("Don't emable disable Count is already zero \n")); return; - + } // Check to see if we still have pending disables. --m_nDisableCount; - if (m_nDisableCount) + if (m_nDisableCount != 0) + { + xxx_UT_DEBUGMSG(("Don't emable, disable Count has not reached zero \n")); return; - + } // stop pending enables; in 10 ms, really enable blinking. m_enabler->stop(); m_enabler->start(); @@ -326,19 +359,20 @@ void GR_Caret::JustErase(UT_sint32 xPoint,UT_sint32 yPoint) { if(m_bRecursiveDraw) { - xxx_UT_DEBUGMSG(("Doing recursive Erase! - abort \n")); + xxx_UT_DEBUGMSG(("Doing recursive Just Erase! - abort \n")); return; } if (m_bCursorIsOn && (((xPoint -m_pG->tlu(2)-1) <= m_xPoint) && (xPoint >= (m_xPoint-m_pG->tlu(2))-1)) && ((yPoint - m_pG->tlu(1)) <= m_yPoint) && (yPoint >= (m_yPoint - m_pG->tlu(1)))) { + xxx_UT_DEBUGMSG(("Doing Just Erase! now \n")); m_pG->restoreRectangle(m_iCaretNumber*3+0); if(m_bSplitCaret) { m_pG->restoreRectangle(m_iCaretNumber*3+1); - m_pG->restoreRectangle(m_iCaretNumber*3+2); - m_bSplitCaret = false; + m_pG->restoreRectangle(m_iCaretNumber*3+2); + m_bSplitCaret = false; } - m_bCursorIsOn = !m_bCursorIsOn; + m_bCursorIsOn = false; m_nDisableCount = 1; } } @@ -358,18 +392,42 @@ void GR_Caret::_blink(bool bExplicit) } if (!m_bPositionSet) return; - + if(!m_bPendingBlink) + return; + struct timespec spec; + + clock_gettime(CLOCK_REALTIME, &spec); + + UT_sint32 s = spec.tv_sec; + long ms = round(spec.tv_nsec / 1.0e6); // Convert nanoseconds to milliseconds + long this_time = 1000*s + ms; + long time_between = this_time - m_iLastDrawTime; + m_iLastDrawTime = this_time; + // + // If this number is high enough the caret will not blink at all + // This places the caret on the screen during rapid moves. + // + if(time_between < _getCursorBlinkTime()/2) + { + m_iRetry++; + xxx_UT_DEBUGMSG(("Caret redraw after %d ms \n",time_between)); + } + else + { + m_iRetry = 0; + } m_bRecursiveDraw = true; GR_Painter painter (m_pG, false); m_bRecursiveDraw = false; // After any autoblink, we want there to be BLINK_TIME // until next autoblink. + /* if (!bExplicit) { m_worker->stop(); m_worker->start(); } - + */ // Blink if: (a) _blink explicitly called (not autoblink); or // (b) autoblink and caret blink enabled; or // (c) autoblink, caret blink disabled, caret is off @@ -380,6 +438,7 @@ void GR_Caret::_blink(bool bExplicit) if (m_bCursorIsOn) { + xxx_UT_DEBUGMSG(("Clear Caret reTry %d \n",m_iRetry)); m_pG->restoreRectangle(m_iCaretNumber*3+0); if(m_bSplitCaret) @@ -388,6 +447,7 @@ void GR_Caret::_blink(bool bExplicit) m_pG->restoreRectangle(m_iCaretNumber*3+2); m_bSplitCaret = false; } + m_bCursorIsOn = false; } else { @@ -413,7 +473,9 @@ void GR_Caret::_blink(bool bExplicit) m_yPoint+m_pG->tlu(1), m_pG->tlu(5), m_iPointHeight+m_pG->tlu(2)); + m_bRecursiveDraw = false; m_pG->allCarets()->JustErase(m_xPoint,m_yPoint); + m_bRecursiveDraw = true; m_pG->saveRectangle(r0,m_iCaretNumber*3+0); if((m_xPoint != m_xPoint2) || (m_yPoint != m_yPoint2)) @@ -446,7 +508,7 @@ void GR_Caret::_blink(bool bExplicit) if(m_bCaret1OnScreen) { // draw the primary caret - xxx_UT_DEBUGMSG(("blink cursor turned on \n")); + xxx_UT_DEBUGMSG(("Draw Caret reTry %d \n",m_iRetry)); UT_sint32 x1 = m_xPoint + iDelta * m_pG->tlu(1); UT_sint32 x2 = m_xPoint; @@ -463,6 +525,7 @@ void GR_Caret::_blink(bool bExplicit) m_yPoint + m_pG->tlu(1), x2, m_yPoint + m_iPointHeight + m_pG->tlu(1)); + m_bCursorIsOn = true; } if(m_bSplitCaret) @@ -499,6 +562,7 @@ void GR_Caret::_blink(bool bExplicit) m_xPoint + m_pG->tlu(2), m_yPoint + m_pG->tlu(2)); } + m_bCursorIsOn = true; } // Now we deal with the secondary caret needed on ltr-rtl boundary @@ -557,25 +621,54 @@ void GR_Caret::_blink(bool bExplicit) m_xPoint2 /*- m_pG->tlu(1)*/, m_yPoint2 + m_pG->tlu(2)); } + m_bCursorIsOn = true; } } } - m_bCursorIsOn = !m_bCursorIsOn; m_pG->setColor(oldColor); m_bRecursiveDraw = false; } - m_pG->flush(); + // + // Places the caret on the screen during rapid moves like pressing the arrow keys + // + if(m_iRetry == 0) + m_bPendingBlink = false; } +// +// Tell the widget redraw know we only need to blink on this cycle +// +void GR_Caret::setPendingBlink() +{ + xxx_UT_DEBUGMSG(("Pending blink set in GR_CARET \n")); + m_bPendingBlink = true; +} + +// +// Returns true if we did a blink +// +bool GR_Caret::doBlinkIfNeeded() +{ + if(!m_bPendingBlink) + { + return false; + } + _blink(true); + m_bPendingBlink = false; + return true; +} /*! * Only call this is you are absolutely certain you need it! */ void GR_Caret::forceDraw(void) { - _blink(true); + if(m_nDisableCount < 2) + { + _blink(true); + } } void GR_Caret::resetBlinkTimeout(void) diff --git a/src/af/gr/xp/gr_Caret.h b/src/af/gr/xp/gr_Caret.h index ddc9e1831..99cf9b0e2 100644 --- a/src/af/gr/xp/gr_Caret.h +++ b/src/af/gr/xp/gr_Caret.h @@ -67,7 +67,8 @@ public: void setRemoteColor(UT_RGBColor clrRemote); void resetBlinkTimeout(void); - + void setPendingBlink(void); + bool doBlinkIfNeeded(void); private: GR_Caret(); // no impl GR_Caret(const GR_Caret& rhs); // no impl. @@ -121,6 +122,9 @@ private: UT_RGBColor m_clrRemote; std::string m_sID; UT_sint32 m_iCaretNumber; + long m_iLastDrawTime; + UT_sint32 m_iRetry; + bool m_bPendingBlink; }; class ABI_EXPORT GR_CaretDisabler diff --git a/src/af/gr/xp/gr_Graphics.cpp b/src/af/gr/xp/gr_Graphics.cpp index 1e49fcb70..c039c41c5 100644 --- a/src/af/gr/xp/gr_Graphics.cpp +++ b/src/af/gr/xp/gr_Graphics.cpp @@ -185,6 +185,20 @@ void AllCarets::setBlink(bool bBlink) } } +bool AllCarets::doBlinkIfNeeded(void) +{ + bool bBlinked = false; + if((*m_pLocalCaret)) + { + bBlinked = (*m_pLocalCaret)->doBlinkIfNeeded(); + for(UT_sint32 i =0; i< m_vecCarets->getItemCount();i++) + { + m_vecCarets->getNthItem(i)->forceDraw(); + } + } + return bBlinked; +} + void AllCarets::setWindowSize(UT_uint32 width, UT_uint32 height) { if((*m_pLocalCaret)) @@ -195,6 +209,12 @@ void AllCarets::setWindowSize(UT_uint32 width, UT_uint32 height) } } +void AllCarets::setPendingBlink(void) +{ + if((*m_pLocalCaret)) + (*m_pLocalCaret)->setPendingBlink(); +} + void AllCarets::setCoords(UT_sint32 x, UT_sint32 y, UT_uint32 h, UT_sint32 x2, UT_sint32 y2, UT_uint32 h2, bool bPointDirection, diff --git a/src/af/gr/xp/gr_Graphics.h b/src/af/gr/xp/gr_Graphics.h index 9fac1b7c5..ba6ee736f 100644 --- a/src/af/gr/xp/gr_Graphics.h +++ b/src/af/gr/xp/gr_Graphics.h @@ -364,7 +364,9 @@ class ABI_EXPORT AllCarets const UT_RGBColor * pClr = NULL); void setInsertMode (bool mode); void forceDraw(void); - + bool doBlinkIfNeeded(void); + void setPendingBlink(void); + private: GR_Graphics * m_pG; GR_Caret ** m_pLocalCaret; diff --git a/src/af/util/unix/ut_unixTimer.cpp b/src/af/util/unix/ut_unixTimer.cpp index 15d16c295..3b385608b 100644 --- a/src/af/util/unix/ut_unixTimer.cpp +++ b/src/af/util/unix/ut_unixTimer.cpp @@ -66,10 +66,11 @@ static int _Timer_Proc(void *p) UT_ASSERT(pTimer); xxx_UT_DEBUGMSG(("ut_unixTimer.cpp: timer fired\n")); - - pTimer->fire(); - - return true; + if (pTimer) { + pTimer->fire(); + return TRUE; + } + return 0; } UT_sint32 UT_UNIXTimer::set(UT_uint32 iMilliseconds) diff --git a/src/af/util/xp/ut_png.cpp b/src/af/util/xp/ut_png.cpp index 79b0f210b..0a8d648ac 100644 --- a/src/af/util/xp/ut_png.cpp +++ b/src/af/util/xp/ut_png.cpp @@ -28,6 +28,7 @@ #include "ut_assert.h" #include "ut_bytebuf.h" +#include "ut_debugmsg.h" struct _bb { @@ -40,6 +41,19 @@ static void _png_read(png_structp png_ptr, png_bytep data, png_size_t length) struct _bb* p = static_cast(png_get_io_ptr(png_ptr)); const UT_Byte* pBytes = p->pBB->getPointer(0); + // make sure that we don't read outside of pBytes + if (p->iCurPos >= p->pBB->getLength() - length) { + UT_WARNINGMSG(("PNG: Reading past buffer bounds. cur = %u, buflen = %u, length = %lu\n", + p->iCurPos, p->pBB->getLength(), length)); + length = p->pBB->getLength() - p->iCurPos; + if (length == 0) { + UT_WARNINGMSG(("PNG: Truncating to ZERO length.\n")); + png_error(png_ptr, "Premature end of buffer"); + return; + } else { + UT_WARNINGMSG(("PNG: Truncating to %lu.\n", length)); + } + } memcpy(data, pBytes + p->iCurPos, length); p->iCurPos += length; } diff --git a/src/af/xap/gtk/xap_UnixFrameImpl.cpp b/src/af/xap/gtk/xap_UnixFrameImpl.cpp index 780000ea6..3292b3d98 100644 --- a/src/af/xap/gtk/xap_UnixFrameImpl.cpp +++ b/src/af/xap/gtk/xap_UnixFrameImpl.cpp @@ -1208,15 +1208,23 @@ gint XAP_UnixFrameImpl::_fe::delete_event(GtkWidget * w, GdkEvent * /*event*/, g } #if GTK_CHECK_VERSION(3,0,0) -gint XAP_UnixFrameImpl::_fe::draw(GtkWidget * w, cairo_t * cr) +gboolean XAP_UnixFrameImpl::_fe::draw(GtkWidget * w, cairo_t * cr) #else -gint XAP_UnixFrameImpl::_fe::expose(GtkWidget * w, GdkEventExpose* pExposeEvent) +gboolean XAP_UnixFrameImpl::_fe::expose(GtkWidget * w, GdkEventExpose* pExposeEvent) #endif { XAP_UnixFrameImpl * pUnixFrameImpl = static_cast(g_object_get_data(G_OBJECT(w), "user_data")); FV_View * pView = static_cast(pUnixFrameImpl->getFrame()->getCurrentView()); + double x, y, width, height; #if GTK_CHECK_VERSION(3,0,0) - GdkEventExpose *pExposeEvent = reinterpret_cast(gtk_get_current_event()); + cairo_clip_extents (cr, &x, &y, &width, &height); + width -= x; + height -= y; +#else + x = pExposeEvent->area.x; + y = pExposeEvent->area.y; + width = pExposeEvent->area.width; + height = pExposeEvent->area.height; #endif /* Jean: commenting out next lines since the zoom update code does draw only * part of what needs to be updated. */ @@ -1231,19 +1239,21 @@ gint XAP_UnixFrameImpl::_fe::expose(GtkWidget * w, GdkEventExpose* pExposeEvent) if (pGr->getPaintCount () > 0) return TRUE; xxx_UT_DEBUGMSG(("Expose area: x %d y %d width %d height %d \n",pExposeEvent->area.x,pExposeEvent->area.y,pExposeEvent->area.width,pExposeEvent->area.height)); - rClip.left = pGr->tlu(pExposeEvent->area.x); - rClip.top = pGr->tlu(pExposeEvent->area.y); - rClip.width = pGr->tlu(pExposeEvent->area.width)+1; - rClip.height = pGr->tlu(pExposeEvent->area.height)+1; + rClip.left = pGr->tlu(x); + rClip.top = pGr->tlu(y); #if GTK_CHECK_VERSION(3,0,0) + rClip.width = pGr->tlu(width); + rClip.height = pGr->tlu(height); static_cast(pGr)->setCairo(cr); pView->draw(&rClip); static_cast(pGr)->setCairo(NULL); #else + rClip.width = pGr->tlu(width)+1; + rClip.height = pGr->tlu(height)+1; pView->draw(&rClip); #endif } - return FALSE; + return TRUE; } static bool bScrollWait = false; diff --git a/src/af/xap/gtk/xap_UnixFrameImpl.h b/src/af/xap/gtk/xap_UnixFrameImpl.h index 30ee5d8e8..a0ff57fab 100644 --- a/src/af/xap/gtk/xap_UnixFrameImpl.h +++ b/src/af/xap/gtk/xap_UnixFrameImpl.h @@ -152,9 +152,9 @@ protected: static gint key_release_event(GtkWidget* w, GdkEventKey* e); static gint delete_event(GtkWidget * w, GdkEvent * /*event*/, gpointer /*data*/); #if GTK_CHECK_VERSION(3,0,0) - static gint draw(GtkWidget * w, cairo_t * cr); + static gboolean draw(GtkWidget * w, cairo_t * cr); #else - static gint expose(GtkWidget * w, GdkEventExpose* pExposeEvent); + static gboolean expose(GtkWidget * w, GdkEventExpose* pExposeEvent); #endif static gint do_ZoomUpdate( gpointer /* xap_UnixFrame * */ p); static void vScrollChanged(GtkAdjustment * w, gpointer /*data*/); diff --git a/src/af/xap/xp/xap_Frame.cpp b/src/af/xap/xp/xap_Frame.cpp index d291a7a8c..3dabe7026 100644 --- a/src/af/xap/xp/xap_Frame.cpp +++ b/src/af/xap/xp/xap_Frame.cpp @@ -505,7 +505,7 @@ void /* static*/ XAP_FrameImpl::viewAutoUpdater(UT_Worker *wkr) pFrameImpl->m_ViewAutoUpdaterID = 0; DELETEP(pFrameImpl->m_ViewAutoUpdater); pView->draw(); - + pG->flush(); return; } if(!pView->isLayoutFilling() && !pFrameImpl->m_pFrame->m_bFirstDraw) @@ -514,6 +514,7 @@ void /* static*/ XAP_FrameImpl::viewAutoUpdater(UT_Worker *wkr) pG->setCursor(GR_Graphics::GR_CURSOR_WAIT); pFrameImpl->_setCursor(GR_Graphics::GR_CURSOR_WAIT); pFrameImpl->m_pFrame->setStatusMessage ( static_cast(msg.c_str()) ); + pG->flush(); return; } GR_Graphics * pG = pView->getGraphics(); @@ -534,6 +535,7 @@ void /* static*/ XAP_FrameImpl::viewAutoUpdater(UT_Worker *wkr) pView->updateScreen(); } } + pG->flush(); } UT_RGBColor XAP_Frame::getColorSelBackground () const diff --git a/src/text/fmt/xp/fl_SectionLayout.cpp b/src/text/fmt/xp/fl_SectionLayout.cpp index ac792bf6f..96abbae93 100644 --- a/src/text/fmt/xp/fl_SectionLayout.cpp +++ b/src/text/fmt/xp/fl_SectionLayout.cpp @@ -1921,6 +1921,9 @@ void fl_DocSectionLayout::updateLayout(bool bDoFull) checkAndRemovePages(); addValidPages(); } + xxx_UT_DEBUGMSG(("Doing fl_DocSectionLayout::updateLayout here %p view %p \n",this, m_pLayout->getView())); + m_pLayout->getView()->getGraphics()->allCarets()->setPendingBlink(); // place caret after entry + m_pLayout->getView()->getGraphics()->flush(); // schedule redraw for Wayland } void fl_DocSectionLayout::setNeedsSectionBreak(bool bSet, fp_Page * pPage) diff --git a/src/text/fmt/xp/fv_View.cpp b/src/text/fmt/xp/fv_View.cpp index 46b6cb624..6952c9be5 100644 --- a/src/text/fmt/xp/fv_View.cpp +++ b/src/text/fmt/xp/fv_View.cpp @@ -3105,11 +3105,15 @@ bool FV_View::isSelectionEmpty(void) const { if(m_FrameEdit.isActive() && m_FrameEdit.isImageWrapper() ) { - return false; + if (m_pG) + m_pG->allCarets()->disable(true); + return false; } if(m_FrameEdit.isActive() && (m_FrameEdit. getFrameEditMode() >= FV_FrameEdit_RESIZE_INSERT)) { - return false; + if (m_pG) + m_pG->allCarets()->disable(true); + return false; } if (!m_Selection.isSelected()) { @@ -3124,6 +3128,8 @@ bool FV_View::isSelectionEmpty(void) const { return true; } + if (m_pG) + m_pG->allCarets()->disable(true); return false; } PT_DocPosition curPos = getPoint(); @@ -3131,7 +3137,8 @@ bool FV_View::isSelectionEmpty(void) const { return true; } - + if (m_pG) + m_pG->allCarets()->disable(true); return false; } diff --git a/src/text/fmt/xp/fv_ViewDoubleBuffering.cpp b/src/text/fmt/xp/fv_ViewDoubleBuffering.cpp index 6aa624698..52ae5da76 100644 --- a/src/text/fmt/xp/fv_ViewDoubleBuffering.cpp +++ b/src/text/fmt/xp/fv_ViewDoubleBuffering.cpp @@ -27,7 +27,7 @@ #include "ut_misc.h" #include "ut_debugmsg.h" -//#define DEACTIVATE_FV_VIEW_DOUBLE_BUFFERING +//#define DEACTIVATE_FV_VIEW_DOUBLE_BUFFERING 1 FV_ViewDoubleBuffering::FV_ViewDoubleBuffering(FV_View *pView, bool suspendDirectDrawing, bool callDrawOnlyAtTheEnd) : m_pView(pView), diff --git a/src/text/fmt/xp/fv_View_protected.cpp b/src/text/fmt/xp/fv_View_protected.cpp index c24081d15..3dc03bfeb 100644 --- a/src/text/fmt/xp/fv_View_protected.cpp +++ b/src/text/fmt/xp/fv_View_protected.cpp @@ -4478,7 +4478,6 @@ void FV_View::_draw(UT_sint32 x, UT_sint32 y, "\t\twith [yScrollOffset %d][windowHeight %d][bDirtyRunsOnly %d]\n", x,y,width,height,bClip, m_yScrollOffset,getWindowHeight(),bDirtyRunsOnly)); - if(m_pViewDoubleBufferingObject != NULL && m_pViewDoubleBufferingObject->getCallDrawOnlyAtTheEnd()) { // record this call's arguments and return @@ -4727,12 +4726,19 @@ void FV_View::_draw(UT_sint32 x, UT_sint32 y, // advance to the next page pPage = pPage -> getNext(); } - if (bClip) { m_pG->setClipRect(NULL); } - + // + // Look if we have to blink the caret + // + xxx_UT_DEBUGMSG(("Doing _draw bDirtyRunsOnly %d \n",bDirtyRunsOnly)); + + if(m_pG->allCarets()->doBlinkIfNeeded()) + { + xxx_UT_DEBUGMSG(("Pending blink drawn has bDirtyRunsOnly %d \n",bDirtyRunsOnly)); + } xxx_UT_DEBUGMSG(("End _draw\n")); } @@ -4816,6 +4822,14 @@ void FV_View::_setPoint(PT_DocPosition pt, bool bEOL) m_countDisable++; } } + + if(m_pG) + { + xxx_UT_DEBUGMSG(("Schedule redraw in _setPoint \n")); + m_pG->allCarets()->setPendingBlink(); + m_pG->flush(); // scedule a redraw for Wayland + } + } diff --git a/src/wp/ap/gtk/ap_UnixFrameImpl.cpp b/src/wp/ap/gtk/ap_UnixFrameImpl.cpp index ce226c638..828a5fbab 100644 --- a/src/wp/ap/gtk/ap_UnixFrameImpl.cpp +++ b/src/wp/ap/gtk/ap_UnixFrameImpl.cpp @@ -219,11 +219,12 @@ GtkWidget * AP_UnixFrameImpl::_createDocumentWindow() GDK_FOCUS_CHANGE_MASK | GDK_LEAVE_NOTIFY_MASK | GDK_SCROLL_MASK)); - gtk_widget_set_double_buffered(GTK_WIDGET(m_dArea), FALSE); #if GTK_CHECK_VERSION(3,0,0) g_signal_connect(G_OBJECT(m_dArea), "draw", G_CALLBACK(XAP_UnixFrameImpl::_fe::draw), NULL); #else + // We disable double buffering on Gtk3 because it doesn't work. + gtk_widget_set_double_buffered(GTK_WIDGET(m_dArea), FALSE); g_signal_connect(G_OBJECT(m_dArea), "expose_event", G_CALLBACK(XAP_UnixFrameImpl::_fe::expose), NULL); #endif diff --git a/src/wp/ap/xp/ap_Dialog_Spell.cpp b/src/wp/ap/xp/ap_Dialog_Spell.cpp index d2a7522ae..23d1a3f83 100644 --- a/src/wp/ap/xp/ap_Dialog_Spell.cpp +++ b/src/wp/ap/xp/ap_Dialog_Spell.cpp @@ -251,7 +251,7 @@ bool AP_Dialog_Spell::nextMisspelledWord(void) UT_return_val_if_fail (m_Suggestions, false); // get suggestions from spelling engine - const UT_GenericVector *cpvEngineSuggestions = nullptr; + const UT_GenericVector *cpvEngineSuggestions = NULL; if (checker->checkWord(m_pWord, m_iWordLength) == SpellChecker::LOOKUP_FAILED) { diff --git a/src/wp/impexp/xp/ie_exp_DocRangeListener.cpp b/src/wp/impexp/xp/ie_exp_DocRangeListener.cpp index e8eb72ae7..bbac54451 100644 --- a/src/wp/impexp/xp/ie_exp_DocRangeListener.cpp +++ b/src/wp/impexp/xp/ie_exp_DocRangeListener.cpp @@ -166,7 +166,7 @@ void IE_Exp_DocRangeListener::freeAtts(const char *** allAtts) UT_sint32 i=0; while(sAtts[i]) { - delete [] (sAtts[i]); + g_free(const_cast(sAtts[i])); i++; } delete [] sAtts; diff --git a/src/wp/impexp/xp/ie_imp_RTF.cpp b/src/wp/impexp/xp/ie_imp_RTF.cpp index e568dab55..073ee03bd 100644 --- a/src/wp/impexp/xp/ie_imp_RTF.cpp +++ b/src/wp/impexp/xp/ie_imp_RTF.cpp @@ -12068,7 +12068,13 @@ bool IE_Imp_RTF::HandleStyleDefinition(void) // must not mix static and dynamically allocated strings in the same // array, otherwise there is no way we can g_free it !!! //attribs[attribsCount++] = g_strdup(static_cast(m_styleTable[istyle])); - attribs[attribsCount++] = m_styleTable[istyle].c_str(); + if (istyle >= 0 && static_cast(istyle) < m_styleTable.size()) { + attribs[attribsCount++] = m_styleTable[istyle].c_str(); + } else { + UT_WARNINGMSG(("RTF: basedon by style index out of bounds: %d. max %lu.\n", + istyle, m_styleTable.size())); + attribs[attribsCount++] = NULL; + } UT_return_val_if_fail( attribsCount < PT_MAX_ATTRIBUTES * 2,false ); } else @@ -12086,7 +12092,13 @@ bool IE_Imp_RTF::HandleStyleDefinition(void) // must not mix static and dynamically allocated strings in the same // array, otherwise there is no way we can g_free it !!! // attribs[attribsCount++] = g_strdup(static_cast(m_styleTable[istyle])); - attribs[attribsCount++] = m_styleTable[istyle].c_str(); + if (istyle >= 0 && static_cast(istyle) < m_styleTable.size()) { + attribs[attribsCount++] = m_styleTable[istyle].c_str(); + } else { + UT_WARNINGMSG(("RTF: followed by style index out of bounds: %d. max %lu.\n", + istyle, m_styleTable.size())); + attribs[attribsCount++] = NULL; + } UT_return_val_if_fail( attribsCount < PT_MAX_ATTRIBUTES * 2,false ); } else