gfig.c 20.4 KB
Newer Older
Manish Singh's avatar
Manish Singh committed
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21
/*
 * Copyright (C) 1995 Spencer Kimball and Peter Mattis
 *
 * This is a plug-in for the 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 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
22
 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
Manish Singh's avatar
Manish Singh committed
23 24
 */

Tor Lillqvist's avatar
Tor Lillqvist committed
25 26
#include "config.h"

Manish Singh's avatar
Manish Singh committed
27 28
#include <stdio.h>
#include <stdlib.h>
29
#include <errno.h>
30

Tor Lillqvist's avatar
Tor Lillqvist committed
31
#ifdef HAVE_UNISTD_H
Manish Singh's avatar
Manish Singh committed
32
#include <unistd.h>
Tor Lillqvist's avatar
Tor Lillqvist committed
33
#endif
34

Manish Singh's avatar
Manish Singh committed
35
#include <string.h>
36 37 38 39 40 41

#ifdef __GNUC__
#warning GTK_DISABLE_DEPRECATED
#endif
#undef GTK_DISABLE_DEPRECATED

Manish Singh's avatar
Manish Singh committed
42
#include <gtk/gtk.h>
Tor Lillqvist's avatar
Tor Lillqvist committed
43

44
#ifdef G_OS_WIN32
Tor Lillqvist's avatar
Tor Lillqvist committed
45 46 47 48
#  include <io.h>
#  ifndef W_OK
#    define W_OK 2
#  endif
49 50
#endif

51 52
#include <libgimp/gimp.h>
#include <libgimp/gimpui.h>
53 54
#include <gdk-pixbuf/gdk-pixbuf.h>
#include <gdk-pixbuf/gdk-pixdata.h>
55 56
#include "libgimp/stdplugins-intl.h"

57
#include "gfig.h"
58 59
#include "gfig-style.h"
#include "gfig-dialog.h"
60 61 62 63 64
#include "gfig-arc.h"
#include "gfig-bezier.h"
#include "gfig-circle.h"
#include "gfig-dobject.h"
#include "gfig-ellipse.h"
65
#include "gfig-grid.h"
66 67
#include "gfig-line.h"
#include "gfig-poly.h"
68
#include "gfig-preview.h"
69 70
#include "gfig-spiral.h"
#include "gfig-star.h"
71 72
#include "gfig-stock.h"

73
#include "pix-data.h"
Manish Singh's avatar
Manish Singh committed
74

75

Manish Singh's avatar
Manish Singh committed
76 77
/***** Magic numbers *****/

78 79
#define GFIG_HEADER      "GFIG Version 0.2\n"

Manish Singh's avatar
Manish Singh committed
80 81

static void      query  (void);
82
static void      run    (const gchar      *name,
83 84 85 86
                         gint              nparams,
                         const GimpParam  *param,
                         gint             *nreturn_vals,
                         GimpParam       **return_vals);
87

88

Manish Singh's avatar
Manish Singh committed
89

90
GimpPlugInInfo PLUG_IN_INFO =
Manish Singh's avatar
Manish Singh committed
91
{
92 93 94 95
  NULL,  /* init_proc  */
  NULL,  /* quit_proc  */
  query, /* query_proc */
  run,   /* run_proc   */
Manish Singh's avatar
Manish Singh committed
96 97 98 99
};



100
gint   line_no;
Manish Singh's avatar
Manish Singh committed
101

102
gint obj_show_single   = -1; /* -1 all >= 0 object number */
Manish Singh's avatar
Manish Singh committed
103 104 105 106 107

/* Structures etc for the objects */
/* Points used to draw the object  */


108 109
Dobject *obj_creating; /* Object we are creating */
Dobject *tmp_line;     /* Needed when drawing lines */
Manish Singh's avatar
Manish Singh committed
110

111

112
GFigObj  *pic_obj;
113
gint      need_to_scale;
114

Manish Singh's avatar
Manish Singh committed
115

116 117 118 119
static gint       load_options            (GFigObj *gfig, 
                                           FILE    *fp);
static gboolean   match_element           (gchar   *buf,
                                           gchar   *element_name);
