summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorManolo Gouy <Manolo>2012-12-24 11:45:07 +0000
committerManolo Gouy <Manolo>2012-12-24 11:45:07 +0000
commitcf672dba0db831679ba0cb5b9966a6dd1bbcb6e5 (patch)
treea01386823937540124aaf43c9f6237a0c4b1fc99 /src
parent3c72b20458c943f650ddc071577b9876461d6389 (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.cxx22
-rw-r--r--src/Fl_Input_.cxx14
-rw-r--r--src/Fl_Text_Display.cxx12
-rw-r--r--src/Fl_Text_Editor.cxx17
-rw-r--r--src/Fl_cocoa.mm52
-rw-r--r--src/Fl_compose.cxx63
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
}
//