From b053a5da5e010cc4bc13385e7ccb012f013fe2cf Mon Sep 17 00:00:00 2001
From: Kamil Dudka <kdudka@redhat.com>
Date: Wed, 4 Apr 2012 14:19:16 +0200
Subject: [PATCH] curl tool: do not print \r to dumb terminals

... if built with ncurses support.
---
 configure.ac      |   48 ++++++++++++++++++++++++++++++++++++++++++++++++
 src/tool_cb_prg.c |   35 +++++++++++++++++++++++++++++++++--
 src/tool_cb_prg.h |    2 ++
 3 files changed, 83 insertions(+), 2 deletions(-)

diff --git a/configure.ac b/configure.ac
index 7feb364..fa56b95 100644
--- a/configure.ac
+++ b/configure.ac
@@ -2577,6 +2577,54 @@ if test "$want_idn" = "yes"; then
 fi
 
 
+dnl **********************************************************************
+dnl If --with-ncurses was specified, check for its presence and usability.
+dnl **********************************************************************
+
+OPT_NCURSES=no
+
+AC_ARG_WITH(ncurses,
+AC_HELP_STRING([--with-ncurses],[Enable ncurses support if available]),
+  [OPT_NCURSES=$withval])
+
+if test "x$OPT_NCURSES" != xno; then
+  if test "x$OPT_NCURSES" = xyes; then
+    CURL_CHECK_PKGCONFIG(ncurses)
+    if test "$PKGCONFIG" != "no" ; then
+      addlib=`$PKGCONFIG --libs ncurses`
+      addcflags=`$PKGCONFIG --cflags ncurses`
+    else
+      # fallback to default
+      addlib="-lcurses"
+      addcflags=""
+    fi
+  else
+    # Without pkg-config, we'll kludge in some defaults
+    addlib="-L$OPT_NCURSES/lib -lcurses"
+    addcflags="-I$OPT_NCURSES/include"
+  fi
+
+  CLEANLIBS="$LIBS"
+  CLEANCPPFLAGS="$CPPFLAGS"
+
+  LIBS="$LIBS $addlib"
+  if test "$addcflags" != "-I/usr/include"; then
+    CPPFLAGS="$CPPFLAGS $addcflags"
+  fi
+
+  AC_CHECK_HEADERS([term.h])
+  AC_CHECK_LIB(curses, tgetent)
+  if test $ac_cv_header_term_h = yes &&
+     test $ac_cv_lib_curses_tgetent = yes; then
+     AC_DEFINE(USE_NCURSES, 1, [if NCURSES is enabled])
+  else
+     AC_MSG_WARN([ncurses not found])
+     LIBS="$CLEANLIBS"
+     CPPFLAGS="$CLEANCPPFLAGS"
+  fi
+fi
+
+
 dnl Let's hope this split URL remains working:
 dnl http://publibn.boulder.ibm.com/doc_link/en_US/a_doc_lib/aixprggd/ \
 dnl genprogc/thread_quick_ref.htm
diff --git a/src/tool_cb_prg.c b/src/tool_cb_prg.c
index 457c1a7..4b7ecde 100644
--- a/src/tool_cb_prg.c
+++ b/src/tool_cb_prg.c
@@ -32,6 +32,10 @@
 
 #include "memdebug.h" /* keep this as LAST include */
 
+#ifdef USE_NCURSES
+# include <term.h>
+#endif
+
 /*
 ** callback for CURLOPT_PROGRESSFUNCTION
 */
@@ -85,11 +89,27 @@ int tool_progress_cb(void *clientp,
     num = (int) (((double)barwidth) * frac);
     if(num > MAX_BARLENGTH)
       num = MAX_BARLENGTH;
+
+    if(bar->dummy_term) {
+      const int diff = num - bar->cnt_printed;
+      if(0 < diff) {
+        bar->cnt_printed = num;
+        num = diff;
+      }
+      else
+        num = 0;
+    }
+
     for(i = 0; i < num; i++)
       line[i] = '#';
     line[i] = '\0';
-    snprintf(format, sizeof(format), "\r%%-%ds %%5.1f%%%%", barwidth);
-    fprintf(bar->out, format, line, percent);
+
+    if(bar->dummy_term)
+      fputs(line, bar->out);
+    else {
+      snprintf(format, sizeof(format), "\r%%-%ds %%5.1f%%%%", barwidth);
+      fprintf(bar->out, format, line, percent);
+    }
   }
   fflush(bar->out);
   bar->prev = point;
@@ -105,6 +125,9 @@ void progressbarinit(struct ProgressData *bar,
   int scr_size[2];
 #endif
   char *colp;
+#ifdef USE_NCURSES
+  char *term;
+#endif
 
   memset(bar, 0, sizeof(struct ProgressData));
 
@@ -143,6 +166,14 @@ void progressbarinit(struct ProgressData *bar,
   bar->width = scr_size[0] - 1;
 #endif
 
+#ifdef USE_NCURSES
+  term = curlx_getenv("TERM");
+  if(term) {
+    bar->dummy_term = (1 != tgetent(NULL, term)) || !tgetstr("cr", NULL);
+    free(term);
+  }
+#endif
+
   bar->out = config->errors;
 }
 
diff --git a/src/tool_cb_prg.h b/src/tool_cb_prg.h
index f64335a..c0e29fd 100644
--- a/src/tool_cb_prg.h
+++ b/src/tool_cb_prg.h
@@ -32,6 +32,8 @@ struct ProgressData {
   int         width;
   FILE       *out;  /* where to write everything to */
   curl_off_t  initial_size;
+  bool        dummy_term;
+  int         cnt_printed;
 };
 
 void progressbarinit(struct ProgressData *bar,
-- 
1.7.1