Manish Singh's avatar
Manish Singh committed
120 121
/* globals */

122
GdkGC  *gfig_gc;
Manish Singh's avatar
Manish Singh committed
123 124

/* Stuff for the preview bit */
125 126 127 128 129
static gint    sel_x1, sel_y1, sel_x2, sel_y2;
static gint    sel_width, sel_height;
gint    preview_width, preview_height;
gdouble scale_x_factor, scale_y_factor;
GdkPixbuf *back_pixbuf = NULL;
Manish Singh's avatar
Manish Singh committed
130

Adrian Likins's avatar
Adrian Likins committed
131
MAIN ()
Manish Singh's avatar
Manish Singh committed
132 133

static void
134
query (void)
Manish Singh's avatar
Manish Singh committed
135
{
136
  static GimpParamDef args[] =
Manish Singh's avatar
Manish Singh committed
137
  {
138 139
    { GIMP_PDB_INT32,    "run_mode", "Interactive, non-interactive" },
    { GIMP_PDB_IMAGE,    "image",    "Input image (unused)" },
140
    { GIMP_PDB_DRAWABLE, "drawable", "Input drawable" },
141
    { GIMP_PDB_INT32,    "dummy",    "dummy" }
Manish Singh's avatar
Manish Singh committed
142
  };
David Monniaux's avatar
David Monniaux committed
143

Manish Singh's avatar
Manish Singh committed
144
  gimp_install_procedure ("plug_in_gfig",
145 146 147 148 149
                          "Create Geometrical shapes with the Gimp",
                          "More here later",
                          "Andy Thomas",
                          "Andy Thomas",
                          "1997",
150
                          N_("_Gfig..."),
151 152 153 154
                          "RGB*, GRAY*",
                          GIMP_PLUGIN,
                          G_N_ELEMENTS (args), 0,
                          args, NULL);
155 156 157

  gimp_plugin_menu_register ("plug_in_gfig",
                             N_("<Image>/Filters/Render"));
Manish Singh's avatar
Manish Singh committed
158 159 160
}

static void
161 162 163 164 165
run (const gchar      *name,
     gint              nparams,
     const GimpParam  *param,
     gint             *nreturn_vals,
     GimpParam       **return_vals)
