[PATCH] winansi: support ESC [ K (erase in line)

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



To make use of it during a fetch, write() needs to be overridden, too.

Signed-off-by: Johannes Schindelin <johannes.schindelin@xxxxxx>
---

	This fixes the last bit of msysGit issue 124 for me:

		http://code.google.com/p/msysgit/issues/detail?id=124

	which annoyed me one time to many today.

	I had an earlier version which was smaller, but pretty hacky, in 
	that it checked if fprintf is #define'd in xwrite(), and had 
	special handling for that case.

	This patch is only slightly hacky, in that it assumes that you do 
	not try to output something that ends in an incomplete ESC [
	sequence.

 compat/mingw.h   |    2 ++
 compat/winansi.c |   51 +++++++++++++++++++++++++++++++++++++++------------
 2 files changed, 41 insertions(+), 12 deletions(-)

diff --git a/compat/mingw.h b/compat/mingw.h
index b82903c..9aac4e1 100644
--- a/compat/mingw.h
+++ b/compat/mingw.h
@@ -192,9 +192,11 @@ sig_handler_t mingw_signal(int sig, sig_handler_t handler);
 int winansi_fputs(const char *str, FILE *stream);
 int winansi_printf(const char *format, ...) __attribute__((format (printf, 1, 2)));
 int winansi_fprintf(FILE *stream, const char *format, ...) __attribute__((format (printf, 2, 3)));
+int winansi_write(int fd, const void *buf, size_t len);
 #define fputs winansi_fputs
 #define printf(...) winansi_printf(__VA_ARGS__)
 #define fprintf(...) winansi_fprintf(__VA_ARGS__)
+#define write winansi_write
 
 /*
  * git specific compatibility
diff --git a/compat/winansi.c b/compat/winansi.c
index e2d96df..a9d981c 100644
--- a/compat/winansi.c
+++ b/compat/winansi.c
@@ -11,15 +11,13 @@
 #undef printf
 #undef fprintf
 #undef fputs
-/* TODO: write */
+#undef write
 
 /*
  ANSI codes used by git: m, K
 
  This file is git-specific. Therefore, this file does not attempt
  to implement any codes that are not used by git.
-
- TODO: K
 */
 
 static HANDLE console;
@@ -79,6 +77,20 @@ static void set_console_attr(void)
 	SetConsoleTextAttribute(console, attributes);
 }
 
+static void erase_in_line(void)
+{
+	CONSOLE_SCREEN_BUFFER_INFO sbi;
+
+	if (!console)
+		return;
+
+	GetConsoleScreenBufferInfo(console, &sbi);
+	FillConsoleOutputCharacterA(console, ' ',
+		sbi.dwSize.X - sbi.dwCursorPosition.X, sbi.dwCursorPosition,
+		NULL);
+}
+
+
 static const char *set_attr(const char *str)
 {
 	const char *func;
@@ -218,7 +230,7 @@ static const char *set_attr(const char *str)
 		set_console_attr();
 		break;
 	case 'K':
-		/* TODO */
+		erase_in_line();
 		break;
 	default:
 		/* Unsupported code */
@@ -228,13 +240,16 @@ static const char *set_attr(const char *str)
 	return func + 1;
 }
 
-static int ansi_emulate(const char *str, FILE *stream)
+static int ansi_emulate(const char *str, ssize_t len, FILE *stream)
 {
 	int rv = 0;
 	const char *pos = str;
 
-	while (*pos) {
-		pos = strstr(str, "\033[");
+	if (len < 0)
+		len = strlen(str);
+
+	while (rv < len) {
+		pos = memmem(str, len - rv, "\033[", 2);
 		if (pos) {
 			size_t len = pos - str;
 
@@ -254,10 +269,11 @@ static int ansi_emulate(const char *str, FILE *stream)
 			rv += pos - str;
 			str = pos;
 		} else {
-			rv += strlen(str);
-			fputs(str, stream);
-			return rv;
+			fwrite(str, len - rv, 1, stream);
+			return len;
 		}
+		if (rv > len)
+			die ("Invalid use of ESC [ sequence detected");
 	}
 	return rv;
 }
@@ -274,7 +290,7 @@ int winansi_fputs(const char *str, FILE *stream)
 	if (!console)
 		return fputs(str, stream);
 
-	rv = ansi_emulate(str, stream);
+	rv = ansi_emulate(str, -1, stream);
 
 	if (rv >= 0)
 		return 0;
@@ -309,7 +325,7 @@ static int winansi_vfprintf(FILE *stream, const char *format, va_list list)
 		len = vsnprintf(buf, len + 1, format, list);
 	}
 
-	rv = ansi_emulate(buf, stream);
+	rv = ansi_emulate(buf, -1, stream);
 
 	if (buf != small_buf)
 		free(buf);
@@ -343,3 +359,14 @@ int winansi_printf(const char *format, ...)
 
 	return rv;
 }
+
+int winansi_write(int fd, const void *buf, size_t len)
+{
+	if (isatty(fd)) {
+		init();
+		if (console)
+			return ansi_emulate((const char *)buf, len,
+					fd == 2 ? stderr : stdout);
+	}
+	return write(fd, buf, len);
+}
-- 
1.6.2.240.g23c7

--
To unsubscribe from this list: send the line "unsubscribe git" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at  http://vger.kernel.org/majordomo-info.html

[Index of Archives]     [Linux Kernel Development]     [Gcc Help]     [IETF Annouce]     [DCCP]     [Netdev]     [Networking]     [Security]     [V4L]     [Bugtraq]     [Yosemite]     [MIPS Linux]     [ARM Linux]     [Linux Security]     [Linux RAID]     [Linux SCSI]     [Fedora Users]

  Powered by Linux