Printing characters with ncurses fails - c

I am using XUBUNTU 16.04 and Geany.
I am starting to test the library ncurses. Bu I am not able to show characters. When I run the program a window appears, but the characters "a" and "*" does not appear.
This is my code:
#include <ncurses.h>
void line(char ch, int n)
{
int i;
for( i = 1; i<=n; i++ )
addch(ch);
}
int main()
{
clear();
line("a", 50);
line("*", 8);
return 0;
}

man curs_refresh:
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.
So your program is missing a refresh();.
It also looks like you're missing initialization/cleanup, i.e. calling initscr() at the beginning and endwin() at the end of your program.

Two things are missing:
initialization
something to keep the text on the screen momentarily
Initialization begins with initscr (or newterm, if you read the manual page). As written, the program would print something to the screen, and exit without pausing (and if your terminal uses the alternate screen, the text would vanish). A getch (read a character from the keyboard) does that, as well as doing refresh. By the way, the clear is unnecessary, because initscr does that:
The initscr code determines the terminal type and initializes all curses data structures. initscr also causes the first call to refresh(3x)
to clear the screen. If errors occur, initscr writes an appropriate
error message to standard error and exits; otherwise, a pointer is returned to stdscr.
Try this:
#include <curses.h>
void line(char ch, int n)
{
int i;
for( i = 1; i<=n; i++ )
addch(ch);
}
int main()
{
initscr();
cbreak();
noecho();
line("a", 50);
line("*", 8);
getch();
endwin();
return 0;
}

Related

Why printw does display in this case?

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);
}
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.
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.

How to use getch() in a loop (nCurses)

This is my first time using ncurses library. So, I wanted to use getch() to get a character as it is typed by the user (without pressing return every time). However, when I run this code:
#include <pthread.h>
#include <stdio.h>
#include <curses.h>
void *userInput() {
char c;
while((c = getch()) != '~') {
printf("%c\n",c);
}
pthread_exit(NULL);
}
int main() {
cbreak();
pthread_t threads[4];
pthread_create(&threads[0], NULL, userInput, NULL);
pthread_exit(NULL);
}
It printf lots of '?'s without getting any input. Could anyone please help me understand whats wrong?
Thank you.
EDIT: removed dead code.
There are at least three problems with the program:
getch will always return an error because you did not initialize the screen with initscr or newterm. Likewise, the cbreak call does nothing except return an error.
even if you initialized the screen, calling getch with multiple threads will not work predictably because it is not thread-safe. It's an FAQ: Why does (fill in the blank) happen when I use two threads?
the printf does something, but mixing stdio (printf) and curses does not work as you'd like. Use printw for curses applications.
As for printing ?, those -1's sent to a terminal which expects UTF-8 would likely decide they're not valid UTF-8 and display the replacement character.

Does ncurses getch() with echo() on ensure that the character will be visible on the screen before the next statement in the program is executed?

I have an ncurses program that looks like this
1. int c =0;
2. initscr();
3. timeout(-1);
4. printw("Enter a character");
5. getch();
6. printw("\nOkay\n");
7. c = 5;
I would expect that the output of getch() as well as following printw() should happen (and be visible on the screen) before c is modified to 5. However this does not seem to be happening ( Using qemu-kvm and breaking at that point to verify). Is there any reason why this might be happening or some way to ensure the output being visible on the screen before the next statement is executed ?
does fflush(stdout) guarantee that ?
The OS is virtualized gentoo being run using qemu-kvm. The screen is in console mode ( X not initialized).
You are probably forgetting to issue the refresh() command. See the following example code which appears to work:
#include <stdlib.h>
#include <stdio.h>
#include <unistd.h>
#include <curses.h>
int main(void) {
WINDOW * mainwin;
int c=0;
/* Initialize ncurses */
if ( (mainwin = initscr()) == NULL ) {
fprintf(stderr, "Error initialising ncurses.\n");
exit(EXIT_FAILURE);
}
timeout(-1);
printw("Enter a character: ");
getch();
printw("\nC = %d Ok\n", c);
c = 5;
printw("C is now %d\n",c);
refresh();
sleep(10);
/* Clean up after ourselves */
delwin(mainwin);
endwin();
refresh();
return EXIT_SUCCESS;
}

Can someone please explain line-by-line what this short, simple C program does and how I can run it?

#include<curses.h> //includes the curses library so it can be used in the function
main()
{ //opening main method
int i; //declare int i
initscr(); //creates a terminal of a specific type?
noecho(); // turn off echoing
for (i=0; I <5; i++) //loops from 0 to 4
getch(); //takes one character from the keyboard, I think ?
endwin();
} //restores the terminal
I am not sure about what this simple program is doing, and cannot seem to run it either ?
Could someone please help me out here ?
I think you are looking for:
initscr(); //This method initialize the current and standard screen
noecho(); // turn off echoing
for (i=0; i <5; i++) //loops from 0 to 4
getch(); //YES you thinks right, it takes one character from the keyboard.
endwin(); //The endwin() function restores the terminal, by flushing any output to the terminal and moving the cursor to the first column of the last line of the screen.

Print spinning cursor in a terminal running application using C

How would I print a spinning curser in a utility that runs in a terminal using standard C?
I'm looking for something that prints: \ | / - over and over in the same position on the screen?
Thanks
You could use the backspace character (\b) like this:
printf("processing... |");
fflush(stdout);
// do something
printf("\b/");
fflush(stdout);
// do some more
printf("\b-");
fflush(stdout);
etc. You need the fflush(stdout) because normally stdout is buffered until you output a newline.
Here's some example code. Call advance_cursor() every once in a while while the task completes.
#include <stdio.h>
void advance_cursor() {
static int pos=0;
char cursor[4]={'/','-','\\','|'};
printf("%c\b", cursor[pos]);
fflush(stdout);
pos = (pos+1) % 4;
}
int main(int argc, char **argv) {
int i;
for (i=0; i<100; i++) {
advance_cursor();
usleep(100000);
}
printf("\n");
return 0;
}
You can also use \r:
#include <stdio.h>
#include <unistd.h>
void
advance_spinner() {
static char bars[] = { '/', '-', '\\', '|' };
static int nbars = sizeof(bars) / sizeof(char);
static int pos = 0;
printf("%c\r", bars[pos]);
fflush(stdout);
pos = (pos + 1) % nbars;
}
int
main() {
while (1) {
advance_spinner();
usleep(300);
}
return 0;
}
I've done that, long ago. There are two ways.
Use a library like ncurses to give you control over the terminal. This works well if you want to do a lot of this kind of stuff. If you just one this in one little spot, it's obviously overkill.
Print a control character.
First you print "/", then 0x08 (backspace), then "-", then 0x08, then "\"....
The backspace character moves the cursor position back one space, but leaves the current character there until you overwrite it. Get the timing right (so it doesn't spin to fast or slow) and you're golden.
There is no truly "standard" way to do this, since the C Standard Library (http://members.aol.com/wantondeb/) does not provide functions to do raw terminal/console output.
In DOS/Windows console, the standard-ish way to do it is with conio.h, while under Unix/Linux the accepted library for this purpose is ncurses (ncurses basically encapsulates the control-character behavior that MBCook describes, in a terminal-independent way).

Resources