lispgames / cl-sdl2

Common Lisp bindings for SDL2 using C2FFI.
MIT License
304 stars 82 forks source link

sdl2:with-event-loop does not behave correctly with text input events #137

Closed Joh11 closed 2 years ago

Joh11 commented 3 years ago

According to the docs, the text field of the text input event is an array[32] of char, while the with-event-loop macro assumes it is a single value, and returns only the first char.

This works for most ASCII chars, but breaks for anything UTF-8. A simple workaround would be this:

(defun convert-text-event (event)
  (sb-ext:octets-to-string
   (loop with arr = (make-array 32 :element-type '(unsigned-byte 8))
     for i below 32 do
       (let ((n (mod (plus-c:c-ref event sdl2-ffi:sdl-event
                       :text :text i)
             256)))
         (if (= 0 n)
         (return (subseq arr 0 i))
         (setf (aref arr i) n)))
     finally (return arr))))

(defun main ()
  (sdl2:with-init (:video)
    (sdl2:with-window (win)
      (sdl2:with-renderer (render win)
    (sdl2:start-text-input)

    (loop with continue = t while continue do
      (sdl2:with-sdl-event (event)
        (loop as more-eventsp = (sdl2:next-event event)
          until (= 0 more-eventsp) do
            (let ((event-type (sdl2:get-event-type event)))
              (case event-type
            (:quit (setf continue nil))
            (:textinput
             (print (convert-text-event event))
             (finish-output)))))
        (clear-and-present render)))))))

I would be happy to make a PR with this, however this implies choosing a portable array of char -> Lisp string decoder, other than sb-ext:octets-to-strings.

VitoVan commented 2 years ago

I have made a PR for this:

https://github.com/lispgames/cl-sdl2/pull/145