fltk 1.3.0rc3
About: FLTK (Fast Light Tool Kit) is a cross-platform C++ GUI toolkit for UNIX/Linux (X11), Microsoft Windows, and MacOS X. Release candidate.
  SfR Fresh Dox: fltk-1.3.0rc3-source.tar.gz ("inofficial" and yet experimental doxygen-generated source code documentation)  

Fl_Text_Editor.cxx

Go to the documentation of this file.
00001 //
00002 // "$Id: Fl_Text_Editor.cxx 8034 2010-12-15 12:21:55Z AlbrechtS $"
00003 //
00004 // Copyright 2001-2010 by Bill Spitzak and others.
00005 // Original code Copyright Mark Edel.  Permission to distribute under
00006 // the LGPL for the FLTK library granted by Mark Edel.
00007 //
00008 // This library is free software; you can redistribute it and/or
00009 // modify it under the terms of the GNU Library General Public
00010 // License as published by the Free Software Foundation; either
00011 // version 2 of the License, or (at your option) any later version.
00012 //
00013 // This library is distributed in the hope that it will be useful,
00014 // but WITHOUT ANY WARRANTY; without even the implied warranty of
00015 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00016 // Library General Public License for more details.
00017 //
00018 // You should have received a copy of the GNU Library General Public
00019 // License along with this library; if not, write to the Free Software
00020 // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
00021 // USA.
00022 //
00023 // Please report all bugs and problems on the following page:
00024 //
00025 //     http://www.fltk.org/str.php
00026 //
00027 
00028 #include <stdio.h>
00029 #include <stdlib.h>
00030 #include "flstring.h"
00031 #include <ctype.h>
00032 #include <FL/Fl.H>
00033 #include <FL/Fl_Window.H>
00034 #include <FL/Fl_Text_Editor.H>
00035 #include <FL/fl_ask.H>
00036 
00037 
00038 /* Keyboard Control Matrix
00039 
00040 key\modifier   plain  Ctrl   Alt  Meta  
00041   left          1/1  13/9   0/13  0/9  
00042   right         2/2  14/10  0/14  0/10  
00043   up            3/19 21/7   0/15  0/17 
00044   down          4/20 22/8   0/16  0/18
00045   home          9/5  17/0   0/0   0/0
00046   end          10/6  18/0   0/0   0/0
00047   page up      11/7  23/0   0/11  0/0
00048   page down    12/8  24/0   0/12  0/0
00049     (FLTK action / OS X action)
00050     (adding the shift key extends the selection, all other combinations are no-op)
00051 
00052   0: no-op
00053   1: move cursor to the left, at line beginning wrap to end of prev line, at doc start no-op
00054   2: move cursor to the right, at line end move to beginning of the next line, at doc end no-op
00055   3: move cursor up, at doc top no-op
00056   4: move cursor down, at doc bottom no-op
00057   5: scroll display to top of text (cursor unchanged)
00058   6: scroll display to end of text (cursor unchanged)
00059   7: scroll text down one page (cursor unchanged)
00060   8: scroll text up one page (cursor unchanged)
00061   9: move cursor to beginning of line
00062  10: move cursor to end of line
00063  11: move cursor up one page and scroll down
00064  12: move cursor down one page and scroll up
00065  13: move to the beginning of the word or the previous word
00066  14: move to the end of the word or the next word
00067  15: if start of line: start of prev line, else start of this line
00068  16: if end of line: end of next line, else end of this line
00069  17: move cursor to the beginning of the document
00070  18: move cursor to the end of the document
00071  19: move cursor up, at doc top: home, at doc start: no-op)
00072  20: move cursor down, at doc bot: end, at doc end: no-op)
00073  21: scroll text down one line (cursor unchanged)
00074  22: scroll text up one line (cursor unchanged)
00075  23: move cursor to the beginning of the top of the screen
00076  24: move cursor to the beginning of the bottom of the window
00077 */
00078 
00080 Fl_Text_Editor::Fl_Text_Editor(int X, int Y, int W, int H,  const char* l)
00081     : Fl_Text_Display(X, Y, W, H, l) {
00082   mCursorOn = 1;
00083   insert_mode_ = 1;
00084   key_bindings = 0;
00085 
00086   // handle the default key bindings
00087   add_default_key_bindings(&key_bindings);
00088 
00089   // handle everything else
00090   default_key_function(kf_default);
00091 }
00092 
00093 #ifndef FL_DOXYGEN
00094 Fl_Text_Editor::Key_Binding* Fl_Text_Editor::global_key_bindings = 0;
00095 #endif
00096 
00097 // These are the default key bindings every widget should start with
00098 static struct {
00099   int key;
00100   int state;
00101   Fl_Text_Editor::Key_Func func;
00102 } default_key_bindings[] = {
00103   { FL_Escape,    FL_TEXT_EDITOR_ANY_STATE, Fl_Text_Editor::kf_ignore     },
00104   { FL_Enter,     FL_TEXT_EDITOR_ANY_STATE, Fl_Text_Editor::kf_enter      },
00105   { FL_KP_Enter,  FL_TEXT_EDITOR_ANY_STATE, Fl_Text_Editor::kf_enter      },
00106   { FL_BackSpace, FL_TEXT_EDITOR_ANY_STATE, Fl_Text_Editor::kf_backspace  },
00107   { FL_Insert,    FL_TEXT_EDITOR_ANY_STATE, Fl_Text_Editor::kf_insert     },
00108   { FL_Delete,    FL_TEXT_EDITOR_ANY_STATE, Fl_Text_Editor::kf_delete     },
00109   { FL_Home,      0,                        Fl_Text_Editor::kf_move       },
00110   { FL_End,       0,                        Fl_Text_Editor::kf_move       },
00111   { FL_Left,      0,                        Fl_Text_Editor::kf_move       },
00112   { FL_Up,        0,                        Fl_Text_Editor::kf_move       },
00113   { FL_Right,     0,                        Fl_Text_Editor::kf_move       },
00114   { FL_Down,      0,                        Fl_Text_Editor::kf_move       },
00115   { FL_Page_Up,   0,                        Fl_Text_Editor::kf_move       },
00116   { FL_Page_Down, 0,                        Fl_Text_Editor::kf_move       },
00117   { FL_Home,      FL_SHIFT,                 Fl_Text_Editor::kf_shift_move },
00118   { FL_End,       FL_SHIFT,                 Fl_Text_Editor::kf_shift_move },
00119   { FL_Left,      FL_SHIFT,                 Fl_Text_Editor::kf_shift_move },
00120   { FL_Up,        FL_SHIFT,                 Fl_Text_Editor::kf_shift_move },
00121   { FL_Right,     FL_SHIFT,                 Fl_Text_Editor::kf_shift_move },
00122   { FL_Down,      FL_SHIFT,                 Fl_Text_Editor::kf_shift_move },
00123   { FL_Page_Up,   FL_SHIFT,                 Fl_Text_Editor::kf_shift_move },
00124   { FL_Page_Down, FL_SHIFT,                 Fl_Text_Editor::kf_shift_move },
00125   { FL_Home,      FL_CTRL,                  Fl_Text_Editor::kf_ctrl_move  },
00126   { FL_End,       FL_CTRL,                  Fl_Text_Editor::kf_ctrl_move  },
00127   { FL_Left,      FL_CTRL,                  Fl_Text_Editor::kf_ctrl_move  },
00128   { FL_Up,        FL_CTRL,                  Fl_Text_Editor::kf_ctrl_move  },
00129   { FL_Right,     FL_CTRL,                  Fl_Text_Editor::kf_ctrl_move  },
00130   { FL_Down,      FL_CTRL,                  Fl_Text_Editor::kf_ctrl_move  },
00131   { FL_Page_Up,   FL_CTRL,                  Fl_Text_Editor::kf_ctrl_move  },
00132   { FL_Page_Down, FL_CTRL,                  Fl_Text_Editor::kf_ctrl_move  },
00133   { FL_Home,      FL_CTRL|FL_SHIFT,         Fl_Text_Editor::kf_c_s_move   },
00134   { FL_End,       FL_CTRL|FL_SHIFT,         Fl_Text_Editor::kf_c_s_move   },
00135   { FL_Left,      FL_CTRL|FL_SHIFT,         Fl_Text_Editor::kf_c_s_move   },
00136   { FL_Up,        FL_CTRL|FL_SHIFT,         Fl_Text_Editor::kf_c_s_move   },
00137   { FL_Right,     FL_CTRL|FL_SHIFT,         Fl_Text_Editor::kf_c_s_move   },
00138   { FL_Down,      FL_CTRL|FL_SHIFT,         Fl_Text_Editor::kf_c_s_move   },
00139   { FL_Page_Up,   FL_CTRL|FL_SHIFT,         Fl_Text_Editor::kf_c_s_move   },
00140   { FL_Page_Down, FL_CTRL|FL_SHIFT,         Fl_Text_Editor::kf_c_s_move   },
00141 //{ FL_Clear,     0,                        Fl_Text_Editor::delete_to_eol },
00142   { 'z',          FL_CTRL,                  Fl_Text_Editor::kf_undo       },
00143   { '/',          FL_CTRL,                  Fl_Text_Editor::kf_undo       },
00144   { 'x',          FL_CTRL,                  Fl_Text_Editor::kf_cut        },
00145   { FL_Delete,    FL_SHIFT,                 Fl_Text_Editor::kf_cut        },
00146   { 'c',          FL_CTRL,                  Fl_Text_Editor::kf_copy       },
00147   { FL_Insert,    FL_CTRL,                  Fl_Text_Editor::kf_copy       },
00148   { 'v',          FL_CTRL,                  Fl_Text_Editor::kf_paste      },
00149   { FL_Insert,    FL_SHIFT,                 Fl_Text_Editor::kf_paste      },
00150   { 'a',          FL_CTRL,                  Fl_Text_Editor::kf_select_all },
00151 
00152 #ifdef __APPLE__
00153   // Define CMD+key accelerators...
00154   { 'z',          FL_COMMAND,               Fl_Text_Editor::kf_undo       },
00155   { 'x',          FL_COMMAND,               Fl_Text_Editor::kf_cut        },
00156   { 'c',          FL_COMMAND,               Fl_Text_Editor::kf_copy       },
00157   { 'v',          FL_COMMAND,               Fl_Text_Editor::kf_paste      },
00158   { 'a',          FL_COMMAND,               Fl_Text_Editor::kf_select_all },
00159   { FL_Left,      FL_COMMAND,               Fl_Text_Editor::kf_meta_move  },
00160   { FL_Right,     FL_COMMAND,               Fl_Text_Editor::kf_meta_move  },
00161   { FL_Up,        FL_COMMAND,               Fl_Text_Editor::kf_meta_move  },
00162   { FL_Down,      FL_COMMAND,               Fl_Text_Editor::kf_meta_move  },
00163   { FL_Left,      FL_COMMAND|FL_SHIFT,      Fl_Text_Editor::kf_m_s_move   },
00164   { FL_Right,     FL_COMMAND|FL_SHIFT,      Fl_Text_Editor::kf_m_s_move   },
00165   { FL_Up,        FL_COMMAND|FL_SHIFT,      Fl_Text_Editor::kf_m_s_move   },
00166   { FL_Down,      FL_COMMAND|FL_SHIFT,      Fl_Text_Editor::kf_m_s_move   },
00167 #endif // __APPLE__
00168 
00169   { 0,            0,                        0                             }
00170 };
00171 
00173 void Fl_Text_Editor::add_default_key_bindings(Key_Binding** list) {
00174   for (int i = 0; default_key_bindings[i].key; i++) {
00175     add_key_binding(default_key_bindings[i].key,
00176                     default_key_bindings[i].state,
00177                     default_key_bindings[i].func,
00178                     list);
00179   }
00180 }
00181 
00183 Fl_Text_Editor::Key_Func Fl_Text_Editor::bound_key_function(int key, int state, Key_Binding* list) {
00184   Key_Binding* cur;
00185   for (cur = list; cur; cur = cur->next)
00186     if (cur->key == key)
00187       if (cur->state == FL_TEXT_EDITOR_ANY_STATE || cur->state == state)
00188         break;
00189   if (!cur) return 0;
00190   return cur->function;
00191 }
00192 
00194 void Fl_Text_Editor::remove_all_key_bindings(Key_Binding** list) {
00195   Key_Binding *cur, *next;
00196   for (cur = *list; cur; cur = next) {
00197     next = cur->next;
00198     delete cur;
00199   }
00200   *list = 0;
00201 }
00202 
00204 void Fl_Text_Editor::remove_key_binding(int key, int state, Key_Binding** list) {
00205   Key_Binding *cur, *last = 0;
00206   for (cur = *list; cur; last = cur, cur = cur->next)
00207     if (cur->key == key && cur->state == state) break;
00208   if (!cur) return;
00209   if (last) last->next = cur->next;
00210   else *list = cur->next;
00211   delete cur;
00212 }
00214 void Fl_Text_Editor::add_key_binding(int key, int state, Key_Func function,
00215                                 Key_Binding** list) {
00216   Key_Binding* kb = new Key_Binding;
00217   kb->key = key;
00218   kb->state = state;
00219   kb->function = function;
00220   kb->next = *list;
00221   *list = kb;
00222 }
00223 
00225 
00226 static void kill_selection(Fl_Text_Editor* e) {
00227   if (e->buffer()->selected()) {
00228     e->insert_position(e->buffer()->primary_selection()->start());
00229     e->buffer()->remove_selection();
00230   }
00231 }
00232 
00234 int Fl_Text_Editor::kf_default(int c, Fl_Text_Editor* e) {
00235   // FIXME: this function is a mess! Fix this!
00236   if (!c || (!isprint(c) && c != '\t')) return 0;
00237   char s[2] = "\0";
00238   s[0] = (char)c;
00239   kill_selection(e);
00240   if (e->insert_mode()) e->insert(s);
00241   else e->overstrike(s);
00242   e->show_insert_position();
00243   e->set_changed();
00244   if (e->when()&FL_WHEN_CHANGED) e->do_callback();
00245   return 1;
00246 }
00247 
00249 int Fl_Text_Editor::kf_ignore(int, Fl_Text_Editor*) {
00250   return 0; // don't handle
00251 }
00253 int Fl_Text_Editor::kf_backspace(int, Fl_Text_Editor* e) {
00254   if (!e->buffer()->selected() && e->move_left()) {
00255     int p1 = e->insert_position();
00256     int p2 = e->buffer()->next_char(p1);
00257     e->buffer()->select(p1, p2);
00258   }
00259   kill_selection(e);
00260   e->show_insert_position();
00261   e->set_changed();
00262   if (e->when()&FL_WHEN_CHANGED) e->do_callback();
00263   return 1;
00264 }
00265 
00267 int Fl_Text_Editor::kf_enter(int, Fl_Text_Editor* e) {
00268   kill_selection(e);
00269   e->insert("\n");
00270   e->show_insert_position();
00271   e->set_changed();
00272   if (e->when()&FL_WHEN_CHANGED) e->do_callback();
00273   return 1;
00274 }
00275 
00276 extern void fl_text_drag_me(int pos, Fl_Text_Display* d);
00278 int Fl_Text_Editor::kf_move(int c, Fl_Text_Editor* e) {
00279   int i;
00280   int selected = e->buffer()->selected();
00281   if (!selected)
00282     e->dragPos = e->insert_position();
00283   e->buffer()->unselect();
00284   Fl::copy("", 0, 0);
00285   switch (c) {
00286   case FL_Home:
00287       e->insert_position(e->buffer()->line_start(e->insert_position()));
00288       break;
00289     case FL_End:
00290       e->insert_position(e->buffer()->line_end(e->insert_position()));
00291       break;
00292     case FL_Left:
00293       e->move_left();
00294       break;
00295     case FL_Right:
00296       e->move_right();
00297       break;
00298     case FL_Up:
00299       e->move_up();
00300       break;
00301     case FL_Down:
00302       e->move_down();
00303       break;
00304     case FL_Page_Up:
00305       for (i = 0; i < e->mNVisibleLines - 1; i++) e->move_up();
00306       break;
00307     case FL_Page_Down:
00308       for (i = 0; i < e->mNVisibleLines - 1; i++) e->move_down();
00309       break;
00310   }
00311   e->show_insert_position();
00312   return 1;
00313 }
00314 
00316 int Fl_Text_Editor::kf_shift_move(int c, Fl_Text_Editor* e) {
00317   kf_move(c, e);
00318   fl_text_drag_me(e->insert_position(), e);
00319   char *copy = e->buffer()->selection_text();
00320   if (copy) {
00321     Fl::copy(copy, strlen(copy), 0);
00322     free(copy);
00323     }
00324   return 1;
00325 }
00327 int Fl_Text_Editor::kf_ctrl_move(int c, Fl_Text_Editor* e) {
00328   if (!e->buffer()->selected())
00329     e->dragPos = e->insert_position();
00330   if (c != FL_Up && c != FL_Down) {
00331     e->buffer()->unselect();
00332     Fl::copy("", 0, 0);
00333     e->show_insert_position();
00334   }
00335   switch (c) {
00336     case FL_Home:
00337       e->insert_position(0);
00338       e->scroll(0, 0);
00339       break;
00340     case FL_End:
00341       e->insert_position(e->buffer()->length());
00342       e->scroll(e->count_lines(0, e->buffer()->length(), 1), 0);
00343       break;
00344     case FL_Left:
00345       e->previous_word();
00346       break;
00347     case FL_Right:
00348       e->next_word();
00349       break;
00350     case FL_Up:
00351       e->scroll(e->mTopLineNum-1, e->mHorizOffset);
00352       break;
00353     case FL_Down:
00354       e->scroll(e->mTopLineNum+1, e->mHorizOffset);
00355       break;
00356     case FL_Page_Up:
00357       e->insert_position(e->mLineStarts[0]);
00358       break;
00359     case FL_Page_Down:
00360       e->insert_position(e->mLineStarts[e->mNVisibleLines-2]);
00361       break;
00362   }
00363   return 1;
00364 }
00365 
00367 int Fl_Text_Editor::kf_meta_move(int c, Fl_Text_Editor* e) {
00368   if (!e->buffer()->selected())
00369     e->dragPos = e->insert_position();
00370   if (c != FL_Up && c != FL_Down) {
00371     e->buffer()->unselect();
00372     Fl::copy("", 0, 0);
00373     e->show_insert_position();
00374   }
00375   switch (c) {
00376     case FL_Up:                         // top of buffer
00377       e->insert_position(0);
00378       e->scroll(0, 0);
00379       break;
00380     case FL_Down:                       // end of buffer
00381       e->insert_position(e->buffer()->length());
00382       e->scroll(e->count_lines(0, e->buffer()->length(), 1), 0);
00383       break;
00384     case FL_Left:                       // beginning of line
00385       kf_move(FL_Home, e);
00386       break;
00387     case FL_Right:                      // end of line
00388       kf_move(FL_End, e);
00389       break;
00390   }
00391   return 1;
00392 }
00393 
00395 int Fl_Text_Editor::kf_m_s_move(int c, Fl_Text_Editor* e) {
00396   kf_meta_move(c, e);
00397   fl_text_drag_me(e->insert_position(), e);
00398   return 1;
00399 }
00400 
00402 int Fl_Text_Editor::kf_c_s_move(int c, Fl_Text_Editor* e) {
00403   kf_ctrl_move(c, e);
00404   fl_text_drag_me(e->insert_position(), e);
00405   return 1;
00406 }
00407 
00409 int Fl_Text_Editor::kf_home(int, Fl_Text_Editor* e) {
00410     return kf_move(FL_Home, e);
00411 }
00412 
00414 int Fl_Text_Editor::kf_end(int, Fl_Text_Editor* e) {
00415   return kf_move(FL_End, e);
00416 }
00417 
00419 int Fl_Text_Editor::kf_left(int, Fl_Text_Editor* e) {
00420   return kf_move(FL_Left, e);
00421 }
00422 
00424 int Fl_Text_Editor::kf_up(int, Fl_Text_Editor* e) {
00425   return kf_move(FL_Up, e);
00426 }
00427 
00429 int Fl_Text_Editor::kf_right(int, Fl_Text_Editor* e) {
00430   return kf_move(FL_Right, e);
00431 }
00433 int Fl_Text_Editor::kf_down(int, Fl_Text_Editor* e) {
00434   return kf_move(FL_Down, e);
00435 }
00436 
00438 int Fl_Text_Editor::kf_page_up(int, Fl_Text_Editor* e) {
00439   return kf_move(FL_Page_Up, e);
00440 }
00441 
00443 int Fl_Text_Editor::kf_page_down(int, Fl_Text_Editor* e) {
00444   return kf_move(FL_Page_Down, e);
00445 }
00447 int Fl_Text_Editor::kf_insert(int, Fl_Text_Editor* e) {
00448   e->insert_mode(e->insert_mode() ? 0 : 1);
00449   return 1;
00450 }
00451 
00453 int Fl_Text_Editor::kf_delete(int, Fl_Text_Editor* e) {
00454   if (!e->buffer()->selected()) {
00455     int p1 = e->insert_position();
00456     int p2 = e->buffer()->next_char(p1);
00457     e->buffer()->select(p1, p2);
00458   }
00459 
00460   kill_selection(e);
00461   e->show_insert_position();
00462   e->set_changed();
00463   if (e->when()&FL_WHEN_CHANGED) e->do_callback();
00464   return 1;
00465 }
00466 
00468 int Fl_Text_Editor::kf_copy(int, Fl_Text_Editor* e) {
00469   if (!e->buffer()->selected()) return 1;
00470   const char *copy = e->buffer()->selection_text();
00471   if (*copy) Fl::copy(copy, strlen(copy), 1);
00472   free((void*)copy);
00473   e->show_insert_position();
00474   return 1;
00475 }
00476 
00478 int Fl_Text_Editor::kf_cut(int c, Fl_Text_Editor* e) {
00479   kf_copy(c, e);
00480   kill_selection(e);
00481   e->set_changed();
00482   if (e->when()&FL_WHEN_CHANGED) e->do_callback();
00483   return 1;
00484 }
00485 
00487 int Fl_Text_Editor::kf_paste(int, Fl_Text_Editor* e) {
00488   kill_selection(e);
00489   Fl::paste(*e, 1);
00490   e->show_insert_position();
00491   e->set_changed();
00492   if (e->when()&FL_WHEN_CHANGED) e->do_callback();
00493   return 1;
00494 }
00495 
00497 int Fl_Text_Editor::kf_select_all(int, Fl_Text_Editor* e) {
00498   e->buffer()->select(0, e->buffer()->length());
00499   const char *copy = e->buffer()->selection_text();
00500   if (*copy) Fl::copy(copy, strlen(copy), 0);
00501   free((void*)copy);
00502   return 1;
00503 }
00505 int Fl_Text_Editor::kf_undo(int , Fl_Text_Editor* e) {
00506   e->buffer()->unselect();
00507   Fl::copy("", 0, 0);
00508   int crsr;
00509   int ret = e->buffer()->undo(&crsr);
00510   e->insert_position(crsr);
00511   e->show_insert_position();
00512   e->set_changed();
00513   if (e->when()&FL_WHEN_CHANGED) e->do_callback();
00514   return ret;
00515 }
00516 
00518 int Fl_Text_Editor::handle_key() {
00519   // Call FLTK's rules to try to turn this into a printing character.
00520   // This uses the right-hand ctrl key as a "compose prefix" and returns
00521   // the changes that should be made to the text, as a number of
00522   // bytes to delete and a string to insert:
00523   int del = 0;
00524   if (Fl::compose(del)) {
00525     if (del) {
00526       int dp = insert_position(), di = del;
00527       while (di--) dp = buffer()->prev_char_clipped(dp);
00528       buffer()->select(dp, insert_position());
00529     }
00530     kill_selection(this);
00531     if (Fl::event_length()) {
00532       if (insert_mode()) insert(Fl::event_text());
00533       else overstrike(Fl::event_text());
00534     }
00535     show_insert_position();
00536     set_changed();
00537     if (when()&FL_WHEN_CHANGED) do_callback();
00538     return 1;
00539   }
00540 
00541   int key = Fl::event_key(), state = Fl::event_state(), c = Fl::event_text()[0];
00542   state &= FL_SHIFT|FL_CTRL|FL_ALT|FL_META; // only care about these states
00543   Key_Func f;
00544   f = bound_key_function(key, state, global_key_bindings);
00545   if (!f) f = bound_key_function(key, state, key_bindings);
00546   if (f) return f(key, this);
00547   if (default_key_function_ && !state) return default_key_function_(c, this);
00548   return 0;
00549 }
00550 
00552 void Fl_Text_Editor::maybe_do_callback() {
00553 //  printf("Fl_Text_Editor::maybe_do_callback()\n");
00554 //  printf("changed()=%d, when()=%x\n", changed(), when());
00555   if (changed() || (when()&FL_WHEN_NOT_CHANGED)) do_callback();
00556 }
00557 
00558 int Fl_Text_Editor::handle(int event) {
00559   static int dndCursorPos;
00560   
00561   if (!buffer()) return 0;
00562 
00563   switch (event) {
00564     case FL_FOCUS:
00565       show_cursor(mCursorOn); // redraws the cursor
00566       if (buffer()->selected()) redraw(); // Redraw selections...
00567       Fl::focus(this);
00568       return 1;
00569 
00570     case FL_UNFOCUS:
00571       show_cursor(mCursorOn); // redraws the cursor
00572       if (buffer()->selected()) redraw(); // Redraw selections...
00573     case FL_HIDE:
00574       if (when() & FL_WHEN_RELEASE) maybe_do_callback();
00575       return 1;
00576 
00577     case FL_KEYBOARD:
00578       if (active_r() && window() && this == Fl::belowmouse()) 
00579         window()->cursor(FL_CURSOR_NONE);
00580       return handle_key();
00581 
00582     case FL_PASTE:
00583       if (!Fl::event_text()) {
00584         fl_beep();
00585         return 1;
00586       }
00587       buffer()->remove_selection();
00588       if (insert_mode()) insert(Fl::event_text());
00589       else overstrike(Fl::event_text());
00590       show_insert_position();
00591       set_changed();
00592       if (when()&FL_WHEN_CHANGED) do_callback();
00593       return 1;
00594 
00595     case FL_ENTER:
00596 // MRS: WIN32 only?  Need to test!
00597 //    case FL_MOVE:
00598       show_cursor(mCursorOn);
00599       return 1;
00600 
00601     case FL_PUSH:
00602       if (Fl::event_button() == 2) {
00603         // don't let the text_display see this event
00604         if (Fl_Group::handle(event)) return 1;
00605         dragType = DRAG_NONE;
00606         if(buffer()->selected()) {
00607           buffer()->unselect();
00608           }
00609         int pos = xy_to_position(Fl::event_x(), Fl::event_y(), CURSOR_POS);
00610         insert_position(pos);
00611         Fl::paste(*this, 0);
00612         Fl::focus(this);
00613         set_changed();
00614         if (when()&FL_WHEN_CHANGED) do_callback();
00615         return 1;
00616       }
00617       break;
00618 
00619     case FL_SHORTCUT:
00620       if (!(shortcut() ? Fl::test_shortcut(shortcut()) : test_shortcut()))
00621         return 0;
00622       if (Fl::visible_focus() && handle(FL_FOCUS)) {
00623         Fl::focus(this);
00624         return 1;
00625       }
00626       break;
00627       
00628       // Handle drag'n'drop attempt by the user. This is a simplified 
00629       // implementation which allows dnd operations onto the scroll bars.
00630     case FL_DND_ENTER: // save the current cursor position
00631       if (Fl::visible_focus() && handle(FL_FOCUS))
00632         Fl::focus(this);
00633       show_cursor(mCursorOn);
00634       dndCursorPos = insert_position();
00635       /* fall through */
00636     case FL_DND_DRAG: // show a temporary insertion cursor
00637       insert_position(xy_to_position(Fl::event_x(), Fl::event_y(), CURSOR_POS));
00638       return 1;      
00639     case FL_DND_LEAVE: // restore original cursor
00640       insert_position(dndCursorPos);
00641       return 1;      
00642     case FL_DND_RELEASE: // keep insertion cursor and wait for the FL_PASTE event
00643       buffer()->unselect(); // FL_PASTE must not destroy current selection!
00644       return 1;
00645   }
00646 
00647   return Fl_Text_Display::handle(event);
00648 }
00649 
00650 //
00651 // End of "$Id: Fl_Text_Editor.cxx 8034 2010-12-15 12:21:55Z AlbrechtS $".
00652 //