Author: manolo
Date: 2012-12-24 03:45:07 -0800 (Mon, 24 Dec 2012)
New Revision: 9774
Log:
Mac OS text input: defined a small API that user-defined text editing widgets 
can use to signal marked text.

Modified:
   branches/branch-1.3/FL/Fl.H
   branches/branch-1.3/FL/Fl_Secret_Input.H
   branches/branch-1.3/FL/mac.H
   branches/branch-1.3/src/Fl_Input.cxx
   branches/branch-1.3/src/Fl_Input_.cxx
   branches/branch-1.3/src/Fl_Text_Display.cxx
   branches/branch-1.3/src/Fl_Text_Editor.cxx
   branches/branch-1.3/src/Fl_cocoa.mm
   branches/branch-1.3/src/Fl_compose.cxx

Modified: branches/branch-1.3/FL/Fl.H
===================================================================
--- branches/branch-1.3/FL/Fl.H 2012-12-24 04:06:46 UTC (rev 9773)
+++ branches/branch-1.3/FL/Fl.H 2012-12-24 11:45:07 UTC (rev 9774)
@@ -144,7 +144,12 @@
   static Fl_Window* grab_;
   static int compose_state;
   static void call_screen_init(); // recompute screen number and dimensions
+#ifdef __APPLE__
+  static int marked_text_length(void); // returns length of marked text
+  static void reset_marked_text(); // resets marked text
+  static void insertion_point_location(int x, int y); // sets window 
coordinates of insertion point
 #endif
+#endif
   /**
     If true then flush() will do something.
   */

Modified: branches/branch-1.3/FL/Fl_Secret_Input.H
===================================================================
--- branches/branch-1.3/FL/Fl_Secret_Input.H    2012-12-24 04:06:46 UTC (rev 
9773)
+++ branches/branch-1.3/FL/Fl_Secret_Input.H    2012-12-24 11:45:07 UTC (rev 
9774)
@@ -41,6 +41,7 @@
     Inherited destructor destroys the widget and any value associated with it.
   */
   Fl_Secret_Input(int X,int Y,int W,int H,const char *l = 0);
+  int handle(int);
 };
 
 #endif

Modified: branches/branch-1.3/FL/mac.H
===================================================================
--- branches/branch-1.3/FL/mac.H        2012-12-24 04:06:46 UTC (rev 9773)
+++ branches/branch-1.3/FL/mac.H        2012-12-24 11:45:07 UTC (rev 9774)
@@ -131,7 +131,8 @@
   static CGContextRef none_cursor_image(void);
   static void *get_carbon_function(const char *name);
   static void screen_work_area(int &X, int &Y, int &W, int &H, int n); // 
compute work area of a given screen
-  static void compose_state(int);
+  static int next_marked_length; // next length of marked text after current 
marked text will have been replaced
+  static int insertion_point_location(int *px, int *py); // computes window 
coordinates of insertion point
 private:
   static void relink(Fl_Window*, Fl_Window*);
   bool subwindow;

Modified: branches/branch-1.3/src/Fl_Input.cxx
===================================================================
--- branches/branch-1.3/src/Fl_Input.cxx        2012-12-24 04:06:46 UTC (rev 
9773)
+++ branches/branch-1.3/src/Fl_Input.cxx        2012-12-24 11:45:07 UTC (rev 
9774)
@@ -358,6 +358,11 @@
       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 @@
   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 @@
   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$".

Modified: branches/branch-1.3/src/Fl_Input_.cxx
===================================================================
--- branches/branch-1.3/src/Fl_Input_.cxx       2012-12-24 04:06:46 UTC (rev 
9773)
+++ branches/branch-1.3/src/Fl_Input_.cxx       2012-12-24 11:45:07 UTC (rev 
9774)
@@ -339,8 +339,8 @@
       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 @@
       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 @@
 
   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)

Modified: branches/branch-1.3/src/Fl_Text_Display.cxx
===================================================================
--- branches/branch-1.3/src/Fl_Text_Display.cxx 2012-12-24 04:06:46 UTC (rev 
9773)
+++ branches/branch-1.3/src/Fl_Text_Display.cxx 2012-12-24 11:45:07 UTC (rev 
9774)
@@ -1942,7 +1942,7 @@
     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 @@
     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 @@
 
   // 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,

Modified: branches/branch-1.3/src/Fl_Text_Editor.cxx
===================================================================
--- branches/branch-1.3/src/Fl_Text_Editor.cxx  2012-12-24 04:06:46 UTC (rev 
9773)
+++ branches/branch-1.3/src/Fl_Text_Editor.cxx  2012-12-24 11:45:07 UTC (rev 
9774)
@@ -524,6 +524,16 @@
       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 @@
 
     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();

Modified: branches/branch-1.3/src/Fl_cocoa.mm
===================================================================
--- branches/branch-1.3/src/Fl_cocoa.mm 2012-12-24 04:06:46 UTC (rev 9773)
+++ branches/branch-1.3/src/Fl_cocoa.mm 2012-12-24 11:45:07 UTC (rev 9774)
@@ -1929,15 +1929,15 @@
   } 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 @@
   // 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 @@
 }
 
 - (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 @@
   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 @@
       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 @@
 
 @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

Modified: branches/branch-1.3/src/Fl_compose.cxx
===================================================================
--- branches/branch-1.3/src/Fl_compose.cxx      2012-12-24 04:06:46 UTC (rev 
9773)
+++ branches/branch-1.3/src/Fl_compose.cxx      2012-12-24 11:45:07 UTC (rev 
9774)
@@ -21,7 +21,10 @@
 
 #ifndef FL_DOXYGEN
 int Fl::compose_state = 0;
+#ifdef __APPLE__
+int Fl_X::next_marked_length = 0;
 #endif
+#endif
 
 #if !defined(WIN32) && !defined(__APPLE__)
 extern XIC fl_xim_ic;
@@ -41,6 +44,23 @@
  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 @@
   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 @@
   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 @@
  */
 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
 }
 
 //

_______________________________________________
fltk-commit mailing list
[email protected]
http://lists.easysw.com/mailman/listinfo/fltk-commit

Reply via email to