/* The GIMP -- an image manipulation program
 * 
 * This file Copyright (C) 1999 Simon Budig
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 2 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
 */

#include "config.h"

#include <stdlib.h>

#include <gtk/gtk.h>

#include "libgimpmath/gimpmath.h"
#include "libgimpwidgets/gimpwidgets.h"

#include "tools-types.h"

#include "display/gimpdisplay.h"

#include "gimpdrawtool.h"
#include "gimppathtool.h"
#include "tool_manager.h"
#include "tool_options.h"
#include "path_tool.h"

#include "libgimp/gimpintl.h"

#include "path_curves.h"


/*  local function prototypes  */
static void   gimp_path_tool_class_init      (GimpPathToolClass *klass);
static void   gimp_path_tool_init            (GimpPathTool      *tool);

static void   gimp_path_tool_finalize        (GObject        *object);

static void   gimp_path_tool_control         (GimpTool       *tool,
                                              ToolAction      action,
                                              GDisplay       *gdisp);
static void   gimp_path_tool_button_press    (GimpTool       *tool,
                                              GdkEventButton *bevent,
                                              GDisplay       *gdisp);
static gint   gimp_path_tool_button_press_canvas (GimpPathTool *tool,
						  GdkEventButton *bevent,
						  GDisplay *gdisp);
static gint   gimp_path_tool_button_press_anchor (GimpPathTool *tool,
						  GdkEventButton *bevent,
						  GDisplay *gdisp);
static gint   gimp_path_tool_button_press_handle (GimpPathTool *tool,
						  GdkEventButton *bevent,
						  GDisplay *gdisp);
static gint   gimp_path_tool_button_press_curve  (GimpPathTool *tool,
						  GdkEventButton *bevent,
						  GDisplay *gdisp);

static void   gimp_path_tool_button_release  (GimpTool       *tool,
                                              GdkEventButton *bevent,
                                              GDisplay       *gdisp);

static void   gimp_path_tool_motion          (GimpTool       *tool,
                                              GdkEventMotion *mevent,
                                              GDisplay       *gdisp);
static void   gimp_path_tool_motion_anchor   (GimpPathTool *path_tool,
					      GdkEventMotion *mevent,
					      GDisplay *gdisp);
static void   gimp_path_tool_motion_handle   (GimpPathTool *path_tool,
					      GdkEventMotion *mevent,
					      GDisplay *gdisp);
static void   gimp_path_tool_motion_curve    (GimpPathTool *path_tool,
					      GdkEventMotion *mevent,
					      GDisplay *gdisp);

static void   gimp_path_tool_cursor_update   (GimpTool       *tool,
                                              GdkEventMotion *mevent,
                                              GDisplay       *gdisp);

static void   gimp_path_tool_draw            (GimpDrawTool   *draw_tool);




static GimpDrawToolClass *parent_class = NULL;

/*  the move tool options  */
static GimpToolOptions *path_options = NULL;


void
gimp_path_tool_register (Gimp *gimp)
{
  tool_manager_register_tool (gimp,
			      GIMP_TYPE_PATH_TOOL,
                              FALSE,
			      "gimp:path_tool",
			      _("Path Tool"),
			      _("Path tool prototype"),
			      N_("/Tools/Path"), NULL,
			      NULL, "tools/path.html",
			      GIMP_STOCK_TOOL_PATH);
}

GType
gimp_path_tool_get_type (void)
{
  static GType tool_type = 0;

  if (! tool_type)
    {
      static const GTypeInfo tool_info =
      {
        sizeof (GimpPathToolClass),
	(GBaseInitFunc) NULL,
	(GBaseFinalizeFunc) NULL,
	(GClassInitFunc) gimp_path_tool_class_init,
	NULL,           /* class_finalize */
	NULL,           /* class_data     */
	sizeof (GimpPathTool),
	0,              /* n_preallocs    */
	(GInstanceInitFunc) gimp_path_tool_init,
      };

      tool_type = g_type_register_static (GIMP_TYPE_DRAW_TOOL,
					  "GimpPathTool", 
                                          &tool_info, 0);
    }

  return tool_type;
}

