In the code example below, the ncurses printw located in the MouseLeftClicked function is printing twice instead of once as intended. I've scoured the Internet looking for a similar issue but have been unable to find anything. I'm sure I'm missing something fundamental to ncurses, which I'm in the beginning stages of learning. Any help is greatly appreciated. TIA
#include <stdbool.h>
#include <time.h>
#include <ncurses.h>
int main(void);
void MouseLeftClicked(int x, int y, char *caption);
int main(void)
{
int ch;
bool exit = false;
MEVENT event;
initscr();
noecho();
cbreak();
keypad(stdscr, TRUE);
mousemask(ALL_MOUSE_EVENTS, NULL);
clear();
curs_set(0);
mvprintw(0, 0, "F1 exits");
start_color();
init_pair(1, COLOR_WHITE, COLOR_BLUE);
attron(COLOR_PAIR(1));
mvprintw(10, 1, " Exit ");
attroff(COLOR_PAIR(1));
refresh();
do
{
ch = getch();
if(ch == KEY_MOUSE)
{
mvprintw(2, 0, "Got KEY_MOUSE");
if(getmouse(&event) == OK)
{
mvprintw(3, 0, "Got mouse event");
if(event.bstate & BUTTON1_CLICKED)
{
mvprintw(4, 0, "Got click on button #1");
mvprintw(5, 0, "Mouse position: x=%d y=%d ", event.x, event.y);
refresh();
if(event.x > 0 && event.x < 7 && event.y == 10)
MouseLeftClicked(event.x+1, event.y+1, " Exit ");
ch = 0;
}
}
}
if(ch == KEY_F(1))
exit = true;
} while(! exit);
curs_set(1);
endwin();
return 0;
}
void MouseLeftClicked(int x, int y, char *caption)
{
struct timespec tim, tim2;
tim.tv_sec = 0;
tim.tv_nsec = 999999998L;
init_pair(1, COLOR_WHITE, COLOR_GREEN);
attron(COLOR_PAIR(1));
mvprintw(y, x, "%s", caption);
//printw("%s", caption);
attroff(COLOR_PAIR(1));
refresh();
//nanosleep(&tim, &tim2);
//init_pair(1, COLOR_WHITE, COLOR_BLUE);
//attron(COLOR_PAIR(1));
//mvprintw(y, x, " Exit ");
//attroff(COLOR_PAIR(1));
}

The
mvprintwis not printing twice in that function. It is in fact printing text exactly where you told it to. That happens to not be in the same location as the originalExittext because you provided the co-ordinateevent.x+1, event.y+1.The reason why both are drawn in green is because you replaced color pair 1 with a different color and then called
refresh(). The originalExittext uses that attribute, so the result is that it's re-colored.If all you want to do is change the button color, you do not need to draw the text again with
mvprintw. Just change the color pair and refresh:Further reading: init_pair documentation
I would highly recommend you use enum values or similar to name your color pairs, instead of hard-coding magic numbers. That will make the code more readable and less error-prone.
Example:
Then, the initial setup looks like this:
And the update looks like this: