User Tools

Site Tools


programming:ncurses

Differences

This shows you the differences between two versions of the page.

Link to this comparison view

Both sides previous revision Previous revision
Next revision
Previous revision
programming:ncurses [2022/03/19 04:30]
nanodano r
programming:ncurses [2022/03/19 23:56] (current)
nanodano
Line 36: Line 36:
 make install make install
 </code> </code>
- 
-The man pages with API documentation will be in ''~/.local/share/man/'' if you used the home prefix. 
  
 If you install to your home rather than the system, when compiling, linking, and running, you may need to specify where the header files and libraries are. With ''gcc'', that's the ''-I'' and ''-L'' options. When running, set the environment variable ''LD_LIBRARY_PATH'' to include path to libraries. If you install to your home rather than the system, when compiling, linking, and running, you may need to specify where the header files and libraries are. With ''gcc'', that's the ''-I'' and ''-L'' options. When running, set the environment variable ''LD_LIBRARY_PATH'' to include path to libraries.
 +
 +===== Documentation =====
 +
 +==== Man pages =====
 +
 +There are a few ''man'' pages that are particularly helpful. The man pages with API documentation will be in ''~/.local/share/man/man{1,3,5,7}'' if you used the home prefix.
 +
 +If you aren't sure which man pages mean what, run ''man man'' which tells you which man page number corresponds to which section. (1 is executable, 3 is library calls, 5 is file formats, 7 is misc).
 +
 +<code bash>
 +# Read the developer documentation (page 3)
 +# This page tells you the #include statement to use,
 +# how to link against it, and instructions on how to
 +# initialize and use the library itself.
 +# It also lists out all the man pages for each function
 +man 3 ncurses
 +
 +man 3 initscr
 +man 3 getch
 +man 3 getmouse
 +
 +man 1 ncurses6-config
 +</code>
 +
 +
 +===== Online Docs =====
 +
 +  * Online tutorial [[https://invisible-island.net/ncurses/ncurses-intro.html]]
 +
 +Other resources:
 +
 +  * https://tldp.org/HOWTO/NCURSES-Programming-HOWTO/
 +  * https://tldp.org/HOWTO/pdf/NCURSES-Programming-HOWTO.pdf
 +
 +
 +
  
  
Line 61: Line 95:
  
  
-===== Hello world example =====+===== Examples =====
  
 +==== Hello world ====
 <code cpp hello_curses.cpp> <code cpp hello_curses.cpp>
-#include <>+// g++ hello_curses.cpp -lncurses 
 +// add -static for static binary 
 +#include <curses.h>
  
 int main(int argc, char* argv[]) { int main(int argc, char* argv[]) {
 +  initscr(); // Take over terminal and start managing it with curses
 +  endwin(); // Cleanup or terminal will be left in a weird state
   return 0;   return 0;
 } }
Line 72: Line 111:
  
  
 +<code cpp example.cpp>
 +// A more robust example, taken from
 +// https://invisible-island.net/ncurses/ncurses-intro.html#using
 +
 +#include <stdlib.h>
 +#include <curses.h>
 +#include <signal.h>
 +
 +static void finish(int sig);
 +
 +int
 +main(int argc, char *argv[])
 +{
 +    int num = 0;
 +
 +    /* initialize your non-curses data structures here */
 +
 +    (void) signal(SIGINT, finish);      /* arrange interrupts to terminate */
 +
 +    (void) initscr();      /* initialize the curses library */
 +    keypad(stdscr, TRUE);  /* enable keyboard mapping */
 +    (void) nonl();         /* tell curses not to do NL->CR/NL on output */
 +    (void) cbreak();       /* take input chars one at a time, no wait for \n */
 +    (void) echo();         /* echo input - in color */
 +
 +    if (has_colors())
 +    {
 +        start_color();
 +
 +        /*
 +         * Simple color assignment, often all we need.  Color pair 0 cannot
 +         * be redefined.  This example uses the same value for the color
 +         * pair as for the foreground color, though of course that is not
 +         * necessary:
 +         */
 +        init_pair(1, COLOR_RED,     COLOR_BLACK);
 +        init_pair(2, COLOR_GREEN,   COLOR_BLACK);
 +        init_pair(3, COLOR_YELLOW,  COLOR_BLACK);
 +        init_pair(4, COLOR_BLUE,    COLOR_BLACK);
 +        init_pair(5, COLOR_CYAN,    COLOR_BLACK);
 +        init_pair(6, COLOR_MAGENTA, COLOR_BLACK);
 +        init_pair(7, COLOR_WHITE,   COLOR_BLACK);
 +    }
 +
 +    for (;;)
 +    {
 +        int c = getch();     /* refresh, accept single keystroke of input */
 +        attrset(COLOR_PAIR(num % 8));
 +        num++;
 +
 +        /* process the command keystroke */
 +    }
 +
 +    finish(0);               /* we are done */
 +}
 +
 +static void finish(int sig)
 +{
 +    endwin();
 +
 +    /* do your non-curses wrapup here */
 +
 +    exit(0);
 +}
 +</code>
 +
 +==== Shelling out ====
 +
 +<code cpp shell_out.cpp>
 +// From https://invisible-island.net/ncurses/ncurses-intro.html#leaving
 +addstr("Shelling out...");
 +def_prog_mode();           /* save current tty modes */
 +endwin();                  /* restore original tty modes */
 +system("sh");              /* run shell */
 +addstr("returned.\n");     /* prepare return message */
 +refresh();                 /* restore save modes, repaint screen */
 +</code>
 +
 +
 +==== Test mouse input ====
 +
 +<code cpp mouse_test.cpp>
 +#include <ncurses.h>
 +#include <iostream>
 +#include <bitset>
 +
 +void redrawBorder() {
 + clear();
 + box(stdscr, 0, 0); // Redraw main border
 +
 +}
 +
 +int main() {
 +
 +    initscr();
 +    mousemask(ALL_MOUSE_EVENTS, NULL);
 +    
 +    /**
 +      Colors
 +     */
 +    if (has_colors()) { start_color(); }
 +    //use_default_colors();
 +    init_pair(1, COLOR_CYAN, COLOR_BLACK);
 +    init_pair(2, COLOR_WHITE, COLOR_RED);
 +        
 +    cbreak();
 +    keypad(stdscr, TRUE);
 +    nonl();         /* tell curses not to do NL->CR/NL on output */
 +    noecho();
 +    curs_set(0);
 +    
 +    attrset(COLOR_PAIR(1));
 + redrawBorder();
 +    //refresh();
 +    
 +    
 +    
 +    // short id;         /* ID to distinguish multiple devices */
 +    // int x, y, z;      /* event coordinates */
 +    // mmask_t bstate;   /* button state bits */
 +
 +    while (true) {
 +     int c = getch();
 +     switch (c) {
 + case 'q':
 + endwin();
 + exit(0);
 + case KEY_MOUSE:
 + MEVENT event;
 + if (getmouse(&event) == OK) {
 + clear();
 + redrawBorder();
 +
 + attrset(COLOR_PAIR(2));
 + mvaddstr(5, 5, std::to_string(event.x).c_str());
 + mvaddstr(6, 5, std::to_string(event.y).c_str());
 + mvaddstr(7, 5, "Mouse bitset: ");
 + addstr(std::bitset<32>(event.bstate).to_string().c_str());
 + if (event.bstate & BUTTON1_PRESSED) {
 + addstr(" - Button 1 pressed");
 + } else if (event.bstate & BUTTON1_DOUBLE_CLICKED) {
 + addstr(" - Button 1 dclick");
 + }
 + attrset(COLOR_PAIR(1));
 +
 + }
 + break;
 +
 + /**
 + BUTTON1_PRESSED          mouse button 1 down
 + BUTTON1_RELEASED         mouse button 1 up
 + BUTTON1_CLICKED          mouse button 1 clicked
 + BUTTON1_DOUBLE_CLICKED   mouse button 1 double clicked
 + BUTTON1_TRIPLE_CLICKED   mouse button 1 triple clicked
 + BUTTON2_PRESSED          mouse button 2 down
 + BUTTON2_RELEASED         mouse button 2 up
 + BUTTON2_CLICKED          mouse button 2 clicked
 + BUTTON2_DOUBLE_CLICKED   mouse button 2 double clicked
 + BUTTON2_TRIPLE_CLICKED   mouse button 2 triple clicked
 + BUTTON3_PRESSED          mouse button 3 down
 + BUTTON3_RELEASED         mouse button 3 up
 + BUTTON3_CLICKED          mouse button 3 clicked
 + BUTTON3_DOUBLE_CLICKED   mouse button 3 double clicked
 + BUTTON3_TRIPLE_CLICKED   mouse button 3 triple clicked
 + BUTTON4_PRESSED          mouse button 4 down
 + BUTTON4_RELEASED         mouse button 4 up
 + BUTTON4_CLICKED          mouse button 4 clicked
 + BUTTON4_DOUBLE_CLICKED   mouse button 4 double clicked
 + BUTTON4_TRIPLE_CLICKED   mouse button 4 triple clicked
 + BUTTON_SHIFT             shift was down during button state change
 + BUTTON_CTRL              control was down during button state change
 + BUTTON_ALT               alt was down during button state change
 + ALL_MOUSE_EVENTS         report all button state changes
 + REPORT_MOUSE_POSITION    report mouse movement
 + */ 
 +
 + case KEY_RESIZE:
 + redrawBorder();
 + mvaddstr(10, 10, "Window resized");
 + break;
 +
 + default:
 + break;
 + }
 + }
 +
 +
 +
 + /**
 + * Cleanup and shutdown
 + */
 +    endwin();
 +    return 0;
 +}
 +
 +</code>
 +
 +
 +==== Modifier keys ====
 +
 +<code cpp>
 +
 +// int c = getch();
 +// switch (c)
 +case ctrl('j'): // #define ctrl(x) ((x) & 0x1f)
 + addstr("ctrl j detected");
 + break;
 +default:
 + if (c == KEY_ENTER) {
 + addstr("Keypad enter pressed.");
 + }
 + if (c == 27) { // Alt key was down when key pressed
 + // Get the next char that came with the alt
 + c = getch();
 + addstr("Alt/escaped key pressed: ");
 + addch(c); // could be 'a' or 'A' if alt+shift
 + }
 +
 +</code>
 +
 +
 +===== Important variables and functions =====
 +
 +
 +<code cpp>
 +initscr(); // Initialize ncurses
 +endwin(); // Cleanup for exit or shell out (refresh will bring state)
 +getmaxyx() // get terminal size
 +
 +cbreak()
 +nonl()
 +noecho()
 +curs_set()
 +
 +
 +newwin()
 +
 +// Add chars to window
 +mvaddch(y,x,ch)
 +addstr()
 +printw()
 +addch()
 +
 +
 +// Get input
 +getch()
 +wgetstr()
 +wscanw()
 +keypad(stdscr, TRUE)
 +
 +if (has_colors()) { start_color(); }
 +use_default_colors()
 +
 +
 +refresh() // Refresh from stdscr
 +wrefresh() // Refresh using non-stdscr window
 +wnoutrefresh() // Disable auto update on window update (pair with doupdate)
 +doupdate() // Manually repaint all updates
 +touchwin()
 +
 +box()
 +border()
 +
 +// Colors
 +init_pair()
 +COLOR_PAIR
 +
 +attron()
 +attroff()
 +attrset()
 +
 +move(y, x)
 +
 +
 +
 +mousemask(ALL_MOUSE_EVENTS, null) // Specify which mouse events to get
 +MEVENT // data type with bits set for specific mouse events like BUTTON1_CLICKED
 +
 +// Special events from wgetch()
 +KEY_MOUSE // Mouse event (use getmouse())
 +KEY_RESIZE // Terminal was resized and adjusted
 +
 +
 +
 +
 +scrollok()
 +leaveok()
 +
 +derwin()
 +subwin()
 +delwin()
 +
 +
 +define_key() // function-key control sequences
 +keyok() // toggle the listening for special control sequences
 +</code>
  
programming/ncurses.1647664204.txt.gz · Last modified: 2022/03/19 04:30 by nanodano