diff options
| author | Manolo Gouy <Manolo> | 2012-12-24 11:45:07 +0000 |
|---|---|---|
| committer | Manolo Gouy <Manolo> | 2012-12-24 11:45:07 +0000 |
| commit | cf672dba0db831679ba0cb5b9966a6dd1bbcb6e5 (patch) | |
| tree | a01386823937540124aaf43c9f6237a0c4b1fc99 /src | |
| parent | 3c72b20458c943f650ddc071577b9876461d6389 (diff) | |
Mac OS text input: defined a small API that user-defined text editing widgets can use to signal marked text.
git-svn-id: file:///fltk/svn/fltk/branches/branch-1.3@9774 ea41ed52-d2ee-0310-a9c1-e6b18d33e121
Diffstat (limited to 'src')
| -rw-r--r-- | src/Fl_Input.cxx | 22 | ||||
| -rw-r--r-- | src/Fl_Input_.cxx | 14 | ||||
| -rw-r--r-- | src/Fl_Text_Display.cxx | 12 | ||||
| -rw-r--r-- | src/Fl_Text_Editor.cxx | 17 | ||||
| -rw-r--r-- | src/Fl_cocoa.mm | 52 | ||||
| -rw-r--r-- | src/Fl_compose.cxx | 63 |
6 files changed, 126 insertions, 54 deletions
diff --git a/src/Fl_Input.cxx b/src/Fl_Input.cxx index 094912ea1..80d7cf955 100644 --- a/src/Fl_Input.cxx +++ b/src/Fl_Input.cxx @@ -358,6 +358,11 @@ int Fl_Input::handle_key() { else replace(position(), del ? position()-del : mark(), Fl::event_text(), Fl::event_length()); } +#ifdef __APPLE__ + if (Fl::marked_text_length()) { + this->mark( this->position() - Fl::marked_text_length() ); + } +#endif return 1; } @@ -585,6 +590,14 @@ int Fl_Input::handle(int event) { static int dnd_save_position, dnd_save_mark, drag_start = -1, newpos; static Fl_Widget *dnd_save_focus; switch (event) { +#ifdef __APPLE__ + case FL_UNFOCUS: + if (Fl::marked_text_length()) { + this->mark( this->position() ); + Fl::reset_marked_text(); + } + break; +#endif case FL_FOCUS: switch (Fl::event_key()) { case FL_Right: @@ -799,6 +812,15 @@ Fl_Secret_Input::Fl_Secret_Input(int X,int Y,int W,int H,const char *l) type(FL_SECRET_INPUT); } +int Fl_Secret_Input::handle(int event) { + int retval = Fl_Input::handle(event); +#ifdef __APPLE__ + if (event == FL_KEYBOARD && Fl::marked_text_length()) { + this->mark( this->position() ); // don't underline marked text + } +#endif + return retval; +} // // End of "$Id$". diff --git a/src/Fl_Input_.cxx b/src/Fl_Input_.cxx index bf96bd4c9..644d954c3 100644 --- a/src/Fl_Input_.cxx +++ b/src/Fl_Input_.cxx @@ -339,8 +339,8 @@ void Fl_Input_::drawtext(int X, int Y, int W, int H) { int offset2; if (pp <= e) x2 = xpos + (float)expandpos(p, pp, buf, &offset2); else offset2 = (int) strlen(buf); -#ifdef __APPLE__ // Mac OS: underline marked ( = selected + Fl::compose_state != 0) text - if (Fl::compose_state) { +#ifdef __APPLE__ // Mac OS: underline marked ( = selected + Fl::marked_text_length() != 0) text + if (Fl::marked_text_length()) { fl_color(textcolor()); } else @@ -351,8 +351,8 @@ void Fl_Input_::drawtext(int X, int Y, int W, int H) { fl_color(fl_contrast(textcolor(), selection_color())); } fl_draw(buf+offset1, offset2-offset1, x1, (float)(Y+ypos+desc)); -#ifdef __APPLE__ // Mac OS: underline marked ( = selected + Fl::compose_state != 0) text - if (Fl::compose_state) { +#ifdef __APPLE__ // Mac OS: underline marked ( = selected + Fl::marked_text_length() != 0) text + if (Fl::marked_text_length()) { fl_color( fl_color_average(textcolor(), color(), 0.6) ); float width = fl_width(buf+offset1, offset2-offset1); fl_line(x1, Y+ypos+height-1, x1+width, Y+ypos+height-1); @@ -372,7 +372,11 @@ void Fl_Input_::drawtext(int X, int Y, int W, int H) { CONTINUE2: // draw the cursor: - if (Fl::focus() == this && (Fl::compose_state || selstart == selend) && + if (Fl::focus() == this && ( +#ifdef __APPLE__ + Fl::marked_text_length() || +#endif + selstart == selend) && position() >= p-value() && position() <= e-value()) { fl_color(cursor_color()); // cursor position may need to be recomputed (see STR #2486) diff --git a/src/Fl_Text_Display.cxx b/src/Fl_Text_Display.cxx index fb0eee61c..5c418fc7d 100644 --- a/src/Fl_Text_Display.cxx +++ b/src/Fl_Text_Display.cxx @@ -1942,7 +1942,7 @@ void Fl_Text_Display::draw_string(int style, if (style & PRIMARY_MASK) { if (Fl::focus() == (Fl_Widget*)this) { #ifdef __APPLE__ - if (Fl::compose_state) background = color();// Mac OS: underline marked text + if (Fl::marked_text_length()) background = color();// Mac OS: underline marked text else #endif background = selection_color(); @@ -1978,8 +1978,8 @@ void Fl_Text_Display::draw_string(int style, fl_push_clip(X, Y, toX - X, mMaxsize); #endif fl_draw( string, nChars, X, Y + mMaxsize - fl_descent()); -#ifdef __APPLE__ // Mac OS: underline marked (= selected + Fl::compose_state != 0) text - if (Fl::compose_state && (style & PRIMARY_MASK)) { +#ifdef __APPLE__ // Mac OS: underline marked (= selected + Fl::marked_text_length() != 0) text + if (Fl::marked_text_length() && (style & PRIMARY_MASK)) { fl_color( fl_color_average(foreground, background, 0.6) ); fl_line(X, Y + mMaxsize - 1, X + fl_width(string, nChars), Y + mMaxsize - 1); } @@ -3469,7 +3469,11 @@ void Fl_Text_Display::draw(void) { // draw the text cursor if (damage() & (FL_DAMAGE_ALL | FL_DAMAGE_SCROLL | FL_DAMAGE_EXPOSE) - && (Fl::compose_state || !buffer()->primary_selection()->selected()) && + && ( +#ifdef __APPLE__ + Fl::marked_text_length() || +#endif + !buffer()->primary_selection()->selected()) && mCursorOn && Fl::focus() == (Fl_Widget*)this ) { fl_push_clip(text_area.x-LEFT_MARGIN, text_area.y, diff --git a/src/Fl_Text_Editor.cxx b/src/Fl_Text_Editor.cxx index d13fd7139..b580951ae 100644 --- a/src/Fl_Text_Editor.cxx +++ b/src/Fl_Text_Editor.cxx @@ -524,6 +524,16 @@ int Fl_Text_Editor::handle_key() { if (insert_mode()) insert(Fl::event_text()); else overstrike(Fl::event_text()); } +#ifdef __APPLE__ + if (Fl::marked_text_length()) { + int x, y; + int pos = this->insert_position(); + this->buffer()->select(pos - Fl::marked_text_length(), pos); + this->position_to_xy( this->insert_position(), &x, &y); + y += this->textsize(); + Fl::insertion_point_location(x, y); + } +#endif show_insert_position(); set_changed(); if (when()&FL_WHEN_CHANGED) do_callback(); @@ -561,6 +571,13 @@ int Fl_Text_Editor::handle(int event) { case FL_UNFOCUS: show_cursor(mCursorOn); // redraws the cursor +#ifdef __APPLE__ + if (buffer()->selected() && Fl::marked_text_length()) { + int pos = insert_position(); + buffer()->select(pos, pos); + Fl::reset_marked_text(); + } +#endif if (buffer()->selected()) redraw(); // Redraw selections... case FL_HIDE: if (when() & FL_WHEN_RELEASE) maybe_do_callback(); diff --git a/src/Fl_cocoa.mm b/src/Fl_cocoa.mm index 293dd80c6..20733b974 100644 --- a/src/Fl_cocoa.mm +++ b/src/Fl_cocoa.mm @@ -1929,15 +1929,15 @@ static void q_set_window_title(NSWindow *nsw, const char * name, const char *mi } else { received = (NSString*)aString; } - //NSLog(@"insertText: received=%@ Fl::compose_state=%d",received,Fl::compose_state); + //NSLog(@"insertText: received=%@ Fl::marked_text_length()=%d",received,Fl::marked_text_length()); fl_lock_function(); [FLView prepareEtext:received]; // We can get called outside of key events (e.g., from the character palette, from CJK text input). // Transform character palette actions to FL_PASTE events. Fl_Window *target = [(FLWindow*)[self window] getFl_Window]; - Fl::handle( (in_key_event || Fl::compose_state) ? FL_KEYBOARD : FL_PASTE, target); - Fl_X::compose_state(0); + Fl_X::next_marked_length = 0; + Fl::handle( (in_key_event || Fl::marked_text_length()) ? FL_KEYBOARD : FL_PASTE, target); // for some reason, with the palette, the window does not redraw until the next mouse move or button push // sending a 'redraw()' or 'awake()' does not solve the issue! @@ -1956,18 +1956,18 @@ static void q_set_window_title(NSWindow *nsw, const char * name, const char *mi // This code creates the OS X behaviour of seeing dead keys as things // are being composed. [FLView prepareEtext:received]; - /*NSLog(@"setMarkedText:%@ %d %d Fl::compose_state=%d Fl::e_length=%d", - received, newSelection.location, newSelection.length, Fl::compose_state, Fl::e_length);*/ + /*NSLog(@"setMarkedText:%@ %d %d Fl::marked_text_length()=%d Fl::e_length=%d", + received, newSelection.location, newSelection.length, Fl::marked_text_length(), Fl::e_length);*/ Fl_Window *target = [(FLWindow*)[self window] getFl_Window]; + Fl_X::next_marked_length = Fl::e_length; Fl::handle(FL_KEYBOARD, target); - Fl_X::compose_state(Fl::e_length); fl_unlock_function(); } - (void)unmarkText { fl_lock_function(); - Fl_X::compose_state(0); + Fl::reset_marked_text(); fl_unlock_function(); //NSLog(@"unmarkText"); } @@ -1977,13 +1977,13 @@ static void q_set_window_title(NSWindow *nsw, const char * name, const char *mi } - (NSRange)markedRange { - //NSLog(@"markedRange=%d %d", Fl::compose_state > 0?0:NSNotFound, Fl::compose_state); - return NSMakeRange(Fl::compose_state > 0?0:NSNotFound, Fl::compose_state); + //NSLog(@"markedRange=%d %d", Fl::marked_text_length() > 0?0:NSNotFound, Fl::marked_text_length()); + return NSMakeRange(Fl::marked_text_length() > 0?0:NSNotFound, Fl::marked_text_length()); } - (BOOL)hasMarkedText { - //NSLog(@"hasMarkedText %s", Fl::compose_state > 0?"YES":"NO"); - return (Fl::compose_state > 0); + //NSLog(@"hasMarkedText %s", Fl::marked_text_length() > 0?"YES":"NO"); + return (Fl::marked_text_length() > 0); } - (NSAttributedString *)attributedSubstringFromRange:(NSRange)aRange { @@ -2004,13 +2004,10 @@ static void q_set_window_title(NSWindow *nsw, const char * name, const char *mi if (!focus) focus = wfocus; glyphRect.size.width = 0; - Fl_Text_Display *current = dynamic_cast<Fl_Text_Display*>(focus); - if (current) { - int x, y; - current->position_to_xy( current->insert_position(), &x, &y ); + int x, y; + if (Fl_X::insertion_point_location(&x, &y)) { glyphRect.origin.x = (CGFloat)x; - glyphRect.origin.y = (CGFloat)y + current->textsize(); - glyphRect.size.height = current->textsize(); + glyphRect.origin.y = (CGFloat)y; } else { if (focus->as_window()) { glyphRect.origin.x = 0; @@ -2020,8 +2017,8 @@ static void q_set_window_title(NSWindow *nsw, const char * name, const char *mi glyphRect.origin.x = focus->x(); glyphRect.origin.y = focus->y() + focus->h(); } - glyphRect.size.height = 12; } + glyphRect.size.height = 12; Fl_Window *win = focus->as_window(); if (!win) win = focus->window(); while (win != NULL && win != wfocus) { @@ -2046,25 +2043,6 @@ static void q_set_window_title(NSWindow *nsw, const char * name, const char *mi @end -void Fl_X::compose_state(int new_val) -{ // select marked text in text widgets - if (Fl::compose_state == 0 && new_val == 0) return; - Fl::compose_state = new_val; - Fl_Widget *widget = Fl::focus(); - if (!widget) return; - - Fl_Input_* input = dynamic_cast<Fl_Input_*>(widget); - Fl_Text_Display* text; - if (input) { - if ( ! dynamic_cast<Fl_Secret_Input*>(input) ) - input->mark( input->position() - Fl::compose_state ); - } - else if ( (text = dynamic_cast<Fl_Text_Display*>(widget)) ) { - int pos = text->insert_position(); - text->buffer()->select(pos - Fl::compose_state, pos); - } -} - void Fl_Window::fullscreen_x() { _set_fullscreen(); /* On OS X < 10.6, it is necessary to recreate the window. This is done diff --git a/src/Fl_compose.cxx b/src/Fl_compose.cxx index 8aea820d1..138d3477c 100644 --- a/src/Fl_compose.cxx +++ b/src/Fl_compose.cxx @@ -21,6 +21,9 @@ #ifndef FL_DOXYGEN int Fl::compose_state = 0; +#ifdef __APPLE__ +int Fl_X::next_marked_length = 0; +#endif #endif #if !defined(WIN32) && !defined(__APPLE__) @@ -41,6 +44,23 @@ extern XIC fl_xim_ic; keys, and del is set to zero. You could insert the text anyways, if you don't know what else to do. + <p>On the Mac OS platform, text editing widgets should preferentially signal + marked text, that is, temporary text replaced by other text during the text + input process. Such signaling is usually done underlining marked text. Widgets can call + <tt>int Fl::marked_text_length()</tt> <i>after</i> having called Fl::compose(int&) + to obtain the length in bytes of marked text that always finishes at the + current insertion point. It's the widget's task to underline marked text. + Widgets should also call <tt>void Fl::reset_marked_text()</tt> when processing FL_UNFOCUS events. + Optionally, widgets can also call + <tt>void Fl::insertion_point_location(int x, int y)</tt> to indicate the window + coordinates of the bottom of the current insertion point. + This way, auxiliary windows that help choosing among alternative characters + appear just below the insertion point. If widgets don't do that, + auxiliary windows appear at the widget's bottom. The + Fl_Input and Fl_Text_Editor widgets signal marked text underlining it. + If none of this is done by a user-defined text editing widget, complex + (e.g., CJK) text input will work, but will not signal to the user what text is marked. + <p>Though the current implementation returns immediately, future versions may take quite awhile, as they may pop up a window or do other user-interface things to allow characters to be selected. @@ -59,11 +79,13 @@ unsigned char ascii = (unsigned char)e_text[0]; condition = (e_state & (FL_ALT | FL_META)) && !(ascii & 128) ; #else condition = (e_state & (FL_ALT | FL_META | FL_CTRL)) && !(ascii & 128) ; -#endif -#endif +#endif // WIN32 +#endif // __APPLE__ if (condition) { del = 0; return 0;} // this stuff is to be treated as a function key del = Fl::compose_state; -#ifndef __APPLE__ +#ifdef __APPLE__ + Fl::compose_state = Fl_X::next_marked_length; +#else Fl::compose_state = 0; // Only insert non-control characters: if ( (!Fl::compose_state) && ! (ascii & ~31 && ascii!=127)) { return 0; } @@ -71,6 +93,35 @@ unsigned char ascii = (unsigned char)e_text[0]; return 1; } +#ifdef __APPLE__ +int Fl::marked_text_length() { + return (Fl::compose_state ? Fl::compose_state : Fl_X::next_marked_length); + } + +static int insertion_point_x = 0; +static int insertion_point_y = 0; +static bool insertion_point_location_is_valid = false; + +void Fl::reset_marked_text() { + Fl::compose_state = 0; + Fl_X::next_marked_length = 0; + insertion_point_location_is_valid = false; + } +int Fl_X::insertion_point_location(int *px, int *py) +// return true if the current coordinates of the insertion point are available +{ + if ( ! insertion_point_location_is_valid ) return false; + *px = insertion_point_x; + *py = insertion_point_y; + return true; +} +void Fl::insertion_point_location(int x, int y) { + insertion_point_location_is_valid = true; + insertion_point_x = x; + insertion_point_y = y; +} +#endif // __APPLE__ + /** If the user moves the cursor, be sure to call Fl::compose_reset(). The next call to Fl::compose() will start out in an initial state. In @@ -79,14 +130,10 @@ unsigned char ascii = (unsigned char)e_text[0]; */ void Fl::compose_reset() { -#ifdef __APPLE__ - Fl_X::compose_state(0); -#else Fl::compose_state = 0; -#if !defined(WIN32) +#if !defined(WIN32) && !defined(__APPLE__) if (fl_xim_ic) XmbResetIC(fl_xim_ic); #endif -#endif } // |
