0

Why in this case, printw displays "Blah" ? I use nocbreak. So printw is not supposed to produce output normally, because the output is line-buffered.

int main(int ac, char **av)
{
    initscr();
    nocbreak();
    printw("Blah");
    refresh();
    while (1);
}
Progear
  • 157
  • 8

2 Answers2

3

Actually, printw is not line-buffered. ncurses initializes the terminal to raw mode and simulates cooked mode as needed. But that applies only to input. For output, ncurses will immediately write the relevant updates to the screen as noted in the manual page:

The refresh and wrefresh routines (or wnoutrefresh and doupdate) must be called to get actual output to the terminal, as other routines merely manipulate data structures. The routine wrefresh copies the named window to the physical screen, taking into account what is already there to do optimizations. The refresh routine is the same, using stdscr as the default window. Unless leaveok has been enabled, the physical cursor of the terminal is left at the location of the cursor for that window.

The physical screen is your terminal, of course. ncurses remembers what's there by recording it in curscr:

This implementation of curses uses a special window curscr to record its updates to the terminal screen.

This is referred to as the "physical screen" in the curs_refresh(3x) and curs_outopts(3x) manual pages.

From ncurses' viewpoint, the terminal (that you see) and curscr are the same thing.

For printw, the manual page says it acts as if it calls waddstr, and that in turn calls waddch:

These functions write the (null-terminated) character string str on the given window. It is similar to calling waddch once for each character in the string.

Thomas Dickey
  • 51,086
  • 7
  • 70
  • 105
  • Ok ok thanks for your answer, but now i don’t know when it might be relevant to use cbreak(), since printw doesn’t act as printf ! – Progear May 22 '19 at 06:00
  • `cbreak` tells ncurses (part of) how to simulate cooked versus raw *input* modes, so it's not relevant to `printw` (an *output* function). – Thomas Dickey May 22 '19 at 08:54
1

It is because of the call to refresh.

The refresh man page does not explicitly state it, but it seems to apply the buffered outputs as well.

Without the call to refresh, no output is shown.

If you add a call to getch instead of refresh, you get the output too, because getch does a wrefresh. Man page:

If the window is not a pad, and it has been moved or modified since the last call to wrefresh, wrefresh will be called before another character is read.

To see the different behavior for inputs in cbreak/nocbreak mode, you can use this program:

int main(int ac, char **av)
{
    char c, i;
    initscr();
    noecho();  // switch off display of typed characters by the tty

    printw("cbreak\n");
    cbreak();
    for (i = 0; i < 5; ++i) {
        c = getch();
        printw("%c", c);
    }

    printw("\nnocbreak\n");
    nocbreak();
    for (i = 0; i < 5; ++i) {
        c = getch();
        printw("%c", c);
    }

    return 0;
}

In cbreak mode, the program sees the five input characters as you type them (and outputs immediately due to getch). In nocbreak mode, they will be received and output only after you press return.

undur_gongor
  • 15,657
  • 5
  • 63
  • 75
  • Ok ok ok, I did this test to see how cbreak() works. Do you have a test to show that it works? Because I had used refresh() to update the terminal but now I don't know what to use... – Progear May 21 '19 at 20:59
  • So you want to see that output in nocbreak mode is line-buffered? You see this because without `refresh` nothing is displayed. If you `printw("Blah\n");` however, it is printed even without the `refresh`. – undur_gongor May 21 '19 at 21:06
  • 1
    You are right. `cbreak`/`nocbreak` is about input: Does the program receive key strokes immediately or only after newline. "Normally, the tty driver buffers typed characters until a newline or carriage return is typed. The cbreak routine disables line buffering and erase/kill character-processing (interrupt and flow control characters are unaffected), making characters typed by the user immediately available to the program." For the output, you always need a refresh (or similar) to make it visible. – undur_gongor May 21 '19 at 21:22