PageRenderTime 170ms CodeModel.GetById 81ms app.highlight 83ms RepoModel.GetById 1ms app.codeStats 0ms

/TeXmacs-1.0.7.11-src/src/Edit/Interface/edit_mouse.cpp

#
C++ | 350 lines | 295 code | 28 blank | 27 comment | 135 complexity | 0f9845fc37a2140bef6db97aecaabd8b MD5 | raw file
Possible License(s): GPL-3.0, GPL-2.0, MPL-2.0-no-copyleft-exception
  1
  2/******************************************************************************
  3* MODULE     : edit_mouse.cpp
  4* DESCRIPTION: Mouse handling
  5* COPYRIGHT  : (C) 1999  Joris van der Hoeven
  6*******************************************************************************
  7* This software falls under the GNU general public license version 3 or later.
  8* It comes WITHOUT ANY WARRANTY WHATSOEVER. For details, see the file LICENSE
  9* in the root directory or <http://www.gnu.org/licenses/gpl-3.0.html>.
 10******************************************************************************/
 11
 12#include "edit_interface.hpp"
 13#include "tm_buffer.hpp"
 14#include "timer.hpp"
 15#include "link.hpp"
 16#include "analyze.hpp"
 17#include "drd_mode.hpp"
 18#include "message.hpp"
 19#include "window.hpp"
 20
 21/******************************************************************************
 22* dispatching
 23******************************************************************************/
 24
 25void
 26edit_interface_rep::mouse_any (string type, SI x, SI y, int mods, time_t t) {
 27  last_x= x; last_y= y;
 28  if (type != "move" || (is_attached (this) && !check_event (MOTION_EVENT)))
 29    update_active_loci ();
 30
 31  if (type == "leave")
 32    set_pointer ("XC_top_left_arrow");
 33  if ((type != "move") && (type != "enter") && (type != "leave"))
 34    set_input_normal ();
 35  if (!is_nil (popup_win) && (type != "leave")) {
 36    set_visibility (popup_win, false);
 37    destroy_window_widget (popup_win);
 38    popup_win= widget ();
 39  }
 40
 41  if (inside_graphics (false)) {
 42    string type2= type;
 43    if (type == "enter") {
 44      dragging= start_drag= false;
 45      right_dragging= start_right_drag= false;
 46    }
 47    if (type == "press-left")
 48      start_drag= true;
 49    if (type == "press-right")
 50      start_right_drag= true;
 51
 52    if (start_drag && type == "move") {
 53      type2= "start-drag";
 54      start_drag= false;
 55      dragging= true;
 56    }
 57    else if (dragging && (type == "move"))
 58      type2= "dragging";
 59    if (dragging && (type == "release-left"))
 60      type2= "end-drag";
 61
 62    if (start_right_drag && type == "move") {
 63      type2= "start-right-drag";
 64      start_right_drag= false;
 65      right_dragging= true;
 66    }
 67    else if (right_dragging && (type == "move"))
 68      type2= "right-dragging";
 69    if (right_dragging && (type == "release-right"))
 70      type2= "end-right-drag";
 71
 72    if (type == "release-left")
 73      dragging= start_drag= false;
 74    if (type == "release-right")
 75      right_dragging= start_right_drag= false;
 76    if (mouse_graphics (type2, x, y, mods, t)) return;
 77    if (!over_graphics (x, y))
 78      eval ("(graphics-reset-context 'text-cursor)");
 79  }
 80
 81  if (type == "press-left") mouse_click (x, y);
 82  if (dragging && (type == "move")) {
 83    if (is_attached (this) && check_event (DRAG_EVENT)) return;
 84    mouse_drag (x, y);
 85  }
 86  if (type == "release-left" || type == "release-right") {
 87    dragging= right_dragging= false;
 88    send_mouse_grab (this, false);
 89    if ((t >= last_click) && ((t - last_click) <= 500)) {
 90      last_click= t;
 91      if (mouse_extra_click (x, y))
 92	last_click= t- 2000;
 93    }
 94    else {
 95      last_click= t;
 96      mouse_select (x, y, mods);
 97    }
 98  }
 99  if (type == "press-middle") mouse_paste (x, y);
100  if (type == "press-right") mouse_adjust (x, y);
101  if (type == "press-up") mouse_scroll (x, y, true);
102  if (type == "press-down") mouse_scroll (x, y, false);
103
104  if ((type == "press-left") ||
105      (type == "release-left") ||
106      (type == "press-middle") ||
107      (type == "press-right"))
108    notify_change (THE_DECORATIONS);
109}
110
111/******************************************************************************
112* Routines for the mouse
113******************************************************************************/
114
115void
116edit_interface_rep::mouse_click (SI x, SI y) {
117  if (eb->action ("click", x, y, 0) != "") return;
118  start_x   = x;
119  start_y   = y;
120  start_drag= dragging= true;
121  start_right_drag= right_dragging= false;
122  send_mouse_grab (this, true);
123}
124
125bool
126edit_interface_rep::mouse_extra_click (SI x, SI y) {
127  go_to (x, y);
128  if (eb->action ("double-click", x, y, 0) != "") return true;
129  go_to (x, y);
130  path p1, p2;
131  get_selection (p1, p2);
132  if ((p1==p2) || path_less (tp, p1) || path_less (p2, tp)) select (tp, tp);
133  select_enlarge ();
134  if (selection_active_any ())
135    selection_set ("mouse", selection_get (), true);
136  return false;
137}
138
139void
140edit_interface_rep::mouse_drag (SI x, SI y) {
141  if (inside_graphics ()) return;
142  if (eb->action ("drag", x, y, 0) != "") return;
143  go_to (x, y);
144  end_x  = x;
145  end_y  = y;
146  selection_visible ();
147  path sp= find_innermost_scroll (eb, tp);
148  path p1= tree_path (sp, start_x, start_y, 0);
149  path p2= tree_path (sp, end_x  , end_y  , 0);
150  if (path_inf (p2, p1)) {
151    path temp= p1;
152    p1= p2;
153    p2= temp;
154  }
155  if ((p1 == p2) && start_drag) return;
156  set_selection (p1, p2);
157  start_drag= start_right_drag= false;
158  notify_change (THE_SELECTION);
159}
160
161void
162edit_interface_rep::mouse_select (SI x, SI y, int mods) {
163  if (eb->action ("select" , x, y, 0) != "") return;
164  if (!is_nil (active_ids) && (mods & 256) == 0) {
165    call ("link-follow-ids", object (active_ids));
166    return;
167  }
168  tree g;
169  bool b0= inside_graphics (false);
170  bool b= inside_graphics ();
171  if (b) g= get_graphics ();
172  go_to (x, y);
173  if ((!b0 && inside_graphics (false)) || (b0 && !inside_graphics (false))) {
174    dragging= start_drag= false;
175    right_dragging= start_right_drag= false;
176  }
177  if (!b && inside_graphics ())
178    eval ("(graphics-reset-context 'begin)");
179  tree g2= get_graphics ();
180  if (b && (!inside_graphics () || obtain_ip (g) != obtain_ip (g2))) {
181    invalidate_graphical_object ();
182    eval ("(graphics-reset-context 'exit)");
183  }
184  if (start_drag) {
185    path sp= find_innermost_scroll (eb, tp);
186    path p0= tree_path (sp, x, y, 0);
187    set_selection (p0, p0);
188    notify_change (THE_SELECTION);
189  }
190  if (selection_active_any ())
191    selection_set ("mouse", selection_get (), true);
192}
193
194void
195edit_interface_rep::mouse_paste (SI x, SI y) { (void) x; (void) y;
196  if (eb->action ("paste", x, y, 0) != "") return;
197  go_to (x, y);
198  selection_paste ("mouse");
199}
200
201void
202edit_interface_rep::mouse_adjust (SI x, SI y) {
203  if (eb->action ("adjust", x, y, 0) != "") return;
204  x /= sfactor; y /= sfactor;
205  abs_round (x, y);
206  if (is_nil (popup_win)) {
207    SI wx, wy;
208    ::get_position (get_window (this), wx, wy);
209    widget wid;
210    SERVER (menu_widget ("(vertical (link texmacs-popup-menu))", wid));
211    widget popup_wid= popup_widget (wid);
212    popup_win= ::popup_window_widget (popup_wid, "Popup menu");
213#if defined (QTTEXMACS) || defined(AQUATEXMACS)
214    SI ox, oy;
215    get_position (this, ox, oy);
216    set_position (popup_win, wx+     x, wy+     y);
217#else
218    set_position (popup_win, wx+ ox+ x, wy+ oy+ y);
219#endif
220    set_visibility (popup_win, true);
221    send_keyboard_focus (this);
222    send_mouse_grab (popup_wid, true);
223  }
224}
225
226void
227edit_interface_rep::mouse_scroll (SI x, SI y, bool up) {
228  string action= up? string ("scroll up"): string ("scroll down");
229  if (eb->action (action , x, y, 0) != "") return;
230  SI dy= 100*PIXEL;
231  if (!up) dy= -dy;
232  path sp= find_innermost_scroll (eb, tp);
233  if (is_nil (sp)) {
234    SERVER (scroll_where (x, y));
235    y += dy;
236    SERVER (scroll_to (x, y));
237  }
238  else {
239    SI x, y, sx, sy;
240    rectangle outer, inner;
241    find_canvas_info (eb, sp, x, y, sx, sy, outer, inner);
242    SI ty= inner->y2 - inner->y1;
243    SI cy= outer->y2 - outer->y1;
244    if (ty > cy) {
245      tree   old_yt= eb[path_up (sp)]->get_info ("scroll-y");
246      string old_ys= as_string (old_yt);
247      double old_p = 0.0;
248      if (ends (old_ys, "%")) old_p= as_double (old_ys (0, N(old_ys)-1));
249      double new_p= old_p + 100.0 * ((double) dy) / ((double) (ty - cy));
250      new_p= max (min (new_p, 100.0), 0.0);
251      tree new_yt= as_string (new_p) * "%";
252      if (new_yt != old_yt && is_accessible (obtain_ip (old_yt))) {
253	object fun= symbol_object ("tree-set");
254	object cmd= list_object (fun, old_yt, new_yt);
255	exec_delayed (scheme_cmd (cmd));
256	temp_invalid_cursor= true;
257      }
258    }
259  }
260}
261
262/******************************************************************************
263* getting the cursor (both for text and graphics)
264******************************************************************************/
265
266cursor
267edit_interface_rep::get_cursor () {
268  if (inside_graphics ()) {
269    frame f= find_frame ();
270    if (!is_nil (f)) {
271      point p= f [point (last_x, last_y)];
272      p= f (adjust (p));
273      SI x= (SI) p[0];
274      SI y= (SI) p[1];
275      return cursor (x, y, 0, -5*pixel, 5*pixel, 1.0);
276    }
277  }
278  return copy (the_cursor ());
279}
280
281void
282edit_interface_rep::set_pointer (string name) {
283  send_mouse_pointer (this, name);
284}
285
286void
287edit_interface_rep::set_pointer (
288  string curs_name, string mask_name)
289{
290  send_mouse_pointer (this, curs_name, mask_name);
291}
292
293/******************************************************************************
294* Active loci
295******************************************************************************/
296
297void
298edit_interface_rep::update_active_loci () {
299  int old_mode= set_access_mode (DRD_ACCESS_SOURCE);
300  path cp= path_up (tree_path (path (), last_x, last_y, 0));
301  set_access_mode (old_mode);
302  tree mt= subtree (et, cp);
303  path p = cp;
304  list<string> ids1, ids2;
305  rectangles rs1, rs2;
306  eb->loci (last_x, last_y, 0, ids1, rs1);
307  while (rp <= p) {
308    ids2 << get_ids (subtree (et, p));
309    p= path_up (p);
310  }
311
312  locus_new_rects= rectangles ();
313  active_ids= list<string> ();
314  if (!is_nil (ids1 * ids2) && !has_changed (THE_FOCUS)) {
315    list<tree> l= as_list_tree (call ("link-active-upwards", object (mt)));
316    while (!is_nil (l)) {
317      tree lt= l->item;
318      path lp= reverse (obtain_ip (lt));
319      selection sel= eb->find_check_selection (lp * start(lt), lp * end(lt));
320      rs2 << outline (sel->rs, pixel);
321      l= l->next;
322    }
323    ids1= as_list_string (call ("link-active-ids", object (ids1)));
324    ids2= as_list_string (call ("link-active-ids", object (ids2)));
325    if (is_nil (ids1)) rs1= rectangles ();
326    // FIXME: we should keep track which id corresponds to which rectangle
327    locus_new_rects= rs1 * rs2;
328    active_ids= ids1 * ids2;
329  }
330  if (locus_new_rects != locus_rects) notify_change (THE_LOCUS);
331}
332
333/******************************************************************************
334* Event handlers
335******************************************************************************/
336
337void
338edit_interface_rep::handle_mouse (string kind, SI x, SI y, int m, time_t t) {
339  if (is_nil (eb)) apply_changes ();
340  start_editing ();
341  x *= sfactor;
342  y *= sfactor;
343  //cout << kind << " (" << x << ", " << y << "; " << m << ")"
344  //<< " at " << t << "\n";
345  array<object> args;
346  args << object (kind) << object (x) << object (y)
347       << object (m) << object ((double) t);
348  call ("mouse-event", args);
349  end_editing ();
350}