Eine aufbereitete Darstellung der Quelle

 
     
 
 
Anforderungen  |   Konzepte  |   Entwurf  |   Entwicklung  |   Qualitätssicherung  |   Lebenszyklus  |   Steuerung
 
 
 
 

Benutzer

Quelle  gfig-dobject.c   Sprache: C

 

/*
 * Copyright (C) 1995 Spencer Kimball and Peter Mattis
 *
 * This is a plug-in for GIMP.
 *
 * Generates images containing vector type drawings.
 *
 * Copyright (C) 1997 Andy Thomas  alt@picnic.demon.co.uk
 *
 * 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 3 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, see <https://www.gnu.org/licenses/>.
 */


#include "config.h"

#include <stdlib.h>
#include <string.h>

#include <libgimp/gimp.h>
#include <libgimp/gimpui.h>

#include "gfig.h"
#include "gfig-dialog.h"
#include "gfig-style.h"
#include "gfig-arc.h"
#include "gfig-bezier.h"
#include "gfig-circle.h"
#include "gfig-dobject.h"
#include "gfig-ellipse.h"
#include "gfig-line.h"
#include "gfig-poly.h"
#include "gfig-rectangle.h"
#include "gfig-spiral.h"
#include "gfig-star.h"

#include "libgimp/stdplugins-intl.h"

static GfigObject *operation_obj = NULL;
static GdkPoint   *move_all_pnt; /* Point moving all from */


static void draw_one_obj         (GfigObject *obj,
                                  cairo_t    *cr);
static void do_move_obj          (GfigObject *obj,
                                  GdkPoint   *to_pnt);
static void do_move_all_obj      (GdkPoint   *to_pnt);
static void do_move_obj_pnt      (GfigObject *obj,
                                  GdkPoint   *to_pnt);
static void remove_obj_from_list (GFigObj    *obj,
                                  GfigObject *del_obj);
static gint scan_obj_points      (DobjPoints *opnt,
                                  GdkPoint   *pnt);

void
d_save_object (GfigObject *obj,
               GString    *string)
{
  do_save_obj (obj, string);

  switch (obj->type)
    {
    case BEZIER:
    case POLY:
    case SPIRAL:
    case STAR:
      g_string_append_printf (string, "<EXTRA>\n");
      g_string_append_printf (string, "%d\n</EXTRA>\n", obj->type_data);
      break;
    default:
      break;
    }
}

static DobjType
gfig_read_object_type (gchar *desc)
{
  gchar    *ptr = desc;
  DobjType  type;

  if (*ptr != '<')
    return OBJ_TYPE_NONE;

  ptr++;

  for (type = LINE; type < NUM_OBJ_TYPES; type++)
    {
      if (ptr == strstr (ptr, dobj_class[type].name))
        return type;
    }

  return OBJ_TYPE_NONE;
}

GfigObject *
d_load_object (gchar *desc,
               FILE  *fp)
{
  GfigObject *new_obj = NULL;
  gint        xpnt;
  gint        ypnt;
  gchar       buf[MAX_LOAD_LINE];
  DobjType    type;

  type = gfig_read_object_type (desc);
  if (type == OBJ_TYPE_NONE)
    {
      g_message ("Error loading object: type not recognized.");
      return NULL;
    }

  while (get_line (buf, MAX_LOAD_LINE, fp, 0))
    {
      if (sscanf (buf, "%d %d", &xpnt, &ypnt) != 2)
        {
          /* Read <EXTRA> block if there is one */
          if (!strcmp ("<EXTRA>", buf))
            {
              if ( !new_obj)
                {
                  g_message ("Error while loading object (no points)");
                  return NULL;
                }

              get_line (buf, MAX_LOAD_LINE, fp, 0);

              if (sscanf (buf, "%d", &new_obj->type_data) != 1)
                {
                  g_message ("Error while loading object (no type data)");
                  g_free (new_obj);
                  return NULL;
                }

              get_line (buf, MAX_LOAD_LINE, fp, 0);
              if (strcmp ("</EXTRA>", buf))
                {
                  g_message ("Syntax error while loading object");
                  g_free (new_obj);
                  return NULL;
                }
              /* Go around and read the last line */
              continue;
            }
          else
            return new_obj;
        }

      if (!new_obj)
        new_obj = d_new_object (type, xpnt, ypnt);
      else
        d_pnt_add_line (new_obj, xpnt, ypnt, -1);
    }

  return new_obj;
}

