
/******************************************************************************
* MODULE     : edit_mouse.gen.cc
* DESCRIPTION: Mouse handling
* COPYRIGHT  : (C) 1999  Joris van der Hoeven
*******************************************************************************
* This software falls under the GNU general public license and comes WITHOUT
* ANY WARRANTY WHATSOEVER. See the file $TEXMACS_PATH/LICENSE for more details.
* If you don't have this file, write to the Free Software Foundation, Inc.,
* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
******************************************************************************/

#module code_edit_mouse

/******************************************************************************
* Routines for the mouse
******************************************************************************/

void
edit_interface_rep::mouse_press (string s, SI x, SI y) {
  buf->mark_undo_block ();
  if (s == "<mouse-select>")
    mouse_select (x, y);
  if (s == "<mouse-paste>")
    mouse_paste (x, y);
  if (s == "<mouse-adjust>")
    mouse_adjust (x, y);
}

void
edit_interface_rep::mouse_select (SI x, SI y) {
  buf->mark_undo_block ();
  go_to (x, y);
  if (selection_active_any ())
    selection_set ("primary", selection_get (), TRUE);
}

bool
edit_interface_rep::mouse_extra_click (SI x, SI y) {
  buf->mark_undo_block ();
  go_to (x, y);

  // temporary hack for clickable footnotes
  path p= path_up (tp);
  if (!nil (p)) {
    if (is_expand (subtree (et, p), "footnote", 1)) {
      go_to (start (et, p * 1));
      return TRUE;
    }
    tree st= subtree (et, path_up (p));
    if (is_concat (st) && ((last_item (p) + 1) < N(st)))
      if (last_item (tp) == right_index (st [last_item (p)]))
	if (is_expand (subtree (et, path_inc (p)), "footnote", 1)) {
	  go_to (start (et, path_inc (p) * 1));
	  return TRUE;
	}
    path q= search_upwards_expand ("footnote");
    if ((!nil (q)) && (tp == start (et, q * 1))) {
      go_to (end (et, q));
      return TRUE;
    }
  }
  // end temporary hack

  tree result= eb->action ("click", x, y, 0);
  if (result == "") {
    go_to (x, y);
    path p1, p2;
    get_selection (p1, p2);
    if ((p1==p2) || path_less (tp, p1) || path_less (p2, tp)) select (tp, tp);
    select_enlarge ();
    return FALSE;
  }
  else return TRUE;
}

void
edit_interface_rep::mouse_paste (SI x, SI y) { (void) x; (void) y;
  buf->mark_undo_block ();
  selection_copy ();
  selection_paste ();
}

void
edit_interface_rep::mouse_drag (SI x, SI y) {
  buf->mark_undo_block ();
  end_x  = x;
  end_y  = y;
  selection_visible ();
  path p1= tree_path (start_x, start_y, 0);
  path p2= tree_path (end_x  , end_y  , 0);
  if (path_inf (p2, p1)) {
    path temp= p1;
    p1= p2;
    p2= temp;
  }
  set_selection (p1, p2);
  if ((p1 == p2) && start_drag) return;
  start_drag= FALSE;
  notify_change (THE_SELECTION);
}

void
edit_interface_rep::mouse_adjust (SI x, SI y) {
  buf->mark_undo_block ();
  x /= sfactor; y /= sfactor;
  abs_round (x, y);
  if (popup_win == NULL) {
    SI wx, wy;
    win->get_position (wx, wy);
    widget wid; SERVER (menu_widget (popup_menu, wid));
    widget popup_wid= popup_widget (wid, center);
    popup_win= popup_window (popup_wid, wx+ ox+ x, wy+ oy+ y);
    popup_win->map ();
    this << emit_mouse_grab (TRUE);
    popup_wid << set_integer ("grabbed", 1);
    // popup_wid << set_integer ("freeze", 1);
    popup_wid << emit_mouse_grab (TRUE);
  }
}

/******************************************************************************
* event handlers
******************************************************************************/

extern time_t texmacs_time ();

void
edit_interface_rep::handle_mouse (mouse_event ev) {
  string type= ev->type;
  SI     x   = ev->x*sfactor;
  SI     y   = ev->y*sfactor;
  
  if ((type != "move") && (type != "enter") && (type != "leave"))
    set_input_normal ();

  if ((popup_win != NULL) && (type != "leave")) {
    popup_win->map ();
    delete popup_win;
    popup_win= NULL;
    this << emit_mouse_grab (FALSE);
  }
  if (type == "press-left") {
    start_x   = x;
    start_y   = y;
    start_drag= TRUE;
    dragging  = TRUE;
    this << emit_mouse_grab (TRUE);
  }
  if (dragging && (type == "move")) {
    if (attached () && win->check_event (DRAG_EVENT)) return;
    mouse_drag (x, y);
  }
  if (type == "release-left") {
    dragging= FALSE;
    this << emit_mouse_grab (FALSE);
    if ((ev->t >= last_click) && ((ev->t - last_click) <= 250)) {
      last_click= ev->t;
      if (mouse_extra_click (x, y))
	last_click= ev->t- 1000;
    }
    else {
      last_click= ev->t;
      mouse_select (x, y);
    }
  }
  if (type == "press-middle") mouse_paste (x, y);
  if (type == "press-right") mouse_adjust (x, y);

  if ((type == "press-left") ||
      (type == "release-left") ||
      (type == "press-middle") ||
      (type == "press-right"))
    notify_change (THE_DECORATIONS);

  if ((type == "press-up") || (type == "press-down")) {
    SI x, y, dy= 100*PIXEL;
    if (type == "press-down") dy= -dy;
    SERVER (scroll_where (x, y));
    y += dy;
    SERVER (scroll_to (x, y));
  }
}

#endmodule // code_edit_mouse
