dotfiles/sbcl/.quicklisp/dists/quicklisp/software/croatoan-20191227-git/ncurses/ncurses.lisp
2020-02-18 14:21:14 -05:00

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)