GfigObject *
d_new_object (DobjType    type,
              gint        x,
              gint        y)
{
  GfigObject *nobj = g_new0 (GfigObject, 1);

  nobj->type = type;
  nobj->class = &dobj_class[type];
  nobj->points = new_dobjpoint (x, y);

  nobj->type_data = 0;

  if (type == BEZIER)
    {
      nobj->type_data = 4;
    }
  else if (type == POLY)
    {
      nobj->type_data = 3;  /* default to 3 sides */
    }
  else if (type == SPIRAL)
    {
      nobj->type_data = 4;  /* default to 4 turns */
    }
  else if (type == STAR)
    {
      nobj->type_data = 3;  /* default to 3 sides 6 points */
    }

  return nobj;
}

void
gfig_init_object_classes (void)
{
  d_arc_object_class_init ();
  d_line_object_class_init ();
  d_rectangle_object_class_init ();
  d_circle_object_class_init ();
  d_ellipse_object_class_init ();
  d_poly_object_class_init ();
  d_spiral_object_class_init ();
  d_star_object_class_init ();
  d_bezier_object_class_init ();
}

/* Delete a list of points */
void
d_delete_dobjpoints (DobjPoints * pnts)
{
  DobjPoints *next;
  DobjPoints *pnt2del = pnts;

  while (pnt2del)
    {
      next = pnt2del->next;
      g_free (pnt2del);
      pnt2del = next;
    }
}

DobjPoints *
new_dobjpoint (gint x, gint y)
{
  DobjPoints *npnt = g_new0 (DobjPoints, 1);

  npnt->pnt.x = x;
  npnt->pnt.y = y;

  return npnt;
}

DobjPoints *
d_copy_dobjpoints (DobjPoints *pnts)
{
  DobjPoints *ret = NULL;
  DobjPoints *head = NULL;
  DobjPoints *newpnt;
  DobjPoints *pnt2copy;

  for (pnt2copy = pnts; pnt2copy; pnt2copy = pnt2copy->next)
    {
      newpnt = new_dobjpoint (pnt2copy->pnt.x, pnt2copy->pnt.y);

      if (!ret)
        {
          head = ret = newpnt;
        }
      else
        {
          head->next = newpnt;
          head = newpnt;
        }
    }

  return ret;
}

static DobjPoints *
get_diffs (GfigObject *obj,
           gint       *xdiff,
           gint       *ydiff,
           GdkPoint   *to_pnt)
{
  DobjPoints *spnt;

  g_assert (obj != NULL);

  for (spnt = obj->points; spnt; spnt = spnt->next)
    {
      if (spnt->found_me)
        {
          *xdiff = spnt->pnt.x - to_pnt->x;
          *ydiff = spnt->pnt.y - to_pnt->y;
          return spnt;
        }
    }
  return NULL;
}

static gboolean
inside_sqr (GdkPoint *cpnt,
            GdkPoint *testpnt)
{
  /* Return TRUE if testpnt is near cpnt */
  gint x  = cpnt->x;
  gint y  = cpnt->y;
  gint tx = testpnt->x;
  gint ty = testpnt->y;

  return (abs (x - tx) <= SQ_SIZE && abs (y - ty) < SQ_SIZE);
}

