Reputation: 1005
I am making an application which has several windows, each contained inside of a panel. One of these windows in particular must take input from the keyboard. I also need to be able to detect special keys like the F keys and the arrow keys. My current application is doing this currently. However the cursor is not in the proper location even after I call wmove(my_wins[1], 3, 2)
.
How do I move the cursor to be in the proper panel at the proper location? I would like the terminal cursor to be in my second window (my_wins[1]
), at the next empty space that I want to take characters from. In this case, this is the 3rd row of my_wins[1]
after the last character entered into this line.
My code:
#include <panel.h>
#include <ncurses.h>
#include <string>
#include <stdlib.h>
#include <unistd.h>
#include <vector>
WINDOW *my_wins[4];
PANEL* my_panels[4];
// forward declarations
void make_screen();
void clear_win1();
void get_input();
int main()
{
initscr();
cbreak();
noecho();
make_screen();
get_input();
endwin();
}
void get_input()
{
// enable f-keys and arrow keys
keypad(my_wins[1], TRUE);
int ch;
std::string str = "";
std::vector<std::string> cmds;
while ((ch = wgetch(my_wins[1])) != KEY_F(1))
{
switch(ch)
{
case 127: // delete
if (str.size() > 0)
{
str.erase(str.size()-1);
}
break;
case '\n':
cmds.push_back(str);
str = "";
break;
default:
if (ch >= ' ' || ch <= 126)
{
str += (char) ch;
}
break;
}
clear_win1();
mvwprintw(my_wins[1], 3, 2, "%s", str.c_str());
wmove(my_wins[1], 3, 2+str.size());
update_panels();
doupdate();
}
}
void make_screen()
{
int maxx, maxy;
getmaxyx(stdscr, maxy, maxx);
float win1y = maxy;
float win1x = (2.0/7)*maxx;
float win2y = (3.0/5)*maxy;
float win2x = (3.0/7)*maxx;
float win3y = (3.0/5)*maxy;
float win3x = (2.0/7)*maxx;
float win4y = (2.0/5)*maxy + 1;
float win4x = (5.0/7)*maxx;
my_wins[0] = newwin(win1y, win1x, 0, 0);
my_wins[1] = newwin(win2y, win2x, 0, win1x);
my_wins[2] = newwin(win3y, win3x, 0, win1x+win2x);
my_wins[3] = newwin(win4y, win4x, win2y, win1x);
/*
* Create borders around the windows so that you can see the effect
* of panels
*/
for(int i = 0; i < 4; ++i)
{
box(my_wins[i], 0, 0);
}
my_panels[0] = new_panel(my_wins[0]);
my_panels[1] = new_panel(my_wins[1]);
my_panels[2] = new_panel(my_wins[2]);
my_panels[3] = new_panel(my_wins[3]);
mvwprintw(my_wins[0], 2, 2, "Yelp data");
mvwprintw(my_wins[1], 2, 2, "I/O Window");
mvwprintw(my_wins[2], 2, 2, "Menu items");
mvwprintw(my_wins[3], 2, 2, "Tables");
mvwprintw(my_wins[3], 3, 2, "maxy: %d, maxx: %d", maxy, maxx);
mvwprintw(my_wins[3], 4, 2, "win1y: %f, win1x: %f", win1y, win1x);
mvwprintw(my_wins[3], 5, 2, "win2y: %f, win2x: %f", win2y, win2x);
mvwprintw(my_wins[3], 6, 2, "win3y: %f, win3x: %f", win3y, win3x);
mvwprintw(my_wins[3], 7, 2, "win4y: %f, win4x: %f", win4y, win4x);
mvwprintw(my_wins[1], 3, 2, "");
update_panels();
doupdate();
}
void clear_win1()
{
werase(my_wins[1]);
box(my_wins[1], 0, 0);
mvwprintw(my_wins[1], 2, 2, "I/O Window");
update_panels();
doupdate();
}
Upvotes: 1
Views: 724
Reputation: 54524
Your example puts the wmove
before the updates to the screen. Those updates leave the cursor in whatever location made sense for minimal cursor movement when updating the screen.
This change shows how to do what you're asking:
$ diff -u foo.c.orig foo.c
--- foo.c.orig 2017-03-06 18:56:26.000000000 -0500
+++ foo.c 2017-03-06 19:00:03.568868347 -0500
@@ -33,6 +33,7 @@
std::string str = "";
std::vector<std::string> cmds;
+ wmove(my_wins[1], 3, 2+str.size());
while ((ch = wgetch(my_wins[1])) != KEY_F(1))
{
switch(ch)
@@ -56,9 +57,9 @@
}
clear_win1();
mvwprintw(my_wins[1], 3, 2, "%s", str.c_str());
- wmove(my_wins[1], 3, 2+str.size());
update_panels();
doupdate();
+ wmove(my_wins[1], 3, 2+str.size());
}
}
Upvotes: 1