Manish Singh's avatar
Manish Singh committed
166
{
167 168 169 170
  GimpParam         *values = g_new (GimpParam, 1);
  GimpDrawable      *drawable;
  GimpRunMode        run_mode;
  GimpPDBStatusType  status = GIMP_PDB_SUCCESS;
171
  gint               pwidth, pheight;
172 173
  INIT_I18N ();

174 175 176
  gfig_context = (GFigContext*)g_malloc (sizeof (GFigContext));
  gfig_context->show_background = TRUE;
  gfig_context->selected_obj = NULL;
Manish Singh's avatar
Manish Singh committed
177
  run_mode = param[0].data.d_int32;
178 179
  gfig_context->image_id = param[1].data.d_image;
  gfig_context->drawable_id = param[2].data.d_drawable;
Manish Singh's avatar
Manish Singh committed
180 181 182 183

  *nreturn_vals = 1;
  *return_vals = values;

184
  values[0].type = GIMP_PDB_STATUS;
Manish Singh's avatar
Manish Singh committed
185 186
  values[0].data.d_status = status;

187 188
  gimp_image_undo_group_start (gfig_context->image_id);

189

190
  drawable = gimp_drawable_get (param[2].data.d_drawable);
Manish Singh's avatar
Manish Singh committed
191 192

  /* TMP Hack - clear any selections */
193 194
  if (! gimp_selection_is_empty (gfig_context->image_id))
    gimp_selection_clear (gfig_context->image_id);
Manish Singh's avatar
Manish Singh committed
195

196
  gimp_drawable_mask_bounds (drawable->drawable_id,
197
                             &sel_x1, &sel_y1, &sel_x2, &sel_y2);
Manish Singh's avatar
Manish Singh committed
198 199 200 201

  sel_width  = sel_x2 - sel_x1;
  sel_height = sel_y2 - sel_y1;

202

Manish Singh's avatar
Manish Singh committed
203
  /* Calculate preview size */
204

205 206 207 208 209 210 211 212 213
  if (sel_width > sel_height)
    {
      pwidth  = MIN (sel_width, PREVIEW_SIZE);
      pheight = sel_height * pwidth / sel_width;
    }
  else
    {
      pheight = MIN (sel_height, PREVIEW_SIZE);
      pwidth  = sel_width * pheight / sel_height;
214
    }
215
  
216

217
  preview_width  = MAX (pwidth, 2);  /* Min size is 2 */
218
  preview_height = MAX (pheight, 2);
Manish Singh's avatar
Manish Singh committed
219

220 221 222 223
  org_scale_x_factor = scale_x_factor =
    (gdouble) sel_width / (gdouble) preview_width;
  org_scale_y_factor = scale_y_factor =
    (gdouble) sel_height / (gdouble) preview_height;
224

225 226 227 228 229
  gimp_tile_cache_ntiles ((drawable->width + gimp_tile_width () - 1) /
                          gimp_tile_width ());

  gimp_drawable_detach (drawable);

230 231 232
  /* initialize */
  gfig_init_object_classes ();

Manish Singh's avatar
Manish Singh committed
233 234
  switch (run_mode)
    {
235
    case GIMP_RUN_INTERACTIVE:
Manish Singh's avatar
Manish Singh committed
236
      /*gimp_get_data ("plug_in_gfig", &selvals);*/
237
      if (! gfig_dialog ())
238
        {
239 240 241
          gimp_drawable_detach (gfig_drawable);
          gimp_image_undo_group_end (gfig_context->image_id);

242 243
          return;
        }
Manish Singh's avatar
Manish Singh committed
244 245
      break;

246 247
    case GIMP_RUN_NONINTERACTIVE:
      status = GIMP_PDB_CALLING_ERROR;
Manish Singh's avatar
Manish Singh committed
248 249
      break;

250
    case GIMP_RUN_WITH_LAST_VALS:
Manish Singh's avatar
Manish Singh committed
251 252 253 254 255 256 257
      /*gimp_get_data ("plug_in_gfig", &selvals);*/
      break;

    default:
      break;
    }

258 259 260 261 262
  gimp_image_undo_group_end (gfig_context->image_id);
  
  if (run_mode != GIMP_RUN_NONINTERACTIVE)
    gimp_displays_flush ();
  else  
Manish Singh's avatar
Manish Singh committed
263
#if 0
264 265
  if (run_mode == GIMP_RUN_INTERACTIVE)
    gimp_set_data ("plug_in_gfig", &selvals, sizeof (SelectItVals));
Manish Singh's avatar
Manish Singh committed
266
  else
267
#endif /* 0 */
Manish Singh's avatar
Manish Singh committed
268
    {
269
      status = GIMP_PDB_EXECUTION_ERROR;
Manish Singh's avatar
Manish Singh committed
270 271 272 273 274 275 276 277 278
    }

  values[0].data.d_status = status;

  gimp_drawable_detach (drawable);
}

/*
  Translate SPACE to "\\040", etc.
Manish Singh's avatar
Manish Singh committed
279
  Taken from gflare plugin
Manish Singh's avatar
Manish Singh committed
280
 */
281
void
282
gfig_name_encode (gchar *dest,
283
                  gchar *src)
Manish Singh's avatar
Manish Singh committed
284
{
285
  gint cnt = MAX_LOAD_LINE - 1;
Manish Singh's avatar
Manish Singh committed
286 287 288

  while (*src && cnt--)
    {
289
      if (g_ascii_iscntrl (*src) || g_ascii_isspace (*src) || *src == '\\')
290 291 292 293
        {
          sprintf (dest, "\\%03o", *src++);
          dest += 4;
        }
Manish Singh's avatar
Manish Singh committed
294
      else
295
        *dest++ = *src++;
Manish Singh's avatar
Manish Singh committed
296 297 298 299 300 301 302
    }
  *dest = '\0';
}

/*
  Translate "\\040" to SPACE, etc.
 */
303
void
304
gfig_name_decode (gchar       *dest,
305
                  const gchar *src)