static gboolean
scan_obj_points (DobjPoints *opnt,
                 GdkPoint   *pnt)
{
  while (opnt)
    {
      if (inside_sqr (&opnt->pnt, pnt))
        {
          opnt->found_me = TRUE;
          return TRUE;
        }
      opnt->found_me = FALSE;
      opnt = opnt->next;
    }
  return FALSE;
}

static GfigObject *
get_nearest_objs (GFigObj  *obj,
                  GdkPoint *pnt)
{
  /* Nearest object to given point or NULL */
  GList      *all;
  GfigObject *test_obj;
  gint        count = 0;

  if (!obj)
    return NULL;

  for (all = obj->obj_list; all; all = g_list_next (all))
    {
      test_obj = all->data;

      if (count == obj_show_single || obj_show_single == -1)
        if (scan_obj_points (test_obj->points, pnt))
          {
            return test_obj;
          }
      count++;
    }
  return NULL;
}

void
object_operation_start (GimpGfig *gfig,
                        GdkPoint *pnt,
                        gboolean  shift_down)
{
  GfigObject *new_obj;

  /* Find point in given object list */
  operation_obj = get_nearest_objs (gfig_context->current_obj, pnt);

  /* Special case if shift down && move obj then moving all objs */

  if (shift_down && selvals.otype == MOVE_OBJ)
    {
      move_all_pnt = g_new (GdkPoint, 1);
      *move_all_pnt = *pnt; /* Structure copy */
      setup_undo (gfig);
      return;
    }

  if (!operation_obj)
    return;/* None to work on */

  gfig_context->selected_obj = operation_obj;

  setup_undo (gfig);

  switch (selvals.otype)
    {
    case MOVE_OBJ:
      if (operation_obj->type == BEZIER)
        {
          tmp_bezier = operation_obj;
        }
      break;

    case MOVE_POINT:
      if (operation_obj->type == BEZIER)
        {
          tmp_bezier = operation_obj;
        }
      /* If shift is down the break into sep lines */
      if ((operation_obj->type == POLY
          || operation_obj->type == STAR)
         && shift_down)
        {
          switch (operation_obj->type)
            {
            case POLY:
              d_poly2lines (operation_obj);
              break;
            case STAR:
              d_star2lines (operation_obj);
              break;
            default:
              break;
            }
          /* Re calc which object point we are looking at */
          scan_obj_points (operation_obj->points, pnt);
          gtk_widget_queue_draw (gfig_context->preview);
        }
      break;

    case COPY_OBJ:
      /* Copy the "operation object" */
      /* Then bung us into "copy/move" mode */

      new_obj = (GfigObject*) operation_obj->class->copyfunc (operation_obj);
      if (new_obj)
        {
          gfig_style_copy (&new_obj->style, &operation_obj->style, "Object");
          scan_obj_points (new_obj->points, pnt);
          add_to_all_obj (gfig, gfig_context->current_obj, new_obj);
          operation_obj = new_obj;
          selvals.otype = MOVE_COPY_OBJ;
          gtk_widget_queue_draw (gfig_context->preview);
        }
      break;

    case DEL_OBJ:
      remove_obj_from_list (gfig_context->current_obj, operation_obj);
      break;

    case SELECT_OBJ:
      /* don't need to do anything */
      break;

    case MOVE_COPY_OBJ: /* Never when button down */
    default:
      g_warning ("Internal error selvals.otype object operation start");
      break;
    }

}

void
object_operation_end (GdkPoint *pnt,
                      gboolean  shift_down)
{
  if (selvals.otype != DEL_OBJ && operation_obj &&
      operation_obj->type == BEZIER)
    {
      tmp_bezier = NULL; /* use as switch */
    }

  if (operation_obj && selvals.otype != DEL_OBJ)
    gfig_style_set_context_from_style (&operation_obj->style);

  operation_obj = NULL;

  if (move_all_pnt)
    {
      g_free (move_all_pnt);
      move_all_pnt = NULL;
    }

  /* Special case - if copying mode MUST be copy when button up received */
  if (selvals.otype == MOVE_COPY_OBJ)
    selvals.otype = COPY_OBJ;
}