static void
gimp_path_tool_class_init (GimpPathToolClass *klass)
{
  GObjectClass      *object_class;
  GimpToolClass     *tool_class;
  GimpDrawToolClass *draw_tool_class;

  object_class    = G_OBJECT_CLASS (klass);
  tool_class      = GIMP_TOOL_CLASS (klass);
  draw_tool_class = GIMP_DRAW_TOOL_CLASS (klass);

  parent_class = g_type_class_peek_parent (klass);

  object_class->finalize     = gimp_path_tool_finalize;

  tool_class->control        = gimp_path_tool_control;
  tool_class->button_press   = gimp_path_tool_button_press;
  tool_class->button_release = gimp_path_tool_button_release;
  tool_class->motion         = gimp_path_tool_motion;
  tool_class->cursor_update  = gimp_path_tool_cursor_update;

  draw_tool_class->draw      = gimp_path_tool_draw;
}

static void
gimp_path_tool_init (GimpPathTool *path_tool)
{
  GimpTool *tool;

  tool = GIMP_TOOL (path_tool);
 
  /*  The tool options  */
  if (! path_options)
    {
      path_options = tool_options_new ();

      tool_manager_register_tool_options (GIMP_TYPE_PATH_TOOL,
                                          (GimpToolOptions *) path_options);
    }


  tool->preserve = TRUE;  /*  Preserve on drawable change  */

  path_tool->click_type       = ON_CANVAS;
  path_tool->click_x         = 0;
  path_tool->click_y         = 0;
  path_tool->click_halfwidth = 0;
  path_tool->click_modifier  = 0;
  path_tool->click_path      = NULL;
  path_tool->click_curve     = NULL;
  path_tool->click_segment   = NULL;
  path_tool->click_position  = -1;

  path_tool->active_count    = 0;
  path_tool->single_active_segment = NULL;

  path_tool->state           = 0;
  path_tool->draw            = PATH_TOOL_REDRAW_ALL;
  path_tool->cur_path        = g_new0(NPath, 1);
  path_tool->scanlines       = NULL;


  /* Initial Path */
  path_tool->cur_path->curves    = NULL;
  path_tool->cur_path->cur_curve = NULL;
  path_tool->cur_path->name      = g_string_new("Path 0");
  path_tool->cur_path->state     = 0;
  /* path_tool->cur_path->path_tool = path_tool; */

}

static void
gimp_path_tool_finalize (GObject *object)
{
  GimpPathTool *path_tool;

  path_tool = GIMP_PATH_TOOL (object);

#ifdef PATH_TOOL_DEBUG
  fprintf (stderr, "gimp_path_tool_free start\n");
#endif PATH_TOOL_DEBUG

  if (path_tool->cur_path)
    {
      path_free_path (path_tool->cur_path);
      path_tool->cur_path = NULL;
    }

  G_OBJECT_CLASS (parent_class)->finalize (object);
}

static void
gimp_path_tool_control (GimpTool   *tool,
                        ToolAction  action,
                        GDisplay   *gdisp)
{
  GimpPathTool *path_tool;

#ifdef PATH_TOOL_DEBUG
  fprintf (stderr, "path_tool_control\n");
#endif PATH_TOOL_DEBUG

  path_tool = GIMP_PATH_TOOL (tool);

  switch (action)
    {
    case PAUSE:
      break;

    case RESUME:
      break;

    case HALT:
      tool->state = INACTIVE;
      break;

    default:
      break;
    }

  if (GIMP_TOOL_CLASS (parent_class)->control)
    GIMP_TOOL_CLASS (parent_class)->control (tool, action, gdisp);
}

