├── LICENSE ├── Makefile ├── README.md ├── defs.go ├── doc.go ├── examples ├── acs │ └── acs.go ├── border │ └── border.go ├── color │ └── color.go ├── concurrency │ └── concur.go ├── curs_menu │ └── menu.go ├── features │ └── features.go ├── form │ └── form.go ├── getstr │ └── getstr.go ├── hello │ └── hello.go ├── init │ └── init.go ├── menu │ └── menu.go ├── menu_mcol │ └── mcolmenu.go ├── menu_scroll │ └── scrollmenu.go ├── menu_subwin │ └── submenu.go ├── menugrey │ └── menugrey.go ├── menutoggle │ └── menutoggle.go ├── mouse │ └── mouse.go ├── newterm │ └── newterm.go ├── pad │ └── pad.go ├── panel │ └── panel.go ├── panel2 │ └── panel2.go ├── print │ └── print.go ├── resize │ ├── resize.go │ └── termsize.go ├── slk │ └── slk.go ├── starfield │ └── starfield.go └── window │ └── window.go ├── ext.go ├── ext_defs.go ├── form.go ├── go.mod ├── goncurses.c ├── goncurses.h ├── menu.go ├── mouse.go ├── ncurses.go ├── ncurses_test.go ├── pad.go ├── pad_posix.go ├── panel.go ├── pdcurses └── curses.h ├── screen.go ├── slk.go └── window.go /LICENSE: -------------------------------------------------------------------------------- 1 | goncurses - ncurses library for Go. 2 | 3 | Copyright (c) 2011, Rob Thornton 4 | 5 | All rights reserved. 6 | 7 | Redistribution and use in source and binary forms, with or without 8 | modification, are permitted provided that the following conditions are met: 9 | 10 | * Redistributions of source code must retain the above copyright notice, this 11 | list of conditions and the following disclaimer. 12 | 13 | * Redistributions in binary form must reproduce the above copyright notice, 14 | this list of conditions and the following disclaimer in the documentation 15 | and/or other materials provided with the distribution. 16 | 17 | * Neither the name of the copyright holder nor the names of its contributors 18 | may be used to endorse or promote products derived from this software 19 | without specific prior written permission. 20 | 21 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND 22 | ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 23 | WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 24 | DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE 25 | FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 26 | DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 27 | SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 28 | CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 29 | OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 30 | OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 31 | -------------------------------------------------------------------------------- /Makefile: -------------------------------------------------------------------------------- 1 | BUILD_FLAGS=-Wl,-Bsymbolic-functions 2 | 3 | build: 4 | CGO_LDFLAGS_ALLOW=${BUILD_FLAGS} go build 5 | 6 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Overview 2 | Goncurses is an ncurses library for the Go programming language. It 3 | requires both pkg-config and ncurses C development files be installed. 4 | 5 | # Installation 6 | The go tool is the recommended method of installing goncurses. Issue the 7 | following command on the command line: 8 | ``` shell 9 | $ go get github.com/rthornton128/goncurses 10 | ``` 11 | 12 | # Prerequisites 13 | The ncurses C development library must be installed on your system in order to build and install Goncurses. For example, on Debian based systems you can run: 14 | ``` shell 15 | $ sudo apt install libncurses-dev 16 | ``` 17 | 18 | OSX and Windows users should visit the 19 | [Wiki](https://github.com/rthornton128/goncurses/wiki) for installation 20 | instructions. 21 | 22 | ## Pkg-config Flags Error 23 | **Cgo** will fail to build with an invalid or unknown flag error with recent 24 | versions of **ncurses**. Unfortunately, the **cgo** tool only provides one 25 | mechanism for overcoming this. You need to set \*\_ALLOW environment variables 26 | to overcome the issue. There are no **cgo** directives or any other clever 27 | ways (that I know of) to fix this. 28 | 29 | This package provides a [Makefile](../master/Makefile) as one solution. 30 | Another would be to set the variables in your shell in whatever way makes 31 | you feel comfortable. 32 | 33 | See Issues: [#55](https://github.com/rthornton128/goncurses/issues/55) and 34 | [#56](https://github.com/rthornton128/goncurses/issues/56) 35 | 36 | # Notes 37 | 38 | No functions which operate only on stdscr have been implemented because 39 | it makes little sense to do so in a Go implementation. Stdscr is treated the 40 | same as any other window. 41 | 42 | Whenever possible, versions of ncurses functions which could potentially 43 | have a buffer overflow, like the getstr() family of functions, have not been 44 | implemented. Instead, only mvwgetnstr() and wgetnstr() are used. 45 | -------------------------------------------------------------------------------- /defs.go: -------------------------------------------------------------------------------- 1 | // Copyright 2011 Rob Thornton. All rights reserved. 2 | // Use of this source code is governed by a BSD-style 3 | // license that can be found in the LICENSE file. 4 | 5 | package goncurses 6 | 7 | // #cgo !darwin,!openbsd,!windows pkg-config: ncurses 8 | // #include 9 | import "C" 10 | 11 | // Synconize options for Sync() function 12 | const ( 13 | SYNC_NONE = iota 14 | SYNC_CURSOR // Sync cursor in all sub/derived windows 15 | SYNC_DOWN // Sync changes in all parent windows 16 | SYNC_UP // Sync change in all child windows 17 | ) 18 | 19 | type Char C.chtype 20 | 21 | // Text attributes 22 | const ( 23 | A_NORMAL Char = C.A_NORMAL 24 | A_STANDOUT = C.A_STANDOUT 25 | A_UNDERLINE = C.A_UNDERLINE 26 | A_REVERSE = C.A_REVERSE 27 | A_BLINK = C.A_BLINK 28 | A_DIM = C.A_DIM 29 | A_BOLD = C.A_BOLD 30 | A_PROTECT = C.A_PROTECT 31 | A_INVIS = C.A_INVIS 32 | A_ALTCHARSET = C.A_ALTCHARSET 33 | A_CHARTEXT = C.A_CHARTEXT 34 | ) 35 | 36 | var attrList = map[C.int]string{ 37 | C.A_NORMAL: "normal", 38 | C.A_STANDOUT: "standout", 39 | C.A_UNDERLINE: "underline", 40 | C.A_REVERSE: "reverse", 41 | C.A_BLINK: "blink", 42 | //C.A_DIM: "dim", TODO: pdcurses only, distinct in ncurses 43 | C.A_BOLD: "bold", 44 | C.A_PROTECT: "protect", 45 | C.A_INVIS: "invis", 46 | C.A_ALTCHARSET: "altcharset", 47 | C.A_CHARTEXT: "chartext", 48 | } 49 | 50 | // Definitions for printed characters not found on most keyboards. 51 | const ( 52 | /* VT100 symbols */ 53 | ACS_ULCORNER Char = C.A_ALTCHARSET + 'l' 54 | ACS_LLCORNER = C.A_ALTCHARSET + 'm' 55 | ACS_URCORNER = C.A_ALTCHARSET + 'k' 56 | ACS_LRCORNER = C.A_ALTCHARSET + 'j' 57 | ACS_LTEE = C.A_ALTCHARSET + 't' 58 | ACS_RTEE = C.A_ALTCHARSET + 'u' 59 | ACS_BTEE = C.A_ALTCHARSET + 'v' 60 | ACS_TTEE = C.A_ALTCHARSET + 'w' 61 | ACS_HLINE = C.A_ALTCHARSET + 'q' 62 | ACS_VLINE = C.A_ALTCHARSET + 'x' 63 | ACS_PLUS = C.A_ALTCHARSET + 'n' 64 | ACS_S1 = C.A_ALTCHARSET + 'o' 65 | ACS_S9 = C.A_ALTCHARSET + 's' 66 | ACS_DIAMOND = C.A_ALTCHARSET + '`' 67 | ACS_CKBOARD = C.A_ALTCHARSET + 'a' 68 | ACS_DEGREE = C.A_ALTCHARSET + 'f' 69 | ACS_PLMINUS = C.A_ALTCHARSET + 'g' 70 | ACS_BULLET = C.A_ALTCHARSET + '~' 71 | 72 | /* Teletype 5410v1 symbols */ 73 | ACS_LARROW = C.A_ALTCHARSET + ',' 74 | ACS_RARROW = C.A_ALTCHARSET + '+' 75 | ACS_DARROW = C.A_ALTCHARSET + '.' 76 | ACS_UARROW = C.A_ALTCHARSET + '-' 77 | ACS_BOARD = C.A_ALTCHARSET + 'h' 78 | ACS_LANTERN = C.A_ALTCHARSET + 'i' 79 | ACS_BLOCK = C.A_ALTCHARSET + '0' 80 | 81 | /* Undocumented, not well supported */ 82 | ACS_S3 = C.A_ALTCHARSET + 'p' 83 | ACS_S7 = C.A_ALTCHARSET + 'r' 84 | ACS_LEQUAL = C.A_ALTCHARSET + 'y' 85 | ACS_GEQUAL = C.A_ALTCHARSET + 'z' 86 | ACS_PI = C.A_ALTCHARSET + '{' 87 | ACS_NEQUAL = C.A_ALTCHARSET + '|' 88 | ACS_STERLING = C.A_ALTCHARSET + '}' 89 | ) 90 | 91 | // Colors available to ncurses. Combine these with the dim/bold attributes 92 | // for bright/dark versions of each color. These colors can be used for 93 | // both background and foreground colors. 94 | const ( 95 | C_BLACK int16 = C.COLOR_BLACK 96 | C_BLUE = C.COLOR_BLUE 97 | C_CYAN = C.COLOR_CYAN 98 | C_GREEN = C.COLOR_GREEN 99 | C_MAGENTA = C.COLOR_MAGENTA 100 | C_RED = C.COLOR_RED 101 | C_WHITE = C.COLOR_WHITE 102 | C_YELLOW = C.COLOR_YELLOW 103 | ) 104 | 105 | type Key int 106 | 107 | const ( 108 | KEY_TAB Key = 9 // tab 109 | KEY_RETURN = 10 // enter key vs. KEY_ENTER 110 | KEY_ESC = 27 // esc key 111 | KEY_DOWN = C.KEY_DOWN // down arrow key 112 | KEY_UP = C.KEY_UP // up arrow key 113 | KEY_LEFT = C.KEY_LEFT // left arrow key 114 | KEY_RIGHT = C.KEY_RIGHT // right arrow key 115 | KEY_HOME = C.KEY_HOME // home key 116 | KEY_BACKSPACE = C.KEY_BACKSPACE // backpace 117 | KEY_F1 = C.KEY_F0 + 1 // F1 key 118 | KEY_F2 = C.KEY_F0 + 2 // F2 key 119 | KEY_F3 = C.KEY_F0 + 3 // F3 key 120 | KEY_F4 = C.KEY_F0 + 4 // F4 key 121 | KEY_F5 = C.KEY_F0 + 5 // F5 key 122 | KEY_F6 = C.KEY_F0 + 6 // F6 key 123 | KEY_F7 = C.KEY_F0 + 7 // F7 key 124 | KEY_F8 = C.KEY_F0 + 8 // F8 key 125 | KEY_F9 = C.KEY_F0 + 9 // F9 key 126 | KEY_F10 = C.KEY_F0 + 10 // F10 key 127 | KEY_F11 = C.KEY_F0 + 11 // F11 key 128 | KEY_F12 = C.KEY_F0 + 12 // F12 key 129 | KEY_DL = C.KEY_DL // delete-line key 130 | KEY_IL = C.KEY_IL // insert-line key 131 | KEY_DC = C.KEY_DC // delete-character key 132 | KEY_IC = C.KEY_IC // insert-character key 133 | KEY_EIC = C.KEY_EIC // sent by rmir or smir in insert mode 134 | KEY_CLEAR = C.KEY_CLEAR // clear-screen or erase key 135 | KEY_EOS = C.KEY_EOS // clear-to-end-of-screen key 136 | KEY_EOL = C.KEY_EOL // clear-to-end-of-line key 137 | KEY_SF = C.KEY_SF // scroll-forward key 138 | KEY_SR = C.KEY_SR // scroll-backward key 139 | KEY_PAGEDOWN = C.KEY_NPAGE // page-down key (next-page) 140 | KEY_PAGEUP = C.KEY_PPAGE // page-up key (prev-page) 141 | KEY_STAB = C.KEY_STAB // set-tab key 142 | KEY_CTAB = C.KEY_CTAB // clear-tab key 143 | KEY_CATAB = C.KEY_CATAB // clear-all-tabs key 144 | KEY_ENTER = C.KEY_ENTER // enter/send key 145 | KEY_PRINT = C.KEY_PRINT // print key 146 | KEY_LL = C.KEY_LL // lower-left key (home down) 147 | KEY_A1 = C.KEY_A1 // upper left of keypad 148 | KEY_A3 = C.KEY_A3 // upper right of keypad 149 | KEY_B2 = C.KEY_B2 // center of keypad 150 | KEY_C1 = C.KEY_C1 // lower left of keypad 151 | KEY_C3 = C.KEY_C3 // lower right of keypad 152 | KEY_BTAB = C.KEY_BTAB // back-tab key 153 | KEY_BEG = C.KEY_BEG // begin key 154 | KEY_CANCEL = C.KEY_CANCEL // cancel key 155 | KEY_CLOSE = C.KEY_CLOSE // close key 156 | KEY_COMMAND = C.KEY_COMMAND // command key 157 | KEY_COPY = C.KEY_COPY // copy key 158 | KEY_CREATE = C.KEY_CREATE // create key 159 | KEY_END = C.KEY_END // end key 160 | KEY_EXIT = C.KEY_EXIT // exit key 161 | KEY_FIND = C.KEY_FIND // find key 162 | KEY_HELP = C.KEY_HELP // help key 163 | KEY_MARK = C.KEY_MARK // mark key 164 | KEY_MESSAGE = C.KEY_MESSAGE // message key 165 | KEY_MOVE = C.KEY_MOVE // move key 166 | KEY_NEXT = C.KEY_NEXT // next key 167 | KEY_OPEN = C.KEY_OPEN // open key 168 | KEY_OPTIONS = C.KEY_OPTIONS // options key 169 | KEY_PREVIOUS = C.KEY_PREVIOUS // previous key 170 | KEY_REDO = C.KEY_REDO // redo key 171 | KEY_REFERENCE = C.KEY_REFERENCE // reference key 172 | KEY_REFRESH = C.KEY_REFRESH // refresh key 173 | KEY_REPLACE = C.KEY_REPLACE // replace key 174 | KEY_RESTART = C.KEY_RESTART // restart key 175 | KEY_RESUME = C.KEY_RESUME // resume key 176 | KEY_SAVE = C.KEY_SAVE // save key 177 | KEY_SBEG = C.KEY_SBEG // shifted begin key 178 | KEY_SCANCEL = C.KEY_SCANCEL // shifted cancel key 179 | KEY_SCOMMAND = C.KEY_SCOMMAND // shifted command key 180 | KEY_SCOPY = C.KEY_SCOPY // shifted copy key 181 | KEY_SCREATE = C.KEY_SCREATE // shifted create key 182 | KEY_SDC = C.KEY_SDC // shifted delete-character key 183 | KEY_SDL = C.KEY_SDL // shifted delete-line key 184 | KEY_SELECT = C.KEY_SELECT // select key 185 | KEY_SEND = C.KEY_SEND // shifted end key 186 | KEY_SEOL = C.KEY_SEOL // shifted clear-to-end-of-line key 187 | KEY_SEXIT = C.KEY_SEXIT // shifted exit key 188 | KEY_SFIND = C.KEY_SFIND // shifted find key 189 | KEY_SHELP = C.KEY_SHELP // shifted help key 190 | KEY_SHOME = C.KEY_SHOME // shifted home key 191 | KEY_SIC = C.KEY_SIC // shifted insert-character key 192 | KEY_SLEFT = C.KEY_SLEFT // shifted left-arrow key 193 | KEY_SMESSAGE = C.KEY_SMESSAGE // shifted message key 194 | KEY_SMOVE = C.KEY_SMOVE // shifted move key 195 | KEY_SNEXT = C.KEY_SNEXT // shifted next key 196 | KEY_SOPTIONS = C.KEY_SOPTIONS // shifted options key 197 | KEY_SPREVIOUS = C.KEY_SPREVIOUS // shifted previous key 198 | KEY_SPRINT = C.KEY_SPRINT // shifted print key 199 | KEY_SREDO = C.KEY_SREDO // shifted redo key 200 | KEY_SREPLACE = C.KEY_SREPLACE // shifted replace key 201 | KEY_SRIGHT = C.KEY_SRIGHT // shifted right-arrow key 202 | KEY_SRSUME = C.KEY_SRSUME // shifted resume key 203 | KEY_SSAVE = C.KEY_SSAVE // shifted save key 204 | KEY_SSUSPEND = C.KEY_SSUSPEND // shifted suspend key 205 | KEY_SUNDO = C.KEY_SUNDO // shifted undo key 206 | KEY_SUSPEND = C.KEY_SUSPEND // suspend key 207 | KEY_UNDO = C.KEY_UNDO // undo key 208 | KEY_MOUSE = C.KEY_MOUSE // any mouse event 209 | KEY_RESIZE = C.KEY_RESIZE // Terminal resize event 210 | //KEY_EVENT = C.KEY_EVENT // We were interrupted by an event 211 | KEY_MAX = C.KEY_MAX // Maximum key value is KEY_EVENT (0633) 212 | ) 213 | 214 | var keyList = map[Key]string{ 215 | KEY_TAB: "tab", 216 | KEY_RETURN: "enter", // On some keyboards? 217 | KEY_DOWN: "down", 218 | KEY_UP: "up", 219 | KEY_LEFT: "left", 220 | KEY_RIGHT: "right", 221 | KEY_HOME: "home", 222 | KEY_BACKSPACE: "backspace", 223 | KEY_ENTER: "enter", // And not others? 224 | KEY_F1: "F1", 225 | KEY_F2: "F2", 226 | KEY_F3: "F3", 227 | KEY_F4: "F4", 228 | KEY_F5: "F5", 229 | KEY_F6: "F6", 230 | KEY_F7: "F7", 231 | KEY_F8: "F8", 232 | KEY_F9: "F9", 233 | KEY_F10: "F10", 234 | KEY_F11: "F11", 235 | KEY_F12: "F12", 236 | KEY_MOUSE: "mouse", 237 | KEY_PAGEUP: "page up", 238 | KEY_PAGEDOWN: "page down", 239 | KEY_ESC: "esc", 240 | } 241 | 242 | type MouseButton int 243 | 244 | // Mouse button events 245 | const ( 246 | M_ALL MouseButton = C.ALL_MOUSE_EVENTS 247 | M_ALT = C.BUTTON_ALT // alt-click 248 | M_B1_PRESSED = C.BUTTON1_PRESSED // button 1 249 | M_B1_RELEASED = C.BUTTON1_RELEASED 250 | M_B1_CLICKED = C.BUTTON1_CLICKED 251 | M_B1_DBL_CLICKED = C.BUTTON1_DOUBLE_CLICKED 252 | M_B1_TPL_CLICKED = C.BUTTON1_TRIPLE_CLICKED 253 | M_B2_PRESSED = C.BUTTON2_PRESSED // button 2 254 | M_B2_RELEASED = C.BUTTON2_RELEASED 255 | M_B2_CLICKED = C.BUTTON2_CLICKED 256 | M_B2_DBL_CLICKED = C.BUTTON2_DOUBLE_CLICKED 257 | M_B2_TPL_CLICKED = C.BUTTON2_TRIPLE_CLICKED 258 | M_B3_PRESSED = C.BUTTON3_PRESSED // button 3 259 | M_B3_RELEASED = C.BUTTON3_RELEASED 260 | M_B3_CLICKED = C.BUTTON3_CLICKED 261 | M_B3_DBL_CLICKED = C.BUTTON3_DOUBLE_CLICKED 262 | M_B3_TPL_CLICKED = C.BUTTON3_TRIPLE_CLICKED 263 | M_B4_PRESSED = C.BUTTON4_PRESSED // button 4 264 | M_B4_RELEASED = C.BUTTON4_RELEASED 265 | M_B4_CLICKED = C.BUTTON4_CLICKED 266 | M_B4_DBL_CLICKED = C.BUTTON4_DOUBLE_CLICKED 267 | M_B4_TPL_CLICKED = C.BUTTON4_TRIPLE_CLICKED 268 | M_CTRL = C.BUTTON_CTRL // ctrl-click 269 | M_SHIFT = C.BUTTON_SHIFT // shift-click 270 | M_POSITION = C.REPORT_MOUSE_POSITION // mouse moved 271 | ) 272 | -------------------------------------------------------------------------------- /doc.go: -------------------------------------------------------------------------------- 1 | // goncurses - ncurses library for Go. 2 | // Copyright 2011 Rob Thornton. All rights reserved. 3 | // Use of this source code is governed by a BSD-style 4 | // license that can be found in the LICENSE file. 5 | 6 | // Package goncurses is a new curses (ncurses) library for the Go programming 7 | // language. It implements all the ncurses extension libraries: form, menu and 8 | // panel. 9 | // 10 | // Minimal operation would consist of initializing the display: 11 | // 12 | // src, err := goncurses.Init() 13 | // if err != nil { 14 | // log.Fatal("init:", err) 15 | // } 16 | // defer goncurses.End() 17 | // 18 | // It is important to always call End() before your program exits. If you 19 | // fail to do so, the terminal will not perform properly and will either 20 | // need to be reset or restarted completely. 21 | // 22 | // CAUTION: Calls to ncurses functions are normally not atomic nor reentrant 23 | // and therefore extreme care should be taken to ensure ncurses functions 24 | // are not called concurrently. Specifically, never write data to the same 25 | // window concurrently nor accept input and send output to the same window as 26 | // both alter the underlying C data structures in a non safe manner. 27 | // 28 | // Ideally, you should structure your program to ensure all ncurses related 29 | // calls happen in a single goroutine. This is probably most easily achieved 30 | // via channels and Go's built-in select. Alternatively, or additionally, you 31 | // can use a mutex to protect any calls in multiple goroutines from happening 32 | // concurrently. Failure to do so will result in unpredictable and 33 | // undefined behaviour in your program. 34 | // 35 | // The examples directory contains demonstrations of many of the capabilities 36 | // goncurses can provide. 37 | package goncurses 38 | -------------------------------------------------------------------------------- /examples/acs/acs.go: -------------------------------------------------------------------------------- 1 | // goncurses - ncurses library for Go. 2 | // Copyright 2011 Rob Thornton. All rights reserved. 3 | // Use of this source code is governed by a BSD-style 4 | // license that can be found in the LICENSE file. 5 | 6 | /* An example of using AddChar to show a non-standard character. Some common 7 | * VT100 symbols do not work on the windows command line (like ACS_DIAMOND) or 8 | * may require the use of chcp to change the codepage to 437 or 850 */ 9 | package main 10 | 11 | import ( 12 | gc "github.com/rthornton128/goncurses" 13 | "log" 14 | ) 15 | 16 | func main() { 17 | stdscr, err := gc.Init() 18 | if err != nil { 19 | log.Fatal(err) 20 | } 21 | defer gc.End() 22 | 23 | gc.Cursor(0) 24 | gc.Echo(false) 25 | 26 | stdscr.Print("A reversed plus-minus symbol: ") 27 | stdscr.AddChar(gc.ACS_PLMINUS | gc.A_REVERSE) 28 | stdscr.Refresh() 29 | stdscr.GetChar() 30 | } 31 | -------------------------------------------------------------------------------- /examples/border/border.go: -------------------------------------------------------------------------------- 1 | // Copyright 2011 Rob Thornton. All rights reserved. 2 | // Use of this source code is governed by a BSD-style 3 | // license that can be found in the LICENSE file. 4 | package main 5 | 6 | import gc "github.com/rthornton128/goncurses" 7 | 8 | func main() { 9 | stdscr, err := gc.Init() 10 | if err != nil { 11 | return 12 | } 13 | defer gc.End() 14 | 15 | stdscr.Border(gc.ACS_VLINE, gc.ACS_VLINE, gc.ACS_HLINE, gc.ACS_HLINE, 16 | gc.ACS_ULCORNER, gc.ACS_URCORNER, gc.ACS_LLCORNER, gc.ACS_LRCORNER) 17 | stdscr.GetChar() 18 | } 19 | -------------------------------------------------------------------------------- /examples/color/color.go: -------------------------------------------------------------------------------- 1 | // goncurses - ncurses library for Go. 2 | // Copyright 2011 Rob Thornton. All rights reserved. 3 | // Use of this source code is governed by a BSD-style 4 | // license that can be found in the LICENSE file. 5 | 6 | /* Demonstrates some of the color facilities of ncurses */ 7 | package main 8 | 9 | import ( 10 | gc "github.com/rthornton128/goncurses" 11 | "log" 12 | ) 13 | 14 | func main() { 15 | stdscr, err := gc.Init() 16 | if err != nil { 17 | log.Fatal("init:", err) 18 | } 19 | defer gc.End() 20 | 21 | // HasColors can be used to determine whether the current terminal 22 | // has the capability of using colours. You could then chose whether or 23 | // not to use some other mechanism, like using A_REVERSE, instead 24 | if !gc.HasColors() { 25 | log.Fatal("Example requires a colour capable terminal") 26 | } 27 | 28 | // Must be called after Init but before using any colour related functions 29 | if err := gc.StartColor(); err != nil { 30 | log.Fatal(err) 31 | } 32 | 33 | gc.Echo(false) 34 | 35 | // Initialize a colour pair. Should only fail if an improper pair value 36 | // is given 37 | if err := gc.InitPair(1, gc.C_RED, gc.C_WHITE); err != nil { 38 | log.Fatal("InitPair failed: ", err) 39 | } 40 | gc.InitPair(2, gc.C_BLACK, gc.C_CYAN) 41 | 42 | stdscr.Println("Type any key to proceed and again to exit") 43 | 44 | // An example of trying to set an invalid color pair 45 | err = gc.InitPair(-1, gc.C_BLACK, gc.C_CYAN) 46 | stdscr.Println("An intentional error:", err) 47 | 48 | stdscr.Keypad(true) 49 | stdscr.MovePrint(12, 30, "Hello, World!!!") 50 | stdscr.Refresh() 51 | stdscr.GetChar() 52 | // Note that background doesn't just accept colours but will fill 53 | // any blank positions with the supplied character too. Note that newly 54 | // added text with spaces in it will have the blanks converted to the fill 55 | // character, if given 56 | stdscr.SetBackground(gc.Char('*') | gc.ColorPair(2)) 57 | // ColorOn/Off is a shortcut to calling AttrOn/Off(gc.ColorPair(pair)) 58 | stdscr.ColorOn(1) 59 | stdscr.MovePrint(13, 30, "Hello, World in Color!!!") 60 | stdscr.ColorOff(1) 61 | stdscr.Refresh() 62 | stdscr.GetChar() 63 | } 64 | -------------------------------------------------------------------------------- /examples/concurrency/concur.go: -------------------------------------------------------------------------------- 1 | // goncurses - ncurses library for Go. 2 | // Copyright 2011 Rob Thornton. All rights reserved. 3 | // Use of this source code is governed by a BSD-style 4 | // license that can be found in the LICENSE file. 5 | 6 | // This example demonstrates using goncurses with Go's built-in concurrency 7 | // primitives. It is key to ensure no reads or writes occur concurrently to 8 | // a window or screen. Another method would be to use a global mutex. 9 | package main 10 | 11 | import ( 12 | gc "github.com/rthornton128/goncurses" 13 | "log" 14 | ) 15 | 16 | func main() { 17 | scr, err := gc.Init() 18 | if err != nil { 19 | log.Fatal("init:", err) 20 | } 21 | defer gc.End() 22 | 23 | gc.Echo(false) 24 | 25 | scr.Println("Type characters to have them appear on the screen.") 26 | scr.Println("Press 'q' to exit.") 27 | scr.Println() 28 | 29 | // Accept input concurrently via a goroutine and connect a channel 30 | in := make(chan gc.Char) 31 | ready := make(chan bool) 32 | go func(w *gc.Window, ch chan<- gc.Char) { 33 | for { 34 | // Block until all write operations are complete 35 | <-ready 36 | // Send typed character down the channel (which is blocking 37 | // in the main loop) 38 | ch <- gc.Char(w.GetChar()) 39 | } 40 | }(scr, in) 41 | 42 | // Once a character has been received on the 'in' channel the 43 | // 'ready' channel will block until it receives another piece of data. 44 | // This happens only once the received character has been written to 45 | // the screen. The 'in' channel then blocks on the next loop until 46 | // another 'true' is sent down the 'ready' channel signaling to the 47 | // input goroutine that it's okay to receive input 48 | for { 49 | var c gc.Char 50 | select { 51 | case c = <-in: // blocks while waiting for input from goroutine 52 | scr.Print(string(c)) 53 | scr.Refresh() 54 | case ready <- true: // sends once above block completes 55 | } 56 | // Exit when 'q' is pressed 57 | if c == gc.Char('q') { 58 | break 59 | } 60 | } 61 | } 62 | -------------------------------------------------------------------------------- /examples/curs_menu/menu.go: -------------------------------------------------------------------------------- 1 | // goncurses - ncurses library for Go. 2 | // Copyright 2011 Rob Thornton. All rights reserved. 3 | // Use of this source code is governed by a BSD-style 4 | // license that can be found in the LICENSE file. 5 | 6 | /* This example show a basic menu similar to that found in the ncurses 7 | * examples from TLDP */ 8 | package main 9 | 10 | import ( 11 | . "github.com/rthornton128/goncurses" 12 | "log" 13 | ) 14 | 15 | const ( 16 | HEIGHT = 10 17 | WIDTH = 30 18 | ) 19 | 20 | func main() { 21 | var active int 22 | menu := []string{"Choice 1", "Choice 2", "Choice 3", "Choice 4", "Exit"} 23 | 24 | stdscr, err := Init() 25 | if err != nil { 26 | log.Fatal(err) 27 | } 28 | defer End() 29 | 30 | Raw(true) 31 | Echo(false) 32 | Cursor(0) 33 | stdscr.Clear() 34 | stdscr.Keypad(true) 35 | 36 | my, mx := stdscr.MaxYX() 37 | y, x := 2, (mx/2)-(WIDTH/2) 38 | 39 | win, _ := NewWindow(HEIGHT, WIDTH, y, x) 40 | win.Keypad(true) 41 | 42 | stdscr.Print("Use arrow keys to go up and down, Press enter to select") 43 | stdscr.Refresh() 44 | 45 | printmenu(win, menu, active) 46 | 47 | for { 48 | ch := stdscr.GetChar() 49 | switch Key(ch) { 50 | case 'q': 51 | return 52 | case KEY_UP: 53 | if active == 0 { 54 | active = len(menu) - 1 55 | } else { 56 | active -= 1 57 | } 58 | case KEY_DOWN: 59 | if active == len(menu)-1 { 60 | active = 0 61 | } else { 62 | active += 1 63 | } 64 | case KEY_RETURN, KEY_ENTER, Key('\r'): 65 | stdscr.MovePrintf(my-2, 0, "Choice #%d: %s selected", 66 | active, 67 | menu[active]) 68 | stdscr.ClearToEOL() 69 | stdscr.Refresh() 70 | default: 71 | stdscr.MovePrintf(my-2, 0, "Character pressed = %3d/%c", 72 | ch, ch) 73 | stdscr.ClearToEOL() 74 | stdscr.Refresh() 75 | } 76 | 77 | printmenu(win, menu, active) 78 | } 79 | } 80 | 81 | func printmenu(w *Window, menu []string, active int) { 82 | y, x := 2, 2 83 | w.Box(0, 0) 84 | for i, s := range menu { 85 | if i == active { 86 | w.AttrOn(A_REVERSE) 87 | w.MovePrint(y+i, x, s) 88 | w.AttrOff(A_REVERSE) 89 | } else { 90 | w.MovePrint(y+i, x, s) 91 | } 92 | } 93 | w.Refresh() 94 | } 95 | -------------------------------------------------------------------------------- /examples/features/features.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | gc "github.com/rthornton128/goncurses" 5 | "log" 6 | ) 7 | 8 | func main() { 9 | stdscr, err := gc.Init() 10 | if err != nil { 11 | log.Fatal(err) 12 | } 13 | defer gc.End() 14 | 15 | gc.StartColor() 16 | gc.Echo(false) 17 | gc.Raw(true) 18 | 19 | var colours = []int16{gc.C_BLACK, gc.C_BLUE, gc.C_CYAN, gc.C_GREEN, 20 | gc.C_MAGENTA, gc.C_RED, gc.C_WHITE, gc.C_YELLOW} 21 | var attributes = []struct { 22 | attr gc.Char 23 | text string 24 | }{ 25 | {gc.A_NORMAL, "normal"}, 26 | {gc.A_STANDOUT, "standout"}, 27 | {gc.A_UNDERLINE | gc.A_BOLD, "underline"}, 28 | {gc.A_REVERSE, "reverse"}, 29 | {gc.A_BLINK, "blink"}, 30 | {gc.A_DIM, "dim"}, 31 | {gc.A_BOLD, "bold"}, 32 | } 33 | stdscr.MovePrint(0, 0, "Normal terminal colors: ") 34 | for i, c := range colours { 35 | gc.InitPair(int16(i), c, c) 36 | stdscr.ColorOn(int16(i)) 37 | stdscr.AddChar(' ') 38 | stdscr.ColorOff(int16(i)) 39 | } 40 | stdscr.MovePrint(1, 0, "Bold terminal colors: ") 41 | stdscr.AttrOn(gc.A_BLINK) 42 | for i, _ := range colours { 43 | stdscr.ColorOn(int16(i)) 44 | stdscr.AddChar(' ') 45 | stdscr.ColorOff(int16(i)) 46 | } 47 | stdscr.AttrOff(gc.A_BLINK) 48 | stdscr.Move(2, 0) 49 | for _, a := range attributes { 50 | stdscr.AttrOn(a.attr) 51 | stdscr.Println(a.text) 52 | stdscr.AttrOff(a.attr) 53 | } 54 | stdscr.GetChar() 55 | } 56 | -------------------------------------------------------------------------------- /examples/form/form.go: -------------------------------------------------------------------------------- 1 | // goncurses - ncurses library for Go. 2 | // Copyright 2011 Rob Thornton. All rights reserved. 3 | // Use of this source code is governed by a BSD-style 4 | // license that can be found in the LICENSE file. 5 | 6 | /* This simple example demonstrates how to implement a form */ 7 | package main 8 | 9 | import gc "github.com/rthornton128/goncurses" 10 | 11 | func main() { 12 | stdscr, _ := gc.Init() 13 | defer gc.End() 14 | 15 | gc.Echo(false) 16 | gc.CBreak(true) 17 | gc.StartColor() 18 | stdscr.Keypad(true) 19 | 20 | gc.InitPair(1, gc.C_WHITE, gc.C_BLUE) 21 | gc.InitPair(2, gc.C_YELLOW, gc.C_BLUE) 22 | 23 | fields := make([]*gc.Field, 2) 24 | fields[0], _ = gc.NewField(1, 10, 4, 18, 0, 0) 25 | defer fields[0].Free() 26 | fields[0].SetForeground(gc.ColorPair(1)) 27 | fields[0].SetBackground(gc.ColorPair(2) | gc.A_UNDERLINE | gc.A_BOLD) 28 | fields[0].SetOptionsOff(gc.FO_AUTOSKIP) 29 | 30 | fields[1], _ = gc.NewField(1, 10, 6, 18, 0, 0) 31 | defer fields[1].Free() 32 | fields[1].SetForeground(gc.ColorPair(1)) 33 | fields[1].SetBackground(gc.A_UNDERLINE) 34 | fields[1].SetOptionsOff(gc.FO_AUTOSKIP) 35 | fields[1].SetPad('*') 36 | 37 | form, _ := gc.NewForm(fields) 38 | form.Post() 39 | defer form.UnPost() 40 | defer form.Free() 41 | stdscr.Refresh() 42 | 43 | fields[0].SetBuffer("Buffer 0") 44 | 45 | stdscr.AttrOn(gc.ColorPair(2) | gc.A_BOLD) 46 | stdscr.MovePrint(4, 10, "Value 1:") 47 | stdscr.AttrOff(gc.ColorPair(2) | gc.A_BOLD) 48 | stdscr.MovePrint(6, 10, "Value 2:") 49 | stdscr.Refresh() 50 | 51 | form.Driver(gc.REQ_FIRST_FIELD) 52 | 53 | ch := stdscr.GetChar() 54 | for ch != 'q' { 55 | switch ch { 56 | case gc.KEY_DOWN, gc.KEY_TAB: 57 | form.Driver(gc.REQ_NEXT_FIELD) 58 | form.Driver(gc.REQ_END_LINE) 59 | case gc.KEY_UP: 60 | form.Driver(gc.REQ_PREV_FIELD) 61 | form.Driver(gc.REQ_END_LINE) 62 | case gc.KEY_BACKSPACE: 63 | form.Driver(gc.REQ_CLR_FIELD) 64 | default: 65 | form.Driver(ch) 66 | } 67 | ch = stdscr.GetChar() 68 | } 69 | stdscr.MovePrint(20, 0, fields[1].Buffer()) 70 | stdscr.GetChar() 71 | } 72 | -------------------------------------------------------------------------------- /examples/getstr/getstr.go: -------------------------------------------------------------------------------- 1 | // goncurses - ncurses library for Go. 2 | // Copyright 2011 Rob Thornton. All rights reserved. 3 | // Use of this source code is governed by a BSD-style 4 | // license that can be found in the LICENSE file. 5 | 6 | /* This example demonstrates reading a string from input, rather than a 7 | * single character */ 8 | package main 9 | 10 | import ( 11 | gc "github.com/rthornton128/goncurses" 12 | "log" 13 | ) 14 | 15 | func main() { 16 | stdscr, err := gc.Init() 17 | if err != nil { 18 | log.Fatal("init:", err) 19 | } 20 | defer gc.End() 21 | 22 | msg := "Enter a string: " 23 | row, col := stdscr.MaxYX() 24 | row, col = (row/2)-1, (col-len(msg))/2 25 | stdscr.MovePrint(row, col, msg) 26 | 27 | /* GetString will only retrieve the specified number of characters. Any 28 | attempts by the user to enter more characters will elicit an audible 29 | beep */ 30 | var str string 31 | str, err = stdscr.GetString(10) 32 | if err != nil { 33 | stdscr.MovePrint(row+1, col, "GetString Error:", err) 34 | } else { 35 | stdscr.MovePrintf(row+1, col, "You entered: %s", str) 36 | } 37 | 38 | stdscr.Refresh() 39 | stdscr.GetChar() 40 | } 41 | -------------------------------------------------------------------------------- /examples/hello/hello.go: -------------------------------------------------------------------------------- 1 | // goncurses - ncurses library for Go. 2 | // Copyright 2011 Rob Thornton. All rights reserved. 3 | // Use of this source code is governed by a BSD-style 4 | // license that can be found in the LICENSE file. 5 | 6 | /* The classic "Hello, World!" program in Goncurses! */ 7 | package main 8 | 9 | import ( 10 | "github.com/rthornton128/goncurses" 11 | "log" 12 | ) 13 | 14 | func main() { 15 | // Initialize goncurses. It's essential End() is called to ensure the 16 | // terminal isn't altered after the program ends 17 | stdscr, err := goncurses.Init() 18 | if err != nil { 19 | log.Fatal("init", err) 20 | } 21 | defer goncurses.End() 22 | 23 | // (Go)ncurses draws by cursor position and uses reverse Cartesian 24 | // coordinate system (y,x). Initially, the cursor is positioned at the 25 | // coordinates 0,0 so the first call to Print will output the text at the 26 | // top, left position of the screen since stdscr is a window which 27 | // represents the terminal's screen size. 28 | stdscr.Print("Hello, World!") 29 | stdscr.MovePrint(3, 0, "Press any key to continue") 30 | 31 | // Refresh() flushes output to the screen. Internally, it is the same as 32 | // calling NoutRefresh() on the window followed by a call to Update() 33 | stdscr.Refresh() 34 | 35 | // GetChar will block execution until an input event, like typing a 36 | // character on your keyboard, is received 37 | stdscr.GetChar() 38 | } 39 | -------------------------------------------------------------------------------- /examples/init/init.go: -------------------------------------------------------------------------------- 1 | // goncurses - ncurses library for Go. 2 | // Copyright 2011 Rob Thornton. All rights reserved. 3 | // Use of this source code is governed by a BSD-style 4 | // license that can be found in the LICENSE file. 5 | 6 | /* Demonstrates some of the initilization options for ncurses; 7 | In gnome, the F1 key launches help, so F2 is tested for instead */ 8 | package main 9 | 10 | import ( 11 | "github.com/rthornton128/goncurses" 12 | "log" 13 | ) 14 | 15 | func main() { 16 | stdscr, err := goncurses.Init() 17 | if err != nil { 18 | log.Fatal("init", err) 19 | } 20 | defer goncurses.End() 21 | 22 | goncurses.Raw(true) // turn on raw "uncooked" input 23 | goncurses.Echo(false) // turn echoing of typed characters off 24 | goncurses.Cursor(0) // hide cursor 25 | stdscr.Keypad(true) // allow keypad input 26 | 27 | stdscr.Print("Press a key...") 28 | stdscr.Refresh() 29 | 30 | if ch := stdscr.GetChar(); ch == goncurses.KEY_F2 { 31 | stdscr.Print("The F2 key was pressed.") 32 | } else { 33 | stdscr.Print("The key pressed is: ") 34 | stdscr.AttrOn(goncurses.A_BOLD) 35 | stdscr.AddChar(goncurses.Char(ch)) 36 | stdscr.AttrOff(goncurses.A_BOLD) 37 | } 38 | stdscr.Refresh() 39 | stdscr.GetChar() 40 | } 41 | -------------------------------------------------------------------------------- /examples/menu/menu.go: -------------------------------------------------------------------------------- 1 | // goncurses - ncurses library for Go. 2 | // Copyright 2011 Rob Thornton. All rights reserved. 3 | // Use of this source code is governed by a BSD-style 4 | // license that can be found in the LICENSE file. 5 | 6 | /* This example demonstrates the use of the menu library */ 7 | package main 8 | 9 | import ( 10 | "github.com/rthornton128/goncurses" 11 | "log" 12 | ) 13 | 14 | const ( 15 | HEIGHT = 10 16 | WIDTH = 30 17 | ) 18 | 19 | func main() { 20 | stdscr, err := goncurses.Init() 21 | if err != nil { 22 | log.Fatal("init:", err) 23 | } 24 | defer goncurses.End() 25 | 26 | goncurses.Raw(true) 27 | goncurses.Echo(false) 28 | goncurses.Cursor(0) 29 | stdscr.Clear() 30 | stdscr.Keypad(true) 31 | 32 | menu_items := []string{"Choice 1", "Choice 2", "Choice 3", "Choice 4", 33 | "Exit"} 34 | items := make([]*goncurses.MenuItem, len(menu_items)) 35 | for i, val := range menu_items { 36 | items[i], _ = goncurses.NewItem(val, "") 37 | defer items[i].Free() 38 | } 39 | 40 | menu, err := goncurses.NewMenu(items) 41 | if err != nil { 42 | stdscr.Print(err) 43 | return 44 | } 45 | defer menu.Free() 46 | 47 | menu.Post() 48 | 49 | stdscr.MovePrint(20, 0, "'q' to exit") 50 | stdscr.Refresh() 51 | 52 | for { 53 | goncurses.Update() 54 | ch := stdscr.GetChar() 55 | 56 | switch goncurses.KeyString(ch) { 57 | case "q": 58 | return 59 | case "down": 60 | menu.Driver(goncurses.REQ_DOWN) 61 | case "up": 62 | menu.Driver(goncurses.REQ_UP) 63 | } 64 | } 65 | } 66 | -------------------------------------------------------------------------------- /examples/menu_mcol/mcolmenu.go: -------------------------------------------------------------------------------- 1 | // goncurses - ncurses library for Go. 2 | // Copyright 2011 Rob Thornton. All rights reserved. 3 | // Use of this source code is governed by a BSD-style 4 | // license that can be found in the LICENSE file. 5 | 6 | /* This example shows a basic multi-column menu similar to that found in the 7 | * ncurses examples from TLDP */ 8 | package main 9 | 10 | import gc "github.com/rthornton128/goncurses" 11 | 12 | const ( 13 | HEIGHT = 10 14 | WIDTH = 40 15 | ) 16 | 17 | func main() { 18 | stdscr, _ := gc.Init() 19 | defer gc.End() 20 | 21 | gc.StartColor() 22 | gc.Raw(true) 23 | gc.Echo(false) 24 | gc.Cursor(0) 25 | stdscr.Keypad(true) 26 | gc.InitPair(1, gc.C_RED, gc.C_BLACK) 27 | gc.InitPair(2, gc.C_CYAN, gc.C_BLACK) 28 | 29 | // build the menu items 30 | menu_items := []string{ 31 | "Choice 1", 32 | "Choice 2", 33 | "Choice 3", 34 | "Choice 4", 35 | "Choice 5", 36 | "Choice 6", 37 | "Choice 7", 38 | "Choice 8", 39 | "Choice 9", 40 | "Choice 10", 41 | "Choice 11", 42 | "Choice 12", 43 | "Choice 13", 44 | "Choice 14", 45 | "Choice 15", 46 | "Choice 16", 47 | "Choice 17", 48 | "Choice 18", 49 | "Choice 19", 50 | "Choice 20", 51 | "Exit"} 52 | items := make([]*gc.MenuItem, len(menu_items)) 53 | for i, val := range menu_items { 54 | items[i], _ = gc.NewItem(val, "") 55 | defer items[i].Free() 56 | } 57 | 58 | // create the menu 59 | menu, _ := gc.NewMenu(items) 60 | defer menu.Free() 61 | 62 | menuwin, _ := gc.NewWindow(HEIGHT, WIDTH, 4, 14) 63 | menuwin.Keypad(true) 64 | 65 | menu.SetWindow(menuwin) 66 | dwin := menuwin.Derived(6, 38, 3, 1) 67 | menu.SubWindow(dwin) 68 | menu.Option(gc.O_SHOWDESC, true) 69 | menu.Format(5, 3) 70 | menu.Mark(" * ") 71 | 72 | // MovePrint centered menu title 73 | title := "My Menu" 74 | menuwin.Box(0, 0) 75 | menuwin.ColorOn(1) 76 | menuwin.MovePrint(1, (WIDTH/2)-(len(title)/2), title) 77 | menuwin.ColorOff(1) 78 | menuwin.MoveAddChar(2, 0, gc.ACS_LTEE) 79 | menuwin.HLine(2, 1, gc.ACS_HLINE, WIDTH-2) 80 | menuwin.MoveAddChar(2, WIDTH-1, gc.ACS_RTEE) 81 | 82 | y, _ := stdscr.MaxYX() 83 | stdscr.ColorOn(2) 84 | stdscr.MovePrint(y-3, 1, 85 | "Use up/down arrows or page up/down to navigate. 'q' to exit") 86 | stdscr.ColorOff(2) 87 | stdscr.Refresh() 88 | 89 | menu.Post() 90 | defer menu.UnPost() 91 | menuwin.Refresh() 92 | 93 | for { 94 | gc.Update() 95 | 96 | if ch := menuwin.GetChar(); ch == 'q' { 97 | return 98 | } else { 99 | menu.Driver(gc.DriverActions[ch]) 100 | } 101 | } 102 | } 103 | -------------------------------------------------------------------------------- /examples/menu_scroll/scrollmenu.go: -------------------------------------------------------------------------------- 1 | // goncurses - ncurses library for Go. 2 | // Copyright 2011 Rob Thornton. All rights reserved. 3 | // Use of this source code is governed by a BSD-style 4 | // license that can be found in the LICENSE file. 5 | 6 | /* This example shows a scrolling menu similar to that found in the ncurses 7 | * examples from TLDP */ 8 | package main 9 | 10 | import gc "github.com/rthornton128/goncurses" 11 | 12 | const ( 13 | HEIGHT = 10 14 | WIDTH = 40 15 | ) 16 | 17 | func main() { 18 | stdscr, _ := gc.Init() 19 | defer gc.End() 20 | 21 | gc.StartColor() 22 | gc.Raw(true) 23 | gc.Echo(false) 24 | gc.Cursor(0) 25 | stdscr.Keypad(true) 26 | gc.InitPair(1, gc.C_RED, gc.C_BLACK) 27 | gc.InitPair(2, gc.C_CYAN, gc.C_BLACK) 28 | 29 | // build the menu items 30 | menu_items := []string{ 31 | "Choice 1", 32 | "Choice 2", 33 | "Choice 3", 34 | "Choice 4", 35 | "Choice 5", 36 | "Choice 6", 37 | "Choice 7", 38 | "Choice 8", 39 | "Choice 9", 40 | "Choice 10", 41 | "Exit"} 42 | items := make([]*gc.MenuItem, len(menu_items)) 43 | for i, val := range menu_items { 44 | items[i], _ = gc.NewItem(val, "") 45 | defer items[i].Free() 46 | } 47 | 48 | // create the menu 49 | menu, _ := gc.NewMenu(items) 50 | defer menu.Free() 51 | 52 | menuwin, _ := gc.NewWindow(HEIGHT, WIDTH, 4, 14) 53 | menuwin.Keypad(true) 54 | 55 | menu.SetWindow(menuwin) 56 | dwin := menuwin.Derived(6, 38, 3, 1) 57 | menu.SubWindow(dwin) 58 | menu.Format(5, 1) 59 | menu.Mark(" * ") 60 | 61 | // Print centered menu title 62 | title := "My Menu" 63 | menuwin.Box(0, 0) 64 | menuwin.ColorOn(1) 65 | menuwin.MovePrint(1, (WIDTH/2)-(len(title)/2), title) 66 | menuwin.ColorOff(1) 67 | menuwin.MoveAddChar(2, 0, gc.ACS_LTEE) 68 | menuwin.HLine(2, 1, gc.ACS_HLINE, WIDTH-2) 69 | menuwin.MoveAddChar(2, WIDTH-1, gc.ACS_RTEE) 70 | 71 | y, _ := stdscr.MaxYX() 72 | stdscr.ColorOn(2) 73 | stdscr.MovePrint(y-3, 1, 74 | "Use up/down arrows or page up/down to navigate. 'q' to exit") 75 | stdscr.ColorOff(2) 76 | stdscr.Refresh() 77 | 78 | menu.Post() 79 | defer menu.UnPost() 80 | menuwin.Refresh() 81 | 82 | for { 83 | gc.Update() 84 | if ch := menuwin.GetChar(); ch == 'q' { 85 | return 86 | } else { 87 | menu.Driver(gc.DriverActions[ch]) 88 | } 89 | } 90 | } 91 | -------------------------------------------------------------------------------- /examples/menu_subwin/submenu.go: -------------------------------------------------------------------------------- 1 | // goncurses - ncurses library for Go. 2 | // Copyright 2011 Rob Thornton. All rights reserved. 3 | // Use of this source code is governed by a BSD-style 4 | // license that can be found in the LICENSE file. 5 | 6 | /* This example show a basic menu similar to that found in the ncurses 7 | * examples from TLDP */ 8 | package main 9 | 10 | import gc "github.com/rthornton128/goncurses" 11 | 12 | func main() { 13 | stdscr, _ := gc.Init() 14 | defer gc.End() 15 | 16 | gc.StartColor() 17 | gc.Raw(true) 18 | gc.Echo(false) 19 | gc.Cursor(0) 20 | stdscr.Keypad(true) 21 | gc.InitPair(1, gc.C_RED, gc.C_BLACK) 22 | 23 | // build the menu items 24 | menu_items := []string{"Choice 1", "Choice 2", "Choice 3", "Choice 4", 25 | "Exit"} 26 | items := make([]*gc.MenuItem, len(menu_items)) 27 | for i, val := range menu_items { 28 | items[i], _ = gc.NewItem(val, "") 29 | defer items[i].Free() 30 | } 31 | 32 | // create the menu 33 | menu, _ := gc.NewMenu(items) 34 | defer menu.Free() 35 | 36 | menuwin, _ := gc.NewWindow(10, 40, 4, 14) 37 | menuwin.Keypad(true) 38 | 39 | menu.SetWindow(menuwin) 40 | dwin := menuwin.Derived(6, 38, 3, 1) 41 | menu.SubWindow(dwin) 42 | menu.Mark(" * ") 43 | 44 | // Print centered menu title 45 | y, x := menuwin.MaxYX() 46 | title := "My Menu" 47 | menuwin.Box(0, 0) 48 | menuwin.ColorOn(1) 49 | menuwin.MovePrint(1, (x/2)-(len(title)/2), title) 50 | menuwin.ColorOff(1) 51 | menuwin.MoveAddChar(2, 0, gc.ACS_LTEE) 52 | menuwin.HLine(2, 1, gc.ACS_HLINE, x-2) 53 | menuwin.MoveAddChar(2, x-1, gc.ACS_RTEE) 54 | 55 | y, x = stdscr.MaxYX() 56 | stdscr.MovePrint(y-2, 1, "'q' to exit") 57 | stdscr.Refresh() 58 | 59 | menu.Post() 60 | defer menu.UnPost() 61 | menuwin.Refresh() 62 | 63 | for { 64 | gc.Update() 65 | ch := menuwin.GetChar() 66 | 67 | switch ch { 68 | case 'q': 69 | return 70 | case gc.KEY_DOWN: 71 | menu.Driver(gc.REQ_DOWN) 72 | case gc.KEY_UP: 73 | menu.Driver(gc.REQ_UP) 74 | } 75 | } 76 | } 77 | -------------------------------------------------------------------------------- /examples/menugrey/menugrey.go: -------------------------------------------------------------------------------- 1 | // goncurses - ncurses library for Go. 2 | // Copyright 2011 Rob Thornton. All rights reserved. 3 | // Use of this source code is governed by a BSD-style 4 | // license that can be found in the LICENSE file. 5 | 6 | /* This example show a basic menu similar to that found in the ncurses 7 | * examples from TLDP */ 8 | package main 9 | 10 | import ( 11 | gc "github.com/rthornton128/goncurses" 12 | "log" 13 | ) 14 | 15 | func main() { 16 | stdscr, err := gc.Init() 17 | if err != nil { 18 | log.Fatal("init:", err) 19 | } 20 | defer gc.End() 21 | 22 | gc.StartColor() 23 | gc.Raw(true) 24 | gc.Echo(false) 25 | gc.Cursor(0) 26 | stdscr.Keypad(true) 27 | gc.InitPair(1, gc.C_RED, gc.C_BLACK) 28 | gc.InitPair(2, gc.C_GREEN, gc.C_BLACK) 29 | gc.InitPair(3, gc.C_MAGENTA, gc.C_BLACK) 30 | 31 | // build the menu items 32 | menu_items := []string{ 33 | "Choice 1", 34 | "Choice 2", 35 | "Choice 3", 36 | "Choice 4", 37 | "Choice 5", 38 | "Exit"} 39 | items := make([]*gc.MenuItem, len(menu_items)) 40 | for i, val := range menu_items { 41 | items[i], _ = gc.NewItem(val, "") 42 | defer items[i].Free() 43 | 44 | if i == 2 || i == 4 { 45 | items[i].Selectable(false) 46 | } 47 | } 48 | 49 | // create the menu 50 | menu, _ := gc.NewMenu(items) 51 | defer menu.Free() 52 | 53 | y, _ := stdscr.MaxYX() 54 | stdscr.MovePrint(y-3, 0, "Use up/down arrows to move; 'q' to exit") 55 | stdscr.Refresh() 56 | 57 | menu.SetForeground(gc.ColorPair(1) | gc.A_REVERSE) 58 | menu.SetBackground(gc.ColorPair(2) | gc.A_BOLD) 59 | menu.Grey(gc.ColorPair(3) | gc.A_BOLD) 60 | 61 | menu.Post() 62 | defer menu.UnPost() 63 | 64 | for { 65 | gc.Update() 66 | ch := stdscr.GetChar() 67 | switch ch { 68 | case ' ': 69 | menu.Driver(gc.REQ_TOGGLE) 70 | case 'q': 71 | return 72 | case gc.KEY_RETURN: 73 | stdscr.Move(20, 0) 74 | stdscr.ClearToEOL() 75 | stdscr.Printf("Item selected is: %s", menu.Current(nil).Name()) 76 | menu.PositionCursor() 77 | default: 78 | menu.Driver(gc.DriverActions[ch]) 79 | } 80 | } 81 | } 82 | -------------------------------------------------------------------------------- /examples/menutoggle/menutoggle.go: -------------------------------------------------------------------------------- 1 | // goncurses - ncurses library for Go. 2 | // Copyright 2011 Rob Thornton. All rights reserved. 3 | // Use of this source code is governed by a BSD-style 4 | // license that can be found in the LICENSE file. 5 | 6 | /* This example show a basic menu similar to that found in the ncurses 7 | * examples from TLDP */ 8 | package main 9 | 10 | import gc "github.com/rthornton128/goncurses" 11 | 12 | func main() { 13 | stdscr, _ := gc.Init() 14 | defer gc.End() 15 | 16 | gc.StartColor() 17 | gc.Raw(true) 18 | gc.Echo(false) 19 | gc.Cursor(0) 20 | stdscr.Keypad(true) 21 | 22 | // build the menu items 23 | menu_items := []string{ 24 | "Choice 1", 25 | "Choice 2", 26 | "Choice 3", 27 | "Choice 4", 28 | "Choice 5", 29 | "Choice 6", 30 | "Choice 7", 31 | "Exit"} 32 | items := make([]*gc.MenuItem, len(menu_items)) 33 | for i, val := range menu_items { 34 | items[i], _ = gc.NewItem(val, "") 35 | defer items[i].Free() 36 | } 37 | 38 | // create the menu 39 | menu, _ := gc.NewMenu(items) 40 | defer menu.Free() 41 | 42 | menu.Option(gc.O_ONEVALUE, false) 43 | 44 | y, _ := stdscr.MaxYX() 45 | stdscr.MovePrint(y-3, 0, "Use up/down arrows to move, spacebar to "+ 46 | "toggle and enter to print. 'q' to exit") 47 | stdscr.Refresh() 48 | 49 | menu.Post() 50 | defer menu.UnPost() 51 | 52 | for { 53 | gc.Update() 54 | ch := stdscr.GetChar() 55 | 56 | switch ch { 57 | case 'q': 58 | return 59 | case ' ': 60 | menu.Driver(gc.REQ_TOGGLE) 61 | case gc.KEY_RETURN, gc.KEY_ENTER: 62 | var list string 63 | for _, item := range menu.Items() { 64 | if item.Value() { 65 | list += "\"" + item.Name() + "\" " 66 | } 67 | } 68 | stdscr.Move(20, 0) 69 | stdscr.ClearToEOL() 70 | stdscr.MovePrint(20, 0, list) 71 | stdscr.Refresh() 72 | default: 73 | menu.Driver(gc.DriverActions[ch]) 74 | } 75 | } 76 | } 77 | -------------------------------------------------------------------------------- /examples/mouse/mouse.go: -------------------------------------------------------------------------------- 1 | // goncurses - ncurses library for Go. 2 | // Copyright 2011 Rob Thornton. All rights reserved. 3 | // Use of this source code is governed by a BSD-style 4 | // license that can be found in the LICENSE file. 5 | 6 | /* Expanding on the basic menu example, the example demonstrates how you 7 | * could possibly utilize the mouse to navigate a menu and select options 8 | */ 9 | package main 10 | 11 | import ( 12 | "log" 13 | 14 | gc "github.com/rthornton128/goncurses" 15 | ) 16 | 17 | const ( 18 | HEIGHT = 10 19 | WIDTH = 30 20 | ) 21 | 22 | func main() { 23 | var active int 24 | menu := []string{"Choice 1", "Choice 2", "Choice 3", "Choice 4", "Exit"} 25 | 26 | stdscr, err := gc.Init() 27 | if err != nil { 28 | log.Fatal("init:", err) 29 | } 30 | defer gc.End() 31 | 32 | gc.Raw(true) 33 | gc.Echo(false) 34 | gc.Cursor(0) 35 | stdscr.Keypad(true) 36 | 37 | y, x := 5, 2 38 | 39 | win, err := gc.NewWindow(HEIGHT, WIDTH, y, x) 40 | if err != nil { 41 | log.Fatal("new_window:", err) 42 | } 43 | stdscr.MovePrint(0, 0, "Use up/down arrow keys, enter to "+ 44 | "select or 'q' to quit") 45 | stdscr.MovePrint(1, 0, "You may also left mouse click on an entry to select") 46 | stdscr.Refresh() 47 | 48 | printmenu(win, menu, active) 49 | 50 | // Check to see if the Mouse is available. This function was not available 51 | // in older versions of ncurses (5.7 and older) and may return false even 52 | // if the mouse is in fact avaiable for use. 53 | if gc.MouseOk() { 54 | stdscr.MovePrint(3, 0, "WARN: Mouse support not detected.") 55 | } 56 | 57 | // Adjust the default mouse-click sensitivity to make it more responsive 58 | gc.MouseInterval(50) 59 | 60 | // If, for example, you are temporarily disabling the mouse or are 61 | // otherwise altering mouse button detection temporarily, you could 62 | // pass a pointer to a MouseButton object as the 2nd argument to 63 | // record that information. Invocation may look something like: 64 | 65 | var prev gc.MouseButton 66 | gc.MouseMask(gc.M_B1_PRESSED, nil) // only detect left mouse clicks 67 | gc.MouseMask(gc.M_ALL, &prev) // temporarily enable all mouse clicks 68 | gc.MouseMask(prev, nil) // change it back 69 | 70 | var key gc.Key 71 | for key != 'q' { 72 | key = stdscr.GetChar() 73 | switch key { 74 | case gc.KEY_UP: 75 | if active == 0 { 76 | active = len(menu) - 1 77 | } else { 78 | active -= 1 79 | } 80 | case gc.KEY_DOWN: 81 | if active == len(menu)-1 { 82 | active = 0 83 | } else { 84 | active += 1 85 | } 86 | case gc.KEY_MOUSE: 87 | /* pull the mouse event off the queue */ 88 | if md := gc.GetMouse(); md != nil { 89 | new := getactive(x, y, md.X, md.Y, menu) 90 | if new != -1 { 91 | active = new 92 | } 93 | } 94 | fallthrough 95 | case gc.KEY_RETURN, gc.KEY_ENTER, gc.Key('\r'): 96 | stdscr.MovePrintf(23, 0, "Choice #%d: %s selected", active+1, 97 | menu[active]) 98 | stdscr.ClearToEOL() 99 | stdscr.Refresh() 100 | default: 101 | stdscr.MovePrintf(23, 0, "Character pressed = %3d/%c", key, key) 102 | stdscr.ClearToEOL() 103 | stdscr.Refresh() 104 | } 105 | 106 | printmenu(win, menu, active) 107 | } 108 | } 109 | 110 | func getactive(x, y, mx, my int, menu []string) int { 111 | row := my - y - 2 112 | col := mx - x - 2 113 | 114 | if row < 0 || row > len(menu)-1 { 115 | return -1 116 | } 117 | 118 | l := menu[row] 119 | 120 | if col >= 0 && col < len(l) { 121 | return row 122 | } 123 | return -1 124 | } 125 | 126 | func printmenu(w *gc.Window, menu []string, active int) { 127 | y, x := 2, 2 128 | w.Box(0, 0) 129 | for i, s := range menu { 130 | if i == active { 131 | w.AttrOn(gc.A_REVERSE) 132 | w.MovePrint(y+i, x, s) 133 | w.AttrOff(gc.A_REVERSE) 134 | } else { 135 | w.MovePrint(y+i, x, s) 136 | } 137 | } 138 | w.Refresh() 139 | } 140 | -------------------------------------------------------------------------------- /examples/newterm/newterm.go: -------------------------------------------------------------------------------- 1 | // goncurses - ncurses library for Go. 2 | // Copyright 2011 Rob Thornton. All rights reserved. 3 | // Use of this source code is governed by a BSD-style 4 | // license that can be found in the LICENSE file. 5 | 6 | // This example demonstrates how one might write to multiple terminals from a 7 | // single program or redirect output. In order to run the program you must 8 | // supply a single argument with is a path to a pseudo-terminal device. 9 | // 10 | // This example should compile on Windows but running it may be problematic 11 | package main 12 | 13 | import ( 14 | "flag" 15 | gc "github.com/rthornton128/goncurses" 16 | "log" 17 | "os" 18 | ) 19 | 20 | func main() { 21 | var term1, term2 *gc.Screen 22 | var err error 23 | 24 | flag.Parse() 25 | 26 | if flag.NArg() != 1 { 27 | log.Fatal("Must supply path to a pseudo-terminal (ie. /dev/pts/0)") 28 | } 29 | 30 | // You can, for example, use the current psuedo-terminal to read/write to 31 | // You may need to change the to one you have read/write access to 32 | var pts *os.File 33 | pts, err = os.OpenFile(flag.Arg(0), os.O_RDWR, os.FileMode(666)) 34 | if err != nil { 35 | log.Fatal(err) 36 | } 37 | defer pts.Close() 38 | 39 | // Create a new terminal using the default $TERM type and the psuedo-terminal 40 | term1, err = gc.NewTerm("", pts, pts) 41 | if err != nil { 42 | log.Fatal("newterm:", err) 43 | } 44 | // Remember that defer is LIFO order and End must be called prior to Delete 45 | defer term1.Delete() 46 | defer term1.End() 47 | 48 | // Create a second terminal as if we had two to interact with 49 | term2, err = gc.NewTerm("", os.Stdout, os.Stdin) 50 | if err != nil { 51 | log.Fatal("newterm:", err) 52 | } 53 | // It is important that End is called on term2 prior to term1 54 | defer term2.Delete() 55 | defer term2.End() // comment out for an alternative to End 56 | //defer gc.End() // uncomment for alternate way to end 57 | //defer term2.Set() // uncomment 58 | 59 | // Set the active terminal to term1 60 | term1.Set() 61 | 62 | // Get the Standard Screen Window and write to the active terminal 63 | mw := gc.StdScr() 64 | mw.MovePrint(0, 0, "Term 1 works! Press any key to exit...") 65 | mw.Refresh() 66 | mw.GetChar() 67 | 68 | // activate term2 and send data to it 69 | term2.Set() 70 | mw.MovePrint(0, 0, "Term 2 works! Press any key to exit...") 71 | mw.Refresh() 72 | mw.GetChar() 73 | } 74 | -------------------------------------------------------------------------------- /examples/pad/pad.go: -------------------------------------------------------------------------------- 1 | // goncurses - ncurses library for Go. 2 | // Copyright 2011 Rob Thornton. All rights reserved. 3 | // Use of this source code is governed by a BSD-style 4 | // license that can be found in the LICENSE file. 5 | 6 | // A basic example of how to create and display a pad. Unlike a window, a 7 | // pad can exceed the size of the physical screen. In order to display a 8 | // pad you must select the portion you wish to view and where it should be 9 | // located on the screen. 10 | package main 11 | 12 | import ( 13 | gc "github.com/rthornton128/goncurses" 14 | "log" 15 | ) 16 | 17 | func main() { 18 | _, err := gc.Init() 19 | if err != nil { 20 | log.Fatal(err) 21 | } 22 | defer gc.End() 23 | 24 | // create a new pad of 50 rows and 200 columns... 25 | var pad *gc.Pad 26 | pad, err = gc.NewPad(50, 200) 27 | if err != nil { 28 | log.Fatal(err) 29 | } 30 | // ...and fill it with some characters 31 | for x := 0; x < 50; x++ { 32 | pad.MovePrint(x, x, "This is a pad.") 33 | } 34 | // Refresh the pad to show only a portion of the pad. Understanding 35 | // what these coordinates mean can be a bit tricky. The first two 36 | // coordinates are the position in the pad, in this case 0,5 (remember 37 | // the coordinates in ncurses are y,x). The next four set of numbers 38 | // are the coordinates of the pad on the screen (y1, x1, y2, x2): 39 | // 40 | // (y1,x1) +-------------+ 41 | // | | 42 | // | | 43 | // | | 44 | // | | 45 | // | | 46 | // | | 47 | // +-------------+ (y2, x2) 48 | // 49 | pad.Refresh(0, 5, 5, 10, 15, 25) 50 | pad.GetChar() 51 | } 52 | -------------------------------------------------------------------------------- /examples/panel/panel.go: -------------------------------------------------------------------------------- 1 | // goncurses - ncurses library for Go. 2 | // Copyright 2011 Rob Thornton. All rights reserved. 3 | // Use of this source code is governed by a BSD-style 4 | // license that can be found in the LICENSE file. 5 | 6 | /* A simmple example of how to use panels */ 7 | package main 8 | 9 | import gc "github.com/rthornton128/goncurses" 10 | 11 | func main() { 12 | stdscr, _ := gc.Init() 13 | defer gc.End() 14 | 15 | var panels [3]*gc.Panel 16 | y, x := 2, 4 17 | 18 | for i := 0; i < 3; i++ { 19 | window, _ := gc.NewWindow(10, 40, y+i, x+(i*5)) 20 | window.Box(0, 0) 21 | panels[i] = gc.NewPanel(window) 22 | } 23 | 24 | gc.UpdatePanels() 25 | gc.Update() 26 | 27 | stdscr.GetChar() 28 | } 29 | -------------------------------------------------------------------------------- /examples/panel2/panel2.go: -------------------------------------------------------------------------------- 1 | // goncurses - ncurses library for Go. 2 | // Copyright 2011 Rob Thornton. All rights reserved. 3 | // Use of this source code is governed by a BSD-style 4 | // license that can be found in the LICENSE file. 5 | 6 | /* A slightly more advanced example of how to use the panel routines */ 7 | package main 8 | 9 | import gc "github.com/rthornton128/goncurses" 10 | 11 | func main() { 12 | stdscr, _ := gc.Init() 13 | defer gc.End() 14 | 15 | gc.StartColor() 16 | gc.CBreak(true) 17 | gc.Echo(true) 18 | stdscr.Keypad(true) 19 | stdscr.Print("Hit 'tab' to cycle through windows, 'q' to quit") 20 | 21 | gc.InitPair(1, gc.C_RED, gc.C_BLACK) 22 | gc.InitPair(2, gc.C_GREEN, gc.C_BLACK) 23 | gc.InitPair(3, gc.C_BLUE, gc.C_BLACK) 24 | gc.InitPair(4, gc.C_CYAN, gc.C_BLACK) 25 | 26 | var panels [3]*gc.Panel 27 | y, x := 4, 10 28 | 29 | for i := 0; i < 3; i++ { 30 | h, w := 10, 40 31 | title := "Window Number %d" 32 | 33 | window, _ := gc.NewWindow(h, w, y+(i*4), x+(i*10)) 34 | window.Box(0, 0) 35 | window.MoveAddChar(2, 0, gc.ACS_LTEE) 36 | window.HLine(2, 1, gc.ACS_HLINE, w-2) 37 | window.MoveAddChar(2, w-1, gc.ACS_RTEE) 38 | window.ColorOn(int16(i + 1)) 39 | window.MovePrintf(1, (w/2)-(len(title)/2), title, i+1) 40 | window.ColorOff(int16(i + 1)) 41 | panels[i] = gc.NewPanel(window) 42 | 43 | } 44 | 45 | active := 2 46 | 47 | for { 48 | gc.UpdatePanels() 49 | gc.Update() 50 | 51 | switch stdscr.GetChar() { 52 | case 'q': 53 | return 54 | case gc.KEY_TAB: 55 | active += 1 56 | if active > 2 { 57 | active = 0 58 | } 59 | panels[active].Top() 60 | } 61 | } 62 | } 63 | -------------------------------------------------------------------------------- /examples/print/print.go: -------------------------------------------------------------------------------- 1 | // goncurses - ncurses library for Go. 2 | // Copyright 2011 Rob Thornton. All rights reserved. 3 | // Use of this source code is governed by a BSD-style 4 | // license that can be found in the LICENSE file. 5 | 6 | /* This example demonstrates the use of the print function. */ 7 | package main 8 | 9 | import gc "github.com/rthornton128/goncurses" 10 | 11 | func main() { 12 | stdscr, _ := gc.Init() 13 | defer gc.End() 14 | 15 | row, col := stdscr.MaxYX() 16 | msg := "Just a string " 17 | stdscr.MovePrint(row/2, (col-len(msg))/2, msg) 18 | 19 | stdscr.MovePrintf(row-3, 0, "This screen has %d rows and %d columns. ", 20 | row, col) 21 | stdscr.Println() 22 | stdscr.Print("Try resizing your terminal window and then " + 23 | "run this program again.") 24 | stdscr.Refresh() 25 | stdscr.GetChar() 26 | } 27 | -------------------------------------------------------------------------------- /examples/resize/resize.go: -------------------------------------------------------------------------------- 1 | // goncurses - ncurses library for Go. 2 | 3 | /* This example demonstrates the ability to resize. Only one of detecting SIGWINCH or KEY_RESIZE 4 | * is strictly needed, but depending on the options ncurses was built with, one or the other may 5 | * work better. */ 6 | package main 7 | 8 | import ( 9 | "os" 10 | "os/signal" 11 | "syscall" 12 | 13 | gc "github.com/rthornton128/goncurses" 14 | ) 15 | 16 | var stdscr *gc.Window 17 | var sigWinChCount, keyResizeCount int 18 | 19 | func main() { 20 | sigWinChCount = 0 21 | keyResizeCount = 0 22 | sigs := make(chan os.Signal, 1) 23 | signal.Notify(sigs, syscall.SIGWINCH) 24 | 25 | // Errors should not be ignored in production code 26 | stdscr, _ = gc.Init() 27 | defer gc.End() 28 | stdscr.Timeout(0) 29 | redrawDisplay() 30 | 31 | for { 32 | select { 33 | case <-sigs: 34 | sigWinChCount++ 35 | resize() 36 | default: 37 | c := stdscr.GetChar() 38 | switch c { 39 | case gc.KEY_RESIZE: 40 | keyResizeCount++ 41 | //resize() 42 | case 'q': 43 | return 44 | } 45 | } 46 | } 47 | } 48 | 49 | func redrawDisplay() { 50 | // Errors should not be ignored in production code 51 | stdscr.Clear() 52 | row, col := stdscr.MaxYX() 53 | tRow, tCol, _ := osTermSize() 54 | stdscr.MovePrintf(1, 1, " MaxYX shows %d rows and %d columns", row, col) 55 | stdscr.MovePrintf(2, 1, "osTermSize shows %d rows and %d columns", tRow, tCol) 56 | stdscr.MovePrintf(3, 1, " SIGWINCH has been sent %d times", sigWinChCount) 57 | stdscr.MovePrintf(4, 1, "KEY_RESIZE has been sent %d times", keyResizeCount) 58 | stdscr.MovePrint(6, 1, "Press 'q' to quit") 59 | stdscr.Box(0, 0) 60 | stdscr.Refresh() 61 | } 62 | 63 | func resize() { 64 | // Errors should not be ignored in production code 65 | tRow, tCol, _ := osTermSize() 66 | gc.ResizeTerm(tRow, tCol) 67 | 68 | redrawDisplay() 69 | } 70 | -------------------------------------------------------------------------------- /examples/resize/termsize.go: -------------------------------------------------------------------------------- 1 | // Inspired by https://stackoverflow.com/a/15784352/587091 2 | 3 | package main 4 | 5 | // #include 6 | import "C" 7 | 8 | import ( 9 | "syscall" 10 | "unsafe" 11 | ) 12 | 13 | func osTermSize() (int, int, error) { 14 | w := &C.struct_winsize{} 15 | // See http://www.delorie.com/djgpp/doc/libc/libc_495.html 16 | res, _, err := syscall.Syscall(syscall.SYS_IOCTL, 17 | uintptr(syscall.Stdin), 18 | uintptr(syscall.TIOCGWINSZ), 19 | uintptr(unsafe.Pointer(w)), 20 | ) 21 | if int(res) == -1 { 22 | return 0, 0, err 23 | } 24 | 25 | return int(w.ws_row), int(w.ws_col), nil 26 | } 27 | -------------------------------------------------------------------------------- /examples/slk/slk.go: -------------------------------------------------------------------------------- 1 | // goncurses - ncurses library for Go. 2 | // Copyright 2011 Rob Thornton. All rights reserved. 3 | // Use of this source code is governed by a BSD-style 4 | // license that can be found in the LICENSE file. 5 | 6 | /* Demonstarates the use of the SLK Soft-Keys facilities */ 7 | package main 8 | 9 | import ( 10 | gc "github.com/rthornton128/goncurses" 11 | "log" 12 | ) 13 | 14 | const SOFTKEYS = 1 15 | 16 | func main() { 17 | gc.SlkInit(gc.SLK_323) 18 | scr, err := gc.Init() 19 | if err != nil { 20 | log.Fatal("INIT:", err) 21 | } 22 | defer gc.End() 23 | 24 | gc.StartColor() 25 | gc.InitPair(SOFTKEYS, gc.C_YELLOW, gc.C_BLUE) 26 | 27 | scr.Print("Type any key to exit...") 28 | labels := [...]string{"ONE", "TWO", "THREE", "FOUR", "FIVE", "SIX", "SEVEN", 29 | "EIGHT"} 30 | for i := range labels { 31 | gc.SlkSet(i+1, labels[i], gc.SLK_CENTER) 32 | } 33 | gc.SlkColor(SOFTKEYS) 34 | gc.SlkNoutRefresh() 35 | scr.Refresh() 36 | scr.GetChar() 37 | } 38 | -------------------------------------------------------------------------------- /examples/starfield/starfield.go: -------------------------------------------------------------------------------- 1 | // Starfield is a simple Goncurses game demo. 2 | package main 3 | 4 | import ( 5 | gc "github.com/rthornton128/goncurses" 6 | "log" 7 | "math/rand" 8 | "os" 9 | "time" 10 | ) 11 | 12 | const density = 0.05 13 | const planet_density = 0.001 14 | 15 | var ship_ascii = []string{ 16 | ` ,`, 17 | ` |\-`, 18 | `>|^===0`, 19 | ` |/-`, 20 | ` '`, 21 | } 22 | 23 | func genStarfield(pl, pc int) *gc.Pad { 24 | pad, err := gc.NewPad(pl, pc) 25 | if err != nil { 26 | log.Fatal(err) 27 | } 28 | stars := int(float64(pc*pl) * density) 29 | planets := int(float64(pc*pl) * planet_density) 30 | for i := 0; i < stars; i++ { 31 | y, x := rand.Intn(pl), rand.Intn(pc) 32 | c := int16(rand.Intn(4) + 1) 33 | pad.AttrOn(gc.A_BOLD | gc.ColorPair(c)) 34 | pad.MovePrint(y, x, ".") 35 | pad.AttrOff(gc.A_BOLD | gc.ColorPair(c)) 36 | } 37 | for i := 0; i < planets; i++ { 38 | y, x := rand.Intn(pl), rand.Intn(pc) 39 | c := int16(rand.Intn(2) + 5) 40 | pad.ColorOn(c) 41 | if i%2 == 0 { 42 | pad.MoveAddChar(y, x, 'O') 43 | } 44 | pad.MoveAddChar(y, x, 'o') 45 | pad.ColorOff(c) 46 | } 47 | return pad 48 | } 49 | 50 | func handleInput(stdscr *gc.Window, ship *Ship) bool { 51 | lines, cols := stdscr.MaxYX() 52 | y, x := ship.YX() 53 | k := stdscr.GetChar() 54 | 55 | switch byte(k) { 56 | case 0: 57 | break 58 | case 'a': 59 | x-- 60 | if x < 2 { 61 | x = 2 62 | } 63 | case 'd': 64 | x++ 65 | if x > cols-3 { 66 | x = cols - 3 67 | } 68 | case 's': 69 | y++ 70 | if y > lines-4 { 71 | y = lines - 4 72 | } 73 | case 'w': 74 | y-- 75 | if y < 2 { 76 | y = 2 77 | } 78 | case ' ': 79 | objects = append(objects, newBullet(y+1, x+4)) 80 | objects = append(objects, newBullet(y+3, x+4)) 81 | default: 82 | return false 83 | } 84 | ship.MoveWindow(y, x) 85 | return true 86 | } 87 | 88 | type Object interface { 89 | Cleanup() 90 | Collide(int) 91 | Draw(*gc.Window) 92 | Expired(int, int) bool 93 | Update() 94 | } 95 | 96 | type Asteroid struct { 97 | *gc.Window 98 | alive bool 99 | y, x int 100 | sy, sx int 101 | } 102 | 103 | var speeds = []int{-75, -50, -25, -10, 0, 10, 25, 50, 75} 104 | 105 | func spawnAsteroid(my, mx int) { 106 | var y, x, sy, sx int 107 | switch rand.Intn(4) { 108 | case 0: 109 | y, x = 1, rand.Intn(mx-2)+1 110 | sy, sx = speeds[5:][rand.Intn(4)], speeds[rand.Intn(9)] 111 | case 1: 112 | y, x = rand.Intn(my-2)+1, 1 113 | sy, sx = speeds[rand.Intn(9)], speeds[5:][rand.Intn(4)] 114 | case 2: 115 | y, x = rand.Intn(my-2)+1, mx-2 116 | sy, sx = speeds[rand.Intn(9)], speeds[rand.Intn(4)] 117 | case 3: 118 | y, x = my-2, rand.Intn(mx-2)+1 119 | sy, sx = speeds[rand.Intn(4)], speeds[rand.Intn(9)] 120 | } 121 | w, err := gc.NewWindow(1, 1, y, x) 122 | if err != nil { 123 | log.Println("spawnAsteroid:", err) 124 | } 125 | a := &Asteroid{Window: w, alive: true, sy: sy, sx: sx, y: y * 100, 126 | x: x * 100} 127 | a.ColorOn(2) 128 | a.Print("@") 129 | objects = append(objects, a) 130 | } 131 | 132 | func (a *Asteroid) Cleanup() { 133 | a.Delete() 134 | } 135 | 136 | func (a *Asteroid) Collide(i int) { 137 | } 138 | 139 | func (a *Asteroid) Draw(w *gc.Window) { 140 | w.Overlay(a.Window) 141 | } 142 | 143 | func (a *Asteroid) Expired(my, mx int) bool { 144 | y, x := a.YX() 145 | if x <= 0 || x >= mx-1 || y <= 0 || y >= my-1 || !a.alive { 146 | return true 147 | } 148 | return false 149 | } 150 | 151 | func (a *Asteroid) Update() { 152 | a.y += a.sy 153 | a.x += a.sx 154 | a.MoveWindow(a.y/100, a.x/100) 155 | } 156 | 157 | type Bullet struct { 158 | *gc.Window 159 | alive bool 160 | } 161 | 162 | func newBullet(y, x int) *Bullet { 163 | w, err := gc.NewWindow(1, 1, y, x) 164 | if err != nil { 165 | log.Println("newBullet:", err) 166 | } 167 | w.AttrOn(gc.A_BOLD | gc.ColorPair(4)) 168 | w.Print("-") 169 | return &Bullet{w, true} 170 | } 171 | 172 | func (b *Bullet) Cleanup() { 173 | b.Delete() 174 | } 175 | 176 | func (b *Bullet) Collide(i int) { 177 | for k, v := range objects { 178 | if k == i { 179 | continue 180 | } 181 | switch a := v.(type) { 182 | case *Asteroid: 183 | ay, ax := a.YX() 184 | by, bx := b.YX() 185 | if ay == by && ax == bx { 186 | objects = append(objects, newExplosion(a.YX())) 187 | a.alive = false 188 | b.alive = false 189 | } 190 | } 191 | } 192 | } 193 | 194 | func (b *Bullet) Draw(w *gc.Window) { 195 | w.Overlay(b.Window) 196 | } 197 | 198 | func (b *Bullet) Expired(my, mx int) bool { 199 | _, x := b.YX() 200 | if x >= mx-1 || !b.alive { 201 | return true 202 | } 203 | return false 204 | } 205 | 206 | func (b *Bullet) Update() { 207 | y, x := b.YX() 208 | b.MoveWindow(y, x+1) 209 | } 210 | 211 | type Explosion struct { 212 | *gc.Window 213 | life int 214 | } 215 | 216 | func newExplosion(y, x int) *Explosion { 217 | w, err := gc.NewWindow(3, 3, y-1, x-1) 218 | if err != nil { 219 | log.Println("newExplosion:", err) 220 | } 221 | w.ColorOn(4) 222 | w.MovePrint(0, 0, `\ /`) 223 | w.AttrOn(gc.A_BOLD) 224 | w.MovePrint(1, 0, ` X `) 225 | w.AttrOn(gc.A_DIM) 226 | w.MovePrint(2, 0, `/ \`) 227 | return &Explosion{w, 5} 228 | } 229 | 230 | func (e *Explosion) Cleanup() { 231 | e.Delete() 232 | } 233 | 234 | func (e *Explosion) Collide(i int) {} 235 | 236 | func (e *Explosion) Draw(w *gc.Window) { 237 | w.Overlay(e.Window) 238 | } 239 | 240 | func (e *Explosion) Expired(y, x int) bool { 241 | return e.life <= 0 242 | } 243 | 244 | func (e *Explosion) Update() { 245 | e.life-- 246 | } 247 | 248 | type Ship struct { 249 | *gc.Window 250 | life int 251 | } 252 | 253 | func newShip(y, x int) *Ship { 254 | w, err := gc.NewWindow(5, 7, y, x) 255 | if err != nil { 256 | log.Fatal("newShip:", err) 257 | } 258 | for i := 0; i < len(ship_ascii); i++ { 259 | w.MovePrint(i, 0, ship_ascii[i]) 260 | } 261 | return &Ship{w, 5} 262 | } 263 | 264 | func (s *Ship) Cleanup() { 265 | s.Delete() 266 | } 267 | 268 | func (s *Ship) Collide(i int) { 269 | ty, tx := s.YX() 270 | by, bx := s.MaxYX() 271 | for _, ob := range objects { 272 | if a, ok := ob.(*Asteroid); ok { 273 | ay, ax := a.YX() 274 | if ay >= ty && ay+1 <= ty+by && ax >= tx && ax+1 <= tx+bx { 275 | objects = append(objects, newExplosion(a.YX())) 276 | a.alive = false 277 | s.life-- 278 | } 279 | } 280 | } 281 | } 282 | 283 | func (s *Ship) Draw(w *gc.Window) { 284 | w.Overlay(s.Window) 285 | } 286 | 287 | func (s *Ship) Expired(y, x int) bool { 288 | return s.life <= 0 289 | } 290 | 291 | func (s *Ship) Update() {} 292 | 293 | var objects = make([]Object, 0, 16) 294 | 295 | func updateObjects(my, mx int) { 296 | end := len(objects) 297 | tmp := make([]Object, 0, end) 298 | for _, ob := range objects { 299 | ob.Update() 300 | } 301 | for i, ob := range objects { 302 | ob.Collide(i) 303 | if ob.Expired(my, mx) { 304 | ob.Cleanup() 305 | } else { 306 | tmp = append(tmp, ob) 307 | } 308 | } 309 | if len(objects) > end { 310 | objects = append(tmp, objects[end:]...) 311 | } else { 312 | objects = tmp 313 | } 314 | } 315 | 316 | func drawObjects(s *gc.Window) { 317 | for _, ob := range objects { 318 | ob.Draw(s) 319 | } 320 | } 321 | 322 | func lifeToText(n int) string { 323 | s := "" 324 | for i := 0; i < n; i++ { 325 | s += "*" 326 | } 327 | return s 328 | } 329 | 330 | func main() { 331 | f, err := os.Create("err.log") 332 | if err != nil { 333 | log.Fatal(err) 334 | } 335 | defer f.Close() 336 | 337 | log.SetOutput(f) 338 | 339 | var stdscr *gc.Window 340 | stdscr, err = gc.Init() 341 | if err != nil { 342 | log.Println("Init:", err) 343 | } 344 | defer gc.End() 345 | 346 | rand.Seed(time.Now().Unix()) 347 | gc.StartColor() 348 | gc.Cursor(0) 349 | gc.Echo(false) 350 | gc.HalfDelay(1) 351 | 352 | gc.InitPair(1, gc.C_WHITE, gc.C_BLACK) 353 | gc.InitPair(2, gc.C_YELLOW, gc.C_BLACK) 354 | gc.InitPair(3, gc.C_MAGENTA, gc.C_BLACK) 355 | gc.InitPair(4, gc.C_RED, gc.C_BLACK) 356 | 357 | gc.InitPair(5, gc.C_BLUE, gc.C_BLACK) 358 | gc.InitPair(6, gc.C_GREEN, gc.C_BLACK) 359 | 360 | lines, cols := stdscr.MaxYX() 361 | pl, pc := lines, cols*3 362 | 363 | ship := newShip(lines/2, 5) 364 | objects = append(objects, ship) 365 | 366 | field := genStarfield(pl, pc) 367 | text := stdscr.Duplicate() 368 | 369 | c := time.NewTicker(time.Second / 2) 370 | c2 := time.NewTicker(time.Second / 16) 371 | px := 0 372 | 373 | loop: 374 | for { 375 | text.MovePrintf(0, 0, "Life: [%-5s]", lifeToText(ship.life)) 376 | stdscr.Erase() 377 | stdscr.Copy(field.Window, 0, px, 0, 0, lines-1, cols-1, true) 378 | drawObjects(stdscr) 379 | stdscr.Overlay(text) 380 | stdscr.Refresh() 381 | select { 382 | case <-c.C: 383 | spawnAsteroid(stdscr.MaxYX()) 384 | if px+cols >= pc { 385 | break loop 386 | } 387 | px++ 388 | case <-c2.C: 389 | updateObjects(stdscr.MaxYX()) 390 | drawObjects(stdscr) 391 | default: 392 | if !handleInput(stdscr, ship) || ship.Expired(-1, -1) { 393 | break loop 394 | } 395 | } 396 | } 397 | msg := "Game Over" 398 | end, err := gc.NewWindow(5, len(msg)+4, (lines/2)-2, (cols-len(msg))/2) 399 | if err != nil { 400 | log.Fatal("game over:", err) 401 | } 402 | end.MovePrint(2, 2, msg) 403 | end.Box(gc.ACS_VLINE, gc.ACS_HLINE) 404 | end.Refresh() 405 | gc.Nap(2000) 406 | } 407 | -------------------------------------------------------------------------------- /examples/window/window.go: -------------------------------------------------------------------------------- 1 | // goncurses - ncurses library for Go. 2 | // Copyright 2011 Rob Thornton. All rights reserved. 3 | // Use of this source code is governed by a BSD-style 4 | // license that can be found in the LICENSE file. 5 | 6 | /* This simple example demonstrates how one might move a window about the 7 | * screen. It is worthy of note that the window must be erased each time it 8 | * is moved. This is because a 'ghost' of the prior window will be left 9 | * behind. There are other techniques you could use depending on what you 10 | * need to achieve but this demonstrates a fairly simple method */ 11 | package main 12 | 13 | import ( 14 | gc "github.com/rthornton128/goncurses" 15 | "log" 16 | ) 17 | 18 | func main() { 19 | stdscr, err := gc.Init() 20 | if err != nil { 21 | log.Fatal(err) 22 | } 23 | defer gc.End() 24 | 25 | // Turn off character echo, hide the cursor and disable input buffering 26 | gc.Echo(false) 27 | gc.CBreak(true) 28 | gc.Cursor(0) 29 | 30 | stdscr.Print("Use arrow keys to move the window. Press 'q' to exit") 31 | stdscr.NoutRefresh() 32 | 33 | // Determine the center of the screen and offset those coordinates by 34 | // half of the window size we are about to create. These coordinates will 35 | // be used to move our window around the screen 36 | rows, cols := stdscr.MaxYX() 37 | height, width := 5, 10 38 | y, x := (rows-height)/2, (cols-width)/2 39 | 40 | // Create a new window centered on the screen and enable the use of the 41 | // keypad on it so the arrow keys are available 42 | var win *gc.Window 43 | win, err = gc.NewWindow(height, width, y, x) 44 | if err != nil { 45 | log.Fatal(err) 46 | } 47 | win.Keypad(true) 48 | 49 | main: 50 | for { 51 | // Clear the section of screen where the box is currently located so 52 | // that it is blanked by calling Erase on the window and refreshing it 53 | // so that the chances are sent to the virtual screen but not actually 54 | // output to the terminal 55 | win.Erase() 56 | win.NoutRefresh() 57 | // Move the window to it's new location (if any) and redraw it 58 | win.MoveWindow(y, x) 59 | win.Box(gc.ACS_VLINE, gc.ACS_HLINE) 60 | win.NoutRefresh() 61 | // Update will flush only the characters which have changed between the 62 | // physical screen and the virtual screen, minimizing the number of 63 | // characters which must be sent 64 | gc.Update() 65 | 66 | // In order for the window to display correctly, we must call GetChar() 67 | // on it rather than stdscr 68 | switch win.GetChar() { 69 | case 'q': 70 | break main 71 | case gc.KEY_LEFT: 72 | if x > 0 { 73 | x-- 74 | } 75 | case gc.KEY_RIGHT: 76 | if x < cols-width { 77 | x++ 78 | } 79 | case gc.KEY_UP: 80 | if y > 1 { 81 | y-- 82 | } 83 | case gc.KEY_DOWN: 84 | if y < rows-height { 85 | y++ 86 | } 87 | } 88 | } 89 | win.Delete() 90 | } 91 | -------------------------------------------------------------------------------- /ext.go: -------------------------------------------------------------------------------- 1 | // Copyright 2011 Rob Thornton. All rights reserved. 2 | // Use of this source code is governed by a BSD-style 3 | // license that can be found in the LICENSE file. 4 | 5 | // +build !windows 6 | 7 | package goncurses 8 | 9 | // #include 10 | // #include 11 | // #include 12 | import "C" 13 | 14 | import ( 15 | "errors" 16 | "syscall" 17 | ) 18 | 19 | // DriverActions is a convenience mapping for common responses 20 | // to keyboard input 21 | var DriverActions = map[Key]MenuDriverReq{ 22 | KEY_DOWN: C.REQ_DOWN_ITEM, 23 | KEY_HOME: C.REQ_FIRST_ITEM, 24 | KEY_END: C.REQ_LAST_ITEM, 25 | KEY_LEFT: C.REQ_LEFT_ITEM, 26 | KEY_PAGEDOWN: C.REQ_SCR_DPAGE, 27 | KEY_PAGEUP: C.REQ_SCR_UPAGE, 28 | KEY_RIGHT: C.REQ_RIGHT_ITEM, 29 | KEY_UP: C.REQ_UP_ITEM, 30 | } 31 | 32 | var errList = map[C.int]string{ 33 | C.E_SYSTEM_ERROR: "System error occurred", 34 | C.E_BAD_ARGUMENT: "Incorrect or out-of-range argument", 35 | C.E_POSTED: "Form has already been posted", 36 | C.E_CONNECTED: "Field is already connected to a form", 37 | C.E_BAD_STATE: "Bad state", 38 | C.E_NO_ROOM: "No room", 39 | C.E_NOT_POSTED: "Form has not been posted", 40 | C.E_UNKNOWN_COMMAND: "Unknown command", 41 | C.E_NO_MATCH: "No match", 42 | C.E_NOT_SELECTABLE: "Not selectable", 43 | C.E_NOT_CONNECTED: "Field is not connected to a form", 44 | C.E_REQUEST_DENIED: "Request denied", 45 | C.E_INVALID_FIELD: "Invalid field", 46 | C.E_CURRENT: "Current", 47 | } 48 | 49 | func ncursesError(e error) error { 50 | errno, ok := e.(syscall.Errno) 51 | if int(errno) == C.OK { 52 | e = nil 53 | } 54 | if ok { 55 | errstr, ok := errList[C.int(errno)] 56 | if ok { 57 | return errors.New(errstr) 58 | } 59 | } 60 | return e 61 | } 62 | -------------------------------------------------------------------------------- /ext_defs.go: -------------------------------------------------------------------------------- 1 | // Copyright 2011 Rob Thornton. All rights reserved. 2 | // Use of this source code is governed by a BSD-style 3 | // license that can be found in the LICENSE file. 4 | 5 | // +build !windows 6 | 7 | package goncurses 8 | 9 | // #include 10 | // #include 11 | import "C" 12 | 13 | // Form Driver Requests 14 | type FormDriverReq C.int 15 | 16 | const ( 17 | REQ_NEXT_PAGE FormDriverReq = C.REQ_NEXT_PAGE // next page 18 | REQ_PREV_PAGE = C.REQ_PREV_PAGE // previous page 19 | REQ_FIRST_PAGE = C.REQ_FIRST_PAGE // first page 20 | REQ_LAST_PAGE = C.REQ_LAST_PAGE // last page 21 | REQ_NEXT_FIELD = C.REQ_NEXT_FIELD // next field 22 | REQ_PREV_FIELD = C.REQ_PREV_FIELD // previous field 23 | REQ_FIRST_FIELD = C.REQ_FIRST_FIELD // first field 24 | REQ_LAST_FIELD = C.REQ_LAST_FIELD // last field 25 | REQ_SNEXT_FIELD = C.REQ_SNEXT_FIELD // sorted next field 26 | REQ_SPREV_FIELD = C.REQ_SPREV_FIELD // sorted previous field 27 | REQ_SFIRST_FIELD = C.REQ_SFIRST_FIELD // sorted first field 28 | REQ_SLAST_FIELD = C.REQ_SLAST_FIELD // sorted last field 29 | REQ_LEFT_FIELD = C.REQ_LEFT_FIELD // left field 30 | REQ_RIGHT_FIELD = C.REQ_RIGHT_FIELD // right field 31 | REQ_UP_FIELD = C.REQ_UP_FIELD // up to a field 32 | REQ_DOWN_FIELD = C.REQ_DOWN_FIELD // down to a field 33 | REQ_NEXT_CHAR = C.REQ_NEXT_CHAR // next character in field 34 | REQ_PREV_CHAR = C.REQ_PREV_CHAR // previous character in field 35 | REQ_NEXT_LINE = C.REQ_NEXT_LINE // next line 36 | REQ_PREV_LINE = C.REQ_PREV_LINE // previous line 37 | REQ_NEXT_WORD = C.REQ_NEXT_WORD // next word 38 | REQ_PREV_WORD = C.REQ_PREV_WORD // previous word 39 | REQ_BEG_FIELD = C.REQ_BEG_FIELD // beginning of field 40 | REQ_END_FIELD = C.REQ_END_FIELD // end of field 41 | REQ_BEG_LINE = C.REQ_BEG_LINE // beginning of line 42 | REQ_END_LINE = C.REQ_END_LINE // end of line 43 | REQ_LEFT_CHAR = C.REQ_LEFT_CHAR // character to the left 44 | REQ_RIGHT_CHAR = C.REQ_RIGHT_CHAR // character to the right 45 | REQ_UP_CHAR = C.REQ_UP_CHAR // up a character 46 | REQ_DOWN_CHAR = C.REQ_DOWN_CHAR // down a character 47 | REQ_NEW_LINE = C.REQ_NEW_LINE // insert of overlay a new line 48 | REQ_INS_CHAR = C.REQ_INS_CHAR // insert a blank character at cursor 49 | REQ_INS_LINE = C.REQ_INS_LINE // insert a blank line at cursor 50 | REQ_DEL_CHAR = C.REQ_DEL_CHAR // delete character at cursor 51 | REQ_DEL_PREV = C.REQ_DEL_PREV // delete character before cursor 52 | REQ_DEL_LINE = C.REQ_DEL_LINE // delete line 53 | REQ_DEL_WORD = C.REQ_DEL_WORD // delete word 54 | REQ_CLR_EOL = C.REQ_CLR_EOL // clear from cursor to end of line 55 | REQ_CLR_EOF = C.REQ_CLR_EOF // clear from cursor to end of field 56 | REQ_CLR_FIELD = C.REQ_CLR_FIELD // clear field 57 | REQ_OVL_MODE = C.REQ_OVL_MODE // overlay mode 58 | REQ_INS_MODE = C.REQ_INS_MODE // insert mode 59 | REQ_SCR_FLINE = C.REQ_SCR_FLINE // scroll field forward a line 60 | REQ_SCR_BLINE = C.REQ_SCR_BLINE // scroll field back a line 61 | REQ_SCR_FPAGE = C.REQ_SCR_FPAGE // scroll field forward a page 62 | REQ_SCR_BPAGE = C.REQ_SCR_BPAGE // scroll field back a page 63 | REQ_SCR_FHPAGE = C.REQ_SCR_FHPAGE // scroll field forward half a page 64 | REQ_SCR_BHPAGE = C.REQ_SCR_BHPAGE // scroll field back half a page 65 | REQ_SCR_FCHAR = C.REQ_SCR_FCHAR // scroll field forward a character 66 | REQ_SCR_BCHAR = C.REQ_SCR_BCHAR // scroll field back a character 67 | REQ_SCR_HFLINE = C.REQ_SCR_HFLINE // horisontal scroll field forward a line 68 | REQ_SCR_HBLINE = C.REQ_SCR_HBLINE // horisontal scroll field back a line 69 | REQ_SCR_HFHALF = C.REQ_SCR_HFHALF // horisontal scroll field forward half a line 70 | REQ_SCR_HBHALF = C.REQ_SCR_HBHALF // horisontal scroll field back half a line 71 | REQ_VALIDATION = C.REQ_VALIDATION // validate field 72 | REQ_NEXT_CHOICE = C.REQ_NEXT_CHOICE // display next field choice 73 | REQ_PREV_CHOICE = C.REQ_PREV_CHOICE // display previous field choice 74 | ) 75 | 76 | const ( 77 | FO_VISIBLE = C.O_VISIBLE // Field visibility 78 | FO_ACTIVE = C.O_ACTIVE // Field is sensitive/accessable 79 | FO_PUBLIC = C.O_PUBLIC // Typed characters are echoed 80 | FO_EDIT = C.O_EDIT // Editable 81 | FO_WRAP = C.O_WRAP // Line wrapping 82 | FO_BLANK = C.O_BLANK // Clear on entry 83 | FO_AUTOSKIP = C.O_AUTOSKIP // Skip to next field when current filled 84 | FO_NULLOK = C.O_NULLOK // Blank ok 85 | FO_STATIC = C.O_STATIC // Fixed size 86 | FO_PASSOK = C.O_PASSOK // Field validation 87 | ) 88 | 89 | // Menu Driver Requests 90 | type MenuDriverReq C.int 91 | 92 | const ( 93 | REQ_LEFT MenuDriverReq = C.REQ_LEFT_ITEM 94 | REQ_RIGHT MenuDriverReq = C.REQ_RIGHT_ITEM 95 | REQ_UP MenuDriverReq = C.REQ_UP_ITEM 96 | REQ_DOWN MenuDriverReq = C.REQ_DOWN_ITEM 97 | REQ_ULINE MenuDriverReq = C.REQ_SCR_ULINE 98 | REQ_DLINE MenuDriverReq = C.REQ_SCR_DLINE 99 | REQ_PAGE_DOWN MenuDriverReq = C.REQ_SCR_DPAGE 100 | REQ_PAGE_UP MenuDriverReq = C.REQ_SCR_UPAGE 101 | REQ_FIRST MenuDriverReq = C.REQ_FIRST_ITEM 102 | REQ_LAST MenuDriverReq = C.REQ_LAST_ITEM 103 | REQ_NEXT MenuDriverReq = C.REQ_NEXT_ITEM 104 | REQ_PREV MenuDriverReq = C.REQ_PREV_ITEM 105 | REQ_TOGGLE MenuDriverReq = C.REQ_TOGGLE_ITEM 106 | REQ_CLEAR_PATTERN MenuDriverReq = C.REQ_CLEAR_PATTERN 107 | REQ_BACK_PATTERN MenuDriverReq = C.REQ_BACK_PATTERN 108 | REQ_NEXT_MATCH MenuDriverReq = C.REQ_NEXT_MATCH 109 | REQ_PREV_MATCH MenuDriverReq = C.REQ_PREV_MATCH 110 | ) 111 | 112 | // Menu Options 113 | const ( 114 | O_ONEVALUE = C.O_ONEVALUE // Only one item can be selected 115 | O_SHOWDESC = C.O_SHOWDESC // Display item descriptions 116 | O_ROWMAJOR = C.O_ROWMAJOR // Display in row-major order 117 | O_IGNORECASE = C.O_IGNORECASE // Ignore case when pattern-matching 118 | O_SHOWMATCH = C.O_SHOWMATCH // Move cursor to item when pattern-matching 119 | O_NONCYCLIC = C.O_NONCYCLIC // Don't wrap next/prev item 120 | ) 121 | 122 | // Menu Item Options 123 | const O_SELECTABLE = C.O_SELECTABLE 124 | -------------------------------------------------------------------------------- /form.go: -------------------------------------------------------------------------------- 1 | // Copyright 2011 Rob Thornton. All rights reserved. 2 | // Use of this source code is governed by a BSD-style 3 | // license that can be found in the LICENSE file. 4 | 5 | // +build !windows 6 | 7 | package goncurses 8 | 9 | // #cgo !darwin,!openbsd pkg-config: form 10 | // #cgo darwin openbsd LDFLAGS: -lform 11 | // #include 12 | // #include 13 | import "C" 14 | 15 | import ( 16 | "syscall" 17 | "unsafe" 18 | ) 19 | 20 | type Field C.FIELD 21 | 22 | type Form struct { 23 | form *C.FORM 24 | } 25 | 26 | func NewField(h, w, tr, lc, oscr, nbuf int32) (*Field, error) { 27 | f, err := C.new_field(C.int(h), C.int(w), C.int(tr), C.int(lc), 28 | C.int(oscr), C.int(nbuf)) 29 | return (*Field)(f), ncursesError(err) 30 | } 31 | 32 | // Background returns the field's background character attributes 33 | func (f *Field) Background() Char { 34 | return Char(C.field_back((*C.FIELD)(f))) 35 | } 36 | 37 | // Buffer returns a string containing the contents of the buffer. The returned 38 | // string will contain whitespace up to the buffer size as set by SetMax or 39 | // the value by the call to NewField 40 | func (f *Field) Buffer() string { 41 | str := C.field_buffer((*C.FIELD)(f), C.int(0)) 42 | 43 | return C.GoString(str) 44 | } 45 | 46 | // Duplicate the field at the specified coordinates, returning a pointer 47 | // to the newly allocated object. 48 | func (f *Field) Duplicate(y, x int32) (*Field, error) { 49 | nf, err := C.dup_field((*C.FIELD)(f), C.int(y), C.int(x)) 50 | return (*Field)(nf), ncursesError(err) 51 | } 52 | 53 | // Foreground returns the field's foreground character attributes 54 | func (f *Field) Foreground() Char { 55 | return Char(C.field_fore((*C.FIELD)(f))) 56 | } 57 | 58 | // Free field's allocated memory. This must be called to prevent memory 59 | // leaks 60 | func (f *Field) Free() error { 61 | err := C.free_field((*C.FIELD)(f)) 62 | f = nil 63 | return ncursesError(syscall.Errno(err)) 64 | } 65 | 66 | // Info retrieves the height, width, y, x, offset and buffer size of the 67 | // given field. Pass the memory address of the variable to store the data 68 | // in or nil. 69 | func (f *Field) Info(h, w, y, x, off, nbuf *int) error { 70 | err := C.field_info((*C.FIELD)(f), (*C.int)(unsafe.Pointer(h)), 71 | (*C.int)(unsafe.Pointer(w)), (*C.int)(unsafe.Pointer(y)), 72 | (*C.int)(unsafe.Pointer(x)), (*C.int)(unsafe.Pointer(off)), 73 | (*C.int)(unsafe.Pointer(nbuf))) 74 | return ncursesError(syscall.Errno(err)) 75 | } 76 | 77 | // Just returns the justification type of the field 78 | func (f *Field) Justification() int { 79 | return int(C.field_just((*C.FIELD)(f))) 80 | } 81 | 82 | // Move the field to the location of the specified coordinates 83 | func (f *Field) Move(y, x int32) error { 84 | err := C.move_field((*C.FIELD)(f), C.int(y), C.int(x)) 85 | return ncursesError(syscall.Errno(err)) 86 | } 87 | 88 | // Options turns features on and off 89 | func (f *Field) Options(opts int, on bool) { 90 | if on { 91 | C.field_opts_on((*C.FIELD)(f), C.Field_Options(opts)) 92 | return 93 | } 94 | C.field_opts_off((*C.FIELD)(f), C.Field_Options(opts)) 95 | } 96 | 97 | // Pad returns the padding character of the field 98 | func (f *Field) Pad() int { 99 | return int(C.field_pad((*C.FIELD)(f))) 100 | } 101 | 102 | // SetBuffer sets the visible characters in the field. A buffer is empty by 103 | // default. 104 | func (f *Field) SetBuffer(s string) error { 105 | cstr := C.CString(s) 106 | defer C.free(unsafe.Pointer(cstr)) 107 | 108 | err := C.set_field_buffer((*C.FIELD)(f), C.int(0), cstr) 109 | return ncursesError(syscall.Errno(err)) 110 | } 111 | 112 | // SetJustification of the field 113 | func (f *Field) SetJustification(just int) error { 114 | err := C.set_field_just((*C.FIELD)(f), C.int(just)) 115 | return ncursesError(syscall.Errno(err)) 116 | } 117 | 118 | // SetMax sets the maximum size of a field 119 | func (f *Field) SetMax(max int) error { 120 | err := C.set_max_field((*C.FIELD)(f), C.int(max)) 121 | return ncursesError(syscall.Errno(err)) 122 | } 123 | 124 | // OptionsOff turns feature(s) off 125 | func (f *Field) SetOptionsOff(opts Char) error { 126 | err := int(C.field_opts_off((*C.FIELD)(f), C.Field_Options(opts))) 127 | if err != C.E_OK { 128 | return ncursesError(syscall.Errno(err)) 129 | } 130 | return nil 131 | } 132 | 133 | // OptionsOn turns feature(s) on 134 | func (f *Field) SetOptionsOn(opts Char) error { 135 | err := int(C.field_opts_on((*C.FIELD)(f), C.Field_Options(opts))) 136 | if err != C.E_OK { 137 | return ncursesError(syscall.Errno(err)) 138 | } 139 | return nil 140 | } 141 | 142 | // SetPad sets the padding character of the field 143 | func (f *Field) SetPad(padch int) error { 144 | err := C.set_field_pad((*C.FIELD)(f), C.int(padch)) 145 | return ncursesError(syscall.Errno(err)) 146 | } 147 | 148 | // SetBackground character and attributes (colours, etc) 149 | func (f *Field) SetBackground(ch Char) error { 150 | err := C.set_field_back((*C.FIELD)(f), C.chtype(ch)) 151 | return ncursesError(syscall.Errno(err)) 152 | } 153 | 154 | // SetForeground character and attributes (colours, etc) 155 | func (f *Field) SetForeground(ch Char) error { 156 | err := C.set_field_fore((*C.FIELD)(f), C.chtype(ch)) 157 | return ncursesError(syscall.Errno(err)) 158 | } 159 | 160 | // NewForm returns a new form object using the fields array supplied as 161 | // an argument 162 | func NewForm(fields []*Field) (Form, error) { 163 | if fields[len(fields)-1] != nil { 164 | fields = append(fields, nil) 165 | } 166 | form, err := C.new_form((**C.FIELD)(unsafe.Pointer(&fields[0]))) 167 | 168 | return Form{form}, ncursesError(err) 169 | } 170 | 171 | // FieldCount returns the number of fields attached to the Form 172 | func (f *Form) FieldCount() int { 173 | return int(C.field_count(f.form)) 174 | } 175 | 176 | // Driver issues the actions requested to the form itself. See the 177 | // corresponding REQ_* constants 178 | func (f *Form) Driver(drvract Key) error { 179 | err := C.form_driver(f.form, C.int(drvract)) 180 | return ncursesError(syscall.Errno(err)) 181 | } 182 | 183 | // Free the memory allocated to the form. Forms are not automatically 184 | // free'd by Go's garbage collection system so the memory allocated to 185 | // it must be explicitly free'd 186 | func (f *Form) Free() error { 187 | err := C.free_form(f.form) 188 | f = nil 189 | return ncursesError(syscall.Errno(err)) 190 | } 191 | 192 | // Post the form, making it visible and interactive 193 | func (f *Form) Post() error { 194 | err := C.post_form(f.form) 195 | return ncursesError(syscall.Errno(err)) 196 | } 197 | 198 | // SetFields overwrites the current fields for the Form with new ones. 199 | // It is important to make sure all prior fields have been freed otherwise 200 | // this action will result in a memory leak 201 | func (f *Form) SetFields(fields []*Field) error { 202 | //cfields := make([]*C.FIELD, len(fields)+1) 203 | //for index, field := range fields { 204 | //cfields[index] = field.field 205 | //} 206 | //cfields[len(fields)] = nil 207 | err := C.set_form_fields(f.form, (**C.FIELD)(unsafe.Pointer(&fields[0]))) 208 | return ncursesError(syscall.Errno(err)) 209 | } 210 | 211 | // SetOptions for the form 212 | func (f *Form) SetOptions(opts int) error { 213 | _, err := C.set_form_opts(f.form, (C.Form_Options)(opts)) 214 | return ncursesError(err) 215 | } 216 | 217 | // SetSub sets the subwindow associated with the form 218 | func (f *Form) SetSub(w *Window) error { 219 | err := int(C.set_form_sub(f.form, w.win)) 220 | return ncursesError(syscall.Errno(err)) 221 | } 222 | 223 | // SetWindow sets the window associated with the form 224 | func (f *Form) SetWindow(w *Window) error { 225 | err := int(C.set_form_win(f.form, w.win)) 226 | return ncursesError(syscall.Errno(err)) 227 | } 228 | 229 | // Sub returns the subwindow associated with the form 230 | func (f *Form) Sub() Window { 231 | return Window{C.form_sub(f.form)} 232 | } 233 | 234 | // UnPost the form, removing it from the interface 235 | func (f *Form) UnPost() error { 236 | err := C.unpost_form(f.form) 237 | return ncursesError(syscall.Errno(err)) 238 | } 239 | -------------------------------------------------------------------------------- /go.mod: -------------------------------------------------------------------------------- 1 | module github.com/rthornton128/goncurses 2 | 3 | go 1.15 4 | -------------------------------------------------------------------------------- /goncurses.c: -------------------------------------------------------------------------------- 1 | // Copyright 2011 Rob Thornton. All rights reserved. 2 | // Use of this source code is governed by a BSD-style 3 | // license that can be found in the LICENSE file. 4 | 5 | #include 6 | #include 7 | #include 8 | 9 | #ifdef PDCURSES 10 | bool is_term_resized(int y, int x) { return is_termresized(); } 11 | int resizeterm(int y, int x) { return resize_term(y, x); } 12 | int ncurses_getmouse(MEVENT *me) { return nc_getmouse(me); } 13 | int ncurses_has_key(int ch) { return has_key(ch) == true ? 1 : 0; } 14 | int ncurses_ungetch(int ch) { return PDC_ungetch(ch); } 15 | int ncurses_wattroff(WINDOW *win, int attr ) { 16 | return wattroff(win, (chtype) attr); 17 | } 18 | int ncurses_wattron(WINDOW *win, int attr) { 19 | return wattron(win, (chtype) attr); 20 | } 21 | #else 22 | int ncurses_getmouse(MEVENT *me) { return getmouse(me); } 23 | int ncurses_has_key(int ch) { return has_key(ch); } 24 | int ncurses_ungetch(int ch) { return ungetch(ch); } 25 | int ncurses_wattroff(WINDOW *win, int attr) { return wattroff(win, attr); } 26 | int ncurses_wattron(WINDOW *win, int attr) { return wattron(win, attr); } 27 | #endif 28 | 29 | int ncurses_COLOR_PAIR(int p) { return COLOR_PAIR(p); } 30 | chtype ncurses_getbkgd(WINDOW *win) { return getbkgd(win); } 31 | void ncurses_getyx(WINDOW *win, int *y, int *x) { getyx(win, *y, *x); } 32 | void ncurses_getbegyx(WINDOW *win, int *y, int *x) { getbegyx(win, *y, *x); } 33 | void ncurses_getmaxyx(WINDOW *win, int *y, int *x) { getmaxyx(win, *y, *x); } 34 | 35 | WINDOW *ncurses_wgetparent(const WINDOW *win) { 36 | #ifdef PDCURSES 37 | return win->_parent; 38 | #else 39 | return wgetparent(win); 40 | #endif 41 | } 42 | 43 | bool ncurses_is_cleared(const WINDOW *win) { 44 | #ifdef PDCURSES 45 | return win->_clear; 46 | #else 47 | return is_cleared(win); 48 | #endif 49 | } 50 | 51 | bool ncurses_is_keypad(const WINDOW *win) { 52 | #ifdef PDCURSES 53 | return win->_use_keypad; 54 | #else 55 | return is_keypad(win); 56 | #endif 57 | } 58 | 59 | bool ncurses_is_pad(const WINDOW *win) { 60 | #if defined(PDCURSES) || NCURSES_VERSION_MAJOR < 6 61 | return false; /* no known built-in way to test for this */ 62 | #else 63 | return is_pad(win); 64 | #endif 65 | } 66 | 67 | bool ncurses_is_subwin(const WINDOW *win) { 68 | #ifdef PDCURSES 69 | return win->_parent != NULL; 70 | #elif NCURSES_VERSION_MAJOR > 5 71 | return is_subwin(win); 72 | #else 73 | return false; /* FIXME */ 74 | #endif 75 | } 76 | 77 | 78 | bool ncurses_has_mouse(void) { 79 | #if NCURSES_VERSION_MINOR < 8 80 | return false; 81 | #else 82 | return has_mouse(); 83 | #endif 84 | } 85 | 86 | int ncurses_touchwin(WINDOW *win) { return touchwin(win); } 87 | int ncurses_untouchwin(WINDOW *win) { return untouchwin(win); } 88 | int ncurses_wattrset(WINDOW *win, int attr) { return wattrset(win, attr); } 89 | int ncurses_wstandend(WINDOW *win) { return wstandend(win); } 90 | int ncurses_wstandout(WINDOW *win) { return wstandout(win); } 91 | 92 | bool goncurses_set_escdelay(int size) { 93 | #ifdef PDCURSES 94 | return false; 95 | #else 96 | ESCDELAY = size; 97 | return true; 98 | #endif 99 | } 100 | -------------------------------------------------------------------------------- /goncurses.h: -------------------------------------------------------------------------------- 1 | // Copyright 2011 Rob Thornton. All rights reserved. 2 | // Use of this source code is governed by a BSD-style 3 | // license that can be found in the LICENSE file. 4 | #ifndef _GONCURSES_ 5 | #define _GONCURSES_ 1 6 | 7 | #ifdef PDCURSES 8 | bool is_term_resized(int y, int x); 9 | int resizeterm(int y, int x); 10 | #endif 11 | 12 | int ncurses_COLOR_PAIR(int p); 13 | chtype ncurses_getbkgd(WINDOW *win); 14 | void ncurses_getbegyx(WINDOW *win, int *y, int *x); 15 | void ncurses_getmaxyx(WINDOW *win, int *y, int *x); 16 | int ncurses_getmouse(MEVENT *me); 17 | void ncurses_getyx(WINDOW *win, int *y, int *x); 18 | int ncurses_has_key(int); 19 | bool ncurses_has_mouse(void); 20 | bool ncurses_is_cleared(const WINDOW *win); 21 | bool ncurses_is_keypad(const WINDOW *win); 22 | bool ncurses_is_pad(const WINDOW *win); 23 | bool ncurses_is_subwin(const WINDOW *win); 24 | int ncurses_touchwin(WINDOW *win); 25 | int ncurses_ungetch(int ch); 26 | int ncurses_untouchwin(WINDOW *win); 27 | int ncurses_wattroff(WINDOW *, int); 28 | int ncurses_wattron(WINDOW *, int); 29 | int ncurses_wattrset(WINDOW *win, int attr); 30 | WINDOW * ncurses_wgetparent(const WINDOW *win); 31 | int ncurses_wstandend(WINDOW *win); 32 | int ncurses_wstandout(WINDOW *win); 33 | bool goncurses_set_escdelay(int size); 34 | 35 | #endif /* _GONCURSES_ */ 36 | -------------------------------------------------------------------------------- /menu.go: -------------------------------------------------------------------------------- 1 | // Copyright 2011 Rob Thornton. All rights reserved. 2 | // Use of this source code is governed by a BSD-style 3 | // license that can be found in the LICENSE file. 4 | 5 | // +build !windows 6 | 7 | package goncurses 8 | 9 | /* 10 | #cgo !darwin,!openbsd pkg-config: menu 11 | #cgo darwin openbsd LDFLAGS: -lmenu 12 | #include 13 | #include 14 | 15 | ITEM* menu_item_at(ITEM** ilist, int i) { 16 | return ilist[i]; 17 | }*/ 18 | import "C" 19 | 20 | import ( 21 | "syscall" 22 | "unsafe" 23 | ) 24 | 25 | type Menu struct { 26 | menu *C.MENU 27 | } 28 | 29 | type MenuItem struct { 30 | item *C.ITEM 31 | } 32 | 33 | // NewMenu returns a pointer to a new menu. 34 | func NewMenu(items []*MenuItem) (*Menu, error) { 35 | citems := make([]*C.ITEM, len(items)+1) 36 | for index, item := range items { 37 | citems[index] = item.item 38 | } 39 | citems[len(items)] = nil 40 | var menu *C.MENU 41 | var err error 42 | menu, err = C.new_menu((**C.ITEM)(&citems[0])) 43 | return &Menu{menu}, ncursesError(err) 44 | } 45 | 46 | // RequestName of menu request code 47 | func RequestName(request int) (string, error) { 48 | cstr, err := C.menu_request_name(C.int(request)) 49 | return C.GoString(cstr), ncursesError(err) 50 | } 51 | 52 | // RequestByName returns the request ID of the provide request 53 | func RequestByName(request string) (res int, err error) { 54 | cstr := C.CString(request) 55 | defer C.free(unsafe.Pointer(cstr)) 56 | 57 | res = int(C.menu_request_by_name(cstr)) 58 | err = ncursesError(syscall.Errno(res)) 59 | return 60 | } 61 | 62 | // Background returns the menu's background character setting 63 | func (m *Menu) Background() int { 64 | return int(C.menu_back(m.menu)) 65 | } 66 | 67 | // Count returns the number of MenuItems in the Menu 68 | func (m *Menu) Count() int { 69 | return int(C.item_count(m.menu)) 70 | } 71 | 72 | // Current returns the selected item in the menu 73 | func (m *Menu) Current(mi *MenuItem) *MenuItem { 74 | if mi == nil { 75 | return &MenuItem{C.current_item(m.menu)} 76 | } 77 | C.set_current_item(m.menu, mi.item) 78 | return nil 79 | } 80 | 81 | // Driver controls how the menu is activated. Action usually corresponds 82 | // to the string returned by the Key() function in goncurses. 83 | func (m *Menu) Driver(daction MenuDriverReq) error { 84 | err := C.menu_driver(m.menu, C.int(daction)) 85 | return ncursesError(syscall.Errno(err)) 86 | } 87 | 88 | // Foreground gets the attributes of highlighted items in the menu 89 | func (m *Menu) Foreground() int { 90 | return int(C.menu_fore(m.menu)) 91 | } 92 | 93 | // Format sets the menu format. See the O_* menu options. 94 | func (m *Menu) Format(r, c int) error { 95 | err := C.set_menu_format(m.menu, C.int(r), C.int(c)) 96 | return ncursesError(syscall.Errno(err)) 97 | } 98 | 99 | // Free deallocates memory set aside for the menu. This must be called 100 | // before exiting. 101 | func (m *Menu) Free() error { 102 | err := C.free_menu(m.menu) 103 | m = nil 104 | return ncursesError(syscall.Errno(err)) 105 | } 106 | 107 | // Grey sets the attributes of non-selectable items in the menu 108 | func (m *Menu) Grey(ch Char) { 109 | C.set_menu_grey(m.menu, C.chtype(ch)) 110 | } 111 | 112 | // Items will return the items in the menu. 113 | func (m *Menu) Items() []*MenuItem { 114 | citems := C.menu_items(m.menu) 115 | count := m.Count() 116 | mitems := make([]*MenuItem, count) 117 | for index := 0; index < count; index++ { 118 | mitems[index] = &MenuItem{C.menu_item_at(citems, C.int(index))} 119 | } 120 | return mitems 121 | } 122 | 123 | // Mark sets the indicator for the currently selected menu item 124 | func (m *Menu) Mark(mark string) error { 125 | cmark := C.CString(mark) 126 | defer C.free(unsafe.Pointer(cmark)) 127 | 128 | err := C.set_menu_mark(m.menu, cmark) 129 | return ncursesError(syscall.Errno(err)) 130 | } 131 | 132 | // Option sets the options for the menu. See the O_* definitions for 133 | // a list of values which can be OR'd together 134 | func (m *Menu) Option(opts int, on bool) error { 135 | var err C.int 136 | if on { 137 | err = C.menu_opts_on(m.menu, C.Menu_Options(opts)) 138 | } else { 139 | err = C.menu_opts_off(m.menu, C.Menu_Options(opts)) 140 | } 141 | return ncursesError(syscall.Errno(err)) 142 | } 143 | 144 | // Pad sets the padding character for menu items. 145 | func (m *Menu) Pad() int { 146 | return int(C.menu_pad(m.menu)) 147 | } 148 | 149 | // Pattern returns the menu's pattern buffer 150 | func (m *Menu) Pattern() string { 151 | return C.GoString(C.menu_pattern(m.menu)) 152 | } 153 | 154 | // PositionCursor sets the cursor over the currently selected menu item. 155 | func (m *Menu) PositionCursor() { 156 | C.pos_menu_cursor(m.menu) 157 | } 158 | 159 | // Post the menu, making it visible 160 | func (m *Menu) Post() error { 161 | err := C.post_menu(m.menu) 162 | return ncursesError(syscall.Errno(err)) 163 | } 164 | 165 | // Scale 166 | func (m *Menu) Scale() (int, int, error) { 167 | var y, x C.int 168 | err := C.scale_menu(m.menu, (*C.int)(&y), (*C.int)(&x)) 169 | return int(y), int(x), ncursesError(syscall.Errno(err)) 170 | } 171 | 172 | // SetBackground set the attributes of the un-highlighted items in the 173 | // menu 174 | func (m *Menu) SetBackground(ch Char) error { 175 | err := C.set_menu_back(m.menu, C.chtype(ch)) 176 | return ncursesError(syscall.Errno(err)) 177 | } 178 | 179 | // SetForeground sets the attributes of the highlighted items in the menu 180 | func (m *Menu) SetForeground(ch Char) error { 181 | err := C.set_menu_fore(m.menu, C.chtype(ch)) 182 | return ncursesError(syscall.Errno(err)) 183 | } 184 | 185 | // SetItems will either set the items in the menu. When setting 186 | // items you must make sure the prior menu items will be freed. 187 | func (m *Menu) SetItems(items []*MenuItem) error { 188 | citems := make([]*C.ITEM, len(items)+1) 189 | for index, item := range items { 190 | citems[index] = item.item 191 | } 192 | citems[len(items)] = nil 193 | err := C.set_menu_items(m.menu, (**C.ITEM)(&citems[0])) 194 | return ncursesError(syscall.Errno(err)) 195 | } 196 | 197 | // SetPad sets the padding character for menu items. 198 | func (m *Menu) SetPad(ch Char) error { 199 | err := C.set_menu_pad(m.menu, C.int(ch)) 200 | return ncursesError(syscall.Errno(err)) 201 | } 202 | 203 | // SetPattern sets the padding character for menu items. 204 | func (m *Menu) SetPattern(pattern string) error { 205 | cpattern := C.CString(pattern) 206 | defer C.free(unsafe.Pointer(cpattern)) 207 | err := C.set_menu_pattern(m.menu, (*C.char)(cpattern)) 208 | return ncursesError(syscall.Errno(err)) 209 | } 210 | 211 | // SetSpacing of the menu's items. 'desc' is the space between the 212 | // item and it's description and may not be larger than TAB_SIZE. 'row' 213 | // is the number of rows separating each item and may not be larger than 214 | // three. 'col' is the spacing between each column of items in 215 | // multi-column mode. Use values of 0 or 1 to reset spacing to default, 216 | // which is one 217 | func (m *Menu) SetSpacing(desc, row, col int) error { 218 | err := C.set_menu_spacing(m.menu, C.int(desc), C.int(row), 219 | C.int(col)) 220 | return ncursesError(syscall.Errno(err)) 221 | } 222 | 223 | // SetWindow container for the menu 224 | func (m *Menu) SetWindow(w *Window) error { 225 | err := C.set_menu_win(m.menu, w.win) 226 | return ncursesError(syscall.Errno(err)) 227 | } 228 | 229 | // Spacing returns the menu item spacing. See SetSpacing for a description 230 | func (m *Menu) Spacing() (int, int, int) { 231 | var desc, row, col C.int 232 | C.menu_spacing(m.menu, (*C.int)(&desc), (*C.int)(&row), 233 | (*C.int)(&col)) 234 | 235 | return int(desc), int(row), int(col) 236 | } 237 | 238 | // SubWindow for the menu 239 | func (m *Menu) SubWindow(sub *Window) error { 240 | err := C.set_menu_sub(m.menu, sub.win) 241 | return ncursesError(syscall.Errno(err)) 242 | } 243 | 244 | // UnPost the menu, effectively hiding it. 245 | func (m *Menu) UnPost() error { 246 | err := C.unpost_menu(m.menu) 247 | return ncursesError(syscall.Errno(err)) 248 | } 249 | 250 | // Window container for the menu. Returns nil on failure 251 | func (m *Menu) Window() *Window { 252 | return &Window{C.menu_win(m.menu)} 253 | } 254 | 255 | // NewItem creates a new menu item with name and description. 256 | func NewItem(name, desc string) (*MenuItem, error) { 257 | cname := C.CString(name) 258 | cdesc := C.CString(desc) 259 | 260 | var item *C.ITEM 261 | var err error 262 | item, err = C.new_item(cname, cdesc) 263 | return &MenuItem{item}, ncursesError(err) 264 | } 265 | 266 | // Description returns the second value passed to NewItem 267 | func (mi *MenuItem) Description() string { 268 | return C.GoString(C.item_description(mi.item)) 269 | } 270 | 271 | // Free must be called on all menu items to avoid memory leaks 272 | func (mi *MenuItem) Free() { 273 | C.free(unsafe.Pointer(C.item_name(mi.item))) 274 | C.free_item(mi.item) 275 | } 276 | 277 | // Index of the menu item in it's parent menu 278 | func (mi *MenuItem) Index() int { 279 | return int(C.item_index(mi.item)) 280 | } 281 | 282 | // Name of the menu item 283 | func (mi *MenuItem) Name() string { 284 | return C.GoString(C.item_name(mi.item)) 285 | } 286 | 287 | // Selectable turns on/off whether a menu option is "greyed out" 288 | func (mi *MenuItem) Selectable(on bool) { 289 | if on { 290 | C.item_opts_on(mi.item, O_SELECTABLE) 291 | } else { 292 | C.item_opts_off(mi.item, O_SELECTABLE) 293 | } 294 | } 295 | 296 | // SetValue sets whether an item is active or not 297 | func (mi *MenuItem) SetValue(val bool) error { 298 | err := int(C.set_item_value(mi.item, C.bool(val))) 299 | return ncursesError(syscall.Errno(err)) 300 | } 301 | 302 | // Value returns true if menu item is toggled/active, otherwise false 303 | func (mi *MenuItem) Value() bool { 304 | return bool(C.item_value(mi.item)) 305 | } 306 | 307 | // Visible returns true if the item is visible, false if not 308 | func (mi *MenuItem) Visible() bool { 309 | return bool(C.item_visible(mi.item)) 310 | } 311 | -------------------------------------------------------------------------------- /mouse.go: -------------------------------------------------------------------------------- 1 | // goncurses - ncurses library for Go. 2 | // Copyright 2011 Rob Thornton. All rights reserved. 3 | // Use of this source code is governed by a BSD-style 4 | // license that can be found in the LICENSE file. 5 | 6 | package goncurses 7 | 8 | // #cgo !darwin,!openbsd,!windows pkg-config: ncurses 9 | // #cgo windows CFLAGS: -DNCURSES_MOUSE_VERSION 10 | // #cgo windows LDFLAGS: -lpdcurses 11 | // #include 12 | // #include "goncurses.h" 13 | import "C" 14 | 15 | import ( 16 | "unsafe" 17 | ) 18 | 19 | type MouseEvent struct { 20 | Id int16 /* device ID */ 21 | X, Y, Z int /* event coordinates */ 22 | State MouseButton /* button state */ 23 | } 24 | 25 | // GetMouse returns the MouseEvent associated with a KEY_MOUSE event returned 26 | // by a call to GetChar(). Returns a new MouseEvent or nil on error or if no 27 | // event is currently in the mouse event queue 28 | func GetMouse() *MouseEvent { 29 | var event C.MEVENT 30 | if C.ncurses_getmouse(&event) != C.OK { 31 | return nil 32 | } 33 | return &MouseEvent{ 34 | Id: int16(event.id), 35 | Y: int(event.y), 36 | X: int(event.x), 37 | Z: int(event.z), 38 | State: MouseButton(event.bstate), 39 | } 40 | } 41 | 42 | // MouseOk returns true if ncurses has built-in mouse support. On ncurses 5.7 43 | // and earlier, this function is not present and so will always return false 44 | func MouseOk() bool { 45 | return bool(C.ncurses_has_mouse()) 46 | } 47 | 48 | // MouseInterval sets the maximum time in milliseconds that can elapse 49 | // between press and release mouse events and returns the previous setting. 50 | // Use a value of 0 (zero) to disable click resolution. Use a value of -1 51 | // to get the previous value without changing the current value. Default 52 | // value is 1/6 of a second. 53 | func MouseInterval(ms int) int { 54 | return int(C.mouseinterval(C.int(ms))) 55 | } 56 | 57 | // MouseMask accepts a single int of OR'd mouse events. If a mouse event 58 | // is triggered, GetChar() will return KEY_MOUSE. To retrieve the actual 59 | // event use GetMouse() to pop it off the queue. Pass a pointer as the 60 | // second argument to store the prior events being monitored or nil. 61 | func MouseMask(mask MouseButton, old *MouseButton) MouseButton { 62 | return MouseButton(C.mousemask((C.mmask_t)(mask), 63 | (*C.mmask_t)(unsafe.Pointer(old)))) 64 | } 65 | -------------------------------------------------------------------------------- /ncurses.go: -------------------------------------------------------------------------------- 1 | // goncurses - ncurses library for Go. 2 | // Copyright 2011 Rob Thornton. All rights reserved. 3 | // Use of this source code is governed by a BSD-style 4 | // license that can be found in the LICENSE file. 5 | 6 | package goncurses 7 | 8 | // #cgo !darwin,!openbsd,!windows pkg-config: ncurses 9 | // #cgo windows CFLAGS: -DNCURSES_MOUSE_VERSION 10 | // #cgo windows LDFLAGS: -lpdcurses 11 | // #cgo darwin openbsd LDFLAGS: -lncurses 12 | // #include 13 | // #include "goncurses.h" 14 | import "C" 15 | 16 | import ( 17 | "errors" 18 | "fmt" 19 | "unsafe" 20 | ) 21 | 22 | // BaudRate returns the speed of the terminal in bits per second 23 | func BaudRate() int { 24 | return int(C.baudrate()) 25 | } 26 | 27 | // Beep requests the terminal make an audible bell or, if not available, 28 | // flashes the screen. Note that screen flashing doesn't work on all 29 | // terminals 30 | func Beep() { 31 | C.beep() 32 | } 33 | 34 | // Turn on/off buffering; raw user signals are passed to the program for 35 | // handling. Overrides raw mode 36 | func CBreak(on bool) { 37 | if on { 38 | C.cbreak() 39 | return 40 | } 41 | C.nocbreak() 42 | } 43 | 44 | func TypeAhead(fd int) int { 45 | 46 | return int(C.typeahead(C.int(fd))) 47 | } 48 | 49 | // Test whether colour values can be changed 50 | func CanChangeColor() bool { 51 | return bool(C.bool(C.can_change_color())) 52 | } 53 | 54 | // Colors returns the number of colors that the terminal supports 55 | func Colors() int { 56 | return int(C.COLORS) 57 | } 58 | 59 | // Get RGB values for specified colour 60 | func ColorContent(col int16) (int16, int16, int16) { 61 | var r, g, b C.short 62 | C.color_content(C.short(col), (*C.short)(&r), (*C.short)(&g), 63 | (*C.short)(&b)) 64 | return int16(r), int16(g), int16(b) 65 | } 66 | 67 | // Return the value of a color pair which can be passed to functions which 68 | // accept attributes like AddChar, AttrOn/Off and Background. 69 | func ColorPair(pair int16) Char { 70 | return Char(C.ncurses_COLOR_PAIR(C.int(pair))) 71 | } 72 | 73 | // ColorPairs returns the maximum number of color pairs that the terminal supports 74 | func ColorPairs() int { 75 | return int(C.COLOR_PAIRS) 76 | } 77 | 78 | // CursesVersion returns the version of the ncurses library currently linked to 79 | func CursesVersion() string { 80 | return C.GoString(C.curses_version()) 81 | } 82 | 83 | // Set the cursor visibility. Options are: 0 (invisible/hidden), 1 (normal) 84 | // and 2 (extra-visible) 85 | func Cursor(vis byte) error { 86 | if C.curs_set(C.int(vis)) == C.ERR { 87 | return errors.New("Failed to enable ") 88 | } 89 | return nil 90 | } 91 | 92 | // Echo turns on/off the printing of typed characters 93 | func Echo(on bool) { 94 | if on { 95 | C.echo() 96 | return 97 | } 98 | C.noecho() 99 | } 100 | 101 | // Must be called prior to exiting the program in order to make sure the 102 | // terminal returns to normal operation 103 | func End() { 104 | C.endwin() 105 | } 106 | 107 | // Flash requests the terminal flashes the screen or, if not available, 108 | // make an audible bell. Note that screen flashing doesn't work on all 109 | // terminals 110 | func Flash() { 111 | C.flash() 112 | } 113 | 114 | // FlushInput flushes all input 115 | func FlushInput() error { 116 | if C.flushinp() == C.ERR { 117 | return errors.New("Flush input failed") 118 | } 119 | return nil 120 | } 121 | 122 | // Behaves like cbreak() but also adds a timeout for input. If timeout is 123 | // exceeded after a call to Getch() has been made then GetChar will return 124 | // with an error. 125 | func HalfDelay(delay int) error { 126 | var cerr C.int 127 | if delay > 0 { 128 | cerr = C.halfdelay(C.int(delay)) 129 | } 130 | if cerr == C.ERR { 131 | return errors.New("Unable to set delay mode") 132 | } 133 | return nil 134 | } 135 | 136 | // HasColors returns true if terminal can display colors 137 | func HasColors() bool { 138 | return bool(C.has_colors()) 139 | } 140 | 141 | // HasInsertChar return true if the terminal has insert and delete 142 | // character capabilities 143 | func HasInsertChar() bool { 144 | return bool(C.has_ic()) 145 | } 146 | 147 | // HasInsertLine returns true if the terminal has insert and delete line 148 | // capabilities. See ncurses documentation for more details 149 | func HasInsertLine() bool { 150 | return bool(C.has_il()) 151 | } 152 | 153 | // HasKey returns true if terminal recognized the given character 154 | func HasKey(ch Key) bool { 155 | if C.ncurses_has_key(C.int(ch)) == 1 { 156 | return true 157 | } 158 | return false 159 | } 160 | 161 | // InitColor is used to set 'color' to the specified RGB values. Values may 162 | // be between 0 and 1000. 163 | func InitColor(col, r, g, b int16) error { 164 | if C.init_color(C.short(col), C.short(r), C.short(g), 165 | C.short(b)) == C.ERR { 166 | return errors.New("Failed to set new color definition") 167 | } 168 | return nil 169 | } 170 | 171 | // InitPair sets a colour pair designated by 'pair' to fg and bg colors 172 | func InitPair(pair, fg, bg int16) error { 173 | if pair <= 0 || C.int(pair) > C.int(C.COLOR_PAIRS-1) { 174 | return errors.New("Color pair out of range") 175 | } 176 | if C.init_pair(C.short(pair), C.short(fg), C.short(bg)) == C.ERR { 177 | return errors.New("Failed to init color pair") 178 | } 179 | return nil 180 | } 181 | 182 | // Initialize the ncurses library. You must run this function prior to any 183 | // other goncurses function in order for the library to work 184 | func Init() (stdscr *Window, err error) { 185 | stdscr = &Window{C.initscr()} 186 | if unsafe.Pointer(stdscr.win) == nil { 187 | err = errors.New("An error occurred initializing ncurses") 188 | } 189 | return 190 | } 191 | 192 | // IsEnd returns true if End() has been called, otherwise false 193 | func IsEnd() bool { 194 | return bool(C.isendwin()) 195 | } 196 | 197 | // IsTermResized returns true if ResizeTerm would modify any current Windows 198 | // if called with the given parameters 199 | func IsTermResized(nlines, ncols int) bool { 200 | return bool(C.is_term_resized(C.int(nlines), C.int(ncols))) 201 | } 202 | 203 | // Returns a string representing the value of input returned by GetChar 204 | func KeyString(k Key) string { 205 | key, ok := keyList[k] 206 | if !ok { 207 | key = fmt.Sprintf("%c", int(k)) 208 | } 209 | return key 210 | } 211 | 212 | // PairContent returns the current foreground and background colours 213 | // associated with the given pair 214 | func PairContent(pair int16) (fg int16, bg int16, err error) { 215 | var f, b C.short 216 | if C.pair_content(C.short(pair), &f, &b) == C.ERR { 217 | return -1, -1, errors.New("Invalid color pair") 218 | } 219 | return int16(f), int16(b), nil 220 | } 221 | 222 | // Nap (sleep; halt execution) for 'ms' milliseconds 223 | func Nap(ms int) { 224 | C.napms(C.int(ms)) 225 | } 226 | 227 | // NewLines turns newline translation on/off. 228 | func NewLines(on bool) { 229 | if on { 230 | C.nl() 231 | return 232 | } 233 | C.nonl() 234 | } 235 | 236 | // Raw turns on input buffering; user signals are disabled and the key strokes 237 | // are passed directly to input. Set to false if you wish to turn this mode 238 | // off 239 | func Raw(on bool) { 240 | if on { 241 | C.raw() 242 | return 243 | } 244 | C.noraw() 245 | } 246 | 247 | // ResizeTerm will attempt to resize the terminal. This only has an effect if 248 | // the terminal is in an XWindows (GUI) environment. 249 | func ResizeTerm(nlines, ncols int) error { 250 | if C.resizeterm(C.int(nlines), C.int(ncols)) == C.ERR { 251 | return errors.New("Failed to resize terminal") 252 | } 253 | return nil 254 | } 255 | 256 | // Sets the delay from when the escape key is pressed until recognition. 257 | func SetEscDelay(size int) { 258 | C.goncurses_set_escdelay(C.int(size)) 259 | } 260 | 261 | // Enables colors to be displayed. Will return an error if terminal is not 262 | // capable of displaying colors 263 | func StartColor() error { 264 | if C.has_colors() == C.bool(false) { 265 | return errors.New("Terminal does not support colors") 266 | } 267 | if C.start_color() == C.ERR { 268 | return errors.New("Failed to enable color mode") 269 | } 270 | return nil 271 | } 272 | 273 | // StdScr returns a Window for the underlying stdscr object which represents 274 | // the physical screen. This is the same Window returned by Init and therefore 275 | // not useful unless using NewTerm and other multi-screen related functions. 276 | func StdScr() *Window { 277 | return &Window{C.stdscr} 278 | } 279 | 280 | // UnGetChar places the character back into the input queue 281 | func UnGetChar(ch Char) { 282 | C.ncurses_ungetch(C.int(ch)) 283 | } 284 | 285 | // Update the screen, refreshing all windows 286 | func Update() error { 287 | if C.doupdate() == C.ERR { 288 | return errors.New("Failed to update") 289 | } 290 | return nil 291 | } 292 | 293 | // UseDefaultColors tells the curses library to assign the terminal's default 294 | // foreground and background colors to color number -1. This will allow you to 295 | // call InitPair(x, -1, -1) to set both the foreground and background colours 296 | // of pair x to the terminal's default. This function can fail if the terminal 297 | // does not support certain ncurses features like orig_pair or initialize_pair. 298 | func UseDefaultColors() error { 299 | if C.use_default_colors() == C.ERR { 300 | return errors.New("Failed to assume default colours.") 301 | } 302 | return nil 303 | } 304 | 305 | // UseEnvironment specifies whether the LINES and COLUMNS environmental 306 | // variables should be used or not 307 | func UseEnvironment(use bool) { 308 | C.use_env(C.bool(use)) 309 | } 310 | 311 | // SetTabSize allows for modification of the tab width. This setting is global 312 | // and affects all windows. 313 | func SetTabSize(tabSize int) { 314 | C.TABSIZE = C.int(tabSize) 315 | } 316 | 317 | // TabSize returns the configured tab width. 318 | func TabSize() int { 319 | return int(C.TABSIZE) 320 | } 321 | -------------------------------------------------------------------------------- /ncurses_test.go: -------------------------------------------------------------------------------- 1 | // ncurses_example.go 2 | package goncurses_test 3 | 4 | import ( 5 | "testing" 6 | 7 | "github.com/rthornton128/goncurses" 8 | ) 9 | 10 | func TestInit(t *testing.T) { 11 | _, err := goncurses.Init() 12 | if err != nil { 13 | t.Fatal(err) 14 | } 15 | defer goncurses.End() 16 | } 17 | -------------------------------------------------------------------------------- /pad.go: -------------------------------------------------------------------------------- 1 | // goncurses - ncurses library for Go. 2 | // Copyright 2011 Rob Thornton. All rights reserved. 3 | // Use of this source code is governed by a BSD-style 4 | // license that can be found in the LICENSE file. 5 | 6 | package goncurses 7 | 8 | // #include 9 | // #include "goncurses.h" 10 | import "C" 11 | 12 | import "errors" 13 | 14 | type Pad struct { 15 | *Window 16 | } 17 | 18 | // NewPad creates a window which is not restricted by the terminal's 19 | // dimensions (unlike a Window). Pads accept all functions which can be 20 | // called on a window. It returns a pointer to a new Pad of h(eight) by 21 | // w(idth). 22 | func NewPad(h, w int) (*Pad, error) { 23 | p := C.newpad(C.int(h), C.int(w)) 24 | if p == nil { 25 | return nil, errors.New("Failed to create pad") 26 | } 27 | return &Pad{&Window{p}}, nil 28 | } 29 | 30 | // NoutRefresh indicates that a section of the screen should be redrawn but 31 | // does not update the physical screen until Update() is called. See 32 | // Pad.Refresh() for details on the arguments and Window.NoutRefresh for 33 | // more details on the workings of this function 34 | func (p *Pad) NoutRefresh(py, px, sy, sx, h, w int) error { 35 | ok := C.pnoutrefresh(p.win, C.int(py), C.int(px), C.int(sy), 36 | C.int(sx), C.int(h), C.int(w)) 37 | if ok != C.OK { 38 | return errors.New("Failed to refresh pad") 39 | } 40 | return nil 41 | } 42 | 43 | // Refresh will calculate how to update the physical screen in the most 44 | // efficient manor and update it. See Window.Refresh for more details. 45 | // The coordinates py, px specify the location on the pad from which the 46 | // characters we want to display are located. sy1 and sx1 specify the location 47 | // on the screen where this data should be displayed, hence the upper left 48 | // corner of the display area on the screen. sy2 and sx2 specify the location 49 | // of the lower right corner of the display area on the screen: 50 | // 51 | // (y1,x1) +-------------+ 52 | // | | 53 | // | | 54 | // | | 55 | // | | 56 | // | | 57 | // | | 58 | // +-------------+ (y2, x2) 59 | // 60 | // The coordinates of the rectangle must be contained within both the Pad's 61 | // and Window's respective areas. 62 | func (p *Pad) Refresh(py, px, sy1, sx1, sy2, sx2 int) error { 63 | if C.prefresh(p.win, C.int(py), C.int(px), C.int(sy1), C.int(sx1), 64 | C.int(sy2), C.int(sx2)) != C.OK { 65 | return errors.New("Failed to refresh pad") 66 | } 67 | return nil 68 | } 69 | 70 | // Sub creates a sub-pad h(eight) by w(idth) in size starting at the location 71 | // y, x in the parent pad. Changes to a sub-pad will also change it's parent 72 | func (p *Pad) Sub(y, x, h, w int) *Pad { 73 | return &Pad{&Window{C.subpad(p.win, C.int(h), C.int(w), C.int(y), 74 | C.int(x))}} 75 | } 76 | -------------------------------------------------------------------------------- /pad_posix.go: -------------------------------------------------------------------------------- 1 | // goncurses - ncurses library for Go. 2 | // Copyright 2011 Rob Thornton. All rights reserved. 3 | // Use of this source code is governed by a BSD-style 4 | // license that can be found in the LICENSE file. 5 | 6 | // +build !windows 7 | 8 | package goncurses 9 | 10 | // #include 11 | import "C" 12 | 13 | // Echo prints a single character to the pad immediately. This has the 14 | // same effect of calling AddChar() + Refresh() but has a significant 15 | // speed advantage 16 | func (p *Pad) Echo(ch int) { 17 | C.pechochar(p.win, C.chtype(ch)) 18 | } 19 | -------------------------------------------------------------------------------- /panel.go: -------------------------------------------------------------------------------- 1 | // Copyright 2011 Rob Thornton. All rights reserved. 2 | // Use of this source code is governed by a BSD-style 3 | // license that can be found in the LICENSE file. 4 | 5 | package goncurses 6 | 7 | // #cgo !darwin,!openbsd,!windows pkg-config: panel 8 | // #cgo darwin openbsd LDFLAGS: -lpanel 9 | // #include 10 | // #include 11 | import "C" 12 | 13 | import "errors" 14 | 15 | type Panel struct { 16 | pan *C.PANEL 17 | } 18 | 19 | // Panel creates a new panel derived from the window, adding it to the 20 | // panel stack. The pointer to the original window can still be used to 21 | // execute most window functions with the exception of Refresh(). Always 22 | // use panel's Refresh() function. 23 | func NewPanel(w *Window) *Panel { 24 | return &Panel{C.new_panel(w.win)} 25 | } 26 | 27 | // UpdatePanels refreshes the panel stack. It must be called prior to 28 | // using ncurses's DoUpdate() 29 | func UpdatePanels() { 30 | C.update_panels() 31 | return 32 | } 33 | 34 | // Returns a pointer to the panel above in the stack or nil. Passing nil will 35 | // return the top panel in the stack 36 | func (p *Panel) Above() *Panel { 37 | return &Panel{C.panel_above(p.pan)} 38 | } 39 | 40 | // Returns a pointer to the panel below in the stack or nil. Passing nil will 41 | // return the bottom panel in the stack 42 | func Below(p *Panel) *Panel { 43 | return &Panel{C.panel_above(p.pan)} 44 | } 45 | 46 | // Move the panel to the bottom of the stack. 47 | func (p *Panel) Bottom() error { 48 | if C.bottom_panel(p.pan) == C.ERR { 49 | return errors.New("Failed to move panel to bottom of stack") 50 | } 51 | return nil 52 | } 53 | 54 | // Delete panel, removing from the stack. 55 | func (p *Panel) Delete() error { 56 | if C.del_panel(p.pan) == C.ERR { 57 | return errors.New("Failed to delete panel") 58 | } 59 | p = nil 60 | return nil 61 | } 62 | 63 | // Hidden returns true if panel is visible, false if not 64 | func (p *Panel) Hidden() bool { 65 | return C.panel_hidden(p.pan) == C.TRUE 66 | } 67 | 68 | // Hide the panel 69 | func (p *Panel) Hide() error { 70 | if C.hide_panel(p.pan) == C.ERR { 71 | return errors.New("Failed to hide panel") 72 | } 73 | return nil 74 | } 75 | 76 | // Move the panel to the specified location. It is important to never use 77 | // ncurses movement functions on the window governed by panel. Always use 78 | // this function 79 | func (p *Panel) Move(y, x int) error { 80 | if C.move_panel(p.pan, C.int(y), C.int(x)) == C.ERR { 81 | return errors.New("Failed to move panel") 82 | } 83 | return nil 84 | } 85 | 86 | // Replace panel's associated window with a new one. 87 | func (p *Panel) Replace(w *Window) error { 88 | if C.replace_panel(p.pan, w.win) == C.ERR { 89 | return errors.New("Failed to replace window") 90 | } 91 | return nil 92 | } 93 | 94 | // Show the panel, if hidden, and place it on the top of the stack. 95 | func (p *Panel) Show() error { 96 | if C.show_panel(p.pan) == C.ERR { 97 | return errors.New("Failed to show panel") 98 | } 99 | return nil 100 | } 101 | 102 | // Move panel to the top of the stack 103 | func (p *Panel) Top() error { 104 | if C.top_panel(p.pan) == C.ERR { 105 | return errors.New("Failed to move panel to top of stack") 106 | } 107 | return nil 108 | } 109 | 110 | // Window returns the window governed by panel 111 | func (p *Panel) Window() *Window { 112 | return &Window{C.panel_window(p.pan)} 113 | } 114 | -------------------------------------------------------------------------------- /pdcurses/curses.h: -------------------------------------------------------------------------------- 1 | /* Public Domain Curses */ 2 | 3 | /* $Id: curses.h,v 1.295 2008/07/15 17:13:25 wmcbrine Exp $ */ 4 | 5 | /*----------------------------------------------------------------------* 6 | * PDCurses * 7 | *----------------------------------------------------------------------*/ 8 | 9 | #ifndef __PDCURSES__ 10 | #define __PDCURSES__ 1 11 | 12 | /*man-start************************************************************** 13 | 14 | PDCurses definitions list: (Only define those needed) 15 | 16 | XCURSES True if compiling for X11. 17 | PDC_RGB True if you want to use RGB color definitions 18 | (Red = 1, Green = 2, Blue = 4) instead of BGR. 19 | PDC_WIDE True if building wide-character support. 20 | PDC_DLL_BUILD True if building a Win32 DLL. 21 | NCURSES_MOUSE_VERSION Use the ncurses mouse API instead 22 | of PDCurses' traditional mouse API. 23 | 24 | PDCurses portable platform definitions list: 25 | 26 | PDC_BUILD Defines API build version. 27 | PDCURSES Enables access to PDCurses-only routines. 28 | XOPEN Always true. 29 | SYSVcurses True if you are compiling for SYSV portability. 30 | BSDcurses True if you are compiling for BSD portability. 31 | 32 | **man-end****************************************************************/ 33 | 34 | #define PDC_BUILD 3401 35 | #define PDCURSES 1 /* PDCurses-only routines */ 36 | #define XOPEN 1 /* X/Open Curses routines */ 37 | #define SYSVcurses 1 /* System V Curses routines */ 38 | #define BSDcurses 1 /* BSD Curses routines */ 39 | #define CHTYPE_LONG 1 /* size of chtype; long */ 40 | 41 | /*----------------------------------------------------------------------*/ 42 | 43 | #include 44 | #include 45 | #include /* Required by X/Open usage below */ 46 | 47 | #ifdef PDC_WIDE 48 | # include 49 | #endif 50 | 51 | #if defined(__cplusplus) || defined(__cplusplus__) || defined(__CPLUSPLUS) 52 | extern "C" 53 | { 54 | # define bool _bool 55 | #endif 56 | 57 | /*---------------------------------------------------------------------- 58 | * 59 | * PDCurses Manifest Constants 60 | * 61 | */ 62 | 63 | #ifndef FALSE 64 | # define FALSE 0 65 | #endif 66 | #ifndef TRUE 67 | # define TRUE 1 68 | #endif 69 | #ifndef NULL 70 | # define NULL (void *)0 71 | #endif 72 | #ifndef ERR 73 | # define ERR (-1) 74 | #endif 75 | #ifndef OK 76 | # define OK 0 77 | #endif 78 | 79 | /*---------------------------------------------------------------------- 80 | * 81 | * PDCurses Type Declarations 82 | * 83 | */ 84 | 85 | //typedef unsigned char bool; /* PDCurses Boolean type */ 86 | #include 87 | 88 | #ifdef CHTYPE_LONG 89 | # if _LP64 90 | typedef unsigned int chtype; 91 | # else 92 | typedef unsigned long chtype; /* 16-bit attr + 16-bit char */ 93 | # endif 94 | #else 95 | typedef unsigned short chtype; /* 8-bit attr + 8-bit char */ 96 | #endif 97 | 98 | #ifdef PDC_WIDE 99 | typedef chtype cchar_t; 100 | #endif 101 | 102 | typedef chtype attr_t; 103 | 104 | /*---------------------------------------------------------------------- 105 | * 106 | * PDCurses Mouse Interface -- SYSVR4, with extensions 107 | * 108 | */ 109 | 110 | typedef struct 111 | { 112 | int x; /* absolute column, 0 based, measured in characters */ 113 | int y; /* absolute row, 0 based, measured in characters */ 114 | short button[3]; /* state of each button */ 115 | int changes; /* flags indicating what has changed with the mouse */ 116 | } MOUSE_STATUS; 117 | 118 | #define BUTTON_RELEASED 0x0000 119 | #define BUTTON_PRESSED 0x0001 120 | #define BUTTON_CLICKED 0x0002 121 | #define BUTTON_DOUBLE_CLICKED 0x0003 122 | #define BUTTON_TRIPLE_CLICKED 0x0004 123 | #define BUTTON_MOVED 0x0005 /* PDCurses */ 124 | #define WHEEL_SCROLLED 0x0006 /* PDCurses */ 125 | #define BUTTON_ACTION_MASK 0x0007 /* PDCurses */ 126 | 127 | #define PDC_BUTTON_SHIFT 0x0008 /* PDCurses */ 128 | #define PDC_BUTTON_CONTROL 0x0010 /* PDCurses */ 129 | #define PDC_BUTTON_ALT 0x0020 /* PDCurses */ 130 | #define BUTTON_MODIFIER_MASK 0x0038 /* PDCurses */ 131 | 132 | #define MOUSE_X_POS (Mouse_status.x) 133 | #define MOUSE_Y_POS (Mouse_status.y) 134 | 135 | /* 136 | * Bits associated with the .changes field: 137 | * 3 2 1 0 138 | * 210987654321098765432109876543210 139 | * 1 <- button 1 has changed 140 | * 10 <- button 2 has changed 141 | * 100 <- button 3 has changed 142 | * 1000 <- mouse has moved 143 | * 10000 <- mouse position report 144 | * 100000 <- mouse wheel up 145 | * 1000000 <- mouse wheel down 146 | */ 147 | 148 | #define PDC_MOUSE_MOVED 0x0008 149 | #define PDC_MOUSE_POSITION 0x0010 150 | #define PDC_MOUSE_WHEEL_UP 0x0020 151 | #define PDC_MOUSE_WHEEL_DOWN 0x0040 152 | 153 | #define A_BUTTON_CHANGED (Mouse_status.changes & 7) 154 | #define MOUSE_MOVED (Mouse_status.changes & PDC_MOUSE_MOVED) 155 | #define MOUSE_POS_REPORT (Mouse_status.changes & PDC_MOUSE_POSITION) 156 | #define BUTTON_CHANGED(x) (Mouse_status.changes & (1 << ((x) - 1))) 157 | #define BUTTON_STATUS(x) (Mouse_status.button[(x) - 1]) 158 | #define MOUSE_WHEEL_UP (Mouse_status.changes & PDC_MOUSE_WHEEL_UP) 159 | #define MOUSE_WHEEL_DOWN (Mouse_status.changes & PDC_MOUSE_WHEEL_DOWN) 160 | 161 | /* mouse bit-masks */ 162 | 163 | #define BUTTON1_RELEASED 0x00000001L 164 | #define BUTTON1_PRESSED 0x00000002L 165 | #define BUTTON1_CLICKED 0x00000004L 166 | #define BUTTON1_DOUBLE_CLICKED 0x00000008L 167 | #define BUTTON1_TRIPLE_CLICKED 0x00000010L 168 | #define BUTTON1_MOVED 0x00000010L /* PDCurses */ 169 | 170 | #define BUTTON2_RELEASED 0x00000020L 171 | #define BUTTON2_PRESSED 0x00000040L 172 | #define BUTTON2_CLICKED 0x00000080L 173 | #define BUTTON2_DOUBLE_CLICKED 0x00000100L 174 | #define BUTTON2_TRIPLE_CLICKED 0x00000200L 175 | #define BUTTON2_MOVED 0x00000200L /* PDCurses */ 176 | 177 | #define BUTTON3_RELEASED 0x00000400L 178 | #define BUTTON3_PRESSED 0x00000800L 179 | #define BUTTON3_CLICKED 0x00001000L 180 | #define BUTTON3_DOUBLE_CLICKED 0x00002000L 181 | #define BUTTON3_TRIPLE_CLICKED 0x00004000L 182 | #define BUTTON3_MOVED 0x00004000L /* PDCurses */ 183 | 184 | /* For the ncurses-compatible functions only, BUTTON4_PRESSED and 185 | BUTTON5_PRESSED are returned for mouse scroll wheel up and down; 186 | otherwise PDCurses doesn't support buttons 4 and 5 */ 187 | 188 | #define BUTTON4_RELEASED 0x00008000L 189 | #define BUTTON4_PRESSED 0x00010000L 190 | #define BUTTON4_CLICKED 0x00020000L 191 | #define BUTTON4_DOUBLE_CLICKED 0x00040000L 192 | #define BUTTON4_TRIPLE_CLICKED 0x00080000L 193 | 194 | #define BUTTON5_RELEASED 0x00100000L 195 | #define BUTTON5_PRESSED 0x00200000L 196 | #define BUTTON5_CLICKED 0x00400000L 197 | #define BUTTON5_DOUBLE_CLICKED 0x00800000L 198 | #define BUTTON5_TRIPLE_CLICKED 0x01000000L 199 | 200 | #define MOUSE_WHEEL_SCROLL 0x02000000L /* PDCurses */ 201 | #define BUTTON_MODIFIER_SHIFT 0x04000000L /* PDCurses */ 202 | #define BUTTON_MODIFIER_CONTROL 0x08000000L /* PDCurses */ 203 | #define BUTTON_MODIFIER_ALT 0x10000000L /* PDCurses */ 204 | 205 | #define ALL_MOUSE_EVENTS 0x1fffffffL 206 | #define REPORT_MOUSE_POSITION 0x20000000L 207 | 208 | /* ncurses mouse interface */ 209 | 210 | typedef unsigned long mmask_t; 211 | 212 | typedef struct 213 | { 214 | short id; /* unused, always 0 */ 215 | int x, y, z; /* x, y same as MOUSE_STATUS; z unused */ 216 | mmask_t bstate; /* equivalent to changes + button[], but 217 | in the same format as used for mousemask() */ 218 | } MEVENT; 219 | 220 | #ifdef NCURSES_MOUSE_VERSION 221 | # define BUTTON_SHIFT BUTTON_MODIFIER_SHIFT 222 | # define BUTTON_CONTROL BUTTON_MODIFIER_CONTROL 223 | # define BUTTON_CTRL BUTTON_MODIFIER_CONTROL 224 | # define BUTTON_ALT BUTTON_MODIFIER_ALT 225 | #else 226 | # define BUTTON_SHIFT PDC_BUTTON_SHIFT 227 | # define BUTTON_CONTROL PDC_BUTTON_CONTROL 228 | # define BUTTON_ALT PDC_BUTTON_ALT 229 | #endif 230 | 231 | /*---------------------------------------------------------------------- 232 | * 233 | * PDCurses Structure Definitions 234 | * 235 | */ 236 | 237 | typedef struct _win /* definition of a window */ 238 | { 239 | int _cury; /* current pseudo-cursor */ 240 | int _curx; 241 | int _maxy; /* max window coordinates */ 242 | int _maxx; 243 | int _begy; /* origin on screen */ 244 | int _begx; 245 | int _flags; /* window properties */ 246 | chtype _attrs; /* standard attributes and colors */ 247 | chtype _bkgd; /* background, normally blank */ 248 | bool _clear; /* causes clear at next refresh */ 249 | bool _leaveit; /* leaves cursor where it is */ 250 | bool _scroll; /* allows window scrolling */ 251 | bool _nodelay; /* input character wait flag */ 252 | bool _immed; /* immediate update flag */ 253 | bool _sync; /* synchronise window ancestors */ 254 | bool _use_keypad; /* flags keypad key mode active */ 255 | chtype **_y; /* pointer to line pointer array */ 256 | int *_firstch; /* first changed character in line */ 257 | int *_lastch; /* last changed character in line */ 258 | int _tmarg; /* top of scrolling region */ 259 | int _bmarg; /* bottom of scrolling region */ 260 | int _delayms; /* milliseconds of delay for getch() */ 261 | int _parx, _pary; /* coords relative to parent (0,0) */ 262 | struct _win *_parent; /* subwin's pointer to parent win */ 263 | } WINDOW; 264 | 265 | /* Avoid using the SCREEN struct directly -- use the corresponding 266 | functions if possible. This struct may eventually be made private. */ 267 | 268 | typedef struct 269 | { 270 | bool alive; /* if initscr() called, and not endwin() */ 271 | bool autocr; /* if cr -> lf */ 272 | bool cbreak; /* if terminal unbuffered */ 273 | bool echo; /* if terminal echo */ 274 | bool raw_inp; /* raw input mode (v. cooked input) */ 275 | bool raw_out; /* raw output mode (7 v. 8 bits) */ 276 | bool audible; /* FALSE if the bell is visual */ 277 | bool mono; /* TRUE if current screen is mono */ 278 | bool resized; /* TRUE if TERM has been resized */ 279 | bool orig_attr; /* TRUE if we have the original colors */ 280 | short orig_fore; /* original screen foreground color */ 281 | short orig_back; /* original screen foreground color */ 282 | int cursrow; /* position of physical cursor */ 283 | int curscol; /* position of physical cursor */ 284 | int visibility; /* visibility of cursor */ 285 | int orig_cursor; /* original cursor size */ 286 | int lines; /* new value for LINES */ 287 | int cols; /* new value for COLS */ 288 | unsigned long _trap_mbe; /* trap these mouse button events */ 289 | unsigned long _map_mbe_to_key; /* map mouse buttons to slk */ 290 | int mouse_wait; /* time to wait (in ms) for a 291 | button release after a press, in 292 | order to count it as a click */ 293 | int slklines; /* lines in use by slk_init() */ 294 | WINDOW *slk_winptr; /* window for slk */ 295 | int linesrippedoff; /* lines ripped off via ripoffline() */ 296 | int linesrippedoffontop; /* lines ripped off on 297 | top via ripoffline() */ 298 | int delaytenths; /* 1/10ths second to wait block 299 | getch() for */ 300 | bool _preserve; /* TRUE if screen background 301 | to be preserved */ 302 | int _restore; /* specifies if screen background 303 | to be restored, and how */ 304 | bool save_key_modifiers; /* TRUE if each key modifiers saved 305 | with each key press */ 306 | bool return_key_modifiers; /* TRUE if modifier keys are 307 | returned as "real" keys */ 308 | bool key_code; /* TRUE if last key is a special key; 309 | used internally by get_wch() */ 310 | #ifdef XCURSES 311 | int XcurscrSize; /* size of Xcurscr shared memory block */ 312 | bool sb_on; 313 | int sb_viewport_y; 314 | int sb_viewport_x; 315 | int sb_total_y; 316 | int sb_total_x; 317 | int sb_cur_y; 318 | int sb_cur_x; 319 | #endif 320 | short line_color; /* color of line attributes - default -1 */ 321 | } SCREEN; 322 | 323 | /*---------------------------------------------------------------------- 324 | * 325 | * PDCurses External Variables 326 | * 327 | */ 328 | 329 | #ifdef PDC_DLL_BUILD 330 | # ifdef CURSES_LIBRARY 331 | # define PDCEX __declspec(dllexport) extern 332 | # else 333 | # define PDCEX __declspec(dllimport) 334 | # endif 335 | #else 336 | # define PDCEX extern 337 | #endif 338 | 339 | PDCEX int LINES; /* terminal height */ 340 | PDCEX int COLS; /* terminal width */ 341 | PDCEX WINDOW *stdscr; /* the default screen window */ 342 | PDCEX WINDOW *curscr; /* the current screen image */ 343 | PDCEX SCREEN *SP; /* curses variables */ 344 | PDCEX MOUSE_STATUS Mouse_status; 345 | PDCEX int COLORS; 346 | PDCEX int COLOR_PAIRS; 347 | PDCEX int TABSIZE; 348 | PDCEX chtype acs_map[]; /* alternate character set map */ 349 | PDCEX char ttytype[]; /* terminal name/description */ 350 | 351 | /*man-start************************************************************** 352 | 353 | PDCurses Text Attributes 354 | ======================== 355 | 356 | Originally, PDCurses used a short (16 bits) for its chtype. To include 357 | color, a number of things had to be sacrificed from the strict Unix and 358 | System V support. The main problem was fitting all character attributes 359 | and color into an unsigned char (all 8 bits!). 360 | 361 | Today, PDCurses by default uses a long (32 bits) for its chtype, as in 362 | System V. The short chtype is still available, by undefining CHTYPE_LONG 363 | and rebuilding the library. 364 | 365 | The following is the structure of a win->_attrs chtype: 366 | 367 | short form: 368 | 369 | ------------------------------------------------- 370 | |15|14|13|12|11|10| 9| 8| 7| 6| 5| 4| 3| 2| 1| 0| 371 | ------------------------------------------------- 372 | color number | attrs | character eg 'a' 373 | 374 | The available non-color attributes are bold, reverse and blink. Others 375 | have no effect. The high order char is an index into an array of 376 | physical colors (defined in color.c) -- 32 foreground/background color 377 | pairs (5 bits) plus 3 bits for other attributes. 378 | 379 | long form: 380 | 381 | ---------------------------------------------------------------------------- 382 | |31|30|29|28|27|26|25|24|23|22|21|20|19|18|17|16|15|14|13|12|..| 3| 2| 1| 0| 383 | ---------------------------------------------------------------------------- 384 | color number | modifiers | character eg 'a' 385 | 386 | The available non-color attributes are bold, underline, invisible, 387 | right-line, left-line, protect, reverse and blink. 256 color pairs (8 388 | bits), 8 bits for other attributes, and 16 bits for character data. 389 | 390 | **man-end****************************************************************/ 391 | 392 | /*** Video attribute macros ***/ 393 | 394 | #define A_NORMAL (chtype)0 395 | 396 | #ifdef CHTYPE_LONG 397 | # define A_ALTCHARSET (chtype)0x00010000 398 | # define A_RIGHTLINE (chtype)0x00020000 399 | # define A_LEFTLINE (chtype)0x00040000 400 | # define A_INVIS (chtype)0x00080000 401 | # define A_UNDERLINE (chtype)0x00100000 402 | # define A_REVERSE (chtype)0x00200000 403 | # define A_BLINK (chtype)0x00400000 404 | # define A_BOLD (chtype)0x00800000 405 | 406 | # define A_ATTRIBUTES (chtype)0xffff0000 407 | # define A_CHARTEXT (chtype)0x0000ffff 408 | # define A_COLOR (chtype)0xff000000 409 | 410 | # define A_ITALIC A_INVIS 411 | # define A_PROTECT (A_UNDERLINE | A_LEFTLINE | A_RIGHTLINE) 412 | 413 | # define PDC_ATTR_SHIFT 19 414 | # define PDC_COLOR_SHIFT 24 415 | #else 416 | # define A_BOLD (chtype)0x0100 /* X/Open */ 417 | # define A_REVERSE (chtype)0x0200 /* X/Open */ 418 | # define A_BLINK (chtype)0x0400 /* X/Open */ 419 | 420 | # define A_ATTRIBUTES (chtype)0xff00 /* X/Open */ 421 | # define A_CHARTEXT (chtype)0x00ff /* X/Open */ 422 | # define A_COLOR (chtype)0xf800 /* System V */ 423 | 424 | # define A_ALTCHARSET A_NORMAL /* X/Open */ 425 | # define A_PROTECT A_NORMAL /* X/Open */ 426 | # define A_UNDERLINE A_NORMAL /* X/Open */ 427 | 428 | # define A_LEFTLINE A_NORMAL 429 | # define A_RIGHTLINE A_NORMAL 430 | # define A_ITALIC A_NORMAL 431 | # define A_INVIS A_NORMAL 432 | 433 | # define PDC_ATTR_SHIFT 8 434 | # define PDC_COLOR_SHIFT 11 435 | #endif 436 | 437 | #define A_STANDOUT (A_REVERSE | A_BOLD) /* X/Open */ 438 | #define A_DIM A_NORMAL 439 | 440 | #define CHR_MSK A_CHARTEXT /* Obsolete */ 441 | #define ATR_MSK A_ATTRIBUTES /* Obsolete */ 442 | #define ATR_NRM A_NORMAL /* Obsolete */ 443 | 444 | /* For use with attr_t -- X/Open says, "these shall be distinct", so 445 | this is a non-conforming implementation. */ 446 | 447 | #define WA_ALTCHARSET A_ALTCHARSET 448 | #define WA_BLINK A_BLINK 449 | #define WA_BOLD A_BOLD 450 | #define WA_DIM A_DIM 451 | #define WA_INVIS A_INVIS 452 | #define WA_LEFT A_LEFTLINE 453 | #define WA_PROTECT A_PROTECT 454 | #define WA_REVERSE A_REVERSE 455 | #define WA_RIGHT A_RIGHTLINE 456 | #define WA_STANDOUT A_STANDOUT 457 | #define WA_UNDERLINE A_UNDERLINE 458 | 459 | #define WA_HORIZONTAL A_NORMAL 460 | #define WA_LOW A_NORMAL 461 | #define WA_TOP A_NORMAL 462 | #define WA_VERTICAL A_NORMAL 463 | 464 | /*** Alternate character set macros ***/ 465 | 466 | /* 'w' = 32-bit chtype; acs_map[] index | A_ALTCHARSET 467 | 'n' = 16-bit chtype; it gets the fallback set because no bit is 468 | available for A_ALTCHARSET */ 469 | 470 | #ifdef CHTYPE_LONG 471 | # define ACS_PICK(w, n) ((chtype)w | A_ALTCHARSET) 472 | #else 473 | # define ACS_PICK(w, n) ((chtype)n) 474 | #endif 475 | 476 | /* VT100-compatible symbols -- box chars */ 477 | 478 | #define ACS_ULCORNER ACS_PICK('l', '+') 479 | #define ACS_LLCORNER ACS_PICK('m', '+') 480 | #define ACS_URCORNER ACS_PICK('k', '+') 481 | #define ACS_LRCORNER ACS_PICK('j', '+') 482 | #define ACS_RTEE ACS_PICK('u', '+') 483 | #define ACS_LTEE ACS_PICK('t', '+') 484 | #define ACS_BTEE ACS_PICK('v', '+') 485 | #define ACS_TTEE ACS_PICK('w', '+') 486 | #define ACS_HLINE ACS_PICK('q', '-') 487 | #define ACS_VLINE ACS_PICK('x', '|') 488 | #define ACS_PLUS ACS_PICK('n', '+') 489 | 490 | /* VT100-compatible symbols -- other */ 491 | 492 | #define ACS_S1 ACS_PICK('o', '-') 493 | #define ACS_S9 ACS_PICK('s', '_') 494 | #define ACS_DIAMOND ACS_PICK('`', '+') 495 | #define ACS_CKBOARD ACS_PICK('a', ':') 496 | #define ACS_DEGREE ACS_PICK('f', '\'') 497 | #define ACS_PLMINUS ACS_PICK('g', '#') 498 | #define ACS_BULLET ACS_PICK('~', 'o') 499 | 500 | /* Teletype 5410v1 symbols -- these are defined in SysV curses, but 501 | are not well-supported by most terminals. Stick to VT100 characters 502 | for optimum portability. */ 503 | 504 | #define ACS_LARROW ACS_PICK(',', '<') 505 | #define ACS_RARROW ACS_PICK('+', '>') 506 | #define ACS_DARROW ACS_PICK('.', 'v') 507 | #define ACS_UARROW ACS_PICK('-', '^') 508 | #define ACS_BOARD ACS_PICK('h', '#') 509 | #define ACS_LANTERN ACS_PICK('i', '*') 510 | #define ACS_BLOCK ACS_PICK('0', '#') 511 | 512 | /* That goes double for these -- undocumented SysV symbols. Don't use 513 | them. */ 514 | 515 | #define ACS_S3 ACS_PICK('p', '-') 516 | #define ACS_S7 ACS_PICK('r', '-') 517 | #define ACS_LEQUAL ACS_PICK('y', '<') 518 | #define ACS_GEQUAL ACS_PICK('z', '>') 519 | #define ACS_PI ACS_PICK('{', 'n') 520 | #define ACS_NEQUAL ACS_PICK('|', '+') 521 | #define ACS_STERLING ACS_PICK('}', 'L') 522 | 523 | /* Box char aliases */ 524 | 525 | #define ACS_BSSB ACS_ULCORNER 526 | #define ACS_SSBB ACS_LLCORNER 527 | #define ACS_BBSS ACS_URCORNER 528 | #define ACS_SBBS ACS_LRCORNER 529 | #define ACS_SBSS ACS_RTEE 530 | #define ACS_SSSB ACS_LTEE 531 | #define ACS_SSBS ACS_BTEE 532 | #define ACS_BSSS ACS_TTEE 533 | #define ACS_BSBS ACS_HLINE 534 | #define ACS_SBSB ACS_VLINE 535 | #define ACS_SSSS ACS_PLUS 536 | 537 | /* cchar_t aliases */ 538 | 539 | #ifdef PDC_WIDE 540 | # define WACS_ULCORNER (&(acs_map['l'])) 541 | # define WACS_LLCORNER (&(acs_map['m'])) 542 | # define WACS_URCORNER (&(acs_map['k'])) 543 | # define WACS_LRCORNER (&(acs_map['j'])) 544 | # define WACS_RTEE (&(acs_map['u'])) 545 | # define WACS_LTEE (&(acs_map['t'])) 546 | # define WACS_BTEE (&(acs_map['v'])) 547 | # define WACS_TTEE (&(acs_map['w'])) 548 | # define WACS_HLINE (&(acs_map['q'])) 549 | # define WACS_VLINE (&(acs_map['x'])) 550 | # define WACS_PLUS (&(acs_map['n'])) 551 | 552 | # define WACS_S1 (&(acs_map['o'])) 553 | # define WACS_S9 (&(acs_map['s'])) 554 | # define WACS_DIAMOND (&(acs_map['`'])) 555 | # define WACS_CKBOARD (&(acs_map['a'])) 556 | # define WACS_DEGREE (&(acs_map['f'])) 557 | # define WACS_PLMINUS (&(acs_map['g'])) 558 | # define WACS_BULLET (&(acs_map['~'])) 559 | 560 | # define WACS_LARROW (&(acs_map[','])) 561 | # define WACS_RARROW (&(acs_map['+'])) 562 | # define WACS_DARROW (&(acs_map['.'])) 563 | # define WACS_UARROW (&(acs_map['-'])) 564 | # define WACS_BOARD (&(acs_map['h'])) 565 | # define WACS_LANTERN (&(acs_map['i'])) 566 | # define WACS_BLOCK (&(acs_map['0'])) 567 | 568 | # define WACS_S3 (&(acs_map['p'])) 569 | # define WACS_S7 (&(acs_map['r'])) 570 | # define WACS_LEQUAL (&(acs_map['y'])) 571 | # define WACS_GEQUAL (&(acs_map['z'])) 572 | # define WACS_PI (&(acs_map['{'])) 573 | # define WACS_NEQUAL (&(acs_map['|'])) 574 | # define WACS_STERLING (&(acs_map['}'])) 575 | 576 | # define WACS_BSSB WACS_ULCORNER 577 | # define WACS_SSBB WACS_LLCORNER 578 | # define WACS_BBSS WACS_URCORNER 579 | # define WACS_SBBS WACS_LRCORNER 580 | # define WACS_SBSS WACS_RTEE 581 | # define WACS_SSSB WACS_LTEE 582 | # define WACS_SSBS WACS_BTEE 583 | # define WACS_BSSS WACS_TTEE 584 | # define WACS_BSBS WACS_HLINE 585 | # define WACS_SBSB WACS_VLINE 586 | # define WACS_SSSS WACS_PLUS 587 | #endif 588 | 589 | /*** Color macros ***/ 590 | 591 | #define COLOR_BLACK 0 592 | 593 | #ifdef PDC_RGB /* RGB */ 594 | # define COLOR_RED 1 595 | # define COLOR_GREEN 2 596 | # define COLOR_BLUE 4 597 | #else /* BGR */ 598 | # define COLOR_BLUE 1 599 | # define COLOR_GREEN 2 600 | # define COLOR_RED 4 601 | #endif 602 | 603 | #define COLOR_CYAN (COLOR_BLUE | COLOR_GREEN) 604 | #define COLOR_MAGENTA (COLOR_RED | COLOR_BLUE) 605 | #define COLOR_YELLOW (COLOR_RED | COLOR_GREEN) 606 | 607 | #define COLOR_WHITE 7 608 | 609 | /*---------------------------------------------------------------------- 610 | * 611 | * Function and Keypad Key Definitions. 612 | * Many are just for compatibility. 613 | * 614 | */ 615 | 616 | #define KEY_CODE_YES 0x100 /* If get_wch() gives a key code */ 617 | 618 | #define KEY_BREAK 0x101 /* Not on PC KBD */ 619 | #define KEY_DOWN 0x102 /* Down arrow key */ 620 | #define KEY_UP 0x103 /* Up arrow key */ 621 | #define KEY_LEFT 0x104 /* Left arrow key */ 622 | #define KEY_RIGHT 0x105 /* Right arrow key */ 623 | #define KEY_HOME 0x106 /* home key */ 624 | #define KEY_BACKSPACE 0x107 /* not on pc */ 625 | #define KEY_F0 0x108 /* function keys; 64 reserved */ 626 | 627 | #define KEY_DL 0x148 /* delete line */ 628 | #define KEY_IL 0x149 /* insert line */ 629 | #define KEY_DC 0x14a /* delete character */ 630 | #define KEY_IC 0x14b /* insert char or enter ins mode */ 631 | #define KEY_EIC 0x14c /* exit insert char mode */ 632 | #define KEY_CLEAR 0x14d /* clear screen */ 633 | #define KEY_EOS 0x14e /* clear to end of screen */ 634 | #define KEY_EOL 0x14f /* clear to end of line */ 635 | #define KEY_SF 0x150 /* scroll 1 line forward */ 636 | #define KEY_SR 0x151 /* scroll 1 line back (reverse) */ 637 | #define KEY_NPAGE 0x152 /* next page */ 638 | #define KEY_PPAGE 0x153 /* previous page */ 639 | #define KEY_STAB 0x154 /* set tab */ 640 | #define KEY_CTAB 0x155 /* clear tab */ 641 | #define KEY_CATAB 0x156 /* clear all tabs */ 642 | #define KEY_ENTER 0x157 /* enter or send (unreliable) */ 643 | #define KEY_SRESET 0x158 /* soft/reset (partial/unreliable) */ 644 | #define KEY_RESET 0x159 /* reset/hard reset (unreliable) */ 645 | #define KEY_PRINT 0x15a /* print/copy */ 646 | #define KEY_LL 0x15b /* home down/bottom (lower left) */ 647 | #define KEY_ABORT 0x15c /* abort/terminate key (any) */ 648 | #define KEY_SHELP 0x15d /* short help */ 649 | #define KEY_LHELP 0x15e /* long help */ 650 | #define KEY_BTAB 0x15f /* Back tab key */ 651 | #define KEY_BEG 0x160 /* beg(inning) key */ 652 | #define KEY_CANCEL 0x161 /* cancel key */ 653 | #define KEY_CLOSE 0x162 /* close key */ 654 | #define KEY_COMMAND 0x163 /* cmd (command) key */ 655 | #define KEY_COPY 0x164 /* copy key */ 656 | #define KEY_CREATE 0x165 /* create key */ 657 | #define KEY_END 0x166 /* end key */ 658 | #define KEY_EXIT 0x167 /* exit key */ 659 | #define KEY_FIND 0x168 /* find key */ 660 | #define KEY_HELP 0x169 /* help key */ 661 | #define KEY_MARK 0x16a /* mark key */ 662 | #define KEY_MESSAGE 0x16b /* message key */ 663 | #define KEY_MOVE 0x16c /* move key */ 664 | #define KEY_NEXT 0x16d /* next object key */ 665 | #define KEY_OPEN 0x16e /* open key */ 666 | #define KEY_OPTIONS 0x16f /* options key */ 667 | #define KEY_PREVIOUS 0x170 /* previous object key */ 668 | #define KEY_REDO 0x171 /* redo key */ 669 | #define KEY_REFERENCE 0x172 /* ref(erence) key */ 670 | #define KEY_REFRESH 0x173 /* refresh key */ 671 | #define KEY_REPLACE 0x174 /* replace key */ 672 | #define KEY_RESTART 0x175 /* restart key */ 673 | #define KEY_RESUME 0x176 /* resume key */ 674 | #define KEY_SAVE 0x177 /* save key */ 675 | #define KEY_SBEG 0x178 /* shifted beginning key */ 676 | #define KEY_SCANCEL 0x179 /* shifted cancel key */ 677 | #define KEY_SCOMMAND 0x17a /* shifted command key */ 678 | #define KEY_SCOPY 0x17b /* shifted copy key */ 679 | #define KEY_SCREATE 0x17c /* shifted create key */ 680 | #define KEY_SDC 0x17d /* shifted delete char key */ 681 | #define KEY_SDL 0x17e /* shifted delete line key */ 682 | #define KEY_SELECT 0x17f /* select key */ 683 | #define KEY_SEND 0x180 /* shifted end key */ 684 | #define KEY_SEOL 0x181 /* shifted clear line key */ 685 | #define KEY_SEXIT 0x182 /* shifted exit key */ 686 | #define KEY_SFIND 0x183 /* shifted find key */ 687 | #define KEY_SHOME 0x184 /* shifted home key */ 688 | #define KEY_SIC 0x185 /* shifted input key */ 689 | 690 | #define KEY_SLEFT 0x187 /* shifted left arrow key */ 691 | #define KEY_SMESSAGE 0x188 /* shifted message key */ 692 | #define KEY_SMOVE 0x189 /* shifted move key */ 693 | #define KEY_SNEXT 0x18a /* shifted next key */ 694 | #define KEY_SOPTIONS 0x18b /* shifted options key */ 695 | #define KEY_SPREVIOUS 0x18c /* shifted prev key */ 696 | #define KEY_SPRINT 0x18d /* shifted print key */ 697 | #define KEY_SREDO 0x18e /* shifted redo key */ 698 | #define KEY_SREPLACE 0x18f /* shifted replace key */ 699 | #define KEY_SRIGHT 0x190 /* shifted right arrow */ 700 | #define KEY_SRSUME 0x191 /* shifted resume key */ 701 | #define KEY_SSAVE 0x192 /* shifted save key */ 702 | #define KEY_SSUSPEND 0x193 /* shifted suspend key */ 703 | #define KEY_SUNDO 0x194 /* shifted undo key */ 704 | #define KEY_SUSPEND 0x195 /* suspend key */ 705 | #define KEY_UNDO 0x196 /* undo key */ 706 | 707 | /* PDCurses-specific key definitions -- PC only */ 708 | 709 | #define ALT_0 0x197 710 | #define ALT_1 0x198 711 | #define ALT_2 0x199 712 | #define ALT_3 0x19a 713 | #define ALT_4 0x19b 714 | #define ALT_5 0x19c 715 | #define ALT_6 0x19d 716 | #define ALT_7 0x19e 717 | #define ALT_8 0x19f 718 | #define ALT_9 0x1a0 719 | #define ALT_A 0x1a1 720 | #define ALT_B 0x1a2 721 | #define ALT_C 0x1a3 722 | #define ALT_D 0x1a4 723 | #define ALT_E 0x1a5 724 | #define ALT_F 0x1a6 725 | #define ALT_G 0x1a7 726 | #define ALT_H 0x1a8 727 | #define ALT_I 0x1a9 728 | #define ALT_J 0x1aa 729 | #define ALT_K 0x1ab 730 | #define ALT_L 0x1ac 731 | #define ALT_M 0x1ad 732 | #define ALT_N 0x1ae 733 | #define ALT_O 0x1af 734 | #define ALT_P 0x1b0 735 | #define ALT_Q 0x1b1 736 | #define ALT_R 0x1b2 737 | #define ALT_S 0x1b3 738 | #define ALT_T 0x1b4 739 | #define ALT_U 0x1b5 740 | #define ALT_V 0x1b6 741 | #define ALT_W 0x1b7 742 | #define ALT_X 0x1b8 743 | #define ALT_Y 0x1b9 744 | #define ALT_Z 0x1ba 745 | 746 | #define CTL_LEFT 0x1bb /* Control-Left-Arrow */ 747 | #define CTL_RIGHT 0x1bc 748 | #define CTL_PGUP 0x1bd 749 | #define CTL_PGDN 0x1be 750 | #define CTL_HOME 0x1bf 751 | #define CTL_END 0x1c0 752 | 753 | #define KEY_A1 0x1c1 /* upper left on Virtual keypad */ 754 | #define KEY_A2 0x1c2 /* upper middle on Virt. keypad */ 755 | #define KEY_A3 0x1c3 /* upper right on Vir. keypad */ 756 | #define KEY_B1 0x1c4 /* middle left on Virt. keypad */ 757 | #define KEY_B2 0x1c5 /* center on Virt. keypad */ 758 | #define KEY_B3 0x1c6 /* middle right on Vir. keypad */ 759 | #define KEY_C1 0x1c7 /* lower left on Virt. keypad */ 760 | #define KEY_C2 0x1c8 /* lower middle on Virt. keypad */ 761 | #define KEY_C3 0x1c9 /* lower right on Vir. keypad */ 762 | 763 | #define PADSLASH 0x1ca /* slash on keypad */ 764 | #define PADENTER 0x1cb /* enter on keypad */ 765 | #define CTL_PADENTER 0x1cc /* ctl-enter on keypad */ 766 | #define ALT_PADENTER 0x1cd /* alt-enter on keypad */ 767 | #define PADSTOP 0x1ce /* stop on keypad */ 768 | #define PADSTAR 0x1cf /* star on keypad */ 769 | #define PADMINUS 0x1d0 /* minus on keypad */ 770 | #define PADPLUS 0x1d1 /* plus on keypad */ 771 | #define CTL_PADSTOP 0x1d2 /* ctl-stop on keypad */ 772 | #define CTL_PADCENTER 0x1d3 /* ctl-enter on keypad */ 773 | #define CTL_PADPLUS 0x1d4 /* ctl-plus on keypad */ 774 | #define CTL_PADMINUS 0x1d5 /* ctl-minus on keypad */ 775 | #define CTL_PADSLASH 0x1d6 /* ctl-slash on keypad */ 776 | #define CTL_PADSTAR 0x1d7 /* ctl-star on keypad */ 777 | #define ALT_PADPLUS 0x1d8 /* alt-plus on keypad */ 778 | #define ALT_PADMINUS 0x1d9 /* alt-minus on keypad */ 779 | #define ALT_PADSLASH 0x1da /* alt-slash on keypad */ 780 | #define ALT_PADSTAR 0x1db /* alt-star on keypad */ 781 | #define ALT_PADSTOP 0x1dc /* alt-stop on keypad */ 782 | #define CTL_INS 0x1dd /* ctl-insert */ 783 | #define ALT_DEL 0x1de /* alt-delete */ 784 | #define ALT_INS 0x1df /* alt-insert */ 785 | #define CTL_UP 0x1e0 /* ctl-up arrow */ 786 | #define CTL_DOWN 0x1e1 /* ctl-down arrow */ 787 | #define CTL_TAB 0x1e2 /* ctl-tab */ 788 | #define ALT_TAB 0x1e3 789 | #define ALT_MINUS 0x1e4 790 | #define ALT_EQUAL 0x1e5 791 | #define ALT_HOME 0x1e6 792 | #define ALT_PGUP 0x1e7 793 | #define ALT_PGDN 0x1e8 794 | #define ALT_END 0x1e9 795 | #define ALT_UP 0x1ea /* alt-up arrow */ 796 | #define ALT_DOWN 0x1eb /* alt-down arrow */ 797 | #define ALT_RIGHT 0x1ec /* alt-right arrow */ 798 | #define ALT_LEFT 0x1ed /* alt-left arrow */ 799 | #define ALT_ENTER 0x1ee /* alt-enter */ 800 | #define ALT_ESC 0x1ef /* alt-escape */ 801 | #define ALT_BQUOTE 0x1f0 /* alt-back quote */ 802 | #define ALT_LBRACKET 0x1f1 /* alt-left bracket */ 803 | #define ALT_RBRACKET 0x1f2 /* alt-right bracket */ 804 | #define ALT_SEMICOLON 0x1f3 /* alt-semi-colon */ 805 | #define ALT_FQUOTE 0x1f4 /* alt-forward quote */ 806 | #define ALT_COMMA 0x1f5 /* alt-comma */ 807 | #define ALT_STOP 0x1f6 /* alt-stop */ 808 | #define ALT_FSLASH 0x1f7 /* alt-forward slash */ 809 | #define ALT_BKSP 0x1f8 /* alt-backspace */ 810 | #define CTL_BKSP 0x1f9 /* ctl-backspace */ 811 | #define PAD0 0x1fa /* keypad 0 */ 812 | 813 | #define CTL_PAD0 0x1fb /* ctl-keypad 0 */ 814 | #define CTL_PAD1 0x1fc 815 | #define CTL_PAD2 0x1fd 816 | #define CTL_PAD3 0x1fe 817 | #define CTL_PAD4 0x1ff 818 | #define CTL_PAD5 0x200 819 | #define CTL_PAD6 0x201 820 | #define CTL_PAD7 0x202 821 | #define CTL_PAD8 0x203 822 | #define CTL_PAD9 0x204 823 | 824 | #define ALT_PAD0 0x205 /* alt-keypad 0 */ 825 | #define ALT_PAD1 0x206 826 | #define ALT_PAD2 0x207 827 | #define ALT_PAD3 0x208 828 | #define ALT_PAD4 0x209 829 | #define ALT_PAD5 0x20a 830 | #define ALT_PAD6 0x20b 831 | #define ALT_PAD7 0x20c 832 | #define ALT_PAD8 0x20d 833 | #define ALT_PAD9 0x20e 834 | 835 | #define CTL_DEL 0x20f /* clt-delete */ 836 | #define ALT_BSLASH 0x210 /* alt-back slash */ 837 | #define CTL_ENTER 0x211 /* ctl-enter */ 838 | 839 | #define SHF_PADENTER 0x212 /* shift-enter on keypad */ 840 | #define SHF_PADSLASH 0x213 /* shift-slash on keypad */ 841 | #define SHF_PADSTAR 0x214 /* shift-star on keypad */ 842 | #define SHF_PADPLUS 0x215 /* shift-plus on keypad */ 843 | #define SHF_PADMINUS 0x216 /* shift-minus on keypad */ 844 | #define SHF_UP 0x217 /* shift-up on keypad */ 845 | #define SHF_DOWN 0x218 /* shift-down on keypad */ 846 | #define SHF_IC 0x219 /* shift-insert on keypad */ 847 | #define SHF_DC 0x21a /* shift-delete on keypad */ 848 | 849 | #define KEY_MOUSE 0x21b /* "mouse" key */ 850 | #define KEY_SHIFT_L 0x21c /* Left-shift */ 851 | #define KEY_SHIFT_R 0x21d /* Right-shift */ 852 | #define KEY_CONTROL_L 0x21e /* Left-control */ 853 | #define KEY_CONTROL_R 0x21f /* Right-control */ 854 | #define KEY_ALT_L 0x220 /* Left-alt */ 855 | #define KEY_ALT_R 0x221 /* Right-alt */ 856 | #define KEY_RESIZE 0x222 /* Window resize */ 857 | #define KEY_SUP 0x223 /* Shifted up arrow */ 858 | #define KEY_SDOWN 0x224 /* Shifted down arrow */ 859 | 860 | #define KEY_MIN KEY_BREAK /* Minimum curses key value */ 861 | #define KEY_MAX KEY_SDOWN /* Maximum curses key */ 862 | 863 | #define KEY_F(n) (KEY_F0 + (n)) 864 | 865 | /*---------------------------------------------------------------------- 866 | * 867 | * PDCurses Function Declarations 868 | * 869 | */ 870 | 871 | /* Standard */ 872 | 873 | int addch(const chtype); 874 | int addchnstr(const chtype *, int); 875 | int addchstr(const chtype *); 876 | int addnstr(const char *, int); 877 | int addstr(const char *); 878 | int attroff(chtype); 879 | int attron(chtype); 880 | int attrset(chtype); 881 | int attr_get(attr_t *, short *, void *); 882 | int attr_off(attr_t, void *); 883 | int attr_on(attr_t, void *); 884 | int attr_set(attr_t, short, void *); 885 | int baudrate(void); 886 | int beep(void); 887 | int bkgd(chtype); 888 | void bkgdset(chtype); 889 | int border(chtype, chtype, chtype, chtype, chtype, chtype, chtype, chtype); 890 | int box(WINDOW *, chtype, chtype); 891 | bool can_change_color(void); 892 | int cbreak(void); 893 | int chgat(int, attr_t, short, const void *); 894 | int clearok(WINDOW *, bool); 895 | int clear(void); 896 | int clrtobot(void); 897 | int clrtoeol(void); 898 | int color_content(short, short *, short *, short *); 899 | int color_set(short, void *); 900 | int copywin(const WINDOW *, WINDOW *, int, int, int, int, int, int, int); 901 | int curs_set(int); 902 | int def_prog_mode(void); 903 | int def_shell_mode(void); 904 | int delay_output(int); 905 | int delch(void); 906 | int deleteln(void); 907 | void delscreen(SCREEN *); 908 | int delwin(WINDOW *); 909 | WINDOW *derwin(WINDOW *, int, int, int, int); 910 | int doupdate(void); 911 | WINDOW *dupwin(WINDOW *); 912 | int echochar(const chtype); 913 | int echo(void); 914 | int endwin(void); 915 | char erasechar(void); 916 | int erase(void); 917 | void filter(void); 918 | int flash(void); 919 | int flushinp(void); 920 | chtype getbkgd(WINDOW *); 921 | int getnstr(char *, int); 922 | int getstr(char *); 923 | WINDOW *getwin(FILE *); 924 | int halfdelay(int); 925 | bool has_colors(void); 926 | bool has_ic(void); 927 | bool has_il(void); 928 | int hline(chtype, int); 929 | void idcok(WINDOW *, bool); 930 | int idlok(WINDOW *, bool); 931 | void immedok(WINDOW *, bool); 932 | int inchnstr(chtype *, int); 933 | int inchstr(chtype *); 934 | chtype inch(void); 935 | int init_color(short, short, short, short); 936 | int init_pair(short, short, short); 937 | WINDOW *initscr(void); 938 | int innstr(char *, int); 939 | int insch(chtype); 940 | int insdelln(int); 941 | int insertln(void); 942 | int insnstr(const char *, int); 943 | int insstr(const char *); 944 | int instr(char *); 945 | int intrflush(WINDOW *, bool); 946 | bool isendwin(void); 947 | bool is_linetouched(WINDOW *, int); 948 | bool is_wintouched(WINDOW *); 949 | char *keyname(int); 950 | int keypad(WINDOW *, bool); 951 | char killchar(void); 952 | int leaveok(WINDOW *, bool); 953 | char *longname(void); 954 | int meta(WINDOW *, bool); 955 | int move(int, int); 956 | int mvaddch(int, int, const chtype); 957 | int mvaddchnstr(int, int, const chtype *, int); 958 | int mvaddchstr(int, int, const chtype *); 959 | int mvaddnstr(int, int, const char *, int); 960 | int mvaddstr(int, int, const char *); 961 | int mvchgat(int, int, int, attr_t, short, const void *); 962 | int mvcur(int, int, int, int); 963 | int mvdelch(int, int); 964 | int mvderwin(WINDOW *, int, int); 965 | int mvgetch(int, int); 966 | int mvgetnstr(int, int, char *, int); 967 | int mvgetstr(int, int, char *); 968 | int mvhline(int, int, chtype, int); 969 | chtype mvinch(int, int); 970 | int mvinchnstr(int, int, chtype *, int); 971 | int mvinchstr(int, int, chtype *); 972 | int mvinnstr(int, int, char *, int); 973 | int mvinsch(int, int, chtype); 974 | int mvinsnstr(int, int, const char *, int); 975 | int mvinsstr(int, int, const char *); 976 | int mvinstr(int, int, char *); 977 | int mvprintw(int, int, const char *, ...); 978 | int mvscanw(int, int, const char *, ...); 979 | int mvvline(int, int, chtype, int); 980 | int mvwaddchnstr(WINDOW *, int, int, const chtype *, int); 981 | int mvwaddchstr(WINDOW *, int, int, const chtype *); 982 | int mvwaddch(WINDOW *, int, int, const chtype); 983 | int mvwaddnstr(WINDOW *, int, int, const char *, int); 984 | int mvwaddstr(WINDOW *, int, int, const char *); 985 | int mvwchgat(WINDOW *, int, int, int, attr_t, short, const void *); 986 | int mvwdelch(WINDOW *, int, int); 987 | int mvwgetch(WINDOW *, int, int); 988 | int mvwgetnstr(WINDOW *, int, int, char *, int); 989 | int mvwgetstr(WINDOW *, int, int, char *); 990 | int mvwhline(WINDOW *, int, int, chtype, int); 991 | int mvwinchnstr(WINDOW *, int, int, chtype *, int); 992 | int mvwinchstr(WINDOW *, int, int, chtype *); 993 | chtype mvwinch(WINDOW *, int, int); 994 | int mvwinnstr(WINDOW *, int, int, char *, int); 995 | int mvwinsch(WINDOW *, int, int, chtype); 996 | int mvwinsnstr(WINDOW *, int, int, const char *, int); 997 | int mvwinsstr(WINDOW *, int, int, const char *); 998 | int mvwinstr(WINDOW *, int, int, char *); 999 | int mvwin(WINDOW *, int, int); 1000 | int mvwprintw(WINDOW *, int, int, const char *, ...); 1001 | int mvwscanw(WINDOW *, int, int, const char *, ...); 1002 | int mvwvline(WINDOW *, int, int, chtype, int); 1003 | int napms(int); 1004 | WINDOW *newpad(int, int); 1005 | SCREEN *newterm(const char *, FILE *, FILE *); 1006 | WINDOW *newwin(int, int, int, int); 1007 | int nl(void); 1008 | int nocbreak(void); 1009 | int nodelay(WINDOW *, bool); 1010 | int noecho(void); 1011 | int nonl(void); 1012 | void noqiflush(void); 1013 | int noraw(void); 1014 | int notimeout(WINDOW *, bool); 1015 | int overlay(const WINDOW *, WINDOW *); 1016 | int overwrite(const WINDOW *, WINDOW *); 1017 | int pair_content(short, short *, short *); 1018 | int pechochar(WINDOW *, chtype); 1019 | int pnoutrefresh(WINDOW *, int, int, int, int, int, int); 1020 | int prefresh(WINDOW *, int, int, int, int, int, int); 1021 | int printw(const char *, ...); 1022 | int putwin(WINDOW *, FILE *); 1023 | void qiflush(void); 1024 | int raw(void); 1025 | int redrawwin(WINDOW *); 1026 | int refresh(void); 1027 | int reset_prog_mode(void); 1028 | int reset_shell_mode(void); 1029 | int resetty(void); 1030 | int ripoffline(int, int (*)(WINDOW *, int)); 1031 | int savetty(void); 1032 | int scanw(const char *, ...); 1033 | int scr_dump(const char *); 1034 | int scr_init(const char *); 1035 | int scr_restore(const char *); 1036 | int scr_set(const char *); 1037 | int scrl(int); 1038 | int scroll(WINDOW *); 1039 | int scrollok(WINDOW *, bool); 1040 | SCREEN *set_term(SCREEN *); 1041 | int setscrreg(int, int); 1042 | int slk_attroff(const chtype); 1043 | int slk_attr_off(const attr_t, void *); 1044 | int slk_attron(const chtype); 1045 | int slk_attr_on(const attr_t, void *); 1046 | int slk_attrset(const chtype); 1047 | int slk_attr_set(const attr_t, short, void *); 1048 | int slk_clear(void); 1049 | int slk_color(short); 1050 | int slk_init(int); 1051 | char *slk_label(int); 1052 | int slk_noutrefresh(void); 1053 | int slk_refresh(void); 1054 | int slk_restore(void); 1055 | int slk_set(int, const char *, int); 1056 | int slk_touch(void); 1057 | int standend(void); 1058 | int standout(void); 1059 | int start_color(void); 1060 | WINDOW *subpad(WINDOW *, int, int, int, int); 1061 | WINDOW *subwin(WINDOW *, int, int, int, int); 1062 | int syncok(WINDOW *, bool); 1063 | chtype termattrs(void); 1064 | attr_t term_attrs(void); 1065 | char *termname(void); 1066 | void timeout(int); 1067 | int touchline(WINDOW *, int, int); 1068 | int touchwin(WINDOW *); 1069 | int typeahead(int); 1070 | int untouchwin(WINDOW *); 1071 | void use_env(bool); 1072 | int vidattr(chtype); 1073 | int vid_attr(attr_t, short, void *); 1074 | int vidputs(chtype, int (*)(int)); 1075 | int vid_puts(attr_t, short, void *, int (*)(int)); 1076 | int vline(chtype, int); 1077 | int vw_printw(WINDOW *, const char *, va_list); 1078 | int vwprintw(WINDOW *, const char *, va_list); 1079 | int vw_scanw(WINDOW *, const char *, va_list); 1080 | int vwscanw(WINDOW *, const char *, va_list); 1081 | int waddchnstr(WINDOW *, const chtype *, int); 1082 | int waddchstr(WINDOW *, const chtype *); 1083 | int waddch(WINDOW *, const chtype); 1084 | int waddnstr(WINDOW *, const char *, int); 1085 | int waddstr(WINDOW *, const char *); 1086 | int wattroff(WINDOW *, chtype); 1087 | int wattron(WINDOW *, chtype); 1088 | int wattrset(WINDOW *, chtype); 1089 | int wattr_get(WINDOW *, attr_t *, short *, void *); 1090 | int wattr_off(WINDOW *, attr_t, void *); 1091 | int wattr_on(WINDOW *, attr_t, void *); 1092 | int wattr_set(WINDOW *, attr_t, short, void *); 1093 | void wbkgdset(WINDOW *, chtype); 1094 | int wbkgd(WINDOW *, chtype); 1095 | int wborder(WINDOW *, chtype, chtype, chtype, chtype, 1096 | chtype, chtype, chtype, chtype); 1097 | int wchgat(WINDOW *, int, attr_t, short, const void *); 1098 | int wclear(WINDOW *); 1099 | int wclrtobot(WINDOW *); 1100 | int wclrtoeol(WINDOW *); 1101 | int wcolor_set(WINDOW *, short, void *); 1102 | void wcursyncup(WINDOW *); 1103 | int wdelch(WINDOW *); 1104 | int wdeleteln(WINDOW *); 1105 | int wechochar(WINDOW *, const chtype); 1106 | int werase(WINDOW *); 1107 | int wgetch(WINDOW *); 1108 | int wgetnstr(WINDOW *, char *, int); 1109 | int wgetstr(WINDOW *, char *); 1110 | int whline(WINDOW *, chtype, int); 1111 | int winchnstr(WINDOW *, chtype *, int); 1112 | int winchstr(WINDOW *, chtype *); 1113 | chtype winch(WINDOW *); 1114 | int winnstr(WINDOW *, char *, int); 1115 | int winsch(WINDOW *, chtype); 1116 | int winsdelln(WINDOW *, int); 1117 | int winsertln(WINDOW *); 1118 | int winsnstr(WINDOW *, const char *, int); 1119 | int winsstr(WINDOW *, const char *); 1120 | int winstr(WINDOW *, char *); 1121 | int wmove(WINDOW *, int, int); 1122 | int wnoutrefresh(WINDOW *); 1123 | int wprintw(WINDOW *, const char *, ...); 1124 | int wredrawln(WINDOW *, int, int); 1125 | int wrefresh(WINDOW *); 1126 | int wscanw(WINDOW *, const char *, ...); 1127 | int wscrl(WINDOW *, int); 1128 | int wsetscrreg(WINDOW *, int, int); 1129 | int wstandend(WINDOW *); 1130 | int wstandout(WINDOW *); 1131 | void wsyncdown(WINDOW *); 1132 | void wsyncup(WINDOW *); 1133 | void wtimeout(WINDOW *, int); 1134 | int wtouchln(WINDOW *, int, int, int); 1135 | int wvline(WINDOW *, chtype, int); 1136 | 1137 | /* Wide-character functions */ 1138 | 1139 | #ifdef PDC_WIDE 1140 | int addnwstr(const wchar_t *, int); 1141 | int addwstr(const wchar_t *); 1142 | int add_wch(const cchar_t *); 1143 | int add_wchnstr(const cchar_t *, int); 1144 | int add_wchstr(const cchar_t *); 1145 | int border_set(const cchar_t *, const cchar_t *, const cchar_t *, 1146 | const cchar_t *, const cchar_t *, const cchar_t *, 1147 | const cchar_t *, const cchar_t *); 1148 | int box_set(WINDOW *, const cchar_t *, const cchar_t *); 1149 | int echo_wchar(const cchar_t *); 1150 | int erasewchar(wchar_t *); 1151 | int getbkgrnd(cchar_t *); 1152 | int getcchar(const cchar_t *, wchar_t *, attr_t *, short *, void *); 1153 | int getn_wstr(wint_t *, int); 1154 | int get_wch(wint_t *); 1155 | int get_wstr(wint_t *); 1156 | int hline_set(const cchar_t *, int); 1157 | int innwstr(wchar_t *, int); 1158 | int ins_nwstr(const wchar_t *, int); 1159 | int ins_wch(const cchar_t *); 1160 | int ins_wstr(const wchar_t *); 1161 | int inwstr(wchar_t *); 1162 | int in_wch(cchar_t *); 1163 | int in_wchnstr(cchar_t *, int); 1164 | int in_wchstr(cchar_t *); 1165 | char *key_name(wchar_t); 1166 | int killwchar(wchar_t *); 1167 | int mvaddnwstr(int, int, const wchar_t *, int); 1168 | int mvaddwstr(int, int, const wchar_t *); 1169 | int mvadd_wch(int, int, const cchar_t *); 1170 | int mvadd_wchnstr(int, int, const cchar_t *, int); 1171 | int mvadd_wchstr(int, int, const cchar_t *); 1172 | int mvgetn_wstr(int, int, wint_t *, int); 1173 | int mvget_wch(int, int, wint_t *); 1174 | int mvget_wstr(int, int, wint_t *); 1175 | int mvhline_set(int, int, const cchar_t *, int); 1176 | int mvinnwstr(int, int, wchar_t *, int); 1177 | int mvins_nwstr(int, int, const wchar_t *, int); 1178 | int mvins_wch(int, int, const cchar_t *); 1179 | int mvins_wstr(int, int, const wchar_t *); 1180 | int mvinwstr(int, int, wchar_t *); 1181 | int mvin_wch(int, int, cchar_t *); 1182 | int mvin_wchnstr(int, int, cchar_t *, int); 1183 | int mvin_wchstr(int, int, cchar_t *); 1184 | int mvvline_set(int, int, const cchar_t *, int); 1185 | int mvwaddnwstr(WINDOW *, int, int, const wchar_t *, int); 1186 | int mvwaddwstr(WINDOW *, int, int, const wchar_t *); 1187 | int mvwadd_wch(WINDOW *, int, int, const cchar_t *); 1188 | int mvwadd_wchnstr(WINDOW *, int, int, const cchar_t *, int); 1189 | int mvwadd_wchstr(WINDOW *, int, int, const cchar_t *); 1190 | int mvwgetn_wstr(WINDOW *, int, int, wint_t *, int); 1191 | int mvwget_wch(WINDOW *, int, int, wint_t *); 1192 | int mvwget_wstr(WINDOW *, int, int, wint_t *); 1193 | int mvwhline_set(WINDOW *, int, int, const cchar_t *, int); 1194 | int mvwinnwstr(WINDOW *, int, int, wchar_t *, int); 1195 | int mvwins_nwstr(WINDOW *, int, int, const wchar_t *, int); 1196 | int mvwins_wch(WINDOW *, int, int, const cchar_t *); 1197 | int mvwins_wstr(WINDOW *, int, int, const wchar_t *); 1198 | int mvwin_wch(WINDOW *, int, int, cchar_t *); 1199 | int mvwin_wchnstr(WINDOW *, int, int, cchar_t *, int); 1200 | int mvwin_wchstr(WINDOW *, int, int, cchar_t *); 1201 | int mvwinwstr(WINDOW *, int, int, wchar_t *); 1202 | int mvwvline_set(WINDOW *, int, int, const cchar_t *, int); 1203 | int pecho_wchar(WINDOW *, const cchar_t*); 1204 | int setcchar(cchar_t*, const wchar_t*, const attr_t, short, const void*); 1205 | int slk_wset(int, const wchar_t *, int); 1206 | int unget_wch(const wchar_t); 1207 | int vline_set(const cchar_t *, int); 1208 | int waddnwstr(WINDOW *, const wchar_t *, int); 1209 | int waddwstr(WINDOW *, const wchar_t *); 1210 | int wadd_wch(WINDOW *, const cchar_t *); 1211 | int wadd_wchnstr(WINDOW *, const cchar_t *, int); 1212 | int wadd_wchstr(WINDOW *, const cchar_t *); 1213 | int wbkgrnd(WINDOW *, const cchar_t *); 1214 | void wbkgrndset(WINDOW *, const cchar_t *); 1215 | int wborder_set(WINDOW *, const cchar_t *, const cchar_t *, 1216 | const cchar_t *, const cchar_t *, const cchar_t *, 1217 | const cchar_t *, const cchar_t *, const cchar_t *); 1218 | int wecho_wchar(WINDOW *, const cchar_t *); 1219 | int wgetbkgrnd(WINDOW *, cchar_t *); 1220 | int wgetn_wstr(WINDOW *, wint_t *, int); 1221 | int wget_wch(WINDOW *, wint_t *); 1222 | int wget_wstr(WINDOW *, wint_t *); 1223 | int whline_set(WINDOW *, const cchar_t *, int); 1224 | int winnwstr(WINDOW *, wchar_t *, int); 1225 | int wins_nwstr(WINDOW *, const wchar_t *, int); 1226 | int wins_wch(WINDOW *, const cchar_t *); 1227 | int wins_wstr(WINDOW *, const wchar_t *); 1228 | int winwstr(WINDOW *, wchar_t *); 1229 | int win_wch(WINDOW *, cchar_t *); 1230 | int win_wchnstr(WINDOW *, cchar_t *, int); 1231 | int win_wchstr(WINDOW *, cchar_t *); 1232 | wchar_t *wunctrl(cchar_t *); 1233 | int wvline_set(WINDOW *, const cchar_t *, int); 1234 | #endif 1235 | 1236 | /* Quasi-standard */ 1237 | 1238 | chtype getattrs(WINDOW *); 1239 | int getbegx(WINDOW *); 1240 | int getbegy(WINDOW *); 1241 | int getmaxx(WINDOW *); 1242 | int getmaxy(WINDOW *); 1243 | int getparx(WINDOW *); 1244 | int getpary(WINDOW *); 1245 | int getcurx(WINDOW *); 1246 | int getcury(WINDOW *); 1247 | void traceoff(void); 1248 | void traceon(void); 1249 | char *unctrl(chtype); 1250 | 1251 | int crmode(void); 1252 | int nocrmode(void); 1253 | int draino(int); 1254 | int resetterm(void); 1255 | int fixterm(void); 1256 | int saveterm(void); 1257 | int setsyx(int, int); 1258 | 1259 | int mouse_set(unsigned long); 1260 | int mouse_on(unsigned long); 1261 | int mouse_off(unsigned long); 1262 | int request_mouse_pos(void); 1263 | int map_button(unsigned long); 1264 | void wmouse_position(WINDOW *, int *, int *); 1265 | unsigned long getmouse(void); 1266 | unsigned long getbmap(void); 1267 | 1268 | /* ncurses */ 1269 | 1270 | int assume_default_colors(int, int); 1271 | const char *curses_version(void); 1272 | bool has_key(int); 1273 | int use_default_colors(void); 1274 | int wresize(WINDOW *, int, int); 1275 | 1276 | int mouseinterval(int); 1277 | mmask_t mousemask(mmask_t, mmask_t *); 1278 | bool mouse_trafo(int *, int *, bool); 1279 | int nc_getmouse(MEVENT *); 1280 | int ungetmouse(MEVENT *); 1281 | bool wenclose(const WINDOW *, int, int); 1282 | bool wmouse_trafo(const WINDOW *, int *, int *, bool); 1283 | 1284 | /* PDCurses */ 1285 | 1286 | int addrawch(chtype); 1287 | int insrawch(chtype); 1288 | bool is_termresized(void); 1289 | int mvaddrawch(int, int, chtype); 1290 | int mvdeleteln(int, int); 1291 | int mvinsertln(int, int); 1292 | int mvinsrawch(int, int, chtype); 1293 | int mvwaddrawch(WINDOW *, int, int, chtype); 1294 | int mvwdeleteln(WINDOW *, int, int); 1295 | int mvwinsertln(WINDOW *, int, int); 1296 | int mvwinsrawch(WINDOW *, int, int, chtype); 1297 | int raw_output(bool); 1298 | int resize_term(int, int); 1299 | WINDOW *resize_window(WINDOW *, int, int); 1300 | int waddrawch(WINDOW *, chtype); 1301 | int winsrawch(WINDOW *, chtype); 1302 | char wordchar(void); 1303 | 1304 | #ifdef PDC_WIDE 1305 | wchar_t *slk_wlabel(int); 1306 | #endif 1307 | 1308 | void PDC_debug(const char *, ...); 1309 | int PDC_ungetch(int); 1310 | int PDC_set_blink(bool); 1311 | int PDC_set_line_color(short); 1312 | void PDC_set_title(const char *); 1313 | 1314 | int PDC_clearclipboard(void); 1315 | int PDC_freeclipboard(char *); 1316 | int PDC_getclipboard(char **, long *); 1317 | int PDC_setclipboard(const char *, long); 1318 | 1319 | unsigned long PDC_get_input_fd(void); 1320 | unsigned long PDC_get_key_modifiers(void); 1321 | int PDC_return_key_modifiers(bool); 1322 | int PDC_save_key_modifiers(bool); 1323 | 1324 | #ifdef XCURSES 1325 | WINDOW *Xinitscr(int, char **); 1326 | void XCursesExit(void); 1327 | int sb_init(void); 1328 | int sb_set_horz(int, int, int); 1329 | int sb_set_vert(int, int, int); 1330 | int sb_get_horz(int *, int *, int *); 1331 | int sb_get_vert(int *, int *, int *); 1332 | int sb_refresh(void); 1333 | #endif 1334 | 1335 | /*** Functions defined as macros ***/ 1336 | 1337 | /* getch() and ungetch() conflict with some DOS libraries */ 1338 | 1339 | #define getch() wgetch(stdscr) 1340 | #define ungetch(ch) PDC_ungetch(ch) 1341 | 1342 | #define COLOR_PAIR(n) (((chtype)(n) << PDC_COLOR_SHIFT) & A_COLOR) 1343 | #define PAIR_NUMBER(n) (((n) & A_COLOR) >> PDC_COLOR_SHIFT) 1344 | 1345 | /* These will _only_ work as macros */ 1346 | 1347 | #define getbegyx(w, y, x) (y = getbegy(w), x = getbegx(w)) 1348 | #define getmaxyx(w, y, x) (y = getmaxy(w), x = getmaxx(w)) 1349 | #define getparyx(w, y, x) (y = getpary(w), x = getparx(w)) 1350 | #define getyx(w, y, x) (y = getcury(w), x = getcurx(w)) 1351 | 1352 | #define getsyx(y, x) { if (curscr->_leaveit) (y)=(x)=-1; \ 1353 | else getyx(curscr,(y),(x)); } 1354 | 1355 | #ifdef NCURSES_MOUSE_VERSION 1356 | # define getmouse(x) nc_getmouse(x) 1357 | #endif 1358 | 1359 | /* return codes from PDC_getclipboard() and PDC_setclipboard() calls */ 1360 | 1361 | #define PDC_CLIP_SUCCESS 0 1362 | #define PDC_CLIP_ACCESS_ERROR 1 1363 | #define PDC_CLIP_EMPTY 2 1364 | #define PDC_CLIP_MEMORY_ERROR 3 1365 | 1366 | /* PDCurses key modifier masks */ 1367 | 1368 | #define PDC_KEY_MODIFIER_SHIFT 1 1369 | #define PDC_KEY_MODIFIER_CONTROL 2 1370 | #define PDC_KEY_MODIFIER_ALT 4 1371 | #define PDC_KEY_MODIFIER_NUMLOCK 8 1372 | 1373 | #if defined(__cplusplus) || defined(__cplusplus__) || defined(__CPLUSPLUS) 1374 | # undef bool 1375 | } 1376 | #endif 1377 | 1378 | #endif /* __PDCURSES__ */ 1379 | -------------------------------------------------------------------------------- /screen.go: -------------------------------------------------------------------------------- 1 | // Copyright 2011 Rob Thornton. All rights reserved. 2 | // Use of this source code is governed by a BSD-style 3 | // license that can be found in the LICENSE file. 4 | 5 | package goncurses 6 | 7 | // #include 8 | // #if defined(__MINGW32__) || defined(__MINGW64__) 9 | // FILE *fdopen(int fildes, const char *mode) { return _fdopen(fildes, mode); } 10 | // #endif 11 | // #include 12 | // #include 13 | import "C" 14 | 15 | import ( 16 | "errors" 17 | "os" 18 | "unsafe" 19 | ) 20 | 21 | type Screen struct{ scrPtr *C.SCREEN } 22 | 23 | // NewTerm returns a new Screen, representing a physical terminal. If using 24 | // this function to generate a new Screen you should not call Init(). 25 | // Unlike Init(), NewTerm does not call Refresh() to clear the screen so this 26 | // will need to be done manually. When finished with a terminal, you must 27 | // call End() in reverse order that each terminal was created in. After you 28 | // are finished with the screen you must call Delete to free the memory 29 | // allocated to it. This function is usually only useful for programs using 30 | // multiple terminals or test for terminal capabilities. The argument termType 31 | // is the type of terminal to be used ($TERM is used if value is "" which also 32 | // has the same effect of using os.Getenv("TERM")) 33 | func NewTerm(termType string, out, in *os.File) (*Screen, error) { 34 | var tt, wr, rd *C.char 35 | if termType == "" { 36 | tt, wr, rd = (*C.char)(nil), C.CString("w"), C.CString("r") 37 | } else { 38 | tt, wr, rd = C.CString(termType), C.CString("w"), C.CString("r") 39 | defer C.free(unsafe.Pointer(tt)) 40 | } 41 | defer C.free(unsafe.Pointer(wr)) 42 | defer C.free(unsafe.Pointer(rd)) 43 | 44 | cout, cin := C.fdopen(C.int(out.Fd()), wr), C.fdopen(C.int(in.Fd()), rd) 45 | screen := C.newterm(tt, cout, cin) 46 | if screen == nil { 47 | return nil, errors.New("Failed to create new screen") 48 | } 49 | return &Screen{screen}, nil 50 | } 51 | 52 | // Set the screen to be the current, active screen 53 | func (s *Screen) Set() (*Screen, error) { 54 | screen := C.set_term(s.scrPtr) 55 | if screen == nil { 56 | return nil, errors.New("Failed to set screen") 57 | } 58 | return &Screen{screen}, nil 59 | } 60 | 61 | // Delete frees memory allocated to the screen. This function 62 | func (s *Screen) Delete() { 63 | C.delscreen(s.scrPtr) 64 | } 65 | 66 | // End is just a wrapper for the global End function. This helper function 67 | // has been provided to help ensure that new terminals are closed in the 68 | // proper, reverse order they were created. It makes the terminal active via 69 | // set then called End so it is closed properly. You must make sure that 70 | // Delete is called once done with the screen/terminal. 71 | func (s *Screen) End() { 72 | s.Set() 73 | End() 74 | } 75 | -------------------------------------------------------------------------------- /slk.go: -------------------------------------------------------------------------------- 1 | // goncurses - ncurses library for Go. 2 | // Copyright 2011 Rob Thornton. All rights reserved. 3 | // Use of this source code is governed by a BSD-style 4 | // license that can be found in the LICENSE file. 5 | 6 | package goncurses 7 | 8 | // #include 9 | // #include 10 | import "C" 11 | 12 | import ( 13 | "errors" 14 | "unsafe" 15 | ) 16 | 17 | type SlkFormat byte 18 | 19 | const ( 20 | SLK_323 SlkFormat = iota // 8 labels; 3-2-3 arrangement 21 | SLK_44 // 8 labels; 4-4 arrangement 22 | SLK_PC444 // 12 labels; 4-4-4 arrangement 23 | SLK_PC444INDEX // 12 labels; 4-4-4 with index line 24 | ) 25 | 26 | type SlkJustify byte 27 | 28 | const ( 29 | SLK_LEFT SlkJustify = iota 30 | SLK_CENTER 31 | SLK_RIGHT 32 | ) 33 | 34 | // Initializes the soft-key labels with the given format; keys like the 35 | // F1-F12 keys on most keyboards. After a call to SlkRefresh a bar at the 36 | // bottom of the standard screen returned by Init will be displayed. This 37 | // function MUST be called prior to Init() 38 | func SlkInit(f SlkFormat) { 39 | C.slk_init(C.int(f)) 40 | } 41 | 42 | // SlkSet sets the 'labnum' text to the supplied 'label'. Labels must not 43 | // be greater than 8 characters 44 | func SlkSet(labnum int, label string, just SlkJustify) error { 45 | cstr := C.CString(label) 46 | defer C.free(unsafe.Pointer(cstr)) 47 | 48 | if C.slk_set(C.int(labnum), (*C.char)(cstr), C.int(just)) == C.ERR { 49 | return errors.New("Soft-keys or terminal not initialized") 50 | } 51 | return nil 52 | } 53 | 54 | // SlkRefresh behaves the same as Window.Refresh. Most applications would use 55 | // SlkNoutRefresh because a Window.Refresh is likely to follow 56 | func SlkRefresh() error { 57 | if C.slk_refresh() == C.ERR { 58 | return errors.New("Soft-keys or terminal not initialized.") 59 | } 60 | return nil 61 | } 62 | 63 | // SlkNoutFresh behaves like Window.NoutRefresh 64 | func SlkNoutRefresh() error { 65 | if C.slk_noutrefresh() == C.ERR { 66 | return errors.New("Soft-keys or terminal not initialized.") 67 | } 68 | return nil 69 | } 70 | 71 | // SlkLabel returns the label for the given key 72 | func SlkLabel(labnum int) string { 73 | return C.GoString(C.slk_label(C.int(labnum))) 74 | } 75 | 76 | // SlkClear removes the soft-key labels from the screen 77 | func SlkClear() error { 78 | if C.slk_clear() == C.ERR { 79 | return errors.New("Soft-keys or terminal not initialized.") 80 | } 81 | return nil 82 | } 83 | 84 | // SlkRestore restores the soft-key labels to the screen after an SlkClear() 85 | func SlkRestore() error { 86 | if C.slk_restore() == C.ERR { 87 | return errors.New("Soft-keys or terminal not initialized.") 88 | } 89 | return nil 90 | } 91 | 92 | // SlkTouch behaves just like Window.Touch 93 | func SlkTouch() error { 94 | if C.slk_touch() == C.ERR { 95 | return errors.New("Soft-keys or terminal not initialized.") 96 | } 97 | return nil 98 | } 99 | 100 | // SlkColor sets the color pair for the soft-keys 101 | func SlkColor(cp int16) error { 102 | if C.slk_color(C.short(cp)) == C.ERR { 103 | return errors.New("Invalid color pair or soft-keys not initialized.") 104 | } 105 | return nil 106 | } 107 | 108 | /* TODO: Not available in PDCurses 109 | // SlkAttribute returns the currently set attributes 110 | func SlkAttribute() Char { 111 | return Char(C.slk_attr()) 112 | }*/ 113 | 114 | // SlkSetAttribute sets the OR'd attributes to use 115 | func SlkSetAttribute(attr Char) error { 116 | if C.slk_attrset(C.chtype(attr)) == C.ERR { 117 | return errors.New("Soft-keys or terminal not initialized.") 118 | } 119 | return nil 120 | } 121 | 122 | // SlkAttributeOn turns on the given OR'd attributes without turning any off 123 | func SlkAttributeOn(attr Char) error { 124 | if C.slk_attron(C.chtype(attr)) == C.ERR { 125 | return errors.New("Soft-keys or terminal not initialized.") 126 | } 127 | return nil 128 | } 129 | 130 | // SlkAttributeOff turns off the given OR'd attributes without turning any on 131 | func SlkAttributeOff(attr Char) error { 132 | if C.slk_attroff(C.chtype(attr)) == C.ERR { 133 | return errors.New("Soft-keys or terminal not initialized.") 134 | } 135 | return nil 136 | } 137 | -------------------------------------------------------------------------------- /window.go: -------------------------------------------------------------------------------- 1 | // Copyright 2011 Rob Thornton. All rights reserved. 2 | // Use of this source code is governed by a BSD-style 3 | // license that can be found in the LICENSE file. 4 | 5 | package goncurses 6 | 7 | // #include 8 | // #include 9 | // #include "goncurses.h" 10 | import "C" 11 | 12 | import ( 13 | "errors" 14 | "fmt" 15 | "unsafe" 16 | ) 17 | 18 | type Window struct { 19 | win *C.WINDOW 20 | } 21 | 22 | // NewWindow creates a window of size h(eight) and w(idth) at y, x 23 | func NewWindow(h, w, y, x int) (window *Window, err error) { 24 | window = &Window{C.newwin(C.int(h), C.int(w), C.int(y), C.int(x))} 25 | if window.win == nil { 26 | err = errors.New("Failed to create a new window") 27 | } 28 | return 29 | } 30 | 31 | // AddChar prints a single character to the window. The character can be 32 | // OR'd together with attributes and colors. 33 | func (w *Window) AddChar(ach Char) { 34 | C.waddch(w.win, C.chtype(ach)) 35 | } 36 | 37 | // MoveAddChar prints a single character to the window at the specified 38 | // y x coordinates. See AddChar for more info. 39 | func (w *Window) MoveAddChar(y, x int, ach Char) { 40 | C.mvwaddch(w.win, C.int(y), C.int(x), C.chtype(ach)) 41 | } 42 | 43 | // Turn off character attribute. 44 | func (w *Window) AttrOff(attr Char) (err error) { 45 | if C.ncurses_wattroff(w.win, C.int(attr)) == C.ERR { 46 | err = errors.New(fmt.Sprintf("Failed to unset attribute: %s", 47 | attrList[C.int(attr)])) 48 | } 49 | return 50 | } 51 | 52 | // Turn on character attribute 53 | func (w *Window) AttrOn(attr Char) (err error) { 54 | if C.ncurses_wattron(w.win, C.int(attr)) == C.ERR { 55 | err = errors.New(fmt.Sprintf("Failed to set attribute: %s", 56 | attrList[C.int(attr)])) 57 | } 58 | return 59 | } 60 | 61 | // AttrSet sets the attributes to the given value 62 | func (w *Window) AttrSet(attr Char) error { 63 | if C.ncurses_wattrset(w.win, C.int(attr)) == C.ERR { 64 | return errors.New("Failed to set attributes") 65 | } 66 | return nil 67 | } 68 | 69 | // SetBackground fills the background with the supplied attributes and/or 70 | // characters. 71 | func (w *Window) SetBackground(attr Char) { 72 | C.wbkgd(w.win, C.chtype(attr)) 73 | } 74 | 75 | // Background returns the current background attributes 76 | func (w *Window) Background() Char { 77 | return Char(C.ncurses_getbkgd(w.win)) 78 | } 79 | 80 | // Border uses the characters supplied to draw a border around the window. 81 | // t, b, r, l, s correspond to top, bottom, right, left and side respectively. 82 | func (w *Window) Border(ls, rs, ts, bs, tl, tr, bl, br Char) error { 83 | res := C.wborder(w.win, C.chtype(ls), C.chtype(rs), C.chtype(ts), 84 | C.chtype(bs), C.chtype(tl), C.chtype(tr), C.chtype(bl), 85 | C.chtype(br)) 86 | if res == C.ERR { 87 | return errors.New("Failed to draw box around window") 88 | } 89 | return nil 90 | } 91 | 92 | // Box draws a border around the given window. For complete control over the 93 | // characters used to draw the border use Border() 94 | func (w *Window) Box(vch, hch Char) error { 95 | if C.box(w.win, C.chtype(vch), C.chtype(hch)) == C.ERR { 96 | return errors.New("Failed to draw box around window") 97 | } 98 | return nil 99 | } 100 | 101 | // Clears the screen and the underlying virtual screen. This forces the entire 102 | // screen to be rewritten from scratch. This will cause likely cause a 103 | // noticeable flicker because the screen is completely cleared before 104 | // redrawing it. This is probably not what you want. Instead, you should 105 | // probably use the Erase() function. It is the same as called Erase() followed 106 | // by a call to ClearOk(). 107 | func (w *Window) Clear() error { 108 | if C.wclear(w.win) == C.ERR { 109 | return errors.New("Failed to clear screen") 110 | } 111 | return nil 112 | } 113 | 114 | // ClearOk clears the window completely prior to redrawing it. If called 115 | // on stdscr then the whole screen is redrawn no matter which window has 116 | // Refresh() called on it. Defaults to False. 117 | func (w *Window) ClearOk(ok bool) { 118 | C.clearok(w.win, C.bool(ok)) 119 | } 120 | 121 | // Clear starting at the current cursor position, moving to the right, to the 122 | // bottom of window 123 | func (w *Window) ClearToBottom() error { 124 | if C.wclrtobot(w.win) == C.ERR { 125 | return errors.New("Failed to clear bottom of window") 126 | } 127 | return nil 128 | } 129 | 130 | // Clear from the current cursor position, moving to the right, to the end 131 | // of the line 132 | func (w *Window) ClearToEOL() error { 133 | if C.wclrtoeol(w.win) == C.ERR { 134 | return errors.New("Failed to clear to end of line") 135 | } 136 | return nil 137 | } 138 | 139 | // Color sets the foreground/background color pair for the entire window 140 | func (w *Window) Color(pair int16) { 141 | C.wcolor_set(w.win, C.short(ColorPair(pair)), nil) 142 | } 143 | 144 | // ColorOff turns the specified color pair off 145 | func (w *Window) ColorOff(pair int16) error { 146 | if C.ncurses_wattroff(w.win, C.int(ColorPair(pair))) == C.ERR { 147 | return errors.New("Failed to enable color pair") 148 | } 149 | return nil 150 | } 151 | 152 | // Normally color pairs are turned on via attron() in ncurses but this 153 | // implementation chose to make it separate 154 | func (w *Window) ColorOn(pair int16) error { 155 | if C.ncurses_wattron(w.win, C.int(ColorPair(pair))) == C.ERR { 156 | return errors.New("Failed to enable color pair") 157 | } 158 | return nil 159 | } 160 | 161 | // Copy is similar to Overlay and Overwrite but provides a finer grain of 162 | // control. 163 | func (w *Window) Copy(src *Window, sy, sx, dtr, dtc, dbr, dbc int, 164 | overlay bool) error { 165 | var ol int 166 | if overlay { 167 | ol = 1 168 | } 169 | if C.copywin(src.win, w.win, C.int(sy), C.int(sx), 170 | C.int(dtr), C.int(dtc), C.int(dbr), C.int(dbc), C.int(ol)) == 171 | C.ERR { 172 | return errors.New("Failed to copy window") 173 | } 174 | return nil 175 | } 176 | 177 | // DelChar deletes the character at the current cursor position, moving all 178 | // characters to the right of that position one space to the left and appends 179 | // a blank character at the end. 180 | func (w *Window) DelChar() error { 181 | if err := C.wdelch(w.win); err != C.OK { 182 | return errors.New("An error occurred when trying to delete " + 183 | "character") 184 | } 185 | return nil 186 | } 187 | 188 | // MoveDelChar deletes the character at the given cursor coordinates, moving all 189 | // characters to the right of that position one space to the left and appends 190 | // a blank character at the end. 191 | func (w *Window) MoveDelChar(y, x int) error { 192 | if err := C.mvwdelch(w.win, C.int(y), C.int(x)); err != C.OK { 193 | return errors.New("An error occurred when trying to delete " + 194 | "character") 195 | } 196 | return nil 197 | } 198 | 199 | // Delete the window. This function must be called to ensure memory is freed 200 | // to prevent memory leaks once you are done with the window. 201 | func (w *Window) Delete() error { 202 | if C.delwin(w.win) == C.ERR { 203 | return errors.New("Failed to delete window") 204 | } 205 | w = nil 206 | return nil 207 | } 208 | 209 | // Derived creates a new window of height and width at the coordinates 210 | // y, x. These coordinates are relative to the original window thereby 211 | // confining the derived window to the area of original window. See the 212 | // SubWindow function for additional notes. 213 | func (w *Window) Derived(height, width, y, x int) *Window { 214 | return &Window{C.derwin(w.win, C.int(height), C.int(width), C.int(y), 215 | C.int(x))} 216 | } 217 | 218 | // Duplicate the window, creating an exact copy. 219 | func (w *Window) Duplicate() *Window { 220 | return &Window{C.dupwin(w.win)} 221 | } 222 | 223 | // Test whether the given coordinates are within the window or not 224 | func (w *Window) Enclose(y, x int) bool { 225 | return bool(C.wenclose(w.win, C.int(y), C.int(x))) 226 | } 227 | 228 | // Erase the contents of the window, clearing it. This function allows the 229 | // underlying structures to be updated efficiently and thereby provide smooth 230 | // updates to the terminal when frequently clearing and re-writing the window 231 | // or screen. 232 | func (w *Window) Erase() { 233 | C.werase(w.win) 234 | } 235 | 236 | // GetChar retrieves a character from standard input stream and returns it. 237 | // In the event of an error or if the input timeout has expired (i.e. if 238 | // Timeout() has been set to zero or a positive value and no characters have 239 | // been received) the value returned will be zero (0) 240 | func (w *Window) GetChar() Key { 241 | ch := C.wgetch(w.win) 242 | if ch == C.ERR { 243 | ch = 0 244 | } 245 | return Key(ch) 246 | } 247 | 248 | // MoveGetChar moves the cursor to the given position and gets a character 249 | // from the input stream 250 | func (w *Window) MoveGetChar(y, x int) Key { 251 | return Key(C.mvwgetch(w.win, C.int(y), C.int(x))) 252 | } 253 | 254 | // GetString reads at most 'n' characters entered by the user from the Window. 255 | // Attempts to enter greater than 'n' characters will elicit a 'beep' 256 | func (w *Window) GetString(n int) (string, error) { 257 | cstr := make([]C.char, n) 258 | if C.wgetnstr(w.win, (*C.char)(&cstr[0]), C.int(n)) == C.ERR { 259 | return "", errors.New("Failed to retrieve string from input stream") 260 | } 261 | return C.GoString(&cstr[0]), nil 262 | } 263 | 264 | // CursorYX returns the current cursor location in the Window. Note that it 265 | // uses ncurses idiom of returning y then x. 266 | func (w *Window) CursorYX() (int, int) { 267 | var cy, cx C.int 268 | C.ncurses_getyx(w.win, &cy, &cx) 269 | return int(cy), int(cx) 270 | } 271 | 272 | // HLine draws a horizontal line starting at y, x and ending at width using 273 | // the specified character 274 | func (w *Window) HLine(y, x int, ch Char, wid int) { 275 | C.mvwhline(w.win, C.int(y), C.int(x), C.chtype(ch), C.int(wid)) 276 | return 277 | } 278 | 279 | // InChar returns the character at the current position in the curses window 280 | func (w *Window) InChar() Char { 281 | return Char(C.winch(w.win)) 282 | } 283 | 284 | // MoveInChar returns the character at the designated coordates in the curses 285 | // window 286 | func (w *Window) MoveInChar(y, x int) Char { 287 | return Char(C.mvwinch(w.win, C.int(y), C.int(x))) 288 | } 289 | 290 | // IsCleared returns the value set in ClearOk 291 | func (w *Window) IsCleared() bool { 292 | return bool(C.ncurses_is_cleared(w.win)) 293 | } 294 | 295 | // IsKeypad returns the value set in Keypad 296 | func (w *Window) IsKeypad() bool { 297 | return bool(C.ncurses_is_keypad(w.win)) 298 | } 299 | 300 | // Keypad turns on/off the keypad characters, including those like the F1-F12 301 | // keys and the arrow keys 302 | func (w *Window) Keypad(keypad bool) error { 303 | var err C.int 304 | if err = C.keypad(w.win, C.bool(keypad)); err == C.ERR { 305 | return errors.New("Unable to set keypad mode") 306 | } 307 | return nil 308 | } 309 | 310 | // LineTouched returns true if the line has been touched; returns false 311 | // otherwise 312 | func (w *Window) LineTouched(line int) bool { 313 | return bool(C.is_linetouched(w.win, C.int(line))) 314 | } 315 | 316 | // Returns the maximum size of the Window. Note that it uses ncurses idiom 317 | // of returning y then x. 318 | func (w *Window) MaxYX() (int, int) { 319 | var cy, cx C.int 320 | C.ncurses_getmaxyx(w.win, &cy, &cx) 321 | return int(cy), int(cx) 322 | } 323 | 324 | // Move the cursor to the specified coordinates within the window 325 | func (w *Window) Move(y, x int) { 326 | C.wmove(w.win, C.int(y), C.int(x)) 327 | return 328 | } 329 | 330 | // MoveWindow moves the location of the window to the specified coordinates 331 | func (w *Window) MoveWindow(y, x int) { 332 | C.mvwin(w.win, C.int(y), C.int(x)) 333 | return 334 | } 335 | 336 | // NoutRefresh, or No Output Refresh, flags the window for redrawing but does 337 | // not output the changes to the terminal (screen). Essentially, the output is 338 | // buffered and a call to Update() flushes the buffer to the terminal. This 339 | // function provides a speed increase over calling Refresh() when multiple 340 | // windows are involved because only the final output is 341 | // transmitted to the terminal. 342 | func (w *Window) NoutRefresh() { 343 | C.wnoutrefresh(w.win) 344 | return 345 | } 346 | 347 | // Overlay copies overlapping sections of src window onto the destination 348 | // window. Non-blank elements are not overwritten. 349 | func (w *Window) Overlay(src *Window) error { 350 | if C.overlay(src.win, w.win) == C.ERR { 351 | return errors.New("Failed to overlay window") 352 | } 353 | return nil 354 | } 355 | 356 | // Overwrite copies overlapping sections of src window onto the destination 357 | // window. This function is considered "destructive" by copying all 358 | // elements of src onto the destination window. 359 | func (w *Window) Overwrite(src *Window) error { 360 | if C.overwrite(src.win, w.win) == C.ERR { 361 | return errors.New("Failed to overwrite window") 362 | } 363 | return nil 364 | } 365 | 366 | // Parent returns a pointer to a Sub-window's parent, or nil if the window 367 | // has no parent 368 | func (w *Window) Parent() *Window { 369 | p := C.ncurses_wgetparent(w.win) 370 | if p == nil { 371 | return nil 372 | } 373 | return &Window{p} 374 | } 375 | 376 | // Print a string to the given window. See the fmt package in the standard 377 | // library for more information. In order to simulate the 'n' version 378 | // of functions (like addnstr) just slice your string to the maximum 379 | // length before passing it as an argument. 380 | // window.Print("My line which should be clamped to 20 characters"[:20]) 381 | func (w *Window) Print(args ...interface{}) { 382 | w.Printf("%s", fmt.Sprint(args...)) 383 | } 384 | 385 | // Printf functions the same as the standard library's fmt package. See Print 386 | // for more details. 387 | func (w *Window) Printf(format string, args ...interface{}) { 388 | cstr := C.CString(fmt.Sprintf(format, args...)) 389 | defer C.free(unsafe.Pointer(cstr)) 390 | 391 | C.waddstr(w.win, cstr) 392 | } 393 | 394 | // Println behaves the same as the standard library's fmt package. 395 | // See Print for more information. 396 | func (w *Window) Println(args ...interface{}) { 397 | w.Printf("%s", fmt.Sprintln(args...)) 398 | } 399 | 400 | // MovePrint moves the cursor to the specified coordinates and prints the 401 | // supplied message. See Print for more details.The first two arguments are the 402 | // coordinates to print to. 403 | func (w *Window) MovePrint(y, x int, args ...interface{}) { 404 | w.MovePrintf(y, x, "%s", fmt.Sprint(args...)) 405 | } 406 | 407 | // MovePrintf moves the cursor to coordinates and prints the message using 408 | // the specified format. See Printf and MovePrint for more information. 409 | func (w *Window) MovePrintf(y, x int, format string, args ...interface{}) { 410 | cstr := C.CString(fmt.Sprintf(format, args...)) 411 | defer C.free(unsafe.Pointer(cstr)) 412 | 413 | C.mvwaddstr(w.win, C.int(y), C.int(x), cstr) 414 | } 415 | 416 | // MovePrintln moves the cursor to coordinates and prints the message. See 417 | // Println and MovePrint for more details. 418 | func (w *Window) MovePrintln(y, x int, args ...interface{}) { 419 | w.MovePrintf(y, x, "%s", fmt.Sprintln(args...)) 420 | } 421 | 422 | // Refresh the window so it's contents will be displayed 423 | func (w *Window) Refresh() { 424 | C.wrefresh(w.win) 425 | } 426 | 427 | // Resize the window to new height, width 428 | func (w *Window) Resize(height, width int) { 429 | C.wresize(w.win, C.int(height), C.int(width)) 430 | } 431 | 432 | // Scroll the contents of the window. Use a negative number to scroll up, 433 | // a positive number to scroll down. ScrollOk Must have been called prior. 434 | func (w *Window) Scroll(n int) { 435 | C.wscrl(w.win, C.int(n)) 436 | } 437 | 438 | // ScrollOk sets whether scrolling will work 439 | func (w *Window) ScrollOk(ok bool) { 440 | C.scrollok(w.win, C.bool(ok)) 441 | } 442 | 443 | // SubWindow creates a new window of height and width at the coordinates 444 | // y, x. This window shares memory with the original window so changes 445 | // made to one window are reflected in the other. It is necessary to call 446 | // Touch() on this window prior to calling Refresh in order for it to be 447 | // displayed. 448 | func (w *Window) Sub(height, width, y, x int) *Window { 449 | return &Window{C.subwin(w.win, C.int(height), C.int(width), C.int(y), 450 | C.int(x))} 451 | } 452 | 453 | // Standend turns off Standout mode, which is equivalent AttrSet(A_NORMAL) 454 | func (w *Window) Standend() error { 455 | if C.ncurses_wstandend(w.win) == C.ERR { 456 | return errors.New("Failed to set standend") 457 | } 458 | return nil 459 | } 460 | 461 | // Standout is equivalent to AttrSet(A_STANDOUT) 462 | func (w *Window) Standout() error { 463 | if C.ncurses_wstandout(w.win) == C.ERR { 464 | return errors.New("Failed to set standout") 465 | } 466 | return nil 467 | } 468 | 469 | // Sync updates all parent or child windows which were created via 470 | // SubWindow() or DerivedWindow(). Argument can be one of: SYNC_DOWN, which 471 | // syncronizes all parent windows (done by Refresh() by default so should 472 | // rarely, if ever, need to be called); SYNC_UP, which updates all child 473 | // windows to match any updates made to the parent; and, SYNC_CURSOR, which 474 | // updates the cursor position only for all windows to match the parent window 475 | func (w *Window) Sync(sync int) { 476 | switch sync { 477 | case SYNC_DOWN: 478 | C.wsyncdown(w.win) 479 | case SYNC_CURSOR: 480 | C.wcursyncup(w.win) 481 | case SYNC_UP: 482 | C.wsyncup(w.win) 483 | } 484 | } 485 | 486 | // Timeout sets the window to blocking or non-blocking read mode. Calls to 487 | // GetCh will behave in the following manor depending on the value of delay: 488 | // <= -1 - blocking mode is set (blocks indefinitely) 489 | // == 0 - non-blocking; returns zero (0) 490 | // >= 1 - blocks for delay in milliseconds; returns zero (0) 491 | func (w *Window) Timeout(delay int) { 492 | C.wtimeout(w.win, C.int(delay)) 493 | } 494 | 495 | // Touch indicates that the window contains changes which should be updated 496 | // on the next call to Refresh 497 | func (w *Window) Touch() error { 498 | if C.ncurses_touchwin(w.win) == C.ERR { 499 | return errors.New("Failed to Touch window") 500 | } 501 | return nil 502 | } 503 | 504 | // Touched returns true if window will be updated on the next Refresh 505 | func (w *Window) Touched() bool { 506 | return bool(C.is_wintouched(w.win)) 507 | } 508 | 509 | // Touchline behaves like Touch but only effects count number of lines, 510 | // beginning at start 511 | func (w *Window) TouchLine(start, count int) error { 512 | if C.touchline(w.win, C.int(start), C.int(count)) == C.ERR { 513 | return errors.New("Error in call to TouchLine") 514 | } 515 | return nil 516 | } 517 | 518 | // UnTouch indicates the window should not be updated on the next call to 519 | // Refresh 520 | func (w *Window) UnTouch() { 521 | C.ncurses_untouchwin(w.win) 522 | } 523 | 524 | // VLine draws a vertical line starting at y, x and ending at height using 525 | // the specified character 526 | func (w *Window) VLine(y, x int, ch Char, wid int) { 527 | C.mvwvline(w.win, C.int(y), C.int(x), C.chtype(ch), C.int(wid)) 528 | } 529 | 530 | // YX returns the current coordinates of the Window. Note that it uses 531 | // ncurses idiom of returning y then x. 532 | func (w *Window) YX() (int, int) { 533 | var y, x C.int 534 | C.ncurses_getbegyx(w.win, &y, &x) 535 | return int(y), int(x) 536 | } 537 | --------------------------------------------------------------------------------