0 | module NCurses.Core
  1 |
  2 | libncurses : String -> String
  3 | libncurses fn = "C:" ++ fn ++ ",libncurses,ncurses.h"
  4 |
  5 | libhelper : String -> String
  6 | libhelper fn = "C:" ++ fn ++ ",libncurses-idris,curses-helpers.h"
  7 |
  8 | %foreign libhelper "ncurses_err"
  9 | prim__err : PrimIO Int
 10 |
 11 | %foreign libhelper "std_win"
 12 | prim__stdWindow : PrimIO AnyPtr
 13 |
 14 | %foreign libncurses "newwin"
 15 | prim__newWindow : Int -> Int -> Int -> Int -> PrimIO AnyPtr
 16 |
 17 | -- Returns ERR/OK
 18 | %foreign libncurses "delwin"
 19 | prim__deleteWindow : AnyPtr -> PrimIO Int
 20 |
 21 | -- Returns ERR/OK
 22 | %foreign libncurses "mvwin"
 23 | prim__moveWindow : AnyPtr -> Int -> Int -> PrimIO Int
 24 |
 25 | -- Returns ERR/OK
 26 | %foreign libncurses "wresize"
 27 | prim__resizeWindow : AnyPtr -> Int -> Int -> PrimIO Int
 28 |
 29 | %foreign libncurses "getmaxx"
 30 | prim__maxXWindow : AnyPtr -> PrimIO Int
 31 |
 32 | %foreign libncurses "getmaxy"
 33 | prim__maxYWindow : AnyPtr -> PrimIO Int
 34 |
 35 | %foreign libncurses "getcury"
 36 | prim__getYWindow : AnyPtr -> PrimIO Int
 37 |
 38 | %foreign libncurses "getcurx"
 39 | prim__getXWindow : AnyPtr -> PrimIO Int
 40 |
 41 | %foreign libncurses "getbegy"
 42 | prim__begYWindow : AnyPtr -> PrimIO Int
 43 |
 44 | %foreign libncurses "getbegx"
 45 | prim__begXWindow : AnyPtr -> PrimIO Int
 46 |
 47 | %foreign libncurses "refresh"
 48 | prim__refresh : PrimIO ()
 49 |
 50 | %foreign libncurses "wrefresh"
 51 | prim__refreshWindow : AnyPtr -> PrimIO ()
 52 |
 53 | %foreign libncurses "clear"
 54 | prim__clear : PrimIO ()
 55 |
 56 | %foreign libncurses "wclear"
 57 | prim__clearWindow : AnyPtr -> PrimIO ()
 58 |
 59 | %foreign libncurses "erase"
 60 | prim__erase : PrimIO ()
 61 |
 62 | %foreign libncurses "werase"
 63 | prim__eraseWindow : AnyPtr -> PrimIO ()
 64 |
 65 | %foreign libhelper "print"
 66 | prim__print : String -> String -> PrimIO ()
 67 |
 68 | %foreign libhelper "printWindow"
 69 | prim__printWindow : AnyPtr -> String -> String -> PrimIO ()
 70 |
 71 | %foreign libncurses "addch"
 72 | prim__addChar : Char -> PrimIO ()
 73 |
 74 | %foreign libncurses "waddch"
 75 | prim__addCharWindow : AnyPtr -> Char -> PrimIO ()
 76 |
 77 | ||| move to row and column given and print
 78 | ||| the given string.
 79 | |||
 80 | ||| IMPORTANT: This takes the y-position before
 81 | ||| the x-position.
 82 | |||
 83 | ||| The second to last argument is a format string but
 84 | ||| its best to just always pass strings ("%s").
 85 | %foreign libhelper "mvPrint"
 86 | prim__mvPrint : Int -> Int -> String -> String -> PrimIO ()
 87 |
 88 | %foreign libhelper "mvPrintWindow"
 89 | prim__mvPrintWindow : AnyPtr -> Int -> Int -> String -> String -> PrimIO ()
 90 |
 91 | %foreign libncurses "vline"
 92 | prim__verticalLine : Char -> Int -> PrimIO ()
 93 |
 94 | %foreign libncurses "wvline"
 95 | prim__verticalLineWindow : AnyPtr -> Char -> Int -> PrimIO ()
 96 |
 97 | %foreign libncurses "hline"
 98 | prim__horizontalLine : Char -> Int -> PrimIO ()
 99 |
