1

I have the following code.

initscr();
while ((ch = getch()) != '#')
{
    system("ls");
}
endwin();

The problem is that the result is not normally printed. This is how it give me the result:

project  project.c  shell.c  test   test1.c  test2.c
        Project  shell      Signal Labs  test1  test2    text.txt

However I want the result to be like this:
I mean I want it formatted in this way:

project  project.c  shell.c      test   test1.c  test2.c
Project  shell      Signal Labs  test1  test2    text.txt

I'm sure there is a missing function or something that is related to initscr().

Jonathan Leffler
  • 730,956
  • 141
  • 904
  • 1,278
  • You have no control over the output if you use `system`, it's the command you execute that will handle all output. If you want to write output using a curses library, then you have to print the output yourself. In this case I don't see *why* you use curses. Have you tried *without* using it? – Some programmer dude Jan 11 '18 at 16:59
  • It is a bit unclear what your asking. And you do not provide enough code for us to analyze. – Paul Ogilvie Jan 11 '18 at 16:59
  • Does `initsrc` do any printing? – Paul Ogilvie Jan 11 '18 at 17:00
  • @Someprogrammerdude i'm using curses beacuse i want to handle the idea that when user clicks the up arrow it loads the last comment that was typed, but this is a short code just to know how to solve this problem. – Ahmad Alibrahim Jan 11 '18 at 17:03
  • @PaulOgilvie i want the output to be formatted in a normal way. By "normal way" i mean in the same shape as in the terminal. However by using curses the output is like what mentioned in the question. I wish you understand. initsrc() opens a new window. – Ahmad Alibrahim Jan 11 '18 at 17:06
  • https://www.gnu.org/software/libc/manual/html_node/Simple-Directory-Lister.html – Jonny Schubert Jan 11 '18 at 17:07
  • https://stackoverflow.com/questions/43116/how-can-i-run-an-external-program-from-c-and-parse-its-output – Jonny Schubert Jan 11 '18 at 17:09
  • The `initscr()` command prepares the terminal for use by the curses library (and the `getch()` function in particular). You then decide to run a program that has no expectation of being run from a curses environment, and you get the output you get because the terminal settings aren't 'normal'. If you ran `tty -a` instead of `ls`, and compared that output with what you get from your terminal ordinarily, you'll see the differences. You almost certainly need to exit curses mode before running the command, and re-enter curses mode afterwards. – Jonathan Leffler Jan 11 '18 at 17:42
  • @JonathanLeffler "You almost certainly need to exit curses mode before running the command, and re-enter curses mode afterwards." That is a solution but the problem is I'm implementing my own shell so its not an optimal solution because when exiting curses it will take me to the terminal so the output on screen will change and also when using curses (initsrc()) it will open a new window. – Ahmad Alibrahim Jan 11 '18 at 18:05
  • Please note that the function is `initscr()`, not `initsrc()` — your code was correct, but every other reference to it was wrong. – Jonathan Leffler Jan 11 '18 at 18:08
  • Maybe the answer is not to use curses, then. I rather suspect that shells like Bash don't use curses; they manage the terminal more directly (e.g. [`tcgetattr()`](http://pubs.opengroup.org/onlinepubs/9699919799/functions/tcgetattr.html) and relatives). Basically, `initscr()` turns off some mappings that normally occur in the driver, that programs like `ls` reasonably expect to be mapped (things like `onlcr`). You'll have to give the programs 'sane' terminal settings to get 'sane' output. How you do that is up to you. – Jonathan Leffler Jan 11 '18 at 18:12
  • @JonathanLeffler I didn't find another way to check if user presses "up key arrow" except using curses `getch()`. I think of a way that when i want to enter a new window i should take all the stuff that were on the terminal and print them in the new window in order for the user to not recognize what really happened. Do you have a way to do such thing? – Ahmad Alibrahim Jan 11 '18 at 18:20
  • Nope; I've not programmed that sort of code for a long time. You could look at what Bash (or any other open source shell with up-arrow support) does. But I expect you'll find they juggle the terminal attributes back to a 'sane' (non-curses) state before running other programs. The normal way is to do it for every program — you could decide that `vim` isn't going to need the normal terminal settings because it will be running full-screen curses mode, but you could run into issues if you ever exit visual mode into `ex` mode. – Jonathan Leffler Jan 11 '18 at 18:24
  • Programs may use the 'terminfo' library (historically, the 'termcap' library, but that's pretty obsolete now) to access the terminal descriptions independently of `curses`. – Jonathan Leffler Jan 11 '18 at 18:26
  • @JonathanLeffler Okay man thank you :) – Ahmad Alibrahim Jan 11 '18 at 18:28

1 Answers1

1

The 'system' call writes to the standard output, and the curses library writes to the same file descriptor, but their output may not be buffered in the same way, and the curses library additionally sets the output terminal mode to change the way carriage-return and line-feed work. So you don't really want to merge the two in that way...

You could read the result from the command, and print that using curses. Something like this (see the Initialization section of the manual page):

initscr();
cbreak();
noecho();
while ((ch = getch()) != '#')
{
    FILE *pp = popen("ls", "r");
    if (pp != 0) {
        while ((ch = fgetc(pp)) != EOF) {
            addch(ch & 0xff);
        }
        pclose(pp);
    }
}
endwin();
Thomas Dickey
  • 51,086
  • 7
  • 70
  • 105