Sisyphus repository
Last update: 1 october 2023 | SRPMs: 18631 | Visits: 37397777
en ru br
ALT Linux repos
S:3.0.5-alt1.2
D:2.5.2-alt1
5.0: 2.6.5-alt1
4.1: 2.6.4-alt2.M41.1
4.0: 2.5.2-alt2
3.0: 2.2.7-alt1

Other repositories
Upstream:1.4rc5

Group :: Office
RPM: abiword

 Main   Changelog   Spec   Patches   Sources   Download   Gear   Bugs and FR  Repocop 

Patch: abiword-3.0.2-up.patch
Download


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 <inttypes.h>
+#include <math.h>
+#include <stdio.h>
+#include <time.h>
+
 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_Timer *>(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_Timer *>(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<GR_Caret *>(_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<GR_Caret *>(_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<struct _bb*>(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<XAP_UnixFrameImpl *>(g_object_get_data(G_OBJECT(w), "user_data"));
 	FV_View * pView = static_cast<FV_View *>(pUnixFrameImpl->getFrame()->getCurrentView());
+	double x, y, width, height;
 #if GTK_CHECK_VERSION(3,0,0)
-	GdkEventExpose *pExposeEvent = reinterpret_cast<GdkEventExpose *>(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<GR_CairoGraphics *>(pGr)->setCairo(cr);
 		pView->draw(&rClip);
 		static_cast<GR_CairoGraphics *>(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<const gchar *>(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<UT_UCSChar*> *cpvEngineSuggestions = nullptr;
+					const UT_GenericVector<UT_UCSChar*> *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<char*>(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<const char *>(m_styleTable[istyle]));
-					attribs[attribsCount++] = m_styleTable[istyle].c_str();
+					if (istyle >= 0 && static_cast<UT_uint32>(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<const char *>(m_styleTable[istyle]));
-					attribs[attribsCount++] = m_styleTable[istyle].c_str();
+					if (istyle >= 0 && static_cast<UT_uint32>(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
 
design & coding: Vladimir Lettiev aka crux © 2004-2005, Andrew Avramenko aka liks © 2007-2008
current maintainer: Michael Shigorin