|
1 |
| -use crate::sys; |
| 1 | +use crate::{locale::Locale, sys}; |
2 | 2 | use libc::c_char;
|
3 | 3 | use std::ffi::{CStr, CString};
|
4 | 4 |
|
5 | 5 | const VIDEO_MINIMIZE_ON_FOCUS_LOSS: &str = "SDL_VIDEO_MINIMIZE_ON_FOCUS_LOSS";
|
| 6 | +const PREFERRED_LOCALES: &str = "SDL_PREFERRED_LOCALES"; |
6 | 7 |
|
7 | 8 | pub enum Hint {
|
8 | 9 | Default,
|
@@ -74,6 +75,44 @@ pub fn get_video_minimize_on_focus_loss() -> bool {
|
74 | 75 | )
|
75 | 76 | }
|
76 | 77 |
|
| 78 | +/// A hint that overrides the user's locale settings. |
| 79 | +/// |
| 80 | +/// [Official SDL documentation](https://wiki.libsdl.org/SDL2/SDL_HINT_PREFERRED_LOCALES) |
| 81 | +/// |
| 82 | +/// # Default |
| 83 | +/// This is disabled by default. |
| 84 | +/// |
| 85 | +/// # Example |
| 86 | +/// |
| 87 | +/// See [`crate::locale::get_preferred_locales`]. |
| 88 | +pub fn set_preferred_locales<T: std::borrow::Borrow<Locale>>( |
| 89 | + locales: impl IntoIterator<Item = T>, |
| 90 | +) -> bool { |
| 91 | + set(PREFERRED_LOCALES, &format_locale_hint(locales)) |
| 92 | +} |
| 93 | + |
| 94 | +fn format_locale_hint<T: std::borrow::Borrow<Locale>>( |
| 95 | + locales: impl IntoIterator<Item = T>, |
| 96 | +) -> String { |
| 97 | + use std::fmt::Write; |
| 98 | + |
| 99 | + let mut iter = locales.into_iter(); |
| 100 | + let (reserve, _) = iter.size_hint(); |
| 101 | + // Assuming that most locales will be of the form "xx_yy", |
| 102 | + // plus 1 char for the comma. |
| 103 | + let mut formatted = String::with_capacity(reserve * 6); |
| 104 | + |
| 105 | + if let Some(first) = iter.next() { |
| 106 | + write!(formatted, "{}", first.borrow()).ok(); |
| 107 | + } |
| 108 | + |
| 109 | + for locale in iter { |
| 110 | + write!(formatted, ",{}", locale.borrow()).ok(); |
| 111 | + } |
| 112 | + |
| 113 | + formatted |
| 114 | +} |
| 115 | + |
77 | 116 | #[doc(alias = "SDL_SetHint")]
|
78 | 117 | pub fn set(name: &str, value: &str) -> bool {
|
79 | 118 | let name = CString::new(name).unwrap();
|
@@ -126,3 +165,52 @@ pub fn set_with_priority(name: &str, value: &str, priority: &Hint) -> bool {
|
126 | 165 | ) == sys::SDL_bool::SDL_TRUE
|
127 | 166 | }
|
128 | 167 | }
|
| 168 | + |
| 169 | +#[cfg(test)] |
| 170 | +mod test { |
| 171 | + use super::*; |
| 172 | + |
| 173 | + #[test] |
| 174 | + fn locale() { |
| 175 | + // Test set_preferred_locales |
| 176 | + let locales = [Locale { |
| 177 | + lang: "en".to_string(), |
| 178 | + country: Some("US".to_string()), |
| 179 | + }]; |
| 180 | + set_preferred_locales(&locales); |
| 181 | + set_preferred_locales(locales); |
| 182 | + |
| 183 | + // Test hint formatting |
| 184 | + assert_eq!(format_locale_hint(&[]), ""); |
| 185 | + |
| 186 | + assert_eq!( |
| 187 | + format_locale_hint([Locale { |
| 188 | + lang: "en".to_string(), |
| 189 | + country: None, |
| 190 | + }]), |
| 191 | + "en" |
| 192 | + ); |
| 193 | + |
| 194 | + assert_eq!( |
| 195 | + format_locale_hint([Locale { |
| 196 | + lang: "en".to_string(), |
| 197 | + country: Some("US".to_string()), |
| 198 | + }]), |
| 199 | + "en_US" |
| 200 | + ); |
| 201 | + |
| 202 | + assert_eq!( |
| 203 | + format_locale_hint([ |
| 204 | + Locale { |
| 205 | + lang: "en".to_string(), |
| 206 | + country: Some("US".to_string()), |
| 207 | + }, |
| 208 | + Locale { |
| 209 | + lang: "fr".to_string(), |
| 210 | + country: Some("FR".to_string()), |
| 211 | + }, |
| 212 | + ]), |
| 213 | + "en_US,fr_FR" |
| 214 | + ); |
| 215 | + } |
| 216 | +} |
0 commit comments