Просмотр исходного кода

Wide character special handling during reflow

devmil 4 лет назад
Родитель
Сommit
2f0078f50a

+ 35 - 1
lib/buffer/buffer_line.dart

@@ -201,9 +201,13 @@ class BufferLine {
     cellSetFgColor(index, cursor.fg);
     cellSetBgColor(index, cursor.bg);
     cellSetFlags(index, cursor.flags);
+    cellSetWidth(index, 0);
   }
 
-  int getTrimmedLength(int cols) {
+  int getTrimmedLength([int? cols]) {
+    if (cols == null) {
+      cols = _maxCols;
+    }
     for (int i = cols; i >= 0; i--) {
       if (cellGetContent(i) != 0) {
         int length = 0;
@@ -245,4 +249,34 @@ class BufferLine {
       cellSetContent(index, 0x00);
     }
   }
+
+  @override
+  String toString() {
+    final result = StringBuffer();
+    for (int i = 0; i < _maxCols; i++) {
+      final code = cellGetContent(i);
+      if (code == 0) {
+        continue;
+      }
+      result.writeCharCode(code);
+    }
+    return result.toString();
+  }
+
+  String toDebugString(int cols) {
+    final result = StringBuffer();
+    final length = getTrimmedLength();
+    for (int i = 0; i < max(cols, length); i++) {
+      var code = cellGetContent(i);
+      if (code == 0) {
+        if (cellGetWidth(i) == 0) {
+          code = '_'.runes.first;
+        } else {
+          code = cellGetWidth(i).toString().runes.first;
+        }
+      }
+      result.writeCharCode(code);
+    }
+    return result.toString();
+  }
 }

+ 22 - 6
lib/buffer/reflow_strategy_narrower.dart

@@ -11,12 +11,13 @@ class ReflowStrategyNarrower extends ReflowStrategy {
 
   @override
   void reflow(int newCols, int newRows, int oldCols, int oldRows) {
+    //print('Reflow narrower $oldCols -> $newCols');
     for (var i = 0; i < buffer.lines.length; i++) {
       final line = buffer.lines[i];
-      final lineLength = line.getTrimmedLength(oldCols);
+      final lineLength = line.getTrimmedLength();
       if (lineLength > newCols) {
         var moveIndexStart = newCols;
-        var cellsToCopy = oldCols - newCols;
+        var cellsToCopy = lineLength - newCols;
 
         // when we have a double width character and are about to move the "0" placeholder,
         // then we have to move the double width character as well
@@ -26,17 +27,28 @@ class ReflowStrategyNarrower extends ReflowStrategy {
           cellsToCopy += 1;
         }
 
+        var addZero = false;
+        //when the last cell to copy is a double width cell, then add a "0"
+        if (line.cellGetWidth(moveIndexStart + cellsToCopy - 1) == 2) {
+          addZero = true;
+        }
+
         // we need to move cut cells to the next line
         // if the next line is wrapped anyway, we can push them onto the beginning of that line
         // otherwise, we need add a new wrapped line
         if (i + 1 < buffer.lines.length) {
           final nextLine = buffer.lines[i + 1];
           if (nextLine.isWrapped) {
-            nextLine.ensure(oldCols + cellsToCopy); //to be safe
-            nextLine.insertN(0, cellsToCopy);
+            final nextLineLength = nextLine.getTrimmedLength();
+            nextLine.ensure(nextLineLength + cellsToCopy + (addZero ? 1 : 0));
+            nextLine.insertN(0, cellsToCopy + (addZero ? 1 : 0));
             nextLine.copyCellsFrom(line, moveIndexStart, 0, cellsToCopy);
             // clean the cells that we moved
-            line.erase(buffer.terminal.cursor, moveIndexStart, oldCols);
+            line.erase(buffer.terminal.cursor, moveIndexStart,
+                moveIndexStart + cellsToCopy);
+            //print('M: ${i < 10 ? '0' : ''}$i: ${line.toDebugString(oldCols)}');
+            //print(
+            //    'N: ${i + 1 < 10 ? '0' : ''}${i + 1}: ${nextLine.toDebugString(oldCols)}');
             continue;
           }
         }
@@ -45,11 +57,15 @@ class ReflowStrategyNarrower extends ReflowStrategy {
         newLine.ensure(max(newCols, cellsToCopy));
         newLine.copyCellsFrom(line, moveIndexStart, 0, cellsToCopy);
         // clean the cells that we moved
-        line.erase(buffer.terminal.cursor, moveIndexStart, oldCols);
+        line.erase(buffer.terminal.cursor, moveIndexStart, lineLength);
 
         buffer.lines.insert(i + 1, newLine);
 
         //TODO: scrolling is a bit weird afterwards
+
+        //print('S: ${i < 10 ? '0' : ''}$i: ${line.toDebugString(oldCols)}');
+      } else {
+        //print('N: ${i < 10 ? '0' : ''}$i: ${line.toDebugString(oldCols)}');
       }
     }
   }

+ 15 - 4
lib/buffer/reflow_strategy_wider.dart

@@ -17,14 +17,25 @@ class ReflowStrategyWider extends ReflowStrategy {
         if (!nextLine.isWrapped) {
           break;
         }
-        final lineLength = line.getTrimmedLength(oldCols);
-        final spaceOnLine = newCols - lineLength;
+        final lineLength = line.getTrimmedLength();
+
+        var copyDestIndex = lineLength;
+        if (line.cellGetWidth(copyDestIndex - 1) == 2 &&
+            line.cellGetContent(copyDestIndex) == 0) {
+          //we would override a wide char placeholder => move index one to the right
+          copyDestIndex += 1;
+        }
+
+        final spaceOnLine = newCols - copyDestIndex;
         if (spaceOnLine <= 0) {
           // no more space to unwrap
           break;
         }
-        final nextLineLength = nextLine.getTrimmedLength(oldCols);
+        final nextLineLength = nextLine.getTrimmedLength();
         var moveCount = min(spaceOnLine, nextLineLength);
+        if (moveCount <= 0) {
+          break;
+        }
 
         // when we are about to copy a double width character
         // to the end of the line then we can include the 0 width placeholder
@@ -33,7 +44,7 @@ class ReflowStrategyWider extends ReflowStrategy {
             nextLine.cellGetContent(moveCount) == 0) {
           moveCount += 1;
         }
-        line.copyCellsFrom(nextLine, 0, lineLength, moveCount);
+        line.copyCellsFrom(nextLine, 0, copyDestIndex, moveCount);
         if (moveCount >= nextLineLength) {
           // if we unwrapped all cells off the next line, delete it
           buffer.lines.remove(i + offset);