100 | %foreign libncurses "whline"
101 | prim__horizontalLineWindow : AnyPtr -> Char -> Int -> PrimIO ()
102 |
103 | ||| Draw a window border with the given chars used for the
104 | ||| left, right, top, and bottom edges as well as the given
105 | ||| top left, top right, bottom left, and bottom right corners.
106 | %foreign libncurses "wborder"
107 | prim__borderWindow : AnyPtr
108 |                   -> (l : Char)  -> (r : Char)  -> (t : Char)  -> (b : Char)
109 |                   -> (tl : Char) -> (tr : Char) -> (bl : Char) -> (br : Char)
110 |                   -> PrimIO ()
111 |
112 | %foreign libncurses "move"
113 | prim__move : Int -> Int -> PrimIO ()
114 |
115 | %foreign libncurses "wmove"
116 | prim__moveInWindow : AnyPtr -> Int -> Int -> PrimIO ()
117 |
118 | %foreign libncurses "initscr"
119 | prim__initScr : PrimIO ()
120 |
121 | %foreign libncurses "endwin"
122 | prim__endWin : PrimIO ()
123 |
124 | boolToInt : Bool -> Int
125 | boolToInt False = 0
126 | boolToInt True  = 1
127 |
128 | ||| When you make new windows with @newWindow@
129 | ||| this data type stores a reference for you
130 | ||| to use with any function that operates on
131 | ||| a particular window.
132 | |||
133 | ||| Most functions operate on a window even if
134 | ||| they don't appear to; you get a default window
135 | ||| for free with @initNCurses@. You can request the
136 | ||| default window with @stdWindow@.
137 | export
138 | data Window = Win AnyPtr
139 |
140 | ||| Get the default standard ncurses window.
141 | export
142 | stdWindow : HasIO io => io Window
143 | stdWindow = Win <$> (primIO $ prim__stdWindow)
144 |
145 | ||| Create a new ncurses window.
146 | export
147 | newWindow : HasIO io => (height : Nat) -> (width : Nat) -> (y : Nat) -> (x : Nat) -> io Window
148 | newWindow height width y x = Win <$> (primIO $ prim__newWindow (cast height) (cast width) (cast y) (cast x))
149 |
150 | ||| Delete an ncurses window.
151 | |||
152 | ||| Returns @True@ on success and @False@ on error.
153 | export
154 | deleteWindow : HasIO io => Window -> io Bool
155 | deleteWindow (Win win) = do
156 |   err <- primIO $ prim__err
157 |   res <- primIO $ prim__deleteWindow win
158 |   pure $
159 |     if res == err
160 |        then False
161 |        else True
162 |
163 | ||| Move an ncurses window.
164 | |||
165 | ||| Returns @True@ on success and @False@ on error.
166 | export
167 | moveWindow : HasIO io => Window -> (y : Nat) -> (x : Nat) -> io Bool
168 | moveWindow (Win win) y x = do
169 |   err <- primIO $ prim__err
170 |   res <- primIO $ prim__moveWindow win (cast y) (cast x)
171 |   pure $
172 |     if res == err
173 |        then False
174 |        else True
175 |
176 | ||| As is normal for ncurses, returns (y, x).
177 | export
178 | getWindowPos' : HasIO io => Window -> io (Nat, Nat)
179 | getWindowPos' (Win win) = do y <- (primIO $ prim__begYWindow win)
180 |                              x <- (primIO $ prim__begXWindow win)
181 |                              pure (fromInteger (cast y), fromInteger (cast x))
182 |
183 | ||| Resize an ncurses window.
184 | |||
185 | ||| Returns @True@ on success and @False@ on error.
186 | export
187 | setWindowSize : HasIO io => Window -> (rows : Nat) -> (cols : Nat) -> io Bool
188 | setWindowSize (Win win) rows cols = do
189 |   err <- primIO $ prim__err
190 |   res <- primIO $ prim__resizeWindow win (cast rows) (cast cols) 
191 |   pure $
192 |     if res == err
193 |        then False
194 |        else True
195 |
196 | ||| As is normal for ncurses, returns (height, width).
197 | export
198 | getMaxSize' : HasIO io => Window -> io (Nat, Nat)
199 | getMaxSize' (Win win) = do y <- (primIO $ prim__maxYWindow win)
200 |                            x <- (primIO $ prim__maxXWindow win)
201 |                            pure (fromInteger (cast y), fromInteger (cast x))
202 |
203 | export
204 | getYPos' : HasIO io => Window -> io Nat
205 | getYPos' (Win win) = map cast . primIO $ prim__getYWindow win
206 |
207 | export
208 | getYPos : HasIO io => io Nat
209 | getYPos = getYPos' !stdWindow
210 |
211 | export
212 | getXPos' : HasIO io => Window -> io Nat
213 | getXPos' (Win win) = map cast . primIO $ prim__getXWindow win
214 |
215 | export
216 | getXPos : HasIO io => io Nat
217 | getXPos = getXPos' !stdWindow
218 |
219 | ||| Refresh the standard window.
220 | |||
221 | ||| See @refresh'@ to refresh any other window.
222 | export
223 | refresh : HasIO io => io ()
224 | refresh = primIO $ prim__refresh
225 |
226 | ||| Refresh a particular window.
227 | export
228 | refresh' : HasIO io => Window -> io ()
229 | refresh' (Win win) = primIO $ prim__refreshWindow win
230 |
231 | ||| Clear the standard window.
232 | |||
233 | ||| Clearing causes NCurses to redraw the whole terminal on
234 | ||| the next call to refresh. See @erase@ for a less intensive
235 | ||| process that allows NCurses to intelligently determine how
236 | ||| much of the terminal view needs to be redrawn.
237 | |||
238 | ||| Clearing the standard window will require refreshing all
239 | ||| windows after the next call to refresh the standard window,
240 | ||| It probably makes sense much of the time to refresh immediately
241 | ||| after a call to clear.
242 | |||
243 | ||| See @clear'@ to clear any other window.
244 | export
245 | clear : HasIO io => io ()
246 | clear = primIO $ prim__clear
247 |
248 | ||| Clear a particular window.
249 | |||
250 | ||| Clearing causes NCurses to redraw the whole terminal on
251 | ||| the next call to refresh. See @erase@ for a less intensive
252 | ||| process that allows NCurses to intelligently determine how
253 | ||| much of the terminal view needs to be redrawn.
254 | |||
255 | ||| Clearing the standard window will require refreshing all
256 | ||| windows after the next call to refresh the standard window,
257 | ||| It probably makes sense much of the time to refresh immediately
258 | ||| after a call to clear.
259 | export
260 | clear' : HasIO io => Window -> io ()
261 | clear' (Win win) = primIO $ prim__clearWindow win
262 |
263 | ||| Erase the standard window.
264 | |||
265 | ||| See @erase'@ to erase any other window.
266 | export
267 | erase : HasIO io => io ()
268 | erase = primIO $ prim__erase
269 |
270 | ||| Erase the given window.
271 | export
272 | erase' : HasIO io => Window -> io ()
273 | erase' (Win win) = primIO $ prim__eraseWindow win
274 |
275 | export
276 | nPutCh : HasIO io => Char -> io ()
277 | nPutCh ch = primIO $ prim__addChar ch
278 |
279 | export
280 | nPutCh' : HasIO io => Window -> Char -> io ()
281 | nPutCh' (Win win) ch = primIO $ prim__addCharWindow win ch
282 |
283 | export
284 | nPutStr : HasIO io => String -> io ()
285 | nPutStr str = primIO $ prim__print "%s" str
286 |
287 | export
288 | nPutStr' : HasIO io => Window -> String -> io ()
289 | nPutStr' (Win win) str = primIO $ prim__printWindow win "%s" str
290 |
291 | export
292 | nPutStrLn : HasIO io => String -> io ()
293 | nPutStrLn str = primIO $ prim__print "%s\n" str
294 |
295 | export
296 | nPutStrLn' : HasIO io => Window -> String -> io ()
297 | nPutStrLn' (Win win) str = primIO $ prim__printWindow win "%s\n" str
298 |
299 | ||| Move the cursor and print to the standard window.
300 | |||
301 | ||| See @nPutStrLnAt'@ to print to a particular window.
302 | export
303 | nPutStrAt : HasIO io => (row : Nat) -> String -> io ()
304 | nPutStrAt row str = primIO $ prim__mvPrint (cast row) 0 "%s" str
305 |
306 | ||| Move the cursor and print to the given window.
307 | export
308 | nPutStrAt' : HasIO io => Window -> (row : Nat) -> String -> io ()
309 | nPutStrAt' (Win win) row str = primIO $ prim__mvPrintWindow win (cast row) 0 "%s" str
310 |
311 | ||| Draw a vertical line comprised of the given character.
312 | export
313 | nVerticalLine : HasIO io => Char -> Nat -> io ()
314 | nVerticalLine ch n = primIO $ prim__verticalLine ch (cast n)
315 |
316 | ||| Draw a vertical line comprised of the given character in
317 | ||| the given window.
318 | export
319 | nVerticalLine' : HasIO io => Window -> Char -> Nat -> io ()
320 | nVerticalLine' (Win win) ch n = primIO $ prim__verticalLineWindow win ch (cast n)
321 |
322 | ||| Draw a horizontal line comprised of the given character.
323 | export
324 | nHorizontalLine : HasIO io => Char -> Nat -> io ()
325 | nHorizontalLine ch n = primIO $ prim__horizontalLine ch (cast n)
326 |
327 | ||| Draw a horizontal line comprised of the given character in
328 | ||| the given window.
329 | export
330 | nHorizontalLine' : HasIO io => Window -> Char -> Nat -> io ()
331 | nHorizontalLine' (Win win) ch n = primIO $ prim__horizontalLineWindow win ch (cast n)
332 |
333 | ||| Border characters can either be the default or they can be specified
334 | ||| by you. There are different defaults for left/right, top/bottom, and corner characters.
335 | public export
336 | data BorderChar = Custom Char | Default
337 |
338 | ||| Draw a border around the given window.
339 | ||| Use the given characters for each edge and corner of the border.
340 | ||| Specify @Default@ for any character for which you want to use the
341 | ||| default.
342 | |||
343 | ||| The border will use the current background/foreground colors.
344 | |||
345 | ||| The border will be drawn _inside_ the given window.
346 | export
347 | nWindowBorder : HasIO io =>
348 |                 Window
349 |              -> (left   : BorderChar)
350 |              -> (right  : BorderChar)
351 |              -> (top    : BorderChar)
352 |              -> (bottom : BorderChar)
353 |              -> (topLeft     : BorderChar)
354 |              -> (topRight    : BorderChar)
355 |              -> (bottomLeft  : BorderChar)
356 |              -> (bottomRight : BorderChar)
357 |              -> io ()
358 | nWindowBorder (Win win) left right top bottom topLeft topRight bottomLeft bottomRight =
359 |   primIO $ prim__borderWindow win (b left) (b right) (b top) (b bottom)
360 |                                   (b topLeft) (b topRight) (b bottomLeft) (b bottomRight)
361 |   where
362 |     b : BorderChar -> Char
363 |     b (Custom ch) = ch
364 |     b Default = (cast 0)
365 |
366 | ||| Draw the default window border for the given window. This is
367 | ||| equivalent to calling @nWindowBorder@ with all border characters
368 | ||| set to @Default@.
369 | export
370 | nDefaultWindowBorder : HasIO io => Window -> io ()
371 | nDefaultWindowBorder win = nWindowBorder win Default Default Default Default
372 |                                              Default Default Default Default
373 |
374 | ||| Move the cursor in the standard window.
375 | export
376 | nMoveCursor : HasIO io => (row : Nat) -> (col : Nat) -> io ()
377 | nMoveCursor row col = primIO $ prim__move (cast row) (cast col)
378 |
379 | ||| Move the cursor in the given window.
380 | export
381 | nMoveCursor' : HasIO io => Window -> (row : Nat) -> (col : Nat) -> io ()
382 | nMoveCursor' (Win win) row col = primIO $ prim__moveInWindow win (cast row) (cast col)
383 |
384 | ||| You must call @initNCurses@ before using the other
385 | ||| ncurses functions and you must call @deinitNCurses@
386 | ||| after you are done (before exiting your program).
387 | |||
388 | ||| You will actually see weird behavior in the shell
389 | ||| post-exit of your program if you have not deinited
390 | ||| ncurses.
391 | export
392 | initNCurses : HasIO io => io ()
393 | initNCurses = primIO $ prim__initScr
394 |
395 | ||| Must be called after @initNCurses@ and before your
396 | ||| program exits.
397 | export
398 | deinitNCurses : HasIO io => io ()
399 | deinitNCurses = primIO $ prim__endWin
400 |
401 |