Box passed window in ncurses.h - c

I'm having a hard time understanding the problem with a window in ncurses. I created a layout of several windows and want to have a function that will border a window. Look like this:
int main() {
use_env(TRUE);
initscr();
start_color();
cbreak();
noecho();
curs_set(0);
WINDOW *win_corner = newwin(WCLINES, WCCOLS, WCX, WCY);
choose_lvl(win_corner);
...
}
int choose_lvl(WINDOW *win) {
box(win, 0, 0);
wrefresh(win);
refresh();
int c, curr_option = 0;
init_pair(1, COLOR_CYAN, COLOR_BLACK);
attron(COLOR_PAIR(1));
mvwprintw(win, 1, 1, "Choose your level");
...
}
It seems like box() doesnt have any effect at all - what could it be? My current theory is to suppose something wrong with the coordinates of the window.

refresh() refreshes the updates on stdscr. newwin() creates an independant window. A refresh on stdscr does not update the alternate window. The same without refresh() in choose_lvl() function would work fine as you would force update only on the alternate window.
You can also create a sub-window of stdscr with subwin() to make refresh() update the whole hierarchy:
#include <unistd.h>
#include <curses.h>
#define WCLINES 10
#define WCCOLS 80
#define WCX 4
#define WCY 4
int choose_lvl(WINDOW *win) {
box(win, 0, 0);
//wrefresh(win);
//refresh();
int c, curr_option = 0;
init_pair(1, COLOR_CYAN, COLOR_BLACK);
attron(COLOR_PAIR(1));
mvwprintw(win, 1, 1, "Choose your level");
refresh();
return 0;
}
int main() {
use_env(TRUE);
initscr();
start_color();
cbreak();
noecho();
curs_set(0);
//WINDOW *win_corner = newwin(WCLINES, WCCOLS, WCX, WCY);
WINDOW *win_corner = subwin(stdscr, WCLINES, WCCOLS, WCX, WCY);
choose_lvl(win_corner);
// quick&dirty pause to suspend program execution
// right after the windows display
pause();
return 0;
}
Execution:
$ gcc win.c -lncurses
$ ./a.out
The result is:

Related

How to solve ncurses menu border misalignment

I'm using the following simple ncurses code to create a menu:
#include <menu.h>
#include <stdlib.h>
ITEM **it;
MENU *me;
WINDOW *win;
void quit(void)
{
int i;
unpost_menu(me);
free_menu(me);
for(i=0; i<=4; i++)
{
free_item(it[i]);
}
free(it);
delwin(win);
endwin();
}
int main(void)
{
int ch;
initscr();
atexit(quit);
clear();
noecho();
curs_set(0);
cbreak();
nl();
keypad(stdscr, TRUE);
start_color();
init_pair(1, COLOR_WHITE, COLOR_BLUE);
init_pair(2, COLOR_BLUE, COLOR_YELLOW);
bkgd(COLOR_PAIR(1));
it = (ITEM **)calloc(5, sizeof(ITEM *));
it[0] = new_item("M1", "Menueeintrag 1");
it[1] = new_item("M2", "Menueeintrag 2");
it[2] = new_item("M3", "Menueeintrag 3");
it[3] = new_item("Ende", "Programm beenden");
it[4] = 0;
me = new_menu(it);
win = newwin(8, 30, 5, 5);
set_menu_win (me, win);
set_menu_sub (me, derwin(win, 4, 28, 3, 2));
box(win, 0, 0);
mvwaddstr(win, 1, 2, "***** Testmenü *****");
set_menu_fore(me, COLOR_PAIR(1)|A_REVERSE);
set_menu_back(me, COLOR_PAIR(1));
wbkgd(win, COLOR_PAIR(2));
post_menu(me);
mvaddstr(14, 3, "Programm mittels Menü oder F1-Funktionstaste beenden");
refresh();
wrefresh(win);
while((ch=getch()) != KEY_F(1))
{
switch(ch)
{
case KEY_DOWN:
menu_driver(me, REQ_DOWN_ITEM);
break;
case KEY_UP:
menu_driver(me, REQ_UP_ITEM);
break;
case 0xA: /* Return- bzw. Enter-Taste -> ASCII-Code */
if(item_index(current_item(me)) == 3)
exit(0);
}
wrefresh(win);
}
return (0);
}
But at the positions where I put text there is always a weird misalignment. You can see it when looking at the border of the menu as well as at the right border of the terminal on the same height as the help text.
Screenshot of the resulting program
That umlaut on "Testmenü" tells the story: it is probably encoded as UTF-8, which uses two bytes:
252: 252 0374 0xfc text "\374" utf8 \303\274
If the locale settings are (for example) en_US, then that tells ncurses that the terminal doesn't use UTF-8, and it will assume that the string is actually ISO-8859-1. In that case, it counts both bytes of that character as separate cells on the screen.
Meanwhile, the terminal may be using UTF-8 encoding (and display the character as shown in the screenshot). But if the locale settings do not correspond to the terminal, you'll see odd stuff like that.

Open a dock type window with x11 and capture key press

