From b8dc6bb3cc2554f0fbadf37b0178f22e0766df2d Mon Sep 17 00:00:00 2001
From: Přemysl Janouch 
Date: Wed, 15 Oct 2014 00:51:05 +0200
Subject: Avoid flicker while resizing
---
 CMakeLists.txt | 11 +++++++----
 config.h.in    |  1 +
 src/sdtui.c    |  7 ++-----
 src/utils.c    | 40 ++++++++++++++++++++++++++++++++++++++++
 src/utils.h    |  1 +
 5 files changed, 51 insertions(+), 9 deletions(-)
diff --git a/CMakeLists.txt b/CMakeLists.txt
index 9612bfe..813d86c 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -20,10 +20,6 @@ set (project_VERSION "${project_VERSION_MAJOR}")
 set (project_VERSION "${project_VERSION}.${project_VERSION_MINOR}")
 set (project_VERSION "${project_VERSION}.${project_VERSION_PATCH}")
 
-# Configuration
-include (CheckFunctionExists)
-CHECK_FUNCTION_EXISTS ("wcwidth" HAVE_WCWIDTH)
-
 # Dependencies
 find_package (ZLIB REQUIRED)
 find_package (PkgConfig REQUIRED)
@@ -46,6 +42,13 @@ endif (USE_SYSTEM_TERMO)
 include_directories (${ZLIB_INCLUDE_DIRS}
 	${dependencies_INCLUDE_DIRS} ${Termo_INCLUDE_DIRS})
 
+# Configuration
+include (CheckFunctionExists)
+CHECK_FUNCTION_EXISTS ("wcwidth" HAVE_WCWIDTH)
+
+set (CMAKE_REQUIRED_LIBRARIES ${dependencies_LIBRARIES})
+CHECK_FUNCTION_EXISTS ("resize_term" HAVE_RESIZE_TERM)
+
 # Localization
 find_package (Gettext REQUIRED)
 file (GLOB project_PO_FILES ${CMAKE_CURRENT_SOURCE_DIR}/po/*.po)
diff --git a/config.h.in b/config.h.in
index a5fd1be..f125acb 100644
--- a/config.h.in
+++ b/config.h.in
@@ -9,6 +9,7 @@
 #define GETTEXT_DIRNAME "${CMAKE_INSTALL_PREFIX}/share/locale"
 
 #cmakedefine HAVE_WCWIDTH
+#cmakedefine HAVE_RESIZE_TERM
 
 #endif /* ! CONFIG_H */
 
diff --git a/src/sdtui.c b/src/sdtui.c
index b09de99..3dbcb03 100644
--- a/src/sdtui.c
+++ b/src/sdtui.c
@@ -43,6 +43,7 @@
 
 #include "config.h"
 #include "stardict.h"
+#include "utils.h"
 
 #define CTRL_KEY(x)  ((x) - 'A' + 1)
 
@@ -1186,11 +1187,7 @@ process_winch_input (GIOChannel *source,
 	char c;
 	read (g_io_channel_unix_get_fd (source), &c, 1);
 
-	// TODO: look for resizeterm() and use it if available for flicker-free
-	//   resize; endwin() escapes curses mode.
-	endwin ();
-	refresh ();
-
+	update_curses_terminal_size ();
 	app_process_resize (app);
 	return TRUE;
 }
diff --git a/src/utils.c b/src/utils.c
index 8636778..ebbd4a9 100644
--- a/src/utils.c
+++ b/src/utils.c
@@ -20,7 +20,16 @@
 
 #include 
 #include 
+#include 
+#include 
 
+#include 
+#include 
+#ifndef TIOCGWINSZ
+#include 
+#endif  // ! TIOCGWINSZ
+
+#include "config.h"
 #include "utils.h"
 
 
@@ -61,3 +70,34 @@ stream_read_string (GDataInputStream *dis, GError **error)
 
 	return s;
 }
+
+static bool
+xstrtoul (unsigned long *out, const char *s, int base)
+{
+	char *end;
+	errno = 0;
+	*out = strtoul (s, &end, base);
+	return errno == 0 && !*end && end != s;
+}
+
+// Didn't want to have this ugly piece of code in the main source file;
+// the standard endwin/refresh sequence makes the terminal flicker.
+void
+update_curses_terminal_size (void)
+{
+#if defined (HAVE_RESIZE_TERM) && defined (TIOCGWINSZ)
+	struct winsize size;
+	if (!ioctl (STDOUT_FILENO, TIOCGWINSZ, (char *) &size))
+	{
+		char *row = getenv ("LINES");
+		char *col = getenv ("COLUMNS");
+		unsigned long tmp;
+		resize_term (
+			(row && xstrtoul (&tmp, row, 10)) ? tmp : size.ws_row,
+			(col && xstrtoul (&tmp, col, 10)) ? tmp : size.ws_col);
+	}
+#else  // HAVE_RESIZE_TERM && TIOCGWINSZ
+	endwin ();
+	refresh ();
+#endif  // HAVE_RESIZE_TERM && TIOCGWINSZ
+}
diff --git a/src/utils.h b/src/utils.h
index 61c108e..c3bdd84 100644
--- a/src/utils.h
+++ b/src/utils.h
@@ -40,5 +40,6 @@
 
 gboolean stream_read_all (GByteArray *ba, GInputStream *is, GError **error);
 gchar *stream_read_string (GDataInputStream *dis, GError **error);
+void update_curses_terminal_size (void);
 
 #endif /* ! UTILS_H */
-- 
cgit v1.2.3-70-g09d2