C/C++ ncurses blank lines (newline) not being displayed on terminal/console window

I'm following a ncurses tutorial from here: https://www.viget.com/articles/game-programming-in-c-with-the-ncurses-library/

It shows how to make a simple bouncing character that goes left to right on the terminal window.

Here is the code, I modified it slightly:

Code:
#include <ncurses.h>
#include <unistd.h>
#include <string.h>

#define DELAY 30000

int main(int argc, char *argv[])
{
 int x = 0, y = 0;
 int max_y = 0, max_x = 0;
 int next_x = 0;
 int direction = 1;

 initscr();                         // Initialize the window
 noecho();                          // Don't echo any keypresses
 curs_set(TRUE);                    // Don't display a cursor
 getmaxyx(stdscr, max_y, max_x);    // Global var `stdscr` is created by the call to `initscr()`, get screen dimensions.

 while(1)
 {
    clear();

    mvprintw(y, x, "o");  // Moving object

    // Some basic info being displayed to know how the object is moving.
    mvprintw(1,1, "direction: %d", direction);
    mvprintw(2,1, "next_x: %d", next_x);
    mvprintw(3,1, "x: %d", x);
    mvprintw(4,1, "max_y: %d max_x: %d ", max_y, max_x);
   
    mvprintw(5,1, "\n\n\n");  // <---- Here is the newline, not displayed on terminal.

    refresh();

    usleep(DELAY);

    next_x = x + direction;

    if (next_x >= max_x || next_x < 0)
    {
        direction*= -1;
    }
    else
    {
        x+= direction;
    }  
 }

endwin();
}


Based on my code, I should get three newlines (blank lines), but terminal does not display it after I stop the program and scroll up.

These are the results displayed when I scroll up to the terminal after stopping the program:


Code:
                                o
 direction: 1
 next_x: 32
 x: 32
 max_y: 45 max_x: 162
                                 o
 direction: 1
 next_x: 33
 x: 33
 max_y: 45 max_x: 162
                                  o
 direction: 1
 next_x: 34
 x: 34
 max_y: 45 max_x: 162
                                   o
 direction: 1
 next_x: 35
 x: 35
 max_y: 45 max_x: 162
                                    o
 direction: 1
 next_x: 36
 x: 36
 max_y: 45 max_x: 162
                                     o
 direction: 1
 next_x: 37
 x: 37
 max_y: 45 max_x: 162
                                      o
 direction: 1
 next_x: 38
 x: 38
 max_y: 45 max_x: 162
                                       o
 direction: 1
 next_x: 39
 x: 39
 max_y: 45 max_x: 162
                                        o
 direction: 1
 next_x: 40
 x: 40
 max_y: 45 max_x: 162


As you can see, absolutely no newline is being displayed, between each iteration. I have tried null characters and it does not work either. For some reason, terminal discards newline or null characters.

How can I make terminal show the three blank new lines when I scroll upwards after stopping the program?

Using FreeBSD 13.1, clang compiler, headless, no desktop environment.

Thanks.
 

zirias@

Developer
Adding to that: Once you use control sequences that, for example, reposition the cursor (which I assume is the case here), contents of the scrollback buffer become somewhat ill-defined. Many terminals provide a second screen buffer and curses can optionally use that, so once you quit your curses application, there won't be a trace of it left, which is IMHO a pretty "clean" way to deal with that.
 
this most likely depends on your terminal software and how it implements history
mine shows a full screen for each iteration

Thanks for the quick reply.

Yes, it seems like it has something to do with the terminal implementation of history.

However, I did a simple test code of this:

Code:
#include <string.h>
#include <stdio.h>
#include <stdbool.h>

int main()
{
    int a = 0;
    bool b = true;
    while (b)
    {
        if (a < 50)
        {
            printf( "%d \n", a);
            printf( "\n\n\n");
            a++;
        }
        else if (a == 50)
        {
            printf( "%d \n", a);
            printf( "\n\n\n");
            b = false;
        }
    }
return 0;
}


The headless terminal output this:


Code:
root@FreeBSD_13:/usr/home/user/Downloads/ncurses/Tutorial # ./basic
0



1



2



3



4



5



6



7



8



9



10



11



12



13



14



15



16



17



18



19



20



21



22



23



24



25



26



27



28



29



30



31



32



33



34



35



36



37



38



39



40



41



42



43



44



45



46



47



48



49



50



root@FreeBSD_13:/usr/home/user/Downloads/ncurses/Tutorial #

It is showing all the proper ending newlines iterations.

With this and some further testing, I conclude that ncurses is erasing anything that is a newline character or null character, basically anything that is literally invisible will be erased and therefore it prevents a newline to be placed before the next iteration. Seems like a combination of the terminal software and ncurses is preventing to show the previous ending newlines.
I tried three different terminals so far, the FreeBSD headless stock terminal, MobaXterm Terminal SSH to FreeBSD and Microsoft Windows' Command Prompt SSH to FreeBSD all of which does not display the ending newlines.

I'm sure I'll figure it out, I'm new to ncurses.
 
Adding to that: Once you use control sequences that, for example, reposition the cursor (which I assume is the case here), contents of the scrollback buffer become somewhat ill-defined. Many terminals provide a second screen buffer and curses can optionally use that, so once you quit your curses application, there won't be a trace of it left, which is IMHO a pretty "clean" way to deal with that.