static void
gimp_path_tool_button_press (GimpTool       *tool,
                             GdkEventButton *bevent,
                             GDisplay       *gdisp)
{
  GimpPathTool *path_tool = GIMP_PATH_TOOL (tool);
  gint grab_pointer=0;
  gdouble x, y;
  gint halfwidth, dummy;

#ifdef PATH_TOOL_DEBUG
  fprintf (stderr, "path_tool_button_press\n");
#endif PATH_TOOL_DEBUG

  /* Transform window-coordinates to canvas-coordinates */
  gdisplay_untransform_coords_f (gdisp, bevent->x, bevent->y, &x, &y, TRUE);
#ifdef PATH_TOOL_DEBUG
  fprintf(stderr, "Clickcoordinates %.2f, %.2f\n",x,y);
#endif PATH_TOOL_DEBUG
  path_tool->click_x = x;
  path_tool->click_y = y;
  path_tool->click_modifier = bevent->state;
  /* get halfwidth in image coord */
  gdisplay_untransform_coords (gdisp, bevent->x + PATH_TOOL_HALFWIDTH, 0, &halfwidth, &dummy, TRUE, 0);
  halfwidth -= x;
  path_tool->click_halfwidth = halfwidth;
  
  tool->gdisp = gdisp;
  tool->state = ACTIVE;

  if (!path_tool->cur_path->curves)
    gimp_draw_tool_start (GIMP_DRAW_TOOL(path_tool), gdisp->canvas->window);

  /* determine point, where clicked,
   * switch accordingly.
   */
 
  path_tool->click_type =
	       path_tool_cursor_position (path_tool->cur_path, x, y, halfwidth,
					  &(path_tool->click_path),
					  &(path_tool->click_curve),
					  &(path_tool->click_segment),
					  &(path_tool->click_position),
					  &(path_tool->click_handle_id));
 
  switch (path_tool->click_type)
  {
  case ON_CANVAS:
     grab_pointer = gimp_path_tool_button_press_canvas(path_tool, bevent, gdisp);
     break;

  case ON_ANCHOR:
     grab_pointer = gimp_path_tool_button_press_anchor(path_tool, bevent, gdisp);
     break;

  case ON_HANDLE:
     grab_pointer = gimp_path_tool_button_press_handle(path_tool, bevent, gdisp);
     break;

  case ON_CURVE:
     grab_pointer = gimp_path_tool_button_press_curve(path_tool, bevent, gdisp);
     break;

  default:
     g_message("Huh? Whats happening here? (button_press_*)");
  }
 
  if (grab_pointer)
     gdk_pointer_grab (gdisp->canvas->window, FALSE,
		       GDK_POINTER_MOTION_HINT_MASK |
		       GDK_BUTTON1_MOTION_MASK |
		       GDK_BUTTON_RELEASE_MASK,
		       NULL, NULL, bevent->time);


}

static gint
gimp_path_tool_button_press_anchor (GimpPathTool *path_tool,
                               GdkEventButton *bevent,
                               GDisplay *gdisp)
{
   static guint32 last_click_time=0;
   gboolean doubleclick=FALSE;
   
   NPath * cur_path = path_tool->cur_path;
   PathSegment *p_sas;
   gint grab_pointer;
   
#ifdef PATH_TOOL_DEBUG
   fprintf(stderr, "path_tool_button_press_anchor:\n");
#endif PATH_TOOL_DEBUG
   
   grab_pointer = 1;

   if (!cur_path) {
#ifdef PATH_TOOL_DEBUG
      fprintf (stderr, "Fatal error: No current Path\n");
#endif PATH_TOOL_DEBUG
      return 0;
   }
   
   /* 
    * We have to determine, if this was a doubleclick for ourself, because
    * disp_callback.c ignores the GDK_[23]BUTTON_EVENT's and adding them to
    * the switch statement confuses some tools.
    */
   if (bevent->time - last_click_time < 250) {
      doubleclick=TRUE;
#ifdef PATH_TOOL_DEBUG
      fprintf (stderr, "Doppelclick!\n");
#endif PATH_TOOL_DEBUG
   } else
      doubleclick=FALSE;
   last_click_time = bevent->time;


   gimp_draw_tool_pause (GIMP_DRAW_TOOL(path_tool));
  
   /* The user pressed on an anchor:
    *  normally this activates this anchor
    *  + SHIFT toggles the activity of an anchor.
    *  if this anchor is at the end of an open curve and the other
    *  end is active, close the curve.
    *  
    *  Doubleclick (de)activates the whole curve (not Path!).
    */

   p_sas = path_tool->single_active_segment;

#ifdef PATH_TOOL_DEBUG
   fprintf (stderr, "p_sas: %p\n", p_sas);
#endif PATH_TOOL_DEBUG

   if (path_tool->click_modifier & GDK_SHIFT_MASK) {
      if (path_tool->active_count == 1 && p_sas && p_sas != path_tool->click_segment &&
          (p_sas->next == NULL || p_sas->prev == NULL) &&
          (path_tool->click_segment->next == NULL || path_tool->click_segment->prev == NULL)) {
         /*
          * if this is the end of an open curve and the single active segment was another
          * open end, connect those ends.
          */
         path_join_curves (path_tool->click_segment, p_sas);
         path_set_flags (path_tool, path_tool->click_path, path_tool->click_curve,
                         NULL, 0, SEGMENT_ACTIVE);
      }

      if (doubleclick)
         /*
          * Doubleclick set the whole curve to the same state, depending on the
          * state of the clicked anchor.
          */
         if (path_tool->click_segment->flags & SEGMENT_ACTIVE)
            path_set_flags (path_tool, path_tool->click_path, path_tool->click_curve,
                            NULL, SEGMENT_ACTIVE, 0);
         else
            path_set_flags (path_tool, path_tool->click_path, path_tool->click_curve,
                            NULL, 0, SEGMENT_ACTIVE);
      else
         /*
          * Toggle the state of the clicked anchor.
          */
         if (path_tool->click_segment->flags & SEGMENT_ACTIVE)
            path_set_flags (path_tool, path_tool->click_path, path_tool->click_curve,
                            path_tool->click_segment, 0, SEGMENT_ACTIVE);
         else
            path_set_flags (path_tool, path_tool->click_path, path_tool->click_curve,
                            path_tool->click_segment, SEGMENT_ACTIVE, 0);
   }
   /*
    * Delete anchors, when CONTROL is pressed
    */
   else if (path_tool->click_modifier & GDK_CONTROL_MASK)
   {
      if (path_tool->click_segment->flags & SEGMENT_ACTIVE)
      {
         if (path_tool->click_segment->prev)
            path_set_flags (path_tool, path_tool->click_path, path_tool->click_curve,
                            path_tool->click_segment->prev, SEGMENT_ACTIVE, 0);
         else if (path_tool->click_segment->next)
            path_set_flags (path_tool, path_tool->click_path, path_tool->click_curve,
                            path_tool->click_segment->next, SEGMENT_ACTIVE, 0);
      }

      path_delete_segment (path_tool->click_segment);
      path_tool->click_segment = NULL;
      /* Maybe CTRL-ALT Click should remove the whole curve? Or the active points? */
   }
   else if (!(path_tool->click_segment->flags & SEGMENT_ACTIVE))
   {
      path_set_flags (path_tool, cur_path, NULL, NULL, 0, SEGMENT_ACTIVE);
      path_set_flags (path_tool, cur_path, path_tool->click_curve, path_tool->click_segment, SEGMENT_ACTIVE, 0);
   }
   

   gimp_draw_tool_resume (GIMP_DRAW_TOOL(path_tool));

   return grab_pointer;
}


