Skip to content

Commit e2be94b

Browse files
authored
fixed raygui textbox not being able to take input (#195)
1 parent 441c0d0 commit e2be94b

File tree

2 files changed

+54
-15
lines changed

2 files changed

+54
-15
lines changed

raylib/src/rgui/safe.rs

Lines changed: 53 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,10 @@
1+
use crate::core::RaylibHandle;
12
use crate::core::drawing::RaylibDraw;
23
use crate::core::text::WeakFont;
3-
use crate::core::RaylibHandle;
44
use crate::ffi::{Color, Rectangle, Vector2};
5-
use crate::{ffi, MintVec2};
5+
use crate::{MintVec2, ffi};
66

7-
use std::ffi::{c_char, CStr, CString};
7+
use std::ffi::{CStr, CString, c_char};
88

99
/// Global gui modification functions
1010
impl RaylibHandle {
@@ -380,15 +380,32 @@ pub trait RaylibDrawGui {
380380
buffer: &mut String,
381381
edit_mode: bool,
382382
) -> bool {
383-
let len = buffer.len();
384-
unsafe {
385-
ffi::GuiTextBox(
386-
bounds.into(),
387-
buffer.as_mut_ptr() as *mut _,
388-
len as i32,
389-
edit_mode,
390-
) > 0
383+
// NOTE: method of dealing with null terminated strings copied from imgui(input_widget.rs:289, build func)
384+
buffer.push('\0');
385+
let (ptr, capacity) = (buffer.as_mut_ptr(), buffer.capacity());
386+
let res = unsafe {
387+
ffi::GuiTextBox(bounds.into(), ptr as *mut i8, capacity as i32, edit_mode) > 0
388+
};
389+
let cap = buffer.capacity();
390+
391+
// SAFETY: this slice is simply a view into the underlying buffer
392+
// of a String. We MAY be holding onto a view of uninitialized memory,
393+
// however, since we're holding this as a u8 slice, I think it should be
394+
// alright...
395+
// additionally, we can go over the bytes directly, rather than char indices,
396+
// because NUL will never appear in any UTF8 outside the NUL character (ie, within
397+
// a char).
398+
let buf = unsafe { std::slice::from_raw_parts(buffer.as_ptr(), cap) };
399+
if let Some(len) = buf.iter().position(|x| *x == b'\0') {
400+
// `len` is the position of the first `\0` byte in the String
401+
unsafe {
402+
buffer.as_mut_vec().set_len(len);
403+
}
404+
} else {
405+
// There is no null terminator, the best we can do is to not
406+
// update the string length.
391407
}
408+
res
392409
}
393410

394411
/// Slider control, returns selected value
@@ -568,8 +585,11 @@ pub trait RaylibDrawGui {
568585
text_max_size: i32,
569586
secret_view_active: &mut bool,
570587
) -> i32 {
571-
// rgui.h: line 3699 MAX_FILENAME_LEN
572-
text.reserve((256 - text.len()).max(0) as usize);
588+
text.reserve(text_max_size as usize);
589+
// NOTE: method of dealing with null terminated strings copied from imgui(input_widget.rs:289, build func)
590+
text.push('\0');
591+
let (ptr, capacity) = (text.as_mut_ptr(), text.capacity());
592+
573593
let c_title = CString::new(title).unwrap();
574594
let c_message = CString::new(message).unwrap();
575595
let c_buttons = CString::new(buttons).unwrap();
@@ -579,12 +599,30 @@ pub trait RaylibDrawGui {
579599
c_title.as_ptr(),
580600
c_message.as_ptr(),
581601
c_buttons.as_ptr(),
582-
text.as_mut_ptr() as *mut _,
583-
text_max_size,
602+
ptr as *mut i8,
603+
capacity as i32,
584604
secret_view_active,
585605
)
586606
};
607+
let cap = text.capacity();
587608

609+
// SAFETY: this slice is simply a view into the underlying buffer
610+
// of a String. We MAY be holding onto a view of uninitialized memory,
611+
// however, since we're holding this as a u8 slice, I think it should be
612+
// alright...
613+
// additionally, we can go over the bytes directly, rather than char indices,
614+
// because NUL will never appear in any UTF8 outside the NUL character (ie, within
615+
// a char).
616+
let buf = unsafe { std::slice::from_raw_parts(text.as_ptr(), cap) };
617+
if let Some(len) = buf.iter().position(|x| *x == b'\0') {
618+
// `len` is the position of the first `\0` byte in the String
619+
unsafe {
620+
text.as_mut_vec().set_len(len);
621+
}
622+
} else {
623+
// There is no null terminator, the best we can do is to not
624+
// update the string length.
625+
}
588626
btn_index
589627
}
590628

samples/Cargo.toml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,7 @@ path = "./specs.rs"
3535
[[bin]]
3636
name = "rgui"
3737
path = "./rgui.rs"
38+
required-features = ["raylib/raygui"]
3839

3940
[[bin]]
4041
name = "arkanoid"

0 commit comments

Comments
 (0)