1use alloc::{string::String, vec::Vec};
3use rt::sync::SpinLock;
4#[derive(Clone, Default, PartialEq, Eq)]
5pub struct Preedit { pub text: String, pub cursor: usize }
6static PREEDIT: SpinLock<Vec<(u8,Preedit)>> = SpinLock::new(Vec::new());
7static COMMITS: SpinLock<(u32,Vec<(u32,String)>)> = SpinLock::new((0,Vec::new()));
8pub fn ime_commit_set(win:u8,text:&str) -> bool {
10 if win as usize>=crate::PW_MAX || text.len()>4096 { return false; }
11 if text.is_empty() { return true; }
12 let mut q=COMMITS.lock();
13 if q.1.len()>=16 { return false; }
15 q.0=q.0.wrapping_add(1); let token=q.0;
16 q.1.push((token,String::from(text)));
17 if crate::evq_push(crate::Event {typ:crate::E_IME_COMMIT,win,data:token,..Default::default()}) { true }
18 else { q.1.pop(); false }
19}
20pub fn ime_commit_text(win:u8,text:&str) -> usize {
24 let mut at=0;
25 while at<text.len() {
26 let mut end=(at+4096).min(text.len());
27 while !text.is_char_boundary(end) { end-=1; }
28 if !ime_commit_set(win,&text[at..end]) { break; }
29 at=end;
30 }
31 at
32}
33pub fn ime_commit_take(token:u32) -> Option<String> {
34 let mut q=COMMITS.lock(); let i=q.1.iter().position(|v|v.0==token)?; Some(q.1.remove(i).1)
35}
36pub fn ime_preedit(win: u8) -> Preedit { PREEDIT.lock().iter().find(|v| v.0==win).map_or_else(Default::default,|v| v.1.clone()) }
37pub fn ime_preedit_set(win: u8, text: &str, cursor: usize) {
39 if win as usize >= crate::PW_MAX { return; }
40 let value=if text.len()<=4096 && text.is_char_boundary(cursor.min(text.len())) { Preedit { text:String::from(text),cursor:cursor.min(text.len()) } } else { Preedit::default() };
41 let mut slots=PREEDIT.lock();
42 if let Some(slot)=slots.iter_mut().find(|v| v.0==win) { slot.1=value; } else { slots.push((win,value)); }
43 drop(slots);
44 crate::evq_push(crate::Event { typ:crate::E_PREEDIT,win,..Default::default() });
45}