static gint
gimp_path_tool_button_press_handle (GimpPathTool *path_tool,
				    GdkEventButton *bevent,
				    GDisplay *gdisp)
{
   static guint32 last_click_time=0;
   gboolean doubleclick=FALSE;
   
   NPath * cur_path = path_tool->cur_path;
   gint grab_pointer;
   
#ifdef PATH_TOOL_DEBUG
   fprintf(stderr, "path_tool_button_press_handle:\n");
#endif PATH_TOOL_DEBUG
   
   grab_pointer = 1;

   if (!cur_path) {
#ifdef PATH_TOOL_DEBUG
      fprintf (stderr, "Fatal error: No current Path\n");
#endif PATH_TOOL_DEBUG
      return 0;
   }
   
   /* 
    * We have to determine, if this was a doubleclick for ourself, because
    * disp_callback.c ignores the GDK_[23]BUTTON_EVENT's and adding them to
    * the switch statement confuses some tools.
    */
   if (bevent->time - last_click_time < 250) {
      doubleclick=TRUE;
#ifdef PATH_TOOL_DEBUG
      fprintf (stderr, "Doppelclick!\n");
#endif PATH_TOOL_DEBUG
   } else
      doubleclick=FALSE;
   last_click_time = bevent->time;

   return grab_pointer;
}

