FancyTerminalEventHandler: manually break lines in progress bar

Manually break lines in the progress bar (and only in the progress bar!)
that are longer than the terminal width. In this way, we avoid any
confusion about when the terminal advances a line; in particular, when
the terminal is wider than we believe, we do not erase back into the
scrollback buffer.

--
Change-Id: I19f21bdbd6e6af4665d1e712b921f1a15c7d901c
Reviewed-on: https://bazel-review.googlesource.com/#/c/3041
MOS_MIGRATED_REVID=116138487
diff --git a/src/main/java/com/google/devtools/build/lib/runtime/FancyTerminalEventHandler.java b/src/main/java/com/google/devtools/build/lib/runtime/FancyTerminalEventHandler.java
index b273649..bd233bf 100644
--- a/src/main/java/com/google/devtools/build/lib/runtime/FancyTerminalEventHandler.java
+++ b/src/main/java/com/google/devtools/build/lib/runtime/FancyTerminalEventHandler.java
@@ -21,6 +21,9 @@
 import com.google.devtools.build.lib.events.EventKind;
 import com.google.devtools.build.lib.util.Pair;
 import com.google.devtools.build.lib.util.io.AnsiTerminal;
+import com.google.devtools.build.lib.util.io.AnsiTerminalWriter;
+import com.google.devtools.build.lib.util.io.LineCountingAnsiTerminalWriter;
+import com.google.devtools.build.lib.util.io.LineWrappingAnsiTerminalWriter;
 import com.google.devtools.build.lib.util.io.OutErr;
 
 import org.joda.time.Duration;
@@ -261,33 +264,29 @@
       }
     }
 
+    LineCountingAnsiTerminalWriter countingWriter = new LineCountingAnsiTerminalWriter(terminal);
+    AnsiTerminalWriter terminalWriter =
+        new LineWrappingAnsiTerminalWriter(countingWriter, terminalWidth - 1);
+
     if (useColor) {
-      terminal.textGreen();
+      terminalWriter.okStatus();
     }
-    int prefixWidth = prefix.length();
-    terminal.writeString(prefix);
-    terminal.resetTerminal();
+    terminalWriter.append(prefix);
+    terminalWriter.normal();
     if (showTimestamp) {
       String timestamp = timestamp();
-      prefixWidth += timestamp.length();
-      terminal.writeString(timestamp);
+      terminalWriter.append(timestamp);
     }
-    int numLines = 0;
     Iterator<String> lines = LINEBREAK_SPLITTER.split(rest).iterator();
     String firstLine = lines.next();
-    terminal.writeString(firstLine);
-    // Subtract one, because when the line length is the same as the terminal
-    // width, the terminal doesn't line-advance, so we don't want to erase
-    // two lines.
-    numLines += (prefixWidth + firstLine.length() - 1) / terminalWidth + 1;
-    crlf();
+    terminalWriter.append(firstLine);
+    terminalWriter.newline();
     while (lines.hasNext()) {
       String line = lines.next();
-      terminal.writeString(line);
-      crlf();
-      numLines += (line.length() - 1) / terminalWidth + 1;
+      terminalWriter.append(line);
+      terminalWriter.newline();
     }
-    numLinesPreviousErasable = numLines;
+    numLinesPreviousErasable = countingWriter.getWrittenLines();
   }
 
   /**