Manish Singh's avatar
Manish Singh committed
306
{
307 308
  gint  cnt = MAX_LOAD_LINE - 1;
  guint tmp;
Manish Singh's avatar
Manish Singh committed
309 310 311 312

  while (*src && cnt--)
    {
      if (*src == '\\' && *(src+1) && *(src+2) && *(src+3))
313 314 315 316 317
        {
          sscanf (src+1, "%3o", &tmp);
          *dest++ = tmp;
          src += 4;
        }
Manish Singh's avatar
Manish Singh committed
318
      else
319
        *dest++ = *src++;
Manish Singh's avatar
Manish Singh committed
320 321 322 323 324 325 326 327 328 329 330
    }
  *dest = '\0';
}


/*
 * Load all gfig, which are founded in gfig-path-list, into gfig_list.
 * gfig-path-list must be initialized first. (plug_in_parse_gfig_path ())
 * based on code from Gflare.
 */

331
gint
332
gfig_list_pos (GFigObj *gfig)
Manish Singh's avatar
Manish Singh committed
333
{
334 335
  GFigObj *g;
  gint n;
Manish Singh's avatar
Manish Singh committed
336 337 338
  GList *tmp;

  n = 0;
339

340
  for (tmp = gfig_list; tmp; tmp = g_list_next (tmp))
Manish Singh's avatar
Manish Singh committed
341 342
    {
      g = tmp->data;
343

Manish Singh's avatar
Manish Singh committed
344
      if (strcmp (gfig->draw_name, g->draw_name) <= 0)
345
        break;
346

Manish Singh's avatar
Manish Singh committed
347 348
      n++;
    }
349
  return n;
Manish Singh's avatar
Manish Singh committed
350 351
}

352
/*
353
 *      Insert gfigs in alphabetical order
354 355
 */

356
gint
357
gfig_list_insert (GFigObj *gfig)
Manish Singh's avatar
Manish Singh committed
358
{
359
  gint n;
Manish Singh's avatar
Manish Singh committed
360

361
  n = gfig_list_pos (gfig);
Manish Singh's avatar
Manish Singh committed
362 363 364 365 366 367

  gfig_list = g_list_insert (gfig_list, gfig, n);

  return n;
}

368
void
369
gfig_free (GFigObj *gfig)
Manish Singh's avatar
Manish Singh committed
370 371 372
{
  g_assert (gfig != NULL);

373
  free_all_objs (gfig->obj_list);
374 375 376 377 378

  g_free (gfig->name);
  g_free (gfig->filename);
  g_free (gfig->draw_name);

Manish Singh's avatar
Manish Singh committed
379 380 381
  g_free (gfig);
}

382
GFigObj *
383
gfig_new (void)
Manish Singh's avatar
Manish Singh committed
384
{
385
  return g_new0 (GFigObj, 1);
Manish Singh's avatar
Manish Singh committed
386 387
}

388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403
static gboolean
match_element (gchar *buf,
               gchar *element_name)
{
  gchar *ptr = buf;

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

  ptr++;

  if (ptr == strstr (ptr, element_name))
    return TRUE;

  return FALSE;
}
404

405 406
static void
gfig_load_objs (GFigObj *gfig,
407 408
                gint     load_count,
                FILE    *fp)