Interesting, not sure what a scrollback buffer is. Will need to do some googling.

Thanks.
 

zirias@

Developer
I did some googling now, cause it's been a while since I actually used curses. The feature I was talking about is called "alternate screen". This alternate screen does not have a scrollback buffer, while the normal screen of a terminal typically has.

The interesting thing here: As far as I could find, curses should automatically use the alternate screen when using initscr() and switch back to the normal screen on endwin(). So, if you find traces of your curses output in the scrollback buffer, it seems this didn't work as it should. Maybe the terminal just doesn't provide the "alternate screen" 🤔
 
I did some googling now, cause it's been a while since I actually used curses. The feature I was talking about is called "alternate screen". This alternate screen does not have a scrollback buffer, while the normal screen of a terminal typically has.

The interesting thing here: As far as I could find, curses should automatically use the alternate screen when using initscr() and switch back to the normal screen on endwin(). So, if you find traces of your curses output in the scrollback buffer, it seems this didn't work as it should. Maybe the terminal just doesn't provide the "alternate screen" 🤔

Thank You for the detailed info. Will look into this.
Would like to mention that the ending newlines do show up properly when they are saved to a text file if I used the script(1) program to output all terminal executions to a text file.
However its just that I would like them to appear on the terminal window history rather than saving it to a text file.
 
How can I make terminal show the three blank new lines when I scroll upwards after stopping the program?
I am not sure if i get what you want to achieve, but i'd use a standard printf after you exit ncurses with endwin();.

Printing the newlines within ncurses does not work. If you don't want to use that particular line, just don't write to it.
 
I am not sure if i get what you want to achieve, but i'd use a standard printf after you exit ncurses with endwin();.

Printing the newlines within ncurses does not work. If you don't want to use that particular line, just don't write to it.

After endwin() and not in the ncurses scope, printf("\n"); for some reason does not work. Even printf("\n"); before initscr(), does not work.

I will do some test, maybe using a simple timer based multitask program structure where the C program will run the ncurses program on it's own separate scope, then it will run a simple printf("\n"); program which is on a different scope, although I think this might not work since I have tried a similar approach using a while() loop.
I think compilation is also causing this error to be hard written to the compiled program, since it is dealing with ncurses library where ncurses is messing with the newline on the terminal history.

Ncurses for some reason erases or ignores any form of intended whitespace and blank lines, such as the "\n" newline escape sequence and all invisible character escape sequence either in printf("\n"); or ncurses syntax such as printw("\n"); or mvprintw(x, y, "\n");

Basically want the blank horizontal lines to give some space between each iteration, it's easier to read and scroll through the data after pressing the "ctrl+c" key to stop the program.
 
The three newlines print for me, in so far as I can see my cursor is three lines below the text as the program runs. It seems your problem is not about what is printed but what is saved in the terminal history. I don't think there is any standard for terminal history though so it will all depend on what you run and your settings.

Recall that your terminal emulator is emulating a teletype (TTY) which was a line printer with attached keyboard. History there is obvious...its printed further up the paper. Animation such as you are doing wasn't quite so simple though. Animation came along when TTYs got glass screens with virtual cursors and text you could erase. Then the concept of the history became harder. My terminal emulator (ROXTerm which I believe is using VTE under the hood) just shows the last thing that was drawn on each line (if I disable alt-screen) so if I scroll back I see the last "frame" and nothing else. That seems logical to me but each emulator can do what it likes... Therefore, unless your program will only target one specific emulator, I wouldn't spend much time on what appears in the history, only what appears on the screen.
 
The three newlines print for me, in so far as I can see my cursor is three lines below the text as the program runs. It seems your problem is not about what is printed but what is saved in the terminal history. I don't think there is any standard for terminal history though so it will all depend on what you run and your settings.

Recall that your terminal emulator is emulating a teletype (TTY) which was a line printer with attached keyboard. History there is obvious...its printed further up the paper. Animation such as you are doing wasn't quite so simple though. Animation came along when TTYs got glass screens with virtual cursors and text you could erase. Then the concept of the history became harder. My terminal emulator (ROXTerm which I believe is using VTE under the hood) just shows the last thing that was drawn on each line (if I disable alt-screen) so if I scroll back I see the last "frame" and nothing else. That seems logical to me but each emulator can do what it likes... Therefore, unless your program will only target one specific emulator, I wouldn't spend much time on what appears in the history, only what appears on the screen.
Yes, I am trying to view the saved terminal history. For one fact, my program will be designed to run in FreeBSD only. I think it would be better for the program to also be designed to one specific emulator and stick with that for the long run so that I know all the ins and outs for it, will be easier and organized that way.

I do agree, focusing to much to make this little effort to work is really not worth the time. I could run the program and just dump all the displayed iterations to a text file and use the text file as a history source to view iterations. The new lines at the end of each iteration do indeed dump properly to the text file. I think this is also a more professional approach. I could think of the text file as a temporary cache memory to save terminal history.

I’m designing a custom experimental cryptocurrency high frequency “market making” trading program. Using a web socket API provided by the exchange service, to request and save JSON response details to a database and at the save time conduct trades.
 
Top