/* Move object around */
void
object_operation (GdkPoint *to_pnt,
                  gboolean  shift_down)
{
  /* Must do different things depending on object type */
  /* but must have object to operate on! */

  /* Special case - if shift own and move_obj then move ALL objects */
  if (move_all_pnt && shift_down && selvals.otype == MOVE_OBJ)
    {
      do_move_all_obj (to_pnt);
      return;
    }

  if (!operation_obj)
    return;

  switch (selvals.otype)
    {
    case MOVE_OBJ:
    case MOVE_COPY_OBJ:
      switch (operation_obj->type)
        {
        case LINE:
        case RECTANGLE:
        case CIRCLE:
        case ELLIPSE:
        case POLY:
        case ARC:
        case STAR:
        case SPIRAL:
        case BEZIER:
          do_move_obj (operation_obj, to_pnt);
          break;
        default:
          /* Internal error */
          g_warning ("Internal error in operation_obj->type");
          break;
        }
      break;
    case MOVE_POINT:
      switch (operation_obj->type)
        {
        case LINE:
        case RECTANGLE:
        case CIRCLE:
        case ELLIPSE:
        case POLY:
        case ARC:
        case STAR:
        case SPIRAL:
        case BEZIER:
          do_move_obj_pnt (operation_obj, to_pnt);
          break;
        default:
          /* Internal error */
          g_warning ("Internal error in operation_obj->type");
          break;
        }
      break;
    case DEL_OBJ:
    case SELECT_OBJ:
      break;
    case COPY_OBJ: /* Should have been changed to MOVE_COPY_OBJ */
    default:
      g_warning ("Internal error selvals.otype");
      break;
    }
}

static void
update_pnts (GfigObject *obj,
             gint        xdiff,
             gint        ydiff)
{
  DobjPoints *spnt;

  g_assert (obj != NULL);

  /* Update all pnts */
  for (spnt = obj->points; spnt; spnt = spnt->next)
    {
      spnt->pnt.x -= xdiff;
      spnt->pnt.y -= ydiff;
    }
}

static void
remove_obj_from_list (GFigObj    *obj,
                      GfigObject *del_obj)
{
  /* Nearest object to given point or NULL */

  g_assert (del_obj != NULL);

  if (g_list_find (obj->obj_list, del_obj))
    {
      obj->obj_list = g_list_remove (obj->obj_list, del_obj);

      free_one_obj (del_obj);

      if (obj->obj_list)
        gfig_context->selected_obj = obj->obj_list->data;
      else
        gfig_context->selected_obj = NULL;

      if (obj_show_single != -1)
        {
          /* We've just deleted the only visible one */
          draw_grid_clear ();
          obj_show_single = -1; /* Show entry again */
        }

      gtk_widget_queue_draw (gfig_context->preview);
    }
  else
    g_warning (_("Hey, where has the object gone?"));
}

static void
do_move_all_obj (GdkPoint *to_pnt)
{
  /* Move all objects in one go */
  /* Undraw/then draw in new pos */
  gint xdiff = move_all_pnt->x - to_pnt->x;
  gint ydiff = move_all_pnt->y - to_pnt->y;

  if (xdiff || ydiff)
    {
      GList *all;

      for (all = gfig_context->current_obj->obj_list; all; all = all->next)
        {
          GfigObject *obj = all->data;

          update_pnts (obj, xdiff, ydiff);
        }

      *move_all_pnt = *to_pnt;

      gtk_widget_queue_draw (gfig_context->preview);
    }
}

void
do_save_obj (GfigObject *obj,
             GString    *string)
{
  DobjPoints *spnt;

  for (spnt = obj->points; spnt; spnt = spnt->next)
    {
      g_string_append_printf (string, "%d %d\n", spnt->pnt.x, spnt->pnt.y);
    }
}