static gint
gimp_path_tool_button_press_canvas (GimpPathTool *path_tool,
				    GdkEventButton *bevent,
				    GDisplay *gdisp)
{
   
   NPath * cur_path = path_tool->cur_path;
   PathCurve * cur_curve;
   PathSegment * cur_segment;
   gint grab_pointer;
   
#ifdef PATH_TOOL_DEBUG
   fprintf(stderr, "path_tool_button_press_canvas:\n");
#endif PATH_TOOL_DEBUG
   
   grab_pointer = 1;
   
   if (!cur_path) {
#ifdef PATH_TOOL_DEBUG
      fprintf (stderr, "Fatal error: No current Path\n");
#endif PATH_TOOL_DEBUG
      return 0;
   }
   
   gimp_draw_tool_pause (GIMP_DRAW_TOOL(path_tool));
   
   if (path_tool->active_count == 1 && path_tool->single_active_segment != NULL
       && (path_tool->single_active_segment->prev == NULL || path_tool->single_active_segment->next == NULL)) {
      cur_segment = path_tool->single_active_segment;
      cur_curve = cur_segment->parent;

      path_set_flags (path_tool, cur_path, NULL, NULL, 0, SEGMENT_ACTIVE);

      if (cur_segment->next == NULL)
         cur_curve->cur_segment = path_append_segment(cur_path, cur_curve, SEGMENT_BEZIER, path_tool->click_x, path_tool->click_y);
      else
         cur_curve->cur_segment = path_prepend_segment(cur_path, cur_curve, SEGMENT_BEZIER, path_tool->click_x, path_tool->click_y);
      if (cur_curve->cur_segment) {
         path_set_flags (path_tool, cur_path, cur_curve, cur_curve->cur_segment, SEGMENT_ACTIVE, 0);
      }
   } else {
      if (path_tool->active_count == 0) {
         path_set_flags (path_tool, cur_path, NULL, NULL, 0, SEGMENT_ACTIVE);
         cur_path->cur_curve = path_add_curve(cur_path, path_tool->click_x, path_tool->click_y);
         path_set_flags (path_tool, cur_path, cur_path->cur_curve, cur_path->cur_curve->segments, SEGMENT_ACTIVE, 0);
      } else {
         path_set_flags (path_tool, cur_path, NULL, NULL, 0, SEGMENT_ACTIVE);
      }
   }
   
   gimp_draw_tool_resume (GIMP_DRAW_TOOL(path_tool));

   return 0;
}

static gint
gimp_path_tool_button_press_curve (GimpPathTool *path_tool,
				   GdkEventButton *bevent,
				   GDisplay *gdisp)
{
   NPath * cur_path = path_tool->cur_path;
   PathSegment * cur_segment;
   gint grab_pointer;
   
#ifdef PATH_TOOL_DEBUG
   fprintf(stderr, "path_tool_button_press_curve:\n");
#endif PATH_TOOL_DEBUG
   
   grab_pointer = 1;
   
   if (!cur_path) {
#ifdef PATH_TOOL_DEBUG
      fprintf (stderr, "Fatal error: No current NPath\n");
#endif PATH_TOOL_DEBUG
      return 0;
   }
   
   gimp_draw_tool_pause (GIMP_DRAW_TOOL(path_tool));
   
   if (path_tool->click_modifier & GDK_SHIFT_MASK) {
      cur_segment = path_curve_insert_anchor (path_tool->click_segment, path_tool->click_position);
      path_set_flags (path_tool, cur_path, NULL, NULL, 0, SEGMENT_ACTIVE);
      path_set_flags (path_tool, cur_path, path_tool->click_curve, cur_segment, SEGMENT_ACTIVE, 0);
      path_tool->click_type = ON_ANCHOR;
      path_tool->click_segment = cur_segment;

   } else {
      path_set_flags (path_tool, cur_path, NULL, NULL, 0, SEGMENT_ACTIVE);
      path_set_flags (path_tool, cur_path, path_tool->click_curve, path_tool->click_segment, SEGMENT_ACTIVE, 0);
      path_set_flags (path_tool, cur_path, path_tool->click_curve, path_tool->click_segment->next, SEGMENT_ACTIVE, 0);
   }
   gimp_draw_tool_resume (GIMP_DRAW_TOOL(path_tool));

   return 0;
}


static void
gimp_path_tool_button_release (GimpTool       *tool,
			       GdkEventButton *bevent,
			       GDisplay       *gdisp)
{
  GimpPathTool *path_tool = GIMP_PATH_TOOL (tool);

#ifdef PATH_TOOL_DEBUG
   fprintf (stderr, "path_tool_button_release\n");
#endif PATH_TOOL_DEBUG
 
  path_tool->state &= ~PATH_TOOL_DRAG;

  gdk_pointer_ungrab (bevent->time);
  gdk_flush ();
}


