213 lines
6.8 KiB
Common Lisp
213 lines
6.8 KiB
Common Lisp
(in-package :de.anvi.ncurses)
|
|
|
|
;;; ncurses
|
|
;;; CRT screen handling and optimization package
|
|
;;; http://invisible-island.net/ncurses/man/ncurses.3x.html
|
|
|
|
;; The wide multi-byte library is preferred and will be loaded when the underlying lisp system supports unicode.
|
|
#+(or sb-unicode unicode openmcl-unicode-strings)
|
|
(define-foreign-library libncursesw
|
|
(:darwin (:or "libncursesw.6.dylib" "libncursesw.5.dylib" "libncursesw.dylib" "libcurses.dylib"))
|
|
(:unix (:or "libncursesw.so.6.1" "libncursesw.so.6.0" "libncursesw.so.6" "libncursesw.so.5.9" "libncursesw.so.5" "libncursesw.so"))
|
|
(t (:default "libncursesw")))
|
|
|
|
#+(or sb-unicode unicode openmcl-unicode-strings)
|
|
(use-foreign-library libncursesw)
|
|
|
|
;; Attempt to use the legacy single-byte library only when the lisp implementation doesnt support unicode.
|
|
#-(or sb-unicode unicode openmcl-unicode-strings)
|
|
(define-foreign-library libncurses
|
|
(:darwin (:or "libncurses.6.dylib" "libncurses.5.dylib" "libncurses.dylib" "libcurses.dylib"))
|
|
(:unix (:or "libncurses.so.6.1" "libncurses.so.6.0" "libncurses.so.6" "libncurses.so.5.9" "libncurses.so.5" "libncurses.so"))
|
|
(t (:default "libncurses")))
|
|
|
|
#-(or sb-unicode unicode openmcl-unicode-strings)
|
|
(use-foreign-library libncurses)
|
|
|
|
;;; ------------------------------------------------------------------
|
|
|
|
;; Every function that can take a win, should take a win.
|
|
;; We dont want functions that implicitly operate on a global stdscr.
|
|
|
|
;; Function should return lisp-style bools, not C type int 0 or 1.
|
|
;; cffi automatically does this conversion.
|
|
|
|
;;; ------------------------------------------------------------------
|
|
|
|
;; General ncurses library implementation info:
|
|
|
|
;; data types:
|
|
|
|
;; http://pubs.opengroup.org/onlinepubs/7908799/xcurses/curses.h.html
|
|
;; http://pubs.opengroup.org/onlinepubs/7908799/xcurses/implement.html
|
|
;; http://pubs.opengroup.org/onlinepubs/7908799/cursesix.html
|
|
|
|
;; http://refspecs.linuxbase.org/LSB_3.0.0/LSB-Core-generic/LSB-Core-generic/libncurses.html
|
|
;; http://refspecs.linuxbase.org/LSB_3.0.0/LSB-Core-generic/LSB-Core-generic/libncurses-ddefs.html
|
|
|
|
;; http://h71000.www7.hp.com/doc/83final/5763/5763pro_016.html
|
|
|
|
;; http://docs.python.org/release/2.4.3/lib/curses-window-objects.html
|
|
|
|
;; http://web.ist.utl.pt/tiago.dionizio/lua/lcurses.html
|
|
|
|
;;; ------------------------------------------------------------------
|
|
|
|
;;; Types
|
|
|
|
;; Basic types as seen in the ncurses function prototypes.
|
|
;; These will only be used inside cffi wrappers.
|
|
|
|
;; not used, cffi automatically translates a boolean type
|
|
;; typedef unsigned char bool;
|
|
(defctype bool :unsigned-char)
|
|
|
|
#|
|
|
--enable-lp64
|
|
Allows an application to define _LP64 to declare chtype and mmask_t as
|
|
simply unsigned rather than the configured types
|
|
using the --with-chtype and --with-mmask_t options.
|
|
|
|
#if 1 && defined(_LP64)
|
|
typedef unsigned chtype;
|
|
typedef unsigned mmask_t;
|
|
#else
|
|
typedef uint32_t chtype;
|
|
typedef uint32_t mmask_t;
|
|
#endif
|
|
|#
|
|
|
|
;; default ubuntu build options, they build for API5.
|
|
;; --disable-lp64 --with-chtype='long' --with-mmask-t='long'
|
|
|
|
;; the default type on ubuntu isnt "unsigned int" but "long", which means signed long.
|
|
|
|
;; We will use the ABI6 default uint32_t instead of long.
|
|
|
|
;; TODO: use ABI6 values for chtype, cchar_t and mmask: --with-chtype=uint32_t
|
|
;;(defctype chtype :unsigned-int)
|
|
(defctype chtype :uint32)
|
|
|
|
;; wide character type, defined in:
|
|
;; /usr/lib/gcc/x86_64-linux-gnu/5/include/stddef.h
|
|
;; it has to be able to contain the 21-bit 10FFFF, which is the max allowed unicode point.
|
|
(defctype wchar_t :int32)
|
|
|
|
;; typedef unsigned int wint_t;
|
|
;; used in get_wch.lisp
|
|
;; wint_t needs to be a signed int to represent a negative WEOF value.
|
|
(defctype wint_t :int32)
|
|
|
|
;; typedef chtype attr_t;
|
|
;; TODO: rename this to attr_t
|
|
(defctype attr :uint32
|
|
"The 32 bit integral type attr_t holds an OR-ed set of attributes.")
|
|
(defctype attr_t :uint32
|
|
"The 32 bit integral type attr_t holds an OR-ed set of attributes.")
|
|
|
|
;; winptr = *WINDOW
|
|
;; TODO: define window struct
|
|
;; (defctype ptr-window (:pointer (:struct window)))
|
|
(defctype window :pointer)
|
|
|
|
;; scrptr = *SCREEN
|
|
(defctype screen :pointer)
|
|
|
|
;; fileptr = *FILE
|
|
(defctype file :pointer)
|
|
|
|
;;; C structures
|
|
|
|
#|
|
|
|
|
Excerpt from /usr/include/ncurses.h
|
|
|
|
/*
|
|
* cchar_t stores an array of CCHARW_MAX wide characters. The first is
|
|
* normally a spacing character. The others are non-spacing. If those
|
|
* (spacing and nonspacing) do not fill the array, a null L'\0' follows.
|
|
* Otherwise, a null is assumed to follow when extracting via getcchar().
|
|
*/
|
|
#define CCHARW_MAX 5
|
|
typedef struct
|
|
{
|
|
attr_t attr;
|
|
wchar_t chars[CCHARW_MAX];
|
|
#if 0
|
|
#undef NCURSES_EXT_COLORS
|
|
#define NCURSES_EXT_COLORS 20110404
|
|
int ext_color; /* color pair, must be more than 16-bits */
|
|
#endif
|
|
}
|
|
cchar_t;
|
|
|
|
|#
|
|
|
|
;; For non-extended colors, the color pair is OR-ed into the attr value, like it has been done
|
|
;; with color pairs in chtypes. This is ABI5.
|
|
|
|
;;(defcstruct cchar_t
|
|
;; "A C struct containing contains a wide char and an integer containing the color pair and attributes."
|
|
;; (cchar-attr attr)
|
|
;; (cchar-chars wchar_t :count 5))
|
|
|
|
;; For extended colors, we get a new struct slot. This is ABI6, which is the default since ncurses 6.0, 20150808.
|
|
|
|
;; Intended to be used with setcchar.
|
|
;; TODO: write meaningsful docstrings here.
|
|
(defcstruct cchar_t
|
|
"C struct containing a wide char, a color pair and attributes."
|
|
(cchar-attr attr_t)
|
|
(cchar-chars wchar_t :count 5)
|
|
(cchar-colors :int))
|
|
|
|
(defctype ptr-cchar_t (:pointer (:struct cchar_t)))
|
|
|
|
;; Intended to be used with convert-to-foreign plist translation.
|
|
;; For some reasons, plists with pointers dont work, so we have to pass by value.
|
|
;; TODO: we dont need this any more, everything works now with the cchar_t struct.
|
|
(defcstruct cchar
|
|
"C struct containing a wide char, a color pair and attributes."
|
|
(cchar-attr attr_t)
|
|
(cchar-chars wchar_t)
|
|
(cchar-colors :int))
|
|
|
|
;; the default on ubuntu 12.04, 16.04 is --enable-ext-colors,
|
|
;; so is probably on debian, so we need to include "int ext_color" by default in
|
|
;; the cchar struct.
|
|
|
|
;; convert-to-foreign and convert-from-foreign do not return structs,
|
|
;; but pointers to structs.
|
|
|
|
;;; mouse.lisp
|
|
|
|
;; typedef unsigned long mmask_t;
|
|
;;
|
|
;; typedef struct {
|
|
;; short id; /* ID to distinguish multiple devices */
|
|
;; int x, y, z; /* event coordinates */
|
|
;; mmask_t bstate; /* button state bits */
|
|
;; } MEVENT;
|
|
|
|
;; TODO: ABI6: --with-mmask_t=uint32_t
|
|
;;(defctype mmask_t :unsigned-int)
|
|
(defctype mmask_t :uint32)
|
|
|
|
(defcstruct mevent
|
|
"C struct containing mouse coordinates and button state."
|
|
(id :short)
|
|
(x :int)
|
|
(y :int)
|
|
(z :int)
|
|
(bstate mmask_t))
|
|
|
|
;;; ------------------------------------------------------------------
|
|
|
|
;;; Constants
|
|
|
|
;; #defines taken from ncurses.h, should not be user visible.
|
|
;; wherever cffi defines a boolean, we can use t and nil instead of TRUE and FALSE.
|
|
;;(defconstant TRUE 1)
|
|
;;(defconstant FALSE 0)
|
|
;;(defconstant ERROR -1)
|
|
;;(defconstant OK 0)
|