diff --git a/Makefile.am b/Makefile.am index 0a50bf18..10837d32 100644 --- a/Makefile.am +++ b/Makefile.am @@ -39,7 +39,7 @@ ACLOCAL_AMFLAGS = -I m4 AM_DISTCHECK_CONFIGURE_FLAGS = --enable-silent-rules LINGUAS='*' -SUBDIRS = wrlib wutil-rs WINGs wmaker-rs src util po WindowMaker wmlib WPrefs.app doc +SUBDIRS = wrlib wutil-rs wings-rs WINGs wmaker-rs src util po WindowMaker wmlib WPrefs.app doc DIST_SUBDIRS = $(SUBDIRS) test EXTRA_DIST = TODO BUGS BUGFORM FAQ INSTALL \ diff --git a/WINGs/WINGs/WUtil.h b/WINGs/WINGs/WUtil.h index 18c8b52b..62e33dca 100644 --- a/WINGs/WINGs/WUtil.h +++ b/WINGs/WINGs/WUtil.h @@ -156,12 +156,7 @@ typedef struct { -/* DO NOT ACCESS THE CONTENTS OF THIS STRUCT */ -typedef struct { - void *table; - void *nextItem; - int index; -} WMHashEnumerator; +typedef struct WMHashEnumerator WMHashEnumerator; typedef struct { @@ -334,7 +329,7 @@ void WMDeleteInputHandler(WMHandlerID handlerID); void WHandleEvents(void); -/* ---[ WINGs/hashtable.c ]----------------------------------------------- */ +/* ---[ wutil-rs/src/hash_table.rs ]----------------------------------------------- */ WMHashTable* WMCreateIdentityHashTable(); @@ -366,7 +361,7 @@ void* WMHashInsert(WMHashTable *table, const void *key, const void *data); void WMHashRemove(WMHashTable *table, const void *key); /* warning: do not manipulate the table while using the enumerator functions */ -WMHashEnumerator WMEnumerateHashTable(WMHashTable *table); +WMHashEnumerator* WMEnumerateHashTable(WMHashTable *table); void* WMNextHashEnumeratorItem(WMHashEnumerator *enumerator); @@ -381,7 +376,7 @@ Bool WMNextHashEnumeratorItemAndKey(WMHashEnumerator *enumerator, void **item, void **key); - +void WMFreeHashEnumerator(WMHashEnumerator *enumerator); /* some predefined callback sets */ diff --git a/WINGs/wballoon.c b/WINGs/wballoon.c index 8a9c8a84..3e57e530 100644 --- a/WINGs/wballoon.c +++ b/WINGs/wballoon.c @@ -456,12 +456,12 @@ static void handleEvents(XEvent * event, void *data) static void destroyBalloon(Balloon * bPtr) { - WMHashEnumerator e; + WMHashEnumerator *e; char *str; e = WMEnumerateHashTable(bPtr->table); - while ((str = WMNextHashEnumeratorItem(&e))) { + while ((str = WMNextHashEnumeratorItem(e))) { wfree(str); } WMFreeHashTable(bPtr->table); @@ -472,5 +472,7 @@ static void destroyBalloon(Balloon * bPtr) if (bPtr->font) WMReleaseFont(bPtr->font); + WMFreeHashEnumerator(e); + wfree(bPtr); } diff --git a/WINGs/wfontpanel.c b/WINGs/wfontpanel.c index c57678ab..37b2e912 100644 --- a/WINGs/wfontpanel.c +++ b/WINGs/wfontpanel.c @@ -520,7 +520,7 @@ static void listFamilies(WMScreen * scr, WMFontPanel * panel) FcFontSet *fs; FcPattern *pat; WMHashTable *families; - WMHashEnumerator enumer; + WMHashEnumerator *enumer; WMArray *array; int i; @@ -551,7 +551,8 @@ static void listFamilies(WMScreen * scr, WMFontPanel * panel) enumer = WMEnumerateHashTable(families); - while ((array = WMNextHashEnumeratorItem(&enumer))) { + while ((array = WMNextHashEnumeratorItem(enumer))) { + printf("listFamilies: got family with %d items\n", WMGetArrayItemCount(array)); WMArrayIterator i; Family *fam; char buffer[256]; diff --git a/configure.ac b/configure.ac index 78313976..aed888ef 100644 --- a/configure.ac +++ b/configure.ac @@ -959,6 +959,7 @@ AC_CONFIG_FILES( dnl Rust implementation of WINGs libraries wutil-rs/Makefile + wings-rs/Makefile dnl WINGs toolkit WINGs/Makefile WINGs/WINGs/Makefile WINGs/po/Makefile diff --git a/start-captive-wmaker.sh b/start-captive-wmaker.sh index 2afb4c33..35278414 100755 --- a/start-captive-wmaker.sh +++ b/start-captive-wmaker.sh @@ -89,6 +89,8 @@ Xephyr -screen 640x480 "$xephyr_display" & xephyr_pid=$! DISPLAY="$xephyr_display" gdb \ --directory "$project_base" \ + --directory "$HOME/src/libX11-1.5.0/build/src" \ --quiet \ + --fullname \ --args "$WindowMaker" -display "$xephyr_display" --for-real "$@" kill $xephyr_pid diff --git a/wings-rs/Cargo.toml b/wings-rs/Cargo.toml new file mode 100644 index 00000000..2a743277 --- /dev/null +++ b/wings-rs/Cargo.toml @@ -0,0 +1,7 @@ +[package] +name = "wings-rs" +version = "0.1.0" +edition = "2024" + +[dependencies] +wutil-rs = { path = "../wutil-rs" } diff --git a/wings-rs/Makefile.am b/wings-rs/Makefile.am new file mode 100644 index 00000000..2aa61a59 --- /dev/null +++ b/wings-rs/Makefile.am @@ -0,0 +1,19 @@ +AUTOMAKE_OPTIONS = + +RUST_SOURCES = \ + src/lib.rs + +RUST_EXTRA = \ + Cargo.lock \ + Cargo.toml + +target/debug/libwings_rs.a: $(RUST_SOURCES) $(RUST_EXTRA) + $(CARGO) build + +check-local: + $(CARGO) test + +clean-local: + $(CARGO) clean + +all: target/debug/libwings_rs.a diff --git a/wings-rs/src/lib.rs b/wings-rs/src/lib.rs new file mode 100644 index 00000000..b93cf3ff --- /dev/null +++ b/wings-rs/src/lib.rs @@ -0,0 +1,14 @@ +pub fn add(left: u64, right: u64) -> u64 { + left + right +} + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn it_works() { + let result = add(2, 2); + assert_eq!(result, 4); + } +} diff --git a/wutil-rs/src/array.rs b/wutil-rs/src/array.rs index 42a0d45b..acae7c7a 100644 --- a/wutil-rs/src/array.rs +++ b/wutil-rs/src/array.rs @@ -1,7 +1,7 @@ -use std::{ffi::c_void, ptr::NonNull}; +use std::ffi::c_void; pub struct Array { - items: Vec>, + items: Vec, destructor: Option, } @@ -10,7 +10,7 @@ pub mod ffi { use std::{ ffi::{c_int, c_void}, - ptr::{self, NonNull}, + ptr, }; pub const NOT_FOUND: c_int = -1; @@ -64,7 +64,7 @@ pub mod ffi { let array = unsafe { &mut *array }; if let Some(f) = array.destructor { for item in &mut array.items { - unsafe { (f)(item.as_ptr()) } + unsafe { (f)(*item as *mut c_void) } } } array.items.clear(); @@ -94,10 +94,8 @@ pub mod ffi { if array.is_null() { return; } - if let Some(item) = NonNull::new(item) { - unsafe { - (*array).items.push(item); - } + unsafe { + (*array).items.push(item.addr()); } } @@ -114,9 +112,7 @@ pub mod ffi { if index >= array.len() { return; } - if let Some(item) = NonNull::new(item) { - array.insert(index, item); - } + array.insert(index, item.addr()); } #[unsafe(no_mangle)] @@ -141,15 +137,11 @@ pub mod ffi { return ptr::null_mut(); } - let item = match NonNull::new(item) { - Some(x) => x, - None => return ptr::null_mut(), - }; let array = unsafe { &mut (*array).items }; let old = array[index]; - array[index] = item; - old.as_ptr() + array[index] = item.addr(); + old as *mut c_void } #[unsafe(no_mangle)] @@ -168,7 +160,7 @@ pub mod ffi { let old = array.items.remove(index); if let Some(f) = array.destructor { unsafe { - (f)(old.as_ptr()); + (f)(old as *mut c_void); } } 1 @@ -192,8 +184,8 @@ pub mod ffi { let array = unsafe { &mut *array }; let original_len = array.items.len(); match pred { - Some(f) => array.items.retain(|x| unsafe { f(x.as_ptr(), cdata) != 0 }), - None => array.items.retain(|x| ptr::eq(x.as_ptr(), cdata)), + Some(f) => array.items.retain(|x| unsafe { f(*x as *const c_void, cdata) != 0 }), + None => array.items.retain(|x| ptr::eq(*x as *mut c_void, cdata)), } (original_len - array.items.len()) as c_int } @@ -207,7 +199,7 @@ pub mod ffi { (&(*array)) .items .get(index as usize) - .map(|p| p.as_ptr()) + .map(|p| *p as *mut c_void) .unwrap_or(ptr::null_mut()) } } @@ -226,7 +218,7 @@ pub mod ffi { (*array) .items .pop() - .map(|p| p.as_ptr()) + .map(|p| p as *mut c_void) .unwrap_or(ptr::null_mut()) } } @@ -246,7 +238,7 @@ pub mod ffi { .items .iter() .enumerate() - .find(|(_, item)| unsafe { f(item.as_ptr(), cdata) != 0 }) + .find(|(_, item)| unsafe { f(**item as *const c_void, cdata) != 0 }) .map(|(i, _)| i as c_int) .unwrap_or(NOT_FOUND) } else { @@ -254,7 +246,7 @@ pub mod ffi { .items .iter() .enumerate() - .find(|(_, item)| ptr::eq(item.as_ptr(), cdata)) + .find(|(_, item)| ptr::eq(**item as *const c_void, cdata)) .map(|(i, _)| i as c_int) .unwrap_or(NOT_FOUND) } @@ -269,7 +261,7 @@ pub mod ffi { array .items .iter() - .filter(|x| ptr::eq(x.as_ptr(), item)) + .filter(|x| ptr::eq(**x as *const c_void, item)) .count() as c_int } @@ -284,13 +276,17 @@ pub mod ffi { unsafe { (*array) .items - .sort_by(|&a, &b| match comparator(a.as_ptr(), b.as_ptr()).signum() { - -1 => std::cmp::Ordering::Less, - 0 => std::cmp::Ordering::Equal, - 1 => std::cmp::Ordering::Greater, - _ => unreachable!(), + .sort_by(|a, b| { + let a = a as *const _ as *const c_void; + let b = b as *const _ as *const c_void; + match comparator(a, b).signum() { + -1 => std::cmp::Ordering::Less, + 0 => std::cmp::Ordering::Equal, + 1 => std::cmp::Ordering::Greater, + _ => unreachable!(), + } }) - } + } } #[unsafe(no_mangle)] @@ -304,7 +300,7 @@ pub mod ffi { } unsafe { for a in &mut (*array).items { - (f)(a.as_ptr(), data); + (f)(*a as *mut c_void, data); } } } @@ -326,7 +322,7 @@ pub mod ffi { unsafe { *iter = 0; } - x.as_ptr() + *x as *mut c_void } } } @@ -348,7 +344,7 @@ pub mod ffi { unsafe { *iter = (array.items.len() - 1) as c_int; } - x.as_ptr() + *x as *mut c_void } } } @@ -368,7 +364,7 @@ pub mod ffi { unsafe { *iter += 1; } - i.as_ptr() + *i as *mut c_void } None => { unsafe { @@ -394,7 +390,7 @@ pub mod ffi { unsafe { *iter -= 1; } - i.as_ptr() + *i as *mut c_void } None => { unsafe { diff --git a/wutil-rs/src/hash_table.rs b/wutil-rs/src/hash_table.rs index 77c20823..e9ef66ce 100644 --- a/wutil-rs/src/hash_table.rs +++ b/wutil-rs/src/hash_table.rs @@ -69,7 +69,6 @@ impl HashTable { } } -#[derive(Debug)] #[repr(transparent)] pub struct StringKey(*const u8); @@ -85,6 +84,12 @@ impl PartialEq for StringKey { impl Eq for StringKey {} +impl std::fmt::Debug for StringKey { + fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result { + write!(f, "StringKey({:?})", unsafe { std::ffi::CStr::from_ptr(self.0) }) + } +} + impl Hash for StringKey { fn hash(&self, h: &mut H) { if self.0.is_null() { @@ -291,4 +296,43 @@ pub mod ffi { }, } } + + #[cfg(test)] + mod test { + use super::*; + + use std::{ffi::CString, ptr}; + + #[test] + fn enumerate_nonempty() { + unsafe { + let table = WMCreateStringHashTable(); + let k1 = CString::new("hello").unwrap().into_raw(); + let v1 = CString::new("world").unwrap().into_raw(); + let k2 = CString::new("foo").unwrap().into_raw(); + let v2 = CString::new("bar").unwrap().into_raw(); + WMHashInsert(table, k1.cast(), v1.cast()); + WMHashInsert(table, k2.cast(), v2.cast()); + + let i = WMEnumerateHashTable(table); + + let v = WMNextHashEnumeratorItem(i); + assert_ne!(v, ptr::null_mut()); + assert!(v == v1.cast() || v == v2.cast()); + + let v = WMNextHashEnumeratorItem(i); + assert_ne!(v, ptr::null_mut()); + assert!(v == v1.cast() || v == v2.cast()); + + let v = WMNextHashEnumeratorItem(i); + assert_eq!(v, ptr::null_mut()); + WMFreeHashEnumerator(i); + + let _ = CString::from_raw(k1); + let _ = CString::from_raw(v1); + let _ = CString::from_raw(k2); + let _ = CString::from_raw(v2); + } + } + } }