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;
}
Related
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:
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.
This question already has an answer here:
Why has no one written a threadsafe branch of the ncurses library?
(1 answer)
Closed 5 years ago.
When I use ncurses write a library management system, terminals garbled when multi-threaded,my layout has three windows.
1.My code named ncurses.c
#include <stdio.h>
#include <ncurses.h>
#include <pthread.h>
#include <time.h>
#include <unistd.h>
typedef struct _WIN_struct {
int startx, starty;
int height, width;
} WIN;
WIN winTitle; /* title win */
WIN winMenu; /* Main menu win */
WIN winNews; /* win news */
WINDOW *create_newwin(int height, int width, int starty, int startx) {
WINDOW *local_win;
local_win = newwin(height, width, starty, startx);
box(local_win, 0, 0);
wrefresh(local_win);
return local_win;
}
char *getTimeNow() {
time_t rawtime;
struct tm *timeinfo;
time(&rawtime);
timeinfo = localtime(&rawtime);
return asctime(timeinfo);
}
void *threadfunc_title(void *p) {
WINDOW *windowTitle;
windowTitle = create_newwin(winTitle.height, winTitle.width, winTitle.starty, winTitle.startx);
/* show title and time */
for (;;) {
mvwprintw(windowTitle, winTitle.height/2, winTitle.width/2 - 10, "%s", "Library Management System");
mvwprintw(windowTitle, winTitle.height-2, winTitle.width-30, "%s", getTimeNow());
wrefresh(windowTitle);
sleep(1);
}
}
void *threadfunc_menu(void *p) {
WINDOW *windowMenu;
windowMenu = create_newwin(winMenu.height, winMenu.width, winMenu.starty, winMenu.startx);
for (;;) {
/* now do nothing */
sleep(1);
}
}
void *threadfunc_news(void *p) {
WINDOW *windowNews;
windowNews = create_newwin(winNews.height, winNews.width, winNews.starty, winNews.startx);
for (;;) {
wprintw(windowNews, "%d. %s,%s", getTimeNow(), 1, "a borrow a book from c");
wrefresh(windowNews);
wclear(windowNews);
sleep(5);
}
}
void initWin(WIN *p_win, int height, int width, int starty, int startx) {
p_win->height = height;
p_win->width = width;
p_win->starty = starty;
p_win->startx = startx;
}
int main(int argc, char *argv[])
{
pthread_t pidTitle;
pthread_t pidMenu;
pthread_t pidNews;
initscr();
start_color();
cbreak();
keypad(stdscr, TRUE);
noecho();
/* init location */
initWin(&winTitle, LINES*0.2, COLS, 0 , 0);
initWin(&winMenu, LINES*0.7, COLS*0.7, LINES*0.25, 0);
initWin(&winNews, LINES*0.7, COLS*0.2, LINES*0.25, COLS*0.7);
pthread_create(&pidTitle, NULL, threadfunc_title, NULL);
pthread_create(&pidMenu, NULL, threadfunc_menu, NULL);
pthread_create(&pidNews, NULL, threadfunc_news, NULL);
pthread_join(pidTitle, NULL);
pthread_join(pidMenu, NULL);
pthread_join(pidNews, NULL);
endwin();
return 0;
}
2.Three threads for three windows, thread_func_xxx() is pthread_create() third parameter.
3.Compile and Run
$ gcc ncurses.c -lncurses -lpthread -o ncurses
$ ./ncurses
then, I get terminal garbled.
ps:
1.I have changed -lncurses to -lncursesw, but no effect.
2.if you don not have installed ncurses, you can follow this.
short: the example won't work because the lower-level functions used to update the screen share data which isn't mutex'd. If you compile ncurses with the pthread option, that improves the re-entrancy of the higher-level functions and adds some mutexes, it's possible to use multiple threads.
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().
I am developing an application using GLFW, whereby the user can input some information into the console, the program does some processing on the information, then opens an opengl window (using GLFW) to display the results. The user can then close the window, and be returned to the main menu and enter more information if they want.
Currently the problem I'm having is that once closing the GLFW/OpenGL window the console no longer accepts any input from scanf(). I am fairly certain that I am closing GLFW properly, so I am unsure as to what the problem is.
The code I am using is below:
Main.c:
#include <stdio.h>
#include <stdlib.h>
#include "glfw.h"
#include "pantograph.h"
int main(int argc, char** argv)
{
printf("program start");
int a = 0;
scanf("%i",&a); //this works
printf("%c",a);
p_open_window(1000, 500, 0, "hi there");
int i = 0;
for(i=0;i<1000;i++)
{
p_begin_render();
glBegin(GL_POINTS);
glVertex2i(i,i/2);
glEnd();
scanf("%i",&a);
p_end_render();
}
p_close_window();
scanf("%i",&a); //this does not work
printf("%i",a);
return 0;
}
pantograph.h:
int p_open_window(int width, int height, int fullscreen, const char* title)
{
glfwInit();
glfwDisable(GLFW_AUTO_POLL_EVENTS);
if(fullscreen)
{
glfwOpenWindow(width,height,8,8,8,8,0,0,GLFW_FULLSCREEN);
}else{
glfwOpenWindowHint(GLFW_WINDOW_NO_RESIZE, GL_TRUE);
glfwOpenWindow(width,height,8,8,8,8,0,0,GLFW_WINDOW);
}
glViewport(0, 0, width, height);
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
glOrtho(0, width, height, 0, 0, 1);
glMatrixMode(GL_MODELVIEW);
glDisable(GL_DEPTH_TEST);
glEnable(GL_BLEND);
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
return 1;
}
void p_begin_render()
{
glClearColor(0.0, 0.0, 0.0, 1.0);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glColor4f(1.0, 1.0, 1.0, 1.0);
glLoadIdentity();
}
void p_end_render()
{
glfwSwapBuffers();
}
void p_close_window()
{
glfwCloseWindow();
glfwTerminate();
}
I'm a little confused by your program flow. You say 'the user can close the window and be returned to the main menu'. But how does the program exit from the (i<1000) loop? If the user just closes the window it seems like it would still be executing the for loop (especially because of the scanf inside the loop).
Have you used a debugger to see which point your program gets caught on?
Thanks to the people at #glfw I've managed to find a somewhat hackish solution...
If you "flush" the input buffer directly after closing the glfw window scanf will start to work again. I'm not entirely sure why, but it seems to work for now, so I'm satsfied.
The code I'm using to do it is as follows (after closing the window):
int ch;
while ((ch = getchar()) != '\n' && ch != EOF);
After this, scanf began working again.