static void
gimp_path_tool_motion (GimpTool       *tool,
                       GdkEventMotion *mevent,
                       GDisplay       *gdisp)
{
  GimpPathTool *path_tool;

  path_tool = GIMP_PATH_TOOL (tool);

  if (gtk_events_pending()) return;
  
  switch (path_tool->click_type) {
  case ON_ANCHOR:
     gimp_path_tool_motion_anchor (path_tool, mevent, gdisp);
     break;
  case ON_HANDLE:
     gimp_path_tool_motion_handle (path_tool, mevent, gdisp);
     break;
  case ON_CURVE:
     gimp_path_tool_motion_curve (path_tool, mevent, gdisp);
     break;
  default:
     return;
  }
}



static void
gimp_path_tool_motion_anchor (GimpPathTool  *path_tool,
			      GdkEventMotion *mevent,
			      GDisplay       *gdisp)
{
   gdouble dx, dy, d;
   gdouble x,y;
   static gdouble dxsum = 0;
   static gdouble dysum = 0;
   
   /*
    * Dont do anything, if the user clicked with pressed CONTROL-Key,
    * because he deleted an anchor.
    */
   if (path_tool->click_modifier & GDK_CONTROL_MASK)
      return;
   
   if (!(path_tool->state & PATH_TOOL_DRAG))
   {
      path_tool->state |= PATH_TOOL_DRAG;
      dxsum = 0;
      dysum = 0;
   }

   gdisplay_untransform_coords_f (gdisp, mevent->x, mevent->y, &x, &y, TRUE);
   
   dx = x - path_tool->click_x - dxsum;
   dy = y - path_tool->click_y - dysum;
   
   /* restrict to horizontal/vertical lines, if modifiers are pressed
    * I'm not sure, if this is intuitive for the user. Esp. When moving
    * an endpoint of an curve I'd expect, that the *line* is
    * horiz/vertical - not the delta to the point, where the point was
    * originally...
    */
   if (mevent->state & GDK_MOD1_MASK)
   {
      if (mevent->state & GDK_CONTROL_MASK)
      {
         d  = (fabs(dx) + fabs(dy)) / 2;  
         d  = (fabs(x - path_tool->click_x) + fabs(y - path_tool->click_y)) / 2;
         dx = ((x < path_tool->click_x) ? -d : d ) - dxsum;
         dy = ((y < path_tool->click_y) ? -d : d ) - dysum;
      }
      else
         dx = - dxsum;
   }
   else if (mevent->state & GDK_CONTROL_MASK)
      dy = - dysum;
   

   path_tool->draw |= PATH_TOOL_REDRAW_ACTIVE;
   
   gimp_draw_tool_pause (GIMP_DRAW_TOOL(path_tool));

   path_offset_active (path_tool->cur_path, dx, dy);

   dxsum += dx;
   dysum += dy;

   gimp_draw_tool_resume (GIMP_DRAW_TOOL (path_tool));
   
   path_tool->draw &= ~PATH_TOOL_REDRAW_ACTIVE;

}

static void
gimp_path_tool_motion_handle (GimpPathTool   *path_tool,
			      GdkEventMotion *mevent,
			      GDisplay       *gdisp)
{
   gdouble dx, dy;
   gdouble x,y;
   static gdouble dxsum = 0;
   static gdouble dysum = 0;
   
   /*
    * Dont do anything, if the user clicked with pressed CONTROL-Key,
    * because he moved the handle to the anchor an anchor. 
    * XXX: Not yet! :-)
    */
   if (path_tool->click_modifier & GDK_CONTROL_MASK)
      return;
   
   if (!(path_tool->state & PATH_TOOL_DRAG))
   {
      path_tool->state |= PATH_TOOL_DRAG;
      dxsum = 0;
      dysum = 0;
   }

   gdisplay_untransform_coords_f (gdisp, mevent->x, mevent->y, &x, &y, TRUE);
   
   dx = x - path_tool->click_x - dxsum;
   dy = y - path_tool->click_y - dysum;
   
   path_tool->draw |= PATH_TOOL_REDRAW_ACTIVE;
   
   gimp_draw_tool_pause (GIMP_DRAW_TOOL(path_tool));

   path_curve_drag_handle (path_tool->click_segment, dx, dy, path_tool->click_handle_id);

   dxsum += dx;
   dysum += dy;

   gimp_draw_tool_resume (GIMP_DRAW_TOOL(path_tool));
   
   path_tool->draw &= ~PATH_TOOL_REDRAW_ACTIVE;

}
   

