Gimp/app/display/gimpdisplayshell-selection.c
Sven Neumann 073e533a8a Finally landed the new GimpConfig based gimprc parser. It's not finished
2002-11-18  Sven Neumann  <sven@gimp.org>

	Finally landed the new GimpConfig based gimprc parser. It's not
	finished yet but we need to start somewhere. This release removes
	the old gimprc.[ch] files. The gimprc format changes slightly, but
	the changes are minimal. The Preferences dialog is temporarily
	disabled since it still needs to be ported. If you are are afraid,
	stay away from CVS for a few days ;-)

	* app/Makefile.am
	* app/gimprc.[ch]: removed the old gimprc system.

	* app/base/Makefile.am
	* app/base/base-config.[ch]: removed these files in favor of
	config/gimpbaseconfig.[ch].

	* app/core/Makefile.am
	* app/core/gimpcoreconfig.[ch]: removed these files in favor of
	config/gimpcoreconfig.[ch].

	* app/config/Makefile.am
	* app/config/config-types.h: moved typedefs into this new file.

	* app/config/gimpbaseconfig.[ch]
	* app/config/gimpcoreconfig.[ch]
	* app/config/gimpdisplayconfig.[ch]
	* app/config/gimpguiconfig.[ch]
	* app/config/gimprc.[ch]
	* app/config/test-config.c: brought into shape for real use.

	* app/base/base-types.h: include config/config-types.h here. Added
	a global GimpBaseConfig *base_config variable to ease migration.

	* app/gui/Makefile.am: temporarily disabled the preferences dialog.

	* app/app_procs.c
	* app/undo.c
	* app/undo_history.c
	* app/base/base.[ch]
	* app/base/gimphistogram.c
	* app/base/pixel-processor.c
	* app/base/temp-buf.c
	* app/base/tile-cache.c
	* app/core/core-types.h
	* app/core/gimp-documents.c
	* app/core/gimp.c
	* app/core/gimpbrush.c
	* app/core/gimpbrushgenerated.c
	* app/core/gimpcontext.c
	* app/core/gimpdrawable-transform.c
	* app/core/gimpimage-new.c
	* app/core/gimpimage.c
	* app/core/gimpimagefile.c
	* app/core/gimpmodules.c
	* app/core/gimppattern.c
	* app/display/Makefile.am
	* app/display/gimpdisplay-handlers.c
	* app/display/gimpdisplay.[ch]
	* app/display/gimpdisplayshell-callbacks.c
	* app/display/gimpdisplayshell-handlers.c
	* app/display/gimpdisplayshell-layer-select.c
	* app/display/gimpdisplayshell-render.c
	* app/display/gimpdisplayshell-scale.c
	* app/display/gimpdisplayshell-scroll.c
	* app/display/gimpdisplayshell-selection.c
	* app/display/gimpdisplayshell.[ch]
	* app/display/gimpnavigationview.c
	* app/file/file-save.c
	* app/gui/device-status-dialog.c
	* app/gui/dialogs-constructors.c
	* app/gui/file-commands.c
	* app/gui/file-new-dialog.c
	* app/gui/file-open-dialog.c
	* app/gui/file-save-dialog.c
	* app/gui/gui.c
	* app/gui/menus.c
	* app/gui/paths-dialog.c
	* app/gui/resize-dialog.c
	* app/gui/session.c
	* app/gui/test-commands.c
	* app/gui/tips-dialog.c
	* app/gui/tips-dialog.h
	* app/gui/user-install-dialog.c
	* app/gui/view-commands.c
	* app/paint/gimppaintcore.c
	* app/plug-in/plug-in.c
	* app/plug-in/plug-ins.c
	* app/tools/gimpbezierselecttool.c
	* app/tools/gimpbucketfilltool.c
	* app/tools/gimpcolorpickertool.c
	* app/tools/gimpcroptool.c
	* app/tools/gimpeditselectiontool.c
	* app/tools/gimpfuzzyselecttool.c
	* app/tools/gimpinktool.c
	* app/tools/gimpmagnifytool.c
	* app/tools/gimpmeasuretool.c
	* app/tools/gimppainttool.c
	* app/tools/gimppathtool.c
	* app/tools/gimptexttool.[ch]
	* app/tools/selection_options.c
	* app/tools/tools.c
	* app/tools/transform_options.c
	* app/widgets/gimphelp.c
	* app/widgets/gimpitemfactory.c
	* app/widgets/gimpselectioneditor.c
	* app/xcf/xcf-load.c
	* tools/pdbgen/pdb/fileops.pdb
	* tools/pdbgen/pdb/gimprc.pdb
	* tools/pdbgen/pdb/image.pdb
	* tools/pdbgen/pdb/layer.pdb
	* tools/pdbgen/pdb/transform_tools.pdb: use the new config system
	instead of the old gimprc stuff.

	* etc/gimprc.in
	* etc/gimprc_user.in: adapted to the new gimprc format. Will update
	the man-page later...

	* app/pdb/fileops_cmds.c
	* app/pdb/gimprc_cmds.c
	* app/pdb/image_cmds.c
	* app/pdb/layer_cmds.c
	* app/pdb/transform_tools_cmds.c
	* libgimp/gimpgimprc_pdb.c: regenerated.