static void
do_move_obj (GfigObject *obj,
             GdkPoint   *to_pnt)
{
  /* Move the whole line - undraw the line to start with */
  /* Then draw in new pos */
  gint xdiff = 0;
  gint ydiff = 0;

  get_diffs (obj, &xdiff, &ydiff, to_pnt);

  if (xdiff || ydiff)
    {
      update_pnts (obj, xdiff, ydiff);

      gtk_widget_queue_draw (gfig_context->preview);
    }
}

static void
do_move_obj_pnt (GfigObject *obj,
                 GdkPoint   *to_pnt)
{
  /* Move the whole line - undraw the line to start with */
  /* Then draw in new pos */
  DobjPoints *spnt;
  gint xdiff = 0;
  gint ydiff = 0;

  spnt = get_diffs (obj, &xdiff, &ydiff, to_pnt);

  if ((!xdiff && !ydiff) || !spnt)
    return;

  spnt->pnt.x = spnt->pnt.x - xdiff;
  spnt->pnt.y = spnt->pnt.y - ydiff;

  /* Draw in new pos */
  gtk_widget_queue_draw (gfig_context->preview);
}

/* copy objs */
GList *
copy_all_objs (GList *objs)
{
  GList *new_all_objs = NULL;

  while (objs)
    {
      GfigObject *object = objs->data;
      GfigObject *new_object = (GfigObject *) object->class->copyfunc (object);
      gfig_style_copy (&new_object->style, &object->style, "Object");

      new_all_objs = g_list_prepend (new_all_objs, new_object);

      objs = objs->next;
    }

  new_all_objs = g_list_reverse (new_all_objs);

  return new_all_objs;
}

/* Screen refresh */
static void
draw_one_obj (GfigObject *obj,
              cairo_t    *cr)
{
  obj->class->drawfunc (obj, cr);
}

void
draw_objects (GList    *objs,
              gboolean  show_single,
              cairo_t  *cr)
{
  /* Show_single - only one object to draw Unless shift
   * is down in which case show all.
   */


  gint count = 0;

  while (objs)
    {
      if (!show_single || count == obj_show_single || obj_show_single == -1)
        draw_one_obj (objs->data, cr);

      objs = g_list_next (objs);
      count++;
    }
}

void
prepend_to_all_obj (GimpGfig *gfig,
                    GFigObj  *fobj,
                    GList    *nobj)
{
  setup_undo (gfig); /* Remember ME */

  fobj->obj_list = g_list_concat (fobj->obj_list, nobj);
}

static void
scale_obj_points (DobjPoints *opnt,
                  gdouble     scale_x,
                  gdouble     scale_y)
{
  while (opnt)
    {
      opnt->pnt.x = (gint) (opnt->pnt.x * scale_x);
      opnt->pnt.y = (gint) (opnt->pnt.y * scale_y);
      opnt = opnt->next;
    }
}

void
add_to_all_obj (GimpGfig   *gfig,
                GFigObj    *fobj,
                GfigObject *obj)
{
  GList *nobj = NULL;

  nobj = g_list_append (nobj, obj);

  if (need_to_scale)
    scale_obj_points (obj->points, scale_x_factor, scale_y_factor);

  prepend_to_all_obj (gfig, fobj, nobj);

  /* initialize style when we add the object */
  gfig_context->selected_obj = obj;
}

/* First button press -- start drawing object */
/*
 * object_start() creates a new object of the type specified in the
 * button panel.  It is activated by a button press, and causes
 * a small square to be drawn at the initial point.  The style of
 * the new object is set to values taken from the style control
 * widgets.
 */

