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
---
src/common/util-common.c | 13 +++++++++++++
src/common/util-common.h | 3 +++
src/pacman/pacman.c | 2 ++
src/pacman/sighandler.c | 5 +++++
src/pacman/util.c | 19 ++++++++++++++-----
src/pacman/util.h | 1 +
6 files changed, 38 insertions(+), 5 deletions(-)
diff --git a/src/common/util-common.c b/src/common/util-common.c
index 7d43ac0d..3850cffb 100644
--- a/src/common/util-common.c
+++ b/src/common/util-common.c
@@ -21,6 +21,7 @@
#include
#include
#include
+#include
#include "util-common.h"
@@ -104,6 +105,18 @@ int llstat(char *path, struct stat *buf)
return ret;
}
+void console_hide_cursor(void) {
+ if(isatty(fileno(stdout))) {
+ printf("\x1B[?25l");
+ }
+}
+
+void console_show_cursor(void) {
+ if(isatty(fileno(stdout))) {
+ printf("\x1B[?25h");
+ }
+}
+
/** Wrapper around fgets() which properly handles EINTR
* @param s string to read into
* @param size maximum length to read
diff --git a/src/common/util-common.h b/src/common/util-common.h
index 483d5da4..8eacde7e 100644
--- a/src/common/util-common.h
+++ b/src/common/util-common.h
@@ -28,6 +28,9 @@ char *mdirname(const char *path);
int llstat(char *path, struct stat *buf);
+void console_hide_cursor(void);
+void console_show_cursor(void);
+
char *safe_fgets(char *s, int size, FILE *stream);
void wordsplit_free(char **ws);
diff --git a/src/pacman/pacman.c b/src/pacman/pacman.c
index d58c428a..aafd9e63 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_show_cursor();
exit(ret);
}
@@ -1084,6 +1085,7 @@ int main(int argc, char *argv[])
int ret = 0;
uid_t myuid = getuid();
+ console_hide_cursor();
install_segv_handler();
/* i18n init */
diff --git a/src/pacman/sighandler.c b/src/pacman/sighandler.c
index 46e6481f..59aaa61f 100644
--- a/src/pacman/sighandler.c
+++ b/src/pacman/sighandler.c
@@ -27,6 +27,9 @@
#include "sighandler.h"
#include "util.h"
+/* the same ANSI sequence as used in console_show_cursor */
+#define SHOW_CURSOR_ANSI "\x1B[?25h"
+
/** Write function that correctly handles EINTR.
*/
static ssize_t xwrite(int fd, const void *buf, size_t count)
@@ -60,6 +63,7 @@ static void soft_interrupt_handler(int signum)
const char msg[] = "\nHangup signal received\n";
xwrite(STDERR_FILENO, msg, ARRAYSIZE(msg) - 1);
}
+ xwrite(STDOUT_FILENO, SHOW_CURSOR_ANSI, sizeof(SHOW_CURSOR_ANSI) - 1);
if(alpm_trans_interrupt(config->handle) == 0) {
/* a transaction is being interrupted, don't exit pacman yet. */
return;
@@ -95,6 +99,7 @@ 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, SHOW_CURSOR_ANSI, sizeof(SHOW_CURSOR_ANSI) - 1);
/* restore the default handler */
_reset_handler(signum);
diff --git a/src/pacman/util.c b/src/pacman/util.c
index a640ffb4..7dfbdbca 100644
--- a/src/pacman/util.c
+++ b/src/pacman/util.c
@@ -1391,6 +1391,15 @@ static int multiselect_parse(char *array, int count, char *response)
return 0;
}
+char *safe_fgets_stdin(char *s, int size)
+{
+ char *result;
+ console_show_cursor();
+ result = safe_fgets(s, size, stdin);
+ console_hide_cursor();
+ return result;
+}
+
int multiselect_question(char *array, int count)
{
char *response, *lastchar;
@@ -1427,7 +1436,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 +1452,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 +1503,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 +1591,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..fbc5f33c 100644
--- a/src/pacman/util.h
+++ b/src/pacman/util.h
@@ -77,6 +77,7 @@ 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);
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