home *** CD-ROM | disk | FTP | other *** search
/ PC Pro 2002 April / pcpro0402.iso / essentials / graphics / Gimp / gimp-src-20001226.exe / src / gimp / app / rect_select.c < prev    next >
Encoding:
C/C++ Source or Header  |  2000-12-17  |  18.9 KB  |  744 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.  
  23. #include <gtk/gtk.h>
  24. #include <gdk/gdkkeysyms.h>
  25.  
  26. #include "apptypes.h"
  27.  
  28. #include "appenv.h"
  29. #include "gdisplay.h"
  30. #include "gimage_mask.h"
  31. #include "edit_selection.h"
  32. #include "floating_sel.h"
  33. #include "rect_select.h"
  34. #include "rect_selectP.h"
  35. #include "selection_options.h"
  36. #include "cursorutil.h"
  37.  
  38. #include "libgimp/gimpunitmenu.h"
  39.  
  40. #include "libgimp/gimpintl.h"
  41.  
  42.  
  43. #define STATUSBAR_SIZE 128
  44.  
  45.  
  46. /*  the rectangular selection tool options  */
  47. static SelectionOptions *rect_options = NULL;
  48.  
  49. /*  in gimp, ellipses are rectangular, too ;)  */
  50. extern SelectionOptions *ellipse_options;
  51. extern void ellipse_select (GimpImage *gimage,
  52.                 gint       x,
  53.                 gint       y,
  54.                 gint       w,
  55.                 gint       h,
  56.                 SelectOps  op,
  57.                 gboolean   antialias,
  58.                 gboolean   feather,
  59.                 gdouble    feather_radius);
  60.  
  61. static void selection_tool_update_op_state (RectSelect *rect_sel,
  62.                         gint        x,
  63.                         gint        y,
  64.                         gint        state, 
  65.                         GDisplay   *gdisp);
  66.  
  67. /*************************************/
  68. /*  Rectangular selection apparatus  */
  69.  
  70. void
  71. rect_select (GimpImage *gimage,
  72.          gint       x,
  73.          gint       y,
  74.          gint       w,
  75.          gint       h,
  76.          SelectOps  op,
  77.          gboolean   feather,
  78.          gdouble    feather_radius)
  79. {
  80.   Channel *new_mask;
  81.  
  82.   /*  if applicable, replace the current selection  */
  83.   if (op == SELECTION_REPLACE)
  84.     gimage_mask_clear (gimage);
  85.   else
  86.     gimage_mask_undo (gimage);
  87.  
  88.   /*  if feathering for rect, make a new mask with the
  89.    *  rectangle and feather that with the old mask
  90.    */
  91.   if (feather)
  92.     {
  93.       new_mask = channel_new_mask (gimage, gimage->width, gimage->height);
  94.       channel_combine_rect (new_mask, ADD, x, y, w, h);
  95.       channel_feather (new_mask, gimage_get_mask (gimage),
  96.                feather_radius,
  97.                feather_radius,
  98.                op, 0, 0);
  99.       channel_delete (new_mask);
  100.     }
  101.   else if (op == SELECTION_INTERSECT)
  102.     {
  103.       new_mask = channel_new_mask (gimage, gimage->width, gimage->height);
  104.       channel_combine_rect (new_mask, ADD, x, y, w, h);
  105.       channel_combine_mask (gimage_get_mask (gimage), new_mask, op, 0, 0);
  106.       channel_delete (new_mask);
  107.     }
  108.   else
  109.     channel_combine_rect (gimage_get_mask (gimage), op, x, y, w, h);
  110. }
  111.  
  112. void
  113. rect_select_button_press (Tool           *tool,
  114.               GdkEventButton *bevent,
  115.               gpointer        gdisp_ptr)
  116. {
  117.   GDisplay   *gdisp;
  118.   RectSelect *rect_sel;
  119.   gchar       select_mode[STATUSBAR_SIZE];
  120.   gint        x, y;
  121.   GimpUnit    unit = GIMP_UNIT_PIXEL;
  122.   gdouble     unit_factor;
  123.  
  124.   gdisp = (GDisplay *) gdisp_ptr;
  125.   rect_sel = (RectSelect *) tool->private;
  126.  
  127.   gdisplay_untransform_coords (gdisp, bevent->x, bevent->y, &x, &y, TRUE, 0);
  128.  
  129.   rect_sel->x = x;
  130.   rect_sel->y = y;
  131.   switch (tool->type)
  132.     {
  133.     case RECT_SELECT:
  134.       rect_sel->fixed_size   = rect_options->fixed_size;
  135.       rect_sel->fixed_width  = rect_options->fixed_width;
  136.       rect_sel->fixed_height = rect_options->fixed_height;
  137.       unit = rect_options->fixed_unit;
  138.       break;
  139.     case ELLIPSE_SELECT:
  140.       rect_sel->fixed_size   = ellipse_options->fixed_size;
  141.       rect_sel->fixed_width  = ellipse_options->fixed_width;
  142.       rect_sel->fixed_height = ellipse_options->fixed_height;
  143.       unit = ellipse_options->fixed_unit;
  144.       break;
  145.     default:
  146.       break;
  147.     }
  148.  
  149.   switch (unit)
  150.     {
  151.     case GIMP_UNIT_PIXEL:
  152.       break;
  153.     case GIMP_UNIT_PERCENT:
  154.       rect_sel->fixed_width =
  155.     gdisp->gimage->width * rect_sel->fixed_width / 100;
  156.       rect_sel->fixed_height =
  157.     gdisp->gimage->height * rect_sel->fixed_height / 100;
  158.       break;
  159.     default:
  160.       unit_factor = gimp_unit_get_factor (unit);
  161.       rect_sel->fixed_width =
  162.      rect_sel->fixed_width * gdisp->gimage->xresolution / unit_factor;
  163.       rect_sel->fixed_height =
  164.     rect_sel->fixed_height * gdisp->gimage->yresolution / unit_factor;
  165.       break;
  166.     }
  167.  
  168.   rect_sel->fixed_width  = MAX (1, rect_sel->fixed_width);
  169.   rect_sel->fixed_height = MAX (1, rect_sel->fixed_height);
  170.  
  171.   rect_sel->w = 0;
  172.   rect_sel->h = 0;
  173.  
  174.   rect_sel->center = FALSE;
  175.  
  176.   gdk_pointer_grab (gdisp->canvas->window, FALSE,
  177.             GDK_POINTER_MOTION_HINT_MASK |
  178.             GDK_BUTTON1_MOTION_MASK |
  179.             GDK_BUTTON_RELEASE_MASK,
  180.             NULL, NULL, bevent->time);
  181.  
  182.   tool->state = ACTIVE;
  183.   tool->gdisp_ptr = gdisp_ptr;
  184.  
  185.   switch (rect_sel->op)
  186.     {
  187.     case SELECTION_MOVE_MASK:
  188.       init_edit_selection (tool, gdisp_ptr, bevent, EDIT_MASK_TRANSLATE);
  189.       return;
  190.     case SELECTION_MOVE:
  191.       init_edit_selection (tool, gdisp_ptr, bevent, EDIT_MASK_TO_LAYER_TRANSLATE);
  192.       return;
  193.     default:
  194.       break;
  195.     }
  196.  
  197.   /* initialize the statusbar display */
  198.   rect_sel->context_id =
  199.     gtk_statusbar_get_context_id (GTK_STATUSBAR (gdisp->statusbar), "selection");
  200.   switch (rect_sel->op)
  201.     {
  202.     case SELECTION_ADD:
  203.       g_snprintf (select_mode, STATUSBAR_SIZE, _("Selection: ADD"));
  204.       break;
  205.     case SELECTION_SUB:
  206.       g_snprintf (select_mode, STATUSBAR_SIZE, _("Selection: SUBTRACT"));
  207.       break;
  208.     case SELECTION_INTERSECT:
  209.       g_snprintf (select_mode, STATUSBAR_SIZE, _("Selection: INTERSECT"));
  210.       break;
  211.     case SELECTION_REPLACE:
  212.       g_snprintf (select_mode, STATUSBAR_SIZE, _("Selection: REPLACE"));
  213.       break;
  214.     default:
  215.       break;
  216.     }
  217.   gtk_statusbar_push (GTK_STATUSBAR (gdisp->statusbar),
  218.               rect_sel->context_id, select_mode);
  219.  
  220.   draw_core_start (rect_sel->core, gdisp->canvas->window, tool);
  221. }
  222.  
  223. void
  224. rect_select_button_release (Tool           *tool,
  225.                 GdkEventButton *bevent,
  226.                 gpointer        gdisp_ptr)
  227. {
  228.   RectSelect *rect_sel;
  229.   GDisplay   *gdisp;
  230.   gint x1, y1;
  231.   gint x2, y2;
  232.   gint w, h;
  233.  
  234.   gdisp = (GDisplay *) gdisp_ptr;
  235.   rect_sel = (RectSelect *) tool->private;
  236.  
  237.   gdk_pointer_ungrab (bevent->time);
  238.   gdk_flush ();
  239.  
  240.   gtk_statusbar_pop (GTK_STATUSBAR (gdisp->statusbar), rect_sel->context_id);
  241.  
  242.   draw_core_stop (rect_sel->core, tool);
  243.   tool->state = INACTIVE;
  244.  
  245.   /*  First take care of the case where the user "cancels" the action  */
  246.   if (! (bevent->state & GDK_BUTTON3_MASK))
  247.     {
  248.       x1 = (rect_sel->w < 0) ? rect_sel->x + rect_sel->w : rect_sel->x;
  249.       y1 = (rect_sel->h < 0) ? rect_sel->y + rect_sel->h : rect_sel->y;
  250.       w = (rect_sel->w < 0) ? -rect_sel->w : rect_sel->w;
  251.       h = (rect_sel->h < 0) ? -rect_sel->h : rect_sel->h;
  252.  
  253.      if ((!w || !h) && !rect_sel->fixed_size)
  254.     {
  255.       /*  If there is a floating selection, anchor it  */
  256.       if (gimage_floating_sel (gdisp->gimage))
  257.         floating_sel_anchor (gimage_floating_sel (gdisp->gimage));
  258.       /*  Otherwise, clear the selection mask  */
  259.       else
  260.         gimage_mask_clear (gdisp->gimage);
  261.       
  262.       gdisplays_flush ();
  263.       return;
  264.     }
  265.       
  266.       x2 = x1 + w;
  267.       y2 = y1 + h;
  268.  
  269.       switch (tool->type)
  270.     {
  271.     case RECT_SELECT:
  272.       rect_select (gdisp->gimage,
  273.                x1, y1, (x2 - x1), (y2 - y1),
  274.                rect_sel->op,
  275.                rect_options->feather,
  276.                rect_options->feather_radius);
  277.       break;
  278.       
  279.     case ELLIPSE_SELECT:
  280.       ellipse_select (gdisp->gimage,
  281.               x1, y1, (x2 - x1), (y2 - y1),
  282.               rect_sel->op,
  283.               ellipse_options->antialias,
  284.               ellipse_options->feather,
  285.               ellipse_options->feather_radius);
  286.       break;
  287.     default:
  288.       break;
  289.     }
  290.       
  291.       /*  show selection on all views  */
  292.       gdisplays_flush ();
  293.    }
  294. }
  295.  
  296. void
  297. rect_select_motion (Tool           *tool,
  298.             GdkEventMotion *mevent,
  299.             gpointer        gdisp_ptr)
  300. {
  301.   RectSelect *rect_sel;
  302.   GDisplay   *gdisp;
  303.   gchar   size[STATUSBAR_SIZE];
  304.   gint    ox, oy;
  305.   gint    x, y;
  306.   gint    w, h, s;
  307.   gint    tw, th;
  308.   gdouble ratio;
  309.  
  310.   gdisp = (GDisplay *) gdisp_ptr;
  311.   rect_sel = (RectSelect *) tool->private;
  312.  
  313.   /*  needed for immediate cursor update on modifier event  */
  314.   rect_sel->current_x = mevent->x;
  315.   rect_sel->current_y = mevent->y;
  316.  
  317.   if (tool->state != ACTIVE)
  318.     return;
  319.  
  320.   if (rect_sel->op == SELECTION_ANCHOR)
  321.     {
  322.       rect_sel->op = SELECTION_REPLACE;
  323.  
  324.       rect_select_cursor_update (tool, mevent, gdisp_ptr);
  325.     }
  326.  
  327.   draw_core_pause (rect_sel->core, tool);
  328.  
  329.   /* Calculate starting point */
  330.  
  331.   if (rect_sel->center)
  332.     {
  333.       ox = rect_sel->x + rect_sel->w / 2;
  334.       oy = rect_sel->y + rect_sel->h / 2;
  335.     }
  336.   else
  337.     {
  338.       ox = rect_sel->x;
  339.       oy = rect_sel->y;
  340.     }
  341.  
  342.   gdisplay_untransform_coords (gdisp, mevent->x, mevent->y, &x, &y, TRUE, 0);
  343.   if (rect_sel->fixed_size)
  344.     {
  345.       if (mevent->state & GDK_SHIFT_MASK)
  346.     {
  347.       ratio = (double)(rect_sel->fixed_height /
  348.                (double)rect_sel->fixed_width);
  349.       tw = x - ox;
  350.       th = y - oy;
  351.       /* 
  352.        * This is probably an inefficient way to do it, but it gives
  353.        * nicer, more predictable results than the original agorithm
  354.        */
  355.  
  356.       if ((abs(th) < (ratio * abs(tw))) && (abs(tw) > (abs(th) / ratio)))
  357.         {
  358.           w = tw;
  359.           h = (int)(tw * ratio);
  360.           /* h should have the sign of th */
  361.           if ((th < 0 && h > 0) || (th > 0 && h < 0))
  362.         h = -h;
  363.         } 
  364.       else 
  365.         {
  366.           h = th;
  367.           w = (int)(th / ratio);
  368.           /* w should have the sign of tw */
  369.           if ((tw < 0 && w > 0) || (tw > 0 && w < 0))
  370.         w = -w;
  371.         }
  372.     }
  373.       else
  374.     {
  375.       w = (x - ox > 0 ? rect_sel->fixed_width  : -rect_sel->fixed_width);
  376.       h = (y - oy > 0 ? rect_sel->fixed_height : -rect_sel->fixed_height);
  377.     }
  378.     }
  379.   else
  380.     {
  381.       w = (x - ox);
  382.       h = (y - oy);
  383.     }
  384.  
  385.   /*  If the shift key is down, then make the rectangle square (or ellipse circular) */
  386.   if ((mevent->state & GDK_SHIFT_MASK) && !rect_sel->fixed_size)
  387.     {
  388.       s = MAX (abs (w), abs (h));
  389.       
  390.       if (w < 0)
  391.     w = -s;
  392.       else
  393.     w = s;
  394.  
  395.       if (h < 0)
  396.     h = -s;
  397.       else
  398.     h = s;
  399.     }
  400.  
  401.   /*  If the control key is down, create the selection from the center out */
  402.   if (mevent->state & GDK_CONTROL_MASK)
  403.     {
  404.       if (rect_sel->fixed_size) 
  405.     {
  406.           if (mevent->state & GDK_SHIFT_MASK) 
  407.             {
  408.               rect_sel->x = ox - w;
  409.               rect_sel->y = oy - h;
  410.               rect_sel->w = w * 2;
  411.               rect_sel->h = h * 2;
  412.             }
  413.           else
  414.             {
  415.               rect_sel->x = ox - w / 2;
  416.               rect_sel->y = oy - h / 2;
  417.               rect_sel->w = w;
  418.               rect_sel->h = h;
  419.             }
  420.     } 
  421.       else 
  422.     {
  423.       w = abs(w);
  424.       h = abs(h);
  425.       
  426.       rect_sel->x = ox - w;
  427.       rect_sel->y = oy - h;
  428.       rect_sel->w = 2 * w + 1;
  429.       rect_sel->h = 2 * h + 1;
  430.     }
  431.       rect_sel->center = TRUE;
  432.     }
  433.   else
  434.     {
  435.       rect_sel->x = ox;
  436.       rect_sel->y = oy;
  437.       rect_sel->w = w;
  438.       rect_sel->h = h;
  439.  
  440.       rect_sel->center = FALSE;
  441.     }
  442.  
  443.   gtk_statusbar_pop (GTK_STATUSBAR (gdisp->statusbar), rect_sel->context_id);
  444.   if (gdisp->dot_for_dot)
  445.     {
  446.       g_snprintf (size, STATUSBAR_SIZE, gdisp->cursor_format_str,
  447.           _("Selection: "), abs(rect_sel->w), " x ", abs(rect_sel->h));
  448.     }
  449.   else /* show real world units */
  450.     {
  451.       gdouble unit_factor = gimp_unit_get_factor (gdisp->gimage->unit);
  452.  
  453.       g_snprintf (size, STATUSBAR_SIZE, gdisp->cursor_format_str,
  454.           _("Selection: "),
  455.           (gdouble) abs(rect_sel->w) * unit_factor /
  456.           gdisp->gimage->xresolution,
  457.           " x ",
  458.           (gdouble) abs(rect_sel->h) * unit_factor /
  459.           gdisp->gimage->yresolution);
  460.     }
  461.   gtk_statusbar_push (GTK_STATUSBAR (gdisp->statusbar), rect_sel->context_id,
  462.               size);
  463.  
  464.   draw_core_resume (rect_sel->core, tool);
  465. }
  466.  
  467. void
  468. rect_select_draw (Tool *tool)
  469. {
  470.   GDisplay   *gdisp;
  471.   RectSelect *rect_sel;
  472.   gint x1, y1;
  473.   gint x2, y2;
  474.  
  475.   gdisp = (GDisplay *) tool->gdisp_ptr;
  476.   rect_sel = (RectSelect *) tool->private;
  477.  
  478.   x1 = MIN (rect_sel->x, rect_sel->x + rect_sel->w);
  479.   y1 = MIN (rect_sel->y, rect_sel->y + rect_sel->h);
  480.   x2 = MAX (rect_sel->x, rect_sel->x + rect_sel->w);
  481.   y2 = MAX (rect_sel->y, rect_sel->y + rect_sel->h);
  482.  
  483.   gdisplay_transform_coords (gdisp, x1, y1, &x1, &y1, 0);
  484.   gdisplay_transform_coords (gdisp, x2, y2, &x2, &y2, 0);
  485.  
  486.   gdk_draw_rectangle (rect_sel->core->win,
  487.               rect_sel->core->gc, 0,
  488.               x1, y1, (x2 - x1), (y2 - y1));
  489. }
  490.  
  491. static void
  492. selection_tool_update_op_state (RectSelect *rect_sel,
  493.                 gint        x,
  494.                 gint        y,
  495.                 gint        state,  
  496.                 GDisplay   *gdisp)
  497. {
  498.   Layer *layer;
  499.   Layer *floating_sel;
  500.   gint   tx, ty;
  501.  
  502.   if (active_tool->state == ACTIVE)
  503.     return;
  504.  
  505.   gdisplay_untransform_coords (gdisp, x, y, &tx, &ty, FALSE, FALSE);
  506.  
  507.   layer = gimage_pick_correlate_layer (gdisp->gimage, tx, ty);
  508.   floating_sel = gimage_floating_sel (gdisp->gimage);
  509.  
  510.   if (state & GDK_MOD1_MASK &&
  511.       !gimage_mask_is_empty (gdisp->gimage))
  512.     {
  513.       rect_sel->op = SELECTION_MOVE_MASK; /* move just the selection mask */
  514.     }
  515.   else if (!(state & (GDK_SHIFT_MASK | GDK_CONTROL_MASK)) &&
  516.        layer &&
  517.        (layer == floating_sel ||
  518.         (gdisplay_mask_value (gdisp, x, y) &&
  519.          floating_sel == NULL)))
  520.     {
  521.       rect_sel->op = SELECTION_MOVE;      /* move the selection */
  522.     }
  523.   else if ((state & GDK_SHIFT_MASK) &&
  524.        !(state & GDK_CONTROL_MASK))
  525.     {
  526.       rect_sel->op = SELECTION_ADD;       /* add to the selection */
  527.     }
  528.   else if ((state & GDK_CONTROL_MASK) &&
  529.        !(state & GDK_SHIFT_MASK))
  530.     {
  531.       rect_sel->op = SELECTION_SUB;       /* subtract from the selection */
  532.     }
  533.   else if ((state & GDK_CONTROL_MASK) &&
  534.        (state & GDK_SHIFT_MASK))
  535.     {
  536.       rect_sel->op = SELECTION_INTERSECT; /* intersect with selection */
  537.     }
  538.   else if (floating_sel)
  539.     {
  540.       rect_sel->op = SELECTION_ANCHOR;    /* anchor the selection */
  541.     }
  542.   else
  543.     {
  544.       rect_sel->op = SELECTION_REPLACE;   /* replace the selection */
  545.     }
  546. }
  547.  
  548. void
  549. rect_select_oper_update  (Tool           *tool,
  550.               GdkEventMotion *mevent,
  551.               gpointer        gdisp_ptr)
  552. {
  553.   RectSelect *rect_sel;
  554.  
  555.   rect_sel = (RectSelect *) tool->private;
  556.  
  557.   rect_sel->current_x = mevent->x;
  558.   rect_sel->current_y = mevent->y;
  559.  
  560.   selection_tool_update_op_state (rect_sel,
  561.                   rect_sel->current_x,
  562.                   rect_sel->current_y,
  563.                   mevent->state, gdisp_ptr);
  564. }
  565.  
  566. void
  567. rect_select_modifier_update (Tool        *tool,
  568.                  GdkEventKey *kevent,
  569.                  gpointer     gdisp_ptr)
  570. {
  571.   RectSelect *rect_sel;
  572.   gint state;
  573.  
  574.   state = kevent->state;
  575.  
  576.   switch (kevent->keyval)
  577.     {
  578.     case GDK_Alt_L: case GDK_Alt_R:
  579.       if (state & GDK_MOD1_MASK)
  580.     state &= ~GDK_MOD1_MASK;
  581.       else
  582.     state |= GDK_MOD1_MASK;
  583.       break;
  584.  
  585.     case GDK_Shift_L: case GDK_Shift_R:
  586.       if (state & GDK_SHIFT_MASK)
  587.     state &= ~GDK_SHIFT_MASK;
  588.       else
  589.     state |= GDK_SHIFT_MASK;
  590.       break;
  591.  
  592.     case GDK_Control_L: case GDK_Control_R:
  593.       if (state & GDK_CONTROL_MASK)
  594.     state &= ~GDK_CONTROL_MASK;
  595.       else
  596.     state |= GDK_CONTROL_MASK;
  597.       break;
  598.     }
  599.  
  600.   rect_sel = (RectSelect *) tool->private;
  601.   selection_tool_update_op_state (rect_sel,
  602.                   rect_sel->current_x,
  603.                   rect_sel->current_y,
  604.                   state, gdisp_ptr);
  605. }
  606.  
  607. void
  608. rect_select_cursor_update (Tool           *tool,
  609.                GdkEventMotion *mevent,
  610.                gpointer        gdisp_ptr)
  611. {
  612.   RectSelect *rect_sel;
  613.   GDisplay   *gdisp;
  614.  
  615.   rect_sel = (RectSelect *) tool->private;
  616.   gdisp = (GDisplay *) gdisp_ptr;
  617.  
  618.   switch (rect_sel->op)
  619.     {
  620.     case SELECTION_ADD:
  621.       gdisplay_install_tool_cursor (gdisp, GIMP_MOUSE_CURSOR,
  622.                     tool->type,
  623.                     CURSOR_MODIFIER_PLUS,
  624.                     FALSE);
  625.       break;
  626.     case SELECTION_SUB:
  627.       gdisplay_install_tool_cursor (gdisp, GIMP_MOUSE_CURSOR,
  628.                     tool->type,
  629.                     CURSOR_MODIFIER_MINUS,
  630.                     FALSE);
  631.       break;
  632.     case SELECTION_INTERSECT: 
  633.       gdisplay_install_tool_cursor (gdisp, GIMP_MOUSE_CURSOR,
  634.                     tool->type,
  635.                     CURSOR_MODIFIER_INTERSECT,
  636.                     FALSE);
  637.       break;
  638.     case SELECTION_REPLACE:
  639.       gdisplay_install_tool_cursor (gdisp, GIMP_MOUSE_CURSOR,
  640.                     tool->type,
  641.                     CURSOR_MODIFIER_NONE,
  642.                     FALSE);
  643.       break;
  644.     case SELECTION_MOVE_MASK:
  645.       gdisplay_install_tool_cursor (gdisp, GIMP_MOUSE_CURSOR,
  646.                     tool->type,
  647.                     CURSOR_MODIFIER_MOVE,
  648.                     FALSE);
  649.       break;
  650.     case SELECTION_MOVE:
  651.       gdisplay_install_tool_cursor (gdisp, GIMP_MOUSE_CURSOR,
  652.                     MOVE,
  653.                     CURSOR_MODIFIER_NONE,
  654.                     FALSE);
  655.       break;
  656.     case SELECTION_ANCHOR:
  657.       gdisplay_install_tool_cursor (gdisp, GIMP_MOUSE_CURSOR,
  658.                     tool->type,
  659.                     CURSOR_MODIFIER_ANCHOR,
  660.                     FALSE);
  661.       break;
  662.     }
  663. }
  664.  
  665. void
  666. rect_select_control (Tool       *tool,
  667.              ToolAction  action,
  668.              gpointer    gdisp_ptr)
  669. {
  670.   RectSelect *rect_sel;
  671.  
  672.   rect_sel = (RectSelect *) tool->private;
  673.  
  674.   switch (action)
  675.     {
  676.     case PAUSE:
  677.       draw_core_pause (rect_sel->core, tool);
  678.       break;
  679.  
  680.     case RESUME:
  681.       draw_core_resume (rect_sel->core, tool);
  682.       break;
  683.  
  684.     case HALT:
  685.       draw_core_stop (rect_sel->core, tool);
  686.       break;
  687.  
  688.     default:
  689.       break;
  690.     }
  691. }
  692.  
  693. static void
  694. rect_select_options_reset (void)
  695. {
  696.   selection_options_reset (rect_options);
  697. }
  698.  
  699. Tool *
  700. tools_new_rect_select (void)
  701. {
  702.   Tool * tool;
  703.   RectSelect * private;
  704.  
  705.   /*  The tool options  */
  706.   if (! rect_options)
  707.     {
  708.       rect_options =
  709.     selection_options_new (RECT_SELECT, rect_select_options_reset);
  710.       tools_register (RECT_SELECT, (ToolOptions *) rect_options);
  711.     }
  712.  
  713.   tool = tools_new_tool (RECT_SELECT);
  714.   private = g_new0 (RectSelect, 1);
  715.  
  716.   private->core = draw_core_new (rect_select_draw);
  717.   private->x = private->y = 0;
  718.   private->w = private->h = 0;
  719.   private->op = SELECTION_REPLACE;
  720.  
  721.   tool->private = (void *) private;
  722.  
  723.   tool->button_press_func   = rect_select_button_press;
  724.   tool->button_release_func = rect_select_button_release;
  725.   tool->motion_func         = rect_select_motion;
  726.   tool->modifier_key_func   = rect_select_modifier_update;
  727.   tool->cursor_update_func  = rect_select_cursor_update;
  728.   tool->oper_update_func    = rect_select_oper_update;
  729.   tool->control_func        = rect_select_control;
  730.  
  731.   return tool;
  732. }
  733.  
  734. void
  735. tools_free_rect_select (Tool *tool)
  736. {
  737.   RectSelect * rect_sel;
  738.  
  739.   rect_sel = (RectSelect *) tool->private;
  740.  
  741.   draw_core_free (rect_sel->core);
  742.   g_free (rect_sel);
  743. }
  744.