1use crate::{
2 prelude::{FltkError, FltkErrorKind},
3 utils::FlString,
4};
5use fltk_sys::prefs::*;
6use std::ffi::{CStr, CString};
7use std::os::raw::c_char;
8
9bitflags::bitflags! {
10 #[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
12 pub struct Root: i32 {
13 const UNKNOWN_ROOT_TYPE = -1;
15 #[doc(hidden)]
17 const SYSTEM = 0;
18 #[doc(hidden)]
20 const USER = 1;
21 const MEMORY = 2;
23 const ROOT_MASK = 0x00FF;
25 const CORE = 0x0100;
27 const C_LOCALE = 0x1000;
29 const SYSTEM_L = Root::SYSTEM.bits() | Root::C_LOCALE.bits();
32 const USER_L = Root::USER.bits() | Root::C_LOCALE.bits();
34 const CORE_SYSTEM_L = Root::CORE.bits() | Root::SYSTEM_L.bits();
36 const CORE_USER_L = Root::CORE.bits() | Root::USER_L.bits();
38 }
43}
44
45bitflags::bitflags! {
46 #[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
48 pub struct FileAccess: u32 {
49 const NONE = 0x0000;
51 const USER_READ_OK = 0x0001;
53 const USER_WRITE_OK = 0x0002;
55 const USER_OK = FileAccess::USER_READ_OK.bits() | FileAccess::USER_WRITE_OK.bits();
57 const SYSTEM_READ_OK = 0x0004;
59 const SYSTEM_WRITE_OK = 0x0008;
61 const SYSTEM_OK = FileAccess::SYSTEM_READ_OK.bits() | FileAccess::SYSTEM_WRITE_OK.bits();
63 const APP_OK = FileAccess::SYSTEM_OK.bits() | FileAccess::USER_OK.bits();
65 const CORE_READ_OK = 0x0010;
67 const CORE_WRITE_OK = 0x0020;
69 const CORE_OK = FileAccess::CORE_READ_OK.bits() | FileAccess::CORE_WRITE_OK.bits();
71 const ALL_READ_OK = FileAccess::USER_READ_OK.bits() | FileAccess::SYSTEM_READ_OK.bits() | FileAccess::CORE_READ_OK.bits();
73 const ALL_WRITE_OK = FileAccess::USER_WRITE_OK.bits() | FileAccess::SYSTEM_WRITE_OK.bits() | FileAccess::CORE_WRITE_OK.bits();
75 const ALL = FileAccess::ALL_READ_OK.bits() | FileAccess::ALL_WRITE_OK.bits();
77 }
78}
79
80#[derive(Debug)]
82pub struct Preferences {
83 inner: *mut Fl_Preferences,
84}
85
86impl Drop for Preferences {
87 fn drop(&mut self) {
88 unsafe { Fl_Preferences_delete(self.inner) }
89 }
90}
91
92impl Clone for Preferences {
93 fn clone(&self) -> Self {
94 let inner = unsafe { Fl_Preferences_copy(self.inner) };
95 assert!(!inner.is_null());
96 Self { inner }
97 }
98}
99
100impl Preferences {
101 pub fn set_file_access(flags: FileAccess) {
103 unsafe { Fl_Preferences_set_file_access(flags.bits()) }
104 }
105
106 pub fn file_access() -> FileAccess {
108 let ret = unsafe { Fl_Preferences_file_access() };
109 FileAccess::from_bits_retain(ret)
110 }
111
112 pub fn new(root: Root, vendor: &str, application: &str) -> Option<Self> {
114 unsafe {
115 let vendor = CString::safe_new(vendor);
116 let application = CString::safe_new(application);
117 let inner = Fl_Preferences_new(root.bits(), vendor.as_ptr(), application.as_ptr());
118 if inner.is_null() {
119 None
120 } else {
121 Some(Self { inner })
122 }
123 }
124 }
125
126 pub fn new_group(parent: &mut Preferences, group: &str) -> Option<Self> {
128 unsafe {
129 let group = CString::safe_new(group);
130 let inner = Fl_Preferences_from_parent_group(parent.inner, group.as_ptr());
131 if inner.is_null() {
132 None
133 } else {
134 Some(Self { inner })
135 }
136 }
137 }
138
139 pub fn path(&self) -> String {
141 unsafe {
142 let path = Fl_Preferences_path(self.inner);
143 CStr::from_ptr(path).to_string_lossy().to_string()
144 }
145 }
146
147 pub fn filename(&self) -> Result<(std::path::PathBuf, Root), FltkError> {
149 unsafe {
150 let mut v: Vec<c_char> = vec![0; 250];
151 let ret = Fl_Preferences_filename(self.inner, v.as_mut_ptr(), 250);
152 if ret == -1 {
153 Err(FltkError::Internal(FltkErrorKind::ResourceNotFound))
154 } else {
155 Ok((
156 std::path::PathBuf::from(
157 CStr::from_ptr(v.as_ptr()).to_string_lossy().to_string(),
158 ),
159 Root::from_bits_retain(ret),
160 ))
161 }
162 }
163 }
164
165 pub fn get_userdata_path(&self) -> Result<std::path::PathBuf, FltkError> {
167 unsafe {
168 let mut v: Vec<c_char> = vec![0; 250];
169 let ret = Fl_Preferences_filename(self.inner, v.as_mut_ptr(), 250);
170 if ret == 0 {
171 Err(FltkError::Internal(FltkErrorKind::ResourceNotFound))
172 } else {
173 Ok(std::path::PathBuf::from(
174 CStr::from_ptr(v.as_ptr()).to_string_lossy().to_string(),
175 ))
176 }
177 }
178 }
179
180 pub fn set_int(&mut self, entry: &str, val: i32) -> Result<(), FltkError> {
182 unsafe {
183 let entry = CString::safe_new(entry);
184 let ret = Fl_Preferences_seti(self.inner, entry.as_ptr(), val);
185 if ret == 0 {
186 Err(FltkError::Unknown(String::from("Failed to set entry")))
187 } else {
188 Ok(())
189 }
190 }
191 }
192
193 pub fn get_int(&mut self, entry: &str) -> Result<i32, FltkError> {
195 unsafe {
196 let entry = CString::safe_new(entry);
197 let mut i = 0;
198 let ret = Fl_Preferences_geti(self.inner, entry.as_ptr(), &mut i, 0);
199 if ret == 0 {
200 Err(FltkError::Unknown(String::from("Failed to get entry")))
201 } else {
202 Ok(i)
203 }
204 }
205 }
206
207 pub fn set_float(&mut self, entry: &str, val: f32) -> Result<(), FltkError> {
209 unsafe {
210 let entry = CString::safe_new(entry);
211 let ret = Fl_Preferences_setf(self.inner, entry.as_ptr(), val);
212 if ret == 0 {
213 Err(FltkError::Unknown(String::from("Failed to set entry")))
214 } else {
215 Ok(())
216 }
217 }
218 }
219
220 pub fn set_float_with_precision(
222 &mut self,
223 entry: &str,
224 val: f32,
225 precision: u16,
226 ) -> Result<(), FltkError> {
227 unsafe {
228 let entry = CString::safe_new(entry);
229 let ret = Fl_Preferences_setfp(self.inner, entry.as_ptr(), val, i32::from(precision));
230 if ret == 0 {
231 Err(FltkError::Unknown(String::from("Failed to set entry")))
232 } else {
233 Ok(())
234 }
235 }
236 }
237
238 pub fn get_float(&mut self, entry: &str) -> Result<f32, FltkError> {
240 unsafe {
241 let entry = CString::safe_new(entry);
242 let mut i = 0.0;
243 let ret = Fl_Preferences_getf(self.inner, entry.as_ptr(), &mut i, 0.0);
244 if ret == 0 {
245 Err(FltkError::Unknown(String::from("Failed to get entry")))
246 } else {
247 Ok(i)
248 }
249 }
250 }
251
252 pub fn set_double(&mut self, entry: &str, val: f64) -> Result<(), FltkError> {
254 unsafe {
255 let entry = CString::safe_new(entry);
256 let ret = Fl_Preferences_setd(self.inner, entry.as_ptr(), val);
257 if ret == 0 {
258 Err(FltkError::Unknown(String::from("Failed to set entry")))
259 } else {
260 Ok(())
261 }
262 }
263 }
264
265 pub fn set_double_with_precision(
267 &mut self,
268 entry: &str,
269 val: f64,
270 precision: u16,
271 ) -> Result<(), FltkError> {
272 unsafe {
273 let entry = CString::safe_new(entry);
274 let ret = Fl_Preferences_setdp(self.inner, entry.as_ptr(), val, i32::from(precision));
275 if ret == 0 {
276 Err(FltkError::Unknown(String::from("Failed to set entry")))
277 } else {
278 Ok(())
279 }
280 }
281 }
282
283 pub fn get_double(&mut self, entry: &str) -> Result<f64, FltkError> {
285 unsafe {
286 let entry = CString::safe_new(entry);
287 let mut i = 0.0;
288 let ret = Fl_Preferences_getd(self.inner, entry.as_ptr(), &mut i, 0.0);
289 if ret == 0 {
290 Err(FltkError::Unknown(String::from("Failed to get entry")))
291 } else {
292 Ok(i)
293 }
294 }
295 }
296
297 pub fn set_str(&mut self, entry: &str, val: &str) -> Result<(), FltkError> {
299 unsafe {
300 let entry = CString::safe_new(entry);
301 let val = CString::safe_new(val);
302 let ret = Fl_Preferences_sets(self.inner, entry.as_ptr(), val.as_ptr());
303 if ret == 0 {
304 Err(FltkError::Unknown(String::from("Failed to set entry")))
305 } else {
306 Ok(())
307 }
308 }
309 }
310
311 pub fn get_str(&mut self, entry: &str) -> Result<String, FltkError> {
313 unsafe {
314 let entry = CString::safe_new(entry);
315 let sz = Fl_Preferences_size(self.inner, entry.as_ptr());
316 let mut val: Vec<c_char> = vec![0; (sz + 1) as usize];
317 let ret = Fl_Preferences_gets(
318 self.inner,
319 entry.as_ptr(),
320 val.as_mut_ptr(),
321 c"".as_ptr() as _,
322 sz + 1,
323 );
324 if ret == 0 {
325 Err(FltkError::Unknown(String::from("Failed to get entry")))
326 } else {
327 Ok(CStr::from_ptr(val.as_ptr()).to_string_lossy().to_string())
328 }
329 }
330 }
331
332 pub fn name(&mut self) -> Option<String> {
334 unsafe {
335 let ptr = Fl_Preferences_name(self.inner);
336 if ptr.is_null() {
337 None
338 } else {
339 Some(CStr::from_ptr(ptr).to_string_lossy().to_string())
340 }
341 }
342 }
343
344 pub fn groups(&mut self) -> i32 {
346 unsafe { Fl_Preferences_groups(self.inner) }
347 }
348
349 pub fn group_exists(&mut self, key: &str) -> bool {
351 unsafe {
352 let key = CString::safe_new(key);
353 Fl_Preferences_group_exists(self.inner, key.as_ptr()) != 0
354 }
355 }
356
357 pub fn delete_group(&mut self, group: &str) -> Result<(), FltkError> {
359 unsafe {
360 let group = CString::safe_new(group);
361 let ret = Fl_Preferences_delete_group(self.inner, group.as_ptr());
362 if ret == 0 {
363 Err(FltkError::Internal(FltkErrorKind::FailedOperation))
364 } else {
365 Ok(())
366 }
367 }
368 }
369
370 pub fn delete_all_groups(&mut self) -> Result<(), FltkError> {
372 unsafe {
373 let ret = Fl_Preferences_delete_all_groups(self.inner);
374 if ret == 0 {
375 Err(FltkError::Internal(FltkErrorKind::FailedOperation))
376 } else {
377 Ok(())
378 }
379 }
380 }
381
382 pub fn entries(&mut self) -> i32 {
384 unsafe { Fl_Preferences_entries(self.inner) }
385 }
386
387 pub fn entry_exists(&mut self, key: &str) -> bool {
389 unsafe {
390 let key = CString::safe_new(key);
391 Fl_Preferences_entry_exists(self.inner, key.as_ptr()) != 0
392 }
393 }
394
395 pub fn delete_entry(&mut self, entry: &str) -> Result<(), FltkError> {
397 unsafe {
398 let entry = CString::safe_new(entry);
399 let ret = Fl_Preferences_delete_entry(self.inner, entry.as_ptr());
400 if ret == 0 {
401 Err(FltkError::Internal(FltkErrorKind::FailedOperation))
402 } else {
403 Ok(())
404 }
405 }
406 }
407
408 pub fn delete_all_entries(&mut self) -> Result<(), FltkError> {
410 unsafe {
411 let ret = Fl_Preferences_delete_all_entries(self.inner);
412 if ret == 0 {
413 Err(FltkError::Internal(FltkErrorKind::FailedOperation))
414 } else {
415 Ok(())
416 }
417 }
418 }
419
420 pub fn clear(&mut self) -> Result<(), FltkError> {
422 unsafe {
423 let ret = Fl_Preferences_clear(self.inner);
424 if ret == 0 {
425 Err(FltkError::Internal(FltkErrorKind::FailedOperation))
426 } else {
427 Ok(())
428 }
429 }
430 }
431}