Manish Singh's avatar
Manish Singh committed
409
{
410
  Dobject *obj;
Manish Singh's avatar
Manish Singh committed
411
  gchar load_buf[MAX_LOAD_LINE];
412 413 414
  glong offset;
  glong offset2;
  Style style;
Manish Singh's avatar
Manish Singh committed
415

416
  while (load_count-- > 0)
Manish Singh's avatar
Manish Singh committed
417 418
    {
      obj = NULL;
419 420
      get_line (load_buf, MAX_LOAD_LINE, fp, 0);

421 422 423 424
      /* kludge */
      offset = ftell (fp);
      gfig_skip_style (&style, fp);

425
      if (match_element (load_buf, "Line"))
426 427 428
        {
          obj = d_load_line (fp);
        }
429
      else if (match_element (load_buf, "Circle"))
430 431 432
        {
          obj = d_load_circle (fp);
        }
433
      else if (match_element (load_buf, "Ellipse"))
434 435 436
        {
          obj = d_load_ellipse (fp);
        }
437
      else if (match_element (load_buf, "Poly"))
438 439 440
        {
          obj = d_load_poly (fp);
        }
441
      else if (match_element (load_buf, "Star"))
442 443 444
        {
          obj = d_load_star (fp);
        }
445
      else if (match_element (load_buf, "Spiral"))
446 447 448
        {
          obj = d_load_spiral (fp);
        }
449
      else if (match_element (load_buf, "Bezier"))
450 451 452
        {
          obj = d_load_bezier (fp);
        }
453
      else if (match_element (load_buf, "Arc"))
454 455 456
        {
          obj = d_load_arc (fp);
        }
Manish Singh's avatar
Manish Singh committed
457
      else
458 459 460
        {
          g_warning ("Unknown obj type file %s line %d\n", gfig->filename, line_no);
        }
461

462
      if (obj)
463 464
        {
          add_to_all_obj (gfig, obj);
465 466 467 468
          offset2 = ftell (fp);
          fseek (fp, offset, SEEK_SET);
          gfig_load_style (&obj->style, fp);
          fseek (fp, offset2, SEEK_SET);
469
        }
Manish Singh's avatar
Manish Singh committed
470 471 472
    }
}

473
GFigObj *
474 475
gfig_load (const gchar *filename,
           const gchar *name)
Manish Singh's avatar
Manish Singh committed
476
{
477 478 479 480 481 482
  GFigObj *gfig;
  FILE    *fp;
  gchar    load_buf[MAX_LOAD_LINE];
  gchar    str_buf[MAX_LOAD_LINE];
  gint     chk_count;
  gint     load_count = 0;
483 484 485
  gdouble  version;
  guchar   magic1[20];
  guchar   magic2[20];
Manish Singh's avatar
Manish Singh committed
486 487 488
  g_assert (filename != NULL);

#ifdef DEBUG
489
  printf ("Loading %s (%s)\n", filename, name);
Manish Singh's avatar
Manish Singh committed
490 491 492 493 494
#endif /* DEBUG */

  fp = fopen (filename, "r");
  if (!fp)
    {
495
      g_message (_("Could not open '%s' for reading: %s"),
496
                  gimp_filename_to_utf8 (filename), g_strerror (errno));
Manish Singh's avatar
Manish Singh committed
497 498 499
      return NULL;
    }

500
  gfig = gfig_new ();
Manish Singh's avatar
Manish Singh committed
501

502 503
  gfig->name = g_strdup (name);
  gfig->filename = g_strdup (filename);
Manish Singh's avatar
Manish Singh committed
504 505 506 507 508 509 510 511


  /* HEADER
   * draw_name
   * version
   * obj_list
   */

512
  get_line (load_buf, MAX_LOAD_LINE, fp, 1);
Manish Singh's avatar
Manish Singh committed
513

514 515 516
  sscanf (load_buf, "%10s %10s %lf", magic1, magic2, &version);

  if (strcmp (magic1, "GFIG") || strcmp (magic2, "Version"))
Manish Singh's avatar
Manish Singh committed
517
    {
518 519
      g_message ("File '%s' is not a gfig file",
                  gimp_filename_to_utf8 (gfig->filename));
520
      return NULL;
Manish Singh's avatar
Manish Singh committed
521
    }
522

523 524 525 526
  get_line (load_buf, MAX_LOAD_LINE, fp, 0);
  sscanf (load_buf, "Name: %100s", str_buf);
  gfig_name_decode (load_buf, str_buf);
  gfig->draw_name = g_strdup (load_buf);
527
  
528
  get_line (load_buf, MAX_LOAD_LINE, fp, 0);
529 530
  if (strncmp (load_buf, "Version: ", 9) == 0)
    gfig->version = g_ascii_strtod (load_buf + 9, NULL);
531
  
532 533
  get_line (load_buf, MAX_LOAD_LINE, fp, 0);
  sscanf (load_buf, "ObjCount: %d", &load_count);
534
  
535
  if (load_options (gfig, fp))
Manish Singh's avatar
Manish Singh committed
536
    {
537
      g_message ("File '%s' corrupt file - Line %d Option section incorrect",
538
                 gimp_filename_to_utf8 (filename), line_no);
539
      return NULL;
Manish Singh's avatar
Manish Singh committed
540 541
    }

542 543 544 545 546 547 548
  if (gfig_load_styles (gfig, fp))
    {
      g_message ("File '%s' corrupt file - Line %d Option section incorrect",
                 gimp_filename_to_utf8 (filename), line_no);
      return NULL;
    }
  
Manish Singh's avatar
Manish Singh committed
549

550
  
551
  gfig_load_objs (gfig, load_count, fp);
552
  
Manish Singh's avatar
Manish Singh committed
553
  /* Check count ? */
554
  
555
  chk_count = gfig_obj_counts (gfig->obj_list);
556
  
557
  if (chk_count != load_count)
Manish Singh's avatar
Manish Singh committed
558
    {
559
      g_message ("File '%s' corrupt file - Line %d Object count to small",
560
                 gimp_filename_to_utf8 (filename), line_no);
561
      return NULL;
Manish Singh's avatar
Manish Singh committed
562
    }
563
  
564
  fclose (fp);
Manish Singh's avatar
Manish Singh committed
565

566
  if (!pic_obj)
Manish Singh's avatar
Manish Singh committed
567 568 569 570
    pic_obj = gfig;

  gfig->obj_status = GFIG_OK;

571
  return gfig;
Manish Singh's avatar
Manish Singh committed
572 573
}

