Search code examples
cncurses

store ncurses cursor position as variable


I'm printing text at a location: (10, 10).

  • Waiting for input,
  • clearing screen,
  • doing it again.

When I print text, it moves the cursor to the end of the line. How do I get that X, Y position, and store it as a variable?

I want to do this so I can draw an animated box around the text.

I know there is getyx(window, y, x), but it has a void return.

I tried to use it, yet it does not change x and y's values, it will still print at 0, 0. I can't understand how to use this method to do anything.

x = y = 0;
getyx(screen, y, x);
move(y, x);
printw("YX TEST"); // prints at 0,0 (bad)

I would like to do something like:

yPos = getY(screen);
xPos = getX(screen);

Where I can then process coordinates from that information ?

Thanks for help in advance.


Solution

  • You created a second window and used that second window while still drawing on stdscr. I can reproduce Your issue is with:

    WINDOW *w1 = initscr();
    WINDOW *w2 = newwin(LINES, COLS, 0, 0);
    move(10, 10); // this moves the cursor on w1 or stdscr to (10, 10)
    printw("YX TEST"); // this draws on w1, ie. stdscr the default screen
    // now the cursor on w1 is on (10, 15) and cursor on w2 is on (0,0)
    int x, y;
    getxy(w2, x, y); // this gets the position of w2 window, which stayed at (0,0)
    getxy(w1, x, y); // this will get you the position in w1 window, ie (10, 15)
    refresh(); // this will draw window w1 on the screen, ie. `YX TEST`
    wrefresh(w2); // this will draw nothing on the screen, as window w2 is empty
    

    If you have two windows, and draw on one and get the cursor positions from the second, you will get strange results.
    The following:

    #include <ncurses.h>
    #include <stdio.h>
    #include <unistd.h>
    #include <assert.h>
    
    void mybox(WINDOW *w, int sx, int sy, int ex, int ey)
    {
            assert(w != NULL);
            assert(sx <= ex);
            assert(sy <= ey);
            // up
            wmove(w, sy, sx);
            wprintw(w, "+");
            for (int i = sx + 1; i < ex; ++i) {
                    wprintw(w, "-");
            }
            wprintw(w, "+");
            // left right
            for (int i = sy + 1; i < ey; ++i) {
                    wmove(w, i, ex);
                    wprintw(w, "|");
                    wmove(w, i, sx);
                    wprintw(w, "|");
            }
            // down
            wmove(w, ey, sx);
            wprintw(w, "+");
            for (int i = sx + 1; i < ex; ++i) {
                    wprintw(w, "-");
            }
            wprintw(w, "+");
    }
    
    int main() {
            WINDOW *w = initscr();
            for (int i = 2; i; --i) {
                    // print text at a location (10,10)
                    move(10, 10);
                    printw("YX TEST %d", i);
                    refresh();
                    // let's draw a box around.
                    int x, y;
                    getyx(w, y, x);
                    mybox(w, 9, 9, x, y + 1); // x = 10, y = 19
                    refresh();
                    // wait for input
                    getch();
                    // clear screen
                    clear();
                    // doing it again
            }
            endwin();
            return 0;
    }
    

    draws a box around a YX TEST ? text:

     +---------+
     |YX TEST 2|
     +---------+
    

    If you want to have a functions which return a cursor position, just write them...

     int getX(WINDOW *win) {
          int x, y;
          getxy(win, y, x);
          return x;
     }
    
     int getY(WINDOW *win) { 
          int x, y; 
          getxy(win, y, x); 
          return y;
     }