summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/Fl_Input.cxx621
-rw-r--r--test/tree.cxx2
2 files changed, 313 insertions, 310 deletions
diff --git a/src/Fl_Input.cxx b/src/Fl_Input.cxx
index 5f96cf411..67b5f2357 100644
--- a/src/Fl_Input.cxx
+++ b/src/Fl_Input.cxx
@@ -82,18 +82,18 @@ static const char *legal_fp_chars = ".eE+-";
#endif
int Fl_Input::handle_key() {
-
+
char ascii = Fl::event_text()[0];
-
+
int repeat_num=1;
-
+
int del;
if (Fl::compose(del)) {
-
+
// Insert characters into numeric fields after checking for legality:
if (input_type() == FL_FLOAT_INPUT || input_type() == FL_INT_INPUT) {
Fl::compose_reset(); // ignore any foreign letters...
-
+
// initialize the list of legal characters inside a floating point number
#ifdef HAVE_LOCALECONV
if (!legal_fp_chars) {
@@ -108,7 +108,7 @@ int Fl_Input::handle_key() {
// the following line is not a true memory leak because the array is only
// allocated once if required, and automatically freed when the program quits
char *chars = (char*)malloc(len+1);
- legal_fp_chars = chars;
+ legal_fp_chars = chars;
strcpy(chars, standard_fp_chars);
if (lc) {
if (lc->decimal_point) strcat(chars, lc->decimal_point);
@@ -118,361 +118,364 @@ int Fl_Input::handle_key() {
}
}
#endif // HAVE_LOCALECONV
-
+
+ // find the insert position
+ int ip = position()<mark() ? position() : mark();
// This is complex to allow "0xff12" hex to be typed:
- if (!position() && (ascii == '+' || ascii == '-') ||
- (ascii >= '0' && ascii <= '9') ||
- (position()==1 && index(0)=='0' && (ascii=='x' || ascii == 'X')) ||
- (position()>1 && index(0)=='0' && (index(1)=='x'||index(1)=='X')
- && (ascii>='A'&& ascii<='F' || ascii>='a'&& ascii<='f')) ||
- input_type()==FL_FLOAT_INPUT && ascii && strchr(legal_fp_chars, ascii)) {
- if (readonly()) fl_beep();
- else replace(position(), mark(), &ascii, 1);
+ if (!ip && (ascii == '+' || ascii == '-')
+ || (ascii >= '0' && ascii <= '9')
+ || (ip==1 && index(0)=='0' && (ascii=='x' || ascii == 'X'))
+ || (ip>1 && index(0)=='0' && (index(1)=='x'||index(1)=='X')
+ && (ascii>='A'&& ascii<='F' || ascii>='a'&& ascii<='f'))
+ || input_type()==FL_FLOAT_INPUT && ascii && strchr(legal_fp_chars, ascii))
+ {
+ if (readonly()) fl_beep();
+ else replace(position(), mark(), &ascii, 1);
}
return 1;
}
-
+
if (del || Fl::event_length()) {
if (readonly()) fl_beep();
else replace(position(), del ? position()-del : mark(),
- Fl::event_text(), Fl::event_length());
+ Fl::event_text(), Fl::event_length());
}
return 1;
}
-
+
unsigned int mods = Fl::event_state() & (FL_META|FL_CTRL|FL_ALT);
switch (Fl::event_key()) {
- case FL_Insert:
- if (Fl::event_state() & FL_CTRL) ascii = ctrl('C');
- else if (Fl::event_state() & FL_SHIFT) ascii = ctrl('V');
- break;
- case FL_Delete:
+ case FL_Insert:
+ if (Fl::event_state() & FL_CTRL) ascii = ctrl('C');
+ else if (Fl::event_state() & FL_SHIFT) ascii = ctrl('V');
+ break;
+ case FL_Delete:
#ifdef __APPLE__
- if (mods==0 || mods==FL_CTRL) { // delete next char
- ascii = ctrl('D');
- } else if (mods==FL_ALT) { // delete next word
- if (mark() != position()) return cut();
- cut(position(), word_end(position()));
- return 1;
- } else if (mods==FL_META) { // delete to the end of the line
- if (mark() != position()) return cut();
- cut(position(), line_end(position()));
- return 1;
- } else return 1;
+ if (mods==0 || mods==FL_CTRL) { // delete next char
+ ascii = ctrl('D');
+ } else if (mods==FL_ALT) { // delete next word
+ if (mark() != position()) return cut();
+ cut(position(), word_end(position()));
+ return 1;
+ } else if (mods==FL_META) { // delete to the end of the line
+ if (mark() != position()) return cut();
+ cut(position(), line_end(position()));
+ return 1;
+ } else return 1;
#else
- if (mods==0) {
- ascii = ctrl('D');
- } else if (mods==FL_SHIFT) {
- ascii = ctrl('X');
- } else return 1;
+ if (mods==0) {
+ ascii = ctrl('D');
+ } else if (mods==FL_SHIFT) {
+ ascii = ctrl('X');
+ } else return 1;
#endif
- break;
- case FL_Left:
+ break;
+ case FL_Left:
#ifdef __APPLE__
- if (mods==0) { // char left
- ascii = ctrl('B');
- } else if (mods==FL_ALT) { // word left
- shift_position(word_start(position()));
- return 1;
- } else if (mods==FL_CTRL || mods==FL_META) { // start of line
- shift_position(line_start(position()));
- return 1;
- } else return 1;
+ if (mods==0) { // char left
+ ascii = ctrl('B');
+ } else if (mods==FL_ALT) { // word left
+ shift_position(word_start(position()));
+ return 1;
+ } else if (mods==FL_CTRL || mods==FL_META) { // start of line
+ shift_position(line_start(position()));
+ return 1;
+ } else return 1;
#else
- if (mods==0) { // char left
- ascii = ctrl('B');
- } else if (mods==FL_CTRL) { // word left
- shift_position(word_start(position()));
- return 1;
- } else return 1;
+ if (mods==0) { // char left
+ ascii = ctrl('B');
+ } else if (mods==FL_CTRL) { // word left
+ shift_position(word_start(position()));
+ return 1;
+ } else return 1;
#endif
- break;
- case FL_Right:
+ break;
+ case FL_Right:
#ifdef __APPLE__
- if (mods==0) { // char right
- ascii = ctrl('F');
- } else if (mods==FL_ALT) { // word right
- shift_position(word_end(position()));
- return 1;
- } else if (mods==FL_CTRL || mods==FL_META) { // end of line
- shift_position(line_end(position()));
- return 1;
- } else return 1;
+ if (mods==0) { // char right
+ ascii = ctrl('F');
+ } else if (mods==FL_ALT) { // word right
+ shift_position(word_end(position()));
+ return 1;
+ } else if (mods==FL_CTRL || mods==FL_META) { // end of line
+ shift_position(line_end(position()));
+ return 1;
+ } else return 1;
#else
- if (mods==0) { // char right
- ascii = ctrl('F');
- } else if (mods==FL_CTRL) { // word right
- shift_position(word_end(position()));
- return 1;
- } else return 1;
+ if (mods==0) { // char right
+ ascii = ctrl('F');
+ } else if (mods==FL_CTRL) { // word right
+ shift_position(word_end(position()));
+ return 1;
+ } else return 1;
#endif // __APPLE__
- break;
- case FL_Page_Up:
+ break;
+ case FL_Page_Up:
#ifdef __APPLE__
- if (mods==0) { // scroll text one page
- // OS X scrolls the view, but does not move the cursor
- // Fl_Input has no scroll control, so instead we move the cursor by one page
- repeat_num = linesPerPage();
- ascii = ctrl('P');
- } else if (mods==FL_ALT) { // move cursor one page
- repeat_num = linesPerPage();
- ascii = ctrl('P');
- } else return 1;
- break;
+ if (mods==0) { // scroll text one page
+ // OS X scrolls the view, but does not move the cursor
+ // Fl_Input has no scroll control, so instead we move the cursor by one page
+ repeat_num = linesPerPage();
+ ascii = ctrl('P');
+ } else if (mods==FL_ALT) { // move cursor one page
+ repeat_num = linesPerPage();
+ ascii = ctrl('P');
+ } else return 1;
+ break;
#else
- repeat_num = linesPerPage();
- // fall through
+ repeat_num = linesPerPage();
+ // fall through
#endif
- case FL_Up:
+ case FL_Up:
#ifdef __APPLE__
- if (mods==0) { // line up
- ascii = ctrl('P');
- } else if (mods==FL_CTRL) { // scroll text down one page
- // OS X scrolls the view, but does not move the cursor
- // Fl_Input has no scroll control, so instead we move the cursor by one page
- repeat_num = linesPerPage();
- ascii = ctrl('P');
- } else if (mods==FL_ALT) { // line start and up
- if (line_start(position())==position() && position()>0)
- return shift_position(line_start(position()-1)) + NORMAL_INPUT_MOVE;
- else
- return shift_position(line_start(position())) + NORMAL_INPUT_MOVE;
- } else if (mods==FL_META) { // start of document
- shift_position(0);
- return 1;
- } else return 1;
+ if (mods==0) { // line up
+ ascii = ctrl('P');
+ } else if (mods==FL_CTRL) { // scroll text down one page
+ // OS X scrolls the view, but does not move the cursor
+ // Fl_Input has no scroll control, so instead we move the cursor by one page
+ repeat_num = linesPerPage();
+ ascii = ctrl('P');
+ } else if (mods==FL_ALT) { // line start and up
+ if (line_start(position())==position() && position()>0)
+ return shift_position(line_start(position()-1)) + NORMAL_INPUT_MOVE;
+ else
+ return shift_position(line_start(position())) + NORMAL_INPUT_MOVE;
+ } else if (mods==FL_META) { // start of document
+ shift_position(0);
+ return 1;
+ } else return 1;
#else
- if (mods==0) { // line up
- ascii = ctrl('P');
- } else if (mods==FL_CTRL) { // scroll text down one line
- // Fl_Input has no scroll control, so instead we move the cursor by one page
- ascii = ctrl('P');
- } else return 1;
+ if (mods==0) { // line up
+ ascii = ctrl('P');
+ } else if (mods==FL_CTRL) { // scroll text down one line
+ // Fl_Input has no scroll control, so instead we move the cursor by one page
+ ascii = ctrl('P');
+ } else return 1;
#endif
- break;
- case FL_Page_Down:
+ break;
+ case FL_Page_Down:
#ifdef __APPLE__
- if (mods==0) { // scroll text one page
- // OS X scrolls the view, but does not move the cursor
- // Fl_Input has no scroll control, so instead we move the cursor by one page
- repeat_num = linesPerPage();
- ascii = ctrl('N');
- } else if (mods==FL_ALT) { // move cursor one page
- repeat_num = linesPerPage();
- ascii = ctrl('N');
- } else return 1;
- break;
+ if (mods==0) { // scroll text one page
+ // OS X scrolls the view, but does not move the cursor
+ // Fl_Input has no scroll control, so instead we move the cursor by one page
+ repeat_num = linesPerPage();
+ ascii = ctrl('N');
+ } else if (mods==FL_ALT) { // move cursor one page
+ repeat_num = linesPerPage();
+ ascii = ctrl('N');
+ } else return 1;
+ break;
#else
- repeat_num = linesPerPage();
- // fall through
+ repeat_num = linesPerPage();
+ // fall through
#endif
- case FL_Down:
+ case FL_Down:
#ifdef __APPLE__
- if (mods==0) { // line down
- ascii = ctrl('N');
- } else if (mods==FL_CTRL) {
- // OS X scrolls the view, but does not move the cursor
- // Fl_Input has no scroll control, so instead we move the cursor by one page
- repeat_num = linesPerPage();
- ascii = ctrl('N');
- } else if (mods==FL_ALT) { // line end and down
- if (line_end(position())==position() && position()<size())
- return shift_position(line_end(position()+1)) + NORMAL_INPUT_MOVE;
- else
- return shift_position(line_end(position())) + NORMAL_INPUT_MOVE;
- } else if (mods==FL_META) { // end of document
- shift_position(size());
- return 1;
- } else return 1;
+ if (mods==0) { // line down
+ ascii = ctrl('N');
+ } else if (mods==FL_CTRL) {
+ // OS X scrolls the view, but does not move the cursor
+ // Fl_Input has no scroll control, so instead we move the cursor by one page
+ repeat_num = linesPerPage();
+ ascii = ctrl('N');
+ } else if (mods==FL_ALT) { // line end and down
+ if (line_end(position())==position() && position()<size())
+ return shift_position(line_end(position()+1)) + NORMAL_INPUT_MOVE;
+ else
+ return shift_position(line_end(position())) + NORMAL_INPUT_MOVE;
+ } else if (mods==FL_META) { // end of document
+ shift_position(size());
+ return 1;
+ } else return 1;
#else
- if (mods==0) { // line down
- ascii = ctrl('N');
- } else if (mods==FL_CTRL) { // scroll text up one line
- // Fl_Input has no scroll control, so instead we move the cursor by one page
- ascii = ctrl('N');
- } else return 1;
+ if (mods==0) { // line down
+ ascii = ctrl('N');
+ } else if (mods==FL_CTRL) { // scroll text up one line
+ // Fl_Input has no scroll control, so instead we move the cursor by one page
+ ascii = ctrl('N');
+ } else return 1;
#endif
- break;
- case FL_Home:
+ break;
+ case FL_Home:
#ifdef __APPLE__
- if (mods==0) { // scroll display to the top
- // OS X scrolls the view, but does not move the cursor
- // Fl_Input has no scroll control, so instead we move the cursor by one page
- shift_position(0);
- return 1;
- } else return 1;
+ if (mods==0) { // scroll display to the top
+ // OS X scrolls the view, but does not move the cursor
+ // Fl_Input has no scroll control, so instead we move the cursor by one page
+ shift_position(0);
+ return 1;
+ } else return 1;
#else
- if (mods==0) {
- ascii = ctrl('A');
- } else if (mods==FL_CTRL) {
- shift_position(0);
- return 1;
- }
+ if (mods==0) {
+ ascii = ctrl('A');
+ } else if (mods==FL_CTRL) {
+ shift_position(0);
+ return 1;
+ }
#endif
- break;
- case FL_End:
+ break;
+ case FL_End:
#ifdef __APPLE__
- if (mods==0) { // scroll display to the bottom
- // OS X scrolls the view, but does not move the cursor
- // Fl_Input has no scroll control, so instead we move the cursor by one page
- shift_position(size());
- return 1;
- } else return 1;
+ if (mods==0) { // scroll display to the bottom
+ // OS X scrolls the view, but does not move the cursor
+ // Fl_Input has no scroll control, so instead we move the cursor by one page
+ shift_position(size());
+ return 1;
+ } else return 1;
#else
- if (mods==0) {
- ascii = ctrl('E');
- } else if (mods==FL_CTRL) {
- shift_position(size());
- return 1;
- } else return 1;
+ if (mods==0) {
+ ascii = ctrl('E');
+ } else if (mods==FL_CTRL) {
+ shift_position(size());
+ return 1;
+ } else return 1;
#endif
- break;
- case FL_BackSpace:
+ break;
+ case FL_BackSpace:
#ifdef __APPLE__
- if (mods==0 || mods==FL_CTRL) { // delete previous char
- ascii = ctrl('H');
- } else if (mods==FL_ALT) { // delete previous word
- if (mark() != position()) return cut();
- cut(word_start(position()), position());
- return 1;
- } else if (mods==FL_META) { // delete to the beginning of the line
- if (mark() != position()) return cut();
- cut(line_start(position()), position());
- return 1;
- } else return 1;
+ if (mods==0 || mods==FL_CTRL) { // delete previous char
+ ascii = ctrl('H');
+ } else if (mods==FL_ALT) { // delete previous word
+ if (mark() != position()) return cut();
+ cut(word_start(position()), position());
+ return 1;
+ } else if (mods==FL_META) { // delete to the beginning of the line
+ if (mark() != position()) return cut();
+ cut(line_start(position()), position());
+ return 1;
+ } else return 1;
#else
- ascii = ctrl('H');
+ ascii = ctrl('H');
#endif
- break;
- case FL_Enter:
- case FL_KP_Enter:
- if (when() & FL_WHEN_ENTER_KEY) {
- position(size(), 0);
- maybe_do_callback();
- return 1;
- } else if (input_type() == FL_MULTILINE_INPUT && !readonly())
- return replace(position(), mark(), "\n", 1);
- else
- return 0; // reserved for shortcuts
- case FL_Tab:
- if (Fl::event_state(FL_CTRL|FL_SHIFT) || input_type()!=FL_MULTILINE_INPUT || readonly()) return 0;
- return replace(position(), mark(), &ascii, 1);
+ break;
+ case FL_Enter:
+ case FL_KP_Enter:
+ if (when() & FL_WHEN_ENTER_KEY) {
+ position(size(), 0);
+ maybe_do_callback();
+ return 1;
+ } else if (input_type() == FL_MULTILINE_INPUT && !readonly())
+ return replace(position(), mark(), "\n", 1);
+ else
+ return 0; // reserved for shortcuts
+ case FL_Tab:
+ if (Fl::event_state(FL_CTRL|FL_SHIFT) || input_type()!=FL_MULTILINE_INPUT || readonly()) return 0;
+ return replace(position(), mark(), &ascii, 1);
#ifdef __APPLE__
- case 'c' :
- case 'v' :
- case 'x' :
- case 'z' :
-// printf("'%c' (0x%02x) pressed with%s%s%s%s\n", ascii, ascii,
-// Fl::event_state(FL_SHIFT) ? " FL_SHIFT" : "",
-// Fl::event_state(FL_CTRL) ? " FL_CTRL" : "",
-// Fl::event_state(FL_ALT) ? " FL_ALT" : "",
-// Fl::event_state(FL_META) ? " FL_META" : "");
- if (Fl::event_state(FL_META)) ascii -= 0x60;
-// printf("using '%c' (0x%02x)...\n", ascii, ascii);
- break;
+ case 'c' :
+ case 'v' :
+ case 'x' :
+ case 'z' :
+ // printf("'%c' (0x%02x) pressed with%s%s%s%s\n", ascii, ascii,
+ // Fl::event_state(FL_SHIFT) ? " FL_SHIFT" : "",
+ // Fl::event_state(FL_CTRL) ? " FL_CTRL" : "",
+ // Fl::event_state(FL_ALT) ? " FL_ALT" : "",
+ // Fl::event_state(FL_META) ? " FL_META" : "");
+ if (Fl::event_state(FL_META)) ascii -= 0x60;
+ // printf("using '%c' (0x%02x)...\n", ascii, ascii);
+ break;
#endif // __APPLE__
}
-
+
int i;
switch (ascii) {
- case ctrl('A'): // go to the beginning of the current line
- return shift_position(line_start(position())) + NORMAL_INPUT_MOVE;
- case ctrl('B'): // go one character backward
- return shift_position(position()-1) + NORMAL_INPUT_MOVE;
- case ctrl('C'): // copy
- return copy(1);
- case ctrl('D'): // cut the next character
- case ctrl('?'):
- if (readonly()) {
- fl_beep();
- return 1;
- }
- if (mark() != position()) return cut();
- else return cut(1);
- case ctrl('E'): // go to the end of the line
- return shift_position(line_end(position())) + NORMAL_INPUT_MOVE;
- case ctrl('F'): // go to the next character
- return shift_position(position()+1) + NORMAL_INPUT_MOVE;
- case ctrl('H'): // cut the previous character
- if (readonly()) {
- fl_beep();
- return 1;
- }
- if (mark() != position()) cut();
- else cut(-1);
- return 1;
- case ctrl('K'): // cut to the end of the line
- if (readonly()) {
- fl_beep();
- return 1;
- }
- if (position()>=size()) return 0;
- i = line_end(position());
- if (i == position() && i < size()) i++;
- cut(position(), i);
- return copy_cuts();
- case ctrl('N'): // go down one line
- i = position();
- if (line_end(i) >= size()) return NORMAL_INPUT_MOVE;
- while (repeat_num--) {
- i = line_end(i);
- if (i >= size()) break;
- i++;
- }
- shift_up_down_position(i);
- return 1;
- case ctrl('P'): // go up one line
- i = position();
- if (!line_start(i)) return NORMAL_INPUT_MOVE;
- while(repeat_num--) {
- i = line_start(i);
- if (!i) break;
- i--;
- }
- shift_up_down_position(line_start(i));
- return 1;
- case ctrl('U'): // clear the whole document?
- if (readonly()) {
- fl_beep();
- return 1;
- }
- return cut(0, size());
- case ctrl('V'): // paste text
- case ctrl('Y'):
- if (readonly()) {
- fl_beep();
+ case ctrl('A'): // go to the beginning of the current line
+ return shift_position(line_start(position())) + NORMAL_INPUT_MOVE;
+ case ctrl('B'): // go one character backward
+ return shift_position(position()-1) + NORMAL_INPUT_MOVE;
+ case ctrl('C'): // copy
+ return copy(1);
+ case ctrl('D'): // cut the next character
+ case ctrl('?'):
+ if (readonly()) {
+ fl_beep();
+ return 1;
+ }
+ if (mark() != position()) return cut();
+ else return cut(1);
+ case ctrl('E'): // go to the end of the line
+ return shift_position(line_end(position())) + NORMAL_INPUT_MOVE;
+ case ctrl('F'): // go to the next character
+ return shift_position(position()+1) + NORMAL_INPUT_MOVE;
+ case ctrl('H'): // cut the previous character
+ if (readonly()) {
+ fl_beep();
+ return 1;
+ }
+ if (mark() != position()) cut();
+ else cut(-1);
return 1;
- }
- Fl::paste(*this, 1);
- return 1;
- case ctrl('X'): // cut the selected text
- case ctrl('W'):
- if (readonly()) {
- fl_beep();
+ case ctrl('K'): // cut to the end of the line
+ if (readonly()) {
+ fl_beep();
+ return 1;
+ }
+ if (position()>=size()) return 0;
+ i = line_end(position());
+ if (i == position() && i < size()) i++;
+ cut(position(), i);
+ return copy_cuts();
+ case ctrl('N'): // go down one line
+ i = position();
+ if (line_end(i) >= size()) return NORMAL_INPUT_MOVE;
+ while (repeat_num--) {
+ i = line_end(i);
+ if (i >= size()) break;
+ i++;
+ }
+ shift_up_down_position(i);
return 1;
- }
- copy(1);
- return cut();
- case ctrl('Z'): // undo
- case ctrl('_'):
- if (readonly()) {
- fl_beep();
+ case ctrl('P'): // go up one line
+ i = position();
+ if (!line_start(i)) return NORMAL_INPUT_MOVE;
+ while(repeat_num--) {
+ i = line_start(i);
+ if (!i) break;
+ i--;
+ }
+ shift_up_down_position(line_start(i));
return 1;
- }
- return undo();
- case ctrl('I'): // insert literal
- case ctrl('J'):
- case ctrl('L'):
- case ctrl('M'):
- if (readonly()) {
- fl_beep();
+ case ctrl('U'): // clear the whole document?
+ if (readonly()) {
+ fl_beep();
+ return 1;
+ }
+ return cut(0, size());
+ case ctrl('V'): // paste text
+ case ctrl('Y'):
+ if (readonly()) {
+ fl_beep();
+ return 1;
+ }
+ Fl::paste(*this, 1);
return 1;
- }
- // insert a few selected control characters literally:
- if (input_type() != FL_FLOAT_INPUT && input_type() != FL_INT_INPUT)
- return replace(position(), mark(), &ascii, 1);
+ case ctrl('X'): // cut the selected text
+ case ctrl('W'):
+ if (readonly()) {
+ fl_beep();
+ return 1;
+ }
+ copy(1);
+ return cut();
+ case ctrl('Z'): // undo
+ case ctrl('_'):
+ if (readonly()) {
+ fl_beep();
+ return 1;
+ }
+ return undo();
+ case ctrl('I'): // insert literal
+ case ctrl('J'):
+ case ctrl('L'):
+ case ctrl('M'):
+ if (readonly()) {
+ fl_beep();
+ return 1;
+ }
+ // insert a few selected control characters literally:
+ if (input_type() != FL_FLOAT_INPUT && input_type() != FL_INT_INPUT)
+ return replace(position(), mark(), &ascii, 1);
}
-
+
return 0;
}
diff --git a/test/tree.cxx b/test/tree.cxx
index 6ddd847d5..21b6b52a7 100644
--- a/test/tree.cxx
+++ b/test/tree.cxx
@@ -90,7 +90,7 @@ static void cb_tree(Fl_Tree*, void*) {
Fl_Tree_Item *item = tree->item_clicked();
//item->select( item->is_selected() ? 0 : 1);
//tree->redraw();
- fprintf(stderr, "TREE CALLBACK: label='%s' userdata=%d\n",
+ fprintf(stderr, "TREE CALLBACK: label='%s' userdata=%ld\n",
item->label(),
(long)tree->user_data());
}