574 575
void
save_options (GString *string)
Manish Singh's avatar
Manish Singh committed
576 577
{
  /* Save options */
578 579
  g_string_append_printf (string, "<OPTIONS>\n");
  g_string_append_printf (string, "GridSpacing: %d\n", selvals.opts.gridspacing);
580
  if (selvals.opts.gridtype == RECT_GRID)
581 582 583
    {
      g_string_append_printf (string, "GridType: RECT_GRID\n");
    }
584
  else if (selvals.opts.gridtype == POLAR_GRID)
585 586 587
    {
      g_string_append_printf (string, "GridType: POLAR_GRID\n");
    }
588
  else if (selvals.opts.gridtype == ISO_GRID)
589 590 591 592 593 594 595 596 597 598 599 600 601 602 603 604 605 606 607 608 609 610
    {
      g_string_append_printf (string, "GridType: ISO_GRID\n");
    }
  else 
    {
      g_string_append_printf (string, "GridType: RECT_GRID\n"); /* default to RECT_GRID */
    }

  g_string_append_printf (string, "DrawGrid: %s\n", (selvals.opts.drawgrid)?"TRUE":"FALSE");
  g_string_append_printf (string, "Snap2Grid: %s\n", (selvals.opts.snap2grid)?"TRUE":"FALSE");
  g_string_append_printf (string, "LockOnGrid: %s\n", (selvals.opts.lockongrid)?"TRUE":"FALSE");
  g_string_append_printf (string, "ShowControl: %s\n", (selvals.opts.showcontrol)?"TRUE":"FALSE");
  g_string_append_printf (string, "</OPTIONS>\n");
}

static void 
gfig_save_obj_start (Dobject *obj, 
                     GString *string)
{
  switch (obj->type)
    {
    case LINE:
611
      g_string_append_printf (string, "<Line>\n");
612 613
      break;
    case CIRCLE:
614
      g_string_append_printf (string, "<Circle>\n");
615 616
      break;
    case ELLIPSE:
617
      g_string_append_printf (string, "<Ellipse>\n");
618 619
      break;
    case ARC:
620
      g_string_append_printf (string, "<Arc>\n");
621 622
      break;
    case POLY:
623
      g_string_append_printf (string, "<Poly>\n");
624 625
      break;
    case STAR:
626
      g_string_append_printf (string, "<Star>\n");
627 628
      break;
    case SPIRAL:
629
      g_string_append_printf (string, "<Spiral>\n");
630 631
      break;
    case BEZIER:
632
      g_string_append_printf (string, "<Bezier>\n");
633 634 635 636 637 638 639 640 641 642 643
      break;
    default:
      g_message ("Unknown object type in gfig_save_obj_start");
    }
}

