/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}