Skip to content

Instantly share code, notes, and snippets.

@reagent

reagent/.gitignore

Last active May 14, 2020
Embed
What would you like to do?
Curses Windowing Example
demo
*.swp
#include <ncurses.h>
#include <unistd.h>
void draw_borders(WINDOW *screen) {
int x, y, i;
getmaxyx(screen, y, x);
// 4 corners
mvwprintw(screen, 0, 0, "+");
mvwprintw(screen, y - 1, 0, "+");
mvwprintw(screen, 0, x - 1, "+");
mvwprintw(screen, y - 1, x - 1, "+");
// sides
for (i = 1; i < (y - 1); i++) {
mvwprintw(screen, i, 0, "|");
mvwprintw(screen, i, x - 1, "|");
}
// top and bottom
for (i = 1; i < (x - 1); i++) {
mvwprintw(screen, 0, i, "-");
mvwprintw(screen, y - 1, i, "-");
}
}
int main(int argc, char *argv[]) {
int parent_x, parent_y, new_x, new_y;
int score_size = 3;
initscr();
noecho();
curs_set(FALSE);
// set up initial windows
getmaxyx(stdscr, parent_y, parent_x);
WINDOW *field = newwin(parent_y - score_size, parent_x, 0, 0);
WINDOW *score = newwin(score_size, parent_x, parent_y - score_size, 0);
draw_borders(field);
draw_borders(score);
while(1) {
getmaxyx(stdscr, new_y, new_x);
if (new_y != parent_y || new_x != parent_x) {
parent_x = new_x;
parent_y = new_y;
wresize(field, new_y - score_size, new_x);
wresize(score, score_size, new_x);
mvwin(score, new_y - score_size, 0);
wclear(stdscr);
wclear(field);
wclear(score);
draw_borders(field);
draw_borders(score);
}
// draw to our windows
mvwprintw(field, 1, 1, "Field");
mvwprintw(score, 1, 1, "Score");
// refresh each window
wrefresh(field);
wrefresh(score);
}
endwin();
return 0;
}
CFLAGS=-Wall
LDFLAGS=-lncurses
all: demo
clean:
rm -rf demo
@FuryaevStas

This comment has been minimized.

Copy link

@FuryaevStas FuryaevStas commented Mar 20, 2016

while (1) { } gives us a 100% CPU loading.

@mgood7123

This comment has been minimized.

Copy link

@mgood7123 mgood7123 commented Sep 24, 2017

that always happens and is somehow unavoidable

@AnujChitale

This comment has been minimized.

Copy link

@AnujChitale AnujChitale commented Oct 16, 2017

A possible solution to reduce the CPU load due to while (1):
A timer interrupt for checking "getmaxyx(stdscr, new_y, new_x);"
Though this gist is meant to see the functionality of resizing and not for resource efficiency.
@FuryaevStas: Your comment does help out people to avoid using the re-size logic as-is, in their actual implementation.

@robherley

This comment has been minimized.

Copy link

@robherley robherley commented Nov 12, 2017

Would a possible alternative be to handle the signal SIGWINCH? Ex: this Stack Overflow.

@memoriasIT

This comment has been minimized.

Copy link

@memoriasIT memoriasIT commented May 8, 2019

Yes, and that would be much better for the CPU, having a busy while is almost never the answer. @robherley

@makeworld-the-better-one

This comment has been minimized.

Copy link

@makeworld-the-better-one makeworld-the-better-one commented Dec 3, 2019

There is 100% CPU usage because there is no usleep being used, which is normally common in such loops. You would need it if you're doing any animation.

@wmcbrine

This comment has been minimized.

Copy link

@wmcbrine wmcbrine commented May 14, 2020

This version: https://gist.github.com/wmcbrine/f63e83d659cedd5181ae77c56907addb

  1. Loops at 0% CPU; quits on 'q'.
  2. Uses box().
  3. Is compatible with PDCurses as well as ncurses.
@wmcbrine

This comment has been minimized.

Copy link

@wmcbrine wmcbrine commented May 14, 2020

There is 100% CPU usage because there is no usleep being used, which is normally common in such loops.

While that would be an improvement over the original example, my advice is:

  1. In a curses-based program, don't use usleep() where napms() will suffice. usleep() introduces a POSIX dependency, while napms() is native to curses, so the app may still be portable to non-POSIX systems.
  2. Don't use napms() where a blocking getch() will do. Most curses apps will and should spend most of their time in an idle loop waiting on user input, so you may as well let getch() do the work of idling. In the case of this example, even resize events are reported as KEY_RESIZE key events by ncurses and PDCurses. And even in cases where a non-blocking getch() is needed, you can often rely on mechanisms like halfdelay() or timeout() instead of resorting to an explicit napms().
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
You can’t perform that action at this time.