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