├── README.md ├── api.rkt ├── constants.rkt ├── definitions.rkt ├── ffi.rkt ├── info.rkt ├── main.rkt └── test.rkt /README.md: -------------------------------------------------------------------------------- 1 | # racket-ncurses 2 | Heavily WIP and therefore subject to change. However, feel free to use what is currently supported to your heart's content. Feedback is greatly appreciated. Requires libncurses5. 3 | 4 | First, install this package by typing "raco pkg install https://github.com/dys-bigwig/racket-ncurses.git" into your terminal. 5 | 6 | Now you can start using the libary by adding ```(require ncurses)``` to the top of your project.\ 7 | Here's the (admittedly silly) example from test.rkt to give an example of what you can currently do: 8 | ``` 9 | #lang racket 10 | (require ncurses) 11 | 12 | (define (test) 13 | (noecho!) 14 | (curs-set 0) 15 | (border) 16 | (define-values (screen-height screen-width) 17 | (getmaxyx)) 18 | (init-pair! 1 COLOR_WHITE COLOR_RED) 19 | (let ([ch (getch)]) 20 | (addstr (format "YOU PRESSED ~a!" ch) 21 | (color-pair 1) A_BOLD A_UNDERLINE 22 | #:y (quotient screen-height 2) 23 | #:x (quotient (- screen-width 24 | (string-length "YOU PRESSED ~a!")) 25 | 2))) 26 | (define foowin (newwin 10 10 4 4)) 27 | (addstr "WIZARDS" #:win foowin) 28 | (refresh) 29 | (getch #:win foowin) 30 | (delwin foowin)) 31 | 32 | (with-ncurses test) 33 | ``` 34 | The ```with-ncurses``` function is used at the start of your program to automatically initialise ncurses - if you've used the Python api for ncurses before, it serves the same purpose as its ```wrapper``` function. You pass your main function as a callback, and it will be run after the curses environment has been initialised. It takes ```#:start-color?``` as a keyword argument; however, color will be enabled by default, so you need only use this argument if you wish for color to be disabled, in which case you would pass #f as the argument. 35 | 36 | Though the usage of curses itself is somewhat outside the scope of this readme, here is a brief explanation of the functions used, with a particular emphasis upon those elements which are racket-specific: 37 | * ```getmaxyx``` - returns the height and width (maximum y and x values) of the screen as values. Due to the result being returned as values, ```define-values``` is best used for binding its results. 38 | * ```init-pair!``` - used to initialise a pair of colors for use as a text attribute. The first color is the foreground (i.e. the color of the text itself) and the second colour is the background. The list of predefined colors is: 39 | ``` 40 | COLOR_BLACK 41 | COLOR_RED 42 | COLOR_GREEN 43 | COLOR_YELLOW 44 | COLOR_BLUE 45 | COLOR_MAGENTA 46 | COLOR_CYAN 47 | COLOR_WHITE 48 | ``` 49 | * ```getch``` - reads a single character. You can use the keyword argument ```#:win``` to read from specific window. If no argument is given, then stdscr (the default screen which is initialised automatically using ```with-curses```) will be used. 50 | * ```addstr``` - draws a string to the chosen window (default is stdscr). The keyword arguments ```#:y```, ```#:x```, and ```#:win``` can be used to specify the location the string is to be drawn, and the window to which it is to be drawn. The default x and y positions are the current cursor position. Any number of attributes - such as bold, underline... and a single color-pair - can be provided after the string argument as a rest-arg. In the above example, ``(color-pair 1)``, ```A_BOLD``` and ```A_UNDERLINE``` are given as attributes to be apllied to the string. The list of text attributes is: 51 | ``` 52 | A_NORMAL 53 | A_STANDOUT 54 | A_UNDERLINE 55 | A_REVERSE 56 | A_BLINK 57 | A_DIMMED 58 | A_BOLD 59 | A_ALTCHARSET 60 | A_INVISIBLE 61 | A_PROTECT 62 | A_HORIZONTAL 63 | A_LEFT 64 | A_LOW 65 | A_RIGHT 66 | A_TOP 67 | A_VERTICAL 68 | ``` 69 | * ```addch``` - same as addstr, but adds a single Racket char (e.g. ```#\A```) 70 | * ```addchstr``` - similar to addstr, but with some difference which are outside the scope of this readme. For one, it does not advance the cursor, whereas addstr does. 71 | * ```newwin``` - creates a new window, taking the following arguments: lines, columns, x-origin, y-origin. 72 | * ```delwin``` - deletes a window. 73 | * ```refresh``` - refreshes the window given as #:win kwarg, with the default being stdscr. 74 | * ```echo! and noecho!``` - toggles whether typed text is echoed back to the user or not. 75 | * ```curs-set``` - toggles cursor visibility, with 0 being invisible and 2 being bold. 76 | * ```nodelay``` takes #f or #t, setting getch to be blocking or non-blocking respectively. 77 | 78 | If you're working on a particular window (other than stdscr) and you don't want to keep providing the #:win kwarg over-and-over again, you can use parameterize (https://docs.racket-lang.org/guide/parameterize.html) to set stdscr to your window of choice within the parameterize block. 79 | -------------------------------------------------------------------------------- /api.rkt: -------------------------------------------------------------------------------- 1 | #lang racket/base 2 | 3 | (require (prefix-in ffi: "definitions.rkt")) 4 | (require "constants.rkt") 5 | 6 | (provide (all-from-out "constants.rkt")) 7 | (provide (all-defined-out)) 8 | 9 | (define (fold-attrs attrs) 10 | (foldr bitwise-ior 0 attrs)) 11 | 12 | (define stdscr (make-parameter #f)) 13 | 14 | (define (attron #:win [win (stdscr)] . attrs) 15 | (ffi:wattron win (fold-attrs attrs))) 16 | 17 | (define (addstr str 18 | #:win [win (stdscr)] 19 | #:y [y (ffi:getcury win)] 20 | #:x [x (ffi:getcurx win)] 21 | #:n [n -1] 22 | . attrs) 23 | (let ([previous-attrs (fold-attrs (ffi:attr_get))]) 24 | (parameterize ([stdscr win]) 25 | (apply attron attrs) 26 | (ffi:mvwaddnstr win y x str n) 27 | (attr-set! previous-attrs)))) 28 | 29 | (define (addchstr str 30 | #:win [win (stdscr)] 31 | #:y [y (ffi:getcury win)] 32 | #:x [x (ffi:getcurx win)] 33 | . attrs) 34 | (let* ([attrs (fold-attrs attrs)] 35 | [chlist (for/list ([ch (string->list str)]) 36 | (bitwise-ior (char->integer ch) attrs))]) 37 | (ffi:mvwaddchstr win y x (ffi:chlist->chstr chlist)))) 38 | 39 | (define (addch ch #:win [win (stdscr)] 40 | #:y [y (ffi:getcury win)] 41 | #:x [x (ffi:getcurx win)] 42 | . attrs) 43 | (let* ([attrs (fold-attrs attrs)] 44 | [ch (bitwise-ior (char->integer ch) attrs)]) 45 | (ffi:mvwaddch win y x ch))) 46 | 47 | (define (getch #:win [win (stdscr)]) 48 | (ffi:wgetch win)) 49 | 50 | (define (border #:win [win (stdscr)] 51 | #:ch0 [ch0 0] #:ch1 [ch1 0] #:ch2 [ch2 0] #:ch3 [ch3 0] 52 | #:ch4 [ch4 0] #:ch5 [ch5 0] #:ch6 [ch6 0] #:ch7 [ch7 0]) 53 | (ffi:wborder win ch0 ch1 ch2 ch3 ch4 ch5 ch6 ch7)) 54 | 55 | (define (getmaxyx [win (stdscr)]) 56 | (values (ffi:getmaxy win) (ffi:getmaxx win))) 57 | (define (get-curyx win) 58 | (values (ffi:getcury win) (ffi:getcurx win))) 59 | 60 | (define echo! ffi:echo) 61 | (define noecho! ffi:noecho) 62 | (define nodelay ffi:nodelay) 63 | 64 | (define curs-set ffi:curs_set) 65 | (define newwin ffi:newwin) 66 | (define delwin ffi:delwin) 67 | (define (refresh #:win [win (stdscr)]) 68 | (ffi:wrefresh win)) 69 | (define keypad ffi:keypad) 70 | (define init-pair! ffi:init_pair) 71 | (define attr-set! ffi:attrset) 72 | (define (color-pair n) 73 | (arithmetic-shift n 8)) 74 | 75 | (define (with-ncurses func 76 | #:start-color? [start-color? #t]) 77 | (stdscr (ffi:initscr)) 78 | (when (and (ffi:has_colors) start-color?) 79 | (ffi:start_color)) 80 | (define init? #t) 81 | (define (cleanup!) 82 | (when init? 83 | (ffi:endwin) 84 | (set! init? #f))) 85 | (call-with-exception-handler 86 | (lambda (exn) 87 | (cleanup!) 88 | exn) 89 | (lambda () 90 | (call-with-continuation-barrier 91 | (lambda () 92 | (dynamic-wind 93 | void 94 | (λ () (void (func))) 95 | cleanup!)))))) 96 | -------------------------------------------------------------------------------- /constants.rkt: -------------------------------------------------------------------------------- 1 | #lang racket/base 2 | (provide (all-defined-out)) 3 | 4 | (define A_NORMAL #b0) 5 | (define A_STANDOUT #b10000000000000000) 6 | (define A_UNDERLINE #b100000000000000000) 7 | (define A_REVERSE #b1000000000000000000) 8 | (define A_BLINK #b10000000000000000000) 9 | (define A_DIMMED #b100000000000000000000) 10 | (define A_BOLD #b1000000000000000000000) 11 | (define A_ALTCHARSET #b10000000000000000000000) 12 | (define A_INVISIBLE #b100000000000000000000000) 13 | (define A_PROTECT #b1000000000000000000000010) 14 | (define A_HORIZONTAL #b10000000000000000000000000) 15 | (define A_LEFT #b100000000000000000000000000) 16 | (define A_LOW #b1000000000000000000000000000) 17 | (define A_RIGHT #b10000000000000000000000000000) 18 | (define A_TOP #b100000000000000000000000000000) 19 | (define A_VERTICAL #b1000000000000000000000000000000) 20 | (define COLOR_BLACK 0) 21 | (define COLOR_RED 1) 22 | (define COLOR_GREEN 2) 23 | (define COLOR_YELLOW 3) 24 | (define COLOR_BLUE 4) 25 | (define COLOR_MAGENTA 5) 26 | (define COLOR_CYAN 6) 27 | (define COLOR_WHITE 7) 28 | 29 | (define KEY_DOWN 0402) ; down-arrow key ; 30 | (define KEY_UP 0403) ; up-arrow key ; 31 | (define KEY_LEFT 0404) ; left-arrow key ; 32 | (define KEY_RIGHT 0405) ; right-arrow key ; 33 | (define KEY_HOME 0406) ; home key ; 34 | (define KEY_BACKSPACE 0407) ; backspace key ; 35 | (define KEY_F0 0410) ; Function keys. Space for 64 ; 36 | (define KEY_DL 0510) ; delete-line key ; 37 | (define KEY_IL 0511) ; insert-line key ; 38 | (define KEY_DC 0512) ; delete-character key ; 39 | (define KEY_IC 0513) ; insert-character key ; 40 | (define KEY_EIC 0514) ; sent by rmir or smir in insert mode ; 41 | (define KEY_CLEAR 0515) ; clear-screen or erase key ; 42 | (define KEY_EOS 0516) ; clear-to-end-of-screen key ; 43 | (define KEY_EOL 0517) ; clear-to-end-of-line key ; 44 | (define KEY_SF 0520) ; scroll-forward key ; 45 | (define KEY_SR 0521) ; scroll-backward key ; 46 | (define KEY_NPAGE 0522) ; next-page key ; 47 | (define KEY_PPAGE 0523) ; previous-page key ; 48 | (define KEY_STAB 0524) ; set-tab key ; 49 | (define KEY_CTAB 0525) ; clear-tab key ; 50 | (define KEY_CATAB 0526) ; clear-all-tabs key ; 51 | (define KEY_ENTER 0527) ; enter;send key ; 52 | (define KEY_PRINT 0532) ; print key ; 53 | (define KEY_LL 0533) ; lower-left key (home down) ; 54 | (define KEY_A1 0534) ; upper left of keypad ; 55 | (define KEY_A3 0535) ; upper right of keypad ; 56 | (define KEY_B2 0536) ; center of keypad ; 57 | (define KEY_C1 0537) ; lower left of keypad ; 58 | (define KEY_C3 0540) ; lower right of keypad ; 59 | (define KEY_BTAB 0541) ; back-tab key ; 60 | (define KEY_BEG 0542) ; begin key ; 61 | (define KEY_CANCEL 0543) ; cancel key ; 62 | (define KEY_CLOSE 0544) ; close key ; 63 | (define KEY_COMMAND 0545) ; command key ; 64 | (define KEY_COPY 0546) ; copy key ; 65 | (define KEY_CREATE 0547) ; create key ; 66 | (define KEY_END 0550) ; end key ; 67 | (define KEY_EXIT 0551) ; exit key ; 68 | (define KEY_FIND 0552) ; find key ; 69 | (define KEY_HELP 0553) ; help key ; 70 | (define KEY_MARK 0554) ; mark key ; 71 | (define KEY_MESSAGE 0555) ; message key ; 72 | (define KEY_MOVE 0556) ; move key ; 73 | (define KEY_NEXT 0557) ; next key ; 74 | (define KEY_OPEN 0560) ; open key ; 75 | (define KEY_OPTIONS 0561) ; options key ; 76 | (define KEY_PREVIOUS 0562) ; previous key ; 77 | (define KEY_REDO 0563) ; redo key ; 78 | (define KEY_REFERENCE 0564) ; reference key ; 79 | (define KEY_REFRESH 0565) ; refresh key ; 80 | (define KEY_REPLACE 0566) ; replace key ; 81 | (define KEY_RESTART 0567) ; restart key ; 82 | (define KEY_RESUME 0570) ; resume key ; 83 | (define KEY_SAVE 0571) ; save key ; 84 | (define KEY_SBEG 0572) ; shifted begin key ; 85 | (define KEY_SCANCEL 0573) ; shifted cancel key ; 86 | (define KEY_SCOMMAND 0574) ; shifted command key ; 87 | (define KEY_SCOPY 0575) ; shifted copy key ; 88 | (define KEY_SCREATE 0576) ; shifted create key ; 89 | (define KEY_SDC 0577) ; shifted delete-character key ; 90 | (define KEY_SDL 0600) ; shifted delete-line key ; 91 | (define KEY_SELECT 0601) ; select key ; 92 | (define KEY_SEND 0602) ; shifted end key ; 93 | (define KEY_SEOL 0603) ; shifted clear-to-end-of-line key ; 94 | (define KEY_SEXIT 0604) ; shifted exit key ; 95 | (define KEY_SFIND 0605) ; shifted find key ; 96 | (define KEY_SHELP 0606) ; shifted help key ; 97 | (define KEY_SHOME 0607) ; shifted home key ; 98 | (define KEY_SIC 0610) ; shifted insert-character key ; 99 | (define KEY_SLEFT 0611) ; shifted left-arrow key ; 100 | (define KEY_SMESSAGE 0612) ; shifted message key ; 101 | (define KEY_SMOVE 0613) ; shifted move key ; 102 | (define KEY_SNEXT 0614) ; shifted next key ; 103 | (define KEY_SOPTIONS 0615) ; shifted options key ; 104 | (define KEY_SPREVIOUS 0616) ; shifted previous key ; 105 | (define KEY_SPRINT 0617) ; shifted print key ; 106 | (define KEY_SREDO 0620) ; shifted redo key ; 107 | (define KEY_SREPLACE 0621) ; shifted replace key ; 108 | (define KEY_SRIGHT 0622) ; shifted right-arrow key ; 109 | (define KEY_SRSUME 0623) ; shifted resume key ; 110 | (define KEY_SSAVE 0624) ; shifted save key ; 111 | (define KEY_SSUSPEND 0625) ; shifted suspend key ; 112 | (define KEY_SUNDO 0626) ; shifted undo key ; 113 | (define KEY_SUSPEND 0627) ; suspend key ; 114 | (define KEY_UNDO 0630) ; undo key ; 115 | (define KEY_MOUSE 0631) ; Mouse event has occurred ; 116 | (define KEY_RESIZE 0632) ; Terminal resize event ; 117 | (define KEY_EVENT 0633) ; We were interrupted by an event ; 118 | -------------------------------------------------------------------------------- /definitions.rkt: -------------------------------------------------------------------------------- 1 | #lang racket/base 2 | (require ffi/unsafe 3 | ffi/unsafe/define 4 | ffi/unsafe/cvector) 5 | (provide (all-defined-out)) 6 | 7 | (define-ffi-definer define-curses (ffi-lib "libncurses" '("5" #f))) 8 | (define-ffi-definer define-panel (ffi-lib "libpanel" '("5" #f))) 9 | 10 | (define _WINDOW-pointer (_cpointer 'WINDOW)) 11 | (define _chtype _ulong) 12 | (define _chstr _cvector) 13 | (define _attr_t _ulong) 14 | (define (chlist->chstr chars) (list->cvector (append chars '(0)) _chtype)) 15 | 16 | ;ADDCH FUNCTIONS; 17 | 18 | (define-curses addch (_fun _chtype -> _int)) 19 | (define-curses waddch (_fun _WINDOW-pointer _chtype -> _int)) 20 | (define-curses mvaddch (_fun _int _int _chtype -> _int)) 21 | (define-curses mvwaddch (_fun _WINDOW-pointer _int _int _chtype -> _int)) 22 | (define-curses addchstr (_fun _chstr -> _int)) 23 | 24 | ;ADDSTR FUNCTIONS 25 | (define-curses addstr (_fun _string -> _int)) 26 | (define-curses addnstr (_fun _string _int -> _int)) 27 | (define-curses waddstr (_fun _WINDOW-pointer _string -> _int)) 28 | (define-curses waddnstr (_fun _WINDOW-pointer _string _int -> _int)) 29 | (define-curses mvaddstr (_fun _int _int _string -> _int)) 30 | (define-curses mvaddnstr (_fun _int _int _string _int -> _int)) 31 | (define-curses mvwaddstr (_fun _WINDOW-pointer _int _int _string -> _int)) 32 | (define-curses mvwaddnstr (_fun _WINDOW-pointer _int _int _string _int -> _int)) 33 | (define-curses mvwaddchstr (_fun _WINDOW-pointer _int _int _chstr -> _int)) 34 | 35 | ;COLOUR/GRAPHICAL FUNCTIONS 36 | (define-curses assume_default_colors (_fun _int _int -> _int)) 37 | (define-curses has_colors (_fun -> _bool)) 38 | (define-curses start_color (_fun -> _int)) 39 | (define-curses init_pair (_fun _short _short _short -> _int)) 40 | (define-curses attroff (_fun _int -> _int)) 41 | (define-curses attron (_fun _int -> _int)) 42 | (define-curses wattroff (_fun _WINDOW-pointer _int -> _int)) 43 | (define-curses wattron (_fun _WINDOW-pointer _int -> _int)) 44 | (define-curses attrset (_fun _int -> _int)) 45 | (define-curses attr_set (_fun _attr_t _short -> _int)) 46 | (define-curses wattrset (_fun _WINDOW-pointer _int -> _int)) 47 | (define-curses bkgd (_fun _long -> _int)) 48 | (define-curses wbkgd (_fun _WINDOW-pointer _long -> _int)) 49 | (define-curses bkgdset (_fun _long -> _int)) 50 | (define-curses wbkgdset (_fun _WINDOW-pointer _long -> _int)) 51 | (define-curses border (_fun _long _long _long _long 52 | _long _long _long _long 53 | -> _int)) 54 | (define-curses wborder (_fun _WINDOW-pointer _long _long _long _long 55 | _long _long _long _long 56 | -> _int)) 57 | (define-curses box (_fun _WINDOW-pointer _long _long -> _int)) 58 | (define-curses chgat (_fun _int _long _short -> _int)) 59 | (define-curses clear (_fun -> _int)) 60 | (define-curses wclear (_fun _WINDOW-pointer -> _int)) 61 | (define-curses color_content (_fun _short _short _short _short -> _int)) 62 | (define-curses color_set (_fun _short -> _int)) 63 | (define-curses COLOR_PAIR (_fun _int -> _int)) 64 | (define-curses copywin (_fun _WINDOW-pointer _WINDOW-pointer 65 | _int _int _int _int _int _int _int 66 | -> _int)) 67 | 68 | ;INITIALIZATION FUNCTIONS; 69 | (define-curses initscr (_fun -> _WINDOW-pointer)) 70 | (define-curses curs_set (_fun _int -> _int)) 71 | (define-curses newwin (_fun _int _int _int _int -> _WINDOW-pointer)) 72 | (define-curses endwin (_fun -> _int)) 73 | (define-curses newpad (_fun _int _int -> _WINDOW-pointer)) 74 | (define-curses delwin (_fun _WINDOW-pointer -> _int)) 75 | (define-curses derwin (_fun _WINDOW-pointer 76 | _int _int _int _int 77 | -> _WINDOW-pointer)) 78 | 79 | ;SCREEN-UPDATE FUNCTIONS; 80 | (define-curses doupdate (_fun -> _void)) 81 | (define-curses wnoutrefresh (_fun _WINDOW-pointer -> _int)) 82 | (define-curses refresh (_fun -> _int)) 83 | (define-curses wrefresh (_fun _WINDOW-pointer -> _int)) 84 | (define-curses leaveok (_fun _WINDOW-pointer _bool -> _int)) 85 | 86 | ;INPUT FUNCTIONS; 87 | (define-curses echo (_fun -> _int)) 88 | (define-curses noecho (_fun -> _int)) 89 | (define-curses cbreak (_fun -> _int)) 90 | (define-curses nocbreak (_fun -> _int)) 91 | (define-curses getch (_fun -> _int)) 92 | (define-curses wgetch (_fun _WINDOW-pointer 93 | -> (c : _int) 94 | -> (integer->char c))) 95 | (define-curses keypad (_fun _WINDOW-pointer _bool -> _int)) 96 | 97 | ;ATTRS 98 | (define-curses attr_get (_fun (a : (_ptr o _ulong)) 99 | (c : (_ptr o _short)) 100 | -> _int -> (list a c))) 101 | ;MISC; 102 | (define-curses beep (_fun -> _int)) 103 | (define-curses baudrate (_fun -> _int)) 104 | (define-curses move (_fun _int _int -> _int)) 105 | (define-curses wmove (_fun _WINDOW-pointer _int _int -> _int)) 106 | (define-curses clearok (_fun _WINDOW-pointer _bool -> _int)) 107 | (define-curses clrtobot (_fun -> _int)) 108 | (define-curses wclrtobot (_fun _WINDOW-pointer -> _int)) 109 | (define-curses clrtoeol (_fun -> _int)) 110 | (define-curses wclrtoeol (_fun _WINDOW-pointer -> _int)) 111 | (define-curses getmaxy (_fun _WINDOW-pointer -> _int)) 112 | (define-curses getmaxx (_fun _WINDOW-pointer -> _int)) 113 | (define-curses getcury (_fun _WINDOW-pointer -> _int)) 114 | (define-curses getcurx (_fun _WINDOW-pointer -> _int)) 115 | (define-curses napms (_fun _int -> _int)) 116 | (define-curses can_change_color (_fun -> _bool)) 117 | (define-curses nodelay (_fun _bool -> _int)) 118 | 119 | ;PANELS; 120 | (define-panel new_panel (_fun _WINDOW-pointer -> _int)) 121 | (define-panel update_panels (_fun -> _int)) 122 | 123 | -------------------------------------------------------------------------------- /ffi.rkt: -------------------------------------------------------------------------------- 1 | #lang racket/base 2 | (require "constants.rkt") 3 | (require "definitions.rkt") 4 | (provide (all-from-out "constants.rkt" 5 | "definitions.rkt")) 6 | -------------------------------------------------------------------------------- /info.rkt: -------------------------------------------------------------------------------- 1 | #lang info 2 | (define collection "ncurses") 3 | (define deps '("base")) 4 | (define build-deps '()) 5 | (define pkg-desc "ncurses bindings for Racket") 6 | (define version "0.0") 7 | (define pkg-authors '(dys-bigwig)) 8 | -------------------------------------------------------------------------------- /main.rkt: -------------------------------------------------------------------------------- 1 | #lang racket/base 2 | 3 | (require "api.rkt") 4 | (provide (all-from-out "api.rkt")) 5 | -------------------------------------------------------------------------------- /test.rkt: -------------------------------------------------------------------------------- 1 | #lang racket 2 | (require ncurses) 3 | 4 | (define (test) 5 | (noecho!) 6 | (curs-set 0) 7 | (border) 8 | (define-values (screen-height screen-width) 9 | (getmaxyx)) 10 | (init-pair! 1 COLOR_WHITE COLOR_RED) 11 | (let ([ch (getch)]) 12 | (addstr (format "YOU PRESSED ~a!" ch) 13 | 14 | (color-pair 1) A_BOLD A_UNDERLINE 15 | #:y (quotient screen-height 2) 16 | #:x (quotient (- screen-width 17 | (string-length "YOU PRESSED ~a!")) 18 | 2))) 19 | (define foowin (newwin 10 10 4 4)) 20 | (addstr "WIZARDS" #:win foowin) 21 | (refresh) 22 | (getch #:win foowin) 23 | (delwin foowin)) 24 | 25 | (with-ncurses test) 26 | --------------------------------------------------------------------------------