From b4090a7acddf951088b75fcce0d6edb721bbbf45 Mon Sep 17 00:00:00 2001 From: Jedidiah Barber Date: Sun, 13 Oct 2024 03:33:38 +1300 Subject: Fixed bug with Text_Buffers not being deallocated correctly if declared after the Text_Display they are attached to --- src/c_fl_text_buffer.cpp | 21 +++++++++++++++++++-- src/c_fl_text_buffer.h | 1 + ...tk-widgets-groups-text_displays-text_editors.adb | 1 + src/fltk-widgets-groups-text_displays.adb | 6 ++++++ src/fltk-widgets-groups-text_displays.ads | 16 ++++++++++++++++ 5 files changed, 43 insertions(+), 2 deletions(-) diff --git a/src/c_fl_text_buffer.cpp b/src/c_fl_text_buffer.cpp index 2df65f6..4a681e8 100644 --- a/src/c_fl_text_buffer.cpp +++ b/src/c_fl_text_buffer.cpp @@ -6,13 +6,30 @@ +class My_Text_Buffer : public Fl_Text_Buffer { + public: + using Fl_Text_Buffer::Fl_Text_Buffer; + int reference_count = 0; +}; + + + + TEXTBUFFER new_fl_text_buffer(int rs, int pgs) { - Fl_Text_Buffer *tb = new Fl_Text_Buffer(rs, pgs); + My_Text_Buffer *tb = new My_Text_Buffer(rs, pgs); return tb; } +void upref_fl_text_buffer(TEXTBUFFER tb) { + reinterpret_cast(tb)->reference_count += 1; +} + void free_fl_text_buffer(TEXTBUFFER tb) { - delete reinterpret_cast(tb); + if (reinterpret_cast(tb)->reference_count <= 0) { + delete reinterpret_cast(tb); + } else { + reinterpret_cast(tb)->reference_count -= 1; + } } diff --git a/src/c_fl_text_buffer.h b/src/c_fl_text_buffer.h index 7258006..d808f44 100644 --- a/src/c_fl_text_buffer.h +++ b/src/c_fl_text_buffer.h @@ -12,6 +12,7 @@ typedef void* TEXTBUFFER; extern "C" TEXTBUFFER new_fl_text_buffer(int rs, int pgs); +extern "C" void upref_fl_text_buffer(TEXTBUFFER tb); extern "C" void free_fl_text_buffer(TEXTBUFFER tb); diff --git a/src/fltk-widgets-groups-text_displays-text_editors.adb b/src/fltk-widgets-groups-text_displays-text_editors.adb index e0d4588..98175a6 100644 --- a/src/fltk-widgets-groups-text_displays-text_editors.adb +++ b/src/fltk-widgets-groups-text_displays-text_editors.adb @@ -388,6 +388,7 @@ package body FLTK.Widgets.Groups.Text_Displays.Text_Editors is then This.Clear; free_fl_text_editor (This.Void_Ptr); + free_fl_text_buffer (This.Raw_Buffer); This.Void_Ptr := Null_Pointer; end if; Finalize (Text_Display (This)); diff --git a/src/fltk-widgets-groups-text_displays.adb b/src/fltk-widgets-groups-text_displays.adb index 59efc55..3dd9f6d 100644 --- a/src/fltk-widgets-groups-text_displays.adb +++ b/src/fltk-widgets-groups-text_displays.adb @@ -470,6 +470,7 @@ package body FLTK.Widgets.Groups.Text_Displays is then This.Clear; free_fl_text_display (This.Void_Ptr); + free_fl_text_buffer (This.Raw_Buffer); This.Void_Ptr := Null_Pointer; end if; Finalize (Group (This)); @@ -546,6 +547,11 @@ package body FLTK.Widgets.Groups.Text_Displays is begin This.Buffer := Buff'Unchecked_Access; fl_text_display_set_buffer (This.Void_Ptr, Wrapper (Buff).Void_Ptr); + if This.Raw_Buffer /= Null_Pointer then + free_fl_text_buffer (This.Raw_Buffer); + end if; + This.Raw_Buffer := Wrapper (Buff).Void_Ptr; + upref_fl_text_buffer (This.Raw_Buffer); end Set_Buffer; diff --git a/src/fltk-widgets-groups-text_displays.ads b/src/fltk-widgets-groups-text_displays.ads index 609561e..76cff42 100644 --- a/src/fltk-widgets-groups-text_displays.ads +++ b/src/fltk-widgets-groups-text_displays.ads @@ -359,6 +359,7 @@ private type Text_Display is new Group with record Buffer : access FLTK.Text_Buffers.Text_Buffer; + Raw_Buffer : Storage.Integer_Address := Null_Pointer; Style_Callback : Styles.Unfinished_Style_Callback; end record; @@ -373,6 +374,21 @@ private + -- Adds some basic reference counting on the C side to help ensure any Text_Buffers + -- do not get deallocated before all Text_Displays they might be attached to. + procedure upref_fl_text_buffer + (TB : in Storage.Integer_Address); + pragma Import (C, upref_fl_text_buffer, "upref_fl_text_buffer"); + pragma Inline (upref_fl_text_buffer); + + procedure free_fl_text_buffer + (TB : in Storage.Integer_Address); + pragma Import (C, free_fl_text_buffer, "free_fl_text_buffer"); + pragma Inline (free_fl_text_buffer); + + + + pragma Inline (Get_Buffer); pragma Inline (Set_Buffer); -- cgit