I am trying to clear my console each time I am going to printf something in it (Windows environment with GCC compiler). I am using CygWin and the only way I could manage to do it was with system("cmd /c cls");. That works fine but it causes the screen to blink for a fraction of a second which is obviously annoying.
Is there any alternative way of clearing console screen?
First thing I'd do is stop using cmd to do it. CygWin, assuming you're running somewhere within the shell and not a Windows console, has a "native" option in that you can use either of:
clear
tput clear
to clear the screen, without invoking the external cmd interpreter.
So, from within a program running in CygWin, you can clear the screen with a simple:
system("clear");
Of course, if you don't want to run any external executables, you can achieve the same end with curses. By way of example, the following program clears the screen for you (make sure you include -lcurses at the end of the compilation command):
#include <curses.h>
int main (void) {
WINDOW *w = initscr();
clear(); refresh(); sleep(2);
endwin();
return 0;
}
Don't get hung up on the fact that it's restored on exit, you wouldn't be using this program as a screen clearing stand-alone thing. Instead, the statements would be incorporated into your own program, between the initscr() and endwin() calls, something like:
#include <curses.h>
int main (void) {
char buf[2],
*msg = "Now is the time for all good men to come to lunch.";
WINDOW *w = initscr();
buf[1] = '\0';
clear();
refresh();
while (*msg != '\0') {
buf[0] = *msg++; addstr(buf);
if ((buf[0] == ' ') || (buf[0] == '.')) {
refresh();
sleep(1);
}
}
endwin();
return 0;
}
This program clears the screen using curses then outputs a message in word-sized chunks.
this web page:
http://man7.org/linux/man-pages/man4/console_codes.4.html
contains the common ESC sequences for handling the terminal screen/cursor position, etc
this part of the linked info is probably what you want to implement.
These escape sequences can be placed at the beginning of the buffer that you are using to output your data/text
Of special interest is ESC [ 2 j: which erases the whole screen
J ED Erase display (default: from cursor to end of display).
ESC [ 1 J: erase from start to cursor.
ESC [ 2 J: erase whole display.
ESC [ 3 J: erase whole display including scroll-back
buffer (since Linux 3.0).
Related
I have been trying to get getch to work in another program with no success. So I have made the most basic program I can using getch the way I want it to work in the main program.
I have researched the need for noecho, cbreak, initscr and nodelay, I have also tried using newscr() but to no success.
The problem I am having is that the chars aren't being printed to the screen till I hit "enter", when they should be put to the screen every loop. Why is this happening? Also the cursor doesn't return to the left of the screen at the new line. eg.
abc
def
ghi
I have looked for the answer but am stumped again...
#include <stdio.h>
#include <ncurses.h>
int main()
{
initscr();cbreak(); noecho();nodelay(stdscr,0);
char c ;
while((c=getch())!=EOF){
putchar(c);}
return 0;
}
You're not seeing the output because your stdout stream is line buffered.
Your program is getting the individual characters all right; but the output stream is buffering them.
Try fflush(stdout); or switching stdout to unbuffered mode with setbuf(stdout, NULL);.
The problem with disabling buffering is that it's inefficient for bulk data processing when the output isn't a terminal.
You can make it conditional on the standard output being a tty:
if (isatty(fileno(stdout))) /* #include <unistd.h> */
setbuf(stdout, NULL);
To return the cursor to the start of the line, you need to put out a carriage return \r. This is because curses' cbreak mode has disabled the ONLCR tty mode (on Output, when sending NL add CR).
If you unconditionally add \r, then it will appear in files when your output is redirected. So again you need some isatty hack.
A much better might be to learn how to use the tcgetattr and tcsetattr functions to precisely control specific tty parameters, if all you want is to do character-at-a-time input without echo, and not actually develop an interactive curses-based program.
Do you really want character-at-a-time input, or just to diable echo? It's easy to disable echo. Call tcgetattr to fill a struct termios with the current settings of file descriptor 0 (if it is a tty). Flip some flags to turn off echoing, then call tcsetattr to install the updated structure. When your program exits, be nice and put back the original one. Done.
Yes, ncurses is a good way to get character-by-character control.
And yes, you must call "initscr()" and "cbreak()".
SUGGESTIONS:
1) Compare your code with this ncurses "hello world":
#include <ncurses.h>
int main()
{
initscr(); /* Start curses mode */
printw("Hello World !!!"); /* Print Hello World */
refresh(); /* Print it on to the real screen */
getch(); /* Wait for user input */
endwin(); /* End curses mode */
return 0;
}
2) See what happens if you do a "refresh()" and/or remove the "noecho()".
3) This tutorial has lots of good info that might also help:
http://tldp.org/HOWTO/NCURSES-Programming-HOWTO/
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.
I have recently been introduced to ncurses for asynchronous keyboard key listening, and getting on well with it. One issue i'm facing is that you can only have text on the visible screen, no scrollbars. I was wondering if its possible to keep using ncurses as it is so lovely, but have the program still keep the scrollbars rather than getting to the last line and staying there.
scroll(). You have to set scrollok(win, TRUE) first. Actually if you just want to spew data like a normal terminal you only need to set scrollok() by itself.
#include <ncurses.h>
int main(void)
{
int i = 0;
initscr();
scrollok(stdscr,TRUE);
while(1)
{
printw("%d - lots and lots of lines flowing down the terminal\n", i);
++i;
refresh();
}
endwin();
return 0;
}
I am creating some library function for print and scan using assembly language and c.
Now when am entering datas it is getting print,but the problem is when i press the backspace button the cursor is moving backwards(but not deleting anything)..I want the backspace button to work properly(ie,to delete the previous character)
so is there any program for that.Please help me.
The simple, albeit somewhat hackish, way is to just write backspace characters (\b) to the console.
For example:
#include <stdio.h>
int main()
{
printf("Testing");
fflush(stdout);
printf("\b\b\b");
fflush(stdout);
return 0;
}
But this type of thing should really be handled by your terminal driver. You don't mention what operating system you're targeting in the question.
Output a backspace, space, and backspace:
int c = getchar();
if (c == '\b')
{
printf("\b \b");
fflush(stdout);
}
If the user's press of a backspace was already echoed by the terminal driver then just do this:
int c = getchar();
if (c == '\b')
{
printf(" \b");
fflush(stdout);
}
if u r doing so then would like to tell you one thing abt consoles
There are 2 types of consoles , one which can recognize control char. called
Active console(Canonical mode) and one which not called row console .
Obviously if u r using unix's terminal then u will be given default as Active mode console
but u can set it to row mode by executing some commands.
I'm learning to program in C and want to be able to type characters into the terminal while my code is running without pressing return. My program works, however when I call initscr(), the screen is cleared - even after calling filter(). The documentation for filter suggests it should disable clearing - however this is not the case for me.
#include <stdio.h>
#include <curses.h>
#include <term.h>
int main(void) {
int ch;
filter();
initscr();
cbreak();
noecho();
keypad(stdscr, TRUE);
while((ch = getch()) != EOF);
endwin();
return 0;
}
Why does the above code still clearr the screen, and what could be done to fix it?
I'm using Debian Lenny (stable) and gnome-terminal if that helps.
You would see your screen cleared in a curses application for one of these reasons:
your program calls initscr (which clears the screen) or newterm without first calling filter, or
the terminal initialization clears the screen (or makes it appear to clear, by switching to the alternate screen).
In the latter case, you can suppress the alternate screen feature in ncurses by resetting the enter_ca_mode and exit_ca_mode pointers to NULL as done in dialog. Better yet, choose a terminal description which does what you want.
Further reading:
Why doesn't the screen clear when running vi? (xterm FAQ)
Extending the answer by mike.dld, this works for me on MacOS X 10.6.6 (GCC 4.5.2) with the system curses library - without clearing the screen. I added the ability to record the characters typed (logged to a file "x"), and the ability to type CONTROL-D and stop the program rather than forcing the user to interrupt.
#include <stdio.h>
#include <curses.h>
#include <term.h>
#define CONTROL(x) ((x) & 0x1F)
int main(void)
{
FILE *fp = fopen("x", "w");
if (fp == 0)
return(-1);
SCREEN *s = newterm(NULL, stdin, stdout);
if (s == 0)
return(-1);
cbreak();
noecho();
keypad(stdscr, TRUE);
int ch;
while ((ch = getch()) != EOF && ch != CONTROL('d'))
fprintf(fp, "%d\n", ch);
endwin();
return 0;
}
Basically, curses is designed to take over the screen (or window, in the case of a windowed terminal). You can't really mix curses with stdio, and you can't really use curses to just input or output something without messing with the rest of the screen. There are partial workarounds, but you're never really going to be able to make it work the way that it sounds like you want to. Sorry.
I'd suggest either rewriting your program to use curses throughout, or investigating alternatives like readline.
Use newterm() instead of initscr(), you should be fine then. And don't forget about delscreen() if you follow this advice.