Unclear ANSI CUB/CUF behaviour

  ansi, c++, escaping

While studying the ANSI control sequences I came across unclear behaviour.

I tried to make "matrix" effect in terminal, which
changes one random digit per loop iteration in a row of n 0/1 digits:

#include <iostream>
#include <chrono>
#include <thread>

const int n = 5; // row length
const int pause = 50; // milliseconds

int main() {
    using namespace std;
    using this_thread::sleep_for;
    using chrono::milliseconds;

    for (int i = 0; i < n; i++) {
      cout << rand() % 2;
    }

    int offset;
    while (true) {
      offset = rand() % n + 1; // random digit in row 1..n

      cout << "x1b[" << offset << "D";
      cout.flush();
      sleep_for(milliseconds(pause));

      cout << rand() % 2;
      cout.flush();
      // cout << "x1b[" << 1 << "D";
      // cout.flush();
      sleep_for(milliseconds(pause));

      cout << "x1b[" << offset - 1 << "C";
      cout.flush();
      sleep_for(milliseconds(pause));
    }
}

As far as I understand CSI offset D moves cursor back offset times if it’s possible in current row, then I cout random digit, that moves cursor 1 time forward, then I use CSI offset – 1 C to move it forward offset – 1 times, that should return cursor to n + 1 row position, so n digits go before cursor, but sometimes it goes further than n + 1, so, after several iterations it ends up at the end of the row. I would like to know why it happens.

However, when I use cout << "x1b[" << 1 << "D"; and then cout << "x1b[" << offset << "C"; instead of cout << "x1b[" << offset - 1 << "C"; it works fine.

I’m also aware of using CSI n G, which also works fine, but I want to understand what’s going on with CSI n C/D . Maybe it’s my maths fault, but not using cout << "x1b[" << 1 << "D"; seems to be equivalent of using cout << "x1b[" << offset - 1 << "C"; so it’s really confusing to me.

Source: Windows Questions C++

LEAVE A COMMENT