I would like to open a "dock type" window without its title bar with x11 in C and I want to capture a key press (Ctrl-q) to close it. The actual code does not capture the key presses to the active window as they are all sent and printed in the terminal. Almost all the Ctrl key presses are somehow not detected. The only key presses that actually work on the opened window are Ctrl-c. I am aware of the _MOTIF_WM_HINTS property but it has the disadvantage to display a window icon in the panel to show a new opened window.
How can I have a "dock type" window while not losing the ability to detect key presses to the active window?
Here is the code basically copied from two other posts here and here
#include <stdio.h>
#include <X11/Xlib.h>
#include <X11/Xutil.h>
#include <X11/Xatom.h>
#include <X11/keysym.h>
int main(int argc, char **argv)
{
Display *dpy = XOpenDisplay(0);
int blackColor = BlackPixel(dpy, DefaultScreen(dpy));
int whiteColor = WhitePixel(dpy, DefaultScreen(dpy));
Window w = XCreateSimpleWindow(dpy, DefaultRootWindow(dpy), 0, 0,
200, 100, 0, blackColor, blackColor);
//Tell X Server to send MapNotify events
XSelectInput(dpy, w, StructureNotifyMask | KeyPressMask);
Atom window_type = XInternAtom(dpy, "_NET_WM_WINDOW_TYPE", False);
long value = XInternAtom(dpy, "_NET_WM_WINDOW_TYPE_DOCK", False);
XChangeProperty(dpy, w, window_type, 4, 32,
PropModeReplace,
(unsigned char *)&value, 1);
//Make window appear
XMapWindow(dpy, w);
//Graphics Context
GC gc = XCreateGC(dpy, w, 0, 0);
//Set white color for drawing
XSetForeground(dpy, gc, whiteColor);
//Wait for the MapNotify event
for(;;) {
XEvent e;
XNextEvent(dpy, &e);
if (e.type == MapNotify) {
break;
}
}
//Draw the line
XDrawLine(dpy, w, gc, 10, 60, 180, 20);
//Send the "DrawLine" request to the server
XFlush(dpy);
char text[255];
XEvent e;
KeySym key;
int numKeys = 0;
for(;;) {
XNextEvent(dpy, &e);
if(e.type == KeyPress) {
if((numKeys = XLookupString(&e.xkey, text, 255, &key, 0))) {
if(e.xkey.state == ControlMask && key == XK_q) {
printf("CTRL-Q\n");
break;
}
}
}
}
if (dpy && gc) XFreeGC(dpy, gc);
if (dpy && w) XDestroyWindow(dpy, w);
if (dpy) XCloseDisplay(dpy);
return 0;
}
Compiled with:
gcc main.c -L/usr/X11R6/lib -lX11 -lm && ./a.out
I've also looked at the _NET_WM_STRUT_PARTIAL property but I haven't been succesful at implementing it.

Gnome Terminal cannot print the red color in a program using curses

I am trying to get into the ncurses library. I am dissapointed that the Gnome Terminal can print red via ANSI escape characters but not the predefined red from ncurses.
#include <curses.h>
void init_colors() {
int a;
for(a = 1; a < COLORS; a++) {
init_pair(a, a, COLOR_BLACK);
}
}
void print_colors() {
int a;
for(a = 1; a < COLORS; a++) {
attron(COLOR_PAIR(a));
mvprintw(a, 0, "color");
attroff(COLOR_PAIR(a));
}
}
int main() {
initscr();
cbreak();
noecho();
curs_set(0);
if(has_colors())
start_color();
init_colors();
print_colors();
getch();
endwin();
return 0;
}
This should print the word "color" in any default ncurses color, but the second line (init_pair should initialize the second COLOR_PAIR as red) is not printed at all. It seems that Gnome Terminal simply skip this line. How can I fix this?
This is a copy of another stackoverflow answer
#include <curses.h>
int main(void) {
initscr();
start_color();
init_pair(1, COLOR_BLACK, COLOR_RED);
init_pair(2, COLOR_BLACK, COLOR_GREEN);
attron(COLOR_PAIR(1));
printw("This should be printed in black with a red background!\n");
attron(COLOR_PAIR(2));
printw("And this in a green background!\n");
refresh();
getch();
endwin();
}
Notes
you need to call start_color() after initscr() to use color.
you have to use the COLOR_PAIR macro
to pass a color pair allocated with init_pair to attron et al.
you can't use the color pair 0.
you only have to call refresh() once,
and only if you want your output to be seen at that point,
and you're not calling an input function like getch().

Draw simple box using curses

Just started to learn C and got a project using curses. I can't even get the simplest things to draw right now.
Want to do a box and have the following code and it doesn't work. The screens is just black.
What am I doing wrong?
#include <curses.h>
int main()
{
initscr();
noecho();
crmode();
WINDOW * win = newwin(10, 10, 1, 1);
wrefresh(win);
refresh();
getch();
endwin();
}
Try this.
#include <ncurses.h>
int main(int argc, char *argv[])
{
initscr();
WINDOW *win = newwin(10,10,1,1);
box(win, '*', '*');
touchwin(win);
wrefresh(win);
getchar();
endwin();
return 0;
}

ncurses: window color don't work

I found the solution myself: refresh win after stdscr.
I would like to have a white window in a blue screen, and I tried it with the following code:
initscr();
WINDOW *win = newwin(10, 10, 10, 10);
start_color();
init_pair(1, COLOR_BLACK, COLOR_BLUE);
init_pair(2, COLOR_BLACK, COLOR_WHITE);
wbkgd(stdscr, COLOR_PAIR(1));
wbkgd(win, COLOR_PAIR(2));
wrefresh(win);
refresh();
But I only get a completly blue screen. What is wrong?
Thanks for all help!
Solution: Refresh the window after stdscr:
refresh();
wrefresh(win);
instead of:
wrefresh(win);
refresh();

Resources