void
object_start (GdkPoint *pnt,
              gboolean  shift_down)
{
  /* start for the current object */
  if (!selvals.scaletoimage)
    {
      need_to_scale = 1;
      selvals.scaletoimage = 1;
    }
  else
    {
      need_to_scale = 0;
    }

  switch (selvals.otype)
    {
    case LINE:
      /* Shift means we are still drawing */
      d_line_start (pnt, shift_down);
      break;
    case RECTANGLE:
      d_rectangle_start (pnt, shift_down);
      break;
    case CIRCLE:
      d_circle_start (pnt, shift_down);
      break;
    case ELLIPSE:
      d_ellipse_start (pnt, shift_down);
      break;
    case POLY:
      d_poly_start (pnt, shift_down);
      break;
    case ARC:
      d_arc_start (pnt, shift_down);
      break;
    case STAR:
      d_star_start (pnt, shift_down);
      break;
    case SPIRAL:
      d_spiral_start (pnt, shift_down);
      break;
    case BEZIER:
      d_bezier_start (pnt, shift_down);
      break;
    default:
      /* Internal error */
      break;
    }

  if (obj_creating)
    {
      if (gfig_context->debug_styles)
        g_printerr ("Creating object, setting style from context\n");
      gfig_style_set_style_from_context (&obj_creating->style);
    }

}

void
object_end (GimpGfig *gfig,
            GdkPoint *pnt,
            gboolean  shift_down)
{
  /* end for the current object */
  /* Add onto global object list */

  /* If shift is down may carry on drawing */
  switch (selvals.otype)
    {
    case LINE:
      d_line_end (gfig, pnt, shift_down);
      break;
    case RECTANGLE:
      d_rectangle_end (gfig, pnt, shift_down);
      break;
    case CIRCLE:
      d_circle_end (gfig, pnt, shift_down);
      break;
    case ELLIPSE:
      d_ellipse_end (gfig, pnt, shift_down);
      break;
    case POLY:
      d_poly_end (gfig, pnt, shift_down);
      break;
    case STAR:
      d_star_end (gfig, pnt, shift_down);
      break;
    case ARC:
      d_arc_end (gfig, pnt, shift_down);
      break;
    case SPIRAL:
      d_spiral_end (gfig, pnt, shift_down);
      break;
    case BEZIER:
      d_bezier_end (gfig, pnt, shift_down);
      break;
    default:
      /* Internal error */
      break;
    }

  if (need_to_scale)
    {
      need_to_scale = 0;
      selvals.scaletoimage = 0;
    }
}

/* Stuff for the generation/deletion of objects. */

/* Objects are easy one they are created - you just go down the object
 * list calling the draw function for each object but... when they
 * are been created we have to be a little more careful. When
 * the first point is placed on the canvas we create the object,
 * the mouse position then defines the next point that can move around.
 * careful how we draw this position.
 */


void
free_one_obj (GfigObject *obj)
{
  d_delete_dobjpoints (obj->points);
  g_free (obj);
}

void
free_all_objs (GList *objs)
{
  g_list_free_full (objs, (GDestroyNotify) free_one_obj);
}

gchar *
get_line (gchar *buf,
          gint   s,
          FILE  *from,
          gint   init)
{
  gint slen;
  char *ret;

  if (init)
    line_no = 1;
  else
    line_no++;

  do
    {
      ret = fgets (buf, s, from);
    }
  while (!ferror (from) && buf[0] == '#');

  slen = strlen (buf);

  /* The last newline is a pain */
  if (slen > 0)
    buf[slen - 1] = '\0';

  /* Check and remove an '\r' too from Windows */
  if ((slen > 1) && (buf[slen - 2] == '\r'))
    buf[slen - 2] = '\0';

  if (ferror (from))
    {
      g_warning (_("Error reading file"));
      return NULL;
    }

#ifdef DEBUG
  printf ("Processing line '%s'\n", buf);
#endif /* DEBUG */

  return ret;
}

void
clear_undo (GimpGfig *gfig)
{
  int      lv;
  GAction *action;

  for (lv = undo_level; lv >= 0; lv--)
    {
      free_all_objs (undo_table[lv]);
      undo_table[lv] = NULL;
    }

  undo_level = -1;

  action = g_action_map_lookup_action (G_ACTION_MAP (gfig->app), "undo");
  g_simple_action_set_enabled (G_SIMPLE_ACTION (action),
                               FALSE);
}

