/TeXmacs-1.0.7.11-src/src/Edit/Interface/edit_cursor.cpp
C++ | 533 lines | 443 code | 52 blank | 38 comment | 158 complexity | d462487ae011f81a1b5de9b9ee95e25c MD5 | raw file
Possible License(s): GPL-3.0, GPL-2.0, MPL-2.0-no-copyleft-exception
- /******************************************************************************
- * MODULE : cursor.cpp
- * DESCRIPTION: cursor handling
- * COPYRIGHT : (C) 1999 Joris van der Hoeven
- *******************************************************************************
- * This software falls under the GNU general public license version 3 or later.
- * It comes WITHOUT ANY WARRANTY WHATSOEVER. For details, see the file LICENSE
- * in the root directory or <http://www.gnu.org/licenses/gpl-3.0.html>.
- ******************************************************************************/
- #include "edit_cursor.hpp"
- #include "iterator.hpp"
- #include "tm_buffer.hpp"
- #include "tree_traverse.hpp"
- #include "drd_mode.hpp"
- #include "analyze.hpp"
- /******************************************************************************
- * Constructor and destructor
- ******************************************************************************/
- edit_cursor_rep::edit_cursor_rep ():
- cu (0, 0), mv (0, 0), mv_status (0) {}
- edit_cursor_rep::~edit_cursor_rep () {}
- cursor& edit_cursor_rep::the_cursor () { return cu; }
- cursor& edit_cursor_rep::the_ghost_cursor () { return mv; }
- /******************************************************************************
- * Cursor movement
- ******************************************************************************/
- #define DELTA (1<<23)
- static bool searching_forwards;
- path
- edit_cursor_rep::make_cursor_accessible (path p, bool forwards) {
- //time_t t1= texmacs_time ();
- path start_p= p;
- bool inverse= false;
- int old_mode= get_access_mode ();
- if (get_init_string (MODE) == "src")
- set_access_mode (DRD_ACCESS_SOURCE);
- while (!is_accessible_cursor (et, p) && !in_source ()) {
- path pp;
- ASSERT (rp <= p, "path outside document");
- p= rp * closest_inside (subtree (et, rp), p / rp);
- if (forwards ^ inverse)
- pp= rp * next_valid (subtree (et, rp), p / rp);
- else
- pp= rp * previous_valid (subtree (et, rp), p / rp);
- if (pp == p) {
- if (inverse) break;
- else { p= start_p; inverse= true; }
- }
- else p= pp;
- }
- set_access_mode (old_mode);
- //time_t t2= texmacs_time ();
- //if (t2-t1 >= 1) cout << "made_cursor_accessible took " << t2-t1 << "ms\n";
- return p;
- }
- path
- edit_cursor_rep::tree_path (path sp, SI x, SI y, SI delta) {
- path p= correct_cursor (et, find_scrolled_tree_path (eb, sp, x, y, delta));
- return make_cursor_accessible (p, searching_forwards);
- }
- bool
- edit_cursor_rep::cursor_move_sub (SI& x0, SI& y0, SI& d0, SI dx, SI dy) {
- path sp= find_innermost_scroll (eb, tp);
- searching_forwards= dx == 1 || dy == -1;
- int i,d;
- path ref_p= tree_path (sp, x0, y0, d0);
- if (ref_p != tp) {
- tp= ref_p;
- return true;
- }
-
- // cout << "ref_p = " << ref_p << "\n";
- if (ref_p == tree_path (sp, x0, y0, d0+ dx*DELTA)) {
- for (i=1; i<DELTA; i=i<<1)
- if (ref_p != tree_path (sp, x0+ dx*i, y0+ dy*i, d0+ dx*DELTA))
- break;
- if (i>=DELTA) return false;
- for (d=i>>2; d>=1; d=d>>1)
- if (ref_p != tree_path (sp, x0+ dx*(i-d), y0+ dy*(i-d), d0+ dx*DELTA))
- i-=d;
- x0 += dx*i;
- y0 += dy*i;
- }
-
- // cout << "path = " << tree_path (sp, x0, y0, d0) << "\n";
- if (dx!=0) {
- if (ref_p == tree_path (sp, x0, y0, d0)) {
- for (i=1; i<DELTA; i=i<<1)
- if (ref_p != tree_path (sp, x0, y0, d0+ dx*i)) break;
- if (i>=DELTA)
- FAILED ("inconsistent cursor handling");
- for (d=i>>2; d>=1; d=d>>1)
- if (ref_p != tree_path (sp, x0, y0, d0+ dx*(i-d))) i-=d;
- d0 += dx*i;
- }
- else {
- for (i=1; i<DELTA; i=i<<1)
- if (ref_p == tree_path (sp, x0, y0, d0- dx*i)) break;
- if (i<DELTA) {
- for (d=i>>2; d>=1; d=d>>1)
- if (ref_p == tree_path (sp, x0, y0, d0- dx*(i-d))) i-=d;
- i--;
- d0 -= dx*i;
- }
- else { // exceptional case
- ref_p= tree_path (sp, x0, y0, d0- dx*DELTA);
- for (i=1; i<DELTA; i=i<<1)
- if (ref_p == tree_path (sp, x0, y0, d0- dx*i)) break;
- for (d=i>>2; d>=1; d=d>>1)
- if (ref_p == tree_path (sp, x0, y0, d0- dx*(i-d))) i-=d;
- d0 -= dx*i;
- }
- }
- }
- tp= tree_path (sp, x0, y0, d0);
- return true;
- }
- void
- edit_cursor_rep::cursor_move (SI dx, SI dy) {
- //time_t t1= texmacs_time ();
- //stretched_print ((tree) eb, false);
- cursor_move_sub (mv->ox, mv->oy, mv->delta, dx, dy);
- //time_t t2= texmacs_time ();
- //if (t2 - t1 >= 10) cout << "cursor_move took " << t2-t1 << "ms\n";
- }
- /******************************************************************************
- * Routines affecting both the cursor and the ghost cursor
- ******************************************************************************/
- void
- edit_cursor_rep::adjust_ghost_cursor (int status) {
- if (status==mv_status) {
- if (status!=HORIZONTAL) {
- mv->ox = cu->ox;
- mv->delta= cu->delta;
- }
- if (status!=VERTICAL)
- mv->oy= cu->oy;
- }
- }
- void
- edit_cursor_rep::notify_cursor_moved (int status) {
- mv_status= status;
- cu= eb->find_check_cursor (tp);
- notify_change (THE_CURSOR);
- }
- void
- edit_cursor_rep::go_to (SI x, SI y, bool absolute) {
- if (has_changed (THE_TREE+THE_ENVIRONMENT)) return;
- tp= tree_path (absolute? path (): find_innermost_scroll (eb, tp), x, y, 0);
- notify_cursor_moved (CENTER);
- mv->ox = x;
- mv->oy = y;
- mv->delta= 0;
- }
- void
- edit_cursor_rep::go_left_physical () {
- if (has_changed (THE_TREE+THE_ENVIRONMENT)) return;
- adjust_ghost_cursor (VERTICAL);
- cursor_move (-1, 0);
- notify_cursor_moved (HORIZONTAL);
- select_from_cursor_if_active ();
- }
- void
- edit_cursor_rep::go_right_physical () {
- if (has_changed (THE_TREE+THE_ENVIRONMENT)) return;
- adjust_ghost_cursor (VERTICAL);
- cursor_move (1, 0);
- notify_cursor_moved (HORIZONTAL);
- select_from_cursor_if_active ();
- }
- void
- edit_cursor_rep::go_up () {
- if (has_changed (THE_TREE+THE_ENVIRONMENT)) return;
- path scroll_p= find_innermost_scroll (eb, tp);
- path start_p= tree_path (scroll_p, -(1 << 30), 1 << 30, 0);
- if (tp == start_p) return;
- path old_p= tp;
- adjust_ghost_cursor (HORIZONTAL);
- cursor_move (0, 1);
- notify_cursor_moved (VERTICAL);
- if (tp == old_p) tp= start_p;
- select_from_cursor_if_active ();
- }
- void
- edit_cursor_rep::go_down () {
- if (has_changed (THE_TREE+THE_ENVIRONMENT)) return;
- path scroll_p= find_innermost_scroll (eb, tp);
- path end_p= tree_path (scroll_p, 1 << 30, -(1 << 30), 0);
- if (tp == end_p) return;
- path old_p= tp;
- adjust_ghost_cursor (HORIZONTAL);
- cursor_move (0, -1);
- notify_cursor_moved (VERTICAL);
- if (tp == old_p) tp= end_p;
- select_from_cursor_if_active ();
- }
- void
- edit_cursor_rep::go_page_up () {
- if (has_changed (THE_TREE+THE_ENVIRONMENT)) return;
- path sp= find_innermost_scroll (eb, tp);
- if (is_nil (sp)) go_to (mv->ox, min (mv->oy + get_window_height (), eb->y2));
- else {
- SI x, y, sx, sy;
- rectangle outer, inner;
- box b= eb[path_up (sp)];
- find_canvas_info (eb, sp, x, y, sx, sy, outer, inner);
- go_to (mv->ox, min (mv->oy + b->h (), y + sy + inner->y2), false);
- }
- select_from_cursor_if_active ();
- }
- void
- edit_cursor_rep::go_page_down () {
- if (has_changed (THE_TREE+THE_ENVIRONMENT)) return;
- path sp= find_innermost_scroll (eb, tp);
- if (is_nil (sp)) go_to (mv->ox, max (mv->oy - get_window_height (), eb->y1));
- else {
- SI x, y, sx, sy;
- rectangle outer, inner;
- box b= eb[path_up (sp)];
- find_canvas_info (eb, sp, x, y, sx, sy, outer, inner);
- go_to (mv->ox, max (mv->oy - b->h (), y + sy + inner->y1), false);
- }
- select_from_cursor_if_active ();