<commit_before>(in-package :de.anvi.croatoan)

(defun extract-wide-char (window &key y x)
  "Extract and return a wide character (code > 255) from the window.

If the destination coordinates y and x are given, first move the cursor."
  (when (and y x) (move window y x))
  ;; we absolutely need cchar_t here, cchar crashes sbcl.
  (with-foreign-object (ptr '(:struct cchar_t))
    ;; read a struct cchar_t into the space allocated with ptr
    (%win-wch (.winptr window) ptr)
    ;; when we use cchar, the int is dereferenced, cchar_t returns a pointer to the wchar_t array.
    ;; convert-from-foreign returns a plist, then we read the char from the plist using getf
    (let* ((plist (convert-from-foreign ptr '(:struct cchar)))
           (char (getf plist 'cchar-chars))
           (attr (getf plist 'cchar-attr)))
      (make-instance 'complex-char
                     :simple-char (code-char char)
                     :attributes (loop for i in *valid-attributes* if (logtest attr (get-bitmask i)) collect i)
                     ;; first get the color attribute bits by log-AND-ing them with ch.
                     ;; then right shift them by 8 to extract the color int from them.
                     ;; then get the color pair (:white :black) associated with that number.
                     :color-pair (number->pair (ash (logand attr (get-bitmask :color)) -8))))))

;; http://stackoverflow.com/questions/30198550/extracting-wide-chars-w-attributes-in-ncurses<commit_msg>Refactor extract-wide-char to avoid using plists<commit_after>(in-package :de.anvi.croatoan)

(defun extract-wide-char (window &key y x)
  "Extract and return a single (complex) character from the window.

This includes wide characters (code > 255), and requires the ncursesw library.

If the destination coordinates y and x are given, move the cursor first."
  (when (and y x) (move window y x))
  (with-foreign-object (ptr '(:struct cchar_t))
    ;; read a struct cchar_t into the space allocated with ptr
    (%win-wch (.winptr window) ptr)
    ;; the slot cchar-chars is a a pointer to the wchar_t array.
    (let* ((char (mem-aref (foreign-slot-pointer ptr '(:struct cchar_t) 'cchar-chars) 'wchar_t 0))
           ;; the color pair is not placed into the cchar_t slot ext_color, but ORed into the attribute int.
           ;;(col (foreign-slot-value ptr '(:struct cchar_t) 'cchar-colors))
           (attr (foreign-slot-value ptr '(:struct cchar_t) 'cchar-attr)))
      (make-instance 'complex-char
                     :simple-char (code-char char)
                     :attributes (chtype2attrs attr)
                     :color-pair (chtype2colors attr) ))))
{'fraction_non_alphanumeric': 0.10671191553544494, 'fraction_numerical': 0.007164404223227752, 'mean_word_length': 2.741889985895628, 'pattern_counts': {'":': 0, '<': 3, '<?xml version=': 0, '>': 6, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '4075265', 'n_tokens_mistral': 825, 'n_tokens_neox': 780, 'n_words': 305}