void
setup_undo (GimpGfig *gfig)
{
  GAction *action;

  /* Copy object list to undo buffer */
#if DEBUG
  printf ("setup undo level [%d]\n", undo_level);
#endif /*DEBUG*/

  if (!gfig_context->current_obj)
    {
      /* If no current_obj must be loading -> no undo */
      return;
    }

  if (undo_level >= selvals.maxundo - 1)
    {
      int loop;
      /* the little one in the bed said "roll over".. */
      if (undo_table[0])
        free_one_obj (undo_table[0]->data);
      for (loop = 0; loop < undo_level; loop++)
        {
          undo_table[loop] = undo_table[loop + 1];
        }
    }
  else
    {
      undo_level++;
    }
  undo_table[undo_level] =
    copy_all_objs (gfig_context->current_obj->obj_list);

  action = g_action_map_lookup_action (G_ACTION_MAP (gfig->app), "undo");
  g_simple_action_set_enabled (G_SIMPLE_ACTION (action), TRUE);

  gfig_context->current_obj->obj_status |= GFIG_MODIFIED;
}

void
new_obj_2edit (GimpGfig *gfig,
               GFigObj  *obj)
{
  GAction *action;
  GFigObj *old_current = gfig_context->current_obj;

  /* Clear undo levels */
  /* redraw the preview */
  /* Set up options as define in the selected object */

  clear_undo (gfig);

  /* Point at this one */
  gfig_context->current_obj = obj;

  /* Show all objects to start with */
  obj_show_single = -1;

  /* Change options */
  options_update (old_current);

  /* redraw with new */
  gtk_widget_queue_draw (gfig_context->preview);

  action = g_action_map_lookup_action (G_ACTION_MAP (gfig->app), "save");
  if (obj->obj_status & GFIG_READONLY)
    {
      g_message (_("Editing read-only object - "
                   "you will not be able to save it"));

      g_simple_action_set_enabled (G_SIMPLE_ACTION (action),
                                   FALSE);
    }
  else
    {
      g_simple_action_set_enabled (G_SIMPLE_ACTION (action),
                                   FALSE);
    }
}

/* Add a point to a line (given x, y)
 * pos = 0 = head
 * pos = -1 = tail
 * 0 < pos = nth position
 */


void
d_pnt_add_line (GfigObject *obj,
                gint        x,
                gint        y,
                gint        pos)
{
  DobjPoints *npnts = new_dobjpoint (x, y);

  g_assert (obj != NULL);

  if (!pos)
    {
      /* Add to head */
      npnts->next = obj->points;
      obj->points = npnts;
    }
  else
    {
      DobjPoints *pnt = obj->points;

      /* Go down chain until the end if pos */
      while (pos < 0 || pos-- > 0)
        {
          if (!(pnt->next) || !pos)
            {
              npnts->next = pnt->next;
              pnt->next = npnts;
              break;
            }
          else
            {
              pnt = pnt->next;
            }
        }
    }
}

Messung
CHZG
839610093

¤ Dauer der Verarbeitung: 0.6 Sekunden  (vorverarbeitet am  2026-11-04) ¤

*© Formatika GbR, Deutschland






Wurzel

Suchen

PVS Prover

Isabelle Prover


Cephes Mathematical Library

Vienna Development Method

Haftungshinweis

Die Informationen auf dieser Webseite wurden nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit, noch Qualität der bereit gestellten Informationen zugesichert.

Bemerkung:

Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.






                                                                                                                                                                                                                                                                                                                                                                                                     


Neuigkeiten

     Aktuelles
     Motto des Tages

Open Source Software

     Quellcodebibliothek
     Eigene Quellcodes
     Fremde Quellcodes
     Suchen

Jenseits des Üblichen ....
    

Besucherstatistik

Besucherstatistik

Statistik
#Sources=1104851
#Domains=417129