home *** CD-ROM | disk | FTP | other *** search
/ PC Pro 2002 April / pcpro0402.iso / essentials / graphics / Gimp / gimp-src-20001226.exe / src / gimp / app / edit_selection.c < prev    next >
Encoding:
C/C++ Source or Header  |  2000-12-17  |  24.2 KB  |  871 lines

  1. /* The GIMP -- an image manipulation program
  2.  * Copyright (C) 1995 Spencer Kimball and Peter Mattis
  3.  *
  4.  * This program is free software; you can redistribute it and/or modify
  5.  * it under the terms of the GNU General Public License as published by
  6.  * the Free Software Foundation; either version 2 of the License, or
  7.  * (at your option) any later version.
  8.  *
  9.  * This program is distributed in the hope that it will be useful,
  10.  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  11.  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  12.  * GNU General Public License for more details.
  13.  *
  14.  * You should have received a copy of the GNU General Public License
  15.  * along with this program; if not, write to the Free Software
  16.  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
  17.  */
  18.  
  19. #include "config.h"
  20.  
  21. #include <stdlib.h>
  22. #include <stdarg.h>
  23.  
  24. #include <gtk/gtk.h>
  25. #include <gdk/gdkkeysyms.h>
  26.  
  27. #include "apptypes.h"
  28.  
  29. #include "appenv.h"
  30. #include "cursorutil.h"
  31. #include "draw_core.h"
  32. #include "drawable.h"
  33. #include "tools.h"
  34. #include "edit_selection.h"
  35. #include "floating_sel.h"
  36. #include "gimage_mask.h"
  37. #include "gdisplay.h"
  38. #include "undo.h"
  39. #include "gimprc.h"
  40. #include "path_transform.h"
  41.  
  42. #include "libgimp/gimpintl.h"
  43. #include "libgimp/gimpmath.h"
  44.  
  45.  
  46. #define EDIT_SELECT_SCROLL_LOCK FALSE
  47. #define ARROW_VELOCITY          25
  48. #define STATUSBAR_SIZE          128
  49.  
  50.  
  51. typedef struct _EditSelection EditSelection;
  52. struct _EditSelection
  53. {
  54.   gint                origx, origy;      /*  last x and y coords             */
  55.   gint                cumlx, cumly;      /*  cumulative changes to x and yed */
  56.   gint                x, y;              /*  current x and y coords          */
  57.   gint                num_segs_in;       /* Num seg in selection boundary    */
  58.   gint                num_segs_out;      /* Num seg in selection boundary    */
  59.   BoundSeg           *segs_in;           /* Pointer to the channel sel. segs */
  60.   BoundSeg           *segs_out;          /* Pointer to the channel sel. segs */
  61.  
  62.   gint                x1, y1;            /*  bounding box of selection mask  */
  63.   gint                x2, y2;
  64.  
  65.   EditType            edit_type;         /*  translate the mask or layer?    */
  66.  
  67.   DrawCore           *core;              /* selection core for drawing bounds*/
  68.  
  69.   ButtonReleaseFunc   old_button_release;/*  old button press member func    */
  70.   MotionFunc          old_motion;        /*  old motion member function      */
  71.   ToolCtlFunc         old_control;       /*  old control member function     */
  72.   CursorUpdateFunc    old_cursor_update; /*  old cursor update function      */
  73.   gboolean            old_scroll_lock;   /*  old value of scroll lock        */
  74.   gboolean            old_auto_snap_to;  /*  old value of auto snap to       */
  75.  
  76.   gboolean            first_move;        /*  we undo_freeze after the first  */
  77.  
  78.   guint               context_id;        /*  for the statusbar               */
  79. };
  80.  
  81.  
  82. /*  static EditSelection structure -- there is ever only one present  */
  83. static EditSelection edit_select;
  84.  
  85.  
  86. static void
  87. edit_selection_snap (GDisplay *gdisp,
  88.              gdouble   x,
  89.              gdouble   y)
  90. {
  91.   gdouble x1, y1;
  92.   gdouble x2, y2;
  93.   gdouble dx, dy;
  94.  
  95.   gdisplay_untransform_coords_f (gdisp, x, y, &x, &y, TRUE);
  96.  
  97.   dx = x - edit_select.origx;
  98.   dy = y - edit_select.origy;
  99.   
  100.   x1 = edit_select.x1 + dx;
  101.   y1 = edit_select.y1 + dy;
  102.  
  103.   if (gdisp->draw_guides &&
  104.       gdisp->snap_to_guides &&
  105.       gdisp->gimage->guides)
  106.     {
  107.       x2 = edit_select.x2 + dx;
  108.       y2 = edit_select.y2 + dy;
  109.   
  110.       gdisplay_transform_coords_f (gdisp, x1, y1, &x1, &y1, TRUE);
  111.       gdisplay_transform_coords_f (gdisp, x2, y2, &x2, &y2, TRUE);
  112.       
  113.       gdisplay_snap_rectangle (gdisp, x1, y1, x2, y2, &x1, &y1);
  114.       
  115.       gdisplay_untransform_coords_f (gdisp, x1, y1, &x1, &y1, TRUE);
  116.     }
  117.   
  118.   edit_select.x = (gint) RINT (x1) - (edit_select.x1 - edit_select.origx);
  119.   edit_select.y = (gint) RINT (y1) - (edit_select.y1 - edit_select.origy);
  120. }
  121.  
  122. void
  123. init_edit_selection (Tool           *tool,
  124.              gpointer        gdisp_ptr,
  125.              GdkEventButton *bevent,
  126.              EditType        edit_type)
  127. {
  128.   GDisplay *gdisp;
  129.   Layer *layer;
  130.   gint x, y;
  131.  
  132.   gdisp = (GDisplay *) gdisp_ptr;
  133.  
  134.   undo_push_group_start (gdisp->gimage, LAYER_DISPLACE_UNDO);
  135.  
  136.   /*  Move the (x, y) point from screen to image space  */
  137.   gdisplay_untransform_coords (gdisp, 
  138.                    bevent->x, bevent->y, &x, &y, FALSE, TRUE);
  139.  
  140.   edit_select.x = edit_select.origx = x;
  141.   edit_select.y = edit_select.origy = y;
  142.  
  143.   edit_select.cumlx = 0;
  144.   edit_select.cumly = 0;
  145.  
  146.   gimage_mask_boundary (gdisp->gimage, &edit_select.segs_in, 
  147.             &edit_select.segs_out,
  148.             &edit_select.num_segs_in, 
  149.             &edit_select.num_segs_out);
  150.  
  151.   /*  Make a check to see if it should be a floating selection translation  */
  152.   if (edit_type == EDIT_MASK_TO_LAYER_TRANSLATE && gimage_floating_sel (gdisp->gimage))
  153.     edit_type = EDIT_FLOATING_SEL_TRANSLATE;
  154.  
  155.   if (edit_type == EDIT_LAYER_TRANSLATE)
  156.     {
  157.       layer = gimage_get_active_layer (gdisp->gimage);
  158.       if (layer_is_floating_sel (layer))
  159.     edit_type = EDIT_FLOATING_SEL_TRANSLATE;
  160.     }
  161.  
  162.   edit_select.edit_type = edit_type;
  163.  
  164.   edit_select.old_button_release = tool->button_release_func;
  165.   edit_select.old_motion         = tool->motion_func;
  166.   edit_select.old_control        = tool->control_func;
  167.   edit_select.old_cursor_update  = tool->cursor_update_func;
  168.   edit_select.old_scroll_lock    = tool->scroll_lock;
  169.   edit_select.old_auto_snap_to   = tool->auto_snap_to;
  170.  
  171.   edit_select.first_move         = TRUE;
  172.  
  173.   /*  find the bounding box of the selection mask -
  174.    *  this is used for the case of a EDIT_MASK_TO_LAYER_TRANSLATE,
  175.    *  where the translation will result in floating the selection
  176.    *  mask and translating the resulting layer
  177.    */
  178.   drawable_mask_bounds (gimage_active_drawable (gdisp->gimage),
  179.             &edit_select.x1, &edit_select.y1,
  180.             &edit_select.x2, &edit_select.y2);
  181.  
  182.   edit_selection_snap (gdisp, bevent->x, bevent->y);
  183.  
  184.   /*  reset the function pointers on the selection tool  */
  185.   tool->button_release_func = edit_selection_button_release;
  186.   tool->motion_func         = edit_selection_motion;
  187.   tool->control_func        = edit_selection_control;
  188.   tool->cursor_update_func  = edit_selection_cursor_update;
  189.   tool->scroll_lock         = EDIT_SELECT_SCROLL_LOCK;
  190.   tool->auto_snap_to        = FALSE;
  191.  
  192.   /*  pause the current selection  */
  193.   selection_pause (gdisp->select);
  194.  
  195.   /* initialize the statusbar display */
  196.   edit_select.context_id 
  197.     = gtk_statusbar_get_context_id (GTK_STATUSBAR (gdisp->statusbar), 
  198.                     "edit_select");
  199.   gtk_statusbar_push (GTK_STATUSBAR (gdisp->statusbar), 
  200.               edit_select.context_id, 
  201.               _("Move: 0, 0"));
  202.  
  203.   /*  Create and start the selection core  */
  204.   edit_select.core = draw_core_new (edit_selection_draw);
  205.   draw_core_start (edit_select.core,
  206.            gdisp->canvas->window,
  207.            tool);
  208. }
  209.  
  210.  
  211. void
  212. edit_selection_button_release (Tool           *tool,
  213.                    GdkEventButton *bevent,
  214.                    gpointer        gdisp_ptr)
  215. {
  216.   gint      x;
  217.   gint      y;
  218.   GDisplay *gdisp;
  219.   Layer    *layer;
  220.  
  221.   gdisp = (GDisplay *) gdisp_ptr;
  222.  
  223.   /*  resume the current selection and ungrab the pointer  */
  224.   selection_resume (gdisp->select);
  225.  
  226.   gdk_pointer_ungrab (bevent->time);
  227.   gdk_flush ();
  228.  
  229.   gtk_statusbar_pop (GTK_STATUSBAR (gdisp->statusbar), edit_select.context_id);
  230.  
  231.   /*  Stop and free the selection core  */
  232.   draw_core_stop (edit_select.core, tool);
  233.   draw_core_free (edit_select.core);
  234.   edit_select.core = NULL;
  235.   tool->state      = INACTIVE;
  236.  
  237.   tool->button_release_func = edit_select.old_button_release;
  238.   tool->motion_func         = edit_select.old_motion;
  239.   tool->control_func        = edit_select.old_control;
  240.   tool->cursor_update_func  = edit_select.old_cursor_update;
  241.   tool->scroll_lock         = edit_select.old_scroll_lock;
  242.   tool->auto_snap_to        = edit_select.old_auto_snap_to;
  243.  
  244.   /* EDIT_MASK_TRANSLATE is performed here at movement end, not 'live' like
  245.    *  the other translation types.
  246.    */
  247.   if (edit_select.edit_type == EDIT_MASK_TRANSLATE)
  248.     {
  249.       edit_selection_snap (gdisp, bevent->x, bevent->y);
  250.       x = edit_select.x;
  251.       y = edit_select.y;
  252.       
  253.       /* move the selection -- whether there has been net movement or not!
  254.        * (to ensure that there's something on the undo stack)
  255.        */
  256.       gimage_mask_translate (gdisp->gimage, 
  257.                  edit_select.cumlx,
  258.                  edit_select.cumly);
  259.       
  260.       if (edit_select.first_move)
  261.     {
  262.       gimp_image_undo_freeze (gdisp->gimage);
  263.       edit_select.first_move = FALSE;
  264.     }
  265.     }
  266.   
  267.   /* thaw the undo again */
  268.   gimp_image_undo_thaw (gdisp->gimage);
  269.  
  270.   if (edit_select.cumlx == 0 && edit_select.cumly == 0)
  271.     {
  272.       /* The user either didn't actually move the selection,
  273.      or moved it around and eventually just put it back in
  274.      exactly the same spot. */
  275.  
  276.      /*  If no movement occured and the type is EDIT_FLOATING_SEL_TRANSLATE,
  277.       check if the layer is a floating selection.  If so, anchor. */
  278.       if (edit_select.edit_type == EDIT_FLOATING_SEL_TRANSLATE)
  279.     {
  280.       layer = gimage_get_active_layer (gdisp->gimage);
  281.       if (layer_is_floating_sel (layer))
  282.         floating_sel_anchor (layer);
  283.     }
  284.     }
  285.   else
  286.     {
  287.       path_transform_xy (gdisp->gimage, edit_select.cumlx, edit_select.cumly);
  288.  
  289.       layer = gimage_get_active_layer (gdisp->gimage);
  290.       gimp_drawable_invalidate_preview (GIMP_DRAWABLE (layer), TRUE);
  291.     }
  292.     
  293.   undo_push_group_end (gdisp->gimage);
  294.  
  295.   if (bevent->state & GDK_BUTTON3_MASK) /* OPERATION CANCELLED */
  296.     {
  297.       /* Operation cancelled - undo the undo-group! */
  298.       undo_pop (gdisp->gimage);
  299.     }
  300.  
  301.   gdisplays_flush ();
  302. }
  303.  
  304.  
  305. void
  306. edit_selection_motion (Tool           *tool,
  307.                GdkEventMotion *mevent,
  308.                gpointer        gdisp_ptr)
  309. {
  310.   GDisplay * gdisp;
  311.   gchar offset[STATUSBAR_SIZE];
  312.   gdouble lastmotion_x, lastmotion_y;
  313.  
  314.   if (tool->state != ACTIVE)
  315.     {
  316.       g_warning ("BUG: Tracking motion while !ACTIVE");
  317.       return;
  318.     }
  319.  
  320.   gdisp = (GDisplay *) gdisp_ptr;
  321.  
  322.   gdk_flush ();
  323.  
  324.   draw_core_pause (edit_select.core, tool);
  325.  
  326.  
  327.   /* Perform motion compression so that we don't lag and/or waste time. */
  328.  
  329.   if (!gtkutil_compress_motion (gtk_get_event_widget ((GdkEvent*) mevent),
  330.                 &lastmotion_x, &lastmotion_y))
  331.     {
  332.       lastmotion_x = mevent->x;
  333.       lastmotion_y = mevent->y;
  334.     }
  335.  
  336.   /* now do the actual move. */
  337.  
  338.   edit_selection_snap (gdisp, RINT (lastmotion_x), RINT (lastmotion_y));
  339.  
  340.   /******************************************* adam's live move *******/
  341.   /********************************************************************/
  342.   {
  343.     gint    x, y;
  344.     Layer  *layer;
  345.     Layer  *floating_layer;
  346.     GSList *layer_list;
  347.  
  348.     x = edit_select.x;
  349.     y = edit_select.y;
  350.  
  351.     /* if there has been movement, move the selection  */
  352.     if (edit_select.origx != x || edit_select.origy != y)
  353.       {
  354.     gint xoffset, yoffset;
  355.     
  356.     xoffset = x - edit_select.origx;
  357.     yoffset = y - edit_select.origy;
  358.  
  359.     edit_select.cumlx += xoffset;
  360.     edit_select.cumly += yoffset;
  361.  
  362.     switch (edit_select.edit_type)
  363.       {
  364.       case EDIT_MASK_TRANSLATE:
  365.         /*  we don't do the actual edit selection move here.  */
  366.         edit_select.origx = x;
  367.         edit_select.origy = y;
  368.         break;
  369.     
  370.       case EDIT_LAYER_TRANSLATE:
  371.         if ((floating_layer = gimage_floating_sel (gdisp->gimage)))
  372.           floating_sel_relax (floating_layer, TRUE);
  373.       
  374.         /*  translate the layer--and any "linked" layers as well  */
  375.         for (layer_list = gdisp->gimage->layers;
  376.          layer_list;
  377.          layer_list = g_slist_next (layer_list))
  378.           {
  379.         layer = (Layer *) layer_list->data;
  380.         if (layer == gdisp->gimage->active_layer || 
  381.             layer_linked (layer))
  382.           {
  383.             layer_translate (layer, xoffset, yoffset);
  384.           }
  385.           }
  386.       
  387.         if (floating_layer)
  388.           floating_sel_rigor (floating_layer, TRUE);
  389.  
  390.         if (edit_select.first_move)
  391.           {
  392.         gimp_image_undo_freeze (gdisp->gimage);
  393.         edit_select.first_move = FALSE;
  394.           }
  395.         break;
  396.     
  397.       case EDIT_MASK_TO_LAYER_TRANSLATE:
  398.         if (!gimage_mask_float (gdisp->gimage, 
  399.                     gimage_active_drawable (gdisp->gimage),
  400.                     0, 0))
  401.           {
  402.         /* no region to float, abort safely */
  403.          draw_core_resume (edit_select.core, tool);
  404.          return;
  405.           }
  406.  
  407.         /* this is always the first move, since we switch to 
  408.            EDIT_FLOATING_SEL_TRANSLATE when finished here */
  409.         gimp_image_undo_freeze (gdisp->gimage);
  410.         edit_select.first_move = FALSE; 
  411.  
  412.         edit_select.origx -= edit_select.x1;
  413.         edit_select.origy -= edit_select.y1;
  414.         edit_select.x2 -= edit_select.x1;
  415.         edit_select.y2 -= edit_select.y1;
  416.         edit_select.x1 = 0;
  417.         edit_select.y1 = 0;
  418.  
  419.         edit_select.edit_type = EDIT_FLOATING_SEL_TRANSLATE;
  420.         break;
  421.       
  422.       case EDIT_FLOATING_SEL_TRANSLATE:
  423.         layer = gimage_get_active_layer (gdisp->gimage);
  424.       
  425.         floating_sel_relax (layer, TRUE);
  426.         layer_translate (layer, xoffset, yoffset);
  427.         floating_sel_rigor (layer, TRUE);
  428.  
  429.         if (edit_select.first_move)
  430.           {
  431.         gimp_image_undo_freeze (gdisp->gimage);
  432.         edit_select.first_move = FALSE;
  433.           }
  434.         break;
  435.  
  436.       default:
  437.         g_warning ("esm / BAD FALLTHROUGH");
  438.       }
  439.       }
  440.  
  441.     gdisplay_flush (gdisp);
  442.   }
  443.   /********************************************************************/
  444.   /********************************************************************/
  445.   
  446.  
  447.   gtk_statusbar_pop (GTK_STATUSBAR (gdisp->statusbar), edit_select.context_id);
  448.   if (gdisp->dot_for_dot)
  449.     {
  450.       g_snprintf (offset, STATUSBAR_SIZE, gdisp->cursor_format_str,
  451.           _("Move: "),
  452.           edit_select.cumlx,
  453.           ", ",
  454.           edit_select.cumly);
  455.     }
  456.   else /* show real world units */
  457.     {
  458.       gdouble unit_factor = gimp_unit_get_factor (gdisp->gimage->unit);
  459.  
  460.       g_snprintf (offset, STATUSBAR_SIZE, gdisp->cursor_format_str,
  461.           _("Move: "), 
  462.           (edit_select.cumlx) * unit_factor / 
  463.           gdisp->gimage->xresolution,
  464.           ", ",
  465.           (edit_select.cumly) * unit_factor /
  466.           gdisp->gimage->yresolution);
  467.     }
  468.   gtk_statusbar_push (GTK_STATUSBAR (gdisp->statusbar), edit_select.context_id,
  469.               offset);
  470.  
  471.   draw_core_resume (edit_select.core, tool);
  472. }
  473.  
  474. static void
  475. selection_transform_segs (GDisplay   *gdisp,
  476.               BoundSeg   *src_segs,
  477.               GdkSegment *dest_segs,
  478.               gint        num_segs)
  479. {
  480.   gint x, y;
  481.   gint i;
  482.  
  483.   for (i = 0; i < num_segs; i++)
  484.     {
  485.       gdisplay_transform_coords (gdisp, 
  486.                  src_segs[i].x1 + edit_select.cumlx, 
  487.                  src_segs[i].y1 + edit_select.cumly,
  488.                  &x, &y, FALSE);
  489.  
  490.       dest_segs[i].x1 = x;
  491.       dest_segs[i].y1 = y;
  492.  
  493.       gdisplay_transform_coords (gdisp, 
  494.                  src_segs[i].x2 + edit_select.cumlx, 
  495.                  src_segs[i].y2 + edit_select.cumly,
  496.                  &x, &y, FALSE);
  497.  
  498.       dest_segs[i].x2 = x;
  499.       dest_segs[i].y2 = y;
  500.  
  501.     }
  502. }
  503.  
  504. void
  505. edit_selection_draw (Tool *tool)
  506. {
  507.   GDisplay * gdisp;
  508.   Selection * select;
  509.   Layer *layer;
  510.   GSList *layer_list;
  511.   gint floating_sel;
  512.   gint x1, y1, x2, y2;
  513.   gint x3, y3, x4, y4;
  514.   gint off_x, off_y;
  515.   GdkSegment *segs_copy;
  516.  
  517.   gdisp = (GDisplay *) tool->gdisp_ptr;
  518.   select = gdisp->select;
  519.  
  520.   switch (edit_select.edit_type)
  521.     {
  522.     case EDIT_MASK_TRANSLATE:
  523.       layer = gimage_get_active_layer (gdisp->gimage);
  524.       floating_sel = layer_is_floating_sel (layer);
  525.  
  526.       if (!floating_sel)
  527.     {
  528.        segs_copy = g_new (GdkSegment, edit_select.num_segs_in);
  529.  
  530.        selection_transform_segs (gdisp,
  531.                      edit_select.segs_in,
  532.                      segs_copy,
  533.                      edit_select.num_segs_in);
  534.       
  535.        /*  Draw the items  */
  536.        gdk_draw_segments (edit_select.core->win, edit_select.core->gc,
  537.                   segs_copy, select->num_segs_in);
  538.        
  539.        g_free (segs_copy);
  540.     }
  541.  
  542.       segs_copy = g_new (GdkSegment, edit_select.num_segs_out);
  543.       
  544.       selection_transform_segs (gdisp,
  545.                 edit_select.segs_out,
  546.                 segs_copy,
  547.                 edit_select.num_segs_out);
  548.       
  549.       /*  Draw the items  */
  550.       gdk_draw_segments (edit_select.core->win, edit_select.core->gc,
  551.              segs_copy, select->num_segs_out);
  552.  
  553.       g_free (segs_copy);
  554.       break;
  555.  
  556.     case EDIT_MASK_TO_LAYER_TRANSLATE:
  557.       gdisplay_transform_coords (gdisp, 
  558.                  edit_select.x1, edit_select.y1, 
  559.                  &x1, &y1, TRUE);
  560.       gdisplay_transform_coords (gdisp, 
  561.                  edit_select.x2, edit_select.y2, 
  562.                  &x2, &y2, TRUE);
  563.       gdk_draw_rectangle (edit_select.core->win,
  564.               edit_select.core->gc, 0,
  565.               x1, y1,
  566.               x2 - x1 + 1, y2 - y1 + 1);
  567.       break;
  568.  
  569.     case EDIT_LAYER_TRANSLATE:
  570.       gdisplay_transform_coords (gdisp, 0, 0, &x1, &y1, TRUE);
  571.       gdisplay_transform_coords (gdisp,
  572.                  drawable_width (GIMP_DRAWABLE (gdisp->gimage->active_layer)),
  573.                  drawable_height (GIMP_DRAWABLE (gdisp->gimage->active_layer)),
  574.                  &x2, &y2, TRUE);
  575.  
  576.       /*  Now, expand the rectangle to include all linked layers as well  */
  577.       for (layer_list= gdisp->gimage->layers;
  578.        layer_list;
  579.        layer_list = g_slist_next (layer_list))
  580.     {
  581.       layer = (Layer *) layer_list->data;
  582.       if (((layer) != gdisp->gimage->active_layer) && layer_linked (layer))
  583.         {
  584.           drawable_offsets (GIMP_DRAWABLE (layer), &off_x, &off_y);
  585.           gdisplay_transform_coords (gdisp, off_x, off_y, &x3, &y3, FALSE);
  586.           gdisplay_transform_coords (gdisp,
  587.                      off_x + drawable_width (GIMP_DRAWABLE (layer)),
  588.                      off_y + drawable_height (GIMP_DRAWABLE (layer)),
  589.                      &x4, &y4, FALSE);
  590.           if (x3 < x1)
  591.         x1 = x3;
  592.           if (y3 < y1)
  593.         y1 = y3;
  594.           if (x4 > x2)
  595.         x2 = x4;
  596.           if (y4 > y2)
  597.         y2 = y4;
  598.         }
  599.     }
  600.  
  601.       gdk_draw_rectangle (edit_select.core->win,
  602.               edit_select.core->gc, 0,
  603.               x1, y1,
  604.               x2 - x1, y2 - y1);
  605.       break;
  606.  
  607.     case EDIT_FLOATING_SEL_TRANSLATE:
  608.       segs_copy = g_new (GdkSegment, edit_select.num_segs_in);
  609.  
  610.       /* The selection segs are in image space convert these 
  611.        * to display space.
  612.        * Takes care of offset/zoom etc etc.
  613.        */
  614.  
  615.       selection_transform_segs (gdisp,
  616.                 edit_select.segs_in,
  617.                 segs_copy,
  618.                 edit_select.num_segs_in);
  619.       
  620.       /*  Draw the items  */
  621.       gdk_draw_segments (edit_select.core->win, edit_select.core->gc,
  622.              segs_copy, select->num_segs_in);
  623.  
  624.       g_free (segs_copy);
  625.       break;
  626.     }
  627. }
  628.  
  629.  
  630. void
  631. edit_selection_control (Tool       *tool,
  632.             ToolAction  action,
  633.             gpointer    gdisp_ptr)
  634. {
  635.   switch (action)
  636.     {
  637.     case PAUSE:
  638.       draw_core_pause (edit_select.core, tool);
  639.       break;
  640.  
  641.     case RESUME:
  642.       draw_core_resume (edit_select.core, tool);
  643.       break;
  644.  
  645.     case HALT:
  646.       draw_core_stop (edit_select.core, tool);
  647.       draw_core_free (edit_select.core);
  648.       break;
  649.  
  650.     default:
  651.       break;
  652.     }
  653. }
  654.  
  655.  
  656. void
  657. edit_selection_cursor_update (Tool           *tool,
  658.                   GdkEventMotion *mevent,
  659.                   gpointer        gdisp_ptr)
  660. {
  661.   GDisplay *gdisp;
  662.  
  663.   gdisp = (GDisplay *) gdisp_ptr;
  664.   gdisplay_install_tool_cursor (gdisp, GIMP_MOUSE_CURSOR,
  665.                 TOOL_TYPE_NONE,
  666.                 CURSOR_MODIFIER_MOVE,
  667.                 FALSE);
  668. }
  669.  
  670. static gint
  671. process_event_queue_keys (GdkEventKey *kevent, 
  672.               ...)
  673. /* GdkKeyType, GdkModifierType, value ... 0 
  674.  * could move this function to a more central location so it can be used
  675.  * by other tools? */
  676. {
  677. #define FILTER_MAX_KEYS 50
  678.   va_list argp;
  679.   GdkEvent *event;
  680.   GList *event_list = NULL;
  681.   GList *list;
  682.   guint keys[FILTER_MAX_KEYS];
  683.   GdkModifierType modifiers[FILTER_MAX_KEYS];
  684.   gint values[FILTER_MAX_KEYS];
  685.   gint i = 0, nkeys = 0, value = 0;
  686.   gboolean done = FALSE;
  687.   gboolean discard_event;
  688.   GtkWidget *orig_widget;
  689.  
  690.   va_start (argp, kevent);
  691.   while (nkeys <FILTER_MAX_KEYS && (keys[nkeys] = va_arg (argp, guint)) != 0)
  692.     {
  693.       modifiers[nkeys] = va_arg (argp, GdkModifierType);
  694.       values[nkeys]    = va_arg (argp, gint);
  695.       nkeys++;
  696.     }
  697.   va_end(argp);
  698.  
  699.   for (i = 0; i < nkeys; i++)
  700.     {
  701.       if (kevent->keyval == keys[i] && kevent->state == modifiers[i])
  702.     value += values[i];
  703.     }
  704.  
  705.   orig_widget = gtk_get_event_widget ((GdkEvent*) kevent);
  706.  
  707.   while (gdk_events_pending () > 0 && !done)
  708.   {
  709.     discard_event = FALSE;
  710.     event = gdk_event_get ();
  711.  
  712.     if (!event || orig_widget != gtk_get_event_widget (event))
  713.       {
  714.     done = TRUE;
  715.       }
  716.     else
  717.       {
  718.     if (event->any.type == GDK_KEY_PRESS)
  719.       {
  720.         for (i = 0; i < nkeys; i++)
  721.           if (event->key.keyval == keys[i] &&
  722.           event->key.state  == modifiers[i])
  723.         {
  724.           discard_event = TRUE;
  725.           value += values[i];
  726.         }
  727.  
  728.         if (!discard_event)
  729.           done = TRUE;
  730.       }
  731.          /* should there be more types here? */
  732.     else if (event->any.type != GDK_KEY_RELEASE &&
  733.          event->any.type != GDK_MOTION_NOTIFY &&
  734.          event->any.type != GDK_EXPOSE)
  735.       done = FALSE;
  736.       }
  737.  
  738.     if (!event)
  739.       ; /* Do nothing */
  740.     else if (!discard_event)
  741.       event_list = g_list_prepend (event_list, event);
  742.     else
  743.       gdk_event_free (event);
  744.   }
  745.  
  746.   event_list = g_list_reverse (event_list);
  747.  
  748.   /* unget the unused events and free the list */
  749.   for (list = event_list;
  750.        list;
  751.        list = g_list_next (list))
  752.     {
  753.       gdk_event_put ((GdkEvent*)list->data);
  754.       gdk_event_free ((GdkEvent*)list->data);
  755.     }
  756.  
  757.   g_list_free (event_list);
  758.  
  759.   return value;
  760. #undef FILTER_MAX_KEYS
  761. }
  762.  
  763. void
  764. edit_sel_arrow_keys_func (Tool        *tool,
  765.               GdkEventKey *kevent,
  766.               gpointer     gdisp_ptr)
  767. {
  768.   gint inc_x, inc_y, mask_inc_x, mask_inc_y;
  769.   GDisplay *gdisp;
  770.   Layer *layer;
  771.   Layer *floating_layer;
  772.   GSList *layer_list;
  773.   EditType edit_type;
  774.  
  775.   layer = NULL;
  776.  
  777.   gdisp = (GDisplay *) gdisp_ptr;
  778.  
  779.   inc_x = 
  780.     process_event_queue_keys (kevent,
  781.                   GDK_Left,  0,              -1, 
  782.                   GDK_Left,  GDK_SHIFT_MASK, -1 * ARROW_VELOCITY, 
  783.                   GDK_Right, 0,               1, 
  784.                   GDK_Right, GDK_SHIFT_MASK,  1 * ARROW_VELOCITY, 
  785.                   0);
  786.   inc_y = 
  787.     process_event_queue_keys (kevent,
  788.                   GDK_Up,   0,              -1, 
  789.                   GDK_Up,   GDK_SHIFT_MASK, -1 * ARROW_VELOCITY, 
  790.                   GDK_Down, 0,               1, 
  791.                   GDK_Down, GDK_SHIFT_MASK,  1 * ARROW_VELOCITY, 
  792.                   0);
  793.   
  794.   mask_inc_x = 
  795.     process_event_queue_keys (kevent,
  796.                   GDK_Left,  GDK_MOD1_MASK,                    -1, 
  797.                   GDK_Left,  (GDK_MOD1_MASK | GDK_SHIFT_MASK), -1 * ARROW_VELOCITY, 
  798.                   GDK_Right, GDK_MOD1_MASK,                     1, 
  799.                   GDK_Right, (GDK_MOD1_MASK | GDK_SHIFT_MASK),  1 * ARROW_VELOCITY, 
  800.                   0);
  801.   mask_inc_y = 
  802.     process_event_queue_keys (kevent,
  803.                   GDK_Up,   GDK_MOD1_MASK,                    -1, 
  804.                   GDK_Up,   (GDK_MOD1_MASK | GDK_SHIFT_MASK), -1 * ARROW_VELOCITY, 
  805.                   GDK_Down, GDK_MOD1_MASK,                     1, 
  806.                   GDK_Down, (GDK_MOD1_MASK | GDK_SHIFT_MASK),  1 * ARROW_VELOCITY, 
  807.                   0);
  808.  
  809.   if (inc_x == 0 && inc_y == 0  &&  mask_inc_x == 0 && mask_inc_y == 0)
  810.     return;
  811.  
  812.   undo_push_group_start (gdisp->gimage, LAYER_DISPLACE_UNDO);
  813.  
  814.   if (mask_inc_x != 0 || mask_inc_y != 0)
  815.     gimage_mask_translate (gdisp->gimage, mask_inc_x, mask_inc_y);
  816.  
  817.   if (inc_x != 0 || inc_y != 0)
  818.     {
  819.       layer = gimage_get_active_layer (gdisp->gimage);
  820.  
  821.       if (layer_is_floating_sel (layer))
  822.     edit_type = EDIT_FLOATING_SEL_TRANSLATE;
  823.       else
  824.     edit_type = EDIT_LAYER_TRANSLATE;
  825.       
  826.       switch (edit_type)
  827.     {
  828.     case EDIT_MASK_TRANSLATE:
  829.     case EDIT_MASK_TO_LAYER_TRANSLATE:
  830.       /*  this won't happen  */
  831.       break;
  832.  
  833.     case EDIT_LAYER_TRANSLATE:
  834.       
  835.       if ((floating_layer = gimage_floating_sel (gdisp->gimage)))
  836.         floating_sel_relax (floating_layer, TRUE);
  837.       
  838.       /*  translate the layer -- and any "linked" layers as well  */
  839.       for (layer_list = gdisp->gimage->layers; 
  840.            layer_list; 
  841.            layer_list = g_slist_next (layer_list))
  842.         {
  843.           layer = (Layer *) layer_list->data;
  844.           if (((layer) == gdisp->gimage->active_layer) || 
  845.           layer_linked (layer))
  846.         {
  847.           layer_translate (layer, inc_x, inc_y);
  848.         }
  849.         }
  850.       
  851.       if (floating_layer)
  852.         floating_sel_rigor (floating_layer, TRUE);
  853.       
  854.       break;
  855.       
  856.     case EDIT_FLOATING_SEL_TRANSLATE:
  857.       
  858.       floating_sel_relax (layer, TRUE);
  859.       
  860.       layer_translate (layer, inc_x, inc_y);
  861.       
  862.       floating_sel_rigor (layer, TRUE);
  863.       
  864.       break;
  865.     }
  866.     }
  867.  
  868.   undo_push_group_end (gdisp->gimage);
  869.   gdisplays_flush ();
  870. }
  871.