2002-11-18 20:50:31 +00:00

839 lines
20 KiB
C

/* The GIMP -- an image manipulation program
* Copyright (C) 1995 Spencer Kimball and Peter Mattis
*
* 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 <gtk/gtk.h>
#include "display-types.h"
#include "config/gimpdisplayconfig.h"
#include "base/boundary.h"
#include "core/gimp.h"
#include "core/gimpimage.h"
#include "core/gimpimage-mask.h"
#include "gimpdisplay.h"
#include "gimpdisplayshell.h"
#include "gimpdisplayshell-marching-ants.h"
#include "gimpdisplayshell-selection.h"
#undef VERBOSE
/* The possible internal drawing states... */
#define INVISIBLE 0
#define INTRO 1
#define MARCHING 2
#define INITIAL_DELAY 15 /* in milleseconds */
/* local function prototypes */
static GdkPixmap * create_cycled_ants_pixmap (GdkWindow *window,
gint depth);
static void cycle_ant_colors (Selection *select);
static void selection_add_point (GdkPoint *points[8],
gint max_npoints[8],
gint npoints[8],
gint x,
gint y);
static void selection_render_points (Selection *select);
static void selection_draw (Selection *select);
static void selection_transform_segs (Selection *select,
BoundSeg *src_segs,
GdkSegment *dest_segs,
gint num_segs);
static void selection_generate_segs (Selection *select);
static void selection_free_segs (Selection *select);
static gboolean selection_start_marching (gpointer data);
static gboolean selection_march_ants (gpointer data);
static GdkColor marching_ants_colors[8];
static GdkPixmap * marching_ants[9] = { NULL };
static GdkPixmap * cycled_ants_pixmap = NULL;
/* public functions */
Selection *
gimp_display_shell_selection_create (GdkWindow *win,
GimpDisplayShell *shell,
gint size,
gint width,
gint speed)
{
GdkColor fg, bg;
Selection *new;
gint base_type;
gint i;
g_return_val_if_fail (GIMP_IS_DISPLAY_SHELL (shell), NULL);
new = g_new (Selection, 1);
base_type = gimp_image_base_type (shell->gdisp->gimage);
if (GIMP_DISPLAY_CONFIG (shell->gdisp->gimage->gimp->config)->colormap_cycling)
{
new->cycle = TRUE;
if (! cycled_ants_pixmap)
{
GdkVisual *visual;
visual = gdk_rgb_get_visual ();
cycled_ants_pixmap = create_cycled_ants_pixmap (win, visual->depth);
}
new->cycle_pix = cycled_ants_pixmap;
}
else
{
new->cycle = FALSE;
if (! marching_ants[0])
for (i = 0; i < 8; i++)
marching_ants[i] = gdk_bitmap_create_from_data (win,
(gchar *) ant_data[i],
8, 8);
}
new->win = win;
new->shell = shell;
new->segs_in = NULL;
new->segs_out = NULL;
new->segs_layer = NULL;
new->num_segs_in = 0;
new->num_segs_out = 0;
new->num_segs_layer = 0;
new->index_in = 0;
new->index_out = 0;
new->index_layer = 0;
new->state = INVISIBLE;
new->paused = 0;
new->recalc = TRUE;
new->speed = speed;
new->hidden = FALSE;
new->layer_hidden = FALSE;
for (i = 0; i < 8; i++)
new->points_in[i] = NULL;
/* create a new graphics context */
new->gc_in = gdk_gc_new (new->win);
if (new->cycle)
{
gdk_gc_set_fill (new->gc_in, GDK_TILED);
gdk_gc_set_tile (new->gc_in, new->cycle_pix);
gdk_gc_set_line_attributes (new->gc_in, 1,
GDK_LINE_SOLID, GDK_CAP_BUTT, GDK_JOIN_MITER);
}
else
{
/* get black and white pixels for this gdisplay */
fg.red = 0x0;
fg.green = 0x0;
fg.blue = 0x0;
bg.red = 0xffff;
bg.green = 0xffff;
bg.blue = 0xffff;
gdk_gc_set_rgb_fg_color (new->gc_in, &fg);
gdk_gc_set_rgb_bg_color (new->gc_in, &bg);
gdk_gc_set_fill (new->gc_in, GDK_OPAQUE_STIPPLED);
gdk_gc_set_line_attributes (new->gc_in, 1,
GDK_LINE_SOLID, GDK_CAP_BUTT, GDK_JOIN_MITER);
}
new->gc_white = gdk_gc_new (new->win);
gdk_gc_set_rgb_fg_color (new->gc_white, &bg);
new->gc_black = gdk_gc_new (new->win);
gdk_gc_set_rgb_fg_color (new->gc_black, &fg);
/* Setup 2nd & 3rd GCs */
fg.red = 0xffff;
fg.green = 0xffff;
fg.blue = 0xffff;
bg.red = 0x7f7f;
bg.green = 0x7f7f;
bg.blue = 0x7f7f;
/* create a new graphics context */
new->gc_out = gdk_gc_new (new->win);
gdk_gc_set_rgb_fg_color (new->gc_out, &fg);
gdk_gc_set_rgb_bg_color (new->gc_out, &bg);
gdk_gc_set_fill (new->gc_out, GDK_OPAQUE_STIPPLED);
gdk_gc_set_line_attributes (new->gc_out, 1,
GDK_LINE_SOLID, GDK_CAP_BUTT, GDK_JOIN_MITER);
/* get black and color pixels for this gdisplay */
fg.red = 0x0;
fg.green = 0x0;
fg.blue = 0x0;
bg.red = 0xffff;
bg.green = 0xffff;
bg.blue = 0x0;
/* create a new graphics context */
new->gc_layer = gdk_gc_new (new->win);
gdk_gc_set_rgb_fg_color (new->gc_layer, &fg);
gdk_gc_set_rgb_bg_color (new->gc_layer, &bg);
gdk_gc_set_fill (new->gc_layer, GDK_OPAQUE_STIPPLED);
gdk_gc_set_line_attributes (new->gc_layer, 1,
GDK_LINE_SOLID, GDK_CAP_BUTT, GDK_JOIN_MITER);
return new;
}
void
gimp_display_shell_selection_free (Selection *select)
{
if (select->state != INVISIBLE)
g_source_remove (select->timeout_id);
if (select->gc_in)
g_object_unref (select->gc_in);
if (select->gc_out)
g_object_unref (select->gc_out);
if (select->gc_layer)
g_object_unref (select->gc_layer);
if (select->gc_white)
g_object_unref (select->gc_white);
if (select->gc_black)
g_object_unref (select->gc_black);
selection_free_segs (select);
g_free (select);
}
void
gimp_display_shell_selection_pause (Selection *select)
{
if (select->state != INVISIBLE)
{
g_source_remove (select->timeout_id);
select->timeout_id = 0;
select->state = INVISIBLE;
}
select->paused ++;
}
void
gimp_display_shell_selection_resume (Selection *select)
{
if (select->paused == 1)
{
select->state = INTRO;
select->timeout_id = g_timeout_add (INITIAL_DELAY,
selection_start_marching,
select);
}
select->paused--;
}
void
gimp_display_shell_selection_start (Selection *select,
gboolean recalc)
{
/* A call to selection_start with recalc == TRUE means that
* we want to recalculate the selection boundary--usually
* after scaling or panning the display, or modifying the
* selection in some way. If recalc == FALSE, the already
* calculated boundary is simply redrawn.
*/
if (recalc)
select->recalc = TRUE;
/* If this selection is paused, do not start it */
if (select->paused > 0)
return;
if (select->state != INVISIBLE)
g_source_remove (select->timeout_id);
select->state = INTRO; /* The state before the first draw */
select->timeout_id = g_timeout_add (INITIAL_DELAY,
selection_start_marching,
select);
}
void
gimp_display_shell_selection_invis (Selection *select)
{
gint x1, y1, x2, y2;
if (select->state != INVISIBLE)
{
g_source_remove (select->timeout_id);
select->timeout_id = 0;
select->state = INVISIBLE;
}
/* Find the bounds of the selection */
if (gimp_display_shell_mask_bounds (select->shell, &x1, &y1, &x2, &y2))
{
gimp_display_shell_add_expose_area (select->shell,
x1, y1,
(x2 - x1), (y2 - y1));
}
else
{
gimp_display_shell_selection_start (select, TRUE);
}
}
void
gimp_display_shell_selection_layer_invis (Selection *select)
{
gint x1, y1;
gint x2, y2;
gint x3, y3;
gint x4, y4;
if (select->state != INVISIBLE)
{
g_source_remove (select->timeout_id);
select->timeout_id = 0;
select->state = INVISIBLE;
}
if (select->segs_layer != NULL && select->num_segs_layer == 4)
{
x1 = select->segs_layer[0].x1 - 1;
y1 = select->segs_layer[0].y1 - 1;
x2 = select->segs_layer[3].x2 + 1;
y2 = select->segs_layer[3].y2 + 1;
x3 = select->segs_layer[0].x1 + 1;
y3 = select->segs_layer[0].y1 + 1;
x4 = select->segs_layer[3].x2 - 1;
y4 = select->segs_layer[3].y2 - 1;
/* expose the region */
gimp_display_shell_add_expose_area (select->shell,
x1, y1,
(x2 - x1) + 1, (y3 - y1) + 1);
gimp_display_shell_add_expose_area (select->shell,
x1, y3,
(x3 - x1) + 1, (y4 - y3) + 1);
gimp_display_shell_add_expose_area (select->shell,
x1, y4,
(x2 - x1) + 1, (y2 - y4) + 1);
gimp_display_shell_add_expose_area (select->shell,
x4, y3,
(x2 - x4) + 1, (y4 - y3) + 1);
}
}
void
gimp_display_shell_selection_toggle (Selection *select)
{
gimp_display_shell_selection_invis (select);
gimp_display_shell_selection_layer_invis (select);
/* toggle the visibility */
select->hidden = select->hidden ? FALSE : TRUE;
gimp_display_shell_selection_start (select, TRUE);
}
void
gimp_display_shell_selection_toggle_layer (Selection *select)
{
gimp_display_shell_selection_invis (select);
gimp_display_shell_selection_layer_invis (select);
/* toggle the visibility */
select->layer_hidden = select->layer_hidden ? FALSE : TRUE;
gimp_display_shell_selection_start (select, TRUE);
}
/* private functions */
static GdkPixmap *
create_cycled_ants_pixmap (GdkWindow *window,
gint depth)
{
GdkPixmap *pixmap;
GdkGC *gc;
gint i, j;
pixmap = gdk_pixmap_new (window, 8, 8, depth);
gc = gdk_gc_new (window);
for (i = 0; i < 8; i++)
for (j = 0; j < 8; j++)
{
gdk_gc_set_rgb_fg_color (gc, &marching_ants_colors[((i + j) % 8)]);
gdk_draw_line (pixmap, gc, i, j, i, j);
}
g_object_unref (gc);
return pixmap;
}
static void
cycle_ant_colors (Selection *select)
{
gint i;
gint index;
for (i = 0; i < 8; i++)
{
index = (i + (8 - select->index_in)) % 8;
if (index < 4)
{
marching_ants_colors[i].red = 0x0;
marching_ants_colors[i].green = 0x0;
marching_ants_colors[i].blue = 0x0;
}
else
{
marching_ants_colors[i].red = 0xffff;
marching_ants_colors[i].green = 0xffff;
marching_ants_colors[i].blue = 0xffff;
}
}
}
#define MAX_POINTS_INC 2048
static void
selection_add_point (GdkPoint *points[8],
gint max_npoints[8],
gint npoints[8],
gint x,
gint y)
{
gint i, j;
j = (x - y) & 7;
i = npoints[j]++;
if (i == max_npoints[j])
{
max_npoints[j] += 2048;
points[j] = g_realloc (points[j], sizeof (GdkPoint) * max_npoints[j]);
}
points[j][i].x = x;
points[j][i].y = y;
}
/* Render the segs_in array into points_in */
static void
selection_render_points (Selection *select)
{
gint i, j;
gint max_npoints[8];
gint x, y;
gint dx, dy;
gint dxa, dya;
gint r;
if (select->segs_in == NULL)
return;
for (j = 0; j < 8; j++)
{
max_npoints[j] = MAX_POINTS_INC;
select->points_in[j] = g_new (GdkPoint, max_npoints[j]);
select->num_points_in[j] = 0;
}
for (i = 0; i < select->num_segs_in; i++)
{
#ifdef VERBOSE
g_print ("%2d: (%d, %d) - (%d, %d)\n", i,
select->segs_in[i].x1,
select->segs_in[i].y1,
select->segs_in[i].x2,
select->segs_in[i].y2);
#endif
x = select->segs_in[i].x1;
dxa = select->segs_in[i].x2 - x;
if (dxa > 0)
{
dx = 1;
}
else
{
dxa = -dxa;
dx = -1;
}
y = select->segs_in[i].y1;
dya = select->segs_in[i].y2 - y;
if (dya > 0)
{
dy = 1;
}
else
{
dya = -dya;
dy = -1;
}
if (dxa > dya)
{
r = dya;
do {
selection_add_point (select->points_in,
max_npoints,
select->num_points_in,
x, y);
x += dx;
r += dya;
if (r >= (dxa << 1)) {
y += dy;
r -= (dxa << 1);
}
} while (x != select->segs_in[i].x2);
}
else if (dxa < dya)
{
r = dxa;
do {
selection_add_point (select->points_in,
max_npoints,
select->num_points_in,
x, y);
y += dy;
r += dxa;
if (r >= (dya << 1)) {
x += dx;
r -= (dya << 1);
}
} while (y != select->segs_in[i].y2);
}
else
selection_add_point (select->points_in,
max_npoints,
select->num_points_in,
x, y);
}
}
static void
selection_draw (Selection *select)
{
if (! select->layer_hidden)
{
if (select->segs_layer && select->index_layer == 0)
gdk_draw_segments (select->win, select->gc_layer,
select->segs_layer, select->num_segs_layer);
}
if (select->hidden)
return;
#ifdef VERBOSE
{
gint j, sum;
sum = 0;
for (j = 0; j < 8; j++)
sum += select->num_points_in[j];
g_print ("%d segments, %d points\n", select->num_segs_in, sum);
}
#endif
if (select->segs_in)
{
gint i;
if (select->index_in == 0)
{
for (i = 0; i < 4; i++)
if (select->num_points_in[i])
gdk_draw_points (select->win, select->gc_white,
select->points_in[i], select->num_points_in[i]);
for (i = 4; i < 8; i++)
if (select->num_points_in[i])
gdk_draw_points (select->win, select->gc_black,
select->points_in[i], select->num_points_in[i]);
}
else
{
i = ((select->index_in + 3) & 7);
if (select->num_points_in[i])
gdk_draw_points (select->win, select->gc_white,
select->points_in[i], select->num_points_in[i]);
i = ((select->index_in + 7) & 7);
if (select->num_points_in[i])
gdk_draw_points (select->win, select->gc_black,
select->points_in[i], select->num_points_in[i]);
}
}
if (select->segs_out && select->index_out == 0)
{
gdk_draw_segments (select->win, select->gc_out,
select->segs_out, select->num_segs_out);
}
}
static void
selection_transform_segs (Selection *select,
BoundSeg *src_segs,
GdkSegment *dest_segs,
gint num_segs)
{
gint x, y;
gint i;
for (i = 0; i < num_segs; i++)
{
gimp_display_shell_transform_xy (select->shell,
src_segs[i].x1, src_segs[i].y1,
&x, &y,
FALSE);
dest_segs[i].x1 = x;
dest_segs[i].y1 = y;
gimp_display_shell_transform_xy (select->shell,
src_segs[i].x2, src_segs[i].y2,
&x, &y,
FALSE);
dest_segs[i].x2 = x;
dest_segs[i].y2 = y;
/* If this segment is a closing segment && the segments lie inside
* the region, OR if this is an opening segment and the segments
* lie outside the region...
* we need to transform it by one display pixel
*/
if (!src_segs[i].open)
{
/* If it is vertical */
if (dest_segs[i].x1 == dest_segs[i].x2)
{
dest_segs[i].x1 -= 1;
dest_segs[i].x2 -= 1;
}
else
{
dest_segs[i].y1 -= 1;
dest_segs[i].y2 -= 1;
}
}
}
}
static void
selection_generate_segs (Selection *select)
{
BoundSeg *segs_in;
BoundSeg *segs_out;
BoundSeg *segs_layer;
/* Ask the gimage for the boundary of its selected region...
* Then transform that information into a new buffer of XSegments
*/
gimp_image_mask_boundary (select->shell->gdisp->gimage,
&segs_in, &segs_out,
&select->num_segs_in, &select->num_segs_out);
if (select->num_segs_in)
{
select->segs_in = g_new (GdkSegment, select->num_segs_in);
selection_transform_segs (select, segs_in, select->segs_in,
select->num_segs_in);
selection_render_points (select);
}
else
{
select->segs_in = NULL;
}
/* Possible secondary boundary representation */
if (select->num_segs_out)
{
select->segs_out = g_new (GdkSegment, select->num_segs_out);
selection_transform_segs (select, segs_out, select->segs_out,
select->num_segs_out);
}
else
{
select->segs_out = NULL;
}
/* The active layer's boundary */
gimp_image_layer_boundary (select->shell->gdisp->gimage,
&segs_layer,
&select->num_segs_layer);
if (select->num_segs_layer)
{
select->segs_layer = g_new (GdkSegment, select->num_segs_layer);
selection_transform_segs (select, segs_layer, select->segs_layer,
select->num_segs_layer);
}
else
{
select->segs_layer = NULL;
}
g_free (segs_layer);
}
static void
selection_free_segs (Selection *select)
{
gint j;
if (select->segs_in)
g_free (select->segs_in);
if (select->segs_out)
g_free (select->segs_out);
if (select->segs_layer)
g_free (select->segs_layer);
for (j = 0; j < 8; j++)
{
if (select->points_in[j])
g_free (select->points_in[j]);
select->points_in[j] = NULL;
select->num_points_in[j] = 0;
}
select->segs_in = NULL;
select->num_segs_in = 0;
select->segs_out = NULL;
select->num_segs_out = 0;
select->segs_layer = NULL;
select->num_segs_layer = 0;
}
static gboolean
selection_start_marching (gpointer data)
{
Selection *select;
select = (Selection *) data;
/* if the RECALC bit is set, reprocess the boundaries */
if (select->recalc)
{
selection_free_segs (select);
selection_generate_segs (select);
/* Toggle the RECALC flag */
select->recalc = FALSE;
}
select->index_in = 0;
select->index_out = 0;
select->index_layer = 0;
/* Make sure the state is set to marching */
select->state = MARCHING;
/* Draw the ants */
if (select->cycle)
{
cycle_ant_colors (select);
}
else
{
gdk_gc_set_stipple (select->gc_in, marching_ants[select->index_in]);
gdk_gc_set_stipple (select->gc_out, marching_ants[select->index_out]);
gdk_gc_set_stipple (select->gc_layer, marching_ants[select->index_layer]);
}
selection_draw (select);
/* Reset the timer */
select->timeout_id = g_timeout_add (select->speed,
selection_march_ants,
select);
return FALSE;
}
static gboolean
selection_march_ants (gpointer data)
{
Selection *select;
select = (Selection *) data;
/* increment stipple index */
select->index_in++;
if (select->index_in > 7)
select->index_in = 0;
/* outside segments do not march, so index does not cycle */
select->index_out++;
/* layer doesn't march */
select->index_layer++;
/* Draw the ants */
if (select->cycle)
{
cycle_ant_colors (select);
}
else
{
gdk_gc_set_stipple (select->gc_in, marching_ants[select->index_in]);
selection_draw (select);
}
return TRUE;
}