summaryrefslogtreecommitdiff
path: root/src/Fl_Browser_.cxx
diff options
context:
space:
mode:
Diffstat (limited to 'src/Fl_Browser_.cxx')
-rw-r--r--src/Fl_Browser_.cxx56
1 files changed, 50 insertions, 6 deletions
diff --git a/src/Fl_Browser_.cxx b/src/Fl_Browser_.cxx
index 2a654dbe5..ad98f858f 100644
--- a/src/Fl_Browser_.cxx
+++ b/src/Fl_Browser_.cxx
@@ -678,11 +678,15 @@ int Fl_Browser_::deselect(int docallbacks) {
int Fl_Browser_::select_only(void* item, int docallbacks) {
if (!item) return deselect(docallbacks);
int change = 0;
+ Fl_Widget_Tracker wp(this);
if (type() == FL_MULTI_BROWSER) {
- for (void* p = item_first(); p; p = item_next(p))
+ for (void* p = item_first(); p; p = item_next(p)) {
if (p != item) change |= select(p, 0, docallbacks);
+ if (wp.deleted()) return change;
+ }
}
change |= select(item, 1, docallbacks);
+ if (wp.deleted()) return change;
display(item);
return change;
}
@@ -693,6 +697,20 @@ int Fl_Browser_::select_only(void* item, int docallbacks) {
\returns 1 if event was processed, 0 if not.
*/
int Fl_Browser_::handle(int event) {
+
+ // NOTE:
+ // We use Fl_Widget_Tracker to test if the user has deleted
+ // this widget in a callback. Callbacks can be called by:
+ // - do_callback()
+ // - select()
+ // - select_only()
+ // - deselect()
+ // Thus we must test wp.deleted() after each of these calls,
+ // unless we return directly after one of these.
+ // If wp.deleted() is true, we return 1 because we used the event.
+
+ Fl_Widget_Tracker wp(this);
+
// must do shortcuts first or the scrollbar will get them...
if (event == FL_ENTER || event == FL_LEAVE) return 1;
if (event == FL_KEYBOARD && type() >= FL_HOLD_BROWSER) {
@@ -706,8 +724,12 @@ int Fl_Browser_::handle(int event) {
if (item_height(l)>0) {select_only(l, when()); break;}
return 1;
case FL_Up:
- while ((l = item_prev(l))) if (item_height(l)>0) {
- select_only(l, when()); break;}
+ while ((l = item_prev(l))) {
+ if (item_height(l)>0) {
+ select_only(l, when());
+ break; // no need to test wp (return 1)
+ }
+ }
return 1;
}
} else {
@@ -715,6 +737,7 @@ int Fl_Browser_::handle(int event) {
case FL_Enter:
case FL_KP_Enter:
select_only(l, when() & ~FL_WHEN_ENTER_KEY);
+ if (wp.deleted()) return 1;
if (when() & FL_WHEN_ENTER_KEY) {
set_changed();
do_callback();
@@ -728,6 +751,7 @@ int Fl_Browser_::handle(int event) {
while ((l = item_next(l))) {
if (Fl::event_state(FL_SHIFT|FL_CTRL))
select(l, l1 ? item_selected(l1) : 1, when());
+ if (wp.deleted()) return 1;
if (item_height(l)>0) goto J1;
}
return 1;
@@ -735,6 +759,7 @@ int Fl_Browser_::handle(int event) {
while ((l = item_prev(l))) {
if (Fl::event_state(FL_SHIFT|FL_CTRL))
select(l, l1 ? item_selected(l1) : 1, when());
+ if (wp.deleted()) return 1;
if (item_height(l)>0) goto J1;
}
return 1;
@@ -749,6 +774,8 @@ J1:
}
if (Fl_Group::handle(event)) return 1;
+ if (wp.deleted()) return 1;
+
int X, Y, W, H; bbox(X, Y, W, H);
int my;
// NOTE:
@@ -784,9 +811,11 @@ J1:
;
else if (type() != FL_MULTI_BROWSER) {
change = select_only(find_item(my), 0);
+ if (wp.deleted()) return 1;
if (change && (when() & FL_WHEN_CHANGED)) {
set_changed();
do_callback();
+ if (wp.deleted()) return 1;
}
} else {
void* l = find_item(my);
@@ -796,9 +825,11 @@ J1:
if (l) {
whichway = !item_selected(l);
change = select(l, whichway, 0);
+ if (wp.deleted()) return 1;
if (change && (when() & FL_WHEN_CHANGED)) {
set_changed();
do_callback();
+ if (wp.deleted()) return 1;
}
}
} else if (Fl::event_state(FL_SHIFT)) { // extend selection:
@@ -814,23 +845,29 @@ J1:
if (!m) {down = 0; break;}
}}
if (down) {
- for (void* m = selection_; m != l; m = item_next(m))
+ for (void* m = selection_; m != l; m = item_next(m)) {
select(m, whichway, when() & FL_WHEN_CHANGED);
+ if (wp.deleted()) return 1;
+ }
} else {
void* e = selection_;
for (void* m = item_next(l); m; m = item_next(m)) {
select(m, whichway, when() & FL_WHEN_CHANGED);
+ if (wp.deleted()) return 1;
if (m == e) break;
}
}
// do the clicked item last so the select box is around it:
change = 1;
if (l) select(l, whichway, when() & FL_WHEN_CHANGED);
+ if (wp.deleted()) return 1;
} else { // select only this item
change = select_only(l, 0);
+ if (wp.deleted()) return 1;
if (change && (when() & FL_WHEN_CHANGED)) {
set_changed();
do_callback();
+ if (wp.deleted()) return 1;
}
}
}
@@ -863,10 +900,12 @@ J1:
for (; t && t != b; t = item_next(t)) {
char change_t;
change_t = select(t, whichway, 0);
+ if (wp.deleted()) return 1;
change |= change_t;
if (change_t && (when() & FL_WHEN_CHANGED)) {
set_changed();
do_callback();
+ if (wp.deleted()) return 1;
}
}
if (l) selection_ = l;
@@ -877,12 +916,16 @@ J1:
find_item(my);
change = (l != l1);
select_only(l, when() & FL_WHEN_CHANGED);
+ if (wp.deleted()) return 1;
}
py = my;
return 1;
case FL_RELEASE:
if (type() == FL_SELECT_BROWSER) {
- void* t = selection_; deselect(); selection_ = t;
+ void* t = selection_;
+ deselect();
+ if (wp.deleted()) return 1;
+ selection_ = t;
}
if (change) {
set_changed();
@@ -890,7 +933,8 @@ J1:
} else {
if (when() & FL_WHEN_NOT_CHANGED) do_callback();
}
-
+ if (wp.deleted()) return 1;
+
// double click calls the callback: (like Enter Key)
if (Fl::event_clicks() && (when() & FL_WHEN_ENTER_KEY)) {
set_changed();