Skip to content

Commit 815aa61

Browse files
committed
Still thinking about the filter callbacks...
1 parent fa613c2 commit 815aa61

File tree

1 file changed

+51
-16
lines changed

1 file changed

+51
-16
lines changed

ctru-rs/src/applets/swkbd.rs

Lines changed: 51 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ use ctru_sys::{self, SwkbdState};
88

99
use bitflags::bitflags;
1010
use libc;
11-
use std::ffi::CStr;
11+
use std::ffi::{CStr, CString};
1212
use std::fmt::Display;
1313
use std::iter::once;
1414
use std::str;
@@ -199,10 +199,6 @@ bitflags! {
199199
const BACKSLASH = ctru_sys::SWKBD_FILTER_BACKSLASH;
200200
/// Disallow the use of profanity via Nintendo's profanity filter.
201201
const PROFANITY = ctru_sys::SWKBD_FILTER_PROFANITY;
202-
/// Use a custom callback in order to filter the input.
203-
///
204-
/// TODO: It's currently impossible to setup a custom filter callback.
205-
const CALLBACK = ctru_sys::SWKBD_FILTER_CALLBACK;
206202
}
207203
}
208204

@@ -378,26 +374,52 @@ impl SoftwareKeyboard {
378374
///
379375
/// # Notes
380376
///
381-
/// This function will overwrite any currently set filter configuration.
377+
/// The filter callback will work only for the next time the keyboard is used. After using it once, it must be set again.
378+
///
379+
/// # Example
380+
///
381+
/// ```
382+
/// # let _runner = test_runner::GdbRunner::default();
383+
/// # fn main() {
384+
/// #
385+
/// use ctru::applets::swkbd::{SoftwareKeyboard, CallbackInput};
386+
/// let mut keyboard = SoftwareKeyboard::default();
387+
///
388+
/// keyboard.set_filter_callback(|text| {
389+
/// if text.contains("boo") {
390+
/// println!("Ah, you scared me!");
391+
/// }
392+
///
393+
/// (CallbackResult::Ok, None)
394+
/// });
395+
/// #
396+
/// # }
382397
pub fn set_filter_callback<F>(&mut self, callback: F)
383398
where
384-
F: FnOnce(&str) -> CallbackResult,
399+
F: FnOnce(&str) -> (CallbackResult, Option<CString>),
385400
{
386401
unsafe extern "C" fn internal_callback<F>(
387402
user: *mut libc::c_void,
388-
_pp_message: *mut *const libc::c_char,
403+
pp_message: *mut *const libc::c_char,
389404
text: *const libc::c_char,
390405
_text_size: libc::size_t,
391406
) -> ctru_sys::SwkbdCallbackResult
392407
where
393-
F: FnOnce(&str) -> CallbackResult,
408+
F: FnOnce(&str) -> (CallbackResult, Option<CString>),
394409
{
395410
let closure = Box::from_raw(user as *mut Box<F>);
396411

397412
let text = CStr::from_ptr(text);
398413
let text_slice: &str = text.to_str().unwrap();
399414

400-
closure(text_slice).into()
415+
let result = closure(text_slice);
416+
417+
if let Some(cstr) = result.1 {
418+
*pp_message = cstr.as_ptr();
419+
Box::leak(Box::new(cstr)); // Definitely SHOULD NOT do this, but as far as design goes, it's clean.
420+
}
421+
422+
result.0.into()
401423
}
402424

403425
let boxed_callback = Box::new(Box::new(callback));
@@ -511,10 +533,10 @@ impl SoftwareKeyboard {
511533
/// Set the 2 custom characters to add to the keyboard while using [`Kind::Numpad`].
512534
///
513535
/// These characters will appear in their own buttons right next to the `0` key.
514-
///
536+
///
515537
/// # Notes
516-
///
517-
/// You can set one or both of these keys to `NUL` (value 0) to avoid showing the additional buttons to the user.
538+
///
539+
/// If `None` is passed as either key, that button will not be shown to the user.
518540
///
519541
/// # Example
520542
///
@@ -525,13 +547,26 @@ impl SoftwareKeyboard {
525547
/// use ctru::applets::swkbd::{SoftwareKeyboard, Kind, ButtonConfig};
526548
/// let mut keyboard = SoftwareKeyboard::new(Kind::Numpad, ButtonConfig::LeftRight);
527549
///
528-
/// keyboard.set_numpad_keys(('#', '.'));
550+
/// keyboard.set_numpad_keys(Some('#'), Some('.'));
551+
///
552+
/// // The right numpad key will not be shown.
553+
/// keyboard.set_numpad_keys(Some('!'), None);
529554
/// #
530555
/// # }
531556
#[doc(alias = "swkbdSetNumpadKeys")]
532-
pub fn set_numpad_keys(&mut self, keys: (char, char)) {
557+
pub fn set_numpad_keys(&mut self, left_key: Option<char>, right_key: Option<char>) {
558+
let mut keys = (0, 0);
559+
560+
if let Some(k) = left_key {
561+
keys.0 = k as i32;
562+
}
563+
564+
if let Some(k) = right_key {
565+
keys.1 = k as i32;
566+
}
567+
533568
unsafe {
534-
ctru_sys::swkbdSetNumpadKeys(self.state.as_mut(), keys.0 as i32, keys.1 as i32);
569+
ctru_sys::swkbdSetNumpadKeys(self.state.as_mut(), keys.0, keys.1);
535570
}
536571
}
537572

0 commit comments

Comments
 (0)