static void 
gfig_save_obj_end (Dobject *obj, 
                   GString *string)
{
  g_string_append_printf (string, "</Object>\n");
644 645 646 647
}

static gint
load_bool (gchar *opt_buf,
648
           gint  *toset)
649 650
{
  if (!strcmp (opt_buf, "TRUE"))
Manish Singh's avatar
Manish Singh committed
651
    *toset = 1;
652
  else if (!strcmp (opt_buf, "FALSE"))
Manish Singh's avatar
Manish Singh committed
653 654
    *toset = 0;
  else
655
    return (-1);
Manish Singh's avatar
Manish Singh committed
656

657
  return (0);
Manish Singh's avatar
Manish Singh committed
658 659
}

660 661
static gint
load_options (GFigObj *gfig,
662
              FILE    *fp)
Manish Singh's avatar
Manish Singh committed
663 664 665 666 667
{
  gchar load_buf[MAX_LOAD_LINE];
  gchar str_buf[MAX_LOAD_LINE];
  gchar opt_buf[MAX_LOAD_LINE];

668
  get_line (load_buf, MAX_LOAD_LINE, fp, 0);
Manish Singh's avatar
Manish Singh committed
669 670

#ifdef DEBUG
671
  printf ("load '%s'\n", load_buf);
Manish Singh's avatar
Manish Singh committed
672 673
#endif /* DEBUG */

674 675
  if (strcmp (load_buf, "<OPTIONS>"))
    return (-1);
676

677
  get_line (load_buf, MAX_LOAD_LINE, fp, 0);
Manish Singh's avatar
Manish Singh committed
678 679

#ifdef DEBUG
680
  printf ("opt line '%s'\n", load_buf);
Manish Singh's avatar
Manish Singh committed
681 682
#endif /* DEBUG */

683
  while (strcmp (load_buf, "</OPTIONS>"))
Manish Singh's avatar
Manish Singh committed
684 685 686
    {
      /* Get option name */
#ifdef DEBUG
687
      printf ("num = %d\n", sscanf (load_buf, "%s %s", str_buf, opt_buf));
Manish Singh's avatar
Manish Singh committed
688

689
      printf ("option %s val %s\n", str_buf, opt_buf);
Manish Singh's avatar
Manish Singh committed
690
#else
691
      sscanf (load_buf, "%s %s", str_buf, opt_buf);
Manish Singh's avatar
Manish Singh committed
692 693
#endif /* DEBUG */

694
      if (!strcmp (str_buf, "GridSpacing:"))
695 696 697 698 699 700 701 702
        {
          /* Value is decimal */
          int sp = 0;
          sp = atoi (opt_buf);
          if (sp <= 0)
            return (-1);
          gfig->opts.gridspacing = sp;
        }
703
      else if (!strcmp (str_buf, "DrawGrid:"))
704 705 706 707 708
        {
          /* Value is bool */
          if (load_bool (opt_buf, &gfig->opts.drawgrid))
            return (-1);
        }
709
      else if (!strcmp (str_buf, "Snap2Grid:"))
710 711 712 713 714
        {
          /* Value is bool */
          if (load_bool (opt_buf, &gfig->opts.snap2grid))
            return (-1);
        }
715
      else if (!strcmp (str_buf, "LockOnGrid:"))
716 717 718 719 720
        {
          /* Value is bool */
          if (load_bool (opt_buf, &gfig->opts.lockongrid))
            return (-1);
        }
721
      else if (!strcmp (str_buf, "ShowControl:"))
722 723 724 725 726
        {
          /* Value is bool */
          if (load_bool (opt_buf, &gfig->opts.showcontrol))
            return (-1);
        }
727
      else if (!strcmp (str_buf, "GridType:"))
728 729 730 731 732 733 734 735 736 737 738
        {
          /* Value is string */
          if (!strcmp (opt_buf, "RECT_GRID"))
            gfig->opts.gridtype = RECT_GRID;
          else if (!strcmp (opt_buf, "POLAR_GRID"))
            gfig->opts.gridtype = POLAR_GRID;
          else if (!strcmp (opt_buf, "ISO_GRID"))
            gfig->opts.gridtype = ISO_GRID;
          else
            return (-1);
        }
Manish Singh's avatar
Manish Singh committed
739

740
      get_line (load_buf, MAX_LOAD_LINE, fp, 0);
741

Manish Singh's avatar
Manish Singh committed
742
#ifdef DEBUG
743
      printf ("opt line '%s'\n", load_buf);
Manish Singh's avatar
Manish Singh committed
744
#endif /* DEBUG */
745
    }
746
  return (0);
Manish Singh's avatar
Manish Singh committed
747 748
}

