Use ASCII control codes to hide cursor at the pacman start and then
show the cursor when pacman finishes.

It helps to avoid annoying blinking when progress bars are re-drawn.

Cursor is reenabled if pacman expects user's input.

Signed-off-by: Anatol Pomozov <[email protected]>
---
 src/pacman/pacman.c     |  2 ++
 src/pacman/sighandler.c |  4 ++++
 src/pacman/util.c       | 31 ++++++++++++++++++++++++++-----
 src/pacman/util.h       |  6 ++++++
 4 files changed, 38 insertions(+), 5 deletions(-)

diff --git a/src/pacman/pacman.c b/src/pacman/pacman.c
index d58c428a..fefd3fa4 100644
--- a/src/pacman/pacman.c
+++ b/src/pacman/pacman.c
@@ -300,6 +300,7 @@ static void cleanup(int ret)
 
        /* free memory */
        FREELIST(pm_targets);
+       console_cursor_show();
        exit(ret);
 }
 
@@ -1084,6 +1085,7 @@ int main(int argc, char *argv[])
        int ret = 0;
        uid_t myuid = getuid();
 
+       console_cursor_hide();
        install_segv_handler();
 
        /* i18n init */
diff --git a/src/pacman/sighandler.c b/src/pacman/sighandler.c
index 46e6481f..fc4ea766 100644
--- a/src/pacman/sighandler.c
+++ b/src/pacman/sighandler.c
@@ -60,6 +60,8 @@ static void soft_interrupt_handler(int signum)
                const char msg[] = "\nHangup signal received\n";
                xwrite(STDERR_FILENO, msg, ARRAYSIZE(msg) - 1);
        }
+       xwrite(STDOUT_FILENO, CURSOR_SHOW_ANSICODE,
+               sizeof(CURSOR_SHOW_ANSICODE) - 1);
        if(alpm_trans_interrupt(config->handle) == 0) {
                /* a transaction is being interrupted, don't exit pacman yet. */
                return;
@@ -95,6 +97,8 @@ static void segv_handler(int signum)
        const char msg[] = "\nerror: segmentation fault\n"
                "Please submit a full bug report with --debug if 
appropriate.\n";
        xwrite(STDERR_FILENO, msg, sizeof(msg) - 1);
+       xwrite(STDOUT_FILENO, CURSOR_SHOW_ANSICODE,
+               sizeof(CURSOR_SHOW_ANSICODE) - 1);
 
        /* restore the default handler */
        _reset_handler(signum);
diff --git a/src/pacman/util.c b/src/pacman/util.c
index a640ffb4..a3a85bb9 100644
--- a/src/pacman/util.c
+++ b/src/pacman/util.c
@@ -1391,6 +1391,27 @@ static int multiselect_parse(char *array, int count, 
char *response)
        return 0;
 }
 
+void console_cursor_hide(void) {
+       if(isatty(fileno(stdout))) {
+               printf(CURSOR_HIDE_ANSICODE);
+       }
+}
+
+void console_cursor_show(void) {
+       if(isatty(fileno(stdout))) {
+               printf(CURSOR_SHOW_ANSICODE);
+       }
+}
+
+char *safe_fgets_stdin(char *s, int size)
+{
+       char *result;
+       console_cursor_show();
+       result = safe_fgets(s, size, stdin);
+       console_cursor_hide();
+       return result;
+}
+
 int multiselect_question(char *array, int count)
 {
        char *response, *lastchar;
@@ -1427,7 +1448,7 @@ int multiselect_question(char *array, int count)
 
                flush_term_input(fileno(stdin));
 
-               if(safe_fgets(response, response_len, stdin)) {
+               if(safe_fgets_stdin(response, response_len)) {
                        const size_t response_incr = 64;
                        size_t len;
                        /* handle buffer not being large enough to read full 
line case */
@@ -1443,8 +1464,8 @@ int multiselect_question(char *array, int count)
                                lastchar = response + response_len - 1;
                                /* sentinel byte */
                                *lastchar = 1;
-                               if(safe_fgets(response + response_len - 
response_incr - 1,
-                                                       response_incr + 1, 
stdin) == 0) {
+                               if(safe_fgets_stdin(response + response_len - 
response_incr - 1,
+                                                       response_incr + 1) == 
0) {
                                        free(response);
                                        return -1;
                                }
@@ -1494,7 +1515,7 @@ int select_question(int count)
 
                flush_term_input(fileno(stdin));
 
-               if(safe_fgets(response, sizeof(response), stdin)) {
+               if(safe_fgets_stdin(response, sizeof(response))) {
                        size_t len = strtrim(response);
                        if(len > 0) {
                                int n;
@@ -1582,7 +1603,7 @@ static int question(short preset, const char *format, 
va_list args)
 
        flush_term_input(fd_in);
 
-       if(safe_fgets(response, sizeof(response), stdin)) {
+       if(safe_fgets_stdin(response, sizeof(response))) {
                size_t len = strtrim(response);
                if(len == 0) {
                        return preset;
diff --git a/src/pacman/util.h b/src/pacman/util.h
index 2cee479f..2b21f3d5 100644
--- a/src/pacman/util.h
+++ b/src/pacman/util.h
@@ -28,6 +28,9 @@
 
 #include "util-common.h"
 
+#define CURSOR_HIDE_ANSICODE "\x1B[?25l"
+#define CURSOR_SHOW_ANSICODE "\x1B[?25h"
+
 #ifdef ENABLE_NLS
 #include <libintl.h> /* here so it doesn't need to be included elsewhere */
 /* define _() as shortcut for gettext() */
@@ -77,6 +80,9 @@ int colon_printf(const char *format, ...) 
__attribute__((format(printf, 1, 2)));
 int yesno(const char *format, ...) __attribute__((format(printf, 1, 2)));
 int noyes(const char *format, ...) __attribute__((format(printf, 1, 2)));
 char *arg_to_string(int argc, char *argv[]);
+char *safe_fgets_stdin(char *s, int size);
+void console_cursor_hide(void);
+void console_cursor_show(void);
 
 int pm_printf(alpm_loglevel_t level, const char *format, ...) 
__attribute__((format(printf,2,3)));
 int pm_asprintf(char **string, const char *format, ...) 
__attribute__((format(printf,2,3)));
-- 
2.25.1

Reply via email to