|
|
@ -5,10 +5,10 @@ |
|
|
|
|
|
|
|
|
|
|
|
use crate::services::{apt::Apt, gfx::Gfx}; |
|
|
|
use crate::services::{apt::Apt, gfx::Gfx}; |
|
|
|
use ctru_sys::{ |
|
|
|
use ctru_sys::{ |
|
|
|
self, aptLaunchLibraryApplet, aptSetMessageCallback, envGetAptAppId, svcBreak, svcCloseHandle, |
|
|
|
self, aptLaunchLibraryApplet, aptSetMessageCallback, envGetAptAppId, svcCloseHandle, |
|
|
|
svcCreateMemoryBlock, APT_SendParameter, SwkbdButton, SwkbdDictWord, SwkbdExtra, |
|
|
|
svcCreateMemoryBlock, APT_SendParameter, SwkbdButton, SwkbdDictWord, SwkbdExtra, |
|
|
|
SwkbdLearningData, SwkbdState, SwkbdStatusData, APPID_SOFTWARE_KEYBOARD, APTCMD_MESSAGE, |
|
|
|
SwkbdLearningData, SwkbdState, SwkbdStatusData, APPID_SOFTWARE_KEYBOARD, APTCMD_MESSAGE, |
|
|
|
NS_APPID, SWKBD_CALLBACK_OK, USERBREAK_PANIC, |
|
|
|
NS_APPID, SWKBD_CALLBACK_OK, |
|
|
|
}; |
|
|
|
}; |
|
|
|
|
|
|
|
|
|
|
|
use bitflags::bitflags; |
|
|
|
use bitflags::bitflags; |
|
|
@ -281,7 +281,7 @@ impl SoftwareKeyboard { |
|
|
|
(self as *mut Self).cast(), |
|
|
|
(self as *mut Self).cast(), |
|
|
|
); |
|
|
|
); |
|
|
|
|
|
|
|
|
|
|
|
match Self::swkbd_input_text(self.state.as_mut(), output.as_mut_vec()) { |
|
|
|
match Self::swkbd_input_text(self.state.as_mut(), &mut output) { |
|
|
|
ctru_sys::SWKBD_BUTTON_NONE => Err(self.state.result.into()), |
|
|
|
ctru_sys::SWKBD_BUTTON_NONE => Err(self.state.result.into()), |
|
|
|
ctru_sys::SWKBD_BUTTON_LEFT => Ok((output, Button::Left)), |
|
|
|
ctru_sys::SWKBD_BUTTON_LEFT => Ok((output, Button::Left)), |
|
|
|
ctru_sys::SWKBD_BUTTON_MIDDLE => Ok((output, Button::Middle)), |
|
|
|
ctru_sys::SWKBD_BUTTON_MIDDLE => Ok((output, Button::Middle)), |
|
|
@ -631,7 +631,7 @@ impl SoftwareKeyboard { |
|
|
|
// A reimplementation of `swkbdInputText` from `libctru/source/applets/swkbd.c`. Allows us to
|
|
|
|
// A reimplementation of `swkbdInputText` from `libctru/source/applets/swkbd.c`. Allows us to
|
|
|
|
// get text from the software keyboard and put it directly into a `String` without requiring
|
|
|
|
// get text from the software keyboard and put it directly into a `String` without requiring
|
|
|
|
// an intermediate fixed-size buffer
|
|
|
|
// an intermediate fixed-size buffer
|
|
|
|
fn swkbd_input_text(swkbd: &mut SwkbdState, buf: &mut Vec<u8>) -> SwkbdButton { |
|
|
|
fn swkbd_input_text(swkbd: &mut SwkbdState, output: &mut String) -> SwkbdButton { |
|
|
|
use ctru_sys::{ |
|
|
|
use ctru_sys::{ |
|
|
|
MEMPERM_READ, MEMPERM_WRITE, R_FAILED, SWKBD_BUTTON_LEFT, SWKBD_BUTTON_MIDDLE, |
|
|
|
MEMPERM_READ, MEMPERM_WRITE, R_FAILED, SWKBD_BUTTON_LEFT, SWKBD_BUTTON_MIDDLE, |
|
|
|
SWKBD_BUTTON_NONE, SWKBD_BUTTON_RIGHT, SWKBD_D0_CLICK, SWKBD_D1_CLICK0, |
|
|
|
SWKBD_BUTTON_NONE, SWKBD_BUTTON_RIGHT, SWKBD_D0_CLICK, SWKBD_D1_CLICK0, |
|
|
@ -715,10 +715,10 @@ impl SoftwareKeyboard { |
|
|
|
swkbd.initial_text_offset = 0; |
|
|
|
swkbd.initial_text_offset = 0; |
|
|
|
|
|
|
|
|
|
|
|
unsafe { |
|
|
|
unsafe { |
|
|
|
let utf16_iter = CStr::from_ptr(extra.initial_text) |
|
|
|
let utf16_iter = |
|
|
|
.to_str() |
|
|
|
str::from_utf8_unchecked(CStr::from_ptr(extra.initial_text).to_bytes()) |
|
|
|
.unwrap() |
|
|
|
|
|
|
|
.encode_utf16() |
|
|
|
.encode_utf16() |
|
|
|
|
|
|
|
.take(swkbd.max_text_len as _) |
|
|
|
.chain(once(0)); |
|
|
|
.chain(once(0)); |
|
|
|
|
|
|
|
|
|
|
|
let mut initial_text_cursor = SWKBD_SHARED_MEM.cast::<u16>(); |
|
|
|
let mut initial_text_cursor = SWKBD_SHARED_MEM.cast::<u16>(); |
|
|
@ -803,17 +803,16 @@ impl SoftwareKeyboard { |
|
|
|
|
|
|
|
|
|
|
|
let text16 = if swkbd.text_length > 0 { |
|
|
|
let text16 = if swkbd.text_length > 0 { |
|
|
|
unsafe { |
|
|
|
unsafe { |
|
|
|
widestring::Utf16Str::from_slice(std::slice::from_raw_parts( |
|
|
|
widestring::Utf16Str::from_slice_unchecked(std::slice::from_raw_parts( |
|
|
|
SWKBD_SHARED_MEM.add(swkbd.text_offset as _).cast::<u16>(), |
|
|
|
SWKBD_SHARED_MEM.add(swkbd.text_offset as _).cast::<u16>(), |
|
|
|
swkbd.text_length as usize, |
|
|
|
swkbd.text_length as usize, |
|
|
|
)) |
|
|
|
)) |
|
|
|
.unwrap() |
|
|
|
|
|
|
|
} |
|
|
|
} |
|
|
|
} else { |
|
|
|
} else { |
|
|
|
widestring::utf16str!("") |
|
|
|
widestring::utf16str!("") |
|
|
|
}; |
|
|
|
}; |
|
|
|
|
|
|
|
|
|
|
|
buf.extend(text16.encode_utf8()); |
|
|
|
*output = text16.to_string(); |
|
|
|
|
|
|
|
|
|
|
|
if swkbd.save_state_flags & (1 << 0) != 0 { |
|
|
|
if swkbd.save_state_flags & (1 << 0) != 0 { |
|
|
|
unsafe { |
|
|
|
unsafe { |
|
|
@ -860,20 +859,13 @@ impl SoftwareKeyboard { |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
let text16 = unsafe { |
|
|
|
let text16 = unsafe { |
|
|
|
widestring::Utf16Str::from_slice(std::slice::from_raw_parts( |
|
|
|
widestring::Utf16Str::from_slice_unchecked(std::slice::from_raw_parts( |
|
|
|
SWKBD_SHARED_MEM.add(swkbd.text_offset as _).cast::<u16>(), |
|
|
|
SWKBD_SHARED_MEM.add(swkbd.text_offset as _).cast::<u16>(), |
|
|
|
swkbd.text_length as usize + 1, |
|
|
|
swkbd.text_length as usize + 1, |
|
|
|
)) |
|
|
|
)) |
|
|
|
.unwrap() |
|
|
|
|
|
|
|
}; |
|
|
|
}; |
|
|
|
|
|
|
|
|
|
|
|
let text8 = match String::from_utf8(text16.encode_utf8().collect()) { |
|
|
|
let text8 = text16.to_string(); |
|
|
|
Ok(s) => s, |
|
|
|
|
|
|
|
Err(_) => { |
|
|
|
|
|
|
|
svcBreak(USERBREAK_PANIC); |
|
|
|
|
|
|
|
unreachable!(); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
}; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
let mut retmsg = std::ptr::null(); |
|
|
|
let mut retmsg = std::ptr::null(); |
|
|
|
|
|
|
|
|
|
|
|