1+ use crate :: core:: RaylibHandle ;
12use crate :: core:: drawing:: RaylibDraw ;
23use crate :: core:: text:: WeakFont ;
3- use crate :: core:: RaylibHandle ;
44use 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
1010impl 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
0 commit comments