User Tools

Site Tools


programming:ncurses

Differences

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

Link to this comparison view

Next revision
Previous revision
programming:ncurses [2022/03/19 04:25]
nanodano created
programming:ncurses [2022/03/19 23:56] (current)
nanodano
Line 37: Line 37:
 </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'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'' optionsWhen running, set the environment variable ''LD_LIBRARY_PATH'' to include path to libraries. It comes with a helper function useful for these tasks, ''ncurses6-config'' which will be in ''~/.local/bin/'' if you used the home prefix.+===== Documentation ===== 
 + 
 +==== Man pages ===== 
 + 
 +There are a few ''man'' pages that are particularly helpfulThe 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> <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
 +
 +
 +
 +
 +
 +===== ncurses6-config tool =====
 +
 +Ncurses comes with a helper function useful for these tasks, ''ncurses6-config'' which will be in ''~/.local/bin/'' if you used the home prefix.
 +
 +<code bash>
 +# For compiling and specifying include dirs
 +ncurses6-config --cflags
 +# -D_DEFAULT_SOURCE -D_XOPEN_SOURCE=600 -I/home/dano/.local/include/ncurses -I/home/dano/.local/include
 +
 +# For linking and specifying lib dirs
 ncurses6-config --libs ncurses6-config --libs
 # -L/home/dano/.local/lib -lncurses # -L/home/dano/.local/lib -lncurses
  
-ncurses6-config --cflags +# For LD_LIBRARY_PATH when executing and linking dynamically 
-#-D_DEFAULT_SOURCE -D_XOPEN_SOURCE=600 -I/home/dano/.local/include/ncurses -I/home/dano/.local/include+ncurses6-config  --libdir 
 +#/home/dano/.local/lib
 </code> </code>
  
  
 +===== Examples =====
  
 +==== Hello world ====
 +<code cpp hello_curses.cpp>
 +// g++ hello_curses.cpp -lncurses
 +// add -static for static binary
 +#include <curses.h>
 +
 +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;
 +}
 +</code>
 +
 +
 +<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.1647663927.txt.gz · Last modified: 2022/03/19 04:25 by nanodano