mirror of
https://github.com/storytold/wordcraft.git
synced 2026-10-27 03:47:09 -06:00
Sonar S1612: pass PoisonError::into_inner instead of a closure (#4102)
Co-authored-by: Claude Sonnet 5.5 <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Sonnet 5.5
parent
01d0c63451
commit
ba7e7293e4
@@ -17,7 +17,7 @@ pub fn discover() -> Discover {
|
||||
static JOBS: std::sync::Mutex<Vec<std::thread::JoinHandle<()>>> = std::sync::Mutex::new(Vec::new());
|
||||
|
||||
pub fn finish_pending_jobs() {
|
||||
let workers = std::mem::take(&mut *JOBS.lock().unwrap_or_else(|poison| poison.into_inner()));
|
||||
let workers = std::mem::take(&mut *JOBS.lock().unwrap_or_else(std::sync::PoisonError::into_inner));
|
||||
for worker in workers {
|
||||
if worker.join().is_err() {
|
||||
log::error!("the print worker stopped unexpectedly during shutdown");
|
||||
@@ -46,7 +46,7 @@ pub fn submit() -> Submit {
|
||||
let _ = sender.send(craft_print::submit(&bytes, &job).map_err(|error| error.to_string()));
|
||||
});
|
||||
if let Ok(worker) = worker {
|
||||
let mut jobs = JOBS.lock().unwrap_or_else(|poison| poison.into_inner());
|
||||
let mut jobs = JOBS.lock().unwrap_or_else(std::sync::PoisonError::into_inner);
|
||||
jobs.retain(|job| !job.is_finished());
|
||||
jobs.push(worker);
|
||||
}
|
||||
|
||||
@@ -1406,7 +1406,7 @@ impl Session {
|
||||
/// [`crate::cmd::protect::Facts`] for the document as it is now, cached per revision.
|
||||
fn protect_facts(&self) -> crate::cmd::protect::Facts {
|
||||
let key = (self.document_id, self.rev, self.author.clone());
|
||||
let mut cache = self.protect_facts.lock().unwrap_or_else(|e| e.into_inner());
|
||||
let mut cache = self.protect_facts.lock().unwrap_or_else(std::sync::PoisonError::into_inner);
|
||||
if let Some((k, f)) = cache.as_ref()
|
||||
&& *k == key
|
||||
{
|
||||
|
||||
+27
-26
@@ -101,10 +101,10 @@ impl FaceRef {
|
||||
pub fn of(face: &Arc<FontFace>) -> FaceRef {
|
||||
static LEAKED: RwLock<Vec<Option<&FontFace>>> = RwLock::new(Vec::new());
|
||||
let id = face.id as usize;
|
||||
if let Some(Some(f)) = LEAKED.read().unwrap_or_else(|e| e.into_inner()).get(id) {
|
||||
if let Some(Some(f)) = LEAKED.read().unwrap_or_else(std::sync::PoisonError::into_inner).get(id) {
|
||||
return FaceRef(f);
|
||||
}
|
||||
let mut w = LEAKED.write().unwrap_or_else(|e| e.into_inner());
|
||||
let mut w = LEAKED.write().unwrap_or_else(std::sync::PoisonError::into_inner);
|
||||
if w.len() <= id {
|
||||
w.resize(id + 1, None);
|
||||
}
|
||||
@@ -1023,11 +1023,11 @@ impl FontDb {
|
||||
pub fn set_system_fallback(&self, on: bool) {
|
||||
#[cfg(not(target_arch = "wasm32"))]
|
||||
{
|
||||
self.sys.lock().unwrap_or_else(|e| e.into_inner()).enabled = on;
|
||||
self.sys.lock().unwrap_or_else(std::sync::PoisonError::into_inner).enabled = on;
|
||||
}
|
||||
// Misses remembered while it was off may be found now.
|
||||
self.fallbacks.write().unwrap_or_else(|e| e.into_inner()).map.clear();
|
||||
*self.run_fallbacks.write().unwrap_or_else(|e| e.into_inner()) = RunFallbackCache::default();
|
||||
self.fallbacks.write().unwrap_or_else(std::sync::PoisonError::into_inner).map.clear();
|
||||
*self.run_fallbacks.write().unwrap_or_else(std::sync::PoisonError::into_inner) = RunFallbackCache::default();
|
||||
#[cfg(target_arch = "wasm32")]
|
||||
let _ = on;
|
||||
}
|
||||
@@ -1041,14 +1041,14 @@ impl FontDb {
|
||||
}
|
||||
|
||||
fn read_faces(&self) -> std::sync::RwLockReadGuard<'_, Vec<Arc<FontFace>>> {
|
||||
self.faces.read().unwrap_or_else(|e| e.into_inner())
|
||||
self.faces.read().unwrap_or_else(std::sync::PoisonError::into_inner)
|
||||
}
|
||||
|
||||
/// The system font catalog, scanned first if it hasn't been yet.
|
||||
#[cfg(not(target_arch = "wasm32"))]
|
||||
fn read_catalog(&self) -> std::sync::RwLockReadGuard<'_, Vec<CatalogEntry>> {
|
||||
self.ensure_catalog();
|
||||
self.catalog.read().unwrap_or_else(|e| e.into_inner())
|
||||
self.catalog.read().unwrap_or_else(std::sync::PoisonError::into_inner)
|
||||
}
|
||||
|
||||
/// Family names available (loaded plus cataloged system fonts), sorted and deduplicated. Like
|
||||
@@ -1184,7 +1184,7 @@ impl FontDb {
|
||||
}
|
||||
}
|
||||
}
|
||||
let mut faces = self.faces.write().unwrap_or_else(|e| e.into_inner());
|
||||
let mut faces = self.faces.write().unwrap_or_else(std::sync::PoisonError::into_inner);
|
||||
let mut added = 0;
|
||||
for f in new {
|
||||
if !faces.iter().any(|g| g.family.eq_ignore_ascii_case(&f.family) && g.style.eq_ignore_ascii_case(&f.style)) {
|
||||
@@ -1263,7 +1263,7 @@ impl FontDb {
|
||||
}
|
||||
let n = found.len();
|
||||
log::debug!("cataloged {n} system font faces");
|
||||
*self.catalog.write().unwrap_or_else(|e| e.into_inner()) = found;
|
||||
*self.catalog.write().unwrap_or_else(std::sync::PoisonError::into_inner) = found;
|
||||
self.catalog_gen.fetch_add(1, Ordering::AcqRel);
|
||||
n
|
||||
}
|
||||
@@ -1273,7 +1273,7 @@ impl FontDb {
|
||||
/// its styles. Returns whether any face was added.
|
||||
#[cfg(not(target_arch = "wasm32"))]
|
||||
fn load_cataloged(&self, family: &str) -> bool {
|
||||
let _loading = self.loading.lock().unwrap_or_else(|e| e.into_inner());
|
||||
let _loading = self.loading.lock().unwrap_or_else(std::sync::PoisonError::into_inner);
|
||||
// Another lookup may have loaded it while this one waited.
|
||||
if self.is_loaded(family) {
|
||||
return true;
|
||||
@@ -1282,7 +1282,7 @@ impl FontDb {
|
||||
let files = paths.iter().filter_map(|p| std::fs::read(p).ok()).map(|b| (b, None)).collect();
|
||||
let added = self.add_fonts(files) > 0;
|
||||
// The fallback searches' index: these files are loaded fonts now.
|
||||
let mut index = self.coverage.lock().unwrap_or_else(|e| e.into_inner());
|
||||
let mut index = self.coverage.lock().unwrap_or_else(std::sync::PoisonError::into_inner);
|
||||
for file in index.files.iter_mut().filter(|f| paths.contains(&f.path)) {
|
||||
file.used = true;
|
||||
}
|
||||
@@ -1471,7 +1471,7 @@ impl FontDb {
|
||||
let mut f = make_face(base.bytes.clone(), base.index, base.family.clone(), style.to_string(), base.legacy_family.clone(), coords)?;
|
||||
f.local_names = base.local_names.clone();
|
||||
let f = Arc::new(f);
|
||||
self.faces.write().unwrap_or_else(|e| e.into_inner()).push(f.clone());
|
||||
self.faces.write().unwrap_or_else(std::sync::PoisonError::into_inner).push(f.clone());
|
||||
Some(f)
|
||||
}
|
||||
|
||||
@@ -1540,7 +1540,7 @@ impl FontDb {
|
||||
fn cached_fallback(&self, c: char, exclude: u32) -> Option<Arc<FontFace>> {
|
||||
let n = self.read_faces().len();
|
||||
{
|
||||
let cache = self.fallbacks.read().unwrap_or_else(|e| e.into_inner());
|
||||
let cache = self.fallbacks.read().unwrap_or_else(std::sync::PoisonError::into_inner);
|
||||
if cache.faces == n
|
||||
&& let Some(hit) = cache.map.get(&(c, exclude))
|
||||
{
|
||||
@@ -1554,7 +1554,7 @@ impl FontDb {
|
||||
if n != self.read_faces().len() {
|
||||
return found;
|
||||
}
|
||||
let mut cache = self.fallbacks.write().unwrap_or_else(|e| e.into_inner());
|
||||
let mut cache = self.fallbacks.write().unwrap_or_else(std::sync::PoisonError::into_inner);
|
||||
if cache.faces != n || cache.map.len() >= FALLBACK_CACHE_MAX {
|
||||
cache.map.clear();
|
||||
cache.faces = n;
|
||||
@@ -1587,7 +1587,7 @@ impl FontDb {
|
||||
}
|
||||
#[cfg(not(target_arch = "wasm32"))]
|
||||
{
|
||||
let enabled = self.sys.lock().unwrap_or_else(|e| e.into_inner()).enabled;
|
||||
let enabled = self.sys.lock().unwrap_or_else(std::sync::PoisonError::into_inner).enabled;
|
||||
if enabled {
|
||||
self.load_cataloged(FAMILY);
|
||||
}
|
||||
@@ -1599,7 +1599,7 @@ impl FontDb {
|
||||
/// one search at a time.
|
||||
#[cfg(not(target_arch = "wasm32"))]
|
||||
fn system_search(&self, c: char, exclude: u32) -> (Option<Arc<FontFace>>, usize) {
|
||||
let _searching = self.searching.lock().unwrap_or_else(|e| e.into_inner());
|
||||
let _searching = self.searching.lock().unwrap_or_else(std::sync::PoisonError::into_inner);
|
||||
// A search that held the lock first may have loaded a font covering `c`: choose among the
|
||||
// loaded faces again before loading more.
|
||||
let (found, n) = self.loaded_fallback(c, exclude);
|
||||
@@ -1660,7 +1660,7 @@ impl FontDb {
|
||||
let key = (set, exclude, bold, italic);
|
||||
let n = self.read_faces().len();
|
||||
{
|
||||
let cache = self.run_fallbacks.read().unwrap_or_else(|e| e.into_inner());
|
||||
let cache = self.run_fallbacks.read().unwrap_or_else(std::sync::PoisonError::into_inner);
|
||||
if cache.faces == n
|
||||
&& let Some(hit) = cache.map.get(&key)
|
||||
{
|
||||
@@ -1671,7 +1671,7 @@ impl FontDb {
|
||||
// meanwhile by another thread (one its search, or a family named by a document) must make
|
||||
// a miss count as stale, not as the answer for the new count.
|
||||
let (found, n) = self.search_run(&key.0, exclude, bold, italic);
|
||||
let mut cache = self.run_fallbacks.write().unwrap_or_else(|e| e.into_inner());
|
||||
let mut cache = self.run_fallbacks.write().unwrap_or_else(std::sync::PoisonError::into_inner);
|
||||
if cache.faces != n || cache.map.len() >= RUN_FALLBACK_CACHE_MAX || cache.chars.saturating_add(key.0.len()) > RUN_FALLBACK_CACHE_CHARS {
|
||||
cache.map.clear();
|
||||
cache.faces = n;
|
||||
@@ -1750,7 +1750,7 @@ impl FontDb {
|
||||
return false;
|
||||
}
|
||||
{
|
||||
let sys = self.sys.lock().unwrap_or_else(|e| e.into_inner());
|
||||
let sys = self.sys.lock().unwrap_or_else(std::sync::PoisonError::into_inner);
|
||||
if !sys.enabled || sys.misses.contains(&c) {
|
||||
return false;
|
||||
}
|
||||
@@ -1764,7 +1764,7 @@ impl FontDb {
|
||||
if self.is_loaded(fam) || !cataloged.iter().any(|f| f.eq_ignore_ascii_case(fam)) {
|
||||
continue;
|
||||
}
|
||||
if !self.sys.lock().unwrap_or_else(|e| e.into_inner()).tried.insert(fam) {
|
||||
if !self.sys.lock().unwrap_or_else(std::sync::PoisonError::into_inner).tried.insert(fam) {
|
||||
continue;
|
||||
}
|
||||
self.load_cataloged(fam);
|
||||
@@ -1775,7 +1775,7 @@ impl FontDb {
|
||||
if self.indexed_fallback(c) {
|
||||
return true;
|
||||
}
|
||||
let mut sys = self.sys.lock().unwrap_or_else(|e| e.into_inner());
|
||||
let mut sys = self.sys.lock().unwrap_or_else(std::sync::PoisonError::into_inner);
|
||||
if sys.misses.len() >= SYS_MISSES_MAX {
|
||||
sys.misses.clear();
|
||||
}
|
||||
@@ -1795,7 +1795,7 @@ impl FontDb {
|
||||
/// before the Regular.
|
||||
#[cfg(not(target_arch = "wasm32"))]
|
||||
fn indexed_run_fallback(&self, chars: &[char]) {
|
||||
if !self.sys.lock().unwrap_or_else(|e| e.into_inner()).enabled || chars.iter().any(|c| c.is_control()) {
|
||||
if !self.sys.lock().unwrap_or_else(std::sync::PoisonError::into_inner).enabled || chars.iter().any(|c| c.is_control()) {
|
||||
return;
|
||||
}
|
||||
self.load_indexed(chars, true);
|
||||
@@ -1811,13 +1811,14 @@ impl FontDb {
|
||||
let covered = |db: &FontDb| db.read_faces().iter().any(|f| chars.iter().all(|c| f.covers(*c)));
|
||||
let cps: Vec<u32> = chars.iter().map(|c| u32::from(*c)).collect();
|
||||
let maps_all = |ranges: &[(u32, u32)]| cps.iter().all(|cp| ranges_hold(ranges, *cp));
|
||||
let mut index = self.coverage.lock().unwrap_or_else(|e| e.into_inner());
|
||||
let mut index = self.coverage.lock().unwrap_or_else(std::sync::PoisonError::into_inner);
|
||||
let generation = self.catalog_gen.load(Ordering::Acquire);
|
||||
if index.generation != Some(generation) {
|
||||
// A new scan (or the first search): keep what is known of files still installed.
|
||||
let mut known: HashMap<std::path::PathBuf, IndexedFile> =
|
||||
std::mem::take(&mut index.files).into_iter().map(|f| (f.path.clone(), f)).collect();
|
||||
let mut paths: Vec<std::path::PathBuf> = self.catalog.read().unwrap_or_else(|e| e.into_inner()).iter().map(|e| e.path.clone()).collect();
|
||||
let mut paths: Vec<std::path::PathBuf> =
|
||||
self.catalog.read().unwrap_or_else(std::sync::PoisonError::into_inner).iter().map(|e| e.path.clone()).collect();
|
||||
paths.sort();
|
||||
paths.dedup();
|
||||
let files = paths
|
||||
@@ -1880,11 +1881,11 @@ impl FontDb {
|
||||
/// Glyph outline in font units, y-down (flipped), cached per (face, glyph).
|
||||
pub fn outline(&self, face: &FontFace, gid: u32) -> Arc<BezPath> {
|
||||
let key = (face.id, gid);
|
||||
if let Some(p) = self.outlines.lock().unwrap_or_else(|e| e.into_inner()).get(&key) {
|
||||
if let Some(p) = self.outlines.lock().unwrap_or_else(std::sync::PoisonError::into_inner).get(&key) {
|
||||
return p.clone();
|
||||
}
|
||||
let p = Arc::new(face.glyph_outline(gid));
|
||||
let mut cache = self.outlines.lock().unwrap_or_else(|e| e.into_inner());
|
||||
let mut cache = self.outlines.lock().unwrap_or_else(std::sync::PoisonError::into_inner);
|
||||
if cache.len() >= OUTLINE_CACHE_MAX {
|
||||
cache.clear();
|
||||
}
|
||||
|
||||
@@ -260,7 +260,7 @@ pub fn parse(b: &[u8]) -> Option<MathTable> {
|
||||
pub fn table(face: &FontFace) -> Option<Arc<MathTable>> {
|
||||
static CACHE: OnceLock<Mutex<HashMap<u32, Option<Arc<MathTable>>>>> = OnceLock::new();
|
||||
let cache = CACHE.get_or_init(|| Mutex::new(HashMap::new()));
|
||||
if let Some(t) = cache.lock().unwrap_or_else(|e| e.into_inner()).get(&face.id()) {
|
||||
if let Some(t) = cache.lock().unwrap_or_else(std::sync::PoisonError::into_inner).get(&face.id()) {
|
||||
return t.clone();
|
||||
}
|
||||
let t = face
|
||||
@@ -268,7 +268,7 @@ pub fn table(face: &FontFace) -> Option<Arc<MathTable>> {
|
||||
.and_then(|f| f.table_data(skrifa::raw::types::Tag::new(b"MATH")).map(|d| d.as_bytes().to_vec()))
|
||||
.and_then(|bytes| parse(&bytes))
|
||||
.map(Arc::new);
|
||||
cache.lock().unwrap_or_else(|e| e.into_inner()).insert(face.id(), t.clone());
|
||||
cache.lock().unwrap_or_else(std::sync::PoisonError::into_inner).insert(face.id(), t.clone());
|
||||
t
|
||||
}
|
||||
|
||||
|
||||
@@ -389,7 +389,7 @@ pub fn resolve(family: &str, bold: bool, italic: bool) -> Resolved {
|
||||
let cacheable = family.len() <= FAMILY_KEY_MAX;
|
||||
let key = (if cacheable { family.to_string() } else { String::new() }, bold, italic);
|
||||
{
|
||||
let mut c = cache.lock().unwrap_or_else(|e| e.into_inner());
|
||||
let mut c = cache.lock().unwrap_or_else(std::sync::PoisonError::into_inner);
|
||||
if c.0 != generation {
|
||||
*c = (generation, HashMap::new());
|
||||
}
|
||||
@@ -409,7 +409,7 @@ pub fn resolve(family: &str, bold: bool, italic: bool) -> Resolved {
|
||||
};
|
||||
let face = db.face(&fam, style_name(bold, italic));
|
||||
let r = Resolved { synth_bold: bold && face.weight < 600.0, synth_italic: italic && !face.italic, substituted, face: FaceRef::of(&face) };
|
||||
let mut c = cache.lock().unwrap_or_else(|e| e.into_inner());
|
||||
let mut c = cache.lock().unwrap_or_else(std::sync::PoisonError::into_inner);
|
||||
if cacheable && c.0 == generation {
|
||||
if c.1.len() >= FAMILY_CACHE_MAX {
|
||||
c.1.clear();
|
||||
@@ -431,7 +431,7 @@ fn hhea_line(ascender: i16, descender: i16, line_gap: i16) -> (f64, f64) {
|
||||
pub fn line_metrics(face: &crate::FontFace) -> (f64, f64) {
|
||||
static CACHE: OnceLock<Mutex<HashMap<u32, (f64, f64)>>> = OnceLock::new();
|
||||
let cache = CACHE.get_or_init(|| Mutex::new(HashMap::new()));
|
||||
if let Some(v) = cache.lock().unwrap_or_else(|e| e.into_inner()).get(&face.id()) {
|
||||
if let Some(v) = cache.lock().unwrap_or_else(std::sync::PoisonError::into_inner).get(&face.id()) {
|
||||
return *v;
|
||||
}
|
||||
let mut v = (face.ascent.max(1.0), face.descent.abs());
|
||||
@@ -447,7 +447,7 @@ pub fn line_metrics(face: &crate::FontFace) -> (f64, f64) {
|
||||
v = m;
|
||||
}
|
||||
}
|
||||
cache.lock().unwrap_or_else(|e| e.into_inner()).insert(face.id(), v);
|
||||
cache.lock().unwrap_or_else(std::sync::PoisonError::into_inner).insert(face.id(), v);
|
||||
v
|
||||
}
|
||||
|
||||
|
||||
@@ -31,11 +31,11 @@ const NAMES: &[&str] = &["cs_CZ", "cs-CZ", "cs"];
|
||||
/// [`install_dictionary`], or an empty one when none is available (Czech spelling is off
|
||||
/// then; see [`has_dictionary`]).
|
||||
pub fn dictionary() -> Arc<AffixDict> {
|
||||
if let Some(d) = DICT.read().unwrap_or_else(|e| e.into_inner()).dict.as_ref() {
|
||||
if let Some(d) = DICT.read().unwrap_or_else(std::sync::PoisonError::into_inner).dict.as_ref() {
|
||||
return d.clone();
|
||||
}
|
||||
let loaded = Arc::new(load_installed());
|
||||
let mut slot = DICT.write().unwrap_or_else(|e| e.into_inner());
|
||||
let mut slot = DICT.write().unwrap_or_else(std::sync::PoisonError::into_inner);
|
||||
// Another thread (or an install) may have filled it meanwhile: that one wins.
|
||||
slot.dict.get_or_insert(loaded).clone()
|
||||
}
|
||||
@@ -56,7 +56,7 @@ fn load_installed() -> AffixDict {
|
||||
/// UTF-8), for example one the user picked. On error the current dictionary stays.
|
||||
pub fn install_dictionary(aff: &str, dic: &str) -> Result<(), String> {
|
||||
let d = AffixDict::from_hunspell(aff, dic, &[])?;
|
||||
let mut slot = DICT.write().unwrap_or_else(|e| e.into_inner());
|
||||
let mut slot = DICT.write().unwrap_or_else(std::sync::PoisonError::into_inner);
|
||||
slot.dict = Some(Arc::new(d));
|
||||
slot.in_memory = true;
|
||||
Ok(())
|
||||
@@ -65,7 +65,7 @@ pub fn install_dictionary(aff: &str, dic: &str) -> Result<(), String> {
|
||||
/// Forget the loaded dictionary, so the next check looks for an installed one again (after
|
||||
/// [`crate::hunspell::set_dictionary_dir`] or a dictionary was installed).
|
||||
pub fn reload_dictionary() {
|
||||
let mut slot = DICT.write().unwrap_or_else(|e| e.into_inner());
|
||||
let mut slot = DICT.write().unwrap_or_else(std::sync::PoisonError::into_inner);
|
||||
slot.dict = None;
|
||||
slot.in_memory = false;
|
||||
}
|
||||
@@ -75,7 +75,7 @@ pub fn reload_dictionary() {
|
||||
/// none. A dictionary given with [`install_dictionary`] has no file and isn't reported, even if a
|
||||
/// matching file also happens to exist.
|
||||
pub fn installed_path() -> Option<std::path::PathBuf> {
|
||||
if DICT.read().unwrap_or_else(|e| e.into_inner()).in_memory {
|
||||
if DICT.read().unwrap_or_else(std::sync::PoisonError::into_inner).in_memory {
|
||||
return None;
|
||||
}
|
||||
crate::hunspell::find(NAMES).map(|(_, dic)| dic)
|
||||
|
||||
@@ -25,11 +25,11 @@ const NAMES: &[&str] = &["hr_HR", "hr-HR", "hr"];
|
||||
/// [`install_dictionary`], or an empty one when none is available (Croatian spelling is off
|
||||
/// then; see [`has_dictionary`]).
|
||||
pub fn dictionary() -> Arc<AffixDict> {
|
||||
if let Some(d) = DICT.read().unwrap_or_else(|e| e.into_inner()).as_ref() {
|
||||
if let Some(d) = DICT.read().unwrap_or_else(std::sync::PoisonError::into_inner).as_ref() {
|
||||
return d.clone();
|
||||
}
|
||||
let loaded = Arc::new(load_installed());
|
||||
let mut slot = DICT.write().unwrap_or_else(|e| e.into_inner());
|
||||
let mut slot = DICT.write().unwrap_or_else(std::sync::PoisonError::into_inner);
|
||||
// Another thread (or an install) may have filled it meanwhile: that one wins.
|
||||
slot.get_or_insert(loaded).clone()
|
||||
}
|
||||
@@ -51,14 +51,14 @@ fn load_installed() -> AffixDict {
|
||||
/// UTF-8), for example one the user picked. On error the current dictionary stays.
|
||||
pub fn install_dictionary(aff: &str, dic: &str) -> Result<(), String> {
|
||||
let d = AffixDict::from_hunspell(aff, dic, &[])?;
|
||||
*DICT.write().unwrap_or_else(|e| e.into_inner()) = Some(Arc::new(d));
|
||||
*DICT.write().unwrap_or_else(std::sync::PoisonError::into_inner) = Some(Arc::new(d));
|
||||
Ok(())
|
||||
}
|
||||
|
||||
/// Forget the loaded dictionary, so the next check looks for an installed one again (after
|
||||
/// [`crate::hunspell::set_dictionary_dir`] or a dictionary was installed).
|
||||
pub fn reload_dictionary() {
|
||||
*DICT.write().unwrap_or_else(|e| e.into_inner()) = None;
|
||||
*DICT.write().unwrap_or_else(std::sync::PoisonError::into_inner) = None;
|
||||
}
|
||||
|
||||
/// The `.dic` file of the Hunspell `hr_HR` dictionary found in the dictionaries folder or the
|
||||
|
||||
@@ -27,7 +27,7 @@ static LOAD_ERRORS: RwLock<Vec<(String, PathBuf, String)>> = RwLock::new(Vec::ne
|
||||
/// Remember (or, for `Ok`, forget) why the dictionary `key` found at `dic` failed to load, and
|
||||
/// hand the result back unchanged.
|
||||
pub fn note_load<T>(key: &str, dic: &Path, result: Result<T, String>) -> Result<T, String> {
|
||||
let mut errors = LOAD_ERRORS.write().unwrap_or_else(|e| e.into_inner());
|
||||
let mut errors = LOAD_ERRORS.write().unwrap_or_else(std::sync::PoisonError::into_inner);
|
||||
errors.retain(|(k, _, _)| k != key);
|
||||
if let Err(e) = &result {
|
||||
errors.push((key.to_string(), dic.to_path_buf(), e.clone()));
|
||||
@@ -37,19 +37,19 @@ pub fn note_load<T>(key: &str, dic: &Path, result: Result<T, String>) -> Result<
|
||||
|
||||
/// Forget the load error of the dictionary `key` (none found, or it is about to be searched for again).
|
||||
pub fn clear_load_error(key: &str) {
|
||||
LOAD_ERRORS.write().unwrap_or_else(|e| e.into_inner()).retain(|(k, _, _)| k != key);
|
||||
LOAD_ERRORS.write().unwrap_or_else(std::sync::PoisonError::into_inner).retain(|(k, _, _)| k != key);
|
||||
}
|
||||
|
||||
/// The `.dic` file and the reason of the last failed load of the dictionary `key`, if any.
|
||||
pub fn load_error(key: &str) -> Option<(PathBuf, String)> {
|
||||
LOAD_ERRORS.read().unwrap_or_else(|e| e.into_inner()).iter().find(|(k, _, _)| k == key).map(|(_, p, e)| (p.clone(), e.clone()))
|
||||
LOAD_ERRORS.read().unwrap_or_else(std::sync::PoisonError::into_inner).iter().find(|(k, _, _)| k == key).map(|(_, p, e)| (p.clone(), e.clone()))
|
||||
}
|
||||
|
||||
/// Search `dir` before the system locations (a "dictionaries folder" setting); `None` clears it.
|
||||
/// Takes effect for dictionaries not loaded yet.
|
||||
pub fn set_dictionary_dir(dir: Option<PathBuf>) {
|
||||
*EXTRA_DIR.write().unwrap_or_else(|e| e.into_inner()) = dir;
|
||||
LOAD_ERRORS.write().unwrap_or_else(|e| e.into_inner()).clear(); // they belong to the old search path
|
||||
*EXTRA_DIR.write().unwrap_or_else(std::sync::PoisonError::into_inner) = dir;
|
||||
LOAD_ERRORS.write().unwrap_or_else(std::sync::PoisonError::into_inner).clear(); // they belong to the old search path
|
||||
}
|
||||
|
||||
/// The LibreOffice extension directories a Hunspell dictionary name may live in: LibreOffice's
|
||||
@@ -67,7 +67,7 @@ fn lo_ext_dirs(name: &str) -> Vec<String> {
|
||||
/// language is being searched for, adds LibreOffice's extension folders for it (`dict-pt-BR`).
|
||||
pub fn search_dirs(lo_exts: Option<&[String]>) -> Vec<PathBuf> {
|
||||
let mut dirs: Vec<PathBuf> = Vec::new();
|
||||
if let Some(d) = EXTRA_DIR.read().unwrap_or_else(|e| e.into_inner()).clone() {
|
||||
if let Some(d) = EXTRA_DIR.read().unwrap_or_else(std::sync::PoisonError::into_inner).clone() {
|
||||
dirs.push(d);
|
||||
}
|
||||
if cfg!(target_arch = "wasm32") {
|
||||
|
||||
@@ -30,11 +30,11 @@ const CLITICS: &[&str] = &["se", "nya", "ku", "mu", "lah", "kah", "pun"];
|
||||
/// [`install_dictionary`], or an empty one when none is available (Indonesian spelling is off
|
||||
/// then; see [`has_dictionary`]).
|
||||
pub fn dictionary() -> Arc<AffixDict> {
|
||||
if let Some(d) = DICT.read().unwrap_or_else(|e| e.into_inner()).as_ref() {
|
||||
if let Some(d) = DICT.read().unwrap_or_else(std::sync::PoisonError::into_inner).as_ref() {
|
||||
return d.clone();
|
||||
}
|
||||
let loaded = Arc::new(load_installed());
|
||||
let mut slot = DICT.write().unwrap_or_else(|e| e.into_inner());
|
||||
let mut slot = DICT.write().unwrap_or_else(std::sync::PoisonError::into_inner);
|
||||
// Another thread (or an install) may have filled it meanwhile: that one wins.
|
||||
slot.get_or_insert(loaded).clone()
|
||||
}
|
||||
@@ -55,14 +55,14 @@ fn load_installed() -> AffixDict {
|
||||
/// UTF-8), for example one the user picked. On error the current dictionary stays.
|
||||
pub fn install_dictionary(aff: &str, dic: &str) -> Result<(), String> {
|
||||
let d = AffixDict::from_hunspell(aff, dic, &[])?;
|
||||
*DICT.write().unwrap_or_else(|e| e.into_inner()) = Some(Arc::new(d));
|
||||
*DICT.write().unwrap_or_else(std::sync::PoisonError::into_inner) = Some(Arc::new(d));
|
||||
Ok(())
|
||||
}
|
||||
|
||||
/// Forget the loaded dictionary, so the next check looks for an installed one again (after
|
||||
/// [`crate::hunspell::set_dictionary_dir`] or a dictionary was installed).
|
||||
pub fn reload_dictionary() {
|
||||
*DICT.write().unwrap_or_else(|e| e.into_inner()) = None;
|
||||
*DICT.write().unwrap_or_else(std::sync::PoisonError::into_inner) = None;
|
||||
}
|
||||
|
||||
/// The `.dic` file of the Hunspell `id_ID` dictionary found in the dictionaries folder or the
|
||||
|
||||
@@ -34,11 +34,11 @@ const NAMES: &[&str] = &["it_IT", "it_CH", "it-IT", "it"];
|
||||
/// [`install_dictionary`], or an empty one when none is available (Italian spelling is off
|
||||
/// then; see [`has_dictionary`]).
|
||||
pub fn dictionary() -> Arc<AffixDict> {
|
||||
if let Some(d) = DICT.read().unwrap_or_else(|e| e.into_inner()).as_ref() {
|
||||
if let Some(d) = DICT.read().unwrap_or_else(std::sync::PoisonError::into_inner).as_ref() {
|
||||
return d.clone();
|
||||
}
|
||||
let loaded = Arc::new(load_installed());
|
||||
let mut slot = DICT.write().unwrap_or_else(|e| e.into_inner());
|
||||
let mut slot = DICT.write().unwrap_or_else(std::sync::PoisonError::into_inner);
|
||||
// Another thread (or an install) may have filled it meanwhile: that one wins.
|
||||
slot.get_or_insert(loaded).clone()
|
||||
}
|
||||
@@ -59,14 +59,14 @@ fn load_installed() -> AffixDict {
|
||||
/// UTF-8), for example one the user picked. On error the current dictionary stays.
|
||||
pub fn install_dictionary(aff: &str, dic: &str) -> Result<(), String> {
|
||||
let d = AffixDict::from_hunspell(aff, dic, &[])?;
|
||||
*DICT.write().unwrap_or_else(|e| e.into_inner()) = Some(Arc::new(d));
|
||||
*DICT.write().unwrap_or_else(std::sync::PoisonError::into_inner) = Some(Arc::new(d));
|
||||
Ok(())
|
||||
}
|
||||
|
||||
/// Forget the loaded dictionary, so the next check looks for an installed one again (after
|
||||
/// [`crate::hunspell::set_dictionary_dir`] or a dictionary was installed).
|
||||
pub fn reload_dictionary() {
|
||||
*DICT.write().unwrap_or_else(|e| e.into_inner()) = None;
|
||||
*DICT.write().unwrap_or_else(std::sync::PoisonError::into_inner) = None;
|
||||
}
|
||||
|
||||
/// The `.dic` file of the Hunspell `it_IT` dictionary found in the dictionaries folder or the
|
||||
|
||||
+11
-9
@@ -116,14 +116,14 @@ static DICTIONARY_GENERATION: AtomicU64 = AtomicU64::new(0);
|
||||
|
||||
/// Add a word to the user dictionary ("Add to Dictionary"). It applies to every language.
|
||||
pub fn add_word(w: &str) {
|
||||
if user_words().write().unwrap_or_else(|e| e.into_inner()).insert(w.to_lowercase()) {
|
||||
if user_words().write().unwrap_or_else(std::sync::PoisonError::into_inner).insert(w.to_lowercase()) {
|
||||
DICTIONARY_GENERATION.fetch_add(1, Ordering::Relaxed);
|
||||
}
|
||||
}
|
||||
|
||||
/// Take a word out of the user dictionary (File › Options › Proofing). Returns whether it was there.
|
||||
pub fn remove_word(w: &str) -> bool {
|
||||
let removed = user_words().write().unwrap_or_else(|e| e.into_inner()).remove(&w.to_lowercase());
|
||||
let removed = user_words().write().unwrap_or_else(std::sync::PoisonError::into_inner).remove(&w.to_lowercase());
|
||||
if removed {
|
||||
DICTIONARY_GENERATION.fetch_add(1, Ordering::Relaxed);
|
||||
}
|
||||
@@ -138,7 +138,7 @@ fn ignored_words() -> &'static RwLock<HashSet<String>> {
|
||||
/// Ignore a word everywhere until the app closes ("Ignore All"). Unlike [`add_word`] it isn't
|
||||
/// part of the user dictionary: it is never listed, saved or loaded, as in Word.
|
||||
pub fn ignore_word(w: &str) {
|
||||
if ignored_words().write().unwrap_or_else(|e| e.into_inner()).insert(w.to_lowercase()) {
|
||||
if ignored_words().write().unwrap_or_else(std::sync::PoisonError::into_inner).insert(w.to_lowercase()) {
|
||||
DICTIONARY_GENERATION.fetch_add(1, Ordering::Relaxed);
|
||||
}
|
||||
}
|
||||
@@ -198,13 +198,13 @@ pub fn dictionary_generation() -> u64 {
|
||||
|
||||
/// Is `lower` (a lower-case word) in the user dictionary or ignored?
|
||||
pub(crate) fn in_user_dictionary(lower: &str) -> bool {
|
||||
user_words().read().unwrap_or_else(|e| e.into_inner()).contains(lower)
|
||||
|| ignored_words().read().unwrap_or_else(|e| e.into_inner()).contains(lower)
|
||||
user_words().read().unwrap_or_else(std::sync::PoisonError::into_inner).contains(lower)
|
||||
|| ignored_words().read().unwrap_or_else(std::sync::PoisonError::into_inner).contains(lower)
|
||||
}
|
||||
|
||||
/// Words in the user dictionary.
|
||||
pub fn user_dictionary() -> Vec<String> {
|
||||
let mut v: Vec<String> = user_words().read().unwrap_or_else(|e| e.into_inner()).iter().cloned().collect();
|
||||
let mut v: Vec<String> = user_words().read().unwrap_or_else(std::sync::PoisonError::into_inner).iter().cloned().collect();
|
||||
v.sort();
|
||||
v
|
||||
}
|
||||
@@ -252,7 +252,7 @@ fn read_dictionary_file(path: &std::path::Path) -> Vec<String> {
|
||||
/// never a panic and never an error that stops startup. Returns the words added.
|
||||
pub fn load_user_dictionary(path: &std::path::Path) -> Vec<String> {
|
||||
let words = read_dictionary_file(path);
|
||||
let mut set = user_words().write().unwrap_or_else(|e| e.into_inner());
|
||||
let mut set = user_words().write().unwrap_or_else(std::sync::PoisonError::into_inner);
|
||||
let mut added = Vec::new();
|
||||
for w in words {
|
||||
if set.len() >= MAX_CUSTOM_WORDS {
|
||||
@@ -278,7 +278,7 @@ pub fn save_user_dictionary(path: &std::path::Path, removed: &[String]) -> std::
|
||||
let removed: HashSet<String> = removed.iter().map(|w| w.to_lowercase()).collect();
|
||||
let on_disk = read_dictionary_file(path);
|
||||
{
|
||||
let mut set = user_words().write().unwrap_or_else(|e| e.into_inner());
|
||||
let mut set = user_words().write().unwrap_or_else(std::sync::PoisonError::into_inner);
|
||||
let mut changed = false;
|
||||
for w in on_disk {
|
||||
if set.len() >= MAX_CUSTOM_WORDS {
|
||||
@@ -334,7 +334,9 @@ fn known_core(w: &str) -> bool {
|
||||
if base_known(d, w) || COMMON.split(' ').any(|c| c == w) {
|
||||
return true;
|
||||
}
|
||||
if user_words().read().unwrap_or_else(|e| e.into_inner()).contains(w) || ignored_words().read().unwrap_or_else(|e| e.into_inner()).contains(w) {
|
||||
if user_words().read().unwrap_or_else(std::sync::PoisonError::into_inner).contains(w)
|
||||
|| ignored_words().read().unwrap_or_else(std::sync::PoisonError::into_inner).contains(w)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
// Inflections.
|
||||
|
||||
@@ -33,11 +33,11 @@ const NAMES: &[&str] = &["pl_PL", "pl-PL", "pl"];
|
||||
/// [`install_dictionary`], or an empty one when none is available (Polish spelling is off then;
|
||||
/// see [`has_dictionary`]).
|
||||
pub fn dictionary() -> Arc<AffixDict> {
|
||||
if let Some(d) = DICT.read().unwrap_or_else(|e| e.into_inner()).as_ref() {
|
||||
if let Some(d) = DICT.read().unwrap_or_else(std::sync::PoisonError::into_inner).as_ref() {
|
||||
return d.clone();
|
||||
}
|
||||
let loaded = Arc::new(load_installed());
|
||||
let mut slot = DICT.write().unwrap_or_else(|e| e.into_inner());
|
||||
let mut slot = DICT.write().unwrap_or_else(std::sync::PoisonError::into_inner);
|
||||
// Another thread (or an install) may have filled it meanwhile: that one wins.
|
||||
slot.get_or_insert(loaded).clone()
|
||||
}
|
||||
@@ -58,14 +58,14 @@ fn load_installed() -> AffixDict {
|
||||
/// for example one the user picked. On error the current dictionary stays.
|
||||
pub fn install_dictionary(aff: &str, dic: &str) -> Result<(), String> {
|
||||
let d = AffixDict::from_hunspell(aff, dic, &[])?;
|
||||
*DICT.write().unwrap_or_else(|e| e.into_inner()) = Some(Arc::new(d));
|
||||
*DICT.write().unwrap_or_else(std::sync::PoisonError::into_inner) = Some(Arc::new(d));
|
||||
Ok(())
|
||||
}
|
||||
|
||||
/// Forget the loaded dictionary, so the next check looks for an installed one again (after
|
||||
/// [`crate::hunspell::set_dictionary_dir`] or a dictionary was installed).
|
||||
pub fn reload_dictionary() {
|
||||
*DICT.write().unwrap_or_else(|e| e.into_inner()) = None;
|
||||
*DICT.write().unwrap_or_else(std::sync::PoisonError::into_inner) = None;
|
||||
}
|
||||
|
||||
/// The `.dic` file of the installed Polish dictionary, searching the dictionaries folder and
|
||||
|
||||
@@ -32,11 +32,11 @@ const NAMES: &[&str] = &["pt_BR", "pt-BR", "pt"];
|
||||
/// [`install_dictionary`], or an empty one when none is available (Portuguese spelling is off
|
||||
/// then; see [`has_dictionary`]).
|
||||
pub fn dictionary() -> Arc<AffixDict> {
|
||||
if let Some(d) = DICT.read().unwrap_or_else(|e| e.into_inner()).as_ref() {
|
||||
if let Some(d) = DICT.read().unwrap_or_else(std::sync::PoisonError::into_inner).as_ref() {
|
||||
return d.clone();
|
||||
}
|
||||
let loaded = Arc::new(load_installed());
|
||||
let mut slot = DICT.write().unwrap_or_else(|e| e.into_inner());
|
||||
let mut slot = DICT.write().unwrap_or_else(std::sync::PoisonError::into_inner);
|
||||
// Another thread (or an install) may have filled it meanwhile: that one wins.
|
||||
slot.get_or_insert(loaded).clone()
|
||||
}
|
||||
@@ -57,14 +57,14 @@ fn load_installed() -> AffixDict {
|
||||
/// UTF-8), for example one the user picked. On error the current dictionary stays.
|
||||
pub fn install_dictionary(aff: &str, dic: &str) -> Result<(), String> {
|
||||
let d = AffixDict::from_hunspell(aff, dic, &[])?;
|
||||
*DICT.write().unwrap_or_else(|e| e.into_inner()) = Some(Arc::new(d));
|
||||
*DICT.write().unwrap_or_else(std::sync::PoisonError::into_inner) = Some(Arc::new(d));
|
||||
Ok(())
|
||||
}
|
||||
|
||||
/// Forget the loaded dictionary, so the next check looks for an installed one again (after
|
||||
/// [`crate::hunspell::set_dictionary_dir`] or a dictionary was installed).
|
||||
pub fn reload_dictionary() {
|
||||
*DICT.write().unwrap_or_else(|e| e.into_inner()) = None;
|
||||
*DICT.write().unwrap_or_else(std::sync::PoisonError::into_inner) = None;
|
||||
}
|
||||
|
||||
/// The `.dic` file of the installed Portuguese dictionary, searching the dictionaries folder and
|
||||
|
||||
@@ -52,11 +52,11 @@ const NAMES: &[&str] = &["ru_RU", "ru-RU", "ru"];
|
||||
/// [`install_dictionary`], or an empty one when none is available (Russian spelling is off then;
|
||||
/// see [`has_dictionary`]).
|
||||
pub fn dictionary() -> Arc<AffixDict> {
|
||||
if let Some(d) = DICT.read().unwrap_or_else(|e| e.into_inner()).dict.as_ref() {
|
||||
if let Some(d) = DICT.read().unwrap_or_else(std::sync::PoisonError::into_inner).dict.as_ref() {
|
||||
return d.clone();
|
||||
}
|
||||
let loaded = Arc::new(load_installed());
|
||||
let mut slot = DICT.write().unwrap_or_else(|e| e.into_inner());
|
||||
let mut slot = DICT.write().unwrap_or_else(std::sync::PoisonError::into_inner);
|
||||
// Another thread (or an install) may have filled it meanwhile: that one wins.
|
||||
slot.dict.get_or_insert(loaded).clone()
|
||||
}
|
||||
@@ -77,7 +77,7 @@ fn load_installed() -> AffixDict {
|
||||
/// for example one the user picked. On error the current dictionary stays.
|
||||
pub fn install_dictionary(aff: &str, dic: &str) -> Result<(), String> {
|
||||
let d = AffixDict::from_hunspell(aff, dic, &[])?;
|
||||
let mut slot = DICT.write().unwrap_or_else(|e| e.into_inner());
|
||||
let mut slot = DICT.write().unwrap_or_else(std::sync::PoisonError::into_inner);
|
||||
slot.dict = Some(Arc::new(d));
|
||||
slot.in_memory = true;
|
||||
Ok(())
|
||||
@@ -86,7 +86,7 @@ pub fn install_dictionary(aff: &str, dic: &str) -> Result<(), String> {
|
||||
/// Forget the loaded dictionary, so the next check looks for an installed one again (after
|
||||
/// [`crate::hunspell::set_dictionary_dir`] or a dictionary was installed).
|
||||
pub fn reload_dictionary() {
|
||||
let mut slot = DICT.write().unwrap_or_else(|e| e.into_inner());
|
||||
let mut slot = DICT.write().unwrap_or_else(std::sync::PoisonError::into_inner);
|
||||
slot.dict = None;
|
||||
slot.in_memory = false;
|
||||
}
|
||||
@@ -96,7 +96,7 @@ pub fn reload_dictionary() {
|
||||
/// none. A dictionary given with [`install_dictionary`] has no file and isn't reported, even if a
|
||||
/// matching file also happens to exist.
|
||||
pub fn installed_path() -> Option<std::path::PathBuf> {
|
||||
if DICT.read().unwrap_or_else(|e| e.into_inner()).in_memory {
|
||||
if DICT.read().unwrap_or_else(std::sync::PoisonError::into_inner).in_memory {
|
||||
return None;
|
||||
}
|
||||
crate::hunspell::find(NAMES).map(|(_, dic)| dic)
|
||||
|
||||
@@ -30,11 +30,11 @@ const NAMES: &[&str] = &["tr_TR", "tr-TR", "tr"];
|
||||
/// The Turkish dictionary: the installed Hunspell `tr_TR` (read on first use), one given with
|
||||
/// [`install_dictionary`], or an empty one when none is available.
|
||||
pub fn dictionary() -> Arc<TrDict> {
|
||||
if let Some(d) = DICT.read().unwrap_or_else(|e| e.into_inner()).as_ref() {
|
||||
if let Some(d) = DICT.read().unwrap_or_else(std::sync::PoisonError::into_inner).as_ref() {
|
||||
return d.clone();
|
||||
}
|
||||
let loaded = Arc::new(load_installed());
|
||||
let mut slot = DICT.write().unwrap_or_else(|e| e.into_inner());
|
||||
let mut slot = DICT.write().unwrap_or_else(std::sync::PoisonError::into_inner);
|
||||
slot.get_or_insert(loaded).clone()
|
||||
}
|
||||
|
||||
@@ -61,13 +61,13 @@ fn load_installed() -> TrDict {
|
||||
/// Use this Turkish dictionary from now on.
|
||||
pub fn install_dictionary(aff: &str, dic: &str) -> Result<(), String> {
|
||||
let d = TrDict::from_hunspell(aff, dic)?;
|
||||
*DICT.write().unwrap_or_else(|e| e.into_inner()) = Some(Arc::new(d));
|
||||
*DICT.write().unwrap_or_else(std::sync::PoisonError::into_inner) = Some(Arc::new(d));
|
||||
Ok(())
|
||||
}
|
||||
|
||||
/// Reload the dictionary on next check.
|
||||
pub fn reload_dictionary() {
|
||||
*DICT.write().unwrap_or_else(|e| e.into_inner()) = None;
|
||||
*DICT.write().unwrap_or_else(std::sync::PoisonError::into_inner) = None;
|
||||
}
|
||||
|
||||
/// The `.dic` file of the Hunspell `tr_TR` dictionary found in the dictionaries folder or the
|
||||
|
||||
@@ -181,7 +181,7 @@ impl<T: Clone> MediaCache<T> {
|
||||
}
|
||||
|
||||
fn lock<T>(m: &Mutex<T>) -> std::sync::MutexGuard<'_, T> {
|
||||
m.lock().unwrap_or_else(|e| e.into_inner())
|
||||
m.lock().unwrap_or_else(std::sync::PoisonError::into_inner)
|
||||
}
|
||||
|
||||
fn images() -> &'static Mutex<MediaCache<Option<Arc<Pixmap>>>> {
|
||||
|
||||
@@ -2566,7 +2566,7 @@ impl WordApp {
|
||||
/// recipient lists (CSV/TSV, spreadsheets, or a text file asked for as one) load as recipients.
|
||||
fn drain_inbox(&mut self) {
|
||||
let Some(inbox) = self.services.inbox.clone() else { return };
|
||||
let files = std::mem::take(&mut *inbox.lock().unwrap_or_else(|e| e.into_inner()));
|
||||
let files = std::mem::take(&mut *inbox.lock().unwrap_or_else(std::sync::PoisonError::into_inner));
|
||||
let mut placed_picture = false;
|
||||
for (name, bytes) in files {
|
||||
let lower = name.to_ascii_lowercase();
|
||||
@@ -2600,7 +2600,7 @@ impl WordApp {
|
||||
/// otherwise so the focused field's own paste applies (a text field ignores a picture).
|
||||
fn drain_pasted(&mut self) {
|
||||
let Some(pasted) = self.services.pasted.clone() else { return };
|
||||
let pictures = std::mem::take(&mut *pasted.lock().unwrap_or_else(|e| e.into_inner()));
|
||||
let pictures = std::mem::take(&mut *pasted.lock().unwrap_or_else(std::sync::PoisonError::into_inner));
|
||||
let target = paste_target(self.canvas.focused, self.ui.backstage, self.dialog.is_some() || self.file_dialog_open());
|
||||
for (_, bytes) in pictures {
|
||||
if !target {
|
||||
|
||||
Reference in New Issue
Block a user