749 750
GString *
gfig_save_as_string ()
Manish Singh's avatar
Manish Singh committed
751
{
752 753 754 755 756
  DAllObjs     *objs;
  gint          count = 0;
  gchar         buf[G_ASCII_DTOSTR_BUF_SIZE];
  gchar         conv_buf[MAX_LOAD_LINE*3 +1];
  GString       *string;
Manish Singh's avatar
Manish Singh committed
757

758 759 760 761 762 763 764 765
  string = g_string_new (GFIG_HEADER);
  
  gfig_name_encode (conv_buf, gfig_context->current_obj->draw_name);
  g_string_append_printf (string, "Name: %s\n", conv_buf);
  g_string_append_printf (string, "Version: %s\n",
                          g_ascii_formatd (buf, G_ASCII_DTOSTR_BUF_SIZE, "%f",
                                           gfig_context->current_obj->version));
  objs = gfig_context->current_obj->obj_list;
Manish Singh's avatar
Manish Singh committed
766

767
  count = gfig_obj_counts (objs);
Manish Singh's avatar
Manish Singh committed
768

769
  g_string_append_printf (string, "ObjCount: %d\n", count);
Manish Singh's avatar
Manish Singh committed
770

771
  save_options (string);
Manish Singh's avatar
Manish Singh committed
772

773
  gfig_save_styles (string);
774

775
  for (objs = gfig_context->current_obj->obj_list; objs; objs = objs->next)
Manish Singh's avatar
Manish Singh committed
776
    {
777
      gfig_save_obj_start (objs->obj, string);
778

779
      gfig_save_style (&objs->obj->style, string);
780

781
      if (objs->obj->points)
782
        {
783
          objs->obj->class->savefunc (objs->obj, string);
784
        }
Manish Singh's avatar
Manish Singh committed
785

786
      gfig_save_obj_end (objs->obj, string);
Manish Singh's avatar
Manish Singh committed
787 788
    }

789
  return string;
Manish Singh's avatar
Manish Singh committed
790 791 792
}


793 794
gboolean
gfig_save_as_parasite ()
Manish Singh's avatar
Manish Singh committed
795
{
796 797
  GimpParasite *parasite;
  GString       *string;
Manish Singh's avatar
Manish Singh committed
798

799
  string = gfig_save_as_string ();
Michael Natterer's avatar
Michael Natterer committed
800

801 802 803 804 805 806 807
  /* temporarily make the parasite non-persistent until the
   * format has stabilized.
   */
#if 0
  parasite = gimp_parasite_new ("gfig", GIMP_PARASITE_PERSISTENT | GIMP_PARASITE_UNDOABLE, 
                                datasize, data);
#endif
Michael Natterer's avatar
Michael Natterer committed
808

809 810
  parasite = gimp_parasite_new ("gfig", GIMP_PARASITE_UNDOABLE, 
                                string->len, string->str);
Michael Natterer's avatar
Michael Natterer committed
811

812
  g_string_free (string, TRUE);
Michael Natterer's avatar
Michael Natterer committed
813

814
  if (!gimp_drawable_parasite_attach (gfig_context->drawable_id, parasite))
815
    {
816 817 818
      g_message (_("Error trying to save figure as a parasite: can't attach parasite to drawable.\n"));
      gimp_parasite_free (parasite);
      return FALSE;
819
    }
Manish Singh's avatar
Manish Singh committed
820

821 822
  gimp_parasite_free (parasite);
  return TRUE;