Back to index

texmacs  1.0.7.15
edit_keyboard.cpp
Go to the documentation of this file.
00001 
00002 /******************************************************************************
00003 * MODULE     : edit_keyboard.cpp
00004 * DESCRIPTION: Keyboard handling
00005 * COPYRIGHT  : (C) 1999  Joris van der Hoeven
00006 *******************************************************************************
00007 * This software falls under the GNU general public license version 3 or later.
00008 * It comes WITHOUT ANY WARRANTY WHATSOEVER. For details, see the file LICENSE
00009 * in the root directory or <http://www.gnu.org/licenses/gpl-3.0.html>.
00010 ******************************************************************************/
00011 
00012 #include "edit_interface.hpp"
00013 #include "analyze.hpp"
00014 #include "tm_buffer.hpp"
00015 #include "archiver.hpp"
00016 
00017 /******************************************************************************
00018 * Basic subroutines for keyboard handling
00019 ******************************************************************************/
00020 
00021 int
00022 edit_interface_rep::get_input_mode () {
00023   return input_mode;
00024 }
00025 
00026 void
00027 edit_interface_rep::set_input_mode (int mode) {
00028   interrupt_shortcut ();
00029   // avoids keyboard shortcuts when using the menu between two keystrokes
00030 
00031   if ((mode == INPUT_NORMAL) && (input_mode != INPUT_NORMAL)) {
00032     selection_cancel ();
00033     completions= array<string> ();
00034   }
00035   input_mode= mode;
00036 }
00037 
00038 void
00039 edit_interface_rep::set_input_normal () {
00040   set_input_mode (INPUT_NORMAL);
00041 }
00042 
00043 bool
00044 edit_interface_rep::in_normal_mode () {
00045   return input_mode == INPUT_NORMAL;
00046 }
00047 
00048 bool
00049 edit_interface_rep::in_search_mode () {
00050   return input_mode == INPUT_SEARCH;
00051 }
00052 
00053 bool
00054 edit_interface_rep::in_replace_mode () {
00055   return input_mode == INPUT_REPLACE;
00056 }
00057 
00058 bool
00059 edit_interface_rep::in_spell_mode () {
00060   return input_mode == INPUT_SPELL;
00061 }
00062 
00063 bool
00064 edit_interface_rep::kbd_get_command (string which, string& help, command& c) {
00065   return sv->kbd_get_command (which, help, c);
00066 }
00067 
00068 /******************************************************************************
00069 * Main keyboard routines
00070 ******************************************************************************/
00071 
00072 void
00073 edit_interface_rep::interrupt_shortcut () {
00074   if (sh_mark != 0) mark_end (sh_mark);
00075   sh_s= "";
00076   sh_mark= 0;
00077 }
00078 
00079 bool
00080 edit_interface_rep::try_shortcut (string comb) {
00081   int     status;
00082   command cmd;
00083   string  shorth;
00084   string  help;
00085 
00086   sv->get_keycomb (comb, status, cmd, shorth, help);
00087   //cout << "Try " << comb << " -> " << shorth << ", " << help
00088   //<< "; " << sh_mark << ", " << status << "\n";
00089   if (status != 0) {
00090     if (status >= 3) {
00091       interrupt_shortcut ();
00092       status -= 3;
00093       if (status == 0) return false;
00094     }
00095     else {
00096       if (sh_mark != 0 && !mark_cancel (sh_mark)) {
00097         sh_mark= 0;
00098         return false;
00099       }
00100     }
00101     sh_s= comb;
00102     sh_mark= new_marker ();
00103     mark_start (sh_mark);
00104     archive_state ();
00105     string rew_s= sv->kbd_post_rewrite (sh_s);
00106     tree rew= sv->kbd_system_rewrite (rew_s);
00107     if (N(help)>0) set_message (help, rew);
00108     tree rhs= (shorth == rew_s? tree (""): sv->kbd_system_rewrite (shorth));
00109     //cout << "Shortcut: " << sh_s << " -> " << rew << "\n";
00110     if ((search_forwards (" ", comb) >= 0 && comb != " ") ||
00111        (search_forwards ("-", comb) >= 0 && comb != "-"))
00112       call ("set-temporary-message",
00113            tree (CONCAT, "keyboard shortcut: ", rew), rhs,
00114            shorth == ""? 1: 3000);
00115     if ((status & 1) == 1) cmd ();
00116     else if (N(shorth) > 0) insert_tree (shorth);
00117     //cout << "Mark= " << sh_mark << "\n";
00118     return true;    
00119   }
00120 
00121   return false;
00122 }
00123 
00124 void
00125 edit_interface_rep::key_press (string gkey) {
00126   string zero= "a"; zero[0]= '\0';
00127   string key= replace (gkey, "<#0>", zero);
00128   if (pre_edit_mark != 0) {
00129     ASSERT (sh_mark == 0, "invalid shortcut during pre-edit");
00130     mark_cancel (pre_edit_mark);
00131     pre_edit_s= "";
00132     pre_edit_mark= 0;
00133   }
00134   if (starts (key, "pre-edit:") ) {
00135     interrupt_shortcut ();
00136     string s= key (9, N(key));
00137     if (s == "") return;
00138     int i, n= N(s), pos= N(s);
00139     for (i=0; i<n; i++)
00140       if (s[i] == ':' && is_int (s (0, i))) {
00141        int k= as_int (s (0, i));
00142        s= s (i+1, n);
00143        pos= 0;
00144        for (int j=0; j<k && pos<N(s); j++)
00145          tm_char_forwards (s, pos);
00146        break;
00147       }
00148     pre_edit_s= s;
00149     pre_edit_mark= new_marker ();
00150     mark_start (pre_edit_mark);
00151     archive_state ();
00152     insert_tree (compound ("pre-edit", s), path (0, pos));
00153     return;
00154   }
00155 
00156   string new_sh= N(sh_s)==0? key: sh_s * " " * key;
00157   if (try_shortcut (new_sh)) return;
00158   if (new_sh != key) {
00159     interrupt_shortcut ();
00160     if (try_shortcut (key)) return;
00161   }
00162 
00163   string rew= sv->kbd_post_rewrite (key);
00164   if (N(rew) == 1) {
00165     int i ((unsigned char) rew[0]);
00166     if ((i >= 32 && i <= 127) || (i >= 128 && i <= 255) || (i == 25))
00167       if (!inside_active_graphics ()) {
00168         archive_state ();
00169        insert_tree (rew);
00170       }
00171     interrupt_shortcut ();
00172   }
00173   else if (contains_unicode_char (rew)) {
00174     archive_state ();
00175     insert_tree (key);
00176     interrupt_shortcut ();    
00177   }
00178 }
00179 
00180 void
00181 edit_interface_rep::emulate_keyboard (string keys, string action) {
00182   string s= keys;
00183   while (s != "") {
00184     int i;
00185     for (i=1; i<N(s); i++)
00186       if (s[i]==' ') break;
00187     call ("keyboard-press", object (s (0, i)), object ((double) 0));
00188     if (i<N(s)) i++;
00189     s= s (i, N(s));
00190   }
00191   if (N (action) != 0)
00192     set_message (concat ("You can also obtain ", action, " by typing ", keys),
00193                action);
00194 }
00195 
00196 /******************************************************************************
00197 * Retrieving keyboard shortcuts
00198 ******************************************************************************/
00199 
00200 tree
00201 edit_interface_rep::kbd (string s) {
00202   return sv->kbd_system_rewrite (s);
00203 }
00204 
00205 tree
00206 edit_interface_rep::kbd_shortcut (string cmd) {
00207   string s= as_string (eval ("(kbd-find-inv-binding '" * cmd * ")"));
00208   return kbd (s);
00209 }
00210 
00211 /******************************************************************************
00212 * Event handlers
00213 ******************************************************************************/
00214 
00215 void
00216 edit_interface_rep::handle_keypress (string key, time_t t) {
00217   if (DEBUG_KEYBOARD)
00218     cout << "Keyboard] Pressed " << key << " at " << t << "\n";
00219   //time_t t1= texmacs_time ();
00220   if (is_nil (eb)) apply_changes ();
00221   start_editing ();
00222   string zero= "a"; zero[0]= '\0';
00223   string gkey= replace (key, zero, "<#0>");
00224   call ("keyboard-press", object (gkey), object ((double) t));
00225   notify_change (THE_DECORATIONS);
00226   end_editing ();
00227   //time_t t2= texmacs_time ();
00228   //if (t2 - t1 >= 10) cout << "handle_keypress took " << t2-t1 << "ms\n";
00229 }
00230 
00231 void drag_left_reset ();
00232 void drag_right_reset ();
00233 
00234 void
00235 edit_interface_rep::handle_keyboard_focus (bool has_focus, time_t t) {
00236   if (DEBUG_KEYBOARD) {
00237     if (has_focus) cout << "Keyboard] Got focus at " << t << "\n";
00238     else cout << "Keyboard] Lost focus at " << t << "\n";
00239   }
00240   if (got_focus != has_focus) {
00241     drag_left_reset ();
00242     drag_right_reset ();
00243   }
00244   got_focus= has_focus; (void) t;
00245   notify_change (THE_FOCUS);
00246   if (got_focus) {
00247     focus_on_this_editor ();
00248     notify_change (THE_DECORATIONS);
00249   }
00250   call ("keyboard-focus", object (has_focus), object ((double) t));
00251 }