static void
gimp_path_tool_motion_curve (GimpPathTool   *path_tool,
			     GdkEventMotion *mevent,
			     GDisplay       *gdisp)
{
   gdouble dx, dy;
   gdouble x,y;
   static gdouble dxsum = 0;
   static gdouble dysum = 0;
   
   if (!(path_tool->state & PATH_TOOL_DRAG))
   {
      path_tool->state |= PATH_TOOL_DRAG;
      dxsum = 0;
      dysum = 0;
   }

   gdisplay_untransform_coords_f (gdisp, mevent->x, mevent->y, &x, &y, TRUE);
   
   dx = x - path_tool->click_x - dxsum;
   dy = y - path_tool->click_y - dysum;
   
   path_tool->draw |= PATH_TOOL_REDRAW_ACTIVE;
   
   gimp_draw_tool_pause (GIMP_DRAW_TOOL (path_tool));

   path_curve_drag_segment (path_tool->click_segment, path_tool->click_position, dx, dy);

   dxsum += dx;
   dysum += dy;

   gimp_draw_tool_resume (GIMP_DRAW_TOOL (path_tool));
   
   path_tool->draw &= ~PATH_TOOL_REDRAW_ACTIVE;

}
   



static void
gimp_path_tool_cursor_update (GimpTool       *tool,
			      GdkEventMotion *mevent,
			      GDisplay       *gdisp)
{
#if 0
  gint     x, y, halfwidth, dummy, cursor_location;
  
#idef PATH_TOOL_DEBUG
  /* fprintf (stderr, "path_tool_cursor_update\n");
   */
#edif PATH_TOOL_DEBUG

  gdisplay_untransform_coords (gdisp, mevent->x, mevent->y, &x, &y, TRUE, 0);
  /* get halfwidth in image coord */
  gdisplay_untransform_coords (gdisp, mevent->x + PATH_TOOL_HALFWIDTH, 0, &halfwidth, &dummy, TRUE, 0);
  halfwidth -= x;

  cursor_location = path_tool_cursor_position (tool, x, y, halfwidth, NULL, NULL, NULL, NULL, NULL);

  switch (cursor_location) {
  case ON_CANVAS:
     gdisplay_install_tool_cursor (gdisp, GIMP_MOUSE1AP_CURSOR);
     break;
  case ON_ANCHOR:
     gdisplay_install_tool_cursor (gdisp, GDK_FLEUR);
     break;
  case ON_HANDLE:
     gdisplay_install_tool_cursor (gdisp, GDK_CROSSHAIR);
     break;
  case ON_CURVE:
     gdisplay_install_tool_cursor (gdisp, GDK_CROSSHAIR);
     break;
  default:
     gdisplay_install_tool_cursor (gdisp, GDK_QUESTION_ARROW);
     break;
  }

/* New Syntax */
  gdisplay_install_tool_cursor (gdisp,
				ctype,
				GIMP_MEASURE_TOOL_CURSOR,
				cmodifier);
#endif
}


/* This is a CurveTraverseFunc */
static void
gimp_path_tool_draw_helper (NPath *path,
    			    PathCurve *curve,
			    PathSegment *segment,
			    gpointer tool)
{
  GimpPathTool *path_tool;
  GimpDrawTool *draw_tool;
  gboolean draw = TRUE;

  path_tool = GIMP_PATH_TOOL (tool);
  draw_tool = GIMP_DRAW_TOOL (tool);
  
  if (path_tool->draw & PATH_TOOL_REDRAW_ACTIVE)
    draw = (segment->flags & SEGMENT_ACTIVE ||
	    (segment->next && segment->next->flags & SEGMENT_ACTIVE));

  if (segment->flags & SEGMENT_ACTIVE)
    gimp_draw_tool_draw_handle (draw_tool, segment->x, segment->y, PATH_TOOL_WIDTH, 2);
  else
    gimp_draw_tool_draw_handle (draw_tool, segment->x, segment->y, PATH_TOOL_WIDTH, 3);

  if (segment->next)
    path_curve_draw_segment (draw_tool, segment);
}
  

static void
gimp_path_tool_draw (GimpDrawTool *draw_tool)
{
  GimpPathTool *path_tool;

  path_tool = GIMP_PATH_TOOL (draw_tool);

  path_traverse_path (path_tool->click_path, NULL, gimp_path_tool_draw_helper, NULL, draw_tool);
}

