home *** CD-ROM | disk | FTP | other *** search
/ PC Pro 2002 April / pcpro0402.iso / essentials / graphics / Gimp / gimp-src-20001226.exe / src / gimp / plug-ins / gfig / gfig.c next >
Encoding:
C/C++ Source or Header  |  2000-09-29  |  271.1 KB  |  11,276 lines

  1. /*
  2.  * Copyright (C) 1995 Spencer Kimball and Peter Mattis
  3.  *
  4.  * This is a plug-in for the GIMP.
  5.  *
  6.  * Generates images containing vector type drawings.
  7.  *
  8.  * Copyright (C) 1997 Andy Thomas  alt@picnic.demon.co.uk
  9.  *
  10.  * This program is free software; you can redistribute it and/or modify
  11.  * it under the terms of the GNU General Public License as published by
  12.  * the Free Software Foundation; either version 2 of the License, or
  13.  * (at your option) any later version.
  14.  *
  15.  * This program is distributed in the hope that it will be useful,
  16.  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  17.  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  18.  * GNU General Public License for more details.
  19.  *
  20.  * You should have received a copy of the GNU General Public License
  21.  * along with this program; if not, write to the Free Software
  22.  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
  23.  * 
  24.  * Some of this code was taken from the Whirl plug-in
  25.  * which was copyrighted by Federico Mena Quintero (as below).
  26.  * 
  27.  * Whirl plug-in --- distort an image into a whirlpool
  28.  * Copyright (C) 1997 Federico Mena Quintero           
  29.  *
  30.  */
  31.  
  32. /* Change log:
  33.  * 0.9 First public release. 
  34.  * 0.95 Second release.
  35.  * 
  36.  * 0.96 Added patch from  Rob Saunders that introduces a isometric type grid
  37.  *      Removed use of gtk_idle* stuff on position update. Not required.
  38.  *
  39.  * 1.0  Fixed to work with the new gtk+-0.99.4 (tooltips stuff has changed).  
  40.  * 
  41.  * 1.1  Fixed crashes when objects not fully defined
  42.  * 
  43.  * 1.2  More bug fixes and prevent gtk warning when creating new figs
  44.  * 
  45.  * 1.3  Portability fixes and fixed bug reports 257 and 258 from and 81 & 101 & 133
  46.  *      http://www.wilberworks.com/bugs.cgi
  47.  */
  48.  
  49. #include "config.h"
  50.  
  51. #include <glib.h>
  52.  
  53. #include <stdio.h>
  54. #include <stdlib.h>
  55. #include <sys/types.h>
  56. #include <sys/stat.h>
  57. #ifdef HAVE_UNISTD_H
  58. #include <unistd.h>
  59. #endif
  60. #include <string.h>
  61. #ifdef HAVE_DIRENT_H
  62. #include <dirent.h>
  63. #endif
  64. #include <ctype.h>
  65. #include <gtk/gtk.h>
  66.  
  67. #ifdef G_OS_WIN32
  68. #  include <io.h>
  69. #  ifndef W_OK
  70. #    define W_OK 2
  71. #  endif
  72. #  ifndef S_ISDIR
  73. #    define S_ISDIR(m) ((m) & _S_IFDIR)
  74. #  endif
  75. #  ifndef S_ISREG
  76. #    define S_ISREG(m) ((m) & _S_IFREG)
  77. #  endif
  78. #endif
  79.  
  80. #if defined (GTK_CHECK_VERSION) && GTK_CHECK_VERSION (1,3,0)
  81. #define gdk_root_parent (*gdk_parent_root)
  82. #endif
  83.  
  84. #ifdef G_OS_WIN32
  85. extern __declspec(dllimport) void *gdk_root_parent;
  86. #else
  87. extern void * gdk_root_parent;
  88. #endif
  89.  
  90. #include <libgimp/gimp.h>
  91. #include <libgimp/gimpui.h>
  92.  
  93. #include "libgimp/stdplugins-intl.h"
  94.  
  95. #include "pix_data.h"
  96.  
  97. /***** Magic numbers *****/
  98.  
  99. #define PREVIEW_SIZE 400
  100. #define SCALE_WIDTH  120
  101.  
  102. #define MIN_GRID 10
  103. #define MAX_GRID 50
  104. #define MAX_UNDO 10
  105. #define MIN_UNDO 1
  106. #define MAX_LOAD_LINE 256
  107. #define SMALL_PREVIEW_SZ 48
  108. #define BRUSH_PREVIEW_SZ 32
  109. #define GFIG_HEADER "GFIG Version 0.1\n"
  110.  
  111. #define PREVIEW_MASK   GDK_EXPOSURE_MASK | \
  112.                        GDK_MOTION_NOTIFY | \
  113.                GDK_POINTER_MOTION_MASK | \
  114.                        GDK_BUTTON_PRESS_MASK | \
  115.                GDK_BUTTON_RELEASE_MASK | \
  116.                GDK_BUTTON_MOTION_MASK | \
  117.                GDK_KEY_PRESS_MASK | \
  118.                GDK_KEY_RELEASE_MASK 
  119.  
  120. static GimpDrawable *gfig_select_drawable;
  121. static GtkWidget *gfig_preview;
  122. static GtkWidget *pic_preview;
  123. static GtkWidget *gfig_gtk_list;
  124. static gint       gfig_preview_exp_id;
  125. static gint32     gfig_image;
  126. static gint32     gfig_drawable;
  127. static GtkWidget *brush_page_pw;
  128. static GtkWidget *brush_sel_button;
  129.  
  130. static gint   tile_width, tile_height;
  131. static gint   img_width, img_height, img_bpp, real_img_bpp;
  132.  
  133. static void      query  (void);
  134. static void      run    (gchar    *name,
  135.              gint      nparams,
  136.              GimpParam   *param,
  137.              gint     *nreturn_vals,
  138.              GimpParam  **return_vals);
  139.  
  140. static gint      gfig_dialog               (void);
  141. static void      gfig_ok_callback          (GtkWidget *widget,
  142.                         gpointer   data);
  143. static void      gfig_paint_callback       (GtkWidget *widget,
  144.                         gpointer   data);
  145. static void      gfig_clear_callback       (GtkWidget *widget,
  146.                         gpointer   data);
  147. static void      gfig_undo_callback        (GtkWidget *widget,
  148.                         gpointer   data);
  149. static gint      gfig_preview_expose       (GtkWidget *widget,
  150.                         GdkEvent  *event);
  151. static gint      pic_preview_expose        (GtkWidget *widget,
  152.                         GdkEvent  *event);
  153. static gint      gfig_preview_events       (GtkWidget *widget,
  154.                         GdkEvent  *event);
  155. static gint      gfig_brush_preview_events (GtkWidget *widget,
  156.                         GdkEvent  *event);
  157.  
  158. static void      gfig_scale_update_scale   (GtkAdjustment *adjustment,
  159.                         gdouble       *value);
  160.  
  161. static void      gfig_scale2img_update     (GtkWidget *widget,
  162.                         gpointer   data);
  163.  
  164. static gint      gfig_scale_x              (gint       x);
  165. static gint      gfig_scale_y              (gint       y);
  166. static gint      gfig_invscale_x           (gint       x);
  167. static gint      gfig_invscale_y           (gint       y);
  168. static GdkGC *   gfig_get_grid_gc          (GtkWidget *widget,
  169.                         gint       gctype);
  170. static void      gfig_pos_enable           (GtkWidget *widget,
  171.                         gpointer   data);
  172.  
  173. static gint      list_button_press         (GtkWidget      *widget,
  174.                         GdkEventButton *event,
  175.                         gpointer        data);
  176.  
  177. static void      rescan_button_callback    (GtkWidget *widget,
  178.                         gpointer   data);
  179. static void      load_button_callback      (GtkWidget *widget,
  180.                         gpointer   data);
  181. static void      save_button_callback      (GtkWidget *widget,
  182.                         gpointer   data);
  183. static void      new_button_callback       (GtkWidget *widget,
  184.                         gpointer   data);
  185. static void   gfig_do_delete_gfig_callback (GtkWidget *widget,
  186.                         gboolean   delete,
  187.                         gpointer   data);
  188. static void      gfig_delete_gfig_callback (GtkWidget *widget,
  189.                         gpointer   data);
  190. static void      edit_button_callback      (GtkWidget *widget,
  191.                         gpointer   data);
  192. static void      merge_button_callback     (GtkWidget *widget,
  193.                         gpointer   data);
  194. static void      about_button_callback     (GtkWidget *widget,
  195.                         gpointer   data);
  196. static void      reload_button_callback    (GtkWidget *widget,
  197.                         gpointer   data);
  198.  
  199. static void      do_gfig                   (void);
  200. static void      dialog_update_preview     (void);
  201.  
  202. static void      draw_grid_clear           (GtkWidget *widget,
  203.                         gpointer   data);
  204. static void      toggle_show_image         (GtkWidget *widget,
  205.                         gpointer   data);
  206. static void      toggle_tooltips           (GtkWidget *widget,
  207.                         gpointer   data);
  208. static void      toggle_obj_type           (GtkWidget *widget,
  209.                         gpointer   data);
  210. static void      draw_grid                 (GtkWidget *widget,
  211.                         gpointer   data);
  212.  
  213. static void      gfig_new_gc               (void);
  214. static void      find_grid_pos             (GdkPoint  *p,
  215.                         GdkPoint  *gp,
  216.                         guint      state);
  217.  
  218. static void      brush_list_button_callback (GtkWidget *widget,
  219.                          gpointer   data);
  220. static gint      calculate_point_to_line_distance (GdkPoint *p,
  221.                            GdkPoint *A,
  222.                            GdkPoint *B,
  223.                            GdkPoint *I);
  224.  
  225. GimpPlugInInfo PLUG_IN_INFO =
  226. {
  227.   NULL,  /* init_proc  */
  228.   NULL,  /* quit_proc  */
  229.   query, /* query_proc */
  230.   run,   /* run_proc   */
  231. };
  232.  
  233. /* The types of an object */
  234. /* Also includes actions that can be performed on objects */
  235.  
  236. typedef enum
  237. {
  238.   LINE,
  239.   CIRCLE,
  240.   ELLIPSE,
  241.   ARC,
  242.   POLY,
  243.   STAR,
  244.   SPIRAL,
  245.   BEZIER,
  246.   MOVE_OBJ,
  247.   MOVE_POINT,
  248.   COPY_OBJ,
  249.   MOVE_COPY_OBJ,
  250.   DEL_OBJ,
  251.   NULL_OPER
  252. } DobjType;
  253.  
  254. typedef enum
  255. {
  256.   RECT_GRID = 0,
  257.   POLAR_GRID,
  258.   ISO_GRID
  259. } GridType;
  260.  
  261. typedef enum
  262. {
  263.   ORIGINAL_LAYER = 0,
  264.   SINGLE_LAYER,
  265.   MULTI_LAYER
  266. } DrawonLayers;
  267.  
  268. typedef enum
  269. {
  270.   LAYER_TRANS_BG = 0,
  271.   LAYER_BG_BG,
  272.   LAYER_FG_BG,
  273.   LAYER_WHITE_BG,
  274.   LAYER_COPY_BG
  275. } LayersBGType;
  276.  
  277. typedef enum
  278. {
  279.   PAINT_BRUSH_TYPE = 0,
  280.   PAINT_SELECTION_TYPE,
  281.   PAINT_SELECTION_FILL_TYPE
  282. } PaintType;
  283.  
  284. typedef enum
  285. {
  286.   BRUSH_BRUSH_TYPE = 0,
  287.   BRUSH_PENCIL_TYPE,
  288.   BRUSH_AIRBRUSH_TYPE,
  289.   BRUSH_PATTERN_TYPE
  290. } BrushType;
  291.  
  292.  
  293. #define GRID_TYPE_MENU 1
  294. #define GRID_RENDER_MENU 2
  295. #define GRID_IGNORE 0 
  296. #define GRID_HIGHTLIGHT 1
  297. #define GRID_RESTORE 2
  298.  
  299. #define GFIG_BLACK_GC -2
  300. #define GFIG_WHITE_GC -3
  301. #define GFIG_GREY_GC -4
  302.  
  303. #define PAINT_LAYERS_MENU 1
  304. #define PAINT_BGS_MENU 2
  305. #define PAINT_TYPE_MENU 3
  306.  
  307. #define SELECT_TYPE_MENU 1
  308. #define SELECT_ARCTYPE_MENU 2
  309. #define SELECT_TYPE_MENU_FILL 3
  310. #define SELECT_TYPE_MENU_WHEN 4
  311.  
  312. #define OBJ_SELECT_GT 1
  313. #define OBJ_SELECT_LT 2
  314. #define OBJ_SELECT_EQ 4
  315.  
  316.  
  317. typedef struct
  318. {
  319.   gint     gridspacing;
  320.   GridType gridtype;
  321.   gint     drawgrid;
  322.   gint     snap2grid;
  323.   gint     lockongrid;
  324.   gint     showcontrol;
  325. } GfigOpts;
  326.  
  327. /* Must keep in step with the above */
  328. typedef struct
  329. {
  330.   void      *gridspacing;
  331.   GtkWidget *gridtypemenu;
  332.   GtkWidget *drawgrid;
  333.   GtkWidget *snap2grid;
  334.   GtkWidget *lockongrid;
  335.   GtkWidget *showcontrol;
  336. } GfigOptWidgets;
  337.  
  338. static GfigOptWidgets gfig_opt_widget;
  339.  
  340. typedef struct
  341. {
  342.   GfigOpts      opts;
  343.   gint          showimage;
  344.   gint          maxundo;
  345.   gint          showpos;
  346.   gdouble       brushfade;
  347.   gdouble       brushgradient;
  348.   gdouble       airbrushpressure;
  349.   gint          showtooltips;
  350.   DrawonLayers  onlayers;
  351.   LayersBGType  onlayerbg;
  352.   PaintType     painttype;
  353.   gint          reverselines;
  354.   gint          scaletoimage;
  355.   gdouble       scaletoimagefp;
  356.   gint          approxcircles;
  357.   BrushType    brshtype;
  358.   DobjType      otype;
  359. } SelectItVals;
  360.  
  361. /* Values when first invoked */
  362. static SelectItVals selvals =
  363. {
  364.   {
  365.     MIN_GRID + (MAX_GRID - MIN_GRID)/2, /* Gridspacing */
  366.     RECT_GRID, /* Default to rectangle type */
  367.     0,  /* drawgrid */
  368.     0,  /* snap2grid */
  369.     0,  /* lockongrid */
  370.     1,  /* show control points */
  371.   },
  372.   0,  /* show image */
  373.   MIN_UNDO + (MAX_UNDO - MIN_UNDO)/2,  /* Max level of undos */
  374.   FALSE, /* Show pos updates */
  375.   0.0, /* Brush fade */
  376.   0.0, /* Brush gradient */
  377.   20.0, /* Air bursh pressure */
  378.   TRUE,  /* show Tool tips */
  379.   ORIGINAL_LAYER, /* Draw all objects on one layer */
  380.   LAYER_TRANS_BG, /* New layers background */
  381.   PAINT_BRUSH_TYPE, /* Default to use brushes */
  382.   FALSE, /* reverse lines */
  383.   TRUE, /* Scale to image when painting */
  384.   1.0, /* Scale to image fp */
  385.   FALSE, /* Approx circles by drawing lines */
  386.   BRUSH_BRUSH_TYPE, /* Default to use a brush */
  387.   LINE /* Initial object type */
  388. };
  389.  
  390. typedef enum
  391. {
  392.   ADD=0,
  393.   SUBTRACT=1,
  394.   REPLACE=2,
  395.   INTERSECT=3
  396. } SelectionType;
  397.     
  398.  
  399. typedef enum
  400. {
  401.   ARC_SEGMENT,
  402.   ARC_SECTOR
  403. } ArcType;
  404.  
  405. typedef enum
  406. {
  407.   FILL_FOREGROUND = 0,
  408.   FILL_BACKGROUND = 1,
  409.   FILL_PATTERN = 2
  410. } FillType;
  411.  
  412. typedef enum
  413. {
  414.   FILL_EACH = 0,
  415.   FILL_AFTER
  416. } FillWhen;
  417.  
  418. struct selection_option
  419. {
  420.   SelectionType type; /* ADD etc .. */
  421.   gint antia; /* Boolean for Antia */
  422.   gint feather; /* Feather it ? */
  423.   gdouble feather_radius; /* Radius to feather */
  424.   ArcType as_pie; /* Arc type selection segment/sector */
  425.   FillType fill_type; /* Fill type for selection */
  426.   FillWhen fill_when; /* Fill on each selection or after all? */
  427.   gdouble fill_opacity; /* You can guess this one */
  428. } selopt =
  429. {
  430.   ADD, /* type */
  431.   FALSE, /* Antia */
  432.   FALSE, /* Feather */
  433.   10.0, /* feather radius */
  434.   ARC_SEGMENT,  /* Arc as a segment */
  435.   FILL_PATTERN, /* Fill as pattern */
  436.   FILL_EACH, /* Fill after each selection */
  437.   100.0, /* Max opacity */
  438. };
  439.  
  440.  
  441. static GList *gfig_path_list = NULL;
  442. static GList *gfig_list      = NULL;
  443. static gint   line_no;
  444.  
  445. static gint poly_num_sides    = 3; /* Default to three sided object */
  446. static gint star_num_sides    = 3; /* Default to three sided object */
  447. static gint spiral_num_turns  = 4; /* Default to 4 turns */
  448. static gint spiral_toggle     = 0; /* 0 = clockwise -1 = anti-clockwise */
  449. static gint bezier_closed     = 0; /* Closed curve 0 = false 1 = true */
  450. static gint bezier_line_frame = 0; /* Show frame = false 1 = true */
  451.  
  452. static gint obj_show_single = -1; /* -1 all >= 0 object number */
  453.  
  454. /* Structures etc for the objects */
  455. /* Points used to draw the object  */
  456.  
  457. typedef struct DobjPoints
  458. {
  459.   struct DobjPoints * next;
  460.   GdkPoint pnt;
  461.   gint found_me;
  462. } DobjPoints;
  463.  
  464.  
  465. struct Dobject; /* fwd declaration for DobjFunc */
  466.  
  467. typedef void            (*DobjFunc) (struct Dobject *);
  468. typedef struct Dobject *(*DobjGenFunc) (struct Dobject *);
  469. typedef struct Dobject *(*DobjLoadFunc) (FILE *);
  470. typedef void            (*DobjSaveFunc) (struct Dobject *, FILE *);
  471.  
  472. /* The object itself */
  473. typedef struct Dobject
  474. {
  475.   DobjType      type; /* What is the type? */
  476.   gpointer      type_data; /* Extra data needed by the object */
  477.   DobjPoints   *points; /* List of points */
  478.   DobjFunc      drawfunc; /* How do I draw myself */
  479.   DobjFunc      paintfunc; /* Draw me on canvas */
  480.   DobjGenFunc   copyfunc;  /* copy */
  481.   DobjLoadFunc  loadfunc;  /* Load this type of object */
  482.   DobjSaveFunc  savefunc;  /* Save me out */
  483. } Dobject;
  484.  
  485.  
  486. static Dobject *obj_creating; /* Object we are creating */
  487. static Dobject *tmp_line; /* Needed when drawing lines */
  488. static Dobject *tmp_bezier; /* Neeed when drawing bezier curves */
  489.  
  490. typedef struct DAllObjs
  491. {
  492.   struct DAllObjs *next; 
  493.   Dobject         *obj; /* Object on list */
  494. } DAllObjs;
  495.  
  496. /* States of the object */
  497. #define GFIG_OK       0x0
  498. #define GFIG_MODIFIED 0x1
  499. #define GFIG_READONLY 0x2
  500.  
  501. typedef struct DFigObj
  502. {
  503.   gchar     *name;     /* Trailing name of file  */
  504.   gchar     *filename; /* Filename itself */
  505.   gchar     *draw_name;/* Name of the drawing */
  506.   gfloat     version;     /* Version number of data file */
  507.   GfigOpts   opts;    /* Options enforced when fig saved */
  508.   DAllObjs  *obj_list; /* Objects that make up this list */
  509.   gint       obj_status;    /* See above for possible values */
  510.   GtkWidget *list_item;
  511.   GtkWidget *label_widget;
  512.   GtkWidget *pixmap_widget;
  513. } GFigObj;  
  514.  
  515.  
  516. typedef struct BrushDesc
  517. {
  518.   gchar  *bname; /* name of the brush */
  519.   gint32  width;  /* Width of brush */
  520.   gint32  height;  /* Height of brush */
  521.   guchar *pv_buf; /* Buffer where brush placed */
  522.   gint16  x_off;
  523.   gint16  y_off;
  524.   gint    bpp; /* Depth - should ALWAYS be the same for all BrushDesc */
  525. } BrushDesc;
  526.  
  527. static GFigObj  *current_obj;
  528. static Dobject  *operation_obj;
  529. static GdkPoint *move_all_pnt; /* Point moving all from */
  530. static GFigObj  *pic_obj;
  531. static DAllObjs *undo_table[MAX_UNDO];
  532. static gint      need_to_scale;
  533. static gint32    brush_image_ID = -1;
  534.  
  535. static GtkWidget *undo_widget;
  536. static GtkWidget *gfig_op_menu; /* Popup menu in the list box */
  537. static GtkWidget *delete_frame_to_freeze; /* Top preview frame window */
  538. static GtkWidget *fade_out_hbox;   /* Fade out widget in brush page */
  539. static GtkWidget *gradient_hbox;   /* Gradient widget in brush page */
  540. static GtkWidget *pressure_hbox;   /* Pressure widget in brush page */
  541. static GtkWidget *pencil_hbox;     /* Dummy widget in brush page */
  542. static GtkWidget *pos_label;       /* XY pos marker */
  543. static GtkWidget *brush_page_widget; /* Widget for the brush part of notebook */
  544. static GtkWidget *select_page_widget; /* Widget for the selection part
  545.                        * of notebook */
  546.  
  547. static gint undo_water_mark = -1; /* Last slot filled in -1 = no undo */
  548. static gint drawing_pic = FALSE;  /* If true drawing to the small preview */
  549. static GtkWidget *status_label_dname;
  550. static GtkWidget *status_label_fname;
  551. static GFigObj   *gfig_obj_for_menu; /* More static data -
  552.                       * need to know which object was selected*/
  553. static GtkWidget *save_menu_item;  
  554. static GtkWidget *save_button;
  555.  
  556.  
  557. /* Don't up just like BIGGG source files? */
  558.  
  559. static void       object_start            (GdkPoint *pnt, gint);
  560. static void       object_operation        (GdkPoint *pnt, gint);
  561. static void       object_operation_start  (GdkPoint *pnt, gint shift_down);
  562. static void       object_operation_end    (GdkPoint *pnt, gint);
  563. static void       object_end              (GdkPoint *pnt, gint shift_down);
  564. static void       object_update           (GdkPoint * pnt);
  565. static void       add_to_all_obj          (GFigObj * fobj, Dobject *obj);
  566. static void       d_delete_dobjpoints     (DobjPoints *);
  567. static Dobject  * d_new_line              (gint x, gint y);
  568. static Dobject  * d_new_circle            (gint x, gint y);
  569. static DAllObjs * copy_all_objs           (DAllObjs *objs);
  570. static void       setup_undo              (void);
  571. static void       d_pnt_add_line          (Dobject *obj,
  572.                        gint x, gint y, gint pos);
  573. static GFigObj  * gfig_load               (gchar *filename, gchar *name);
  574. static void       free_all_objs           (DAllObjs * objs);
  575. static void       draw_objects            (DAllObjs *objs, gint show_single);
  576. static Dobject  * d_load_line             (FILE *from);
  577. static Dobject  * d_load_circle           (FILE *from);
  578. static gchar    * get_line                (gchar *buf, gint s,
  579.                        FILE * from, gint init);
  580. static GFigObj  * gfig_new                (void);
  581. static void       clear_undo              (void);
  582. static void       list_button_update      (GFigObj *obj);
  583. static void       prepend_to_all_obj      (GFigObj *fobj, DAllObjs *nobj);
  584. static void       gfig_update_stat_labels (void);
  585. static void       gfig_obj_modified       (GFigObj *obj, gint stat_type);
  586. static void       gfig_op_menu_create     (GtkWidget *window);
  587. static void       gridtype_menu_callback  (GtkWidget *widget, gpointer data);
  588. static void       draw_one_obj            (Dobject * obj);
  589. static void       d_save_poly             (Dobject * obj, FILE *to);
  590. static Dobject  * d_load_poly             (FILE *from);
  591. static void       d_draw_poly             (Dobject *obj);
  592. static void       d_paint_poly            (Dobject *obj);
  593. static Dobject  * d_copy_poly             (Dobject * obj);
  594. static Dobject  * d_new_poly              (gint x, gint y);
  595. static void       d_update_poly           (GdkPoint *pnt);
  596. static void       d_poly_start            (GdkPoint *pnt, gint shift_down);
  597. static void       d_poly_end              (GdkPoint *pnt, gint shift_down);
  598. static void       d_save_star             (Dobject * obj, FILE *to);
  599. static Dobject  * d_load_star             (FILE *from);
  600. static void       d_draw_star             (Dobject *obj);
  601. static void       d_paint_star            (Dobject *obj);
  602. static Dobject  * d_copy_star             (Dobject * obj);
  603. static Dobject  * d_new_star              (gint x, gint y);
  604. static void       d_update_star           (GdkPoint *pnt);
  605. static void       d_star_start            (GdkPoint *pnt, gint shift_down);
  606. static void       d_star_end              (GdkPoint *pnt, gint shift_down);
  607. static Dobject  * d_load_spiral           (FILE *from);
  608. static void       d_draw_spiral           (Dobject *obj);
  609. static void       d_paint_spiral          (Dobject *obj);
  610. static Dobject  * d_copy_spiral           (Dobject * obj);
  611. static Dobject  * d_new_spiral            (gint x, gint y);
  612. static void       d_update_spiral         (GdkPoint *pnt);
  613. static void       d_spiral_start          (GdkPoint *pnt, gint shift_down);
  614. static void       d_spiral_end            (GdkPoint *pnt, gint shift_down);
  615.  
  616. static Dobject  * d_load_bezier           (FILE *from);
  617. static void       d_draw_bezier           (Dobject *obj);
  618. static void       d_paint_bezier          (Dobject *obj);
  619. static Dobject  * d_copy_bezier           (Dobject * obj);
  620. static Dobject  * d_new_bezier            (gint x, gint y);
  621. static void       d_update_bezier         (GdkPoint *pnt);
  622. static void       d_bezier_start          (GdkPoint *pnt, gint shift_down);
  623. static void       d_bezier_end            (GdkPoint *pnt, gint shift_down);
  624.  
  625. static void       new_obj_2edit           (GFigObj *obj);
  626. static Dobject  * d_new_ellipse           (gint x, gint y);
  627. static Dobject  * d_load_ellipse          (FILE *from);
  628. static Dobject  * d_new_arc               (gint x, gint y);
  629. static Dobject  * d_load_arc              (FILE *from);
  630. static gint       load_options            (GFigObj *gfig, FILE *fp);
  631. static gint       gfig_obj_counts         (DAllObjs * objs);
  632.  
  633. static void    gfig_brush_fill_preview_xy (GtkWidget *pw, gint x , gint y);
  634.  
  635.  
  636. /* globals */
  637.  
  638. static gint    gfig_run;
  639. static GdkGC  *gfig_gc;
  640. static GdkGC  *grid_hightlight_drawgc;
  641. static gint    grid_gc_type = GTK_STATE_NORMAL;
  642. static guchar *pv_cache = NULL;
  643. static guchar  preview_row[PREVIEW_SIZE*4];
  644.  
  645. /* Stuff for the preview bit */
  646. static gint    sel_x1, sel_y1, sel_x2, sel_y2;
  647. static gint    sel_width, sel_height;
  648. static gint    preview_width, preview_height;
  649. static gint    has_alpha;
  650. static gdouble scale_x_factor, scale_y_factor;
  651. static gdouble org_scale_x_factor, org_scale_y_factor;
  652.  
  653. MAIN ()
  654.  
  655. static void
  656. query (void)
  657. {
  658.   static GimpParamDef args[] =
  659.   {
  660.     { GIMP_PDB_INT32, "run_mode", "Interactive, non-interactive" },
  661.     { GIMP_PDB_IMAGE, "image", "Input image (unused)" },
  662.     { GIMP_PDB_DRAWABLE, "drawable", "Input drawable" },
  663.     { GIMP_PDB_INT32, "dummy", "dummy" } 
  664.   };
  665.   static gint nargs = sizeof (args) / sizeof (args[0]);
  666.  
  667.   gimp_install_procedure ("plug_in_gfig",
  668.               "Create Geometrical shapes with the Gimp",
  669.               "More here later",
  670.               "Andy Thomas",
  671.               "Andy Thomas",
  672.               "1997",
  673.               N_("<Image>/Filters/Render/Gfig..."),
  674.               "RGB*, GRAY*",
  675.               GIMP_PLUGIN,
  676.               nargs, 0,
  677.               args, NULL);
  678. }
  679.  
  680. static void
  681. run (gchar    *name,
  682.      gint      nparams,
  683.      GimpParam   *param,
  684.      gint     *nreturn_vals,
  685.      GimpParam  **return_vals)
  686. {
  687.   GimpParam * values = g_new (GimpParam, 1);
  688.   GimpDrawable *drawable;
  689.   GimpRunModeType run_mode;
  690.   GimpPDBStatusType status = GIMP_PDB_SUCCESS;
  691.  
  692.   gint pwidth, pheight;
  693.  
  694.   /*kill (getpid (), 19);*/
  695.  
  696.   run_mode = param[0].data.d_int32;
  697.   gfig_image = param[1].data.d_image;
  698.   gfig_drawable = param[2].data.d_drawable;
  699.  
  700.   *nreturn_vals = 1;
  701.   *return_vals = values;
  702.  
  703.   values[0].type = GIMP_PDB_STATUS;
  704.   values[0].data.d_status = status;
  705.  
  706.   gfig_select_drawable = drawable =
  707.     gimp_drawable_get (param[2].data.d_drawable);
  708.  
  709.   tile_width  = gimp_tile_width ();
  710.   tile_height = gimp_tile_height ();
  711.  
  712.   /* TMP Hack - clear any selections */
  713.   gimp_selection_clear (gfig_image);
  714.  
  715.   gimp_drawable_mask_bounds (drawable->id, &sel_x1, &sel_y1, &sel_x2, &sel_y2);
  716.  
  717.   sel_width  = sel_x2 - sel_x1;
  718.   sel_height = sel_y2 - sel_y1;
  719.  
  720.   /* Calculate preview size */
  721.   
  722.   if (sel_width > sel_height)
  723.     {
  724.       pwidth  = MIN (sel_width, PREVIEW_SIZE);
  725.       pheight = sel_height * pwidth / sel_width;
  726.     }
  727.   else
  728.     {
  729.       pheight = MIN (sel_height, PREVIEW_SIZE);
  730.       pwidth  = sel_width * pheight / sel_height;
  731.   }
  732.   
  733.   preview_width  = MAX (pwidth, 2);  /* Min size is 2 */
  734.   preview_height = MAX (pheight, 2); 
  735.  
  736.   org_scale_x_factor = scale_x_factor =
  737.     (gdouble) sel_width / (gdouble) preview_width;
  738.   org_scale_y_factor = scale_y_factor =
  739.     (gdouble) sel_height / (gdouble) preview_height;
  740.   
  741.   switch (run_mode)
  742.     {
  743.     case GIMP_RUN_INTERACTIVE:
  744.       /*gimp_get_data ("plug_in_gfig", &selvals);*/
  745.       INIT_I18N_UI ();
  746.       if (!gfig_dialog ())
  747.     {
  748.       gimp_drawable_detach (drawable);
  749.       return;
  750.     }
  751.       break;
  752.  
  753.     case GIMP_RUN_NONINTERACTIVE:
  754.       status = GIMP_PDB_CALLING_ERROR;
  755.       break;
  756.  
  757.     case GIMP_RUN_WITH_LAST_VALS:
  758.       /*gimp_get_data ("plug_in_gfig", &selvals);*/
  759.       break;
  760.  
  761.     default:
  762.       break;
  763.     }
  764.  
  765.   if (gimp_drawable_is_rgb (drawable->id) ||
  766.       gimp_drawable_is_gray (drawable->id))
  767.     {
  768.       /* Set the tile cache size */
  769.       gimp_tile_cache_ntiles ((drawable->width + gimp_tile_width () - 1) /
  770.                   gimp_tile_width ());
  771.  
  772.       do_gfig ();
  773.  
  774.       if (run_mode != GIMP_RUN_NONINTERACTIVE)
  775.     gimp_displays_flush ();
  776.  
  777. #if 0
  778.       if (run_mode == GIMP_RUN_INTERACTIVE)
  779.     gimp_set_data ("plug_in_gfig", &selvals, sizeof (SelectItVals));
  780. #endif /* 0 */
  781.     }
  782.   else
  783.     {
  784.       status = GIMP_PDB_EXECUTION_ERROR;
  785.     }
  786.  
  787.   values[0].data.d_status = status;
  788.  
  789.   gimp_drawable_detach (drawable);
  790. }
  791.  
  792. /*
  793.  *  Query gimprc for gfig-path, and parse it.
  794.  */
  795.  
  796. static void
  797. plug_in_parse_gfig_path (void)
  798. {
  799.   GList *fail_list = NULL;
  800.   GList *list;
  801.   gchar *gfig_path;
  802.  
  803.   if (gfig_path_list)
  804.     gimp_path_free (gfig_path_list);
  805.   
  806.   gfig_path_list = NULL;
  807.   
  808.   gfig_path = gimp_gimprc_query ("gfig-path");
  809.  
  810.   if (!gfig_path)
  811.     {
  812.       gchar *gimprc = gimp_personal_rc_file ("gimprc");
  813.       gchar *path = gimp_strescape
  814.     ("${gimp_dir}" G_DIR_SEPARATOR_S "gfig"
  815.      G_SEARCHPATH_SEPARATOR_S
  816.      "${gimp_data_dir}" G_DIR_SEPARATOR_S "gfig",
  817.      NULL);
  818.       g_message (_("No gfig-path in gimprc:\n"
  819.            "You need to add an entry like\n"
  820.            "(gfig-path \"%s\")\n"
  821.            "to your %s file."),
  822.            path, gimprc);
  823.       g_free (gimprc);
  824.       g_free (path);
  825.       return;
  826.     }
  827.   
  828.   gfig_path_list = gimp_path_parse (gfig_path, 16, TRUE, &fail_list);
  829.  
  830.   g_free (gfig_path);
  831.  
  832.   if (fail_list)
  833.     {
  834.       GString *err =
  835.     g_string_new (_("gfig-path misconfigured - "
  836.             "the following directories were not found"));
  837.  
  838.       for (list = fail_list; list; list = g_list_next (list))
  839.     {
  840.       g_string_append_c (err, '\n');
  841.       g_string_append (err, (gchar *) list->data);
  842.     }
  843.  
  844.       g_message (err->str);
  845.  
  846.       g_string_free (err, TRUE);
  847.       gimp_path_free (fail_list);
  848.     }
  849. }
  850.  
  851.  
  852. /*
  853.   Translate SPACE to "\\040", etc.
  854.   Taken from gflare plugin
  855.  */
  856. static void
  857. gfig_name_encode (gchar *dest,
  858.           gchar *src)
  859. {
  860.   gint cnt = MAX_LOAD_LINE - 1;
  861.  
  862.   while (*src && cnt--)
  863.     {
  864.       if (iscntrl (*src) || isspace (*src) || *src == '\\')
  865.     {
  866.       sprintf (dest, "\\%03o", *src++);
  867.       dest += 4;
  868.     }
  869.       else
  870.     *dest++ = *src++;
  871.     }
  872.   *dest = '\0';
  873. }
  874.  
  875. /*
  876.   Translate "\\040" to SPACE, etc.
  877.  */
  878. static void
  879. gfig_name_decode (gchar *dest,
  880.           gchar *src)
  881. {
  882.   gint cnt = MAX_LOAD_LINE - 1;
  883.   gint tmp;
  884.  
  885.   while (*src && cnt--)
  886.     {
  887.       if (*src == '\\' && *(src+1) && *(src+2) && *(src+3))
  888.     {
  889.       sscanf (src+1, "%3o", &tmp);
  890.       *dest++ = tmp;
  891.       src += 4;
  892.     }
  893.       else
  894.     *dest++ = *src++;
  895.     }
  896.   *dest = '\0';
  897. }
  898.  
  899.  
  900. /*
  901.  * Load all gfig, which are founded in gfig-path-list, into gfig_list.
  902.  * gfig-path-list must be initialized first. (plug_in_parse_gfig_path ())
  903.  * based on code from Gflare.
  904.  */
  905.  
  906. static gint
  907. gfig_list_pos (GFigObj *gfig)
  908. {
  909.   GFigObj *g;
  910.   gint n;
  911.   GList *tmp;
  912.  
  913.   n = 0;
  914.  
  915.   for (tmp = gfig_list; tmp; tmp = g_list_next (tmp)) 
  916.     {
  917.       g = tmp->data;
  918.       
  919.       if (strcmp (gfig->draw_name, g->draw_name) <= 0)
  920.     break;
  921.  
  922.       n++;
  923.     }
  924.  
  925.   return n;
  926. }
  927.  
  928. static gint
  929. gfig_list_insert (GFigObj *gfig)
  930. {
  931.   gint n;
  932.  
  933.   /*
  934.    *    Insert gfigs in alphabetical order
  935.    */
  936.  
  937.   n = gfig_list_pos (gfig);
  938.  
  939.   gfig_list = g_list_insert (gfig_list, gfig, n);
  940.  
  941. #ifdef DEBUG
  942.   printf ("gfig_list_insert %s => %d\n", gfig->draw_name, n);
  943. #endif /* DEBUG */
  944.  
  945.   return n;
  946. }
  947.  
  948. static void
  949. gfig_free (GFigObj *gfig)
  950. {
  951.   g_assert (gfig != NULL);
  952.  
  953.   if (gfig->obj_list)
  954.     free_all_objs (gfig->obj_list);
  955.  
  956.   g_free (gfig->name);
  957.   g_free (gfig->filename);
  958.   g_free (gfig->draw_name);
  959.  
  960.   g_free (gfig);
  961. }
  962.  
  963. static void
  964. gfig_free_everything (GFigObj *gfig)
  965. {
  966.   g_assert (gfig != NULL);
  967.  
  968.   if (gfig->filename)
  969.     {
  970. #ifdef DEBUG
  971.       printf ("Removing filename '%s'\n", gfig->filename);
  972. #endif /* DEBUG */
  973.       remove (gfig->filename);
  974.     }
  975.  
  976.   gfig_free (gfig);
  977. }
  978.  
  979. static void
  980. gfig_list_free_all (void)
  981. {
  982.   GList   *list;
  983.   GFigObj *gfig;
  984.  
  985.   for (list = gfig_list; list; list = g_list_next (list))
  986.     {
  987.       gfig = (GFigObj *) list->data;
  988.       gfig_free (gfig);
  989.     }
  990.  
  991.   g_list_free (gfig_list);
  992.   gfig_list = NULL;
  993. }
  994.  
  995.  
  996. static void
  997. gfig_list_load_all (GList *plist)
  998. {
  999.   GFigObj *gfig;
  1000.   GList   *list;
  1001.   gchar      *path;
  1002.   gchar      *filename;
  1003.   DIR      *dir;
  1004.   struct dirent *dir_ent;
  1005.   struct stat    filestat;
  1006.   gint err;
  1007.  
  1008.   /*  Make sure to clear any existing gfigs  */
  1009.   current_obj = pic_obj = NULL;
  1010.   gfig_list_free_all ();
  1011.  
  1012.   list = plist;
  1013.   while (list)
  1014.     {
  1015.       path = list->data;
  1016.       list = list->next;
  1017.  
  1018.       /* Open directory */
  1019.       dir = opendir (path);
  1020.  
  1021.       if (!dir)
  1022.     g_warning ("Error reading GFig directory \"%s\"", path);
  1023.       else
  1024.     {
  1025.       while ((dir_ent = readdir (dir)))
  1026.         {
  1027.           filename = g_malloc (strlen (path) + strlen (dir_ent->d_name) + 1);
  1028.  
  1029.           sprintf (filename, "%s%s", path, dir_ent->d_name);
  1030.  
  1031.           /* Check the file and see that it is not a sub-directory */
  1032.           err = stat (filename, &filestat);
  1033.  
  1034.           if (!err && S_ISREG (filestat.st_mode))
  1035.         {
  1036.           gfig = gfig_load (filename, dir_ent->d_name);
  1037.           
  1038.           if (gfig)
  1039.             {
  1040.               /* Read only ?*/
  1041.               if (access (filename, W_OK))
  1042.             gfig->obj_status |= GFIG_READONLY;
  1043.  
  1044.               gfig_list_insert (gfig);
  1045.             }
  1046.         }
  1047.  
  1048.           g_free (filename);
  1049.         } /* while */
  1050.       closedir (dir);
  1051.     } /* else */
  1052.     }
  1053.  
  1054.   if (!gfig_list)
  1055.     {
  1056.       /* lets have at least one! */
  1057.       gfig = gfig_new ();
  1058.       gfig->draw_name = g_strdup (_("First Gfig"));
  1059.       gfig_list_insert (gfig);
  1060.     }
  1061.   pic_obj = current_obj = gfig_list->data;  /* set to first entry */
  1062.  
  1063. }
  1064.  
  1065. static GFigObj *
  1066. gfig_new (void)
  1067. {
  1068.   GFigObj * new;
  1069.  
  1070.   new = g_new0 (GFigObj, 1);
  1071.  
  1072.   return new;
  1073. }
  1074.  
  1075. static void
  1076. gfig_load_objs (GFigObj *gfig,
  1077.         gint     load_count,
  1078.         FILE    *fp)
  1079. {
  1080.   Dobject *obj;
  1081.   gchar load_buf[MAX_LOAD_LINE];
  1082.  
  1083.   /* Loading object */
  1084.   /*kill (getpid (), 19);*/
  1085.   /* Read first line */
  1086.   while (load_count-- > 0)
  1087.     {
  1088.       obj = NULL;
  1089.       get_line (load_buf, MAX_LOAD_LINE, fp, 0);
  1090.  
  1091.       if (!strcmp (load_buf, "<LINE>"))
  1092.     {
  1093.       obj = d_load_line (fp);
  1094.     }
  1095.       else if (!strcmp (load_buf, "<CIRCLE>"))
  1096.     {
  1097.       obj = d_load_circle (fp);
  1098.     }
  1099.       else if (!strcmp (load_buf, "<ELLIPSE>"))
  1100.     {
  1101.       obj = d_load_ellipse (fp);
  1102.     }
  1103.       else if (!strcmp (load_buf, "<POLY>"))
  1104.     {
  1105.       obj = d_load_poly (fp);
  1106.     }
  1107.       else if (!strcmp (load_buf, "<STAR>"))
  1108.     {
  1109.       obj = d_load_star (fp);
  1110.     }
  1111.       else if (!strcmp (load_buf, "<SPIRAL>"))
  1112.     {
  1113.       obj = d_load_spiral (fp);
  1114.     }
  1115.       else if (!strcmp (load_buf, "<BEZIER>"))
  1116.     {
  1117.       obj = d_load_bezier (fp);
  1118.     }
  1119.       else if (!strcmp (load_buf, "<ARC>"))
  1120.     {
  1121.       obj = d_load_arc (fp);
  1122.     }
  1123.       else
  1124.     {
  1125.       g_warning ("Unknown obj type file %s line %d\n", gfig->filename, line_no);
  1126.     }
  1127.       
  1128.       if (obj)
  1129.     {
  1130.       add_to_all_obj (gfig, obj);
  1131.     }
  1132.     }
  1133. }
  1134.  
  1135. static GFigObj *
  1136. gfig_load (gchar *filename, gchar *name)
  1137. {
  1138.   GFigObj * gfig;
  1139.   FILE * fp;
  1140.   gchar load_buf[MAX_LOAD_LINE];
  1141.   gchar str_buf[MAX_LOAD_LINE];
  1142.   gint chk_count;
  1143.   gint load_count = 0;
  1144.   
  1145.   g_assert (filename != NULL);
  1146.  
  1147. #ifdef DEBUG
  1148.   printf ("Loading %s (%s)\n", filename, name);
  1149. #endif /* DEBUG */
  1150.  
  1151.   fp = fopen (filename, "r");
  1152.   if (!fp)
  1153.     {
  1154.       g_warning ("Error opening: %s", filename);
  1155.       return NULL;
  1156.     }
  1157.  
  1158.   gfig = gfig_new ();
  1159.  
  1160.   gfig->name = g_strdup (name);
  1161.   gfig->filename = g_strdup (filename);
  1162.  
  1163.  
  1164.   /* HEADER
  1165.    * draw_name
  1166.    * version
  1167.    * obj_list
  1168.    */
  1169.  
  1170.   get_line (load_buf, MAX_LOAD_LINE, fp, 1);
  1171.  
  1172.   if (strncmp (GFIG_HEADER, load_buf, strlen (load_buf)))
  1173.     {
  1174.       g_message ("File '%s' is not a gfig file", gfig->filename);
  1175.       return NULL;
  1176.     }
  1177.   
  1178.   get_line (load_buf, MAX_LOAD_LINE, fp, 0);
  1179.   sscanf (load_buf, "Name: %100s", str_buf);
  1180.   gfig_name_decode (load_buf, str_buf);
  1181.   gfig->draw_name = g_strdup (load_buf);
  1182.  
  1183.   get_line (load_buf, MAX_LOAD_LINE, fp, 0);
  1184.   sscanf (load_buf, "Version: %f", &gfig->version);
  1185.  
  1186.   get_line (load_buf, MAX_LOAD_LINE, fp, 0);
  1187.   sscanf (load_buf, "ObjCount: %d", &load_count);
  1188.  
  1189.   if (load_options (gfig, fp))
  1190.     {
  1191.       g_message ("File '%s' corrupt file - Line %d Option section incorrect",
  1192.          filename, line_no);
  1193.       return NULL;
  1194.     }
  1195.  
  1196.   /*return (NULL);*/
  1197.  
  1198.   gfig_load_objs (gfig, load_count, fp);
  1199.  
  1200.   /* Check count ? */
  1201.   
  1202.   chk_count = gfig_obj_counts (gfig->obj_list);
  1203.  
  1204.   if (chk_count != load_count)
  1205.     {
  1206.       g_message ("File '%s' corrupt file - Line %d Object count to small",
  1207.          filename, line_no);
  1208.       return NULL;
  1209.     }
  1210.  
  1211.   fclose (fp);
  1212.  
  1213.   if (!pic_obj)
  1214.     pic_obj = gfig;
  1215.  
  1216.   gfig->obj_status = GFIG_OK;
  1217.  
  1218.   return gfig;
  1219. }
  1220.  
  1221. static void
  1222. save_options (FILE *fp)
  1223. {
  1224.   /* Save options */
  1225.   fprintf (fp, "<OPTIONS>\n");
  1226.   fprintf (fp, "GridSpacing: %d\n", selvals.opts.gridspacing);
  1227.   if (selvals.opts.gridtype == RECT_GRID)
  1228.     fprintf (fp, "GridType: RECT_GRID\n");
  1229.   else if (selvals.opts.gridtype == POLAR_GRID)
  1230.     fprintf (fp, "GridType: POLAR_GRID\n");
  1231.   else if (selvals.opts.gridtype == ISO_GRID)
  1232.     fprintf (fp, "GridType: ISO_GRID\n");
  1233.   else fprintf (fp, "GridType: RECT_GRID\n"); /* If in doubt, default to RECT_GRID */
  1234.   fprintf (fp, "DrawGrid: %s\n", (selvals.opts.drawgrid)?"TRUE":"FALSE");
  1235.   fprintf (fp, "Snap2Grid: %s\n", (selvals.opts.snap2grid)?"TRUE":"FALSE");
  1236.   fprintf (fp, "LockOnGrid: %s\n", (selvals.opts.lockongrid)?"TRUE":"FALSE");
  1237.   /*  fprintf (fp, "ShowImage: %s\n", (selvals.opts.showimage)?"TRUE":"FALSE");*/
  1238.   fprintf (fp, "ShowControl: %s\n", (selvals.opts.showcontrol)?"TRUE":"FALSE");
  1239.   fprintf (fp, "</OPTIONS>\n");
  1240. }
  1241.  
  1242. static gint
  1243. load_bool (gchar *opt_buf,
  1244.        gint  *toset)
  1245. {
  1246.   if (!strcmp (opt_buf, "TRUE"))
  1247.     *toset = 1;
  1248.   else if (!strcmp (opt_buf, "FALSE"))
  1249.     *toset = 0;
  1250.   else
  1251.     return (-1);
  1252.  
  1253.   return (0);
  1254. }
  1255.  
  1256. static void
  1257. update_options (GFigObj *old_obj)
  1258. {
  1259.   /* Save old vals */
  1260.   if (selvals.opts.gridspacing != old_obj->opts.gridspacing)
  1261.     {
  1262.       old_obj->opts.gridspacing = selvals.opts.gridspacing;
  1263.     }
  1264.   if (selvals.opts.gridtype != old_obj->opts.gridtype)
  1265.     {
  1266.       old_obj->opts.gridtype = selvals.opts.gridtype;
  1267.     }
  1268.   if (selvals.opts.drawgrid != old_obj->opts.drawgrid)
  1269.     {
  1270.       old_obj->opts.drawgrid = selvals.opts.drawgrid;
  1271.     }
  1272.   if (selvals.opts.snap2grid != old_obj->opts.snap2grid)
  1273.     {
  1274.       old_obj->opts.snap2grid = selvals.opts.snap2grid;
  1275.     }
  1276.   if (selvals.opts.lockongrid != old_obj->opts.lockongrid)
  1277.     {
  1278.       old_obj->opts.lockongrid = selvals.opts.lockongrid;
  1279.     }
  1280.   if (selvals.opts.showcontrol != old_obj->opts.showcontrol)
  1281.     {
  1282.       old_obj->opts.showcontrol = selvals.opts.showcontrol;
  1283.     }
  1284.  
  1285.   /* New vals */
  1286.   if (selvals.opts.gridspacing != current_obj->opts.gridspacing)
  1287.     {
  1288.       gtk_adjustment_set_value
  1289.     (GTK_ADJUSTMENT (gfig_opt_widget.gridspacing),
  1290.      current_obj->opts.gridspacing);
  1291.     }
  1292.   if (selvals.opts.drawgrid != current_obj->opts.drawgrid)
  1293.     {
  1294.       gtk_toggle_button_set_active
  1295.     (GTK_TOGGLE_BUTTON (gfig_opt_widget.drawgrid),
  1296.      current_obj->opts.drawgrid);
  1297.     }
  1298.   if (selvals.opts.snap2grid != current_obj->opts.snap2grid)
  1299.     {
  1300.       gtk_toggle_button_set_active
  1301.     (GTK_TOGGLE_BUTTON (gfig_opt_widget.snap2grid),
  1302.      current_obj->opts.snap2grid);
  1303.     }
  1304.   if (selvals.opts.lockongrid != current_obj->opts.lockongrid)
  1305.     {
  1306.       gtk_toggle_button_set_active
  1307.     (GTK_TOGGLE_BUTTON (gfig_opt_widget.lockongrid),
  1308.      current_obj->opts.lockongrid);
  1309.     }
  1310.   if (selvals.opts.showcontrol != current_obj->opts.showcontrol)
  1311.     {
  1312.       gtk_toggle_button_set_active
  1313.     (GTK_TOGGLE_BUTTON (gfig_opt_widget.showcontrol),
  1314.      current_obj->opts.showcontrol);
  1315.     }
  1316.   if (selvals.opts.gridtype != current_obj->opts.gridtype)
  1317.     {
  1318.       gtk_option_menu_set_history
  1319.     (GTK_OPTION_MENU (gfig_opt_widget.gridtypemenu),
  1320.      current_obj->opts.gridtype); 
  1321.  
  1322.       gridtype_menu_callback
  1323.     (gtk_menu_get_active
  1324.      (GTK_MENU (gtk_option_menu_get_menu
  1325.             (GTK_OPTION_MENU (gfig_opt_widget.gridtypemenu)))),
  1326.      (gpointer) GRID_TYPE_MENU);
  1327. #ifdef DEBUG
  1328.       printf ("Gridtype set in options to ");
  1329.       if (current_obj->opts.gridtype == RECT_GRID)
  1330.     printf ("RECT_GRID\n");
  1331.       else if (current_obj->opts.gridtype == POLAR_GRID)
  1332.     printf ("POLAR_GRID\n");
  1333.       else if (current_obj->opts.gridtype == ISO_GRID)
  1334.     printf ("ISO_GRID\n");
  1335.       else printf ("NONE\n");
  1336. #endif /* DEBUG */
  1337.     }
  1338. }
  1339.  
  1340. static gint
  1341. load_options (GFigObj *gfig,
  1342.           FILE    *fp)
  1343. {
  1344.   gchar load_buf[MAX_LOAD_LINE];
  1345.   gchar str_buf[MAX_LOAD_LINE];
  1346.   gchar opt_buf[MAX_LOAD_LINE];
  1347.  
  1348.   get_line (load_buf, MAX_LOAD_LINE, fp, 0);
  1349.  
  1350. #ifdef DEBUG
  1351.   printf ("load '%s'\n", load_buf);
  1352. #endif /* DEBUG */
  1353.  
  1354.   if (strcmp (load_buf, "<OPTIONS>"))
  1355.     return (-1);
  1356.   
  1357.   get_line (load_buf, MAX_LOAD_LINE, fp, 0);
  1358.  
  1359. #ifdef DEBUG
  1360.   printf ("opt line '%s'\n", load_buf);
  1361. #endif /* DEBUG */
  1362.  
  1363.   while (strcmp (load_buf, "</OPTIONS>"))
  1364.     {
  1365.       /* Get option name */
  1366. #ifdef DEBUG
  1367.       printf ("num = %d\n", sscanf (load_buf, "%s %s", str_buf, opt_buf));
  1368.  
  1369.       printf ("option %s val %s\n", str_buf, opt_buf);
  1370. #else
  1371.       sscanf (load_buf, "%s %s", str_buf, opt_buf);
  1372. #endif /* DEBUG */
  1373.  
  1374.       if (!strcmp (str_buf, "GridSpacing:"))
  1375.     {
  1376.       /* Value is decimal */
  1377.       int sp = 0;
  1378.       sp = atoi (opt_buf);
  1379.       if (sp <= 0)
  1380.         return (-1);
  1381.       gfig->opts.gridspacing = sp;
  1382.     }
  1383.       else if (!strcmp (str_buf, "DrawGrid:"))
  1384.     {
  1385.       /* Value is bool */
  1386.       if (load_bool (opt_buf, &gfig->opts.drawgrid))
  1387.         return (-1);
  1388.     }
  1389.       else if (!strcmp (str_buf, "Snap2Grid:"))
  1390.     {
  1391.       /* Value is bool */
  1392.       if (load_bool (opt_buf, &gfig->opts.snap2grid))
  1393.         return (-1);
  1394.     }
  1395.       else if (!strcmp (str_buf, "LockOnGrid:"))
  1396.     {
  1397.       /* Value is bool */
  1398.       if (load_bool (opt_buf, &gfig->opts.lockongrid))
  1399.         return (-1);
  1400.     }
  1401.       else if (!strcmp (str_buf, "ShowControl:"))
  1402.     {
  1403.       /* Value is bool */
  1404.       if (load_bool (opt_buf, &gfig->opts.showcontrol))
  1405.         return (-1);
  1406.     }
  1407.       else if (!strcmp (str_buf, "GridType:"))
  1408.     {
  1409.       /* Value is string */
  1410.       if (!strcmp (opt_buf, "RECT_GRID"))
  1411.         gfig->opts.gridtype = RECT_GRID;
  1412.       else if (!strcmp (opt_buf, "POLAR_GRID"))
  1413.         gfig->opts.gridtype = POLAR_GRID;
  1414.       else if (!strcmp (opt_buf, "ISO_GRID"))
  1415.         gfig->opts.gridtype = ISO_GRID;
  1416.       else
  1417.         return (-1);
  1418.     }
  1419.  
  1420.       get_line (load_buf, MAX_LOAD_LINE, fp, 0);
  1421. #ifdef DEBUG
  1422.       printf ("opt line '%s'\n", load_buf);
  1423. #endif /* DEBUG */
  1424.     }  
  1425.   return (0);
  1426. }
  1427.  
  1428. static gint
  1429. gfig_obj_counts (DAllObjs *objs)
  1430. {
  1431.   gint count = 0;
  1432.  
  1433.   while (objs)
  1434.     {
  1435.       count++;
  1436.       objs = objs->next;
  1437.     }
  1438.  
  1439.   return (count);
  1440. }
  1441.  
  1442. static void
  1443. gfig_save_callbk (void)
  1444. {
  1445.   FILE *fp;
  1446.   DAllObjs * objs;
  1447.   gint count = 0;
  1448.   gchar *savename;
  1449.   gchar *message;
  1450.   gchar conv_buf[MAX_LOAD_LINE*3 +1];
  1451.  
  1452.   savename = current_obj->filename;
  1453.  
  1454.   fp = fopen (savename, "w+");
  1455.   
  1456.   if (!fp)
  1457.     {
  1458.       message = g_strconcat (_("Error opening: %s"), 
  1459.                  "\n",
  1460.                  _("Could not save."), 
  1461.                  savename);
  1462.       g_message (message);
  1463.       g_free (message);
  1464.       return;
  1465.     }
  1466.  
  1467.   /* Write header out */
  1468.   fputs (GFIG_HEADER, fp);
  1469.   
  1470.   /* 
  1471.    * draw_name 
  1472.    * version
  1473.    * obj_list
  1474.    *
  1475.    */
  1476.  
  1477.   gfig_name_encode (conv_buf, current_obj->draw_name);
  1478.   fprintf (fp, "Name: %s\n", conv_buf);
  1479.   fprintf (fp, "Version: %f\n", current_obj->version);
  1480.   objs = current_obj->obj_list;
  1481.  
  1482.   count = gfig_obj_counts (objs);
  1483.  
  1484.   fprintf (fp, "ObjCount: %d\n", count);
  1485.  
  1486.   save_options (fp);
  1487.  
  1488.   objs = current_obj->obj_list;
  1489.   while (objs)
  1490.     {
  1491.       objs->obj->savefunc (objs->obj, fp);
  1492.       objs = objs->next;
  1493.     }
  1494.  
  1495.   if (ferror (fp))
  1496.     g_message ("Failed to write file\n");
  1497.   else
  1498.     {
  1499.       gfig_obj_modified (current_obj, GFIG_OK);
  1500.       current_obj->obj_status &= ~(GFIG_MODIFIED | GFIG_READONLY);
  1501.     }
  1502.  
  1503.   fclose (fp);
  1504.  
  1505.   gfig_update_stat_labels ();
  1506. }
  1507.  
  1508. static void
  1509. file_selection_ok (GtkWidget        *w,
  1510.            GtkFileSelection *fs,
  1511.            gpointer data)
  1512. {
  1513.   gchar *filenamebuf;
  1514.   struct stat filestat;
  1515.   gint    err;
  1516.   GFigObj *obj = (GFigObj *)gtk_object_get_user_data (GTK_OBJECT (fs));
  1517.   GFigObj *real_current;
  1518.  
  1519.   filenamebuf = gtk_file_selection_get_filename (GTK_FILE_SELECTION (fs));
  1520. #ifdef DEBUG
  1521.   g_print ("name selected '%s'\n", filenamebuf);
  1522. #endif /* DEBUG */
  1523.  
  1524.   /* Get the name */
  1525.   if (strlen (filenamebuf) == 0)
  1526.     {
  1527.       g_message ("Save: No filename given");
  1528.       return;
  1529.     }
  1530.  
  1531.   /* Check if directory exists */
  1532.   err = stat (filenamebuf, &filestat);
  1533.   
  1534.   if (!err && S_ISDIR (filestat.st_mode))
  1535.     {
  1536.       g_message ("Save: Can't save to a directory");
  1537.       return;
  1538.     }
  1539.   
  1540.   obj->filename = g_strdup (filenamebuf);
  1541.  
  1542.   real_current = current_obj;
  1543.   current_obj = obj;
  1544.   gfig_save_callbk ();
  1545.   current_obj = current_obj;
  1546.  
  1547.   gtk_widget_destroy (GTK_WIDGET (fs));
  1548.  
  1549. }
  1550.  
  1551. static void
  1552. create_file_selection (GFigObj *obj,
  1553.                gchar   *tpath)
  1554. {
  1555.   static GtkWidget *window = NULL;
  1556.  
  1557.   if (!window)
  1558.     {
  1559.       window = gtk_file_selection_new ("Save gfig drawing");
  1560.       gtk_window_set_position (GTK_WINDOW (window), GTK_WIN_POS_MOUSE);
  1561.  
  1562.       gtk_signal_connect (GTK_OBJECT (window), "destroy",
  1563.               GTK_SIGNAL_FUNC (gtk_widget_destroyed),
  1564.               &window);
  1565.  
  1566.       gtk_object_set_user_data (GTK_OBJECT (window), obj);
  1567.       gtk_signal_connect (GTK_OBJECT (GTK_FILE_SELECTION (window)->ok_button),
  1568.               "clicked",
  1569.               GTK_SIGNAL_FUNC (file_selection_ok),
  1570.               (gpointer) window);
  1571.       gtk_signal_connect_object (GTK_OBJECT (GTK_FILE_SELECTION (window)->cancel_button),
  1572.                  "clicked",
  1573.                  GTK_SIGNAL_FUNC (gtk_widget_destroy),
  1574.                  GTK_OBJECT (window));
  1575.     }
  1576.  
  1577.   if (tpath)
  1578.     {
  1579.       gtk_file_selection_set_filename (GTK_FILE_SELECTION (window), tpath);
  1580.     }
  1581.   else if (gfig_path_list)
  1582.     {
  1583.       gchar *dir;
  1584.  
  1585.       dir = gimp_path_get_user_writable_dir (gfig_path_list);
  1586.  
  1587.       if (!dir)
  1588.     dir = g_strdup (gimp_directory ());
  1589.  
  1590.       gtk_file_selection_set_filename (GTK_FILE_SELECTION (window), dir);
  1591.  
  1592.       g_free (dir);
  1593.     }
  1594.   else
  1595.     {
  1596.       gchar *tmp = g_get_tmp_dir ();
  1597.  
  1598.       gtk_file_selection_set_filename (GTK_FILE_SELECTION (window), tmp);
  1599.       g_free (tmp);
  1600.     }
  1601.  
  1602.   if (!GTK_WIDGET_VISIBLE (window))
  1603.     gtk_widget_show (window);
  1604. }
  1605.  
  1606. static void
  1607. gfig_save (void)
  1608. {
  1609.   /* Save the current object */
  1610.   if (!current_obj->filename)
  1611.    {
  1612.      create_file_selection (current_obj, NULL);
  1613.      return;
  1614.    }
  1615.   gfig_save_callbk ();
  1616. }
  1617.  
  1618. /* HACK WARNING */
  1619. void * xxx;
  1620. void * yyy;
  1621.  
  1622. /* Cache the preview image - updates are a lot faster. */
  1623. /* The preview_cache will contain the small image */
  1624.  
  1625. static void
  1626. cache_preview (void)
  1627. {
  1628.   GimpPixelRgn src_rgn;
  1629.   int y, x;
  1630.   guchar *src_rows;
  1631.   guchar *p;
  1632.   int isgrey = 0;
  1633.  
  1634.   gimp_pixel_rgn_init (&src_rgn, gfig_select_drawable,
  1635.                sel_x1, sel_y1, sel_width, sel_height, FALSE, FALSE);
  1636.  
  1637.   src_rows = g_new (guchar , sel_width * 4); 
  1638.   p = pv_cache = g_new (guchar , preview_width * preview_height * 4);
  1639.  
  1640.   real_img_bpp = gimp_drawable_bpp (gfig_select_drawable->id);
  1641.  
  1642.   has_alpha = gimp_drawable_has_alpha (gfig_select_drawable->id);
  1643.  
  1644.   if (real_img_bpp < 3)
  1645.     {
  1646.       img_bpp = 3 + has_alpha;
  1647.     }
  1648.   else
  1649.     {
  1650.       img_bpp = real_img_bpp;
  1651.     }
  1652.  
  1653.   switch (gimp_drawable_type (gfig_select_drawable->id))
  1654.     {
  1655.     case GIMP_GRAYA_IMAGE:
  1656.     case GIMP_GRAY_IMAGE:
  1657.       isgrey = 1;
  1658.     default:
  1659.       break;
  1660.     }
  1661.  
  1662.   /*memset (p,-1, preview_width*preview_height*4); return;*/
  1663.  
  1664.   for (y = 0; y < preview_height; y++)
  1665.     {
  1666.       gimp_pixel_rgn_get_row (&src_rgn,
  1667.                   src_rows,
  1668.                   sel_x1,
  1669.                   sel_y1 + (y*sel_height)/preview_height,
  1670.                   sel_width);
  1671.  
  1672.     for (x = 0; x < (preview_width); x ++)
  1673.       {
  1674.     /* Get the pixels of each col */
  1675.     int i;
  1676.     for (i = 0 ; i < 3; i++)
  1677.       p[x*img_bpp+i] =
  1678.         src_rows[((x*sel_width)/preview_width)*src_rgn.bpp +((isgrey)?0:i)]; 
  1679.     if (has_alpha)
  1680.       p[x*img_bpp+3] =
  1681.         src_rows[((x*sel_width)/preview_width)*src_rgn.bpp + ((isgrey)?1:3)];
  1682.       }
  1683.     p += (preview_width*img_bpp);
  1684.     }
  1685.   g_free (src_rows);
  1686. }
  1687.  
  1688. static void
  1689. refill_cache (void)
  1690. {
  1691.   GdkCursorType ctype1 = GDK_WATCH;
  1692.   GdkCursorType ctype2 = GDK_TOP_LEFT_ARROW;
  1693.   static GdkCursor *preview_cursor1;  
  1694.   static GdkCursor *preview_cursor2;  
  1695.  
  1696.   if (!preview_cursor1)
  1697.     preview_cursor1 = gdk_cursor_new (ctype1);
  1698.  
  1699.   if (!preview_cursor2)
  1700.     preview_cursor2 = gdk_cursor_new (ctype2);
  1701.  
  1702.   gdk_window_set_cursor
  1703.     (gtk_widget_get_toplevel (GTK_WIDGET (gfig_preview))->window,
  1704.      preview_cursor1);
  1705.  
  1706.   gdk_window_set_cursor (gfig_preview->window, preview_cursor1);
  1707.  
  1708.   gdk_flush ();
  1709.  
  1710.   cache_preview ();
  1711.  
  1712.   gdk_window_set_cursor
  1713.     (gtk_widget_get_toplevel (GTK_WIDGET (gfig_preview))->window,
  1714.      preview_cursor2);
  1715.  
  1716.   toggle_obj_type (NULL, (gpointer) selvals.otype);
  1717. }
  1718.  
  1719. static GtkWidget *
  1720. gfig_list_item_new_with_label_and_pixmap (GFigObj   *obj,
  1721.                       gchar     *label,
  1722.                       GtkWidget *pix_widget)
  1723. {
  1724.   GtkWidget *list_item;
  1725.   GtkWidget *label_widget;
  1726.   GtkWidget *hbox;
  1727.  
  1728.   list_item = gtk_list_item_new ();
  1729.  
  1730.   hbox = gtk_hbox_new (FALSE, 1);
  1731.   gtk_container_add (GTK_CONTAINER (list_item), hbox);
  1732.   gtk_widget_show (hbox);
  1733.  
  1734.   gtk_box_pack_start (GTK_BOX (hbox), pix_widget, FALSE, FALSE, 0);
  1735.  
  1736.   label_widget = gtk_label_new (label);
  1737.   gtk_misc_set_alignment (GTK_MISC (label_widget), 0.0, 0.5);
  1738.   gtk_container_add (GTK_CONTAINER (hbox), label_widget);
  1739.  
  1740.   gtk_widget_show (obj->label_widget = label_widget);
  1741.   gtk_widget_show (obj->pixmap_widget = pix_widget);
  1742.   gtk_widget_show (obj->list_item = list_item);
  1743.  
  1744.   return list_item;
  1745. }
  1746.  
  1747. static void
  1748. gfig_obj_modified (GFigObj *obj,
  1749.            gint     stat_type)
  1750. {
  1751.   g_assert (obj != NULL);
  1752.  
  1753.   if (obj->obj_status == stat_type)
  1754.     return;
  1755.  
  1756.   /* Set the new one up */
  1757.   if (stat_type == GFIG_MODIFIED)
  1758.     gimp_pixmap_set (GIMP_PIXMAP (obj->pixmap_widget), Floppy6_xpm);
  1759.   else 
  1760.     gimp_pixmap_set (GIMP_PIXMAP (obj->pixmap_widget), blank_xpm);
  1761. }
  1762.  
  1763. static gint
  1764. select_button_press (GtkWidget      *widget,
  1765.              GdkEventButton *event,
  1766.              gpointer        data)
  1767. {
  1768.   gint type = (gint) data;
  1769.   gint count = 0;
  1770.   DAllObjs * objs;
  1771.  
  1772.   if (current_obj)
  1773.     {
  1774.       objs = current_obj->obj_list;
  1775.  
  1776.       while (objs)
  1777.     {
  1778.       objs = objs->next;
  1779.       count++;
  1780.     }
  1781.     }
  1782.  
  1783.   switch (type)
  1784.     {
  1785.     case OBJ_SELECT_LT:
  1786.       obj_show_single--;
  1787.       if (obj_show_single < 0)
  1788.     obj_show_single = count - 1;
  1789.       break;
  1790.     case OBJ_SELECT_GT:
  1791.       obj_show_single++;
  1792.       if (obj_show_single >= count)
  1793.     obj_show_single = 0;
  1794.       break;
  1795.     case OBJ_SELECT_EQ:
  1796.       obj_show_single = -1; /* Reset to show all */
  1797.       break;
  1798.     default:
  1799.       break;
  1800.     }
  1801.  
  1802.   draw_grid_clear (widget, data);
  1803.  
  1804.   return FALSE;
  1805. }
  1806.  
  1807. static GtkWidget *
  1808. obj_select_buttons (void)
  1809. {
  1810.   GtkWidget *button;
  1811.   GtkWidget *hbox, *vbox;
  1812.  
  1813.   vbox = gtk_vbox_new (FALSE, 0);
  1814.   gtk_widget_show (vbox);
  1815.  
  1816.   hbox = gtk_hbox_new (FALSE, 0);
  1817.   gtk_box_pack_start (GTK_BOX (vbox), hbox, TRUE, TRUE, 0);
  1818.   gtk_widget_show (hbox);
  1819.  
  1820.   button = gtk_button_new_with_label ("<");
  1821.   gtk_box_pack_start (GTK_BOX (hbox), button, TRUE, TRUE, 0);
  1822.   gtk_signal_connect (GTK_OBJECT (button), "button_press_event",
  1823.               GTK_SIGNAL_FUNC (select_button_press),
  1824.               (gpointer) OBJ_SELECT_LT);
  1825.   gtk_widget_show (button);
  1826.  
  1827.   button = gtk_button_new_with_label (">");
  1828.   gtk_box_pack_start (GTK_BOX (hbox), button, TRUE, TRUE, 0);
  1829.   gtk_signal_connect (GTK_OBJECT (button), "button_press_event",
  1830.               GTK_SIGNAL_FUNC (select_button_press),
  1831.               (gpointer) OBJ_SELECT_GT);
  1832.   gtk_widget_show (button);
  1833.  
  1834.   button = gtk_button_new_with_label ("==");
  1835.   gtk_box_pack_start (GTK_BOX (vbox), button, TRUE, TRUE, 0);
  1836.   gtk_signal_connect (GTK_OBJECT (button), "button_press_event",
  1837.               GTK_SIGNAL_FUNC (select_button_press),
  1838.               (gpointer) OBJ_SELECT_EQ);
  1839.   gtk_widget_show (button);
  1840.  
  1841.   return vbox;
  1842. }
  1843.  
  1844. static GtkWidget *
  1845. but_with_pix (gchar  **pixdata,
  1846.           GSList **group,
  1847.           gint     baction)
  1848. {
  1849.   GtkWidget *button;
  1850.   GtkWidget *alignment;
  1851.   GtkWidget *pixmap_widget;
  1852.  
  1853.   button = gtk_radio_button_new (*group);
  1854.   gtk_toggle_button_set_mode (GTK_TOGGLE_BUTTON (button), FALSE); 
  1855.   gtk_signal_connect (GTK_OBJECT (button), "toggled",
  1856.               GTK_SIGNAL_FUNC (toggle_obj_type),
  1857.               (gpointer) baction);
  1858.   gtk_widget_show (button);
  1859.  
  1860.   *group = gtk_radio_button_group (GTK_RADIO_BUTTON (button));
  1861.  
  1862.   alignment = gtk_alignment_new (0.5, 0.5, 0.0, 0.0);
  1863.   gtk_container_add (GTK_CONTAINER (button), alignment);
  1864.   gtk_widget_show (alignment);
  1865.  
  1866.   pixmap_widget = gimp_pixmap_new (pixdata);
  1867.   gtk_container_add (GTK_CONTAINER (alignment), pixmap_widget);
  1868.   gtk_widget_show (pixmap_widget);
  1869.  
  1870.   return button;
  1871. }
  1872.  
  1873. static GtkWidget *
  1874. small_preview (GtkWidget *list)
  1875. {
  1876.   GtkWidget *label;
  1877.   GtkWidget *frame;
  1878.   GtkWidget *button;
  1879.   GtkWidget *vbox;
  1880.   gint y;
  1881.  
  1882.   vbox = gtk_vbox_new (FALSE, 0);
  1883.   gtk_widget_show (vbox);
  1884.  
  1885.   label = gtk_label_new (_("Prev"));
  1886.   gtk_container_add (GTK_CONTAINER (vbox), label);
  1887.   gtk_widget_show (label);
  1888.  
  1889.   frame = gtk_frame_new (NULL);
  1890.   gtk_frame_set_shadow_type (GTK_FRAME (frame), GTK_SHADOW_IN);
  1891.   gtk_container_add (GTK_CONTAINER (vbox), frame);
  1892.   gtk_widget_show (frame);
  1893.  
  1894.   pic_preview = gtk_preview_new (GTK_PREVIEW_COLOR);
  1895.   gtk_preview_size (GTK_PREVIEW (pic_preview),
  1896.             SMALL_PREVIEW_SZ, SMALL_PREVIEW_SZ);
  1897.   gtk_container_add (GTK_CONTAINER (frame), pic_preview);
  1898.   gtk_widget_show (pic_preview);
  1899.  
  1900.   /* Fill with white */
  1901.   for (y = 0; y < SMALL_PREVIEW_SZ; y++)
  1902.     {
  1903.       guchar prow[SMALL_PREVIEW_SZ*3];
  1904.       memset (prow, -1, SMALL_PREVIEW_SZ * 3);
  1905.       gtk_preview_draw_row (GTK_PREVIEW (pic_preview), prow,
  1906.                 0, y, SMALL_PREVIEW_SZ);
  1907.     }
  1908.  
  1909.   gtk_signal_connect_after (GTK_OBJECT (pic_preview), "expose_event",
  1910.                 GTK_SIGNAL_FUNC (pic_preview_expose),
  1911.                 NULL);
  1912.  
  1913.   /* More Buttons */
  1914.   button = gtk_button_new_with_label (_("Edit"));
  1915.   gtk_container_add (GTK_CONTAINER (vbox), button);
  1916.   gtk_signal_connect (GTK_OBJECT (button), "clicked",
  1917.               GTK_SIGNAL_FUNC (edit_button_callback),
  1918.               (gpointer) list);
  1919.   gimp_help_set_help_data (button, _("Edit Gfig object collection"), NULL); 
  1920.   gtk_widget_show (button);
  1921.  
  1922.   button = gtk_button_new_with_label (_("Merge"));
  1923.   gtk_container_add (GTK_CONTAINER (vbox), button);
  1924.   gtk_signal_connect (GTK_OBJECT (button), "clicked",
  1925.               GTK_SIGNAL_FUNC (merge_button_callback),
  1926.               (gpointer) list);
  1927.   gimp_help_set_help_data (button, _("Merge Gfig Object collection into the "
  1928.                      "current edit session"), NULL); 
  1929.   gtk_widget_show (button);
  1930.  
  1931.   return vbox;
  1932. }
  1933.  
  1934. /* Special case for now - options on poly/star/spiral button */
  1935.  
  1936. static void
  1937. num_sides_dialog (gchar *d_title,
  1938.           gint  *num_sides,
  1939.           gint  *which_way,
  1940.           gint   adj_min,
  1941.           gint   adj_max)
  1942. {
  1943.   GtkWidget *window;
  1944.   GtkWidget *table;
  1945.   GtkObject *size_data;
  1946.  
  1947.   window = gimp_dialog_new (d_title, "gfig",
  1948.                 gimp_standard_help_func, "filters/gfig.html",
  1949.                 GTK_WIN_POS_MOUSE,
  1950.                 FALSE, TRUE, FALSE,
  1951.  
  1952.                 _("Close"), gtk_widget_destroy,
  1953.                 NULL, 1, NULL, TRUE, TRUE,
  1954.  
  1955.                 NULL);
  1956.  
  1957.   table = gtk_table_new (which_way ? 2 : 1, 3, FALSE);
  1958.   gtk_table_set_col_spacings (GTK_TABLE (table), 4);
  1959.   gtk_table_set_row_spacings (GTK_TABLE (table), 2);
  1960.   gtk_container_set_border_width (GTK_CONTAINER (table), 6);
  1961.   gtk_box_pack_start (GTK_BOX (GTK_DIALOG (window)->vbox), table,
  1962.               FALSE, FALSE, 0);
  1963.   gtk_widget_show (table);
  1964.  
  1965.   size_data = gimp_scale_entry_new (GTK_TABLE (table), 0, 0,
  1966.                     _("Number of Sides/Points/Turns:"), 0, 0,
  1967.                     *num_sides, adj_min, adj_max, 1, 10, 0,
  1968.                     TRUE, 0, 0,
  1969.                     NULL, NULL);
  1970.   gtk_signal_connect (GTK_OBJECT (size_data), "value_changed",
  1971.               GTK_SIGNAL_FUNC (gimp_int_adjustment_update),
  1972.               num_sides);
  1973.  
  1974.   if (which_way)
  1975.     {
  1976.       GtkWidget *option_menu;
  1977.  
  1978.       option_menu =
  1979.     gimp_option_menu_new2 (FALSE, gimp_menu_item_update,
  1980.                    which_way, (gpointer) *which_way,
  1981.  
  1982.                    _("Clockwise"),      (gpointer) 0, NULL,
  1983.                    _("Anti-Clockwise"), (gpointer) 1, NULL,
  1984.  
  1985.                    NULL);
  1986.       gimp_table_attach_aligned (GTK_TABLE (table), 0, 1,
  1987.                  _("Orientation:"), 1.0, 0.5,
  1988.                  option_menu, 1, TRUE);
  1989.     }
  1990.  
  1991.   gtk_widget_show (window);
  1992. }
  1993.  
  1994. static void
  1995. bezier_dialog (void)
  1996. {
  1997.   static GtkWidget *window = NULL;
  1998.   GtkWidget *vbox;
  1999.   GtkWidget *toggle;
  2000.  
  2001.   if (window)
  2002.     {
  2003.       gdk_window_raise (window->window);
  2004.       return;
  2005.     }
  2006.  
  2007.   window = gimp_dialog_new (_("Bezier Settings"), "gfig",
  2008.                 gimp_standard_help_func, "filters/gfig.html",
  2009.                 GTK_WIN_POS_MOUSE,
  2010.                 FALSE, FALSE, FALSE,
  2011.  
  2012.                 _("Close"), gtk_widget_destroy,
  2013.                 NULL, 1, NULL, TRUE, TRUE,
  2014.  
  2015.                 NULL);
  2016.  
  2017.   gtk_signal_connect (GTK_OBJECT (window), "destroy",
  2018.               GTK_SIGNAL_FUNC (gtk_widget_destroyed),
  2019.               &window);
  2020.  
  2021.   vbox = gtk_vbox_new (FALSE, 2);
  2022.   gtk_container_set_border_width (GTK_CONTAINER (vbox), 4);
  2023.   gtk_box_pack_start (GTK_BOX (GTK_DIALOG (window)->vbox), vbox,
  2024.               FALSE, FALSE, 0);
  2025.   gtk_widget_show (vbox);
  2026.  
  2027.   toggle = gtk_check_button_new_with_label (_("Closed"));
  2028.   gtk_signal_connect (GTK_OBJECT (toggle), "toggled",
  2029.               GTK_SIGNAL_FUNC (gimp_toggle_button_update),
  2030.               &bezier_closed);
  2031.   gimp_help_set_help_data (toggle,
  2032.             _("Close curve on completion"), NULL);
  2033.   gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (toggle), bezier_closed);
  2034.   gtk_box_pack_start (GTK_BOX (vbox), toggle, FALSE, FALSE, 0);
  2035.   gtk_widget_show (toggle);
  2036.  
  2037.   toggle = gtk_check_button_new_with_label (_("Show Line Frame"));
  2038.   gtk_signal_connect (GTK_OBJECT (toggle), "toggled",
  2039.               GTK_SIGNAL_FUNC (gimp_toggle_button_update),
  2040.               &bezier_line_frame);
  2041.   gimp_help_set_help_data (toggle,
  2042.             _("Draws lines between the control points. "
  2043.               "Only during curve creation"), NULL);
  2044.   gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (toggle), bezier_line_frame);
  2045.   gtk_box_pack_start (GTK_BOX (vbox), toggle, FALSE, FALSE, 0);
  2046.   gtk_widget_show (toggle);
  2047.  
  2048.   gtk_widget_show (window);
  2049. }
  2050.  
  2051. static gint
  2052. poly_button_press (GtkWidget      *widget,
  2053.            GdkEventButton *event,
  2054.            gpointer        data)
  2055. {
  2056.   if ((event->type == GDK_2BUTTON_PRESS) &&
  2057.       (event->button == 1))
  2058.     num_sides_dialog (_("Regular Polygon Number of Sides"),
  2059.               &poly_num_sides, NULL, 3, 200);
  2060.   return FALSE;
  2061. }
  2062.  
  2063. static gint
  2064. star_button_press (GtkWidget      *widget,
  2065.            GdkEventButton *event,
  2066.            gpointer        data)
  2067. {
  2068.   if ((event->type == GDK_2BUTTON_PRESS) &&
  2069.       (event->button == 1))
  2070.     num_sides_dialog (_("Star Number of Points"),
  2071.               &star_num_sides, NULL, 3, 200);
  2072.   return FALSE;
  2073. }
  2074.  
  2075. static gint
  2076. spiral_button_press (GtkWidget      *widget,
  2077.              GdkEventButton *event,
  2078.              gpointer        data)
  2079. {
  2080.   if ((event->type == GDK_2BUTTON_PRESS) &&
  2081.       (event->button == 1))
  2082.     num_sides_dialog (_("Spiral Number of Points"),
  2083.               &spiral_num_turns, &spiral_toggle, 1, 20);
  2084.   return FALSE;
  2085. }
  2086.  
  2087. static gint
  2088. bezier_button_press (GtkWidget      *widget,
  2089.              GdkEventButton *event,
  2090.              gpointer        data)
  2091. {
  2092.   if ((event->type == GDK_2BUTTON_PRESS) &&
  2093.       (event->button == 1))
  2094.     bezier_dialog ();
  2095.   return FALSE;
  2096. }              
  2097.  
  2098. static GtkWidget *
  2099. draw_buttons (GtkWidget *ww)
  2100. {
  2101.   GtkWidget *frame;
  2102.   GtkWidget *button;
  2103.   GtkWidget *vbox;
  2104.   GSList    *group;
  2105.  
  2106.   frame = gtk_frame_new (_("Ops"));
  2107.   gtk_container_set_border_width (GTK_CONTAINER (frame), 1);
  2108.   
  2109.   /* Create group */
  2110.   group = NULL;
  2111.   vbox = gtk_vbox_new (FALSE, 0);
  2112.   gtk_container_add (GTK_CONTAINER (frame), vbox); 
  2113.   gtk_container_set_border_width (GTK_CONTAINER (vbox), 2);
  2114.  
  2115.   /* Put buttons in */
  2116.   button = but_with_pix (line_xpm, &group, LINE);
  2117.   gtk_box_pack_start (GTK_BOX (vbox), button, TRUE, TRUE, 0);
  2118.   gtk_widget_show (button);
  2119.   gimp_help_set_help_data (button, _("Create line"), NULL); 
  2120.  
  2121.   button = but_with_pix (circle_xpm, &group, CIRCLE);
  2122.   gtk_container_add (GTK_CONTAINER (vbox), button);
  2123.   gtk_widget_show (button);
  2124.   gimp_help_set_help_data (button, _("Create circle"), NULL); 
  2125.  
  2126.   button = but_with_pix (ellipse_xpm, &group, ELLIPSE);
  2127.   gtk_container_add (GTK_CONTAINER (vbox), button);
  2128.   gtk_widget_show (button);
  2129.   gimp_help_set_help_data (button, _("Create ellipse"), NULL); 
  2130.  
  2131.   button = but_with_pix (curve_xpm, &group, ARC);
  2132.   gtk_container_add (GTK_CONTAINER (vbox), button);
  2133.   gtk_widget_show (button);
  2134.   gimp_help_set_help_data (button, _("Create arch"), NULL); 
  2135.  
  2136.   button = but_with_pix (poly_xpm, &group, POLY);
  2137.   gtk_container_add (GTK_CONTAINER (vbox), button);
  2138.   gtk_widget_show (button);
  2139.  
  2140.   gtk_signal_connect (GTK_OBJECT (button), "button_press_event",
  2141.               GTK_SIGNAL_FUNC (poly_button_press),
  2142.               NULL);
  2143.   gimp_help_set_help_data (button, _("Create reg polygon"), NULL); 
  2144.  
  2145.   button = but_with_pix (star_xpm, &group, STAR);
  2146.   gtk_container_add (GTK_CONTAINER (vbox), button);
  2147.   gtk_widget_show (button);
  2148.   gtk_signal_connect (GTK_OBJECT (button), "button_press_event",
  2149.               GTK_SIGNAL_FUNC (star_button_press),
  2150.               NULL);
  2151.   gimp_help_set_help_data (button, "Create star", NULL); 
  2152.  
  2153.   button = but_with_pix (spiral_xpm, &group, SPIRAL);
  2154.   gtk_box_pack_start (GTK_BOX (vbox), button, TRUE, TRUE, 0);
  2155.   gtk_widget_show (button);
  2156.  
  2157.   gtk_signal_connect (GTK_OBJECT (button), "button_press_event",
  2158.               GTK_SIGNAL_FUNC (spiral_button_press),
  2159.               NULL);
  2160.   gimp_help_set_help_data (button, _("Create spiral"), NULL); 
  2161.  
  2162.   button = but_with_pix (bezier_xpm, &group, BEZIER);
  2163.   gtk_box_pack_start (GTK_BOX (vbox), button, TRUE, TRUE, 0);
  2164.   gtk_widget_show (button);
  2165.   gtk_signal_connect (GTK_OBJECT (button), "button_press_event",
  2166.               GTK_SIGNAL_FUNC (bezier_button_press),
  2167.               NULL);
  2168.  
  2169.   gimp_help_set_help_data (button,
  2170.             _("Create bezier curve. "
  2171.               "Shift + Button ends object creation."), NULL); 
  2172.  
  2173.   button = but_with_pix (move_obj_xpm, &group, MOVE_OBJ);
  2174.   gtk_container_add (GTK_CONTAINER (vbox), button);
  2175.   gtk_widget_show (button);
  2176.   gimp_help_set_help_data (button, _("Move an object"), NULL); 
  2177.  
  2178.   button = but_with_pix (move_point_xpm, &group, MOVE_POINT);
  2179.   gtk_container_add (GTK_CONTAINER (vbox), button);
  2180.   gtk_widget_show (button);
  2181.   gimp_help_set_help_data (button, _("Move a single point"), NULL); 
  2182.  
  2183.   button = but_with_pix (copy_obj_xpm, &group, COPY_OBJ);
  2184.   gtk_container_add (GTK_CONTAINER (vbox), button);
  2185.   gtk_widget_show (button);
  2186.   gimp_help_set_help_data (button, _("Copy an object"), NULL); 
  2187.  
  2188.   button = but_with_pix (delete_xpm, &group, DEL_OBJ);
  2189.   gtk_container_add (GTK_CONTAINER (vbox), button);
  2190.   gtk_widget_show (button);
  2191.   gimp_help_set_help_data (button, _("Delete an object"), NULL); 
  2192.  
  2193.   button = obj_select_buttons ();
  2194.   gtk_container_add (GTK_CONTAINER (vbox), button);
  2195.   gtk_widget_show (button);
  2196.  
  2197. #if 0
  2198.   button = but_with_pix (blank_xpm, &group, NULL_OPER);
  2199.   gtk_container_add (GTK_CONTAINER (vbox), button);
  2200.   gtk_widget_set_sensitive (button, FALSE);
  2201.   gtk_widget_show (button);
  2202. #endif /* 0 */
  2203.  
  2204.   gtk_widget_show (vbox);
  2205.   gtk_widget_show (frame);
  2206.  
  2207.   return frame;
  2208. }
  2209.  
  2210. /* Brush preview stuff */
  2211. static gint
  2212. gfig_brush_preview_events (GtkWidget *widget,
  2213.                GdkEvent  *event)
  2214. {
  2215.   GdkEventButton *bevent;
  2216.   GdkEventMotion *mevent;
  2217.   static GdkPoint point;
  2218.   static int have_start = 0;
  2219.  
  2220.   switch (event->type)
  2221.     {
  2222.     case GDK_EXPOSE:
  2223.       break;
  2224.  
  2225.     case GDK_BUTTON_PRESS:
  2226.       bevent = (GdkEventButton *) event;
  2227.       point.x = bevent->x;
  2228.       point.y = bevent->y;
  2229.       have_start = 1;
  2230.  
  2231.       break;
  2232.     case GDK_BUTTON_RELEASE:
  2233.       bevent = (GdkEventButton *) event;
  2234.       have_start = 0;
  2235.  
  2236.       break;
  2237.     case GDK_MOTION_NOTIFY:
  2238.       mevent = (GdkEventMotion *) event;
  2239.  
  2240.       if (!have_start || !(mevent->state & GDK_BUTTON1_MASK))
  2241.     break;
  2242.  
  2243.       gfig_brush_fill_preview_xy (widget,
  2244.                   point.x - mevent->x,
  2245.                   point.y - mevent->y);
  2246.       gtk_widget_draw (widget, NULL);
  2247.       point.x = mevent->x;
  2248.       point.y = mevent->y;
  2249.       break;
  2250.     default:
  2251.       break;
  2252.     }
  2253.   return FALSE;
  2254. }
  2255.  
  2256. static void
  2257. gfig_brush_update_preview (GtkWidget *widget,
  2258.                gpointer   data)
  2259. {
  2260.   GtkWidget *pw = (GtkWidget *) data;
  2261.   BrushDesc *bdesc;
  2262.  
  2263.   /* Must update the dialog area */
  2264.   /* Use the same brush as already set in the dialog */
  2265.   bdesc = gtk_object_get_user_data (GTK_OBJECT (pw));
  2266.   brush_list_button_callback (NULL, bdesc);
  2267. }
  2268.  
  2269. static void
  2270. gfig_brush_menu_callback (GtkWidget *widget,
  2271.               gpointer   data)
  2272. {
  2273.   gimp_menu_item_update (widget, &selvals.brshtype);
  2274.  
  2275.   switch (selvals.brshtype)
  2276.     {
  2277.     case BRUSH_BRUSH_TYPE:
  2278.       gtk_widget_hide (pressure_hbox);
  2279.       gtk_widget_hide (pencil_hbox);
  2280.       gtk_widget_show (fade_out_hbox);
  2281.       gtk_widget_show (gradient_hbox);
  2282.       break;
  2283.     case BRUSH_PENCIL_TYPE:
  2284.       gtk_widget_hide (fade_out_hbox);
  2285.       gtk_widget_hide (gradient_hbox);
  2286.       gtk_widget_hide (pressure_hbox);
  2287.       gtk_widget_show (pencil_hbox);
  2288.       break;
  2289.     case BRUSH_AIRBRUSH_TYPE:
  2290.       gtk_widget_hide (fade_out_hbox);
  2291.       gtk_widget_hide (gradient_hbox);
  2292.       gtk_widget_hide (pencil_hbox);
  2293.       gtk_widget_show (pressure_hbox);
  2294.       break;
  2295.     case BRUSH_PATTERN_TYPE:
  2296.       gtk_widget_hide (fade_out_hbox);
  2297.       gtk_widget_hide (gradient_hbox);
  2298.       gtk_widget_hide (pressure_hbox);
  2299.       gtk_widget_show (pencil_hbox);
  2300.       break;
  2301.     default:
  2302.       g_warning ("Internal error - invalid brush type");
  2303.       break;
  2304.     }
  2305.  
  2306.   gfig_brush_update_preview (widget, data);
  2307. }
  2308.  
  2309.  
  2310. static GtkWidget *
  2311. gfig_brush_preview (GtkWidget **pv)
  2312. {
  2313.   GtkWidget *option_menu;
  2314.   GtkWidget *frame;
  2315.   GtkWidget *hbox;
  2316.   GtkWidget *vbox;
  2317.   gint y;
  2318.  
  2319.   hbox = gtk_hbox_new (FALSE, 0);
  2320.   gtk_container_set_border_width (GTK_CONTAINER (hbox), 4);
  2321.   gtk_widget_show (hbox);
  2322.  
  2323.   frame = gtk_frame_new (NULL);
  2324.   gtk_frame_set_shadow_type (GTK_FRAME (frame), GTK_SHADOW_IN);
  2325.   gtk_container_set_border_width (GTK_CONTAINER (frame), 0);
  2326.   gtk_widget_show (frame);
  2327.  
  2328.   *pv = gtk_preview_new (GTK_PREVIEW_COLOR);
  2329.   gtk_widget_show (*pv);
  2330.   gtk_widget_set_events (GTK_WIDGET (*pv), PREVIEW_MASK);
  2331.   gtk_signal_connect (GTK_OBJECT (*pv), "event",
  2332.               GTK_SIGNAL_FUNC (gfig_brush_preview_events),
  2333.               NULL);
  2334.   gtk_preview_size (GTK_PREVIEW (*pv), BRUSH_PREVIEW_SZ, BRUSH_PREVIEW_SZ);
  2335.   gtk_container_add (GTK_CONTAINER (frame), *pv);
  2336.  
  2337.   /* Fill with white */
  2338.   for (y = 0; y < BRUSH_PREVIEW_SZ; y++)
  2339.     {
  2340.       guchar prow[BRUSH_PREVIEW_SZ*3];
  2341.       memset (prow, -1, BRUSH_PREVIEW_SZ * 3);
  2342.       gtk_preview_draw_row (GTK_PREVIEW (*pv), prow, 0, y, BRUSH_PREVIEW_SZ);
  2343.     }
  2344.  
  2345.   /* Now the buttons */
  2346.   vbox = gtk_vbox_new (FALSE, 0);
  2347.   gtk_container_set_border_width (GTK_CONTAINER (vbox), 4);
  2348.   gtk_widget_show (vbox);
  2349.  
  2350.   option_menu =
  2351.     gimp_option_menu_new2 (FALSE, gfig_brush_menu_callback,
  2352.                *pv, (gpointer) selvals.brshtype,
  2353.  
  2354.                _("Brush"),    (gpointer) BRUSH_BRUSH_TYPE, NULL,
  2355.                _("Airbrush"), (gpointer) BRUSH_AIRBRUSH_TYPE, NULL,
  2356.                _("Pencil"),   (gpointer) BRUSH_PENCIL_TYPE, NULL,
  2357.                _("Pattern"),  (gpointer) BRUSH_PATTERN_TYPE, NULL,
  2358.  
  2359.                NULL);
  2360.   gtk_widget_show (option_menu);
  2361.  
  2362.   gtk_container_add (GTK_CONTAINER (vbox), option_menu);
  2363.   gimp_help_set_help_data (option_menu,
  2364.             _("Use the brush/pencil or the airbrush when drawing "
  2365.               "on the image. Pattern paints with currently "
  2366.               "selected brush with a pattern. Only applies to "
  2367.               "circles/ellipses if Approx. Circles/Ellipses "
  2368.               "toggle is set."), NULL);
  2369.  
  2370.   gtk_container_add (GTK_CONTAINER (hbox), vbox);
  2371.   gtk_container_add (GTK_CONTAINER (hbox), frame);
  2372.  
  2373.   return hbox;
  2374. }
  2375.  
  2376. static void
  2377. gfig_brush_fill_preview_xy (GtkWidget *pw,
  2378.                 gint       x1,
  2379.                 gint       y1)
  2380. {
  2381.   gint row_count;
  2382.   BrushDesc *bdesc = (BrushDesc*) gtk_object_get_user_data (GTK_OBJECT (pw));
  2383.  
  2384.   /* Adjust start position */
  2385.   bdesc->x_off += x1;
  2386.   bdesc->y_off += y1;
  2387.  
  2388.   if (bdesc->y_off < 0)
  2389.     bdesc->y_off = 0;
  2390.   if (bdesc->y_off > (bdesc->height - BRUSH_PREVIEW_SZ))
  2391.     bdesc->y_off = bdesc->height - BRUSH_PREVIEW_SZ;
  2392.  
  2393.   if (bdesc->x_off < 0)
  2394.     bdesc->x_off = 0;
  2395.   if (bdesc->x_off > (bdesc->width - BRUSH_PREVIEW_SZ))
  2396.     bdesc->x_off = bdesc->width - BRUSH_PREVIEW_SZ;
  2397.  
  2398.   /* Given an x and y fill preview in correctly offsetted */
  2399.   for (row_count = 0; row_count < BRUSH_PREVIEW_SZ; row_count++)
  2400.     gtk_preview_draw_row (GTK_PREVIEW (pw),
  2401.               &bdesc->pv_buf[bdesc->x_off*bdesc->bpp 
  2402.                     + (bdesc->width
  2403.                        *bdesc->bpp
  2404.                        *(row_count + bdesc->y_off))],
  2405.               0,
  2406.               row_count,
  2407.               BRUSH_PREVIEW_SZ);
  2408. }
  2409.  
  2410. static void
  2411. gfig_brush_fill_preview (GtkWidget *pw,
  2412.              gint32     layer_ID,
  2413.              BrushDesc *bdesc)
  2414. {
  2415.   GimpPixelRgn src_rgn;
  2416.   GimpDrawable *brushdrawable;
  2417.   gint bcount = 3;
  2418.  
  2419.   if (bdesc->pv_buf)
  2420.     {
  2421.       g_free (bdesc->pv_buf); /* Free old area */
  2422.     }
  2423.  
  2424.   brushdrawable = gimp_drawable_get (layer_ID);
  2425.  
  2426.   bdesc->bpp = bcount;
  2427.  
  2428.   /* Fill the preview with the current brush name */
  2429.   gimp_pixel_rgn_init (&src_rgn, brushdrawable,
  2430.                0, 0, bdesc->width, bdesc->height, FALSE, FALSE);
  2431.  
  2432.   bdesc->pv_buf = g_new (guchar, bdesc->width * bdesc->height * bcount);
  2433.   bdesc->x_off = bdesc->y_off = 0; /* Start from top left */
  2434.  
  2435.   gimp_pixel_rgn_get_rect (&src_rgn, bdesc->pv_buf,
  2436.                0, 0, bdesc->width, bdesc->height);
  2437.  
  2438.   /* Dump the pv_buf into the preview area */
  2439.   gfig_brush_fill_preview_xy (pw, 0, 0);
  2440. }
  2441.  
  2442. static void
  2443. mygimp_brush_set (gchar *bname)
  2444. {
  2445.   GimpParam *return_vals;
  2446.   int nreturn_vals;
  2447.  
  2448.   return_vals = gimp_run_procedure ("gimp_brushes_set_brush",
  2449.                     &nreturn_vals,
  2450.                     GIMP_PDB_STRING, bname,
  2451.                     GIMP_PDB_END);
  2452.  
  2453.   if (return_vals[0].data.d_status != GIMP_PDB_SUCCESS)
  2454.     {
  2455.       g_message ("Can't set brush...(1)");
  2456.     }
  2457.  
  2458.   gimp_destroy_params (return_vals, nreturn_vals);
  2459. }
  2460.  
  2461. static gchar *
  2462. mygimp_brush_get (void)
  2463. {
  2464.   GimpParam *return_vals;
  2465.   int nreturn_vals;
  2466.   static gchar saved_bname[1024]; /* required to be static - returned from proc */
  2467.  
  2468.   return_vals = gimp_run_procedure ("gimp_brushes_get_brush",
  2469.                                     &nreturn_vals,
  2470.                     GIMP_PDB_END);
  2471.  
  2472.   if (return_vals[0].data.d_status == GIMP_PDB_SUCCESS)
  2473.     {
  2474.       strncpy (saved_bname, return_vals[1].data.d_string, sizeof (saved_bname));
  2475.     }
  2476.   else
  2477.     {
  2478.       saved_bname[0] = '\0';
  2479.     }
  2480.  
  2481.   gimp_destroy_params (return_vals, nreturn_vals);
  2482.  
  2483.   return (saved_bname);
  2484. }
  2485.  
  2486. static void
  2487. mygimp_brush_info (gint32 *width,
  2488.            gint32 *height)
  2489. {
  2490.   GimpParam *return_vals;
  2491.   int nreturn_vals;
  2492.  
  2493.   return_vals = gimp_run_procedure ("gimp_brushes_get_brush",
  2494.                                     &nreturn_vals,
  2495.                     GIMP_PDB_END);
  2496.  
  2497.   if (return_vals[0].data.d_status == GIMP_PDB_SUCCESS)
  2498.     {
  2499.       *width  = MAX (return_vals[2].data.d_int32, 32);
  2500.       *height = MAX (return_vals[3].data.d_int32, 32);
  2501.     }
  2502.   else
  2503.     {
  2504.       g_message ("Failed to get brush info");
  2505.       *width = *height = 48;
  2506.     }
  2507.  
  2508.   gimp_destroy_params (return_vals, nreturn_vals);
  2509. }          
  2510.  
  2511. static void
  2512. gfig_paint (BrushType brush_type,
  2513.         gint32    drawable_ID,
  2514.         gint      seg_count,
  2515.         gdouble   line_pnts[])
  2516. {
  2517.   switch (brush_type)
  2518.     {
  2519.     case BRUSH_BRUSH_TYPE:
  2520.       gimp_paintbrush (drawable_ID,
  2521.                selvals.brushfade,
  2522.                seg_count, line_pnts,
  2523.                GIMP_HARD,
  2524.                selvals.brushgradient);
  2525.       break;
  2526.  
  2527.     case BRUSH_PENCIL_TYPE:
  2528.       gimp_pencil (drawable_ID,
  2529.            seg_count, line_pnts);
  2530.       break;
  2531.  
  2532.     case BRUSH_AIRBRUSH_TYPE:
  2533.       gimp_airbrush (drawable_ID,
  2534.              selvals.airbrushpressure,
  2535.              seg_count, line_pnts); 
  2536.       break;
  2537.  
  2538.     case BRUSH_PATTERN_TYPE:
  2539.       gimp_clone (drawable_ID,
  2540.           drawable_ID,
  2541.           GIMP_PATTERN_CLONE,
  2542.           0.0, 0.0,
  2543.           seg_count, line_pnts);
  2544.       break;
  2545.     }
  2546. }
  2547.  
  2548. static gint32
  2549. gfig_gen_brush_preview (BrushDesc *bdesc)
  2550. {
  2551.   /* Given the name of a brush then paint it and return the ID of the image 
  2552.    * the preview can be got from
  2553.    */
  2554.   static gint32 layer_ID = -1;
  2555.   guchar fR, fG, fB;
  2556.   guchar bR, bG, bB;
  2557.   gchar *saved_bname;
  2558.   gint32 width, height;
  2559.   gdouble line_pnts[2];
  2560.  
  2561.   if (brush_image_ID == -1)
  2562.     {
  2563.       /* Create a new image */
  2564.       brush_image_ID = gimp_image_new (48, 48, 0);
  2565.       if (brush_image_ID < 0)
  2566.     {
  2567.       g_message ("Failed to generate brush preview");
  2568.       return -1;
  2569.     }
  2570.       if ((layer_ID = gimp_layer_new (brush_image_ID,
  2571.                       "Brush preview",
  2572.                       48,
  2573.                       48,
  2574.                       0, /* RGB type */
  2575.                       100.0, /* opacity */
  2576.                       0 /* mode */)) < 0)
  2577.     {
  2578.       g_message ("Error in creating layer for brush preview");
  2579.       return -1;
  2580.     }
  2581.       gimp_image_add_layer (brush_image_ID, layer_ID, -1);
  2582.     }
  2583.  
  2584.   /* Need this later to delete it */
  2585.  
  2586.   /* Store foreground & backgroud colours set to black/white
  2587.    * paint with brush
  2588.    * restore colours
  2589.    */
  2590.  
  2591.   gimp_palette_get_foreground (&fR, &fG, &fB);
  2592.   gimp_palette_get_background (&bR, &bG, &bB);
  2593.   saved_bname = mygimp_brush_get ();
  2594.  
  2595.   gimp_palette_set_background ((guchar) -1, (guchar) -1, (guchar) -1);
  2596.   gimp_palette_set_foreground (0, 0, 0);
  2597.   mygimp_brush_set (bdesc->bname);
  2598.  
  2599.   mygimp_brush_info (&width, &height);
  2600.   bdesc->width = width;
  2601.   bdesc->height = height;
  2602.   line_pnts[0] = (gdouble) width / 2;
  2603.   line_pnts[1] = (gdouble) height / 2;
  2604.  
  2605.   gimp_layer_resize (layer_ID, width, height, 0, 0);
  2606.   gimp_image_resize (brush_image_ID, width, height, 0, 0);
  2607.  
  2608.   gimp_drawable_fill (layer_ID, 1); /* Clear... Fill with white ... */
  2609.  
  2610.   /* Blob of paint */
  2611.   gfig_paint (selvals.brshtype,
  2612.           layer_ID,
  2613.           2, line_pnts);
  2614.  
  2615.   gimp_palette_set_background (bR, bG, bB);  
  2616.   gimp_palette_set_foreground (fR, fG, fB);
  2617.   mygimp_brush_set (saved_bname);
  2618.  
  2619.   return layer_ID;
  2620. }
  2621.  
  2622. static void
  2623. brush_list_button_callback (GtkWidget *widget,
  2624.                 gpointer   data)
  2625. {
  2626.   gint32 layer_ID;
  2627.  
  2628.   BrushDesc *bdesc = (BrushDesc *) data;
  2629.   if ((layer_ID = gfig_gen_brush_preview (bdesc)) != -1)
  2630.     {
  2631.       gtk_object_set_user_data (GTK_OBJECT (brush_page_pw), (gpointer) bdesc);
  2632.       gfig_brush_fill_preview (brush_page_pw, layer_ID, bdesc);
  2633.       gtk_widget_draw (brush_page_pw, NULL);
  2634.     }
  2635. }
  2636.  
  2637. /* Build the dialog up. This was the hard part! */
  2638.  
  2639. static GtkWidget *page_menu_bg;
  2640. static GtkWidget *page_menu_layers;
  2641.  
  2642. static void
  2643. gfig_brush_pane_activate (GtkWidget *widget,
  2644.               gpointer   data)
  2645. {
  2646.   gint flag = (gint) data;
  2647.  
  2648.   if (flag)
  2649.     {
  2650.       gtk_widget_show (brush_page_widget);
  2651.     }
  2652.   else
  2653.     {
  2654.       gtk_widget_hide (brush_page_widget);
  2655.     }
  2656.  
  2657.   gtk_widget_set_sensitive (brush_page_widget, flag);
  2658. }
  2659.  
  2660. static void
  2661. gfig_select_pane_activate (GtkWidget *widget,
  2662.                gpointer   data)
  2663. {
  2664.   gint flag = (gint) data;
  2665.  
  2666.   if (flag)
  2667.     {
  2668.       gtk_widget_show (select_page_widget);
  2669.     }
  2670.   else
  2671.     {
  2672.       gtk_widget_hide (select_page_widget);
  2673.     }
  2674.  
  2675.   gtk_widget_set_sensitive (select_page_widget, flag);
  2676. }
  2677.  
  2678.  
  2679. static void
  2680. paint_menu_callback (GtkWidget *widget,
  2681.              gpointer   data)
  2682. {
  2683.   gint mtype = (gint)data;
  2684.  
  2685.   if (mtype == PAINT_LAYERS_MENU)
  2686.     {
  2687. #ifdef DEBUG
  2688.       printf ("layer type set to %s\n",
  2689.          ((DrawonLayers)gtk_object_get_user_data (GTK_OBJECT (widget)) == SINGLE_LAYER)?"SINGLE_LAYER":"MULTI_LAYER");
  2690. #endif /* DEBUG */
  2691.       selvals.onlayers = (DrawonLayers)gtk_object_get_user_data (GTK_OBJECT (widget));
  2692.       /* Type only meaningful if creating new layers */
  2693.       if (selvals.onlayers == ORIGINAL_LAYER)
  2694.     gtk_widget_set_sensitive (page_menu_bg, FALSE);
  2695.       else
  2696.     gtk_widget_set_sensitive (page_menu_bg, TRUE);
  2697.     }
  2698.   else if (mtype == PAINT_BGS_MENU)
  2699.     {
  2700. #ifdef DEBUG
  2701.       printf ("BG type = %d\n",
  2702.          ((LayersBGType)gtk_object_get_user_data (GTK_OBJECT (widget))));
  2703. #endif /* DEBUG */
  2704.       selvals.onlayerbg = (LayersBGType)gtk_object_get_user_data (GTK_OBJECT (widget));
  2705.     }
  2706.   else if (mtype == PAINT_TYPE_MENU)
  2707.     {
  2708. #ifdef DEBUG
  2709.       printf ("Got type menu = %d\n", (PaintType)gtk_object_get_user_data (GTK_OBJECT (widget)));
  2710. #endif /* DEBUG */
  2711.       selvals.painttype = (PaintType)gtk_object_get_user_data (GTK_OBJECT (widget));
  2712.       switch (selvals.painttype)
  2713.     {
  2714.     case PAINT_BRUSH_TYPE:
  2715.       gtk_widget_set_sensitive (select_page_widget, FALSE);
  2716.       gtk_widget_set_sensitive (brush_page_widget, TRUE);
  2717.       gtk_widget_set_sensitive (page_menu_layers, TRUE);
  2718.       if (selvals.onlayers == ORIGINAL_LAYER)
  2719.         gtk_widget_set_sensitive (page_menu_bg, FALSE);
  2720.       else
  2721.         gtk_widget_set_sensitive (page_menu_bg, TRUE);
  2722.       break;
  2723.     case PAINT_SELECTION_TYPE:
  2724.       gtk_widget_set_sensitive (select_page_widget, TRUE);
  2725.       gtk_widget_set_sensitive (brush_page_widget, FALSE);
  2726.       gtk_widget_set_sensitive (page_menu_layers, FALSE);
  2727.       gtk_widget_set_sensitive (page_menu_bg, FALSE);
  2728.       break;
  2729.     case PAINT_SELECTION_FILL_TYPE:
  2730.       gtk_widget_set_sensitive (select_page_widget, TRUE);
  2731.       gtk_widget_set_sensitive (brush_page_widget, FALSE);
  2732.       gtk_widget_set_sensitive (page_menu_layers, TRUE);
  2733.       if (selvals.onlayers == ORIGINAL_LAYER)
  2734.         gtk_widget_set_sensitive (page_menu_bg, FALSE);
  2735.       else
  2736.         gtk_widget_set_sensitive (page_menu_bg, TRUE);
  2737.       break;
  2738.     default:
  2739.       break;
  2740.     }
  2741.     }
  2742. }
  2743.  
  2744. static GtkWidget *
  2745. paint_page (void)
  2746. {
  2747.   GtkWidget *table;
  2748.   GtkWidget *vbox;
  2749.   GtkWidget *vbox2;
  2750.   GtkWidget *hbox;
  2751.   GtkWidget *toggle;
  2752.   GtkWidget *page_menu_type;
  2753.   GtkWidget *scale_scale;
  2754.   GtkObject *scale_scale_data;
  2755.   GtkWidget *item1, *item2, *item3;
  2756.  
  2757.   vbox = gtk_vbox_new (FALSE, 0);
  2758.   gtk_container_set_border_width (GTK_CONTAINER (vbox), 4);
  2759.  
  2760.   table = gtk_table_new (5, 2, FALSE); 
  2761.   gtk_table_set_col_spacings (GTK_TABLE (table), 4);
  2762.   gtk_table_set_row_spacings (GTK_TABLE (table), 2);
  2763.   gtk_box_pack_start (GTK_BOX (vbox), table, FALSE, FALSE, 0);
  2764.   gtk_widget_show (table);
  2765.  
  2766.   page_menu_layers =
  2767.     gimp_option_menu_new2 (FALSE, paint_menu_callback,
  2768.                (gpointer) PAINT_LAYERS_MENU, 0,
  2769.  
  2770.                _("Original"), (gpointer) ORIGINAL_LAYER, NULL,
  2771.                _("New"),      (gpointer) SINGLE_LAYER, NULL,
  2772.                _("Multiple"), (gpointer) MULTI_LAYER, NULL,
  2773.  
  2774.                NULL);
  2775.  
  2776.   gimp_help_set_help_data (page_menu_layers,
  2777.             _("Draw all objects on one layer (original or new) "
  2778.               "or one object per layer"), NULL);
  2779.   if (gimp_drawable_is_channel (gfig_drawable))
  2780.       gtk_widget_set_sensitive (page_menu_layers, FALSE);
  2781.   gimp_table_attach_aligned (GTK_TABLE (table), 0, 0,
  2782.                  _("Draw on:"), 1.0, 0.5,
  2783.                  page_menu_layers, 1, TRUE);
  2784.  
  2785.   page_menu_type =
  2786.     gimp_option_menu_new2 (FALSE, paint_menu_callback,
  2787.                (gpointer) PAINT_TYPE_MENU, 0,
  2788.  
  2789.                _("Brush"),
  2790.                (gpointer) PAINT_BRUSH_TYPE, &item1,
  2791.                _("Selection"),
  2792.                (gpointer) PAINT_SELECTION_TYPE, &item2,
  2793.                _("Selection+Fill"),
  2794.                (gpointer) PAINT_SELECTION_FILL_TYPE, &item3,
  2795.  
  2796.                NULL);
  2797.  
  2798.   gtk_signal_connect (GTK_OBJECT (item1), "activate",
  2799.               GTK_SIGNAL_FUNC (gfig_brush_pane_activate),
  2800.               (gpointer) 1);
  2801.   gtk_signal_connect (GTK_OBJECT (item1), "activate",
  2802.               GTK_SIGNAL_FUNC (gfig_select_pane_activate),
  2803.               (gpointer) 0);
  2804.  
  2805.   gtk_signal_connect (GTK_OBJECT (item2), "activate",
  2806.               GTK_SIGNAL_FUNC (gfig_brush_pane_activate),
  2807.               (gpointer) 0);
  2808.   gtk_signal_connect (GTK_OBJECT (item2), "activate",
  2809.               GTK_SIGNAL_FUNC (gfig_select_pane_activate),
  2810.               (gpointer) 1);
  2811.  
  2812.   gtk_signal_connect (GTK_OBJECT (item3), "activate",
  2813.               GTK_SIGNAL_FUNC (gfig_brush_pane_activate),
  2814.               (gpointer) 0);
  2815.   gtk_signal_connect (GTK_OBJECT (item3), "activate",
  2816.               GTK_SIGNAL_FUNC (gfig_select_pane_activate),
  2817.               (gpointer) 1);
  2818.  
  2819.   gimp_help_set_help_data (page_menu_type,
  2820.             _("Draw type. Either a brush or a selection. "
  2821.               "See brush page or selection page for more options"),
  2822.             NULL);
  2823.   gimp_table_attach_aligned (GTK_TABLE (table), 0, 1,
  2824.                  _("Using:"), 1.0, 0.5,
  2825.                  page_menu_type, 1, TRUE);
  2826.  
  2827.   page_menu_bg =
  2828.     gimp_option_menu_new2 (FALSE, paint_menu_callback,
  2829.                (gpointer) PAINT_BGS_MENU, 0,
  2830.  
  2831.                _("Transparent"), (gpointer) LAYER_TRANS_BG, NULL,
  2832.                _("Background"),  (gpointer) LAYER_BG_BG, NULL,
  2833.                _("Foreground"),  (gpointer) LAYER_FG_BG, NULL,
  2834.                _("White"),       (gpointer) LAYER_WHITE_BG, NULL,
  2835.                _("Copy"),        (gpointer) LAYER_COPY_BG, NULL,
  2836.  
  2837.                NULL);
  2838.   gimp_help_set_help_data (page_menu_bg,
  2839.             _("Layer background type. Copy causes previous "
  2840.               "layer to be copied before the draw is performed"),
  2841.             NULL);
  2842.   gtk_widget_set_sensitive (page_menu_bg, FALSE);
  2843.   gimp_table_attach_aligned (GTK_TABLE (table), 0, 2,
  2844.                  _("With BG of:"), 1.0, 0.5,
  2845.                  page_menu_bg, 1, TRUE);
  2846.  
  2847.   toggle = gtk_check_button_new_with_label (_("Reverse Line"));
  2848.   gtk_table_attach (GTK_TABLE (table), toggle, 0, 1, 4, 5,
  2849.             GTK_FILL, GTK_FILL, 0, 0);
  2850.   gtk_signal_connect (GTK_OBJECT (toggle), "toggled",
  2851.               GTK_SIGNAL_FUNC (gimp_toggle_button_update),
  2852.               (gpointer)&selvals.reverselines);
  2853.   gimp_help_set_help_data (toggle,
  2854.             _("Draw lines in reverse order"), NULL);
  2855.   gtk_widget_show (toggle);
  2856.  
  2857.   vbox2 = gtk_vbox_new (FALSE, 0);
  2858.   gtk_table_attach (GTK_TABLE (table), vbox2, 0, 1, 3, 4,
  2859.             GTK_FILL, GTK_FILL, 0, 0);
  2860.   gtk_widget_show (vbox2);
  2861.  
  2862.   toggle = gtk_check_button_new_with_label (_("Scale to Image"));
  2863.   gtk_box_pack_end (GTK_BOX (vbox2), toggle, FALSE, FALSE, 0);
  2864.   gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (toggle),
  2865.                 selvals.scaletoimage);
  2866.   gtk_signal_connect (GTK_OBJECT (toggle), "toggled",
  2867.               GTK_SIGNAL_FUNC (gfig_scale2img_update),
  2868.               &selvals.scaletoimage);
  2869.   gimp_help_set_help_data (toggle,
  2870.             _("Scale drawings to images size"), NULL);
  2871.   gtk_widget_show (toggle);
  2872.  
  2873.   hbox = gtk_hbox_new (FALSE, 1);
  2874.   scale_scale_data = gtk_adjustment_new (1.0, 0.1, 5.0, 0.01, 0.01, 0.0);
  2875.   scale_scale = gtk_hscale_new (GTK_ADJUSTMENT (scale_scale_data));
  2876.   gtk_box_pack_start (GTK_BOX (hbox), scale_scale, TRUE, TRUE, 0);
  2877.   gtk_scale_set_value_pos (GTK_SCALE (scale_scale), GTK_POS_TOP);
  2878.   gtk_scale_set_digits (GTK_SCALE (scale_scale), 2);
  2879.   gtk_range_set_update_policy (GTK_RANGE (scale_scale), GTK_UPDATE_CONTINUOUS);
  2880.   gtk_signal_connect (GTK_OBJECT (scale_scale_data), "value_changed",
  2881.                       GTK_SIGNAL_FUNC (gfig_scale_update_scale),
  2882.                       &selvals.scaletoimagefp);
  2883.   gtk_widget_show (scale_scale);
  2884.   gtk_widget_show (hbox);   
  2885.   gtk_table_attach (GTK_TABLE (table), hbox, 1, 2, 3, 4,
  2886.             GTK_FILL | GTK_EXPAND, GTK_FILL, 0, 0);
  2887.  
  2888.   gtk_widget_set_sensitive (GTK_WIDGET (scale_scale), FALSE);
  2889.   gtk_object_set_data (GTK_OBJECT (toggle), "inverse_sensitive", scale_scale);
  2890.   gtk_object_set_user_data (GTK_OBJECT (toggle), scale_scale_data);
  2891.  
  2892.   toggle = gtk_check_button_new_with_label (_("Approx. Circles/Ellipses"));
  2893.   gtk_table_attach (GTK_TABLE (table), toggle, 1, 2, 4, 5,
  2894.             GTK_FILL, GTK_FILL, 0, 0);
  2895.   gtk_signal_connect (GTK_OBJECT (toggle), "toggled",
  2896.               GTK_SIGNAL_FUNC (gimp_toggle_button_update),
  2897.               &selvals.approxcircles);
  2898.   gimp_help_set_help_data (toggle,
  2899.             _("Approx. circles & ellipses using lines. Allows "
  2900.               "the use of brush fading with these types of "
  2901.               "objects."), NULL); 
  2902.   gtk_widget_show (toggle);
  2903.  
  2904.   return vbox;
  2905. }
  2906.  
  2907. static void
  2908. gfig_brush_invoker (gchar    *name,
  2909.             gdouble  opacity,
  2910.             gint     spacing,
  2911.             gint     paint_mode,
  2912.             gint     width,
  2913.             gint     height,
  2914.             gchar   *mask_data,
  2915.             gint     closing,
  2916.             gpointer udata)
  2917. {
  2918.   BrushDesc *bdesc = g_new0 (BrushDesc, 1); /* Mem leak */
  2919.  
  2920.   bdesc->bpp = 3;
  2921.   bdesc->width = width;
  2922.   bdesc->height = height;
  2923.   bdesc->bname = g_strdup (name);
  2924.  
  2925.   brush_list_button_callback (NULL, bdesc);
  2926. }
  2927.  
  2928. static void
  2929. select_brush_callback (GtkWidget *widget,
  2930.                gpointer   data)
  2931. {
  2932.   BrushDesc *bdesc = g_new0 (BrushDesc, 1);
  2933.  
  2934.   gimp_interactive_selection_brush ("Gfig brush selection",
  2935.                     mygimp_brush_get (),
  2936.                     1.0, /* Opacity */
  2937.                     -1,  /* spacing (default)*/
  2938.                     1,   /* Paint mode */
  2939.                     gfig_brush_invoker,
  2940.                     NULL);
  2941.  
  2942.    bdesc->bpp = 3; 
  2943.    bdesc->bname = mygimp_brush_get ();
  2944.    
  2945.    brush_list_button_callback (NULL, bdesc); 
  2946. }
  2947.  
  2948. static GtkWidget *
  2949. brush_page (void)
  2950. {
  2951.   GtkWidget *table;
  2952.   GtkWidget *label;
  2953.   GtkWidget *pw;
  2954.   GtkWidget *scale;
  2955.   GtkObject *fade_out_scale_data;
  2956.   GtkObject *gradient_scale_data;
  2957.   GtkObject *pressure_scale_data;
  2958.   GtkWidget *vbox;
  2959.   GtkWidget *button;
  2960.   BrushDesc *bdesc = g_new0 (BrushDesc, 1); /* Initial brush settings */
  2961.  
  2962.   vbox = gtk_vbox_new (FALSE, 0);
  2963.   gtk_container_set_border_width (GTK_CONTAINER (vbox), 4);
  2964.  
  2965.   table = gtk_table_new (2, 3, FALSE); 
  2966.   gtk_table_set_col_spacings (GTK_TABLE (table), 4);
  2967.   gtk_table_set_row_spacings (GTK_TABLE (table), 2);
  2968.   gtk_box_pack_start (GTK_BOX (vbox), table, FALSE, FALSE, 0);
  2969.   gtk_widget_show (table);
  2970.  
  2971.   /* Fade option */
  2972.   /*  the fade-out scale  From GIMP itself*/
  2973.   fade_out_hbox = gtk_hbox_new (FALSE, 4);
  2974.  
  2975.   label = gtk_label_new (_("Fade out:"));
  2976.   gtk_misc_set_alignment (GTK_MISC (label), 1.0, 1.0);
  2977.   gtk_box_pack_start (GTK_BOX (fade_out_hbox), label, FALSE, FALSE, 0);
  2978.   gtk_widget_show (label);
  2979.  
  2980.   fade_out_scale_data = gtk_adjustment_new (0.0, 0.0, 3000.0, 1.0, 1.0, 0.0);
  2981.   scale = gtk_hscale_new (GTK_ADJUSTMENT (fade_out_scale_data));
  2982.   gtk_box_pack_start (GTK_BOX (fade_out_hbox), scale, TRUE, TRUE, 0);
  2983.   gtk_scale_set_value_pos (GTK_SCALE (scale), GTK_POS_TOP);
  2984.   gtk_range_set_update_policy (GTK_RANGE (scale), GTK_UPDATE_DELAYED);
  2985.   gtk_signal_connect (GTK_OBJECT (fade_out_scale_data), "value_changed",
  2986.                       GTK_SIGNAL_FUNC (gimp_double_adjustment_update),
  2987.                       &selvals.brushfade);
  2988.   gtk_widget_show (scale);
  2989.  
  2990.   gtk_table_attach (GTK_TABLE (table), fade_out_hbox, 0, 2, 1, 2,
  2991.             GTK_FILL | GTK_EXPAND, GTK_FILL, 0, 0);
  2992.   gtk_widget_show (fade_out_hbox);   
  2993.  
  2994.  
  2995.   /* Gradient drawing */
  2996.   gradient_hbox = gtk_hbox_new (FALSE, 4);
  2997.  
  2998.   label = gtk_label_new (_("Gradient:"));
  2999.   gtk_misc_set_alignment (GTK_MISC (label), 1.0, 1.0);
  3000.   gtk_box_pack_start (GTK_BOX (gradient_hbox), label, FALSE, FALSE, 0);
  3001.   gtk_widget_show (label);
  3002.  
  3003.   gradient_scale_data = gtk_adjustment_new (0.0, 0.0, 3000.0, 1.0, 1.0, 0.0);
  3004.   scale = gtk_hscale_new (GTK_ADJUSTMENT (gradient_scale_data));
  3005.   gtk_box_pack_start (GTK_BOX (gradient_hbox), scale, TRUE, TRUE, 0);
  3006.   gtk_scale_set_value_pos (GTK_SCALE (scale), GTK_POS_TOP);
  3007.   gtk_range_set_update_policy (GTK_RANGE (scale), GTK_UPDATE_DELAYED);
  3008.   gtk_signal_connect (GTK_OBJECT (gradient_scale_data), "value_changed",
  3009.                       GTK_SIGNAL_FUNC (gimp_double_adjustment_update),
  3010.                       &selvals.brushgradient);
  3011.   gtk_widget_show (scale);
  3012.   gtk_table_attach (GTK_TABLE (table), gradient_hbox, 0, 2, 2, 3,
  3013.             GTK_FILL | GTK_EXPAND, GTK_FILL, 0, 0);
  3014.   gtk_widget_show (gradient_hbox);   
  3015.  
  3016.  
  3017.   pressure_hbox = gtk_hbox_new (FALSE, 4);
  3018.   label = gtk_label_new (_("Pressure:"));
  3019.   gtk_misc_set_alignment (GTK_MISC (label), 1.0, 1.0);
  3020.   gtk_box_pack_start (GTK_BOX (pressure_hbox), label, FALSE, FALSE, 0);
  3021.   gtk_widget_show (label);
  3022.  
  3023.   pressure_scale_data = gtk_adjustment_new (20.0, 0.0, 100.0, 1.0, 1.0, 0.0);
  3024.   scale = gtk_hscale_new (GTK_ADJUSTMENT (pressure_scale_data));
  3025.   gtk_box_pack_start (GTK_BOX (pressure_hbox), scale, TRUE, TRUE, 0);
  3026.   gtk_widget_show (scale);
  3027.   gtk_scale_set_value_pos (GTK_SCALE (scale), GTK_POS_TOP);
  3028.   gtk_range_set_update_policy (GTK_RANGE (scale), GTK_UPDATE_DELAYED);
  3029.   gtk_signal_connect (GTK_OBJECT (pressure_scale_data), "value_changed",
  3030.                       GTK_SIGNAL_FUNC (gimp_double_adjustment_update),
  3031.                       &selvals.airbrushpressure);
  3032.   gtk_table_attach (GTK_TABLE (table), pressure_hbox, 0, 2, 1, 2,
  3033.             GTK_FILL | GTK_EXPAND, GTK_FILL, 0, 0);
  3034.  
  3035.   pencil_hbox = gtk_hbox_new (FALSE, 4);
  3036.   label = gtk_label_new (_("No Options..."));
  3037.   gtk_box_pack_start (GTK_BOX (pencil_hbox), label, FALSE, FALSE, 0);
  3038.   gtk_widget_show (label);
  3039.   gtk_table_attach (GTK_TABLE (table), pencil_hbox, 0, 2, 1, 2,
  3040.             GTK_FILL | GTK_EXPAND, GTK_FILL, 0, 0);
  3041.  
  3042.   /* Preview widget */
  3043.   pw = gfig_brush_preview (&brush_page_pw);
  3044.   gtk_table_attach (GTK_TABLE (table), pw, 0, 1, 0, 1, 0, 0, 0, 0);
  3045.  
  3046.   gtk_signal_connect (GTK_OBJECT (pressure_scale_data), "value_changed",
  3047.                       GTK_SIGNAL_FUNC (gfig_brush_update_preview),
  3048.                       (gpointer)brush_page_pw);
  3049.  
  3050.   /* Start of new brush selection code */
  3051.   brush_sel_button = button = gtk_button_new_with_label ("Set Brush...");
  3052.   gtk_misc_set_padding (GTK_MISC (GTK_BIN (brush_sel_button)->child), 2, 0);
  3053.   gtk_signal_connect (GTK_OBJECT (button), "clicked",
  3054.               GTK_SIGNAL_FUNC (select_brush_callback),
  3055.               NULL);
  3056.   gimp_table_attach_aligned (GTK_TABLE (table), 0, 0,
  3057.                  NULL, 0, 0,
  3058.                  button, 1,  TRUE);
  3059.  
  3060.   /* Setup initial brush settings */
  3061.   bdesc->bpp   = 3;
  3062.   bdesc->bname = mygimp_brush_get ();
  3063.   brush_list_button_callback (NULL, bdesc);
  3064.  
  3065.   return vbox;
  3066. }
  3067.  
  3068. static void
  3069. select_menu_callback (GtkWidget *widget,
  3070.               gpointer   data)
  3071. {
  3072.   gint mtype = (gint) data;
  3073.  
  3074.   if (mtype == SELECT_TYPE_MENU)
  3075.     {
  3076.       SelectionType type = 
  3077.     (SelectionType) gtk_object_get_user_data (GTK_OBJECT (widget));
  3078.  
  3079.       selopt.type = type;
  3080.     }
  3081.   else if (mtype == SELECT_ARCTYPE_MENU)
  3082.     {
  3083.       ArcType type = 
  3084.     (ArcType) gtk_object_get_user_data (GTK_OBJECT (widget));
  3085.  
  3086.       selopt.as_pie = type;
  3087.     }
  3088.   else if (mtype == SELECT_TYPE_MENU_FILL)
  3089.     {
  3090.       FillType type =
  3091.     (FillType) gtk_object_get_user_data (GTK_OBJECT (widget));
  3092.  
  3093.       selopt.fill_type = type;
  3094.     }
  3095.   else if (mtype == SELECT_TYPE_MENU_WHEN)
  3096.     {
  3097.       FillWhen type = 
  3098.     (FillWhen) gtk_object_get_user_data (GTK_OBJECT (widget));
  3099.       selopt.fill_when = type;
  3100.     }
  3101. }
  3102.  
  3103. static GtkWidget *
  3104. select_page (void)
  3105. {
  3106.   GtkWidget *menu;
  3107.   GtkWidget *toggle;
  3108.   GtkWidget *scale;
  3109.   GtkObject *scale_data;
  3110.   GtkWidget *table;
  3111.   GtkWidget *vbox;
  3112.  
  3113.   vbox = gtk_vbox_new (FALSE, 0);
  3114.   gtk_container_set_border_width (GTK_CONTAINER (vbox), 4);
  3115.  
  3116.   table = gtk_table_new (4, 4, FALSE); 
  3117.   gtk_table_set_row_spacings (GTK_TABLE (table), 4);
  3118.   gtk_table_set_col_spacings (GTK_TABLE (table), 2);
  3119.   gtk_box_pack_start (GTK_BOX (vbox), table, FALSE, FALSE, 0);
  3120.   gtk_widget_show (table);
  3121.  
  3122.   /* The secltion settings - 
  3123.    * 1) Type (option menu)
  3124.    * 2) Anti A (toggle)
  3125.    * 3) Feather (toggle)
  3126.    * 4) F radius (slider)
  3127.    * 5) Fill type (option menu) 
  3128.    * 6) Opacity (slider)
  3129.    * 7) When to fill (toggle)
  3130.    * 8) Arc as segment/sector 
  3131.    */
  3132.  
  3133.   /* 1 */
  3134.   menu = gimp_option_menu_new2 (FALSE, select_menu_callback,
  3135.                 (gpointer) SELECT_TYPE_MENU, 0,
  3136.  
  3137.                 _("Add"),       (gpointer) ADD, NULL,
  3138.                 _("Subtract"),  (gpointer) SUBTRACT, NULL,
  3139.                 _("Replace"),   (gpointer) REPLACE, NULL,
  3140.                 _("Intersect"), (gpointer) INTERSECT, NULL,
  3141.  
  3142.                 NULL);
  3143.   gimp_table_attach_aligned (GTK_TABLE (table), 0, 0,
  3144.                  _("Selection Type:"), 1.0, 0.5,
  3145.                  menu, 1, FALSE);
  3146.  
  3147.   /* 2 */
  3148.   toggle = gtk_check_button_new_with_label (_("Antialiasing"));
  3149.   gtk_table_attach (GTK_TABLE (table), toggle, 2, 4, 0, 1,
  3150.             GTK_FILL, GTK_FILL, 0, 0);
  3151.   gtk_signal_connect (GTK_OBJECT (toggle), "toggled",
  3152.               GTK_SIGNAL_FUNC (gimp_toggle_button_update),
  3153.               &selopt.antia);
  3154.   gtk_widget_show (toggle); 
  3155.  
  3156.   /* 3 */
  3157.   toggle = gtk_check_button_new_with_label (_("Feather"));
  3158.   gtk_table_attach (GTK_TABLE (table), toggle, 2, 4, 2, 3,
  3159.             GTK_FILL, GTK_FILL, 0, 0);
  3160.   gtk_signal_connect (GTK_OBJECT (toggle), "toggled",
  3161.               GTK_SIGNAL_FUNC (gimp_toggle_button_update),
  3162.               &selopt.feather);
  3163.   gtk_widget_show (toggle); 
  3164.  
  3165.   /* 4 */
  3166.   scale_data =
  3167.     gtk_adjustment_new (selopt.feather_radius, 0.0, 100.0, 1.0, 1.0, 0.0);
  3168.   scale = gtk_hscale_new (GTK_ADJUSTMENT (scale_data));
  3169.   gtk_scale_set_value_pos (GTK_SCALE (scale), GTK_POS_TOP);
  3170.   gtk_range_set_update_policy (GTK_RANGE (scale), GTK_UPDATE_DELAYED);
  3171.   gtk_signal_connect (GTK_OBJECT (scale_data), "value_changed",
  3172.                       GTK_SIGNAL_FUNC (gimp_double_adjustment_update),
  3173.                       &selopt.feather_radius);
  3174.   gimp_table_attach_aligned (GTK_TABLE (table), 2, 3,
  3175.                  _("Radius:"), 1.0, 1.0,
  3176.                  scale, 1, FALSE);
  3177.  
  3178.   /* 5 */
  3179.   menu =
  3180.     gimp_option_menu_new2 (FALSE, select_menu_callback,
  3181.                (gpointer) SELECT_TYPE_MENU_FILL, 0,
  3182.  
  3183.                _("Pattern"),    (gpointer) FILL_PATTERN, NULL,
  3184.                _("Foreground"), (gpointer) FILL_FOREGROUND, NULL,
  3185.                _("Background"), (gpointer) FILL_BACKGROUND, NULL,
  3186.  
  3187.                NULL);
  3188.   gimp_table_attach_aligned (GTK_TABLE (table), 0, 1,
  3189.                  _("Fill Type:"), 1.0, 0.5,
  3190.                  menu, 1, FALSE);
  3191.  
  3192.   /* 6 */
  3193.   scale_data =
  3194.     gtk_adjustment_new (selopt.fill_opacity, 0.0, 100.0, 1.0, 1.0, 0.0);
  3195.   scale = gtk_hscale_new (GTK_ADJUSTMENT (scale_data));
  3196.   gtk_scale_set_value_pos (GTK_SCALE (scale), GTK_POS_TOP);
  3197.   gtk_range_set_update_policy (GTK_RANGE (scale), GTK_UPDATE_DELAYED);
  3198.   gtk_signal_connect (GTK_OBJECT (scale_data), "value_changed",
  3199.                       GTK_SIGNAL_FUNC (gimp_double_adjustment_update),
  3200.                       &selopt.fill_opacity);
  3201.   gimp_table_attach_aligned (GTK_TABLE (table), 2, 1,
  3202.                  _("Fill Opacity:"), 1.0, 1.0,
  3203.                  scale, 1, FALSE);
  3204.  
  3205.   /* 7 */
  3206.   menu =
  3207.     gimp_option_menu_new2 (FALSE, select_menu_callback,
  3208.                (gpointer) SELECT_TYPE_MENU_WHEN, 0,
  3209.  
  3210.                _("Each Selection"), (gpointer) FILL_EACH, NULL,
  3211.                _("All Selections"), (gpointer) FILL_AFTER, NULL,
  3212.  
  3213.                NULL);
  3214.   gimp_table_attach_aligned (GTK_TABLE (table), 0, 2,
  3215.                  _("Fill after:"), 1.0, 0.5,
  3216.                  menu, 1, FALSE);
  3217.  
  3218.   /* 8 */
  3219.   menu = gimp_option_menu_new2 (FALSE, select_menu_callback,
  3220.                 (gpointer) SELECT_ARCTYPE_MENU, 0,
  3221.  
  3222.                 _("Segment"), (gpointer) ARC_SEGMENT, NULL,
  3223.                 _("Sector"),  (gpointer) ARC_SECTOR, NULL,
  3224.  
  3225.                 NULL);
  3226.   gimp_table_attach_aligned (GTK_TABLE (table), 0, 3,
  3227.                  _("Arc as:"), 1.0, 0.5,
  3228.                  menu, 1, FALSE);
  3229.  
  3230.   return vbox;
  3231. }
  3232.  
  3233. static void
  3234. gridtype_menu_callback (GtkWidget *widget,
  3235.             gpointer   data)
  3236. {
  3237.   gint mtype = (gint)data;
  3238.  
  3239.   if (mtype == GRID_TYPE_MENU)
  3240.     {
  3241. #ifdef DEBUG
  3242.       printf ("Gridtype set to ");
  3243.       if (current_obj->opts.gridtype == RECT_GRID)
  3244.     printf ("RECT_GRID\n");
  3245.       else if (current_obj->opts.gridtype == POLAR_GRID)
  3246.     printf ("POLAR_GRID\n");
  3247.       else if (current_obj->opts.gridtype == ISO_GRID)
  3248.     printf ("ISO_GRID\n");
  3249.       else printf ("NONE\n");
  3250. #endif /* DEBUG */
  3251.       selvals.opts.gridtype = (GridType)gtk_object_get_user_data (GTK_OBJECT (widget));
  3252.     }
  3253.   else
  3254.     {
  3255.       grid_gc_type = (gint) gtk_object_get_user_data (GTK_OBJECT (widget));
  3256.     }
  3257.  
  3258.   draw_grid_clear (widget, 0);
  3259. }
  3260.  
  3261. static GtkWidget *
  3262. options_page (void)
  3263. {
  3264.   GtkWidget *table;
  3265.   GtkWidget *menu;
  3266.   GtkWidget *toggle;
  3267.   GtkWidget *button;
  3268.   GtkWidget *vbox;
  3269.   GtkObject *size_data;
  3270.  
  3271.   vbox = gtk_vbox_new (FALSE, 0);
  3272.   gtk_container_set_border_width (GTK_CONTAINER (vbox), 4);
  3273.  
  3274.   table = gtk_table_new (6, 3, FALSE);
  3275.   gtk_table_set_col_spacings (GTK_TABLE (table), 4);
  3276.   gtk_table_set_row_spacings (GTK_TABLE (table), 2);
  3277.   gtk_box_pack_start (GTK_BOX (vbox), table, FALSE, FALSE, 0);
  3278.   gtk_widget_show (table);
  3279.  
  3280.   /* Put buttons in */
  3281.   toggle = gtk_check_button_new_with_label (_("Show Image"));
  3282.   gtk_table_attach (GTK_TABLE (table), toggle, 0, 1, 0, 1,
  3283.             GTK_FILL, GTK_FILL, 0, 0);
  3284.   gtk_signal_connect (GTK_OBJECT (toggle), "toggled",
  3285.               GTK_SIGNAL_FUNC (gimp_toggle_button_update),
  3286.               &selvals.showimage);
  3287.   gtk_signal_connect (GTK_OBJECT (toggle), "toggled",
  3288.               (GtkSignalFunc) toggle_show_image,
  3289.               (gpointer) 1);
  3290.   gtk_widget_show (toggle);
  3291.  
  3292.   button = gtk_button_new_with_label (_("Reload Image"));
  3293.   gtk_misc_set_padding (GTK_MISC (GTK_BIN (button)->child), 2, 0);
  3294.   gtk_signal_connect (GTK_OBJECT (button), "clicked",
  3295.               GTK_SIGNAL_FUNC (reload_button_callback),
  3296.               NULL);
  3297.   gimp_table_attach_aligned (GTK_TABLE (table), 0, 0,
  3298.                  NULL, 0, 0,
  3299.                  button, 1, TRUE);
  3300.  
  3301.   menu = gimp_option_menu_new2 (FALSE, gridtype_menu_callback,
  3302.                 (gpointer) GRID_TYPE_MENU, 0,
  3303.  
  3304.                 _("Rectangle"), (gpointer) RECT_GRID, NULL,
  3305.                 _("Polar"),     (gpointer) POLAR_GRID, NULL,
  3306.                 _("Isometric"), (gpointer) ISO_GRID, NULL,
  3307.  
  3308.                 NULL);
  3309.   gimp_table_attach_aligned (GTK_TABLE (table), 0, 1,
  3310.                  _("Grid Type:"), 1.0, 0.5,
  3311.                  menu, 1, TRUE);
  3312.  
  3313.   gfig_opt_widget.gridtypemenu = menu;
  3314.  
  3315.   menu =
  3316.     gimp_option_menu_new2 (FALSE, gridtype_menu_callback,
  3317.                (gpointer) GRID_RENDER_MENU, 0,
  3318.  
  3319.                _("Normal"),     (gpointer) GTK_STATE_NORMAL, NULL,
  3320.                _("Black"),      (gpointer) GFIG_BLACK_GC, NULL,
  3321.                _("White"),      (gpointer) GFIG_WHITE_GC, NULL,
  3322.                _("Grey"),       (gpointer) GFIG_GREY_GC, NULL,
  3323.                _("Darker"),     (gpointer) GTK_STATE_ACTIVE, NULL,
  3324.                _("Lighter"),    (gpointer) GTK_STATE_PRELIGHT, NULL,
  3325.                _("Very Dark"),  (gpointer) GTK_STATE_SELECTED, NULL,
  3326.  
  3327.                NULL);
  3328.   gimp_table_attach_aligned (GTK_TABLE (table), 0, 2,
  3329.                  _("Grid Color:"), 1.0, 0.5,
  3330.                  menu, 1, TRUE);
  3331.  
  3332.   size_data = gimp_scale_entry_new (GTK_TABLE (table), 0, 3,
  3333.                     _("Max Undo:"), 0, 50,
  3334.                     selvals.maxundo, MIN_UNDO, MAX_UNDO, 1, 2, 0,
  3335.                     TRUE, 0, 0,
  3336.                     NULL, NULL);
  3337.   gtk_signal_connect (GTK_OBJECT (size_data), "value_changed",
  3338.               GTK_SIGNAL_FUNC (gimp_int_adjustment_update),
  3339.               &selvals.maxundo);
  3340.  
  3341.   toggle = gtk_check_button_new_with_label (_("Show Position"));
  3342.   gtk_table_attach (GTK_TABLE (table), toggle, 0, 1, 4, 5,
  3343.             GTK_FILL, GTK_FILL, 0, 0);
  3344.   gtk_signal_connect (GTK_OBJECT (toggle), "toggled",
  3345.               GTK_SIGNAL_FUNC (gimp_toggle_button_update),
  3346.               &selvals.showpos);
  3347.   gtk_signal_connect_after (GTK_OBJECT (toggle), "toggled",
  3348.               (GtkSignalFunc) gfig_pos_enable,
  3349.               (gpointer) 1);
  3350.   gtk_widget_show (toggle); 
  3351.  
  3352.   toggle = gtk_check_button_new_with_label (_("Hide Control Points"));
  3353.   gtk_table_attach (GTK_TABLE (table), toggle, 1, 3, 4, 5,
  3354.             GTK_FILL, GTK_FILL, 0, 0);
  3355.   gtk_signal_connect (GTK_OBJECT (toggle), "toggled",
  3356.               GTK_SIGNAL_FUNC (gimp_toggle_button_update),
  3357.               &selvals.opts.showcontrol);
  3358.   gtk_signal_connect (GTK_OBJECT (toggle), "toggled",
  3359.               GTK_SIGNAL_FUNC (toggle_show_image),
  3360.               (gpointer) 1);
  3361.   gtk_widget_show (toggle); 
  3362.   gfig_opt_widget.showcontrol = toggle;
  3363.  
  3364.   toggle = gtk_check_button_new_with_label (_("Show Tooltips"));
  3365.   gtk_table_attach (GTK_TABLE (table), toggle, 0, 1, 5, 6,
  3366.             GTK_FILL, GTK_FILL, 0, 0);
  3367.   gtk_signal_connect (GTK_OBJECT (toggle), "toggled",
  3368.               GTK_SIGNAL_FUNC (toggle_tooltips),
  3369.               &selvals.showtooltips);
  3370.   gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (toggle),
  3371.                 selvals.showtooltips);
  3372.   gtk_widget_show (toggle); 
  3373.  
  3374.   button = gtk_button_new_with_label (_("About"));
  3375.   gtk_misc_set_padding (GTK_MISC (GTK_BIN (button)->child), 8, 0);
  3376.   gtk_table_attach (GTK_TABLE (table), button, 1, 3, 5, 6,
  3377.             0, 0, 0, 0);
  3378.   gtk_signal_connect (GTK_OBJECT (button), "clicked",
  3379.               GTK_SIGNAL_FUNC (about_button_callback),
  3380.               NULL);
  3381.   gtk_widget_show (button);
  3382.  
  3383.   return vbox;
  3384. }
  3385.  
  3386. static GtkWidget *
  3387. grid_frame (void)
  3388. {
  3389.   GtkWidget *frame;
  3390.   GtkWidget *vbox;
  3391.   GtkWidget *hbox;
  3392.   GtkWidget *table;
  3393.   GtkWidget *toggle;
  3394.   GtkObject *size_data;
  3395.  
  3396.   frame = gtk_frame_new (_("Grid"));
  3397.  
  3398.   vbox = gtk_vbox_new (FALSE, 2);
  3399.   gtk_container_set_border_width (GTK_CONTAINER (vbox), 2);
  3400.   gtk_container_add (GTK_CONTAINER (frame), vbox);
  3401.   gtk_widget_show (vbox);
  3402.  
  3403.   hbox = gtk_hbox_new (FALSE, 4);
  3404.   gtk_box_pack_start (GTK_BOX (vbox), hbox, FALSE, FALSE, 0); 
  3405.   gtk_widget_show (hbox);
  3406.  
  3407.   toggle = gtk_check_button_new_with_label (_("Snap to Grid"));
  3408.   gtk_box_pack_start (GTK_BOX (hbox), toggle, FALSE, FALSE, 0); 
  3409.   gtk_signal_connect (GTK_OBJECT (toggle), "toggled",
  3410.               GTK_SIGNAL_FUNC (gimp_toggle_button_update),
  3411.               &selvals.opts.snap2grid);
  3412.   gtk_widget_show (toggle);
  3413.   gfig_opt_widget.snap2grid = toggle;
  3414.  
  3415.   toggle = gtk_check_button_new_with_label (_("Display Grid"));
  3416.   gtk_box_pack_start (GTK_BOX (hbox), toggle, FALSE, FALSE, 0); 
  3417.   gtk_signal_connect (GTK_OBJECT (toggle), "toggled",
  3418.               GTK_SIGNAL_FUNC (gimp_toggle_button_update),
  3419.               &selvals.opts.drawgrid);
  3420.   gtk_signal_connect (GTK_OBJECT (toggle), "toggled",
  3421.               GTK_SIGNAL_FUNC (draw_grid_clear),
  3422.               (gpointer) 1);
  3423.   gtk_widget_show (toggle);
  3424.   gfig_opt_widget.drawgrid = toggle;
  3425.  
  3426.   toggle = gtk_check_button_new_with_label (_("Lock on Grid"));
  3427.   gtk_box_pack_start (GTK_BOX (hbox), toggle, FALSE, FALSE, 0); 
  3428.   gtk_signal_connect (GTK_OBJECT (toggle), "toggled",
  3429.               GTK_SIGNAL_FUNC (gimp_toggle_button_update),
  3430.               &selvals.opts.lockongrid);
  3431.   gtk_widget_show (toggle);
  3432.   gfig_opt_widget.lockongrid = toggle;
  3433.  
  3434.   table = gtk_table_new (1, 3, FALSE);
  3435.   gtk_table_set_col_spacings (GTK_TABLE (table), 4);
  3436.   gtk_table_set_row_spacings (GTK_TABLE (table), 2);
  3437.   gtk_box_pack_start (GTK_BOX (vbox), table, FALSE, FALSE, 0); 
  3438.   gtk_widget_show (table);
  3439.  
  3440.   size_data = gimp_scale_entry_new (GTK_TABLE (table), 0, 0,
  3441.                     _("Grid Spacing:"), 0, 50,
  3442.                     selvals.opts.gridspacing,
  3443.                     MIN_GRID, MAX_GRID, 1, 10, 0,
  3444.                     TRUE, 0, 0,
  3445.                     NULL, NULL);
  3446.   gtk_signal_connect (GTK_OBJECT (size_data), "value_changed",
  3447.               GTK_SIGNAL_FUNC (gimp_int_adjustment_update),
  3448.               &selvals.opts.gridspacing);
  3449.   gtk_signal_connect (GTK_OBJECT (size_data), "value_changed",
  3450.               GTK_SIGNAL_FUNC (draw_grid_clear),
  3451.               (gpointer) 0);
  3452.   gfig_opt_widget.gridspacing = size_data;
  3453.  
  3454.   gtk_widget_show (frame);
  3455.  
  3456.   return frame;
  3457. }
  3458.  
  3459. static void 
  3460. clear_list_items (GtkList *list)
  3461. {
  3462.   gtk_list_clear_items (list, 0, -1);
  3463. }
  3464.  
  3465. static void
  3466. build_list_items (GtkWidget *list)
  3467. {
  3468.   GList     *tmp;
  3469.   GtkWidget *list_item;
  3470.   GtkWidget *list_pix;
  3471.   GFigObj   *g;
  3472.  
  3473.   for (tmp = gfig_list; tmp; tmp = g_list_next (tmp))
  3474.     {
  3475.       g = tmp->data;
  3476.  
  3477.       if (g->obj_status & GFIG_READONLY)
  3478.     list_pix = gimp_pixmap_new (mini_cross_xpm);
  3479.       else
  3480.     list_pix = gimp_pixmap_new (blank_xpm);
  3481.  
  3482.       list_item =
  3483.     gfig_list_item_new_with_label_and_pixmap (g, g->draw_name, list_pix);
  3484.  
  3485.       gtk_object_set_user_data (GTK_OBJECT (list_item), (gpointer) g);
  3486.       gtk_list_append_items (GTK_LIST (list), g_list_append (NULL, list_item));
  3487.  
  3488.       gtk_signal_connect (GTK_OBJECT (list_item), "button_press_event",
  3489.               GTK_SIGNAL_FUNC (list_button_press),
  3490.               (gpointer) g);
  3491.       gtk_widget_show (list_item);
  3492.     }
  3493. }
  3494.  
  3495. static GtkWidget *
  3496. add_objects_list (void)
  3497. {
  3498.   GtkWidget *vbox;
  3499.   GtkWidget *table;
  3500.   GtkWidget *frame;
  3501.   GtkWidget *list_frame;
  3502.   GtkWidget *scrolled_win;
  3503.   GtkWidget *list;
  3504.   GtkWidget *button;
  3505.  
  3506.   frame = gtk_frame_new (_("Object"));
  3507.   gtk_widget_show (frame);
  3508.  
  3509.   table = gtk_table_new (4, 3, FALSE);
  3510.   gtk_table_set_col_spacings (GTK_TABLE (table), 2);
  3511.   gtk_container_set_border_width (GTK_CONTAINER (table), 2);
  3512.   gtk_widget_show (table);
  3513.  
  3514.   delete_frame_to_freeze = list_frame = gtk_frame_new (NULL);
  3515.   gtk_widget_show (list_frame);
  3516.  
  3517.   scrolled_win = gtk_scrolled_window_new (NULL, NULL);
  3518.   gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (scrolled_win),
  3519.                                   GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC);
  3520.   gtk_container_add (GTK_CONTAINER (list_frame), scrolled_win);
  3521.   gtk_widget_show (scrolled_win);
  3522.  
  3523.   gfig_gtk_list = list = gtk_list_new ();
  3524.   /* gtk_list_set_selection_mode (GTK_LIST (list), GTK_SELECTION_MULTIPLE); */
  3525.   gtk_list_set_selection_mode (GTK_LIST (list), GTK_SELECTION_BROWSE);
  3526.   gtk_scrolled_window_add_with_viewport (GTK_SCROLLED_WINDOW (scrolled_win),
  3527.                      list);
  3528.   gtk_widget_show (list);
  3529.  
  3530.   /* Load saved objects */
  3531.   gfig_list_load_all (gfig_path_list);
  3532.  
  3533.   /* Put list in */
  3534.   build_list_items (list);
  3535.  
  3536.   /* Put buttons in */
  3537.   button = gtk_button_new_with_label (_("Rescan"));
  3538.   gtk_signal_connect (GTK_OBJECT (button), "clicked",
  3539.               GTK_SIGNAL_FUNC (rescan_button_callback),
  3540.               NULL);
  3541.   gimp_help_set_help_data (button,
  3542.             _("Select directory and rescan Gfig object "
  3543.               "collection"), NULL); 
  3544.   gtk_table_attach (GTK_TABLE (table), button, 2, 3, 0, 1,
  3545.             GTK_FILL, GTK_FILL, 0, 0);
  3546.   gtk_widget_show (button);
  3547.  
  3548.   button = gtk_button_new_with_label (_("Load"));
  3549.   gtk_signal_connect (GTK_OBJECT (button), "clicked",
  3550.               GTK_SIGNAL_FUNC (load_button_callback),
  3551.               list);
  3552.   gimp_help_set_help_data (button,
  3553.                _("Load a single Gfig object collection"), NULL); 
  3554.   gtk_table_attach (GTK_TABLE (table), button, 2, 3, 1, 2,
  3555.             GTK_FILL, GTK_FILL, 0, 0);
  3556.   gtk_widget_show (button);
  3557.  
  3558.   button = gtk_button_new_with_label (_("New"));
  3559.   gtk_signal_connect (GTK_OBJECT (button), "clicked",
  3560.               GTK_SIGNAL_FUNC (new_button_callback),
  3561.               "New gfig obj");
  3562.   gimp_help_set_help_data (button, _("Create a new Gfig object collection "
  3563.                      "for editing"), NULL); 
  3564.   gtk_table_attach (GTK_TABLE (table), button, 2, 3, 2, 3,
  3565.             GTK_FILL, GTK_FILL, 0, 0);
  3566.   gtk_widget_show (button);
  3567.  
  3568.   button = gtk_button_new_with_label (_("Delete"));
  3569.   gtk_signal_connect (GTK_OBJECT (button), "clicked",
  3570.               GTK_SIGNAL_FUNC (gfig_delete_gfig_callback),
  3571.               (gpointer) list);
  3572.   gimp_help_set_help_data (button, _("Delete currently selected Gfig Object "
  3573.                      "collection"), NULL); 
  3574.   gtk_table_attach (GTK_TABLE (table), button, 2, 3, 3, 4,
  3575.             GTK_FILL, GTK_FILL, 0, 0);
  3576.   gtk_widget_show (button);
  3577.  
  3578.   /* Attach the frame for the list Show the widgets */
  3579.  
  3580.   gtk_table_attach (GTK_TABLE (table), list_frame, 1, 2, 0, 4,
  3581.             GTK_FILL | GTK_EXPAND, GTK_FILL | GTK_EXPAND, 0, 0);
  3582.  
  3583.   vbox = small_preview (list);
  3584.   gtk_table_attach (GTK_TABLE (table), vbox, 0, 1, 0, 4, 0, 0, 0, 0);
  3585.  
  3586.   gtk_container_add (GTK_CONTAINER (frame), table);
  3587.  
  3588.   return frame;
  3589. }
  3590.  
  3591. static gint x_pos_val;
  3592. static gint y_pos_val;
  3593. static gint pos_tag = -1;
  3594.  
  3595. static void
  3596. gfig_pos_enable (GtkWidget *widget,
  3597.          gpointer   data)
  3598. {
  3599.   gint enable = selvals.showpos;
  3600.   gtk_widget_set_sensitive (GTK_WIDGET (pos_label), enable);
  3601. }
  3602.  
  3603. static void
  3604. gfig_pos_update_labels (gpointer data)
  3605. {
  3606.   static gchar buf[256];
  3607.  
  3608.   /*gtk_idle_remove (pos_tag);*/
  3609.   pos_tag = -1;
  3610.  
  3611.   g_snprintf (buf, sizeof (buf), "%d, %d", x_pos_val, y_pos_val);
  3612.   gtk_label_set_text (GTK_LABEL (pos_label), buf);
  3613. }
  3614.  
  3615. static void
  3616. gfig_pos_update (gint x,
  3617.          gint y)
  3618. {
  3619.   gint update;
  3620.  
  3621.   if (x_pos_val != x || y_pos_val != y)
  3622.     update = 1;
  3623.   else
  3624.     update = 0;
  3625.  
  3626.   x_pos_val = x;
  3627.   y_pos_val = y;
  3628.  
  3629.   if (update && pos_tag == -1 && selvals.showpos)
  3630.     {
  3631.       /*pos_tag = gtk_idle_add ((GtkFunction)gfig_pos_update_labels, NULL);*/
  3632.       gfig_pos_update_labels (NULL);
  3633.     }
  3634. }
  3635.  
  3636. #if 0 /* NOT USED */
  3637. static void
  3638. gfig_obj_size_update (gint sz)
  3639. {
  3640.   static gchar buf[256];
  3641.   
  3642.   sprintf (buf, "%6d", sz);
  3643.   gtk_label_set_text (GTK_LABEL (obj_size_label), buf);
  3644. }  
  3645.  
  3646. static GtkWidget *
  3647. gfig_obj_size_label (void)
  3648. {
  3649.   GtkWidget *label;
  3650.   GtkWidget *hbox;
  3651.   gchar buf[256];
  3652.  
  3653.   hbox = gtk_hbox_new (TRUE, 6);
  3654.  
  3655.   /* Position labels */
  3656.   label = gtk_label_new ("Size: ");
  3657.   gtk_widget_show (label);
  3658.   gtk_box_pack_start (GTK_BOX (hbox), label, FALSE, FALSE, 0);
  3659.  
  3660.   obj_size_label = gtk_label_new ("");
  3661.   gtk_misc_set_alignment (GTK_MISC (obj_size_label), 0.5, 0.5);    
  3662.   gtk_widget_show (obj_size_label);
  3663.   gtk_box_pack_start (GTK_BOX (hbox), obj_size_label, FALSE, FALSE, 0);
  3664.  
  3665.   gtk_widget_show (hbox);
  3666.  
  3667.   sprintf (buf, "%6d", 0);
  3668.   gtk_label_set_text (GTK_LABEL (obj_size_label), buf);
  3669.  
  3670.   return (hbox);
  3671. }
  3672.  
  3673. #endif /* NOT USED */
  3674.  
  3675. static GtkWidget *
  3676. gfig_pos_labels (void)
  3677. {
  3678.   GtkWidget *label;
  3679.   GtkWidget *hbox;
  3680.   gchar      buf[256];
  3681.  
  3682.   hbox = gtk_hbox_new (FALSE, 6);
  3683.   gtk_widget_show (hbox);
  3684.  
  3685.   /* Position labels */
  3686.   label = gtk_label_new (_("XY Position:"));
  3687.   gtk_box_pack_start (GTK_BOX (hbox), label, FALSE, FALSE, 0);
  3688.   gtk_widget_show (label);
  3689.  
  3690.   pos_label = gtk_label_new ("");
  3691.   gtk_box_pack_start (GTK_BOX (hbox), pos_label, FALSE, FALSE, 0);
  3692.   gtk_widget_show (pos_label);
  3693.  
  3694.   g_snprintf (buf, sizeof (buf), "%d, %d", 0, 0);
  3695.   gtk_label_set_text (GTK_LABEL (pos_label), buf);
  3696.  
  3697.   return hbox;
  3698. }
  3699.  
  3700. static GtkWidget *
  3701. make_pos_info (void)
  3702. {
  3703.   GtkWidget *xframe;
  3704.   GtkWidget *hbox;
  3705.   GtkWidget *label;
  3706.  
  3707.   xframe = gtk_frame_new (_("Object Details"));
  3708.  
  3709.   hbox = gtk_hbox_new (TRUE, 6);
  3710.   gtk_container_set_border_width (GTK_CONTAINER (hbox), 2);
  3711.   gtk_container_add (GTK_CONTAINER (xframe), hbox);  
  3712.  
  3713.   /* Add labels */
  3714.   label = gfig_pos_labels ();
  3715.   gtk_box_pack_start (GTK_BOX (hbox), label, TRUE, TRUE, 0);
  3716.   gfig_pos_enable (NULL, NULL);
  3717.  
  3718. #if 0
  3719.   label = gfig_obj_size_label ();
  3720.   gtk_box_pack_start (GTK_BOX (hbox), label, FALSE, FALSE, 0);
  3721. #endif /* 0 */
  3722.  
  3723.   gtk_widget_show (hbox);
  3724.   gtk_widget_show (xframe);
  3725.  
  3726.   return xframe;
  3727. }
  3728.  
  3729. static GtkWidget *
  3730. make_status (void)
  3731. {
  3732.   GtkWidget *xframe;
  3733.   GtkWidget *table;
  3734.   GtkWidget *label;
  3735.  
  3736.   xframe = gtk_frame_new (_("Collection Details"));
  3737.  
  3738.   gtk_frame_set_shadow_type (GTK_FRAME (xframe), GTK_SHADOW_ETCHED_IN);
  3739.   table = gtk_table_new (6, 6, FALSE);
  3740.   gtk_table_set_col_spacing (GTK_TABLE (table), 1, 6);
  3741.   gtk_container_set_border_width (GTK_CONTAINER (table), 2);
  3742.  
  3743.   label = gtk_label_new (_("Draw Name:"));
  3744.   gtk_misc_set_alignment (GTK_MISC (label), 1.0, 0.5);
  3745.   gtk_table_attach (GTK_TABLE (table), label, 1, 2, 0, 1,
  3746.             GTK_FILL, GTK_FILL, 0, 0);
  3747.   gtk_widget_show (label);
  3748.  
  3749.   label = gtk_label_new (_("Filename:"));
  3750.   gtk_misc_set_alignment (GTK_MISC (label), 1.0, 0.5);
  3751.   gtk_table_attach (GTK_TABLE (table), label, 1, 2, 1, 2,
  3752.             GTK_FILL, GTK_FILL, 0, 0);
  3753.   gtk_widget_show (label);
  3754.  
  3755.   status_label_dname = gtk_label_new (_("(none)"));
  3756.   gtk_misc_set_alignment (GTK_MISC (status_label_dname), 0.0, 0.5);
  3757.   gtk_table_attach (GTK_TABLE (table), status_label_dname, 2, 4, 0, 1,
  3758.             GTK_FILL | GTK_EXPAND, 0, 0, 0);
  3759.   gtk_widget_show (status_label_dname);
  3760.  
  3761.   status_label_fname = gtk_label_new (_("(none)"));
  3762.   gtk_misc_set_alignment (GTK_MISC (status_label_fname), 0.0, 0.5);
  3763.   gtk_table_attach (GTK_TABLE (table), status_label_fname, 2, 4, 1, 2,
  3764.             GTK_FILL | GTK_EXPAND, 0, 0, 0);
  3765.   gtk_widget_show (status_label_fname);
  3766.  
  3767.   gtk_container_add (GTK_CONTAINER (xframe), table);  
  3768.  
  3769.   gtk_widget_show (table);
  3770.   gtk_widget_show (xframe);
  3771.  
  3772.   return xframe;
  3773. }
  3774.  
  3775. static GtkWidget *
  3776. make_preview (void)
  3777. {
  3778.   GtkWidget *xframe;
  3779.   GtkWidget *vbox;
  3780.   GtkWidget *hbox;
  3781.   GtkWidget *table;
  3782.   GtkWidget *ruler;
  3783.   
  3784.   gfig_preview = gtk_preview_new (GTK_PREVIEW_COLOR);
  3785.   gtk_widget_set_events (GTK_WIDGET (gfig_preview), PREVIEW_MASK);
  3786.   gfig_preview_exp_id = 
  3787.     gtk_signal_connect_after (GTK_OBJECT (gfig_preview), "expose_event",
  3788.                   GTK_SIGNAL_FUNC (gfig_preview_expose),
  3789.                   NULL);
  3790.  
  3791.   gtk_signal_connect (GTK_OBJECT (gfig_preview), "event",
  3792.               GTK_SIGNAL_FUNC (gfig_preview_events),
  3793.               NULL);
  3794.  
  3795.   gtk_preview_size (GTK_PREVIEW (gfig_preview), preview_width, preview_height);
  3796.  
  3797.   xframe = gtk_frame_new (NULL);
  3798.  
  3799.   gtk_frame_set_shadow_type (GTK_FRAME (xframe), GTK_SHADOW_IN);
  3800.  
  3801.   table = gtk_table_new (3, 3, FALSE);
  3802.   gtk_table_attach (GTK_TABLE (table), gfig_preview, 1, 2, 1, 2,
  3803.             GTK_FILL , GTK_FILL , 0, 0);
  3804.   gtk_container_add (GTK_CONTAINER (xframe), table); 
  3805.  
  3806.   ruler = gtk_hruler_new ();
  3807.   gtk_ruler_set_range (GTK_RULER (ruler), 0, preview_width, 0, PREVIEW_SIZE);
  3808.   gtk_signal_connect_object (GTK_OBJECT (gfig_preview), "motion_notify_event",
  3809.                  (GtkSignalFunc) GTK_WIDGET_CLASS (GTK_OBJECT (ruler)->klass)->motion_notify_event,
  3810.                  GTK_OBJECT (ruler));
  3811.   gtk_table_attach (GTK_TABLE (table), ruler, 1, 2, 0, 1,
  3812.             GTK_FILL, GTK_FILL, 0, 0);
  3813.   gtk_widget_show (ruler);
  3814.  
  3815.   ruler = gtk_vruler_new ();
  3816.   gtk_ruler_set_range (GTK_RULER (ruler), 0, preview_height, 0, PREVIEW_SIZE);
  3817.   gtk_signal_connect_object (GTK_OBJECT (gfig_preview), "motion_notify_event",
  3818.                  (GtkSignalFunc) GTK_WIDGET_CLASS (GTK_OBJECT (ruler)->klass)->motion_notify_event,
  3819.                  GTK_OBJECT (ruler));
  3820.   gtk_table_attach (GTK_TABLE (table), ruler, 0, 1, 1, 2,
  3821.             GTK_FILL, GTK_FILL, 0, 0);
  3822.   gtk_widget_show (ruler);
  3823.  
  3824.   gtk_widget_show (xframe);
  3825.   gtk_widget_show (table);
  3826.  
  3827.   vbox = gtk_vbox_new (FALSE, 0);
  3828.   hbox = gtk_hbox_new (FALSE, 0);
  3829.   gtk_box_pack_start (GTK_BOX (hbox), xframe, FALSE, FALSE, 0);
  3830.  
  3831.   gtk_container_set_border_width (GTK_CONTAINER (vbox), 2);
  3832.   gtk_box_pack_start (GTK_BOX (vbox), hbox, FALSE, FALSE, 0);
  3833.  
  3834.   xframe = make_pos_info ();
  3835.   gtk_box_pack_start (GTK_BOX (vbox), xframe, TRUE, TRUE, 0);
  3836.  
  3837.   xframe = make_status ();
  3838.   gtk_box_pack_start (GTK_BOX (vbox), xframe, TRUE, TRUE, 0);
  3839.  
  3840.   gtk_widget_show (vbox);
  3841.   gtk_widget_show (hbox);
  3842.  
  3843.   return vbox;
  3844. }
  3845.  
  3846. #if 0
  3847. scatch ()
  3848. {
  3849.  
  3850.   pause ();
  3851.  
  3852. }
  3853. #endif /* 0 */
  3854.  
  3855. static void
  3856. gfig_grid_colours (GtkWidget   *widget,
  3857.            GdkColormap *cmap)
  3858. {
  3859.   GdkGCValues values;
  3860.   GdkColor new_col1;
  3861.   GdkColor new_col2;
  3862.   guchar stipple[8] =
  3863.   {
  3864.     0xAA,    /*  ####----  */
  3865.     0x55,    /*  ###----#  */
  3866.     0xAA,    /*  ##----##  */
  3867.     0x55,    /*  #----###  */
  3868.     0xAA,    /*  ----####  */
  3869.     0x55,    /*  ---####-  */
  3870.     0xAA,    /*  --####--  */
  3871.     0x55,    /*  -####---  */
  3872.   };
  3873.  
  3874.   gdk_color_parse ("gray50", &new_col1);
  3875.   gdk_color_alloc (xxx, &new_col1);
  3876.   gdk_color_parse ("gray80", &new_col2);
  3877.   gdk_color_alloc (xxx, &new_col2);
  3878.   values.background.pixel = new_col1.pixel;
  3879.   values.foreground.pixel = new_col2.pixel;
  3880.   values.fill    = GDK_OPAQUE_STIPPLED;
  3881.   values.stipple = gdk_bitmap_create_from_data (widget->window,
  3882.                         (gchar *) stipple,
  3883.                         4, 4);
  3884.   grid_hightlight_drawgc = gdk_gc_new_with_values (widget->window,
  3885.                            &values,
  3886.                            GDK_GC_FOREGROUND |
  3887.                            GDK_GC_BACKGROUND |
  3888.                            GDK_GC_FILL |
  3889.                            GDK_GC_STIPPLE);
  3890. }
  3891.  
  3892.  
  3893. static gint
  3894. gfig_dialog (void)
  3895. {
  3896.   GtkWidget *main_hbox;
  3897.   GtkWidget *frame;
  3898.   GtkWidget *vbox;
  3899.   GtkWidget *xframe;
  3900.   GtkWidget *oframe;
  3901.   GtkWidget *notebook;
  3902.   GtkWidget *page;
  3903.   GtkWidget *top_level_dlg;
  3904.  
  3905.   gimp_ui_init ("gfig", TRUE);
  3906.  
  3907.   yyy = gdk_rgb_get_visual ();
  3908.   xxx = gdk_rgb_get_cmap ();
  3909.  
  3910.   plug_in_parse_gfig_path ();
  3911.  
  3912.   /*cache_preview (); Get the preview image and store it also set has_alpha */
  3913.  
  3914.   img_width  = gimp_drawable_width (gfig_select_drawable->id);
  3915.   img_height = gimp_drawable_height (gfig_select_drawable->id);
  3916.  
  3917.   /* Start buildng the dialog up */
  3918.   top_level_dlg = gimp_dialog_new (_("GFig"), "gfig",
  3919.                    gimp_standard_help_func, "filters/gfig.html",
  3920.                    GTK_WIN_POS_MOUSE,
  3921.                    FALSE, FALSE, FALSE,
  3922.  
  3923.                    _("Done"), gfig_ok_callback,
  3924.                    NULL, NULL, NULL, TRUE, FALSE,
  3925.                    _("Paint"), gfig_paint_callback,
  3926.                    NULL, NULL, NULL, FALSE, FALSE,
  3927.                    _("Save"), save_button_callback,
  3928.                    NULL, NULL, &save_button, FALSE, FALSE,
  3929.                    _("Clear"), gfig_clear_callback,
  3930.                    NULL, NULL, NULL, FALSE, FALSE,
  3931.                    _("Undo"), gfig_undo_callback,
  3932.                    NULL, NULL, &undo_widget, FALSE, FALSE,
  3933.                    _("Cancel"), gtk_widget_destroy,
  3934.                    NULL, 1, NULL, FALSE, TRUE,
  3935.  
  3936.                    NULL);
  3937.  
  3938.   gtk_signal_connect (GTK_OBJECT (top_level_dlg), "destroy",
  3939.               GTK_SIGNAL_FUNC (gtk_main_quit),
  3940.               NULL);
  3941.  
  3942.   /* Tooltips bis */
  3943.   gimp_help_init ();
  3944.  
  3945.   main_hbox = gtk_hbox_new (FALSE, 4);
  3946.   gtk_container_set_border_width (GTK_CONTAINER (main_hbox), 4);
  3947.   gtk_box_pack_start (GTK_BOX (GTK_DIALOG (top_level_dlg)->vbox), main_hbox,
  3948.               TRUE, TRUE, 0);
  3949.  
  3950.   /* Add buttons beside the preview frame */
  3951.   xframe = draw_buttons (top_level_dlg);
  3952.   gtk_box_pack_start (GTK_BOX (main_hbox), xframe, FALSE, FALSE, 0);
  3953.   /*gtk_widget_show (xframe);*/
  3954.  
  3955.   /* Start building the frame for the preview area */
  3956.   frame = gtk_frame_new (_("Preview"));
  3957.   gtk_box_pack_start (GTK_BOX (main_hbox), frame, FALSE, FALSE, 0);
  3958.   gtk_widget_show (frame); 
  3959.  
  3960.   /* Preview itself */
  3961.   xframe = make_preview ();
  3962.   gtk_container_add (GTK_CONTAINER (frame), xframe);
  3963.   /* gtk_widget_show (xframe); */
  3964.  
  3965.   gtk_widget_show (gfig_preview);
  3966.  
  3967.   frame = gtk_frame_new (_("Settings"));
  3968.   gtk_box_pack_start (GTK_BOX (main_hbox), frame, FALSE, FALSE, 0);
  3969.   gtk_widget_show (frame); 
  3970.  
  3971.   vbox = gtk_vbox_new (FALSE, 2);
  3972.   gtk_container_set_border_width (GTK_CONTAINER (vbox), 2);
  3973.   gtk_container_add (GTK_CONTAINER (frame), vbox);
  3974.   gtk_widget_show (vbox);
  3975.  
  3976.   /* listbox + entry */
  3977.   oframe = add_objects_list ();
  3978.   gtk_box_pack_start (GTK_BOX (vbox), oframe, FALSE, FALSE, 0);
  3979.  
  3980.   /* Grid entry */
  3981.   xframe = grid_frame ();
  3982.   gtk_box_pack_start (GTK_BOX (vbox), xframe, FALSE, FALSE, 0);
  3983.  
  3984.   /* The notebook */
  3985.   notebook = gtk_notebook_new ();
  3986.   gtk_notebook_set_tab_pos (GTK_NOTEBOOK (notebook), GTK_POS_TOP);
  3987.   gtk_box_pack_start (GTK_BOX (vbox), notebook, FALSE, FALSE, 0);
  3988.   gtk_widget_show (notebook);
  3989.   
  3990.   page = paint_page ();
  3991.   gtk_notebook_append_page (GTK_NOTEBOOK (notebook), page,
  3992.                 gtk_label_new (_("Paint")));
  3993.   gtk_widget_show (page);
  3994.  
  3995.   brush_page_widget = brush_page ();
  3996.   gtk_notebook_append_page (GTK_NOTEBOOK (notebook), brush_page_widget,
  3997.                 gtk_label_new (_("Brush")));
  3998.   gtk_widget_show (brush_page_widget);
  3999.  
  4000.   /* Sometime maybe allow all objects to be done by selections - this
  4001.    * would adjust the selection options.
  4002.    */
  4003.   select_page_widget = select_page ();
  4004.   gtk_notebook_append_page (GTK_NOTEBOOK (notebook), select_page_widget,
  4005.                 gtk_label_new (_("Select")));
  4006.   gtk_widget_set_sensitive (select_page_widget, FALSE);
  4007.  
  4008.   page = options_page ();
  4009.   gtk_notebook_append_page (GTK_NOTEBOOK (notebook), page,
  4010.                 gtk_label_new (_("Options")));
  4011.   gtk_widget_show (page);
  4012.  
  4013.   gtk_widget_show (main_hbox);
  4014.  
  4015.   gtk_widget_show (top_level_dlg);
  4016.  
  4017.   dialog_update_preview ();
  4018.   gfig_new_gc (); /* Need this for drawing */
  4019.   gfig_update_stat_labels ();
  4020.  
  4021.   gfig_grid_colours (gfig_preview, xxx);
  4022.   /* Popup for list area */
  4023.   gfig_op_menu_create (top_level_dlg);
  4024.  
  4025.   /* signal (11, scatch); For debugging */
  4026.  
  4027.   gtk_main ();
  4028.  
  4029.   gimp_image_delete (brush_image_ID);
  4030.   brush_image_ID = -1;
  4031.  
  4032.   gimp_help_free ();
  4033.  
  4034.   gdk_flush ();
  4035.  
  4036.   return gfig_run;
  4037. }
  4038.  
  4039. static void
  4040. gfig_really_ok_callback (GtkWidget *widget,
  4041.              gboolean   doit,
  4042.              gpointer   data)
  4043. {
  4044.   if (doit)
  4045.     {
  4046.       gfig_run = TRUE;
  4047.       gtk_widget_destroy (GTK_WIDGET (data));
  4048.     }
  4049. }
  4050.  
  4051. static void
  4052. gfig_ok_callback (GtkWidget *widget,
  4053.           gpointer   data)
  4054. {
  4055.   /* Check if outstanding saves */
  4056.   GList   *list;
  4057.   GFigObj *gfig;
  4058.   gint     count = 0;
  4059.  
  4060.   for (list = gfig_list; list; list = g_list_next (list))
  4061.     {
  4062.       gfig = (GFigObj *) list->data;
  4063.       if (gfig->obj_status & GFIG_MODIFIED)
  4064.     count++;
  4065.     }
  4066.  
  4067.   if (count)
  4068.     {
  4069.       GtkWidget *dialog;
  4070.       gchar     *message;
  4071.  
  4072.       message =
  4073.     g_strdup_printf (_("%d unsaved Gfig objects.\nContinue with exiting?"), count);
  4074.  
  4075.       dialog = gimp_query_boolean_box (_("Warning"),
  4076.                        gimp_standard_help_func,
  4077.                        "filters/gfig.html",
  4078.                        FALSE,
  4079.                        message,
  4080.                        _("OK"), _("Cancel"),
  4081.                        NULL, NULL,
  4082.                        gfig_really_ok_callback,
  4083.                        data);
  4084.       g_free (message);
  4085.  
  4086.       gtk_widget_show (dialog);
  4087.     }
  4088.   else
  4089.     {
  4090.       gfig_run = TRUE;
  4091.       gtk_widget_destroy (GTK_WIDGET (data));
  4092.     }
  4093. }
  4094.  
  4095. /* Update the bits we put on the screen */
  4096. static void
  4097. update_draw_area (GtkWidget *widget,
  4098.           GdkEvent  *event)
  4099. {
  4100.   if (!GTK_WIDGET_DRAWABLE (widget))
  4101.     return;
  4102.  
  4103.   gtk_signal_handler_block (GTK_OBJECT (widget), gfig_preview_exp_id);
  4104.   gtk_widget_draw (widget, NULL);
  4105.   gtk_signal_handler_unblock (GTK_OBJECT (widget), gfig_preview_exp_id);
  4106.  
  4107.   draw_grid (widget, 0);
  4108.   draw_objects (current_obj->obj_list, TRUE);
  4109. }
  4110.  
  4111. static gint
  4112. gfig_preview_expose (GtkWidget *widget,
  4113.              GdkEvent  *event)
  4114. {
  4115.   GdkCursor *preview_cursor;
  4116.   static gint changed_cursor = 0;
  4117.  
  4118.   if (!changed_cursor && gfig_preview->window)
  4119.     {
  4120.       changed_cursor = 1;
  4121.       preview_cursor = gdk_cursor_new (GDK_CROSSHAIR);
  4122.       gdk_window_set_cursor (gfig_preview->window, preview_cursor);
  4123.     }
  4124.   update_draw_area (widget, event);
  4125.   return FALSE;
  4126. }
  4127.  
  4128. static gint
  4129. pic_preview_expose (GtkWidget *widget,
  4130.             GdkEvent  *event)
  4131. {
  4132.   if (pic_obj)
  4133.     {
  4134.       drawing_pic = TRUE;
  4135.       draw_objects (pic_obj->obj_list, FALSE);
  4136.       drawing_pic = FALSE;
  4137.     }
  4138.   return FALSE;
  4139. }
  4140.  
  4141. static gint
  4142. adjust_pic_coords (gint coord,
  4143.            gint ratio)
  4144. {
  4145.   /*return ((SMALL_PREVIEW_SZ * coord)/PREVIEW_SIZE);*/
  4146.   static gint pratio = -1;
  4147.  
  4148.   if (pratio == -1)
  4149.     {
  4150.       pratio = MAX (preview_width, preview_height);
  4151.     }
  4152.  
  4153.   return (SMALL_PREVIEW_SZ * coord) / pratio;
  4154. }
  4155.  
  4156. static gint
  4157. gfig_preview_events (GtkWidget *widget,
  4158.              GdkEvent  *event)
  4159. {
  4160.   GdkEventButton *bevent;
  4161.   GdkEventMotion *mevent;
  4162.   GdkPoint point;
  4163.   static gint tmp_show_single = 0;
  4164.  
  4165.   switch (event->type)
  4166.     {
  4167.     case GDK_EXPOSE:
  4168.       break;
  4169.  
  4170.     case GDK_BUTTON_PRESS:
  4171.       bevent = (GdkEventButton *) event;
  4172.       point.x = bevent->x;
  4173.       point.y = bevent->y;
  4174.  
  4175.       g_assert (need_to_scale == 0); /* If not out of step some how */
  4176.  
  4177.       /* Start drawing of object */
  4178.       if (selvals.otype >= MOVE_OBJ)
  4179.     {
  4180.       if (!selvals.scaletoimage)
  4181.         {
  4182.           point.x = gfig_invscale_x (point.x);
  4183.           point.y = gfig_invscale_y (point.y);
  4184.         }
  4185.       object_operation_start (&point, bevent->state & GDK_SHIFT_MASK);
  4186.  
  4187.       /* If constraining save start pnt */
  4188.       if (selvals.opts.snap2grid)
  4189.         {
  4190.           /* Save point to constained point ... if button 3 down */
  4191.           if (bevent->button == 3)
  4192.         {
  4193.           find_grid_pos (&point, &point, FALSE);
  4194.         }
  4195.         }
  4196.     }
  4197.       else
  4198.     {
  4199.       if (selvals.opts.snap2grid)
  4200.         {
  4201.           if (bevent->button == 3)
  4202.         {
  4203.           find_grid_pos (&point, &point, FALSE);
  4204.         }
  4205.           else
  4206.         {
  4207.           find_grid_pos (&point, &point, FALSE);
  4208.         }
  4209.         }
  4210.       object_start (&point, bevent->state & GDK_SHIFT_MASK);
  4211.     }
  4212.  
  4213.       break;
  4214.     case GDK_BUTTON_RELEASE:
  4215.       bevent = (GdkEventButton *) event;
  4216.       point.x = bevent->x;
  4217.       point.y = bevent->y;
  4218.  
  4219.       if (selvals.opts.snap2grid)
  4220.     find_grid_pos (&point, &point, bevent->button == 3);
  4221.  
  4222.       /* Still got shift down ?*/
  4223.       if (selvals.otype >= MOVE_OBJ)
  4224.     {
  4225.       if (!selvals.scaletoimage)
  4226.         {
  4227.           point.x = gfig_invscale_x (point.x);
  4228.           point.y = gfig_invscale_y (point.y);
  4229.         }
  4230.       object_operation_end (&point, bevent->state & GDK_SHIFT_MASK);
  4231.     }
  4232.       else
  4233.     {
  4234.       if (obj_creating)
  4235.         {
  4236.           object_end (&point, bevent->state & GDK_SHIFT_MASK);
  4237.         }
  4238.       else
  4239.         break;
  4240.     }
  4241.  
  4242.       /* make small preview reflect changes ?*/
  4243.       list_button_update (current_obj);
  4244.       break;
  4245.     case GDK_MOTION_NOTIFY:
  4246.  
  4247.       mevent = (GdkEventMotion *) event;
  4248.       point.x = mevent->x;
  4249.       point.y = mevent->y;
  4250.  
  4251.       if (selvals.opts.snap2grid)
  4252.     find_grid_pos (&point, &point, mevent->state & GDK_BUTTON3_MASK);
  4253.  
  4254.       if (selvals.otype >= MOVE_OBJ)
  4255.     {
  4256.       /* Moving objects around */
  4257.       if (!selvals.scaletoimage)
  4258.         {
  4259.           point.x = gfig_invscale_x (point.x);
  4260.           point.y = gfig_invscale_y (point.y);
  4261.         }
  4262.       object_operation (&point, mevent->state & GDK_SHIFT_MASK);
  4263.       gfig_pos_update (point.x, point.y);
  4264.       return FALSE;
  4265.     }
  4266.  
  4267.       if (obj_creating)
  4268.     {
  4269.       object_update (&point);
  4270.     }
  4271.       gfig_pos_update (point.x, point.y);
  4272.       break;
  4273.     case GDK_KEY_PRESS:
  4274.       if ((tmp_show_single = obj_show_single) != -1)
  4275.     {
  4276.       obj_show_single = -1;
  4277.       draw_grid_clear (NULL, NULL); /*Args not used */
  4278.     }
  4279.       break;
  4280.     case GDK_KEY_RELEASE:
  4281.       if (tmp_show_single != -1)
  4282.     {
  4283.       obj_show_single = tmp_show_single;
  4284.       draw_grid_clear (NULL, NULL); /*Args not used */
  4285.     }
  4286.       break;
  4287.     default:
  4288.       break;
  4289.     }
  4290.   return FALSE;
  4291. }
  4292.  
  4293.  
  4294. /*
  4295.  *  The edit gfig name attributes dialog
  4296.  *  Modified from Gimp source - layer edit.
  4297.  */
  4298.  
  4299. typedef struct _GfigListOptions
  4300. {
  4301.   GtkWidget *query_box;
  4302.   GtkWidget *name_entry;
  4303.   GtkWidget *list_entry;
  4304.   GFigObj   *obj;
  4305.   gint       created;
  4306. } GfigListOptions;
  4307.  
  4308. static GtkWidget *
  4309. gfig_list_add (GFigObj *obj)
  4310. {
  4311.   GList     *list;
  4312.   gint       pos;
  4313.   GtkWidget *list_item;
  4314.   GtkWidget *list_pix;
  4315.  
  4316.   list_pix  = gimp_pixmap_new (Floppy6_xpm);
  4317.   list_item =
  4318.     gfig_list_item_new_with_label_and_pixmap (obj, obj->draw_name, list_pix);
  4319.  
  4320.   gtk_object_set_user_data (GTK_OBJECT (list_item), (gpointer) obj);
  4321.  
  4322.   pos = gfig_list_insert (obj);
  4323.  
  4324.   list = g_list_append (NULL, list_item);
  4325.   gtk_list_insert_items (GTK_LIST (gfig_gtk_list), list, pos);
  4326.   gtk_widget_show (list_item);
  4327.   gtk_list_select_item (GTK_LIST (gfig_gtk_list), pos);  
  4328.  
  4329.   gtk_signal_connect (GTK_OBJECT (list_item), "button_press_event",
  4330.               GTK_SIGNAL_FUNC (list_button_press),
  4331.               (gpointer) obj);
  4332.  
  4333.   return list_item;
  4334. }
  4335.  
  4336. static void
  4337. gfig_list_ok_callback (GtkWidget *widget,
  4338.                gpointer   data)
  4339. {
  4340.   GfigListOptions *options;
  4341.   GtkWidget *list;
  4342.   gint pos;
  4343.  
  4344.   options = (GfigListOptions *) data;
  4345.   list = options->list_entry;
  4346.  
  4347.   /*  Set the new layer name  */
  4348. #ifdef DEBUG
  4349.   printf ("Found obj %s\n", options->obj->draw_name);
  4350. #endif /* DEBUG */
  4351.   if (options->obj->draw_name)
  4352.     {
  4353.       g_free (options->obj->draw_name);
  4354.     }
  4355.   options->obj->draw_name =
  4356.     g_strdup (gtk_entry_get_text (GTK_ENTRY (options->name_entry)));
  4357. #ifdef DEBUG
  4358.   printf ("NEW name %s\n", options->obj->draw_name);
  4359. #endif /* DEBUG */
  4360.  
  4361.   /* Need to reorder the list */
  4362. /* gtk_label_set_text (GTK_LABEL (options->layer_widget->label), layer->name);*/
  4363.  
  4364.   pos = gtk_list_child_position (GTK_LIST (gfig_gtk_list), list);
  4365. #ifdef DEBUG
  4366.   printf ("pos = %d\n", pos);
  4367. #endif /* DEBUG */
  4368.  
  4369.   gtk_list_clear_items (GTK_LIST (gfig_gtk_list), pos, pos + 1);
  4370.  
  4371.   /* remove/Add again */
  4372.   gfig_list = g_list_remove (gfig_list, options->obj);
  4373.   gfig_list_add (options->obj);
  4374.  
  4375.   options->obj->obj_status |= GFIG_MODIFIED;
  4376.  
  4377.   gtk_widget_destroy (options->query_box);
  4378.   g_free (options);
  4379.  
  4380.   gfig_update_stat_labels ();
  4381. }
  4382.  
  4383. static void
  4384. gfig_list_cancel_callback (GtkWidget *widget,
  4385.                gpointer   data)
  4386. {
  4387.   GfigListOptions *options;
  4388.  
  4389.   options = (GfigListOptions *) data;
  4390.   if (options->created)
  4391.     {
  4392.       /* We are creating an entry so if cancelled
  4393.        * must del the list item as well
  4394.        */
  4395.       gfig_do_delete_gfig_callback (widget, TRUE, gfig_gtk_list);
  4396.     }
  4397.  
  4398.   gtk_widget_destroy (options->query_box);
  4399.   g_free (options);
  4400. }
  4401.  
  4402. static void
  4403. gfig_dialog_edit_list (GtkWidget *lwidget,
  4404.                GFigObj   *obj,
  4405.                gint       created)
  4406. {
  4407.   GfigListOptions *options;
  4408.   GtkWidget *vbox;
  4409.   GtkWidget *hbox;
  4410.   GtkWidget *label;
  4411.  
  4412.   /*  the new options structure  */
  4413.   options = g_new (GfigListOptions, 1);
  4414.   options->list_entry = lwidget;
  4415.   options->obj        = obj;
  4416.   options->created    = created;
  4417.  
  4418.   /*  the dialog  */
  4419.   options->query_box =
  4420.     gimp_dialog_new (_("Enter Gfig Entry Name"), "gfig",
  4421.              gimp_standard_help_func, "filters/gfig.html",
  4422.              GTK_WIN_POS_MOUSE,
  4423.              FALSE, TRUE, FALSE,
  4424.  
  4425.              _("OK"), gfig_list_ok_callback,
  4426.              options, NULL, NULL, TRUE, FALSE,
  4427.              _("Cancel"), gfig_list_cancel_callback,
  4428.              options, NULL, NULL, FALSE, TRUE,
  4429.  
  4430.              NULL);
  4431.  
  4432.   /*  the main vbox  */
  4433.   vbox = gtk_vbox_new (FALSE, 2);
  4434.   gtk_container_set_border_width (GTK_CONTAINER (vbox), 6);
  4435.   gtk_box_pack_start (GTK_BOX (GTK_DIALOG (options->query_box)->vbox), vbox,
  4436.               FALSE, FALSE, 0);
  4437.   gtk_widget_show (vbox);
  4438.  
  4439.   /*  the name entry hbox, label and entry  */
  4440.   hbox = gtk_hbox_new (FALSE, 4);
  4441.   gtk_box_pack_start (GTK_BOX (vbox), hbox, FALSE, FALSE, 0);
  4442.   gtk_widget_show (hbox);
  4443.  
  4444.   label = gtk_label_new (_("Gfig Object Name:"));
  4445.   gtk_box_pack_start (GTK_BOX (hbox), label, FALSE, FALSE, 0);
  4446.   gtk_widget_show (label);
  4447.  
  4448.   options->name_entry = gtk_entry_new ();
  4449.   gtk_box_pack_start (GTK_BOX (hbox), options->name_entry, TRUE, TRUE, 0);
  4450.   gtk_entry_set_text (GTK_ENTRY (options->name_entry), obj->draw_name);
  4451.   gtk_widget_show (options->name_entry);
  4452.  
  4453.   gtk_widget_show (options->query_box);
  4454. }
  4455.  
  4456. static void
  4457. gfig_rescan_ok_callback (GtkWidget *widget,
  4458.              gpointer   data)
  4459. {
  4460.   GtkWidget *patheditor;
  4461.   gchar     *raw_path;
  4462.  
  4463.   gtk_widget_set_sensitive (GTK_WIDGET (data), FALSE);
  4464.  
  4465.   gimp_path_free (gfig_path_list);
  4466.   gfig_path_list = NULL;
  4467.  
  4468.   patheditor = GTK_WIDGET (gtk_object_get_data (GTK_OBJECT (data),
  4469.                         "patheditor"));
  4470.  
  4471.   raw_path = gimp_path_editor_get_path (GIMP_PATH_EDITOR (patheditor));
  4472.  
  4473.   gfig_path_list = gimp_path_parse (raw_path, 16, FALSE, NULL);
  4474.  
  4475.   g_free (raw_path);
  4476.  
  4477.   if (gfig_path_list)
  4478.     {
  4479.       clear_list_items (GTK_LIST (gfig_gtk_list));
  4480.       gfig_list_load_all (gfig_path_list);
  4481.       build_list_items (gfig_gtk_list);
  4482.       list_button_update (current_obj);
  4483.     }
  4484.  
  4485.   gtk_widget_destroy (GTK_WIDGET (data));
  4486. }
  4487.  
  4488. static void
  4489. gfig_rescan_list (void)
  4490. {
  4491.   static GtkWidget *dlg = NULL;
  4492.  
  4493.   GtkWidget *patheditor;
  4494.   gchar     *path;
  4495.  
  4496.   if (dlg)
  4497.     {
  4498.       gdk_window_raise (dlg->window);
  4499.       return;
  4500.     }
  4501.  
  4502.   /*  the dialog  */
  4503.   dlg = gimp_dialog_new (_("Rescan for Gfig Objects"), "gfig",
  4504.              gimp_standard_help_func, "filters/gfig.html",
  4505.              GTK_WIN_POS_MOUSE,
  4506.              FALSE, TRUE, FALSE,
  4507.  
  4508.              _("OK"), gfig_rescan_ok_callback,
  4509.              NULL, NULL, NULL, TRUE, FALSE,
  4510.              _("Cancel"), gtk_widget_destroy,
  4511.              NULL, 1, NULL, FALSE, TRUE,
  4512.  
  4513.              NULL);
  4514.  
  4515.   gtk_signal_connect (GTK_OBJECT (dlg), "destroy",
  4516.               GTK_SIGNAL_FUNC (gtk_widget_destroyed),
  4517.               &dlg);
  4518.  
  4519.   path = gimp_path_to_str (gfig_path_list);
  4520.  
  4521.   patheditor = gimp_path_editor_new (_("Add Gfig Path"), path);
  4522.   gtk_container_set_border_width (GTK_CONTAINER (patheditor), 6);
  4523.   gtk_box_pack_start (GTK_BOX (GTK_DIALOG (dlg)->vbox), patheditor,
  4524.               TRUE, TRUE, 0);
  4525.   gtk_widget_show (patheditor);
  4526.  
  4527.   g_free (path);
  4528.  
  4529.   gtk_object_set_data (GTK_OBJECT (dlg), "patheditor", patheditor);
  4530.  
  4531.   gtk_widget_show (dlg);
  4532. }
  4533.  
  4534. static void
  4535. list_button_update (GFigObj *obj)
  4536. {
  4537.   g_return_if_fail (obj != NULL);
  4538.  
  4539.   pic_obj = (GFigObj *) obj;
  4540.  
  4541.   gtk_widget_draw (pic_preview, NULL);
  4542.  
  4543.   drawing_pic = TRUE;
  4544.   draw_objects (pic_obj->obj_list, FALSE);
  4545.   drawing_pic = FALSE;
  4546. }
  4547.  
  4548.  
  4549. static void
  4550. gfig_load_file_selection_ok (GtkWidget        *widget,
  4551.                      GtkFileSelection *fs,
  4552.                      gpointer          data)
  4553. {
  4554.   gchar       *filename;
  4555.   struct stat  filestat;
  4556.   gint         err;
  4557.   GFigObj     *gfig;
  4558.   GFigObj     *current_saved;
  4559.  
  4560.   filename = gtk_file_selection_get_filename (GTK_FILE_SELECTION (fs));
  4561.  
  4562. #ifdef DEBUG
  4563.   printf ("Loading file '%s'\n", filename);
  4564. #endif /* DEBUG */
  4565.  
  4566.   err = stat (filename, &filestat);
  4567.  
  4568.   if (!err && S_ISREG (filestat.st_mode))
  4569.     {
  4570.       /* Hack - current object MUST be NULL to prevent setup_undo ()
  4571.        * from kicking in.
  4572.        */
  4573.       current_saved = current_obj;
  4574.       current_obj = NULL;
  4575.       gfig = gfig_load (filename, filename);
  4576.       current_obj = current_saved;
  4577.       
  4578.       if (gfig)
  4579.     {
  4580.       /* Read only ?*/
  4581.       if (access (filename, W_OK))
  4582.         gfig->obj_status |= GFIG_READONLY;
  4583.  
  4584.       gfig_list_add (gfig);
  4585.       new_obj_2edit (gfig);
  4586.     }
  4587.     }
  4588.  
  4589.   gtk_widget_destroy (GTK_WIDGET (fs));
  4590. }
  4591.  
  4592. static void
  4593. load_button_callback (GtkWidget *widget,
  4594.               gpointer   data)
  4595. {
  4596.   static GtkWidget *window = NULL;
  4597.  
  4598.   /* Load a single object */
  4599.   window = gtk_file_selection_new (_("Load Gfig obj"));
  4600.   gtk_window_set_position (GTK_WINDOW (window), GTK_WIN_POS_MOUSE);
  4601.  
  4602.   gtk_signal_connect (GTK_OBJECT (window), "destroy",
  4603.               GTK_SIGNAL_FUNC (gtk_widget_destroyed),
  4604.               &window);
  4605.  
  4606.   gtk_signal_connect (GTK_OBJECT (GTK_FILE_SELECTION (window)->ok_button),
  4607.               "clicked",
  4608.               GTK_SIGNAL_FUNC (gfig_load_file_selection_ok),
  4609.               (gpointer) window);
  4610.  
  4611.   gtk_signal_connect_object (GTK_OBJECT (GTK_FILE_SELECTION (window)->cancel_button),
  4612.                  "clicked",
  4613.                  GTK_SIGNAL_FUNC (gtk_widget_destroy),
  4614.                  GTK_OBJECT (window));
  4615.   gtk_widget_show (window);
  4616. }
  4617.  
  4618. static void
  4619. paint_layer_copy (gchar *new_name)
  4620. {
  4621.   gint32 old_drawable = gfig_drawable;
  4622.   if ((gfig_drawable = gimp_layer_copy (gfig_drawable)) < 0)
  4623.     {
  4624.       g_warning (_("Error in copy layer for onlayers"));
  4625.       gfig_drawable = old_drawable;
  4626.       return;
  4627.     }
  4628.  
  4629.   gimp_layer_set_name (gfig_drawable, new_name);
  4630.   gimp_image_add_layer (gfig_image, gfig_drawable, -1);
  4631. }
  4632.  
  4633. static void
  4634. paint_layer_new (gchar *new_name)
  4635. {
  4636.   gint32 layer_id;
  4637.   gint32 fill_type;
  4638.   int isgrey = 0;
  4639.  
  4640.   switch (gimp_drawable_type (gfig_select_drawable->id))
  4641.     {
  4642.     case GIMP_GRAYA_IMAGE:
  4643.     case GIMP_GRAY_IMAGE:
  4644.       isgrey = 2;
  4645.     default:
  4646.       break;
  4647.     }
  4648.  
  4649.   if ((layer_id = gimp_layer_new (gfig_image,
  4650.                   new_name,
  4651.                   img_width,
  4652.                   img_height,
  4653.                   1 + isgrey, /* RGBA or GRAYA type */
  4654.                   100.0, /* opacity */
  4655.                   0 /* mode */)) < 0)
  4656.     g_warning (_("Error in creating layer"));
  4657.   else
  4658.     {
  4659.       gimp_image_add_layer (gfig_image, layer_id, -1);
  4660.       gimp_drawable_fill (layer_id, 1);
  4661.     }
  4662.   
  4663.   gfig_drawable = layer_id;
  4664.   
  4665.   switch (selvals.onlayerbg)
  4666.     {
  4667.     case LAYER_TRANS_BG:
  4668.       fill_type = 3;
  4669.       break;
  4670.     case LAYER_BG_BG:
  4671.       fill_type = 1;
  4672.       break;
  4673.     case LAYER_FG_BG:
  4674.       fill_type = 0;
  4675.       break;
  4676.     case LAYER_WHITE_BG:
  4677.       fill_type = 2;
  4678.       break;
  4679.     case LAYER_COPY_BG:
  4680.     default:
  4681.       fill_type = 1;
  4682.       g_warning ("Paint layer new internal error %d\n", selvals.onlayerbg);
  4683.       break;
  4684.     }
  4685.   /* Have to clear layer out since creating transparent layer
  4686.    * seems to leave rubbish in it.
  4687.    */
  4688.  
  4689.   gimp_drawable_fill (layer_id, fill_type);
  4690.  
  4691. }
  4692.  
  4693. static void
  4694. paint_layer_fill ()
  4695. {
  4696.   gimp_bucket_fill (gfig_drawable,
  4697.             selopt.fill_type,    /* Fill mode */
  4698.             GIMP_NORMAL_MODE,
  4699.             selopt.fill_opacity, /* Fill opacity */
  4700.             0.0,                 /* threshold - ignored */
  4701.             FALSE,               /* Sample merged - ignored */
  4702.             0.0,                 /* x - ignored */
  4703.             0.0);                /* y - ignored */
  4704. }
  4705.        
  4706. static void
  4707. gfig_paint_callback (GtkWidget *widget,
  4708.              gpointer   data)
  4709. {
  4710.   DAllObjs * objs;
  4711.   gint layer_count = 0;
  4712.   gchar buf[128];
  4713.   gint count;
  4714.   gint ccount = 0;
  4715.   BrushDesc *bdesc;
  4716.  
  4717.   objs = current_obj->obj_list;
  4718.  
  4719.   count = gfig_obj_counts (objs);
  4720. #if 0
  4721.   gtk_progress_bar_update (GTK_PROGRESS_BAR (progress_widget), (gfloat) 0.0);
  4722. #endif /* 0 */
  4723.  
  4724.   /* Set the brush up */
  4725.   bdesc = gtk_object_get_user_data (GTK_OBJECT (brush_page_pw));
  4726.  
  4727.   if (bdesc)
  4728.     mygimp_brush_set (bdesc->bname);
  4729.  
  4730.   while (objs)
  4731.     {
  4732.  
  4733.       if (ccount == obj_show_single || obj_show_single == -1)
  4734.     {
  4735.       sprintf (buf, _("Gfig Layer %d"), layer_count++);
  4736.       
  4737.       if (selvals.painttype != PAINT_SELECTION_TYPE)
  4738.         {
  4739.           switch (selvals.onlayers)
  4740.         {
  4741.         case SINGLE_LAYER:
  4742.           if (layer_count == 1)
  4743.             {
  4744.               if (selvals.onlayerbg == LAYER_COPY_BG)
  4745.             paint_layer_copy (buf);
  4746.               else
  4747.             paint_layer_new (buf);
  4748.             }
  4749.           break;
  4750.         case MULTI_LAYER:
  4751.           if (selvals.onlayerbg == LAYER_COPY_BG)
  4752.             paint_layer_copy (buf);
  4753.           else
  4754.             paint_layer_new (buf);
  4755.           break;
  4756.         case ORIGINAL_LAYER:
  4757.           /* Just use the given layer */
  4758.           break;
  4759.         default:
  4760.           g_warning ("Error in onlayers val %d", selvals.onlayers);
  4761.           break;
  4762.         }
  4763.         }
  4764.       
  4765.       objs->obj->paintfunc (objs->obj);
  4766.       
  4767.       /* Fill layer if required */
  4768.       if (selvals.painttype == PAINT_SELECTION_FILL_TYPE 
  4769.           && selopt.fill_when == FILL_EACH)
  4770.         paint_layer_fill ();
  4771.     }
  4772.  
  4773.       objs = objs->next;
  4774.       
  4775.       ccount++;
  4776. #if 0 
  4777.       gtk_progress_bar_update (GTK_PROGRESS_BAR (progress_widget), (gfloat)ccount/(gfloat)count);
  4778.       gtk_widget_draw (GTK_WIDGET (progress_widget), NULL);
  4779. #endif /* 0 */
  4780.     }
  4781.  
  4782.   /* Fill layer if required */
  4783.   if (selvals.painttype == PAINT_SELECTION_FILL_TYPE 
  4784.       && selopt.fill_when == FILL_AFTER)
  4785.     paint_layer_fill ();
  4786.  
  4787.   gimp_displays_flush ();
  4788. }
  4789.  
  4790. static void
  4791. reload_button_callback (GtkWidget *widget,
  4792.             gpointer   data)
  4793. {
  4794.   refill_cache ();
  4795.   draw_grid_clear (widget, data);
  4796. }
  4797.  
  4798. static void
  4799. about_button_callback (GtkWidget *widget,
  4800.                gpointer   data)
  4801. {
  4802.   GtkWidget *window;
  4803.   GtkWidget *label;
  4804.   GtkWidget *hbox;
  4805.   GtkWidget *vbox;
  4806.   GtkWidget *pm;
  4807.  
  4808.   window = gimp_dialog_new (_("About GFig"), "gfig",
  4809.                 gimp_standard_help_func, "filters/gfig.html",
  4810.                 GTK_WIN_POS_MOUSE,
  4811.                 FALSE, FALSE, FALSE,
  4812.  
  4813.                 _("OK"), gtk_widget_destroy,
  4814.                 NULL, 1, NULL, TRUE, TRUE,
  4815.  
  4816.                 NULL);
  4817.  
  4818.   /* Bits and bobs */
  4819.   pm = gimp_pixmap_new (rulers_comp_xpm);
  4820.   gtk_widget_show (pm);
  4821.  
  4822.   hbox = gtk_hbox_new (FALSE, 1);
  4823.   gtk_widget_show (hbox);
  4824.  
  4825.   vbox = gtk_vbox_new (FALSE, 1);
  4826.   gtk_widget_show (vbox);
  4827.  
  4828.   gtk_box_pack_start (GTK_BOX (hbox), pm, TRUE, TRUE, 0);
  4829.   gtk_box_pack_start (GTK_BOX (hbox), vbox, TRUE, TRUE, 0);
  4830.   gtk_box_pack_start (GTK_BOX (GTK_DIALOG (window)->vbox), hbox, TRUE, TRUE, 0);
  4831.  
  4832.   label = gtk_label_new (_("Gfig - GIMP plug-in"));
  4833.   gtk_misc_set_padding (GTK_MISC (label), 2, 2);
  4834.   gtk_widget_show (label);
  4835.   gtk_box_pack_start (GTK_BOX (vbox), label, FALSE, FALSE, 0);
  4836.  
  4837.   label = gtk_label_new (_("Release 1.3"));
  4838.   gtk_misc_set_padding (GTK_MISC (label), 2, 2);
  4839.   gtk_widget_show (label);
  4840.   gtk_box_pack_start (GTK_BOX (vbox), label, FALSE, FALSE, 0);
  4841.  
  4842.   label = gtk_label_new ("Andy Thomas");
  4843.   gtk_misc_set_padding (GTK_MISC (label), 2, 2);
  4844.   gtk_widget_show (label);
  4845.   gtk_box_pack_start (GTK_BOX (vbox), label, FALSE, FALSE, 0);
  4846.  
  4847.   label = gtk_label_new (_("Email alt@picnic.demon.co.uk"));
  4848.   gtk_misc_set_padding (GTK_MISC (label), 2, 2);
  4849.   gtk_widget_show (label);
  4850.   gtk_box_pack_start (GTK_BOX (vbox), label, FALSE, FALSE, 0);
  4851.  
  4852.   label = gtk_label_new ("http://www.picnic.demon.co.uk/");
  4853.   gtk_misc_set_padding (GTK_MISC (label), 2, 2);
  4854.   gtk_widget_show (label);
  4855.   gtk_box_pack_start (GTK_BOX (vbox), label, FALSE, FALSE, 0);
  4856.  
  4857.   label = gtk_label_new (_("Isometric grid By Rob Saunders"));
  4858.   gtk_misc_set_padding (GTK_MISC (label), 2, 2);
  4859.   gtk_widget_show (label);
  4860.   gtk_box_pack_start (GTK_BOX (vbox), label, FALSE, FALSE, 0);
  4861.  
  4862.   gtk_widget_show (window);
  4863. }
  4864.  
  4865.  
  4866. static void
  4867. save_button_callback (GtkWidget *widget,
  4868.               gpointer   data)
  4869. {
  4870.   gfig_save ();  /* Save current object */
  4871. }
  4872.  
  4873. static void
  4874. rescan_button_callback (GtkWidget *widget,
  4875.             gpointer   data)
  4876. {
  4877.   gfig_rescan_list ();
  4878. }
  4879.  
  4880. static GtkWidget *
  4881. new_gfig_obj (gchar *name)
  4882. {
  4883.   GFigObj   *gfig;
  4884.   GtkWidget *new_list_item;
  4885.   /* Create a new entry */
  4886.  
  4887.   gfig = gfig_new ();
  4888.  
  4889.   if (!name)
  4890.     name = _("New gfig obj");
  4891.  
  4892.   gfig->draw_name = g_strdup (name);
  4893.  
  4894.   /* Leave options as before */
  4895.   pic_obj = current_obj = gfig;
  4896.  
  4897.   new_list_item = gfig_list_add (gfig);
  4898.  
  4899.   tmp_bezier = obj_creating = tmp_line = NULL;
  4900.  
  4901.   /* Redraw areas */
  4902.   update_draw_area (gfig_preview, NULL);
  4903.   list_button_update (gfig);
  4904.  
  4905.   return new_list_item;
  4906. }
  4907.  
  4908. static void
  4909. new_button_callback (GtkWidget *widget,
  4910.              gpointer   data)
  4911. {
  4912.   GtkWidget *new_list_item;
  4913.  
  4914.   new_list_item = new_gfig_obj ((gchar*) data);
  4915.   gfig_dialog_edit_list (new_list_item, current_obj, TRUE);
  4916. }
  4917.  
  4918. static GtkWidget *delete_dialog = NULL;
  4919.  
  4920. static void
  4921. gfig_do_delete_gfig_callback (GtkWidget *widget,
  4922.                   gboolean   delete,
  4923.                   gpointer   data)
  4924. {
  4925.   gint pos;
  4926.   GList *sellist;
  4927.   GFigObj *sel_obj;
  4928.   GtkWidget *list = (GtkWidget *) data;
  4929.  
  4930.   if (!delete)
  4931.     {
  4932.       gtk_widget_set_sensitive (delete_frame_to_freeze, TRUE);
  4933.       return;
  4934.     }
  4935.  
  4936. #ifdef DEBUG
  4937.   printf ("Delete button pressed\n");
  4938. #endif /* DEBUG */
  4939.   /* Must update which object we are editing */
  4940.   /* Get the list and which item is selected */
  4941.   /* Only allow single selections */
  4942.  
  4943.   sellist = GTK_LIST (list)->selection; 
  4944.  
  4945.   sel_obj = (GFigObj *) gtk_object_get_user_data (GTK_OBJECT (sellist->data));
  4946.  
  4947.   pos = gtk_list_child_position (GTK_LIST (gfig_gtk_list), sellist->data);
  4948. #ifdef DEBUG
  4949.   printf ("delete pos = %d\n", pos);
  4950. #endif /* DEBUG */
  4951.  
  4952.   /* Delete the current  item + asssociated file */
  4953.   gtk_list_clear_items (GTK_LIST (gfig_gtk_list), pos, pos + 1);
  4954.   /* Shadow copy for ordering info */
  4955.   gfig_list = g_list_remove (gfig_list, sel_obj);
  4956.  
  4957.   if (sel_obj == current_obj)
  4958.     {
  4959.       clear_undo ();
  4960.     }
  4961.   
  4962.   /* Free current obj */
  4963.   gfig_free_everything (sel_obj);
  4964.  
  4965.   /* Select previous one */
  4966.   pos--;
  4967.  
  4968.   if (pos < 0)
  4969.     {
  4970.       if (g_list_length (gfig_list) == 0)
  4971.     {
  4972.       /* Warning - we have a problem here
  4973.        * since we are not really "creating an entry"
  4974.        * why call gfig_new?
  4975.        */
  4976.       new_button_callback (NULL, NULL);
  4977.     }
  4978.  
  4979.       pos = 0;
  4980.     }
  4981.  
  4982.   gtk_widget_set_sensitive (delete_frame_to_freeze, TRUE);
  4983.  
  4984.   gtk_list_select_item (GTK_LIST (gfig_gtk_list), pos);  
  4985.  
  4986.   current_obj = g_list_nth (gfig_list, pos)->data;
  4987.  
  4988.   update_draw_area (gfig_preview, NULL);
  4989.  
  4990.   list_button_update (current_obj);
  4991.  
  4992.   gfig_update_stat_labels ();
  4993. }
  4994.  
  4995. static void
  4996. gfig_delete_gfig_callback (GtkWidget *widget,
  4997.                gpointer   data)
  4998. {
  4999.   gchar *str;
  5000.  
  5001.   GtkWidget *list = (GtkWidget *) data;
  5002.   GList * sellist;
  5003.   GFigObj * sel_obj;
  5004.  
  5005.   sellist = GTK_LIST (list)->selection; 
  5006.  
  5007.   sel_obj = (GFigObj *) gtk_object_get_user_data (GTK_OBJECT (sellist->data));
  5008.  
  5009.   if (delete_dialog)
  5010.     return;
  5011.  
  5012.   str = g_strdup_printf (_("Are you sure you want to delete\n"
  5013.                "\"%s\" from the list and from disk?"),
  5014.              sel_obj->draw_name);
  5015.  
  5016.   delete_dialog = gimp_query_boolean_box (_("Delete Gfig Drawing"),
  5017.                       gimp_standard_help_func,
  5018.                       "filters/gfig.html",
  5019.                       FALSE,
  5020.                       str,
  5021.                       _("Delete"), _("Cancel"),
  5022.                       NULL, NULL,
  5023.                       gfig_do_delete_gfig_callback,
  5024.                       data);
  5025.  
  5026.   g_free (str);
  5027.  
  5028.   gtk_signal_connect (GTK_OBJECT (delete_dialog), "destroy",
  5029.               GTK_SIGNAL_FUNC (gtk_widget_destroyed),
  5030.               &delete_dialog);
  5031.  
  5032.   gtk_widget_set_sensitive (GTK_WIDGET (delete_frame_to_freeze), FALSE);
  5033.   gtk_widget_show (delete_dialog);
  5034.  
  5035. static void
  5036. gfig_update_stat_labels (void)
  5037. {
  5038.   gchar str[45];
  5039.  
  5040.   if (current_obj->draw_name)
  5041.     sprintf (str, "%.34s", current_obj->draw_name);
  5042.   else
  5043.     sprintf (str,_("<NONE>"));
  5044.  
  5045.   gtk_label_set_text (GTK_LABEL (status_label_dname), str);
  5046.  
  5047.   if (current_obj->filename)
  5048.     {
  5049.       gint slen;
  5050.       gchar *hm = g_get_home_dir ();
  5051.       gchar *dfn = g_strdup (current_obj->filename);
  5052. #ifdef __EMX__
  5053.       if (hm)
  5054.     hm = _fnslashify (hm);
  5055. #endif
  5056.  
  5057.       
  5058. #ifndef __EMX__
  5059.       if (hm != NULL && !strncmp (dfn, hm, strlen (hm)-1))
  5060. #else
  5061.       if (hm != NULL && !strnicmp (dfn, hm, strlen (hm)-1))
  5062. #endif
  5063.      {
  5064.        strcpy (dfn, "~");
  5065.        strcat (dfn, &dfn[strlen (hm)]);
  5066.      }
  5067.       if ((slen = strlen (dfn)) > 40)
  5068.     {
  5069.       strncpy (str, dfn, 19);
  5070.       str[19] = '\0';
  5071.       strcat (str, "...");
  5072.       strncat (str, &dfn[slen - 21], 19);
  5073.       str[40] ='\0';
  5074.     }
  5075.       else
  5076.     sprintf (str, "%.40s", dfn);
  5077.       g_free (dfn);
  5078. #ifdef __EMX__
  5079.       g_free (hm);
  5080. #endif
  5081.     }
  5082.   else
  5083.     sprintf (str,_("<NONE>"));
  5084.  
  5085.   gtk_label_set_text (GTK_LABEL (status_label_fname), str);
  5086.  
  5087. }
  5088.  
  5089. static void 
  5090. new_obj_2edit (GFigObj *obj)
  5091. {
  5092.   GFigObj *old_current = current_obj;
  5093.  
  5094.   /* Clear undo levels */
  5095.   /* redraw the preview */
  5096.   /* Set up options as define in the selected object */
  5097.  
  5098.   clear_undo ();
  5099.  
  5100.   /* Point at this one */
  5101.   current_obj = obj;
  5102.  
  5103.   /* Show all objects to start with */
  5104.   obj_show_single = -1;
  5105.  
  5106.   /* Change options */
  5107.   update_options (old_current);
  5108.  
  5109.   /* If have old object and NOT scaleing currently then force 
  5110.    * back to saved coord type.
  5111.    */
  5112.   gfig_update_stat_labels ();
  5113.  
  5114.   /* redraw with new */
  5115.   update_draw_area (gfig_preview, NULL);
  5116.   /* And preview */
  5117.   list_button_update (current_obj);
  5118.  
  5119.   if (obj->obj_status & GFIG_READONLY)
  5120.     {
  5121.       g_message (_("Editing read-only object - "
  5122.            "you will not be able to save it"));
  5123.       gtk_widget_set_sensitive (save_button, FALSE);
  5124.     }
  5125.   else
  5126.     {
  5127.       gtk_widget_set_sensitive (save_button, TRUE);
  5128.     }
  5129. }
  5130.  
  5131. static void
  5132. edit_button_callback (GtkWidget *widget,
  5133.               gpointer   data)
  5134. {
  5135.   GList     *sellist;
  5136.   GFigObj   *sel_obj;
  5137.   GtkWidget *list = (GtkWidget *) data;
  5138.  
  5139. #ifdef DEBUG
  5140.   printf ("Edit button pressed\n");
  5141. #endif /* DEBUG */
  5142.   /* Must update which object we are editing */
  5143.   /* Get the list and which item is selected */
  5144.   /* Only allow single selections */
  5145.  
  5146.   sellist = GTK_LIST (list)->selection; 
  5147.  
  5148.   sel_obj = (GFigObj *) gtk_object_get_user_data (GTK_OBJECT (sellist->data));
  5149.  
  5150.   if (sel_obj)
  5151.     new_obj_2edit (sel_obj);
  5152.   else
  5153.     g_warning ("Internal error - list item has null object!");
  5154. }
  5155.  
  5156. static void
  5157. merge_button_callback (GtkWidget *widget,
  5158.                gpointer   data)
  5159. {
  5160.   GList     *sellist;
  5161.   GFigObj   *sel_obj;
  5162.   DAllObjs  *obj_copies;
  5163.   GtkWidget *list = (GtkWidget *) data;
  5164.  
  5165. #ifdef DEBUG
  5166.   printf ("Merge button pressed\n");
  5167. #endif /* DEBUG */
  5168.   /* Must update which object we are editing */
  5169.   /* Get the list and which item is selected */
  5170.   /* Only allow single selections */
  5171.  
  5172.   sellist = GTK_LIST (list)->selection; 
  5173.  
  5174.   sel_obj = (GFigObj *) gtk_object_get_user_data (GTK_OBJECT (sellist->data));
  5175.  
  5176.   if (sel_obj && sel_obj->obj_list && sel_obj != current_obj)
  5177.     {
  5178.       /* Copy list tag onto current & redraw */
  5179.       obj_copies = copy_all_objs (sel_obj->obj_list);
  5180.       prepend_to_all_obj (current_obj, obj_copies);
  5181.  
  5182.       /* redraw all */
  5183.       update_draw_area (gfig_preview, NULL);
  5184.       /* And preview */
  5185.       list_button_update (current_obj);
  5186.     }
  5187. }
  5188.  
  5189.  
  5190. static void
  5191. gfig_save_menu_callback (GtkWidget *widget,
  5192.              gpointer   data)
  5193. {
  5194.   GFigObj * real_current = current_obj;
  5195.   /* Fiddle the current object and save it */
  5196.   /* What happens if we get a redraw here ? */
  5197.  
  5198.   current_obj = gfig_obj_for_menu;
  5199.  
  5200.   gfig_save ();  /* Save current object */
  5201.  
  5202.   current_obj = real_current;
  5203. }
  5204.  
  5205. static void
  5206. gfig_edit_menu_callback (GtkWidget *widget,
  5207.              gpointer   data)
  5208. {
  5209.   new_obj_2edit (gfig_obj_for_menu);
  5210. }
  5211.  
  5212. static void
  5213. gfig_rename_menu_callback (GtkWidget *widget,
  5214.                gpointer   data)
  5215. {
  5216.   create_file_selection (gfig_obj_for_menu, gfig_obj_for_menu->filename);
  5217. }
  5218.  
  5219. static void
  5220. gfig_copy_menu_callback (GtkWidget *widget,
  5221.              gpointer   data)
  5222. {
  5223.   /* Create new entry with name + copy at end & copy object into it */
  5224.   gchar *new_name = g_strdup_printf (_("%s copy"), gfig_obj_for_menu->draw_name);
  5225.   new_gfig_obj (new_name);
  5226.   g_free (new_name);
  5227.  
  5228.   /* Copy objs across */
  5229.   current_obj->obj_list = copy_all_objs (gfig_obj_for_menu->obj_list);
  5230.   current_obj->opts = gfig_obj_for_menu->opts; /* Structure copy */
  5231.  
  5232.   /* redraw all */
  5233.   update_draw_area (gfig_preview, NULL);
  5234.   /* And preview */
  5235.   list_button_update (current_obj);
  5236. }
  5237.  
  5238. static void
  5239. gfig_op_menu_create (GtkWidget *window)
  5240. {
  5241.   GtkWidget *menu_item;
  5242. #if 0
  5243.   GtkAcceleratorTable *accelerator_table;
  5244. #endif /* 0 */
  5245.  
  5246.   gfig_op_menu = gtk_menu_new ();
  5247.  
  5248. #if 0
  5249.   accelerator_table = gtk_accelerator_table_new ();
  5250.   gtk_menu_set_accelerator_table (GTK_MENU (gfig_op_menu),
  5251.                   accelerator_table);
  5252.   gtk_window_add_accelerator_table (GTK_WINDOW (window), accelerator_table);
  5253. #endif /* 0 */
  5254.  
  5255.   save_menu_item = menu_item = gtk_menu_item_new_with_label (_("Save"));
  5256.   gtk_menu_append (GTK_MENU (gfig_op_menu), menu_item);
  5257.   gtk_widget_show (menu_item);
  5258.  
  5259.   gtk_signal_connect (GTK_OBJECT (menu_item), "activate",
  5260.               (GtkSignalFunc)gfig_save_menu_callback,
  5261.               NULL);
  5262.  
  5263. #if 0 
  5264.   gtk_widget_install_accelerator (menu_item,
  5265.                   accelerator_table,
  5266.                   "activate", 'S', 0);
  5267. #endif /* 0 */
  5268.  
  5269.   menu_item = gtk_menu_item_new_with_label (_("Save as..."));
  5270.   gtk_menu_append (GTK_MENU (gfig_op_menu), menu_item);
  5271.   gtk_widget_show (menu_item);
  5272.   gtk_signal_connect (GTK_OBJECT (menu_item), "activate",
  5273.               (GtkSignalFunc)gfig_rename_menu_callback,
  5274.               NULL);
  5275.  
  5276. #if 0 
  5277.   gtk_widget_install_accelerator (menu_item,
  5278.                   accelerator_table,
  5279.                   "activate", 'A', 0);
  5280. #endif /* 0 */
  5281.  
  5282.   menu_item = gtk_menu_item_new_with_label (_("Copy"));
  5283.   gtk_menu_append (GTK_MENU (gfig_op_menu), menu_item);
  5284.   gtk_widget_show (menu_item);
  5285.   gtk_signal_connect (GTK_OBJECT (menu_item), "activate",
  5286.               (GtkSignalFunc)gfig_copy_menu_callback,
  5287.               NULL);
  5288.  
  5289. #if 0 
  5290.   gtk_widget_install_accelerator (menu_item,
  5291.                   accelerator_table,
  5292.                   "activate", 'C', 0);
  5293. #endif /* 0 */
  5294.  
  5295.   menu_item = gtk_menu_item_new_with_label (_("Edit"));
  5296.   gtk_menu_append (GTK_MENU (gfig_op_menu), menu_item);
  5297.   gtk_widget_show (menu_item);
  5298.   gtk_signal_connect (GTK_OBJECT (menu_item), "activate",
  5299.               (GtkSignalFunc)gfig_edit_menu_callback,
  5300.               NULL);
  5301.  
  5302. #if 0 
  5303.   gtk_widget_install_accelerator (menu_item,
  5304.                   accelerator_table,
  5305.                   "activate", 'E', 0);
  5306. #endif /* 0 */
  5307.  
  5308. }
  5309.  
  5310. static void
  5311. gfig_op_menu_popup (gint     button,
  5312.             guint32  activate_time,
  5313.             GFigObj *obj)
  5314. {
  5315.   gfig_obj_for_menu = obj; /* Static data again!*/
  5316.  
  5317.   if (obj->obj_status & GFIG_READONLY)
  5318.     {
  5319.       gtk_widget_set_sensitive (save_menu_item, FALSE);
  5320.     }
  5321.   else
  5322.     {
  5323.       gtk_widget_set_sensitive (save_menu_item, TRUE);
  5324.     }
  5325.  
  5326.   gtk_menu_popup (GTK_MENU (gfig_op_menu),
  5327.           NULL, NULL, NULL, NULL,
  5328.           button, activate_time);
  5329. }
  5330.  
  5331.  
  5332. static gint
  5333. list_button_press (GtkWidget      *widget,
  5334.            GdkEventButton *event,
  5335.            gpointer        data)
  5336. {
  5337.   switch (event->type)
  5338.     {
  5339.     case GDK_BUTTON_PRESS:
  5340. #ifdef DEBUG
  5341.       printf ("Single button press\n");
  5342. #endif /* DEBUG */
  5343.       if (event->button == 3)
  5344.     {
  5345. #ifdef DEBUG
  5346.       printf ("Popup on '%s'\n", ((GFigObj *)data)->draw_name);
  5347. #endif /* DEBUG */
  5348.       gfig_op_menu_popup (event->button, event->time, (GFigObj *) data);
  5349.       return FALSE;
  5350.     }
  5351.       list_button_update ((GFigObj *) data);
  5352.       break;
  5353.     case GDK_2BUTTON_PRESS:
  5354. #ifdef DEBUG
  5355.       printf ("Two button press\n");
  5356. #endif /* DEBUG */
  5357.       gfig_dialog_edit_list (widget, data, FALSE);
  5358.       break;
  5359.     default:
  5360.       g_warning ("gfig: unknown event.\n");
  5361.       break;
  5362.     }
  5363.  
  5364.   return FALSE;
  5365. }
  5366.  
  5367. static void
  5368. gfig_scale_update_scale (GtkAdjustment *adjustment,
  5369.              gdouble       *value)
  5370. {
  5371.   gimp_double_adjustment_update (adjustment, value);
  5372.  
  5373.   if (!selvals.scaletoimage)
  5374.     {
  5375.       scale_x_factor = (1 / (*value)) * org_scale_x_factor;
  5376.       scale_y_factor = (1 / (*value)) * org_scale_y_factor;
  5377.       update_draw_area (gfig_preview, NULL);
  5378.     }
  5379.  
  5380. /* Use to toggle the toggles */
  5381. static void
  5382. gfig_scale2img_update (GtkWidget *widget,
  5383.                gpointer   data)
  5384. {
  5385.   gimp_toggle_button_update (widget, data);
  5386.  
  5387.   if (*((gint *) data))
  5388.     {
  5389.       GtkObject *adj;
  5390.  
  5391.       adj = gtk_object_get_user_data (GTK_OBJECT (widget));
  5392.  
  5393.       scale_x_factor = org_scale_x_factor;
  5394.       scale_y_factor = org_scale_y_factor;
  5395.       gtk_adjustment_set_value (GTK_ADJUSTMENT (adj), 1.0);
  5396.  
  5397.       update_draw_area (gfig_preview, NULL);
  5398.     }
  5399. }
  5400.  
  5401. /* Given a row then srink it down a bit */
  5402. static void
  5403. do_gfig_preview (guchar *dest_row, 
  5404.          guchar *src_row,
  5405.          gint    width,
  5406.          gint    dh,
  5407.          gint    height,
  5408.          gint    bpp)
  5409. {
  5410.   memcpy (dest_row, src_row, width*bpp);
  5411. }
  5412.  
  5413. static void
  5414. dialog_update_preview (void)
  5415. {
  5416.   gint y;
  5417.   gint check, check_0, check_1;  
  5418.  
  5419.   if (!selvals.showimage)
  5420.     {
  5421.       memset (preview_row, -1, preview_width*4);      
  5422.       for (y = 0; y < preview_height; y++)
  5423.     {
  5424.       gtk_preview_draw_row (GTK_PREVIEW (gfig_preview), preview_row,
  5425.                 0, y, preview_width);
  5426.     }
  5427.       return;
  5428.     }
  5429.  
  5430.   if (!pv_cache)
  5431.     {
  5432.       refill_cache ();
  5433.     }
  5434.  
  5435.   for (y = 0; y < preview_height; y++)
  5436.     {
  5437.       if ((y / GIMP_CHECK_SIZE) & 1)
  5438.     {
  5439.       check_0 = GIMP_CHECK_DARK * 255;
  5440.       check_1 = GIMP_CHECK_LIGHT * 255;
  5441.     }
  5442.       else
  5443.     {
  5444.       check_0 = GIMP_CHECK_LIGHT * 255;
  5445.       check_1 = GIMP_CHECK_DARK * 255;
  5446.     }
  5447.  
  5448.       do_gfig_preview (preview_row,
  5449.                pv_cache+y*preview_width*img_bpp,
  5450.                preview_width,
  5451.                y,
  5452.                preview_height,
  5453.                img_bpp);
  5454.  
  5455.       if (img_bpp > 3)
  5456.     {
  5457.       int i, j;
  5458.       for (i = 0, j = 0 ; i < sizeof (preview_row); i += 4, j += 3)
  5459.         {
  5460.           gint alphaval;
  5461.           if (((i/4) / GIMP_CHECK_SIZE) & 1)
  5462.         check = check_0;
  5463.           else
  5464.         check = check_1;
  5465.         
  5466.           alphaval = preview_row[i + 3];
  5467.  
  5468.           preview_row[j] = 
  5469.         check + (((preview_row[i] - check)*alphaval)/255);
  5470.           preview_row[j + 1] = 
  5471.         check + (((preview_row[i + 1] - check)*alphaval)/255);
  5472.           preview_row[j + 2] = 
  5473.         check + (((preview_row[i + 2] - check)*alphaval)/255);
  5474.         }
  5475.     }
  5476.  
  5477.       gtk_preview_draw_row (GTK_PREVIEW (gfig_preview), preview_row,
  5478.                 0, y, preview_width);
  5479.     }
  5480. }
  5481.  
  5482. static void
  5483. gfig_new_gc (void)
  5484. {
  5485.  GdkColor fg, bg;
  5486.  
  5487.  /*  create a new graphics context  */
  5488.  gfig_gc = gdk_gc_new (gfig_preview->window);
  5489.  gdk_gc_set_function (gfig_gc, GDK_INVERT);
  5490.  fg.pixel = 0xFFFFFFFF;
  5491.  bg.pixel = 0x00000000;
  5492.  gdk_gc_set_foreground (gfig_gc, &fg);
  5493.  gdk_gc_set_background (gfig_gc, &bg);
  5494.  gdk_gc_set_line_attributes (gfig_gc, 1, GDK_LINE_SOLID, GDK_CAP_BUTT, GDK_JOIN_MITER);
  5495. }
  5496.  
  5497. static gint 
  5498. get_num_radials (void)
  5499. {
  5500.   gint gridsp = MAX_GRID + MIN_GRID;
  5501.   /* select number of radials to draw */
  5502.   /* Either have 16 32 or 48 */
  5503.   /* correspond to GRID_MAX, midway and GRID_MIN */
  5504.  
  5505.   return (gridsp - selvals.opts.gridspacing);
  5506. }
  5507.  
  5508. #define SQ_SIZE 8
  5509.  
  5510. static gint 
  5511. inside_sqr (GdkPoint *cpnt,
  5512.         GdkPoint *testpnt)
  5513. {
  5514.   /* Return TRUE if testpnt is near cpnt */
  5515.   gint16 x = cpnt->x;
  5516.   gint16 y = cpnt->y;
  5517.   gint16 tx = testpnt->x;
  5518.   gint16 ty = testpnt->y;
  5519.  
  5520. #ifdef DEBUG
  5521.   printf ("Testing if (%x,%x) is near (%x,%x)\n", tx, ty, x, y);
  5522. #endif /* DEBUG */
  5523.   return (abs (x - tx) <= SQ_SIZE && abs (y - ty) < SQ_SIZE);
  5524. }
  5525.  
  5526. /* find_grid_pos - Given an x, y point return the grid position of it */
  5527. /* return the new position in the passed point */
  5528.  
  5529. static void
  5530. find_grid_pos (GdkPoint *p,
  5531.            GdkPoint *gp,
  5532.            guint     is_butt3)
  5533. {
  5534.   gint16 x = p->x;
  5535.   gint16 y = p->y;
  5536.   static GdkPoint cons_pnt;
  5537.   static gdouble cons_radius;
  5538.   static gdouble cons_ang;
  5539.   static gboolean cons_center;
  5540.   
  5541.   if (selvals.opts.gridtype == RECT_GRID)
  5542.     {
  5543.       if (p->x % selvals.opts.gridspacing > selvals.opts.gridspacing/2)
  5544.     x += selvals.opts.gridspacing;
  5545.       
  5546.       if (p->y % selvals.opts.gridspacing > selvals.opts.gridspacing/2)
  5547.     y += selvals.opts.gridspacing;
  5548.       
  5549.       gp->x = (x/selvals.opts.gridspacing)*selvals.opts.gridspacing;
  5550.       gp->y = (y/selvals.opts.gridspacing)*selvals.opts.gridspacing;
  5551.  
  5552.       if (is_butt3)
  5553.     {
  5554.       if (abs (gp->x - cons_pnt.x) < abs (gp->y - cons_pnt.y))
  5555.         gp->x = cons_pnt.x;
  5556.       else
  5557.         gp->y = cons_pnt.y;
  5558.     }
  5559.       else
  5560.     {
  5561.       /* Store the point since might be used later */
  5562.       cons_pnt = *gp; /* Structure copy */
  5563.     }
  5564.     }
  5565.   else if (selvals.opts.gridtype == POLAR_GRID)
  5566.     { 
  5567.       gdouble ang_grid;
  5568.       gdouble ang_radius;
  5569.       gdouble real_radius;
  5570.       gdouble real_angle;
  5571.       gdouble rounded_angle;
  5572.       gint rounded_radius;
  5573.       gint16 shift_x = x - preview_width/2;
  5574.       gint16 shift_y = -y + preview_height/2;
  5575.  
  5576.       real_radius = ang_radius = sqrt ((shift_y*shift_y) + (shift_x*shift_x));
  5577.  
  5578.       /* round radius */
  5579.       rounded_radius = (gint) (RINT (ang_radius/selvals.opts.gridspacing))*selvals.opts.gridspacing;
  5580.       if (rounded_radius <= 0 || real_radius <=0)
  5581.     {
  5582.       /* DEAD CENTER */
  5583.       gp->x = preview_width/2;
  5584.       gp->y = preview_height/2;
  5585.       if (!is_butt3) cons_center = TRUE;
  5586. #ifdef DEBUG
  5587.       printf ("Dead center\n");
  5588. #endif /* DEBUG */
  5589.       return;
  5590.     }
  5591.  
  5592.       ang_grid = 2*G_PI/get_num_radials ();
  5593.  
  5594.       real_angle = atan2 (shift_y, shift_x);
  5595.       if (real_angle < 0)
  5596.     real_angle += 2*G_PI;
  5597.  
  5598.       rounded_angle = (RINT ((real_angle/ang_grid)))*ang_grid;
  5599. #ifdef DEBUG
  5600.       printf ("real_ang = %f ang_gid = %f rounded_angle = %f rounded radius = %d\n",
  5601.           real_angle, ang_grid, rounded_angle, rounded_radius);
  5602.  
  5603.       printf ("preview_width = %d preview_height = %d\n", preview_width, preview_height);
  5604. #endif /* DEBUG */
  5605.       gp->x = (gint)RINT ((rounded_radius*cos (rounded_angle))) + preview_width/2;
  5606.       gp->y = -(gint)RINT ((rounded_radius*sin (rounded_angle))) + preview_height/2;
  5607.  
  5608.       if (is_butt3)
  5609.     {
  5610.       if (!cons_center)
  5611.         {
  5612.           if (fabs (rounded_angle - cons_ang) > ang_grid/2)
  5613.         {
  5614.           gp->x = (gint)RINT ((cons_radius*cos (rounded_angle))) + preview_width/2;
  5615.           gp->y = -(gint)RINT ((cons_radius*sin (rounded_angle))) + preview_height/2;
  5616.         }
  5617.           else
  5618.         {
  5619.           gp->x = (gint)RINT ((rounded_radius*cos (cons_ang))) + preview_width/2;
  5620.           gp->y = -(gint)RINT ((rounded_radius*sin (cons_ang))) + preview_height/2;
  5621.         }
  5622.         }
  5623.     }
  5624.       else
  5625.     {
  5626.       cons_radius = rounded_radius;
  5627.       cons_ang = rounded_angle;
  5628.       cons_center = FALSE;
  5629.     }
  5630.     }
  5631.    else if (selvals.opts.gridtype == ISO_GRID)
  5632.      {
  5633.     if (is_butt3)
  5634.       {
  5635.          static GdkPoint b_pnt;
  5636.          static GdkPoint i_pnt;
  5637.          static GdkPoint ii_pnt;
  5638.          gint d;
  5639.          gint dd;
  5640.  
  5641.          b_pnt.x = cons_pnt.x;
  5642.          b_pnt.y = cons_pnt.y + preview_width;
  5643.          d = calculate_point_to_line_distance (p, &cons_pnt, &b_pnt, &i_pnt);
  5644.  
  5645.          b_pnt.x = cons_pnt.x;
  5646.          b_pnt.y = cons_pnt.y - preview_width;
  5647.          dd = calculate_point_to_line_distance (p, &cons_pnt, &b_pnt, &ii_pnt);
  5648.          if (dd < d)
  5649.          {
  5650.         i_pnt.x = ii_pnt.x;
  5651.         i_pnt.y = ii_pnt.y;
  5652.         d = dd;
  5653.          }
  5654.  
  5655.          b_pnt.x = cons_pnt.x + preview_width;
  5656.          b_pnt.y = cons_pnt.y + preview_width/2;
  5657.          dd = calculate_point_to_line_distance (p, &cons_pnt, &b_pnt, &ii_pnt);
  5658.          if (dd < d)
  5659.          {
  5660.         i_pnt.x = ii_pnt.x;
  5661.         i_pnt.y = ii_pnt.y;
  5662.         d = dd;
  5663.          }
  5664.  
  5665.          b_pnt.x = cons_pnt.x + preview_width;
  5666.          b_pnt.y = cons_pnt.y - preview_width/2;
  5667.          dd = calculate_point_to_line_distance (p, &cons_pnt, &b_pnt, &ii_pnt);
  5668.          if (dd < d)
  5669.          {
  5670.         i_pnt.x = ii_pnt.x;
  5671.         i_pnt.y = ii_pnt.y;
  5672.         d = dd;
  5673.          }
  5674.  
  5675.          b_pnt.x = cons_pnt.x - preview_width;
  5676.          b_pnt.y = cons_pnt.y + preview_width/2;
  5677.          dd = calculate_point_to_line_distance (p, &cons_pnt, &b_pnt, &ii_pnt);
  5678.          if (dd < d)
  5679.          {
  5680.         i_pnt.x = ii_pnt.x;
  5681.         i_pnt.y = ii_pnt.y;
  5682.         d = dd;
  5683.          }
  5684.  
  5685.          b_pnt.x = cons_pnt.x - preview_width;
  5686.          b_pnt.y = cons_pnt.y - preview_width/2;
  5687.          dd = calculate_point_to_line_distance (p, &cons_pnt, &b_pnt, &ii_pnt);
  5688.          if (dd < d)
  5689.          {
  5690.         i_pnt.x = ii_pnt.x;
  5691.         i_pnt.y = ii_pnt.y;
  5692.         d = dd;
  5693.          }
  5694.  
  5695.          x = i_pnt.x;
  5696.          y = i_pnt.y;
  5697.       }
  5698.  
  5699.     if (x % selvals.opts.gridspacing > selvals.opts.gridspacing/2)
  5700.       x += selvals.opts.gridspacing;
  5701.  
  5702.     gp->x = (x/selvals.opts.gridspacing)*selvals.opts.gridspacing;
  5703.  
  5704.     if (((gp->x/selvals.opts.gridspacing) % 2) != 0)
  5705.       {
  5706.          y -= selvals.opts.gridspacing/2;
  5707.  
  5708.          if (y % selvals.opts.gridspacing > selvals.opts.gridspacing/2)
  5709.            y += selvals.opts.gridspacing;
  5710.     
  5711.          gp->y = (selvals.opts.gridspacing/2) + ((y/selvals.opts.gridspacing)*selvals.opts.gridspacing);
  5712.       }
  5713.     else
  5714.       {
  5715.          if (y % selvals.opts.gridspacing > selvals.opts.gridspacing/2)
  5716.            y += selvals.opts.gridspacing;
  5717.     
  5718.          gp->y = (y/selvals.opts.gridspacing)*selvals.opts.gridspacing;
  5719.       }
  5720.  
  5721.     if (!is_butt3)
  5722.       {
  5723.          /* Store the point since it might be used later */
  5724.          cons_pnt = *gp; /* Structure copy */
  5725.       }
  5726.      }
  5727. }
  5728.  
  5729. /* Calculate distance from a point to a line
  5730.  * Taken from the newsgroup comp.graphics.algorithms FAQ. */
  5731. static gint
  5732. calculate_point_to_line_distance (GdkPoint *p,
  5733.                   GdkPoint *A,
  5734.                   GdkPoint *B,
  5735.                   GdkPoint *I)
  5736. {
  5737.    gint L2;
  5738.    gint L;
  5739.  
  5740.    L2 = ((B->x - A->x)*(B->x - A->x)) + ((B->y - A->y)*(B->y - A->y));
  5741.    L = (gint) sqrt (L2);
  5742.  
  5743.    /* gint r; */
  5744.    /* gint s; */
  5745.    /* r = ((A->y - p->y)*(A->y - B->y) - (A->x - p->x)*(B->x - A->x))/L2; */
  5746.    /* s = ((A->y - p->y)*(B->x - A->x) - (A->x - p->x)*(B->y - A->y))/L2; */
  5747.  
  5748.    /* Let I be the point of perpendicular projection of C onto AB. */
  5749.  
  5750.    I->x = A->x + (((A->y - p->y)*(A->y - B->y) - (A->x - p->x)*(B->x - A->x))*(B->x - A->x))/L2;
  5751.    I->y = A->y + (((A->y - p->y)*(A->y - B->y) - (A->x - p->x)*(B->x - A->x))*(B->y - A->y))/L2;
  5752.  
  5753.    return abs ((((A->y - p->y)*(B->x - A->x)) - ((A->x - p->x)*(B->y - A->y)))*L);
  5754. }
  5755.  
  5756. /* Given a point x, y draw a circle */
  5757. static void
  5758. draw_circle (GdkPoint *p)
  5759. {
  5760.   if (!selvals.opts.showcontrol || drawing_pic)
  5761.     return;
  5762.  
  5763.   gdk_draw_arc (gfig_preview->window,
  5764.         gfig_gc,
  5765.         0,
  5766.         p->x - SQ_SIZE/2,
  5767.         p->y - SQ_SIZE/2,
  5768.         SQ_SIZE,
  5769.         SQ_SIZE,
  5770.         0,
  5771.         360*64);
  5772. }
  5773.  
  5774.  
  5775. /* Given a point x, y draw a square around it */
  5776. static void
  5777. draw_sqr (GdkPoint *p)
  5778. {
  5779.   if (!selvals.opts.showcontrol || drawing_pic)
  5780.     return;
  5781.  
  5782.   gdk_draw_rectangle (gfig_preview->window,
  5783.               gfig_gc,
  5784.               0,
  5785.               gfig_scale_x ((gint)p->x) - SQ_SIZE/2,
  5786.               gfig_scale_y ((gint)p->y) - SQ_SIZE/2,
  5787.               (gint)SQ_SIZE,
  5788.               (gint)SQ_SIZE);
  5789. }
  5790.  
  5791. /* Draw the grid on the screen
  5792.  */
  5793.  
  5794. static void
  5795. draw_grid_clear (GtkWidget *widget,
  5796.          gpointer   data)
  5797. {
  5798.   /* wipe slate and start again */
  5799.   dialog_update_preview ();
  5800.   draw_grid (widget, data);
  5801.   draw_objects (current_obj->obj_list, TRUE);
  5802.   gtk_widget_draw (gfig_preview, NULL);
  5803.   gdk_flush ();
  5804. }
  5805.  
  5806. static void
  5807. toggle_tooltips (GtkWidget *widget,
  5808.          gpointer   data)
  5809. {
  5810.   gimp_toggle_button_update (widget, data);
  5811.  
  5812.   if (gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (widget)))
  5813.     gimp_help_enable_tooltips ();
  5814.   else
  5815.     gimp_help_disable_tooltips ();
  5816. }
  5817.  
  5818. static void
  5819. toggle_show_image (GtkWidget *widget,
  5820.            gpointer   data)
  5821. {
  5822.   /* wipe slate and start again */
  5823.   draw_grid_clear (widget, data);
  5824. }
  5825.  
  5826. static void
  5827. toggle_obj_type (GtkWidget *widget,
  5828.          gpointer   data)
  5829. {
  5830.   GdkCursorType ctype = GDK_LAST_CURSOR;
  5831.   static GdkCursor* p_cursors[DEL_OBJ + 1];
  5832.  
  5833.   if (selvals.otype != (DobjType) data)
  5834.     {
  5835.       /* Mem leak */
  5836.       obj_creating = NULL;
  5837.       tmp_line = NULL;
  5838.       tmp_bezier = NULL;
  5839.  
  5840.       if ((DobjType)data < MOVE_OBJ)
  5841.     {
  5842.       obj_show_single = -1; /* Cancel select preview */
  5843.     }
  5844.       /* Update draw areas */
  5845.       update_draw_area (gfig_preview, NULL);
  5846.       /* And preview */
  5847.       list_button_update (current_obj);
  5848.     }
  5849.  
  5850.   selvals.otype = (DobjType) data;
  5851.  
  5852.   switch (selvals.otype)
  5853.     {
  5854.     case LINE:
  5855.     case CIRCLE:
  5856.     case ELLIPSE:
  5857.     case ARC:
  5858.     case POLY:
  5859.     case STAR:
  5860.     case SPIRAL:
  5861.     case BEZIER:
  5862.     default:
  5863.       ctype = GDK_CROSSHAIR;
  5864.       break;
  5865.     case MOVE_OBJ:
  5866.     case MOVE_POINT:
  5867.     case COPY_OBJ:
  5868.     case MOVE_COPY_OBJ:
  5869.       ctype = GDK_DIAMOND_CROSS;
  5870.       break;
  5871.     case DEL_OBJ:
  5872.       ctype = GDK_PIRATE;
  5873.       break;
  5874.     }
  5875.  
  5876.   if (!p_cursors[selvals.otype])
  5877.     p_cursors[selvals.otype] = gdk_cursor_new (ctype);
  5878.  
  5879.   gdk_window_set_cursor (gfig_preview->window, p_cursors[selvals.otype]);
  5880. }
  5881.  
  5882. static void
  5883. draw_grid_polar (GdkGC *drawgc)
  5884. {
  5885.   gint step;
  5886.   gint loop;
  5887.   gint radius;
  5888.   gint max_rad;
  5889.   gdouble ang_grid;
  5890.   gdouble ang_loop;
  5891.   gdouble ang_radius;
  5892.   /* Pick center and draw concentric circles */
  5893.  
  5894.   gint grid_x_center = preview_width/2;
  5895.   gint grid_y_center = preview_height/2;
  5896.  
  5897.   step = selvals.opts.gridspacing;
  5898.   max_rad = sqrt (preview_width * preview_width +
  5899.           preview_height * preview_height) / 2;
  5900.  
  5901.   for (loop = 0; loop < max_rad; loop += step)
  5902.     {
  5903.       radius = loop;
  5904.  
  5905.       gdk_draw_arc (gfig_preview->window,
  5906.             drawgc,
  5907.             0,
  5908.             grid_x_center - radius,
  5909.             grid_y_center - radius,
  5910.             radius*2,
  5911.             radius*2,
  5912.             0,
  5913.             360 * 64);
  5914.     }
  5915.  
  5916.   /* Lines */
  5917.   ang_grid = 2 * G_PI / get_num_radials ();
  5918.   ang_radius = sqrt ((preview_width * preview_width) +
  5919.              (preview_height * preview_height)) / 2;
  5920.  
  5921.   for (loop = 0; loop <= get_num_radials (); loop++)
  5922.     {
  5923.       gint lx, ly;
  5924.  
  5925.       ang_loop = loop * ang_grid;
  5926.     
  5927.       lx = (gint) RINT (ang_radius * cos (ang_loop));
  5928.       ly = (gint) RINT (ang_radius * sin (ang_loop));
  5929.  
  5930.       gdk_draw_line (gfig_preview->window,
  5931.              drawgc,
  5932.              (gint) lx + (preview_width) / 2,
  5933.              -(gint) ly + (preview_height) / 2,
  5934.              (gint) (preview_width) / 2,
  5935.              (gint) (preview_height) / 2);
  5936.     }
  5937. }
  5938.  
  5939. static void
  5940. draw_grid_sq (GdkGC *drawgc)
  5941. {
  5942.   gint step;
  5943.   gint loop;
  5944.  
  5945.   /* Draw the horizontal lines */
  5946.   step = selvals.opts.gridspacing;
  5947.  
  5948.   for (loop = 0 ; loop < preview_height ; loop += step)
  5949.     {
  5950.       gdk_draw_line (gfig_preview->window,
  5951.              drawgc,
  5952.              (gint)0,
  5953.              (gint)loop,
  5954.              (gint)preview_width,
  5955.              (gint)loop);
  5956.     }
  5957.  
  5958.   /* Draw the vertical lines */
  5959.  
  5960.   for (loop = 0 ; loop < preview_width ; loop += step)
  5961.     {
  5962.       gdk_draw_line (gfig_preview->window,
  5963.              drawgc,
  5964.              (gint)loop,
  5965.              (gint)0,
  5966.              (gint)loop,
  5967.              (gint)preview_height);
  5968.     }
  5969. }
  5970.  
  5971. static void
  5972. draw_grid_iso (GdkGC *drawgc)
  5973. {
  5974.    gint step;
  5975.    gint loop;
  5976.  
  5977.    gint diagonal_start;
  5978.    gint diagonal_end;
  5979.    gint diagonal_width;
  5980.    gint diagonal_height;
  5981.    
  5982.    step = selvals.opts.gridspacing;
  5983.    
  5984.    /* Draw the vertical lines */
  5985.    for (loop = 0 ; loop < preview_width ; loop += step)
  5986.      {
  5987.        gdk_draw_line (gfig_preview->window,
  5988.               drawgc,
  5989.               (gint)loop,
  5990.               (gint)0,
  5991.               (gint)loop,
  5992.               (gint)preview_height);
  5993.      }
  5994.  
  5995.    diagonal_start = preview_width/2;
  5996.    diagonal_start = diagonal_start - (diagonal_start % step);
  5997.    diagonal_start = -diagonal_start;
  5998.    
  5999.    diagonal_end = preview_height + (preview_width/2);
  6000.    diagonal_end = diagonal_end - (diagonal_end % step);
  6001.    
  6002.    diagonal_width = preview_width;
  6003.    diagonal_height = diagonal_width/2;
  6004.    
  6005.    /* Draw diagonal lines */
  6006.    for (loop = diagonal_start ; loop < diagonal_end ; loop += step)
  6007.      {
  6008.        gdk_draw_line (gfig_preview->window,
  6009.               drawgc,
  6010.               (gint)0,
  6011.               (gint)loop,
  6012.               (gint)diagonal_width,
  6013.               (gint)loop + diagonal_height);
  6014.  
  6015.        gdk_draw_line (gfig_preview->window,
  6016.               drawgc,
  6017.               (gint)0,
  6018.               (gint)loop,
  6019.               (gint)diagonal_width,
  6020.               (gint)loop - diagonal_height);
  6021.      }
  6022. }
  6023.  
  6024. static GdkGC *
  6025. gfig_get_grid_gc (GtkWidget *w, gint gctype)
  6026. {
  6027.   switch (gctype)
  6028.     {
  6029.     case GFIG_BLACK_GC:
  6030.       return (w->style->black_gc);
  6031.     case GFIG_WHITE_GC:
  6032.       return (w->style->white_gc);
  6033.     case GFIG_GREY_GC:
  6034.       return (grid_hightlight_drawgc);
  6035.     case GTK_STATE_NORMAL:
  6036.       return (w->style->bg_gc[GTK_STATE_NORMAL]);
  6037.     case GTK_STATE_ACTIVE:
  6038.       return (w->style->bg_gc[GTK_STATE_ACTIVE]);
  6039.     case GTK_STATE_PRELIGHT:
  6040.       return (w->style->bg_gc[GTK_STATE_PRELIGHT]);
  6041.     case GTK_STATE_SELECTED:
  6042.       return (w->style->bg_gc[GTK_STATE_SELECTED]);
  6043.     case GTK_STATE_INSENSITIVE:
  6044.       return (w->style->bg_gc[GTK_STATE_INSENSITIVE]);
  6045.     default:
  6046.       g_warning ("Unknown type for grid colouring\n");
  6047.       return (w->style->bg_gc[GTK_STATE_PRELIGHT]);
  6048.     }
  6049. }
  6050.  
  6051. static void
  6052. draw_grid (GtkWidget *widget,
  6053.       gpointer   data)
  6054. {
  6055.   GdkGC *drawgc;
  6056.   /* Get the size of the preview and calc where the lines go */
  6057.   /* Draw in prelight to start with... */
  6058.   /* Always start in the upper left corner for rect.
  6059.    */
  6060.  
  6061.   if ((preview_width < selvals.opts.gridspacing &&
  6062.        preview_height < selvals.opts.gridspacing) ||
  6063.       drawing_pic)
  6064.     {
  6065.       /* Don't draw if they don't fit */
  6066.       return;
  6067.     }
  6068.  
  6069.   if (selvals.opts.drawgrid)
  6070.     drawgc = gfig_get_grid_gc (gfig_preview, grid_gc_type);
  6071.   else
  6072.     return;
  6073.  
  6074.   if (selvals.opts.gridtype == RECT_GRID)
  6075.     draw_grid_sq (drawgc);
  6076.   else if (selvals.opts.gridtype == POLAR_GRID)
  6077.     draw_grid_polar (drawgc);
  6078.   else if (selvals.opts.gridtype == ISO_GRID)
  6079.     draw_grid_iso (drawgc);
  6080. }
  6081.  
  6082. static void
  6083. do_gfig (void)
  6084. {
  6085.   /* Not sure if requre post proc - leave stub in */
  6086. }
  6087.  
  6088. /* This could belong in a separate file ... but makes it easier to lump into
  6089.  * one when compiling the plugin.
  6090.  */
  6091.  
  6092. /* Stuff for the generation/deletion of objects. */
  6093.  
  6094. /* Objects are easy one they are created - you just go down the object 
  6095.  * list calling the draw function for each object but... when they 
  6096.  * are been created we have to be a little more careful. When 
  6097.  * the first point is placed on the canvas we create the object, 
  6098.  * the mouse position then defines the next point that can move around.
  6099.  * careful how we draw this position.
  6100.  */
  6101.  
  6102. static void
  6103. free_one_obj (Dobject *obj)
  6104. {
  6105.   d_delete_dobjpoints (obj->points);
  6106.   g_free (obj);
  6107. }
  6108.  
  6109. static void
  6110. free_all_objs (DAllObjs * objs)
  6111. {
  6112.   /* Free all objects */
  6113.   DAllObjs * next;
  6114.   
  6115.   while (objs)
  6116.     {
  6117.       free_one_obj (objs->obj);
  6118.       next = objs->next;
  6119.       g_free (objs);
  6120.       objs = next;
  6121.     }
  6122. }
  6123.  
  6124. static gchar *
  6125. get_line (gchar *buf,
  6126.       gint   s,
  6127.       FILE  *from,
  6128.       gint   init)
  6129. {
  6130.   gint slen;
  6131.   char * ret;
  6132.  
  6133.   if (init)
  6134.     line_no = 1;
  6135.   else
  6136.     line_no++;
  6137.  
  6138.   do
  6139.     {
  6140.       ret = fgets (buf, s, from);
  6141.     } while (!ferror (from) && buf[0] == '#');
  6142.  
  6143.   slen = strlen (buf);
  6144.  
  6145.   /* The last newline is a pain */
  6146.   if (slen > 0)
  6147.     buf[slen - 1] = '\0';
  6148.   
  6149.   if (ferror (from))
  6150.     {
  6151.       g_warning (_("Error reading file"));
  6152.       return (0);
  6153.     }
  6154.  
  6155. #ifdef DEBUG
  6156.   printf ("Processing line '%s'\n", buf);
  6157. #endif /* DEBUG */
  6158.  
  6159.   return (ret);
  6160. }
  6161.  
  6162. static void
  6163. gfig_clear_callback (GtkWidget *widget,
  6164.              gpointer   data)
  6165. {
  6166.   /* Make sure we can get back - if we have some objects to get back to */
  6167.   if (!current_obj->obj_list)
  6168.     return;
  6169.  
  6170.   setup_undo ();
  6171.   /* Free all objects */
  6172.   free_all_objs (current_obj->obj_list);
  6173.   current_obj->obj_list = NULL;
  6174.   obj_creating = NULL;
  6175.   tmp_line = NULL;
  6176.   tmp_bezier = NULL;
  6177.   update_draw_area (gfig_preview, NULL);
  6178.   /* And preview */
  6179.   list_button_update (current_obj);
  6180. }
  6181.  
  6182.  
  6183. static void
  6184. gfig_undo_callback (GtkWidget *widget,
  6185.             gpointer   data)
  6186. {
  6187.   if (undo_water_mark >= 0)
  6188.     {
  6189.       /* Free current objects an reinstate previous */
  6190.       free_all_objs (current_obj->obj_list);
  6191.       current_obj->obj_list = NULL;
  6192.       tmp_bezier = tmp_line = obj_creating = NULL;
  6193.       current_obj->obj_list = undo_table[undo_water_mark];
  6194.       undo_water_mark--;
  6195.       /* Update the screen */
  6196.       update_draw_area (gfig_preview, NULL);
  6197.       /* And preview */
  6198.       list_button_update (current_obj);
  6199.       gfig_obj_modified (current_obj, GFIG_MODIFIED);
  6200.       current_obj->obj_status |= GFIG_MODIFIED;
  6201.   }
  6202.  
  6203.   if (undo_water_mark < 0)
  6204.     gtk_widget_set_sensitive (widget, FALSE);
  6205. }
  6206.  
  6207. static void
  6208. clear_undo (void)
  6209. {
  6210.   int lv;
  6211.  
  6212.   for (lv = undo_water_mark; lv >= 0; lv--) 
  6213.     {
  6214.       if (undo_table[lv])
  6215.     free_all_objs (undo_table[lv]);
  6216.       undo_table[lv] = NULL;
  6217.     }
  6218.  
  6219.   undo_water_mark = -1;
  6220.   gtk_widget_set_sensitive (undo_widget, FALSE);
  6221. }
  6222.  
  6223. static void
  6224. setup_undo (void)
  6225. {
  6226.   /* Copy object list to undo buffer */
  6227. #if DEBUG
  6228.   printf ("setup undo level [%d]\n", undo_water_mark);
  6229. #endif /*DEBUG*/  
  6230.  
  6231.   if (!current_obj)
  6232.     {
  6233.       /* If no current_obj must be loading -> no undo */
  6234.       return;
  6235.     }
  6236.  
  6237.   if (undo_water_mark >= selvals.maxundo - 1)
  6238.     {
  6239.       int loop;
  6240.       /* the little one in the bed said "roll over".. */
  6241.       if (undo_table[0])
  6242.     free_one_obj (undo_table[0]->obj);
  6243.       for (loop = 0; loop < undo_water_mark; loop++)
  6244.     {
  6245.       undo_table[loop] = undo_table[loop + 1];
  6246.     }
  6247.     }
  6248.   else
  6249.     {
  6250.       undo_water_mark++;
  6251.     }
  6252.   undo_table[undo_water_mark] = copy_all_objs (current_obj->obj_list);
  6253.   gtk_widget_set_sensitive (undo_widget, TRUE);
  6254.  
  6255.   gfig_obj_modified (current_obj, GFIG_MODIFIED);
  6256.   current_obj->obj_status |= GFIG_MODIFIED;
  6257. }
  6258.  
  6259. /* Given a number of float co-ords adjust for scaling back to org size */
  6260. /* Size is number of PAIRS of points */
  6261. /* FP + int varients */
  6262.  
  6263. static void
  6264. scale_to_orginal_x (gdouble *list)
  6265. {
  6266.   *list *= scale_x_factor;
  6267. }
  6268.  
  6269. static gint
  6270. gfig_scale_x (gint x)
  6271. {
  6272.   if (!selvals.scaletoimage)
  6273.     return (gint) (x * (1 / scale_x_factor));
  6274.   else
  6275.     return x;
  6276. }
  6277.  
  6278. static gint
  6279. gfig_invscale_x (gint x)
  6280. {
  6281.   if (!selvals.scaletoimage)
  6282.     return (gint) (x * (scale_x_factor));
  6283.   else
  6284.     return x;
  6285. }
  6286.  
  6287. static void
  6288. scale_to_orginal_y (gdouble *list)
  6289. {
  6290.   *list *= scale_y_factor;
  6291. }
  6292.  
  6293. static gint
  6294. gfig_scale_y (gint y)
  6295. {
  6296.   if (!selvals.scaletoimage)
  6297.     return (gint) (y * (1 / scale_y_factor));
  6298.   else
  6299.     return y;
  6300. }
  6301.  
  6302. static gint
  6303. gfig_invscale_y (gint y)
  6304. {
  6305.   if (!selvals.scaletoimage)
  6306.     return (gint) (y*(scale_y_factor));
  6307.   else
  6308.     return y;
  6309. }
  6310.  
  6311. /* Pairs x followed by y */
  6312. static void
  6313. scale_to_original_xy (gdouble *list,
  6314.               gint     size)
  6315. {
  6316.   gint i;
  6317.  
  6318.   for (i = 0; i < size * 2; i += 2)
  6319.     {
  6320.       scale_to_orginal_x (&list[i]);
  6321.       scale_to_orginal_y (&list[i + 1]);
  6322.     }
  6323. }
  6324.  
  6325. /* Pairs x followed by y */
  6326. static void
  6327. scale_to_xy (gdouble *list,
  6328.          gint     size)
  6329. {
  6330.   gint i;
  6331.  
  6332.   for (i = 0; i < size * 2; i += 2)
  6333.     {
  6334.       list[i] *= (org_scale_x_factor / scale_x_factor);
  6335.       list[i + 1] *= (org_scale_y_factor / scale_y_factor);
  6336.     }
  6337. }
  6338.  
  6339. /* Given an list of PAIRS of doubles reverse the list */
  6340. /* Size is number of pairs to swap */
  6341. static void
  6342. reverse_pairs_list (gdouble *list,
  6343.             gint     size)
  6344. {
  6345.   gint i;
  6346.  
  6347.   struct cs
  6348.   { 
  6349.     gdouble i1; 
  6350.     gdouble i2;
  6351.   } copyit, *orglist;
  6352.  
  6353.   orglist = (struct cs *) list;
  6354.  
  6355.   /* Uses struct copies */
  6356.   for (i = 0; i < size / 2; i++)
  6357.     {
  6358.       copyit = orglist[i];
  6359.       orglist[i] = orglist[size - 1 - i];
  6360.       orglist[size - 1 - i] = copyit;
  6361.     }
  6362. }
  6363.  
  6364. /* Delete a list of points */
  6365. static void
  6366. d_delete_dobjpoints (DobjPoints * pnts)
  6367. {
  6368.   DobjPoints * next;
  6369.   DobjPoints * pnt2del = pnts;
  6370.  
  6371.   while (pnt2del)
  6372.     {
  6373.       next = pnt2del->next;
  6374.       g_free (pnt2del);
  6375.       pnt2del = next;
  6376.     }
  6377. }
  6378.  
  6379. static DobjPoints *
  6380. d_copy_dobjpoints (DobjPoints * pnts)
  6381. {
  6382.   DobjPoints *ret = NULL;
  6383.   DobjPoints *head = NULL;
  6384.   DobjPoints *newpnt;
  6385.   DobjPoints *pnt2copy = pnts;
  6386.  
  6387.   while (pnt2copy)
  6388.     {
  6389.       newpnt = g_new0 (DobjPoints, 1);
  6390.       newpnt->pnt.x = pnt2copy->pnt.x;
  6391.       newpnt->pnt.y = pnt2copy->pnt.y;
  6392.  
  6393.       if (!ret)
  6394.     head = ret = newpnt;
  6395.       else
  6396.     {
  6397.       head->next = newpnt;
  6398.       head = newpnt;
  6399.     }
  6400.       pnt2copy = pnt2copy->next;
  6401.     }
  6402.  
  6403.   return ret;
  6404. }
  6405.  
  6406. static gint
  6407. scan_obj_points (DobjPoints *opnt,
  6408.          GdkPoint   *pnt)
  6409. {
  6410.   while (opnt)
  6411.     {
  6412.       if (inside_sqr (&opnt->pnt, pnt))
  6413.     {
  6414.       opnt->found_me = TRUE;
  6415.       return TRUE;
  6416.     }
  6417.       opnt->found_me = FALSE;
  6418.       opnt = opnt->next;
  6419.     }
  6420.   return FALSE;
  6421. }
  6422.  
  6423. static Dobject *
  6424. get_nearest_objs (GFigObj  *obj,
  6425.           GdkPoint *pnt)
  6426. {
  6427.   /* Nearest object to given point or NULL */
  6428.   DAllObjs *all;
  6429.   Dobject  *test_obj;
  6430.   gint count = 0;
  6431.  
  6432.   if (!obj)
  6433.     return NULL;
  6434.  
  6435.   all = obj->obj_list;
  6436.  
  6437.   while (all)
  6438.     {
  6439.       test_obj = all->obj;
  6440.  
  6441.       if (count == obj_show_single || obj_show_single == -1)
  6442.     if (scan_obj_points (test_obj->points, pnt))
  6443.       {
  6444.         return test_obj;
  6445.       }
  6446.       all = all->next;
  6447.       count++;
  6448.     }
  6449.   return NULL;
  6450. }
  6451.  
  6452. static void
  6453. scale_obj_points (DobjPoints *opnt,
  6454.           gdouble     scale_x,
  6455.           gdouble     scale_y)
  6456. {
  6457.   while (opnt)
  6458.     {
  6459.       opnt->pnt.x = (gint) (opnt->pnt.x * scale_x);
  6460.       opnt->pnt.y = (gint) (opnt->pnt.y * scale_y);
  6461.       opnt = opnt->next;
  6462.     }
  6463. }
  6464.  
  6465. static void
  6466. remove_obj_from_list (GFigObj *obj,
  6467.               Dobject *del_obj)
  6468. {
  6469.   /* Nearest object to given point or NULL */
  6470.   DAllObjs *all;
  6471.   DAllObjs *prev_all = NULL;
  6472.   
  6473.   g_assert (del_obj != NULL);
  6474.  
  6475.   all = obj->obj_list;
  6476.  
  6477.   while (all)
  6478.     {
  6479.       if (all->obj == del_obj)
  6480.     {
  6481.       /* Found the one to delete */
  6482. #ifdef DEBUG
  6483.       printf ("Found the one to delete\n");
  6484. #endif /* DEBUG */
  6485.  
  6486.       if (prev_all)
  6487.         prev_all->next = all->next;
  6488.       else
  6489.         obj->obj_list = all->next;
  6490.  
  6491.       /* Draw obj (which will actually undraw it! */
  6492.       del_obj->drawfunc (del_obj);
  6493.  
  6494.       free_one_obj (del_obj);
  6495.       g_free (all);
  6496.  
  6497.       if (obj_show_single != -1)
  6498.         {
  6499.           /* We've just deleted the only visible one */
  6500.           draw_grid_clear (NULL, NULL); /*Args not used */
  6501.           obj_show_single = -1; /* Show all again */
  6502.         }
  6503.       return;
  6504.     }
  6505.       prev_all = all;
  6506.       all = all->next;
  6507.     }
  6508.   g_warning (_("Hey where has the object gone ?"));
  6509. }
  6510.  
  6511. static DobjPoints *
  6512. get_diffs (Dobject  *obj,
  6513.        gint16   *xdiff,
  6514.        gint16   *ydiff,
  6515.        GdkPoint *to_pnt)
  6516. {
  6517.   DobjPoints *spnt;
  6518.  
  6519.   g_assert (obj != NULL);
  6520.  
  6521.   spnt = obj->points;
  6522.   
  6523.   if (!spnt)
  6524.     return (NULL); /* no-line */
  6525.   
  6526.   /* Slow slow slowwwwww....*/
  6527.   while (spnt)
  6528.     {
  6529.       if (spnt->found_me)
  6530.     {
  6531.       *xdiff = spnt->pnt.x - to_pnt->x;
  6532.       *ydiff = spnt->pnt.y - to_pnt->y;
  6533.       return (spnt);
  6534.     }
  6535.       spnt = spnt->next;
  6536.     }
  6537.   return (NULL);
  6538. }
  6539.  
  6540. static void
  6541. update_pnts (Dobject *obj,
  6542.          gint16   xdiff,
  6543.          gint16   ydiff)
  6544. {
  6545.   DobjPoints *spnt;
  6546.  
  6547.   g_assert (obj != NULL);
  6548.  
  6549.   /* Update all pnts */
  6550.   spnt = obj->points;
  6551.  
  6552.   if (!spnt)
  6553.     return; /* no-line */
  6554.   
  6555.   /* Go around all the points drawing a line from one to the next */
  6556.   while (spnt)
  6557.     {
  6558.       spnt->pnt.x = spnt->pnt.x - xdiff;
  6559.       spnt->pnt.y = spnt->pnt.y - ydiff;
  6560.       spnt = spnt->next;
  6561.     }
  6562. }
  6563.  
  6564.  
  6565. static void
  6566. do_move_all_obj (GdkPoint *to_pnt)
  6567. {
  6568.   /* Move all objects in one go */
  6569.   /* Undraw/then draw in new pos */
  6570.   DAllObjs *all;
  6571.   Dobject *obj;
  6572.   gint16 xdiff = 0;
  6573.   gint16 ydiff = 0;
  6574.   
  6575.   xdiff = move_all_pnt->x - to_pnt->x;
  6576.   ydiff = move_all_pnt->y - to_pnt->y;
  6577.   
  6578.   if (!xdiff && !ydiff)
  6579.     return;
  6580.   
  6581.   all = current_obj->obj_list;
  6582.  
  6583.   while (all)
  6584.     {
  6585.       obj = all->obj;
  6586.  
  6587.       /* undraw ! */
  6588.       draw_one_obj (obj);
  6589.       
  6590.       update_pnts (obj, xdiff, ydiff);
  6591.       
  6592.       /* Draw in new pos */
  6593.       draw_one_obj (obj);
  6594.  
  6595.       all = all->next;
  6596.     }
  6597.  
  6598.   *move_all_pnt = *to_pnt; /* Structure copy */
  6599. }
  6600.  
  6601.  
  6602. static void
  6603. do_move_obj (Dobject  *obj,
  6604.          GdkPoint *to_pnt)
  6605. {
  6606.   /* Move the whole line - undraw the line to start with */
  6607.   /* Then draw in new pos */
  6608.   gint16 xdiff = 0;
  6609.   gint16 ydiff = 0;
  6610.   
  6611.   get_diffs (obj, &xdiff, &ydiff, to_pnt);
  6612.   
  6613.   if (!xdiff && !ydiff)
  6614.     return;
  6615.   
  6616.   /* undraw ! */
  6617.   draw_one_obj (obj);
  6618.   
  6619.   update_pnts (obj, xdiff, ydiff);
  6620.   
  6621.   /* Draw in new pos */
  6622.   draw_one_obj (obj);
  6623.   
  6624. }
  6625.  
  6626. static void
  6627. do_move_obj_pnt (Dobject  *obj,
  6628.          GdkPoint *to_pnt)
  6629. {
  6630.   /* Move the whole line - undraw the line to start with */
  6631.   /* Then draw in new pos */
  6632.   DobjPoints *spnt;
  6633.   gint16 xdiff = 0;
  6634.   gint16 ydiff = 0;
  6635.   
  6636.   spnt = get_diffs (obj, &xdiff, &ydiff, to_pnt);
  6637.   
  6638.   if ((!xdiff && !ydiff) || !spnt)
  6639.     return;
  6640.   
  6641.   /* undraw ! */
  6642.   draw_one_obj (obj);
  6643.  
  6644.   spnt->pnt.x = spnt->pnt.x - xdiff;
  6645.   spnt->pnt.y = spnt->pnt.y - ydiff;
  6646.   
  6647.   /* Draw in new pos */
  6648.   draw_one_obj (obj);
  6649. }
  6650.  
  6651. /* Save a line away to the specified stream */
  6652.  
  6653. static void
  6654. d_save_line (Dobject *obj,
  6655.          FILE    *to)
  6656. {
  6657.   DobjPoints * spnt;
  6658.  
  6659.   spnt = obj->points;
  6660.  
  6661.   if (!spnt)
  6662.     return; /* End-of-line */
  6663.  
  6664.   fprintf (to, "<LINE>\n");
  6665.  
  6666.   while (spnt)
  6667.     {
  6668.       fprintf (to, "%d %d\n",
  6669.           (gint)spnt->pnt.x,
  6670.           (gint)spnt->pnt.y);
  6671.       spnt = spnt->next;
  6672.     }
  6673.   
  6674.   fprintf (to, "</LINE>\n");
  6675. }
  6676.  
  6677. /* Load a line from the specified stream */
  6678.  
  6679. static Dobject *
  6680. d_load_line (FILE *from)
  6681. {
  6682.   Dobject *new_obj = NULL;
  6683.   gint xpnt;
  6684.   gint ypnt;
  6685.   gchar buf[MAX_LOAD_LINE];
  6686.  
  6687. #ifdef DEBUG
  6688.   printf ("Load line called\n");
  6689. #endif /* DEBUG */
  6690.  
  6691.   while (get_line (buf, MAX_LOAD_LINE, from, 0))
  6692.     {
  6693.       if (sscanf (buf, "%d %d", &xpnt, &ypnt) != 2)
  6694.     {
  6695.       /* Must be the end */
  6696.       if (strcmp ("</LINE>", buf))
  6697.         {
  6698.           g_warning ("[%d] Internal load error while loading line",
  6699.             line_no);
  6700.           return (NULL);
  6701.         }
  6702.       return (new_obj);
  6703.     }
  6704.  
  6705.       if (!new_obj)
  6706.     new_obj = d_new_line (xpnt, ypnt);
  6707.       else
  6708.     d_pnt_add_line (new_obj, xpnt, ypnt, -1);
  6709.     }
  6710.  
  6711.   return (new_obj);
  6712. }
  6713.  
  6714. static Dobject *
  6715. d_copy_line (Dobject *obj)
  6716. {
  6717.   Dobject *nl;
  6718.  
  6719.   if (!obj)
  6720.     return (NULL);
  6721.  
  6722.   g_assert (obj->type == LINE);
  6723.  
  6724.   nl = d_new_line (obj->points->pnt.x, obj->points->pnt.y);
  6725.   
  6726.   nl->points->next = d_copy_dobjpoints (obj->points->next);
  6727.  
  6728.   return (nl);
  6729. }
  6730.  
  6731. /* Draw the given line -- */
  6732. static void
  6733. d_draw_line (Dobject *obj)
  6734. {
  6735.   DobjPoints *spnt;
  6736.   DobjPoints *epnt;
  6737.  
  6738.   spnt = obj->points;
  6739.  
  6740.   if (!spnt)
  6741.     return; /* End-of-line */
  6742.  
  6743.   epnt = spnt->next;
  6744.  
  6745.   while (spnt && epnt)
  6746.     {
  6747. #if DEBUG
  6748.       printf ("Drawing line 0x%x (%x,%x) -> (%x,%x)\n", spnt,
  6749.           (gint)spnt->pnt.x,
  6750.           (gint)spnt->pnt.y,
  6751.           (gint)epnt->pnt.x,
  6752.           (gint)epnt->pnt.y);
  6753. #endif /* DEBUG */
  6754.  
  6755.       draw_sqr (&spnt->pnt);
  6756.       /* Go around all the points drawing a line from one to the next */
  6757.       if (drawing_pic)
  6758.     {
  6759.       gdk_draw_line (pic_preview->window,
  6760.              pic_preview->style->black_gc,
  6761.              adjust_pic_coords ((gint)spnt->pnt.x, preview_width),
  6762.              adjust_pic_coords ((gint)spnt->pnt.y, preview_height),
  6763.              adjust_pic_coords ((gint)epnt->pnt.x, preview_width),
  6764.              adjust_pic_coords ((gint)epnt->pnt.y, preview_height));
  6765.     }
  6766.       else
  6767.     {
  6768.       gdk_draw_line (gfig_preview->window,
  6769.              gfig_gc,
  6770.              gfig_scale_x ((gint)spnt->pnt.x),
  6771.              gfig_scale_y ((gint)spnt->pnt.y),
  6772.              gfig_scale_x ((gint)epnt->pnt.x),
  6773.              gfig_scale_y ((gint)epnt->pnt.y));
  6774.     }
  6775.       spnt = epnt;
  6776.       epnt = epnt->next;
  6777.     }
  6778.   draw_sqr (&spnt->pnt);
  6779. }
  6780.  
  6781. static void 
  6782. d_paint_line (Dobject *obj)
  6783. {
  6784.   DobjPoints * spnt;
  6785.   gdouble *line_pnts;
  6786.   gint seg_count = 0;
  6787.   gint i = 0;
  6788.  
  6789.   spnt = obj->points;
  6790.  
  6791.   /* count */
  6792.  
  6793.   while (spnt)
  6794.     {
  6795.       seg_count++;
  6796.       spnt = spnt->next;
  6797.     }
  6798.  
  6799.   spnt = obj->points;
  6800.  
  6801.   if (!spnt || !seg_count)
  6802.     return; /* no-line */
  6803.  
  6804.   line_pnts = g_new0 (gdouble, 2 * seg_count + 1);
  6805.   
  6806.   /* Go around all the points drawing a line from one to the next */
  6807.   while (spnt)
  6808.     {
  6809.       line_pnts[i++] = spnt->pnt.x;
  6810.       line_pnts[i++] = spnt->pnt.y;
  6811.       spnt = spnt->next;
  6812.     }
  6813.  
  6814.   /* Reverse line if approp */
  6815.   if (selvals.reverselines)
  6816.     reverse_pairs_list (&line_pnts[0], i/2);
  6817.  
  6818.   /* Scale before drawing */
  6819.   if (selvals.scaletoimage)
  6820.     scale_to_original_xy (&line_pnts[0], i/2);
  6821.   else
  6822.     scale_to_xy (&line_pnts[0], i/2);
  6823.  
  6824.   /* One go */
  6825.   if (selvals.painttype == PAINT_BRUSH_TYPE)
  6826.     {
  6827.       gfig_paint (selvals.brshtype,
  6828.           gfig_drawable,
  6829.           seg_count * 2, line_pnts);
  6830.     }
  6831.   else 
  6832.     {
  6833.       gimp_free_select (gfig_image,
  6834.             seg_count * 2, line_pnts,
  6835.             selopt.type,
  6836.             selopt.antia,
  6837.             selopt.feather,
  6838.             selopt.feather_radius);
  6839.     }
  6840.  
  6841.   g_free (line_pnts);
  6842. }
  6843.  
  6844.  
  6845. /* Create a new line object. starting at the x, y point might add styles 
  6846.  * later.
  6847.  */
  6848.  
  6849. static Dobject *
  6850. d_new_line (gint x,
  6851.         gint y)
  6852. {
  6853.   Dobject    *nobj;
  6854.   DobjPoints *npnt;
  6855.  
  6856.   /* Get new object and starting point */
  6857.  
  6858.   /* Start point */
  6859.   npnt = g_new0 (DobjPoints, 1);
  6860.  
  6861. #if DEBUG
  6862.   printf ("New line start at (%x,%x)\n", x, y);
  6863. #endif /* DEBUG */
  6864.   npnt->pnt.x = x;
  6865.   npnt->pnt.y = y;
  6866.  
  6867.   nobj = g_new0 (Dobject, 1);
  6868.  
  6869.   nobj->type = LINE;
  6870.   nobj->points = npnt;
  6871.   nobj->drawfunc  = d_draw_line;
  6872.   nobj->loadfunc  = d_load_line;
  6873.   nobj->savefunc  = d_save_line;
  6874.   nobj->paintfunc = d_paint_line;
  6875.   nobj->copyfunc  = d_copy_line;
  6876.  
  6877.   return (nobj);
  6878. }
  6879.  
  6880. /* You guessed it delete the object !*/
  6881. /*
  6882. static void
  6883. d_delete_line (Dobject *obj)
  6884. {
  6885.   g_assert (obj != NULL);
  6886.   * First free the list of points - then the object itself *
  6887.   d_delete_dobjpoints (obj->points);
  6888.   g_free (obj);
  6889. }
  6890. */
  6891.  
  6892. /* Add a point to a line (given x, y)
  6893.  * pos = 0 = head
  6894.  * pos = -1 = tail
  6895.  * 0 < pos = nth position
  6896.  */
  6897.  
  6898. static void
  6899. d_pnt_add_line (Dobject *obj,
  6900.         gint     x,
  6901.         gint     y,
  6902.         gint     pos)
  6903. {
  6904.   DobjPoints *npnts = g_new0 (DobjPoints, 1);
  6905.  
  6906.   g_assert (obj != NULL);
  6907.  
  6908.   npnts->pnt.x = x;
  6909.   npnts->pnt.y = y;
  6910.  
  6911.   if (!pos)
  6912.     {
  6913.       /* Add to head */
  6914.       npnts->next = obj->points;
  6915.       obj->points = npnts;
  6916.     }
  6917.   else
  6918.     {
  6919.       DobjPoints *pnt = obj->points;
  6920.  
  6921.       /* Go down chain until the end if pos */
  6922.       while (pos < 0 || pos-- > 0)
  6923.     {
  6924.       if (!(pnt->next) || !pos)
  6925.         {
  6926.           npnts->next = pnt->next;
  6927.           pnt->next = npnts;
  6928.           break;
  6929.         }
  6930.       else
  6931.         {
  6932.           pnt = pnt->next;
  6933.         }
  6934.     }
  6935.     }
  6936. }
  6937.  
  6938. /* Update end point of line */
  6939. static void
  6940. d_update_line (GdkPoint *pnt)
  6941. {
  6942.   DobjPoints *spnt, *epnt;
  6943.   /* Get last but one segment and undraw it -
  6944.    * Then draw new segment in.
  6945.    * always dealing with the static object.
  6946.    */
  6947.  
  6948.   /* Get start of segments */
  6949.   spnt = obj_creating->points;
  6950.   
  6951.   if (!spnt)
  6952.     return; /* No points */
  6953.  
  6954.   if ((epnt = spnt->next))
  6955.     {
  6956.       /* undraw  current */
  6957.       /* Draw square on point */
  6958.       draw_circle (&epnt->pnt);
  6959.       
  6960.       gdk_draw_line (gfig_preview->window,
  6961.              /*gfig_preview->style->bg_gc[GTK_STATE_NORMAL],*/
  6962.              gfig_gc,
  6963.              (gint) spnt->pnt.x,
  6964.              (gint) spnt->pnt.y,
  6965.              (gint) epnt->pnt.x,
  6966.              (gint) epnt->pnt.y);
  6967.       g_free (epnt);
  6968.     }
  6969.  
  6970.   /* draw new */
  6971.   /* Draw circle on point */
  6972.   draw_circle (pnt);
  6973.  
  6974.   epnt = g_new0 (DobjPoints, 1);
  6975.  
  6976.   epnt->pnt.x = pnt->x;
  6977.   epnt->pnt.y = pnt->y;
  6978.  
  6979.   gdk_draw_line (gfig_preview->window,
  6980.          /*gfig_preview->style->bg_gc[GTK_STATE_NORMAL],*/
  6981.          gfig_gc,
  6982.          (gint) spnt->pnt.x,
  6983.          (gint) spnt->pnt.y,
  6984.          (gint) epnt->pnt.x,
  6985.          (gint) epnt->pnt.y);
  6986.   spnt->next = epnt;
  6987. }
  6988.  
  6989. static void
  6990. d_line_start (GdkPoint *pnt,
  6991.           gint      shift_down)
  6992. {
  6993.   if (!obj_creating || !shift_down)
  6994.     {
  6995.       /* Draw square on point */
  6996.       /* Must delete obj_creating if we have one */
  6997.       obj_creating = d_new_line (pnt->x, pnt->y);
  6998.     }
  6999.   else
  7000.     {
  7001.       /* Contniuation */
  7002.       d_update_line (pnt);
  7003.     }
  7004. }
  7005.  
  7006. static void
  7007. d_line_end (GdkPoint *pnt,
  7008.         gint      shift_down)
  7009. {
  7010.   /* Undraw the last circle */
  7011.   draw_circle (pnt);
  7012.  
  7013.   if (shift_down)
  7014.     {
  7015.       if (tmp_line)
  7016.     {
  7017.       GdkPoint tmp_pnt = *pnt;
  7018.  
  7019.       if (need_to_scale)
  7020.         {
  7021.           tmp_pnt.x = (gint) (pnt->x * scale_x_factor);
  7022.           tmp_pnt.y = (gint) (pnt->y * scale_y_factor);
  7023.         }
  7024.  
  7025.       d_pnt_add_line (tmp_line, tmp_pnt.x, tmp_pnt.y, -1);
  7026.       free_one_obj (obj_creating);
  7027.       /* Must free obj_creating */
  7028.     }
  7029.       else
  7030.     {
  7031.       tmp_line = obj_creating;
  7032.       add_to_all_obj (current_obj, obj_creating);
  7033.     }
  7034.  
  7035.       obj_creating = d_new_line (pnt->x, pnt->y);
  7036.     }
  7037.   else
  7038.     {
  7039.       if (tmp_line)
  7040.     {
  7041.       GdkPoint tmp_pnt = *pnt;
  7042.  
  7043.       if (need_to_scale)
  7044.         {
  7045.           tmp_pnt.x = (gint) (pnt->x * scale_x_factor);
  7046.           tmp_pnt.y = (gint) (pnt->y * scale_y_factor);
  7047.         }
  7048.  
  7049.       d_pnt_add_line (tmp_line, tmp_pnt.x, tmp_pnt.y, -1);
  7050.       free_one_obj (obj_creating);
  7051.       /* Must free obj_creating */
  7052.     }
  7053.       else
  7054.     {
  7055.       add_to_all_obj (current_obj, obj_creating);
  7056.     }
  7057.       obj_creating = NULL;
  7058.       tmp_line = NULL;
  7059.     }
  7060.   /*update_draw_area (gfig_preview, NULL);*/
  7061. }
  7062.  
  7063. /* Save a circle away to the specified stream */
  7064.  
  7065. static void
  7066. d_save_circle (Dobject *obj,
  7067.            FILE    *to)
  7068. {
  7069.   DobjPoints *spnt;
  7070.  
  7071.   spnt = obj->points;
  7072.  
  7073.   if (!spnt)
  7074.     return;
  7075.  
  7076.   fprintf (to, "<CIRCLE>\n");
  7077.  
  7078.   while (spnt)
  7079.     {
  7080.       fprintf (to, "%d %d\n",
  7081.            (gint) spnt->pnt.x,
  7082.            (gint) spnt->pnt.y);
  7083.       spnt = spnt->next;
  7084.     }
  7085.  
  7086.   fprintf (to, "</CIRCLE>\n");
  7087. }
  7088.  
  7089. /* Load a circle from the specified stream */
  7090.  
  7091. static Dobject *
  7092. d_load_circle (FILE *from)
  7093. {
  7094.   Dobject *new_obj = NULL;
  7095.   gint     xpnt;
  7096.   gint     ypnt;
  7097.   gchar    buf[MAX_LOAD_LINE];
  7098.  
  7099. #ifdef DEBUG
  7100.   printf ("Load circle called\n");
  7101. #endif /* DEBUG */
  7102.  
  7103.   while (get_line (buf, MAX_LOAD_LINE, from, 0))
  7104.     {
  7105.       if (sscanf (buf, "%d %d", &xpnt, &ypnt) != 2)
  7106.     {
  7107.       /* Must be the end */
  7108.       if (strcmp ("</CIRCLE>", buf))
  7109.         {
  7110.           g_warning ("[%d] Internal load error while loading circle",
  7111.              line_no);
  7112.           return NULL;
  7113.         }
  7114.       return new_obj;
  7115.     }
  7116.  
  7117.       if (!new_obj)
  7118.     new_obj = d_new_circle (xpnt, ypnt);
  7119.       else
  7120.     {
  7121.       DobjPoints *edge_pnt;
  7122.       /* Circles only have two points */
  7123.       edge_pnt = g_new0 (DobjPoints, 1);
  7124.  
  7125.       edge_pnt->pnt.x = xpnt;
  7126.       edge_pnt->pnt.y = ypnt;
  7127.       
  7128.       new_obj->points->next = edge_pnt;
  7129.     }
  7130.     }
  7131.  
  7132.   g_warning ("[%d] Not enough points for circle", line_no);
  7133.   return NULL;
  7134. }
  7135.  
  7136. static void
  7137. d_draw_circle (Dobject * obj)
  7138. {
  7139.   DobjPoints *center_pnt;
  7140.   DobjPoints *edge_pnt;
  7141.   gdouble     radius;
  7142.  
  7143.   center_pnt = obj->points;
  7144.  
  7145.   if (!center_pnt)
  7146.     return; /* End-of-line */
  7147.  
  7148.   edge_pnt = center_pnt->next;
  7149.  
  7150.   if (!edge_pnt)
  7151.     {
  7152.       g_warning ("Internal error - circle no edge pnt");
  7153.     }
  7154.  
  7155.   radius = sqrt (((center_pnt->pnt.x - edge_pnt->pnt.x) *
  7156.           (center_pnt->pnt.x - edge_pnt->pnt.x)) +
  7157.          ((center_pnt->pnt.y - edge_pnt->pnt.y) *
  7158.           (center_pnt->pnt.y - edge_pnt->pnt.y)));
  7159.  
  7160.   draw_sqr (¢er_pnt->pnt);
  7161.   draw_sqr (&edge_pnt->pnt);
  7162.  
  7163.   if (drawing_pic)
  7164.     {
  7165.       gdk_draw_arc (pic_preview->window,
  7166.             pic_preview->style->black_gc,
  7167.             0,
  7168.             adjust_pic_coords (center_pnt->pnt.x - radius,
  7169.                        preview_width),
  7170.             adjust_pic_coords (center_pnt->pnt.y - radius,
  7171.                        preview_height),
  7172.             adjust_pic_coords (radius * 2,
  7173.                        preview_width),
  7174.             adjust_pic_coords (radius * 2,
  7175.                        preview_height),
  7176.             0,
  7177.             360 * 64);
  7178.     }
  7179.   else
  7180.     {
  7181.       gdk_draw_arc (gfig_preview->window,
  7182.             gfig_gc,
  7183.             0,
  7184.             gfig_scale_x (center_pnt->pnt.x - (gint) RINT (radius)),
  7185.             gfig_scale_y (center_pnt->pnt.y - (gint) RINT (radius)),
  7186.             gfig_scale_x ((gint) RINT (radius) * 2),
  7187.             gfig_scale_y ((gint) RINT (radius) * 2),
  7188.             0,
  7189.             360 * 64);
  7190.     }
  7191. }
  7192.  
  7193. static void
  7194. d_paint_circle (Dobject *obj)
  7195. {
  7196.   DobjPoints * center_pnt;
  7197.   DobjPoints * edge_pnt;
  7198.   gint radius;
  7199.   gdouble dpnts[4];
  7200.  
  7201.   g_assert (obj != NULL);
  7202.  
  7203.   if (selvals.approxcircles)
  7204.     {
  7205.       obj->type_data = (gpointer) 600;
  7206. #ifdef DEBUG
  7207.       printf ("Painting circle as polygon\n");
  7208. #endif /* DEBUG */
  7209.       d_paint_poly (obj);
  7210.       return;
  7211.     }      
  7212.  
  7213.   /* Drawing circles is hard .
  7214.    * 1) select circle
  7215.    * 2) stroke it
  7216.    */
  7217.   center_pnt = obj->points;
  7218.  
  7219.   if (!center_pnt)
  7220.     return; /* End-of-line */
  7221.  
  7222.   edge_pnt = center_pnt->next;
  7223.  
  7224.   if (!edge_pnt)
  7225.     {
  7226.       g_error ("Internal error - circle no edge pnt");
  7227.     }
  7228.  
  7229.   radius = (gint) sqrt (((center_pnt->pnt.x - edge_pnt->pnt.x) *
  7230.              (center_pnt->pnt.x - edge_pnt->pnt.x)) +
  7231.             ((center_pnt->pnt.y - edge_pnt->pnt.y) *
  7232.              (center_pnt->pnt.y - edge_pnt->pnt.y)));
  7233.  
  7234.   dpnts[0] = (gdouble) center_pnt->pnt.x - radius;
  7235.   dpnts[1] = (gdouble) center_pnt->pnt.y - radius;
  7236.   dpnts[3] = dpnts[2] = (gdouble) radius * 2;
  7237.  
  7238.   /* Scale before drawing */
  7239.   if (selvals.scaletoimage)
  7240.     scale_to_original_xy (&dpnts[0], 2);
  7241.   else
  7242.     scale_to_xy (&dpnts[0], 2);
  7243.  
  7244.   gimp_ellipse_select (gfig_image,
  7245.                dpnts[0], dpnts[1],
  7246.                dpnts[2], dpnts[3],
  7247.                selopt.type,
  7248.                selopt.antia,
  7249.                selopt.feather,
  7250.                selopt.feather_radius);
  7251.  
  7252.   /* Is selection all we need ? */
  7253.   if (selvals.painttype == PAINT_SELECTION_TYPE)
  7254.     return;
  7255.  
  7256.   gimp_edit_stroke (gfig_drawable);
  7257.  
  7258.   gimp_selection_clear (gfig_image);
  7259. }
  7260.  
  7261. static Dobject *
  7262. d_copy_circle (Dobject * obj)
  7263. {
  7264.   Dobject *nc;
  7265.  
  7266. #if DEBUG
  7267.   printf ("Copy circle\n");
  7268. #endif /*DEBUG*/
  7269.   if (!obj)
  7270.     return NULL;
  7271.  
  7272.   g_assert (obj->type == CIRCLE);
  7273.  
  7274.   nc = d_new_circle (obj->points->pnt.x, obj->points->pnt.y);
  7275.  
  7276.   nc->points->next = d_copy_dobjpoints (obj->points->next);
  7277.  
  7278. #if DEBUG
  7279.   printf ("Circle (%x,%x) to (%x,%x)\n",
  7280.       nc->points->pnt.x, obj->points->pnt.y,
  7281.       nc->points->next->pnt.x, obj->points->next->pnt.y);
  7282.   printf ("Done copy\n");
  7283. #endif /*DEBUG*/
  7284.   return nc;
  7285. }
  7286.  
  7287. static Dobject *
  7288. d_new_circle (gint x,
  7289.           gint y)
  7290. {
  7291.   Dobject *nobj;
  7292.   DobjPoints *npnt;
  7293.  
  7294.   /* Get new object and starting point */
  7295.  
  7296.   /* Start point */
  7297.   npnt = g_new0 (DobjPoints, 1);
  7298.  
  7299. #if DEBUG
  7300.   printf ("New circle start at (%x,%x)\n", x, y);
  7301. #endif /* DEBUG */
  7302.   npnt->pnt.x = x;
  7303.   npnt->pnt.y = y;
  7304.  
  7305.   nobj = g_new0 (Dobject, 1);
  7306.  
  7307.   nobj->type   = CIRCLE;
  7308.   nobj->points = npnt;
  7309.   nobj->drawfunc  = d_draw_circle;
  7310.   nobj->loadfunc  = d_load_circle;
  7311.   nobj->savefunc  = d_save_circle;
  7312.   nobj->paintfunc = d_paint_circle;
  7313.   nobj->copyfunc  = d_copy_circle;
  7314.  
  7315.   return nobj;
  7316. }
  7317.  
  7318. static void
  7319. d_update_circle (GdkPoint *pnt)
  7320. {
  7321.   DobjPoints *center_pnt, *edge_pnt;
  7322.   gdouble radius;
  7323.  
  7324.   /* Undraw last one then draw new one */
  7325.   center_pnt = obj_creating->points;
  7326.  
  7327.   if (!center_pnt)
  7328.     return; /* No points */
  7329.  
  7330.   if ((edge_pnt = center_pnt->next))
  7331.     {
  7332.       /* Undraw current */
  7333.       draw_circle (&edge_pnt->pnt);
  7334.       radius = sqrt (((center_pnt->pnt.x - edge_pnt->pnt.x) *
  7335.               (center_pnt->pnt.x - edge_pnt->pnt.x)) +
  7336.              ((center_pnt->pnt.y - edge_pnt->pnt.y) *
  7337.               (center_pnt->pnt.y - edge_pnt->pnt.y)));
  7338.       
  7339.       gdk_draw_arc (gfig_preview->window,
  7340.             gfig_gc,
  7341.             0,
  7342.             center_pnt->pnt.x - (gint) RINT (radius),
  7343.             center_pnt->pnt.y - (gint) RINT (radius),
  7344.             (gint) RINT (radius) * 2,
  7345.             (gint) RINT (radius) * 2,
  7346.             0,
  7347.             360 * 64);
  7348.     }
  7349.  
  7350.   draw_circle (pnt);
  7351.  
  7352.   edge_pnt = g_new0 (DobjPoints, 1);
  7353.  
  7354.   edge_pnt->pnt.x = pnt->x;
  7355.   edge_pnt->pnt.y = pnt->y;
  7356.  
  7357.   radius = sqrt (((center_pnt->pnt.x - edge_pnt->pnt.x) *
  7358.           (center_pnt->pnt.x - edge_pnt->pnt.x)) +
  7359.          ((center_pnt->pnt.y - edge_pnt->pnt.y) *
  7360.           (center_pnt->pnt.y - edge_pnt->pnt.y)));
  7361.  
  7362.   gdk_draw_arc (gfig_preview->window,
  7363.         gfig_gc,
  7364.         0,
  7365.         center_pnt->pnt.x - (gint) RINT (radius),
  7366.         center_pnt->pnt.y - (gint) RINT (radius),
  7367.         (gint) RINT (radius) * 2,
  7368.         (gint) RINT (radius) * 2,
  7369.         0,
  7370.         360 * 64);
  7371.  
  7372.   center_pnt->next = edge_pnt;
  7373. }
  7374.  
  7375. static void
  7376. d_circle_start (GdkPoint *pnt,
  7377.         gint      shift_down)
  7378. {
  7379.   obj_creating = d_new_circle (pnt->x, pnt->y);
  7380. }
  7381.  
  7382. static void
  7383. d_circle_end (GdkPoint *pnt,
  7384.           gint      shift_down)
  7385. {
  7386.   /* Under contrl point */
  7387.   if (!obj_creating->points->next)
  7388.     {
  7389.       /* No circle created */
  7390.       free_one_obj (obj_creating);
  7391.     }
  7392.   else
  7393.     {
  7394.       draw_circle (pnt);
  7395.       add_to_all_obj (current_obj, obj_creating);
  7396.     }
  7397.  
  7398.   obj_creating = NULL;
  7399. }
  7400.  
  7401. /* Save an ellipse away to the specified stream */
  7402.  
  7403. static void
  7404. d_save_ellipse (Dobject *obj,
  7405.         FILE    *to)
  7406. {
  7407.   DobjPoints *spnt;
  7408.  
  7409.   spnt = obj->points;
  7410.  
  7411.   if (!spnt)
  7412.     return;
  7413.  
  7414.   fprintf (to, "<ELLIPSE>\n");
  7415.  
  7416.   while (spnt)
  7417.     {
  7418.       fprintf (to, "%d %d\n",
  7419.            (gint) spnt->pnt.x,
  7420.            (gint) spnt->pnt.y);
  7421.       spnt = spnt->next;
  7422.     }
  7423.  
  7424.   fprintf (to, "</ELLIPSE>\n");
  7425. }
  7426.  
  7427. /* Load a circle from the specified stream */
  7428.  
  7429. static Dobject *
  7430. d_load_ellipse (FILE *from)
  7431. {
  7432.   Dobject *new_obj = NULL;
  7433.   gint     xpnt;
  7434.   gint     ypnt;
  7435.   gchar    buf[MAX_LOAD_LINE];
  7436.  
  7437. #ifdef DEBUG
  7438.   printf ("Load ellipse called\n");
  7439. #endif /* DEBUG */
  7440.  
  7441.   while (get_line (buf, MAX_LOAD_LINE, from, 0))
  7442.     {
  7443.       if (sscanf (buf, "%d %d", &xpnt, &ypnt) != 2)
  7444.     {
  7445.       /* Must be the end */
  7446.       if (strcmp ("</ELLIPSE>", buf))
  7447.         {
  7448.           g_message ("[%d] Internal load error while loading ellipse",
  7449.              line_no);
  7450.           return NULL;
  7451.         }
  7452.       return new_obj;
  7453.     }
  7454.  
  7455.       if (!new_obj)
  7456.     new_obj = d_new_ellipse (xpnt, ypnt);
  7457.       else
  7458.     {
  7459.       DobjPoints *edge_pnt;
  7460.       /* Circles only have two points */
  7461.       edge_pnt = g_new0 (DobjPoints, 1);
  7462.  
  7463.       edge_pnt->pnt.x = xpnt;
  7464.       edge_pnt->pnt.y = ypnt;
  7465.  
  7466.       new_obj->points->next = edge_pnt;
  7467.     }
  7468.     }
  7469.  
  7470.   g_message ("[%d] Not enough points for ellipse", line_no);
  7471.   return NULL;
  7472. }
  7473.  
  7474. static void
  7475. d_draw_ellipse (Dobject * obj)
  7476. {
  7477.   DobjPoints *center_pnt;
  7478.   DobjPoints *edge_pnt;
  7479.   gint bound_wx;
  7480.   gint bound_wy;
  7481.   gint top_x;
  7482.   gint top_y;
  7483.  
  7484.   center_pnt = obj->points;
  7485.  
  7486.   if (!center_pnt)
  7487.     return; /* End-of-line */
  7488.  
  7489.   edge_pnt = center_pnt->next;
  7490.  
  7491.   if (!edge_pnt)
  7492.     {
  7493.       g_warning ("Internal error - ellipse no edge pnt");
  7494.     }
  7495.  
  7496.   draw_sqr (¢er_pnt->pnt);
  7497.   draw_sqr (&edge_pnt->pnt);
  7498.  
  7499.   bound_wx = abs (center_pnt->pnt.x - edge_pnt->pnt.x) * 2;
  7500.   bound_wy = abs (center_pnt->pnt.y - edge_pnt->pnt.y) * 2;
  7501.  
  7502.   if (edge_pnt->pnt.x > center_pnt->pnt.x)
  7503.     top_x = 2 * center_pnt->pnt.x - edge_pnt->pnt.x;
  7504.   else
  7505.     top_x = edge_pnt->pnt.x;
  7506.   
  7507.   if (edge_pnt->pnt.y > center_pnt->pnt.y)
  7508.     top_y = 2 * center_pnt->pnt.y - edge_pnt->pnt.y;
  7509.   else
  7510.     top_y = edge_pnt->pnt.y;
  7511.  
  7512.   if (drawing_pic)
  7513.     {
  7514.       gdk_draw_arc (pic_preview->window,
  7515.             pic_preview->style->black_gc,
  7516.             0,
  7517.             adjust_pic_coords (top_x,
  7518.                        preview_width),
  7519.             adjust_pic_coords (top_y,
  7520.                        preview_height),
  7521.             adjust_pic_coords (bound_wx,
  7522.                        preview_width),
  7523.             adjust_pic_coords (bound_wy,
  7524.                        preview_height),
  7525.             0,
  7526.             360 * 64);
  7527.     }
  7528.   else
  7529.     {
  7530.       gdk_draw_arc (gfig_preview->window,
  7531.             gfig_gc,
  7532.             0,
  7533.             gfig_scale_x (top_x),
  7534.             gfig_scale_y (top_y),
  7535.             gfig_scale_x (bound_wx),
  7536.             gfig_scale_y (bound_wy),
  7537.             0,
  7538.             360 * 64);
  7539.     }
  7540. }
  7541.  
  7542. static void
  7543. d_paint_approx_ellipse (Dobject *obj)
  7544. {
  7545.   /* first point center */
  7546.   /* Next point is radius */
  7547.   gdouble *line_pnts;
  7548.   gint seg_count = 0;
  7549.   gint i = 0;
  7550.   DobjPoints * center_pnt;
  7551.   DobjPoints * radius_pnt;
  7552.   gdouble a_axis;
  7553.   gdouble b_axis;
  7554.   gdouble ang_grid;
  7555.   gdouble ang_loop;
  7556.   gdouble radius;
  7557.   gint loop;
  7558.   GdkPoint first_pnt, last_pnt;
  7559.   gint first = 1;
  7560.  
  7561.   g_assert (obj != NULL);
  7562.  
  7563.   /* count - add one to close polygon */
  7564.   seg_count = 600;
  7565.  
  7566.   center_pnt = obj->points;
  7567.  
  7568.   if (!center_pnt || !seg_count)
  7569.     return; /* no-line */
  7570.  
  7571.   line_pnts = g_new0 (gdouble, 2 * seg_count + 1);
  7572.  
  7573.   /* Go around all the points drawing a line from one to the next */
  7574.  
  7575.   radius_pnt = center_pnt->next; /* this defines the vetices */
  7576.  
  7577.   /* Have center and radius - get lines */
  7578.   a_axis = ((gdouble) (radius_pnt->pnt.x - center_pnt->pnt.x));
  7579.   b_axis = ((gdouble) (radius_pnt->pnt.y - center_pnt->pnt.y));
  7580.  
  7581.   /* Lines */
  7582.   ang_grid = 2 * G_PI / (gdouble) (gint) 600;
  7583.  
  7584.   for (loop = 0; loop < (gint) 600; loop++)
  7585.     {
  7586.       gdouble lx, ly;
  7587.       GdkPoint calc_pnt;
  7588.  
  7589.       ang_loop = (gdouble)loop * ang_grid;
  7590.  
  7591.       radius = (a_axis * b_axis /
  7592.         (sqrt (cos (ang_loop) * cos (ang_loop) *
  7593.                (b_axis * b_axis - a_axis * a_axis) + a_axis * a_axis)));
  7594.  
  7595.       lx = radius * cos (ang_loop);
  7596.       ly = radius * sin (ang_loop);
  7597.  
  7598.       calc_pnt.x = (gint) RINT (lx + center_pnt->pnt.x);
  7599.       calc_pnt.y = (gint) RINT (ly + center_pnt->pnt.y);
  7600.  
  7601.       /* Miss out duped pnts */
  7602.       if (!first)
  7603.     {
  7604.       if (calc_pnt.x == last_pnt.x && calc_pnt.y == last_pnt.y)
  7605.         {
  7606.           continue;
  7607.         }
  7608.     }
  7609.  
  7610.       last_pnt.x = line_pnts[i++] = calc_pnt.x;
  7611.       last_pnt.y = line_pnts[i++] = calc_pnt.y;
  7612.  
  7613.       if (first)
  7614.     {
  7615.       first_pnt.x = calc_pnt.x;
  7616.       first_pnt.y = calc_pnt.y;
  7617.       first = 0;
  7618.     }
  7619.     }
  7620.  
  7621.   line_pnts[i++] = first_pnt.x;
  7622.   line_pnts[i++] = first_pnt.y;
  7623.  
  7624.   /* Reverse line if approp */
  7625.   if (selvals.reverselines)
  7626.     reverse_pairs_list (&line_pnts[0], i / 2);
  7627.  
  7628.   /* Scale before drawing */
  7629.   if (selvals.scaletoimage)
  7630.     scale_to_original_xy (&line_pnts[0], i / 2);
  7631.   else
  7632.     scale_to_xy (&line_pnts[0], i / 2);
  7633.  
  7634.   /* One go */
  7635.   if (selvals.painttype == PAINT_BRUSH_TYPE)
  7636.     {
  7637.       gfig_paint (selvals.brshtype,
  7638.           gfig_drawable,
  7639.           i, line_pnts);
  7640.     }
  7641.   else
  7642.     {
  7643.       gimp_free_select (gfig_image,
  7644.             i, line_pnts,
  7645.             selopt.type,
  7646.             selopt.antia,
  7647.             selopt.feather,
  7648.             selopt.feather_radius);
  7649.     }
  7650.  
  7651.   g_free (line_pnts);
  7652. }
  7653.  
  7654.  
  7655.  
  7656. static void
  7657. d_paint_ellipse (Dobject *obj)
  7658. {
  7659.   DobjPoints * center_pnt;
  7660.   DobjPoints * edge_pnt;
  7661.   gint bound_wx;
  7662.   gint bound_wy;
  7663.   gint top_x;
  7664.   gint top_y;
  7665.   gdouble dpnts[4];
  7666.  
  7667.   /* Drawing ellipse is hard .
  7668.    * 1) select circle
  7669.    * 2) stroke it
  7670.    */
  7671.  
  7672.   g_assert (obj != NULL);
  7673.  
  7674.   if (selvals.approxcircles)
  7675.     {
  7676. #ifdef DEBUG
  7677.       printf ("Painting ellipse as polygon\n");
  7678. #endif /* DEBUG */
  7679.       d_paint_approx_ellipse (obj);
  7680.       return;
  7681.     }      
  7682.  
  7683.   center_pnt = obj->points;
  7684.  
  7685.   if (!center_pnt)
  7686.     return; /* End-of-line */
  7687.  
  7688.   edge_pnt = center_pnt->next;
  7689.  
  7690.   if (!edge_pnt)
  7691.     {
  7692.       g_error ("Internal error - ellipse no edge pnt");
  7693.     }
  7694.  
  7695.   bound_wx = abs (center_pnt->pnt.x - edge_pnt->pnt.x)*2;
  7696.   bound_wy = abs (center_pnt->pnt.y - edge_pnt->pnt.y)*2;
  7697.  
  7698.   if (edge_pnt->pnt.x > center_pnt->pnt.x)
  7699.     top_x = 2*center_pnt->pnt.x - edge_pnt->pnt.x;
  7700.   else
  7701.     top_x = edge_pnt->pnt.x;
  7702.   
  7703.   if (edge_pnt->pnt.y > center_pnt->pnt.y)
  7704.     top_y = 2*center_pnt->pnt.y - edge_pnt->pnt.y;
  7705.   else
  7706.     top_y = edge_pnt->pnt.y;
  7707.  
  7708.   dpnts[0] = (gdouble)top_x;
  7709.   dpnts[1] = (gdouble)top_y;
  7710.   dpnts[2] = (gdouble)bound_wx;
  7711.   dpnts[3] = (gdouble)bound_wy;
  7712.  
  7713.   /* Scale before drawing */
  7714.   if (selvals.scaletoimage)
  7715.     scale_to_original_xy (&dpnts[0], 2);
  7716.   else
  7717.     scale_to_xy (&dpnts[0], 2);
  7718.  
  7719.  
  7720.   gimp_ellipse_select (gfig_image,
  7721.                dpnts[0], dpnts[1],
  7722.                dpnts[2], dpnts[3],
  7723.                selopt.type,
  7724.                selopt.antia,
  7725.                selopt.feather,
  7726.                selopt.feather_radius);
  7727.  
  7728.   /* Is selection all we need ? */
  7729.   if (selvals.painttype == PAINT_SELECTION_TYPE)
  7730.     return;
  7731.  
  7732.   gimp_edit_stroke (gfig_drawable);
  7733.  
  7734.   gimp_selection_clear (gfig_image);
  7735. }
  7736.  
  7737. static Dobject *
  7738. d_copy_ellipse (Dobject * obj)
  7739. {
  7740.   Dobject *nc;
  7741.  
  7742. #if DEBUG
  7743.   printf ("Copy ellipse\n");
  7744. #endif /*DEBUG*/
  7745.   if (!obj)
  7746.     return (NULL);
  7747.  
  7748.   g_assert (obj->type == ELLIPSE);
  7749.  
  7750.   nc = d_new_ellipse (obj->points->pnt.x, obj->points->pnt.y);
  7751.  
  7752.   nc->points->next = d_copy_dobjpoints (obj->points->next);
  7753.  
  7754. #if DEBUG
  7755.   printf ("Ellipse (%x,%x) to (%x,%x)\n",
  7756.      nc->points->pnt.x, obj->points->pnt.y,
  7757.      nc->points->next->pnt.x, obj->points->next->pnt.y);
  7758.   printf ("Done copy\n");
  7759. #endif /*DEBUG*/
  7760.   return (nc);
  7761. }
  7762.  
  7763. static Dobject *
  7764. d_new_ellipse (gint x, gint y)
  7765. {
  7766.   Dobject *nobj;
  7767.   DobjPoints *npnt;
  7768.  
  7769.   /* Get new object and starting point */
  7770.  
  7771.   /* Start point */
  7772.   npnt = g_new0 (DobjPoints, 1);
  7773.  
  7774. #if DEBUG
  7775.   printf ("New ellipse start at (%x,%x)\n", x, y);
  7776. #endif /* DEBUG */
  7777.   npnt->pnt.x = x;
  7778.   npnt->pnt.y = y;
  7779.  
  7780.   nobj = g_new0 (Dobject, 1);
  7781.  
  7782.   nobj->type = ELLIPSE;
  7783.   nobj->points = npnt;
  7784.   nobj->drawfunc  = d_draw_ellipse;
  7785.   nobj->loadfunc  = d_load_ellipse;
  7786.   nobj->savefunc  = d_save_ellipse;
  7787.   nobj->paintfunc = d_paint_ellipse;
  7788.   nobj->copyfunc  = d_copy_ellipse;
  7789.  
  7790.   return (nobj);
  7791. }
  7792.  
  7793. static void
  7794. d_update_ellipse (GdkPoint *pnt)
  7795. {
  7796.   DobjPoints *center_pnt, *edge_pnt;
  7797.   gint bound_wx;
  7798.   gint bound_wy;
  7799.   gint top_x;
  7800.   gint top_y;
  7801.  
  7802.   /* Undraw last one then draw new one */
  7803.   center_pnt = obj_creating->points;
  7804.   
  7805.   if (!center_pnt)
  7806.     return; /* No points */
  7807.  
  7808.   
  7809.   if ((edge_pnt = center_pnt->next))
  7810.     {
  7811.       /* Undraw current */
  7812.       bound_wx = abs (center_pnt->pnt.x - edge_pnt->pnt.x)*2;
  7813.       bound_wy = abs (center_pnt->pnt.y - edge_pnt->pnt.y)*2;
  7814.       
  7815.       if (edge_pnt->pnt.x > center_pnt->pnt.x)
  7816.     top_x = 2*center_pnt->pnt.x - edge_pnt->pnt.x;
  7817.       else
  7818.     top_x = edge_pnt->pnt.x;
  7819.       
  7820.       if (edge_pnt->pnt.y > center_pnt->pnt.y)
  7821.     top_y = 2*center_pnt->pnt.y - edge_pnt->pnt.y;
  7822.       else
  7823.     top_y = edge_pnt->pnt.y;
  7824.  
  7825.       draw_circle (&edge_pnt->pnt);
  7826.       
  7827.       gdk_draw_arc (gfig_preview->window,
  7828.             gfig_gc,
  7829.             0,
  7830.             top_x,
  7831.             top_y,
  7832.             bound_wx,
  7833.             bound_wy,
  7834.             0,
  7835.             360*64);
  7836.     }
  7837.  
  7838.   draw_circle (pnt);
  7839.  
  7840.   edge_pnt = g_new0 (DobjPoints, 1);
  7841.  
  7842.   edge_pnt->pnt.x = pnt->x;
  7843.   edge_pnt->pnt.y = pnt->y;
  7844.  
  7845.   bound_wx = abs (center_pnt->pnt.x - edge_pnt->pnt.x)*2;
  7846.   bound_wy = abs (center_pnt->pnt.y - edge_pnt->pnt.y)*2;
  7847.  
  7848.   if (edge_pnt->pnt.x > center_pnt->pnt.x)
  7849.     top_x = 2*center_pnt->pnt.x - edge_pnt->pnt.x;
  7850.   else
  7851.     top_x = edge_pnt->pnt.x;
  7852.   
  7853.   if (edge_pnt->pnt.y > center_pnt->pnt.y)
  7854.     top_y = 2* center_pnt->pnt.y - edge_pnt->pnt.y;
  7855.   else
  7856.     top_y = edge_pnt->pnt.y;
  7857.   
  7858.   gdk_draw_arc (gfig_preview->window,
  7859.         gfig_gc,
  7860.         0,
  7861.         top_x,
  7862.         top_y,
  7863.         bound_wx,
  7864.         bound_wy,
  7865.         0,
  7866.         360*64);
  7867.   
  7868.   center_pnt->next = edge_pnt;
  7869. }
  7870.  
  7871. static void
  7872. d_ellipse_start (GdkPoint *pnt, gint shift_down)
  7873. {
  7874.   obj_creating = d_new_ellipse (pnt->x, pnt->y);
  7875. }
  7876.  
  7877. static void
  7878. d_ellipse_end (GdkPoint *pnt, gint shift_down)
  7879. {
  7880.   /* Under contrl point */
  7881.   if (!obj_creating->points->next)
  7882.     {
  7883.       /* No circle created */
  7884.       free_one_obj (obj_creating);
  7885.     }
  7886.   else
  7887.     {
  7888.       draw_circle (pnt);
  7889.       add_to_all_obj (current_obj, obj_creating);
  7890.     }
  7891.  
  7892.   obj_creating = NULL;
  7893. }
  7894.  
  7895. /* Normal polygon */
  7896.  
  7897. static void
  7898. d_save_poly (Dobject * obj, FILE *to)
  7899. {
  7900.   DobjPoints * spnt;
  7901.   
  7902.   spnt = obj->points;
  7903.  
  7904.   if (!spnt)
  7905.     return; /* End-of-line */
  7906.  
  7907.   fprintf (to, "<POLY>\n");
  7908.  
  7909.   while (spnt)
  7910.     {
  7911.       fprintf (to, "%d %d\n",
  7912.           (gint)spnt->pnt.x,
  7913.           (gint)spnt->pnt.y);
  7914.       spnt = spnt->next;
  7915.     }
  7916.   
  7917.   fprintf (to, "<EXTRA>\n");
  7918.   fprintf (to, "%d\n</EXTRA>\n", (gint)obj->type_data);
  7919.   fprintf (to, "</POLY>\n");
  7920.  
  7921. }
  7922.  
  7923. /* Load a circle from the specified stream */
  7924.  
  7925. static Dobject *
  7926. d_load_poly (FILE *from)
  7927. {
  7928.   Dobject *new_obj = NULL;
  7929.   gint xpnt;
  7930.   gint ypnt;
  7931.   gchar buf[MAX_LOAD_LINE];
  7932.  
  7933. #ifdef DEBUG
  7934.   printf ("Load poly called\n");
  7935. #endif /* DEBUG */
  7936.  
  7937.   while (get_line (buf, MAX_LOAD_LINE, from, 0))
  7938.     {
  7939.       if (sscanf (buf, "%d %d", &xpnt, &ypnt) != 2)
  7940.     {
  7941.       /* Must be the end */
  7942.       if (!strcmp ("<EXTRA>", buf))
  7943.         {
  7944.           gint nsides = 3;
  7945.           /* Number of sides - data item */
  7946.           if (!new_obj)
  7947.         {
  7948.           g_warning ("[%d] Internal load error while loading poly (extra area)",
  7949.                 line_no);
  7950.           return (NULL);
  7951.         }
  7952.           get_line (buf, MAX_LOAD_LINE, from, 0);
  7953.           if (sscanf (buf, "%d", &nsides) != 1)
  7954.         {
  7955.           g_warning ("[%d] Internal load error while loading poly (extra area scanf)",
  7956.                 line_no);
  7957.           return (NULL);
  7958.         }
  7959.           new_obj->type_data = (gpointer)nsides;
  7960.           get_line (buf, MAX_LOAD_LINE, from, 0);
  7961.           if (strcmp ("</EXTRA>", buf))
  7962.         {
  7963.           g_warning ("[%d] Internal load error while loading poly",
  7964.                 line_no);
  7965.           return (NULL);
  7966.         } 
  7967.           /* Go around and read the last line */
  7968.           continue;
  7969.         }
  7970.       else if (strcmp ("</POLY>", buf))
  7971.         {
  7972.           g_warning ("[%d] Internal load error while loading poly",
  7973.             line_no);
  7974.           return (NULL);
  7975.         }
  7976.       return (new_obj);
  7977.     }
  7978.       
  7979.       if (!new_obj)
  7980.     new_obj = d_new_poly (xpnt, ypnt);
  7981.       else
  7982.     d_pnt_add_line (new_obj, xpnt, ypnt, -1);
  7983.     }
  7984.   return (new_obj);
  7985. }
  7986.  
  7987. static void
  7988. d_draw_poly (Dobject *obj)
  7989. {
  7990.   DobjPoints * center_pnt;
  7991.   DobjPoints * radius_pnt;
  7992.   gint16 shift_x;
  7993.   gint16 shift_y;
  7994.   gdouble ang_grid;
  7995.   gdouble ang_loop;
  7996.   gdouble radius;
  7997.   gdouble offset_angle;
  7998.   gint loop;
  7999.   GdkPoint start_pnt;
  8000.   GdkPoint first_pnt;
  8001.   gint do_line = 0;
  8002.  
  8003.   center_pnt = obj->points;
  8004.  
  8005.   if (!center_pnt)
  8006.     return; /* End-of-line */
  8007.  
  8008.   /* First point is the center */
  8009.   /* Just draw a control point around it */
  8010.  
  8011.   draw_sqr (¢er_pnt->pnt);
  8012.  
  8013.   /* Next point defines the radius */
  8014.   radius_pnt = center_pnt->next; /* this defines the vertices */
  8015.  
  8016.   if (!radius_pnt)
  8017.     {
  8018. #ifdef DEBUG
  8019.       g_warning ("Internal error in polygon - no vertice point \n");
  8020. #endif /* DEBUG */
  8021.       return;
  8022.     }
  8023.  
  8024.   /* Other control point */
  8025.   draw_sqr (&radius_pnt->pnt);
  8026.  
  8027.   /* Have center and radius - draw polygon */
  8028.  
  8029.   shift_x = radius_pnt->pnt.x - center_pnt->pnt.x;
  8030.   shift_y = radius_pnt->pnt.y - center_pnt->pnt.y;
  8031.  
  8032.   radius = sqrt ((shift_x*shift_x) + (shift_y*shift_y));
  8033.  
  8034.   /* Lines */
  8035.   ang_grid = 2*G_PI/(gdouble) (gint)obj->type_data;
  8036.   offset_angle = atan2 (shift_y, shift_x);
  8037.  
  8038.   for (loop = 0 ; loop < (gint)obj->type_data ; loop++)
  8039.     {
  8040.       gdouble lx, ly;
  8041.       GdkPoint calc_pnt;
  8042.  
  8043.       ang_loop = (gdouble)loop * ang_grid + offset_angle;
  8044.     
  8045.       lx = radius * cos (ang_loop);
  8046.       ly = radius * sin (ang_loop);
  8047.  
  8048.       calc_pnt.x = (gint)RINT (lx + center_pnt->pnt.x);
  8049.       calc_pnt.y = (gint)RINT (ly + center_pnt->pnt.y);
  8050.  
  8051.       if (do_line)
  8052.     {
  8053.  
  8054.       /* Miss out points that come to the same location */
  8055.       if (calc_pnt.x == start_pnt.x && calc_pnt.y == start_pnt.y)
  8056.         continue;
  8057.  
  8058.       if (drawing_pic)
  8059.         {
  8060.           gdk_draw_line (pic_preview->window,
  8061.                  pic_preview->style->black_gc,                
  8062.                  adjust_pic_coords (calc_pnt.x,
  8063.                         preview_width),
  8064.                  adjust_pic_coords (calc_pnt.y,
  8065.                         preview_height),
  8066.                  adjust_pic_coords (start_pnt.x,
  8067.                         preview_width),
  8068.                  adjust_pic_coords (start_pnt.y,
  8069.                         preview_height));
  8070.         }
  8071.       else
  8072.         {
  8073.           gdk_draw_line (gfig_preview->window,
  8074.                  gfig_gc,
  8075.                  gfig_scale_x (calc_pnt.x),
  8076.                  gfig_scale_y (calc_pnt.y),
  8077.                  gfig_scale_x (start_pnt.x),
  8078.                  gfig_scale_y (start_pnt.y));
  8079.         }
  8080.     }
  8081.       else
  8082.     {
  8083.       do_line = 1;
  8084.       first_pnt.x = calc_pnt.x;
  8085.       first_pnt.y = calc_pnt.y;
  8086.     }
  8087.       start_pnt.x = calc_pnt.x;
  8088.       start_pnt.y = calc_pnt.y;
  8089.     }
  8090.  
  8091.   /* Join up */
  8092.   if (drawing_pic)
  8093.     {
  8094.       gdk_draw_line (pic_preview->window,
  8095.              pic_preview->style->black_gc,
  8096.              adjust_pic_coords (first_pnt.x, preview_width),
  8097.              adjust_pic_coords (first_pnt.y, preview_width),
  8098.              adjust_pic_coords (start_pnt.x, preview_width),
  8099.              adjust_pic_coords (start_pnt.y, preview_width));
  8100.     }
  8101.   else
  8102.     {
  8103.       gdk_draw_line (gfig_preview->window,
  8104.              gfig_gc,
  8105.              gfig_scale_x (first_pnt.x),
  8106.              gfig_scale_y (first_pnt.y),
  8107.              gfig_scale_x (start_pnt.x),
  8108.              gfig_scale_y (start_pnt.y));
  8109.     }
  8110. }
  8111.  
  8112. static void
  8113. d_paint_poly (Dobject *obj)
  8114. {
  8115.   /* first point center */
  8116.   /* Next point is radius */
  8117.   gdouble *line_pnts;
  8118.   gint seg_count = 0;
  8119.   gint i = 0;
  8120.   DobjPoints * center_pnt;
  8121.   DobjPoints * radius_pnt;
  8122.   gint16 shift_x;
  8123.   gint16 shift_y;
  8124.   gdouble ang_grid;
  8125.   gdouble ang_loop;
  8126.   gdouble radius;
  8127.   gdouble offset_angle;
  8128.   gint loop;
  8129.   GdkPoint first_pnt, last_pnt;
  8130.   gint first = 1;
  8131.  
  8132.   g_assert (obj != NULL);
  8133.  
  8134.   /* count - add one to close polygon */
  8135.   seg_count = (gint)obj->type_data + 1;
  8136.  
  8137.   center_pnt = obj->points;
  8138.  
  8139.   if (!center_pnt || !seg_count || !center_pnt->next)
  8140.     return; /* no-line */
  8141.  
  8142.   line_pnts = g_new0 (gdouble, 2 * seg_count + 1);
  8143.   
  8144.   /* Go around all the points drawing a line from one to the next */
  8145.  
  8146.   radius_pnt = center_pnt->next; /* this defines the vetices */
  8147.  
  8148.   /* Have center and radius - get lines */
  8149.   shift_x = radius_pnt->pnt.x - center_pnt->pnt.x;
  8150.   shift_y = radius_pnt->pnt.y - center_pnt->pnt.y;
  8151.  
  8152.   radius = sqrt ((shift_x*shift_x) + (shift_y*shift_y));
  8153.  
  8154.   /* Lines */
  8155.   ang_grid = 2*G_PI/(gdouble) (gint)obj->type_data;
  8156.   offset_angle = atan2 (shift_y, shift_x);
  8157.  
  8158.   for (loop = 0 ; loop < (gint)obj->type_data ; loop++)
  8159.     {
  8160.       gdouble lx, ly;
  8161.       GdkPoint calc_pnt;
  8162.       
  8163.       ang_loop = (gdouble)loop * ang_grid + offset_angle;
  8164.     
  8165.       lx = radius * cos (ang_loop);
  8166.       ly = radius * sin (ang_loop);
  8167.  
  8168.       calc_pnt.x = (gint)RINT (lx + center_pnt->pnt.x);
  8169.       calc_pnt.y = (gint)RINT (ly + center_pnt->pnt.y);
  8170.  
  8171.       /* Miss out duped pnts */
  8172.       if (!first)
  8173.     {
  8174.       if (calc_pnt.x == last_pnt.x && calc_pnt.y == last_pnt.y)
  8175.         {
  8176.           continue;
  8177.         }
  8178.     }
  8179.  
  8180.       last_pnt.x = line_pnts[i++] = calc_pnt.x;
  8181.       last_pnt.y = line_pnts[i++] = calc_pnt.y;
  8182.  
  8183.       if (first)
  8184.     {
  8185.       first_pnt.x = calc_pnt.x;
  8186.       first_pnt.y = calc_pnt.y;
  8187.       first = 0;
  8188.     }
  8189.     }
  8190.  
  8191.   line_pnts[i++] = first_pnt.x;
  8192.   line_pnts[i++] = first_pnt.y;
  8193.  
  8194.   /* Reverse line if approp */
  8195.   if (selvals.reverselines)
  8196.     reverse_pairs_list (&line_pnts[0], i/2);
  8197.  
  8198.   /* Scale before drawing */
  8199.   if (selvals.scaletoimage)
  8200.     scale_to_original_xy (&line_pnts[0], i/2);
  8201.   else
  8202.     scale_to_xy (&line_pnts[0], i/2);
  8203.  
  8204.   /* One go */
  8205.   if (selvals.painttype == PAINT_BRUSH_TYPE)
  8206.     {
  8207.       gfig_paint (selvals.brshtype,
  8208.           gfig_drawable,
  8209.           i, line_pnts);
  8210.     }
  8211.   else
  8212.     {
  8213.       gimp_free_select (gfig_image,
  8214.             i, line_pnts,
  8215.             selopt.type,
  8216.             selopt.antia,
  8217.             selopt.feather,
  8218.             selopt.feather_radius);
  8219.     }
  8220.  
  8221.   g_free (line_pnts);
  8222. }
  8223.  
  8224. static void
  8225. d_poly2lines (Dobject *obj)
  8226. {
  8227.   /* first point center */
  8228.   /* Next point is radius */
  8229.   gint seg_count = 0;
  8230.   DobjPoints * center_pnt;
  8231.   DobjPoints * radius_pnt;
  8232.   gint16 shift_x;
  8233.   gint16 shift_y;
  8234.   gdouble ang_grid;
  8235.   gdouble ang_loop;
  8236.   gdouble radius;
  8237.   gdouble offset_angle;
  8238.   gint loop;
  8239.   GdkPoint first_pnt, last_pnt;
  8240.   gint first = 1;
  8241.  
  8242.   g_assert (obj != NULL);
  8243.  
  8244. #ifdef DEBUG
  8245.   printf ("d_poly2lines --- \n");
  8246. #endif /* DEBUG */
  8247.  
  8248.   /* count - add one to close polygon */
  8249.   seg_count = (gint)obj->type_data + 1;
  8250.  
  8251.   center_pnt = obj->points;
  8252.  
  8253.   if (!center_pnt)
  8254.     return; /* no-line */
  8255.  
  8256.   /* Undraw it to start with - removes control points */ 
  8257.   obj->drawfunc (obj);
  8258.  
  8259.   /* NULL out these points free later */
  8260.   obj->points = NULL;
  8261.  
  8262.   /* Go around all the points creating line points */
  8263.  
  8264.   radius_pnt = center_pnt->next; /* this defines the vertices */
  8265.  
  8266.   /* Have center and radius - get lines */
  8267.   shift_x = radius_pnt->pnt.x - center_pnt->pnt.x;
  8268.   shift_y = radius_pnt->pnt.y - center_pnt->pnt.y;
  8269.  
  8270.   radius = sqrt ((shift_x*shift_x) + (shift_y*shift_y));
  8271.  
  8272.   /* Lines */
  8273.   ang_grid = 2*G_PI/(gdouble) (gint)obj->type_data;
  8274.   offset_angle = atan2 (shift_y, shift_x);
  8275.  
  8276.   for (loop = 0 ; loop < (gint)obj->type_data ; loop++)
  8277.     {
  8278.       gdouble lx, ly;
  8279.       GdkPoint calc_pnt;
  8280.       
  8281.       ang_loop = (gdouble)loop * ang_grid + offset_angle;
  8282.     
  8283.       lx = radius * cos (ang_loop);
  8284.       ly = radius * sin (ang_loop);
  8285.  
  8286.       calc_pnt.x = (gint)RINT (lx + center_pnt->pnt.x);
  8287.       calc_pnt.y = (gint)RINT (ly + center_pnt->pnt.y);
  8288.  
  8289.       if (!first)
  8290.     {
  8291.       if (calc_pnt.x == last_pnt.x && calc_pnt.y == last_pnt.y)
  8292.         {
  8293.           continue;
  8294.         }
  8295.     }
  8296.  
  8297.       d_pnt_add_line (obj, calc_pnt.x, calc_pnt.y, 0);
  8298.  
  8299.       last_pnt.x = calc_pnt.x;
  8300.       last_pnt.y = calc_pnt.y;
  8301.  
  8302.       if (first)
  8303.     {
  8304.       first_pnt.x = calc_pnt.x;
  8305.       first_pnt.y = calc_pnt.y;
  8306.       first = 0;
  8307.     }
  8308.     }
  8309.  
  8310.   d_pnt_add_line (obj, first_pnt.x, first_pnt.y, 0);
  8311.   /* Free old pnts */
  8312.   d_delete_dobjpoints (center_pnt);
  8313.  
  8314.   /* hey we're a line now */
  8315.   obj->type = LINE;
  8316.   obj->drawfunc  = d_draw_line;
  8317.   obj->loadfunc  = d_load_line;
  8318.   obj->savefunc  = d_save_line;
  8319.   obj->paintfunc = d_paint_line;
  8320.   obj->copyfunc  = d_copy_line;
  8321.  
  8322.   /* draw it + control pnts */
  8323.   obj->drawfunc (obj);
  8324. }
  8325.  
  8326. static void
  8327. d_star2lines (Dobject *obj)
  8328. {
  8329.   /* first point center */
  8330.   /* Next point is radius */
  8331.   gint seg_count = 0;
  8332.   DobjPoints * center_pnt;
  8333.   DobjPoints * outer_radius_pnt;
  8334.   DobjPoints * inner_radius_pnt;
  8335.   gint16 shift_x;
  8336.   gint16 shift_y;
  8337.   gdouble ang_grid;
  8338.   gdouble ang_loop;
  8339.   gdouble outer_radius;
  8340.   gdouble inner_radius;
  8341.   gdouble offset_angle;
  8342.   gint loop;
  8343.   GdkPoint first_pnt, last_pnt;
  8344.   gint first = 1;
  8345.  
  8346.   g_assert (obj != NULL);
  8347.  
  8348. #ifdef DEBUG
  8349.   printf ("d_star2lines --- \n");
  8350. #endif /* DEBUG */
  8351.  
  8352.   /* count - add one to close polygon */
  8353.   seg_count = 2*(gint)obj->type_data + 1;
  8354.  
  8355.   center_pnt = obj->points;
  8356.  
  8357.   if (!center_pnt)
  8358.     return; /* no-line */
  8359.  
  8360.   /* Undraw it to start with - removes control points */ 
  8361.   obj->drawfunc (obj);
  8362.  
  8363.   /* NULL out these points free later */
  8364.   obj->points = NULL;
  8365.  
  8366.   /* Go around all the points creating line points */
  8367.   /* Next point defines the radius */
  8368.   outer_radius_pnt = center_pnt->next; /* this defines the vetices */
  8369.  
  8370.   if (!outer_radius_pnt)
  8371.     {
  8372. #ifdef DEBUG
  8373.       g_warning ("Internal error in star - no outer vertice point \n");
  8374. #endif /* DEBUG */
  8375.       return;
  8376.     }
  8377.  
  8378.   inner_radius_pnt = outer_radius_pnt->next; /* this defines the vetices */
  8379.  
  8380.   if (!inner_radius_pnt)
  8381.     {
  8382. #ifdef DEBUG
  8383.       g_warning ("Internal error in star - no inner vertice point \n");
  8384. #endif /* DEBUG */
  8385.       return;
  8386.     }
  8387.  
  8388.   shift_x = outer_radius_pnt->pnt.x - center_pnt->pnt.x;
  8389.   shift_y = outer_radius_pnt->pnt.y - center_pnt->pnt.y;
  8390.  
  8391.   outer_radius = sqrt ((shift_x*shift_x) + (shift_y*shift_y));
  8392.  
  8393.   /* Lines */
  8394.   ang_grid = 2*G_PI/(2.0*(gdouble) (gint)obj->type_data);
  8395.   offset_angle = atan2 (shift_y, shift_x);
  8396.  
  8397.   shift_x = inner_radius_pnt->pnt.x - center_pnt->pnt.x;
  8398.   shift_y = inner_radius_pnt->pnt.y - center_pnt->pnt.y;
  8399.  
  8400.   inner_radius = sqrt ((shift_x*shift_x) + (shift_y*shift_y));
  8401.  
  8402.   for (loop = 0 ; loop < 2*(gint)obj->type_data ; loop++)
  8403.     {
  8404.       gdouble lx, ly;
  8405.       GdkPoint calc_pnt;
  8406.       
  8407.       ang_loop = (gdouble)loop * ang_grid + offset_angle;
  8408.  
  8409.       if (loop%2)
  8410.     {
  8411.       lx = inner_radius * cos (ang_loop);
  8412.       ly = inner_radius * sin (ang_loop);
  8413.     }
  8414.       else
  8415.     {
  8416.       lx = outer_radius * cos (ang_loop);
  8417.       ly = outer_radius * sin (ang_loop);
  8418.     }
  8419.  
  8420.       calc_pnt.x = (gint)RINT (lx + center_pnt->pnt.x);
  8421.       calc_pnt.y = (gint)RINT (ly + center_pnt->pnt.y);
  8422.  
  8423.       if (!first)
  8424.     {
  8425.       if (calc_pnt.x == last_pnt.x && calc_pnt.y == last_pnt.y)
  8426.         {
  8427.           continue;
  8428.         }
  8429.     }
  8430.  
  8431.       d_pnt_add_line (obj, calc_pnt.x, calc_pnt.y, 0);
  8432.  
  8433.       last_pnt.x = calc_pnt.x;
  8434.       last_pnt.y = calc_pnt.y;
  8435.  
  8436.       if (first)
  8437.     {
  8438.       first_pnt.x = calc_pnt.x;
  8439.       first_pnt.y = calc_pnt.y;
  8440.       first = 0;
  8441.     }
  8442.     }
  8443.  
  8444.   d_pnt_add_line (obj, first_pnt.x, first_pnt.y, 0);
  8445.   /* Free old pnts */
  8446.   d_delete_dobjpoints (center_pnt);
  8447.  
  8448.   /* hey we're a line now */
  8449.   obj->type = LINE;
  8450.   obj->drawfunc  = d_draw_line;
  8451.   obj->loadfunc  = d_load_line;
  8452.   obj->savefunc  = d_save_line;
  8453.   obj->paintfunc = d_paint_line;
  8454.   obj->copyfunc  = d_copy_line;
  8455.  
  8456.   /* draw it + control pnts */
  8457.   obj->drawfunc (obj);
  8458. }
  8459.  
  8460. static Dobject *
  8461. d_copy_poly (Dobject * obj)
  8462. {
  8463.   Dobject *np;
  8464.  
  8465. #if DEBUG
  8466.   printf ("Copy poly\n");
  8467. #endif /*DEBUG*/
  8468.   if (!obj)
  8469.     return (NULL);
  8470.  
  8471.   g_assert (obj->type == POLY);
  8472.  
  8473.   np = d_new_poly (obj->points->pnt.x, obj->points->pnt.y);
  8474.  
  8475.   np->points->next = d_copy_dobjpoints (obj->points->next);
  8476.  
  8477.   np->type_data = obj->type_data;
  8478.  
  8479. #if DEBUG
  8480.   printf ("Done poly copy\n");
  8481. #endif /*DEBUG*/
  8482.   return (np);
  8483. }
  8484.  
  8485. static Dobject *
  8486. d_new_poly (gint x, gint y)
  8487. {
  8488.   Dobject *nobj;
  8489.   DobjPoints *npnt;
  8490.  
  8491.   /* Get new object and starting point */
  8492.  
  8493.   /* Start point */
  8494.   npnt = g_new0 (DobjPoints, 1);
  8495.  
  8496. #if DEBUG
  8497.   printf ("New POLY start at (%x,%x)\n", x, y);
  8498. #endif /* DEBUG */
  8499.   npnt->pnt.x = x;
  8500.   npnt->pnt.y = y;
  8501.  
  8502.   nobj = g_new0 (Dobject, 1);
  8503.  
  8504.   nobj->type = POLY;
  8505.   nobj->type_data = (gpointer)3; /* Default to three sides */
  8506.   nobj->points = npnt;
  8507.   nobj->drawfunc  = d_draw_poly;
  8508.   nobj->loadfunc  = d_load_poly;
  8509.   nobj->savefunc  = d_save_poly;
  8510.   nobj->paintfunc = d_paint_poly;
  8511.   nobj->copyfunc  = d_copy_poly;
  8512.  
  8513.   return (nobj);
  8514. }
  8515.  
  8516. static void
  8517. d_update_poly (GdkPoint *pnt)
  8518. {
  8519.   DobjPoints *center_pnt, *edge_pnt;
  8520.   gint saved_cnt_pnt = selvals.opts.showcontrol;
  8521.  
  8522.   /* Undraw last one then draw new one */
  8523.   center_pnt = obj_creating->points;
  8524.   
  8525.   if (!center_pnt)
  8526.     return; /* No points */
  8527.  
  8528.   /* Leave the first pnt alone -
  8529.    * Edge point defines "radius"
  8530.    * Only undraw if already have edge point.
  8531.    */
  8532.  
  8533.   /* Hack - turn off cnt points in draw routine 
  8534.    * Looking back over the other update routines I could
  8535.    * use this trick again and cut down on code size!
  8536.    */
  8537.  
  8538.  
  8539.   if ((edge_pnt = center_pnt->next))
  8540.     {
  8541.       /* Undraw */
  8542.       draw_circle (&edge_pnt->pnt);
  8543.       selvals.opts.showcontrol = 0;
  8544.       d_draw_poly (obj_creating);
  8545.  
  8546.       edge_pnt->pnt.x = pnt->x;
  8547.       edge_pnt->pnt.y = pnt->y;
  8548.     }
  8549.   else
  8550.     {
  8551.       /* Radius is a few pixels away */
  8552.       /* First edge point */
  8553.       d_pnt_add_line (obj_creating, pnt->x, pnt->y, -1);
  8554.       edge_pnt = center_pnt->next;
  8555.     }
  8556.  
  8557.   /* draw it */
  8558.   selvals.opts.showcontrol = 0;
  8559.   d_draw_poly (obj_creating);
  8560.   selvals.opts.showcontrol = saved_cnt_pnt;
  8561.  
  8562.   /* Realy draw the control points */
  8563.   draw_circle (&edge_pnt->pnt);
  8564. }
  8565.  
  8566. /* first point is center 
  8567.  * next defines the radius
  8568.  */
  8569.  
  8570. static void
  8571. d_poly_start (GdkPoint *pnt,
  8572.           gint      shift_down)
  8573. {
  8574.   gint16 x, y;
  8575.   /* First is center point */
  8576.   obj_creating = d_new_poly (x = pnt->x, y = pnt->y);
  8577.   obj_creating->type_data = (gpointer)poly_num_sides;
  8578. }
  8579.  
  8580. static void
  8581. d_poly_end (GdkPoint *pnt,
  8582.         gint      shift_down)
  8583. {
  8584.   draw_circle (pnt);
  8585.   add_to_all_obj (current_obj, obj_creating);
  8586.   obj_creating = NULL;
  8587. }
  8588.  
  8589. /* ARC stuff */
  8590. /* Distance between two lines */
  8591. static gdouble
  8592. dist (gdouble x1,
  8593.       gdouble y1,
  8594.       gdouble x2,
  8595.       gdouble y2)
  8596. {
  8597.  
  8598.   double s1 = x1 - x2;
  8599.   double s2 = y1 - y2;
  8600.  
  8601.   return (sqrt ((s1*s1) + (s2*s2)));
  8602. }
  8603.  
  8604. /* Mid point of line returned */
  8605. static void
  8606. mid_point (gdouble x1,
  8607.        gdouble y1,
  8608.        gdouble x2,
  8609.        gdouble y2,
  8610.        gdouble *mx,
  8611.        gdouble *my)
  8612. {
  8613.   *mx = ((double) (x1 - x2))/2.0 + (double)x2;
  8614.   *my = ((double) (y1 - y2))/2.0 + (double)y2;
  8615. }
  8616.  
  8617. /* Careful about infinite grads */
  8618. static gdouble
  8619. line_grad (gdouble x1,
  8620.        gdouble y1,
  8621.        gdouble x2,
  8622.        gdouble y2)
  8623. {
  8624.   double dx, dy;
  8625.   
  8626.   dx = x1 - x2;
  8627.   dy = y1 - y2;
  8628.  
  8629.   if (dx == 0.0)
  8630.     return (0.0); /* Infinite ! */
  8631.  
  8632.   return (dy/dx);
  8633. }
  8634.  
  8635. /* Constant of line that goes through x, y with grad lgrad */
  8636. static gdouble
  8637. line_cons (gdouble x,
  8638.        gdouble y,
  8639.        gdouble lgrad)
  8640. {
  8641.   return (y - lgrad*x);
  8642. }
  8643.  
  8644. /*Get grad & const for perpend. line to given points */
  8645. static void
  8646. line_definition (gdouble  x1,
  8647.          gdouble  y1,
  8648.          gdouble  x2,
  8649.          gdouble  y2,
  8650.          gdouble *lgrad,
  8651.          gdouble *lconst)
  8652. {
  8653.   double grad1;
  8654.   double midx, midy;
  8655.  
  8656.   grad1 = line_grad (x1, y1, x2, y2);
  8657.  
  8658.   if (grad1 == 0.0)
  8659.     {
  8660. #ifdef DEBUG
  8661.       printf ("Infinite grad....\n");
  8662. #endif /* DEBUG */
  8663.       return;
  8664.     }
  8665.  
  8666.   mid_point (x1, y1, x2, y2, &midx, &midy);
  8667.  
  8668.   /* Invert grad for perpen gradient */
  8669.  
  8670.   *lgrad = -1.0/grad1;
  8671.   
  8672.   *lconst = line_cons (midx, midy,*lgrad);
  8673. }
  8674.  
  8675. /* Arch details 
  8676.  * Given three points get arc radius and the co-ords 
  8677.  * of center point.
  8678.  */
  8679.  
  8680. static void
  8681. arc_details (GdkPoint *vert_a,
  8682.          GdkPoint *vert_b,
  8683.          GdkPoint *vert_c,
  8684.          GdkPoint *center_pnt,
  8685.          gdouble  *radius)
  8686. {
  8687.   /* Only vertices are in whole numbers - everything else is in doubles */
  8688.   double ax, ay;
  8689.   double bx, by;
  8690.   double cx, cy;
  8691.  
  8692.   double len_a, len_b, len_c;
  8693.   double sum_sides2;
  8694.   double area;
  8695.   double circumcircle_R;
  8696.   double line1_grad, line1_const;
  8697.   double line2_grad, line2_const;
  8698.   double inter_x=0.0, inter_y=0.0;
  8699.   int got_x=0, got_y=0;
  8700.  
  8701.   ax = (double) (vert_a->x);
  8702.   ay = (double) (vert_a->y);
  8703.   bx = (double) (vert_b->x);
  8704.   by = (double) (vert_b->y);
  8705.   cx = (double) (vert_c->x);
  8706.   cy = (double) (vert_c->y);
  8707.  
  8708. #ifdef DEBUG
  8709.   printf ("Vertices (%f,%f), (%f,%f), (%f,%f)\n", ax, ay, bx, by, cx, cy);
  8710. #endif /* DEBUG */
  8711.  
  8712.   len_a = dist (ax, ay, bx, by);
  8713.   len_b = dist (bx, by, cx, cy);
  8714.   len_c = dist (cx, cy, ax, ay);
  8715. #ifdef DEBUG
  8716.   printf ("len_a = %f, len_b = %f, len_c = %f\n", len_a, len_b, len_c);
  8717. #endif /* DEBUG */
  8718.  
  8719.  
  8720.   sum_sides2 = (fabs (len_a) + fabs (len_b) + fabs (len_c))/2;
  8721. #ifdef DEBUG
  8722.   printf ("Sum sides / 2 = %f\n", sum_sides2);
  8723. #endif /* DEBUG */
  8724.  
  8725.   /* Area */
  8726.   area = sqrt (sum_sides2*(sum_sides2 - len_a)*(sum_sides2 - len_b)*(sum_sides2 - len_c));
  8727. #ifdef DEBUG
  8728.   printf ("Area of triangle = %f\n", area);
  8729. #endif /* DEBUG */
  8730.   
  8731.   /* Circumcircle */
  8732.   circumcircle_R = len_a*len_b*len_c/(4*area);
  8733.   *radius = circumcircle_R;
  8734. #ifdef DEBUG
  8735.   printf ("Circumcircle radius = %f\n", circumcircle_R);
  8736. #endif /* DEBUG */
  8737.  
  8738.   /* Deal with exceptions - I hate exceptions */
  8739.  
  8740.   if (ax == bx || ax == cx || cx == bx)
  8741.     {
  8742.       /* vert line -> mid point gives inter_x */
  8743.       if (ax == bx && bx == cx)
  8744.     {
  8745.       /* Straight line */
  8746.       double miny = ay;
  8747.       double maxy = ay;
  8748.  
  8749.       if (by > maxy)
  8750.         maxy = by;
  8751.       
  8752.       if (by < miny)
  8753.         miny = by;
  8754.  
  8755.       if (cy > maxy)
  8756.         maxy = cy;
  8757.  
  8758.       if (cy < miny)
  8759.         miny = cy;
  8760.  
  8761.       inter_y = (maxy - miny)/2 + miny;
  8762.     }
  8763.       else if (ax == bx)
  8764.     {
  8765.       inter_y = (ay - by)/2 + by;
  8766.     }
  8767.       else if (bx == cx)
  8768.     {
  8769.       inter_y = (by - cy)/2 + cy;
  8770.     }
  8771.       else
  8772.     {
  8773.       inter_y = (cy - ay)/2 + ay;
  8774.     }
  8775.       got_y = 1;
  8776.     }
  8777.  
  8778.   if (ay == by || by == cy || ay == cy)
  8779.     {
  8780.       /* Horz line -> midpoint gives inter_y */
  8781.       if (ax == bx && bx == cx)
  8782.     {
  8783.       /* Straight line */
  8784.       double minx = ax;
  8785.       double maxx = ax;
  8786.  
  8787.       if (bx > maxx)
  8788.         maxx = bx;
  8789.       
  8790.       if (bx < minx)
  8791.         minx = bx;
  8792.  
  8793.       if (cx > maxx)
  8794.         maxx = cx;
  8795.  
  8796.       if (cx < minx)
  8797.         minx = cx;
  8798.  
  8799.       inter_x = (maxx - minx)/2 + minx;
  8800.     }
  8801.       else if (ay == by)
  8802.     {
  8803.       inter_x = (ax - bx)/2 + bx;
  8804.     }
  8805.       else if (by == cy)
  8806.     {
  8807.       inter_x = (bx - cx)/2 + cx;
  8808.     }
  8809.       else
  8810.     {
  8811.       inter_x = (cx - ax)/2 + ax;
  8812.     }
  8813.       got_x = 1;
  8814.     }
  8815.  
  8816.   if (!got_x || !got_y)
  8817.     {
  8818.       /* At least two of the lines are not parallel to the axis */
  8819.       /*first line */
  8820.       if (ax != bx && ay != by)
  8821.     line_definition (ax, ay, bx, by, &line1_grad, &line1_const);
  8822.       else
  8823.     line_definition (ax, ay, cx, cy, &line1_grad, &line1_const);
  8824.       /* second line */
  8825.       if (bx != cx && by != cy)
  8826.     line_definition (bx, by, cx, cy, &line2_grad, &line2_const);
  8827.       else
  8828.     line_definition (ax, ay, cx, cy, &line2_grad, &line2_const);
  8829.     }
  8830.  
  8831.   /* Intersection point */
  8832.  
  8833.   if (!got_x)
  8834.     inter_x = /*rint*/((line2_const - line1_const)/(line1_grad - line2_grad));
  8835.   if (!got_y)
  8836.     inter_y = /*rint*/((line1_grad * inter_x + line1_const));
  8837.  
  8838. #ifdef DEBUG
  8839.   printf ("Intersection point is (%f,%f)\n", inter_x, inter_y);
  8840. #endif /* DEBUG */
  8841.  
  8842.   center_pnt->x = (gint16)inter_x;
  8843.   center_pnt->y = (gint16)inter_y;
  8844. }
  8845.  
  8846. static gdouble
  8847. arc_angle (GdkPoint *pnt,
  8848.        GdkPoint *center)
  8849. {
  8850.   /* Get angle (in degress) of point given origin of center */
  8851.   gint16 shift_x;
  8852.   gint16 shift_y;
  8853.   gdouble offset_angle;
  8854.  
  8855.   shift_x = pnt->x - center->x;
  8856.   shift_y = -pnt->y + center->y;
  8857.   offset_angle = atan2 (shift_y, shift_x);
  8858. #ifdef DEBUG
  8859.   printf ("offset_ang = %f\n", offset_angle);
  8860. #endif /* DEBUG */
  8861.   if (offset_angle < 0)
  8862.     offset_angle += 2*G_PI;
  8863.  
  8864.   return (offset_angle*360/(2*G_PI));
  8865. }
  8866.  
  8867. static void
  8868. d_save_arc (Dobject *obj,
  8869.         FILE    *to)
  8870. {
  8871.   DobjPoints * spnt;
  8872.  
  8873.   spnt = obj->points;
  8874.  
  8875.   if (!spnt)
  8876.     return;
  8877.  
  8878.   fprintf (to, "<ARC>\n");
  8879.  
  8880.   while (spnt)
  8881.     {
  8882.       fprintf (to, "%d %d\n",
  8883.           (gint)spnt->pnt.x,
  8884.           (gint)spnt->pnt.y);
  8885.       spnt = spnt->next;
  8886.     }
  8887.   
  8888.   fprintf (to, "</ARC>\n");
  8889. }
  8890.  
  8891. /* Load a circle from the specified stream */
  8892.  
  8893. static Dobject *
  8894. d_load_arc (FILE *from)
  8895. {
  8896.   Dobject *new_obj = NULL;
  8897.   gint xpnt;
  8898.   gint ypnt;
  8899.   gchar buf[MAX_LOAD_LINE];
  8900.   gint num_pnts = 0;
  8901.  
  8902. #ifdef DEBUG
  8903.   printf ("Load arc called\n");
  8904. #endif /* DEBUG */
  8905.  
  8906.   while (get_line (buf, MAX_LOAD_LINE, from, 0))
  8907.     {
  8908.       if (sscanf (buf, "%d %d", &xpnt, &ypnt) != 2)
  8909.     {
  8910.       /* Must be the end */
  8911.       if (strcmp ("</ARC>", buf) || num_pnts != 3)
  8912.         {
  8913.           g_warning ("[%d] Internal load error while loading arc",
  8914.             line_no);
  8915.           return (NULL);
  8916.         }
  8917.       return (new_obj);
  8918.     }
  8919.       
  8920.       num_pnts++;
  8921.  
  8922.       if (!new_obj)
  8923.     new_obj = d_new_arc (xpnt, ypnt);
  8924.       else
  8925.     {
  8926.       d_pnt_add_line (new_obj, xpnt, ypnt,-1);
  8927.     }
  8928.     }
  8929.   g_warning ("[%d] Not enough points for arc", line_no);
  8930.   return (NULL);
  8931. }
  8932.  
  8933. static void
  8934. arc_drawing_details (Dobject  *obj,
  8935.              gdouble  *minang,
  8936.              GdkPoint *center_pnt,
  8937.              gdouble  *arcang,
  8938.              gdouble  *radius,
  8939.              gint      draw_cnts,
  8940.              gint      do_scale)
  8941. {
  8942.   DobjPoints * pnt1 = NULL;
  8943.   DobjPoints * pnt2 = NULL;
  8944.   DobjPoints * pnt3 = NULL;
  8945.   DobjPoints dpnts[3];
  8946.   gdouble ang1, ang2, ang3;
  8947.   gdouble maxang;
  8948.  
  8949.   pnt1 = obj->points;
  8950.  
  8951.   if (!pnt1)
  8952.     return; /* Not fully drawn */
  8953.  
  8954.   pnt2 = pnt1->next;
  8955.  
  8956.   if (!pnt2)
  8957.     return; /* Not fully drawn */
  8958.  
  8959.   pnt3 = pnt2->next;
  8960.  
  8961.   if (!pnt3)
  8962.     return; /* Still not fully drawn */
  8963.  
  8964.   if (draw_cnts)
  8965.     {
  8966.       draw_sqr (&pnt1->pnt);
  8967.       draw_sqr (&pnt2->pnt);
  8968.       draw_sqr (&pnt3->pnt);
  8969.     }
  8970.  
  8971.   if (do_scale)
  8972.     {
  8973.       /* Adjust pnts for scaling */
  8974.       /* Warning struct copies here! and casting to double <-> int */
  8975.       /* Too complex fix me - to much hacking */
  8976.       gdouble xy[2];
  8977.       int j;
  8978.  
  8979.       dpnts[0] = *pnt1;
  8980.       dpnts[1] = *pnt2;
  8981.       dpnts[2] = *pnt3;
  8982.  
  8983.       pnt1 = &dpnts[0];
  8984.       pnt2 = &dpnts[1];
  8985.       pnt3 = &dpnts[2];
  8986.  
  8987.       for (j = 0 ; j < 3; j++)
  8988.     {
  8989.       xy[0] = dpnts[j].pnt.x;
  8990.       xy[1] = dpnts[j].pnt.y;
  8991.       if (selvals.scaletoimage)
  8992.         scale_to_original_xy (&xy[0], 1);
  8993.       else
  8994.         scale_to_xy (&xy[0], 1);
  8995.       dpnts[j].pnt.x = xy[0];
  8996.       dpnts[j].pnt.y = xy[1];
  8997.     }
  8998.     }
  8999.  
  9000.   arc_details (&pnt1->pnt, &pnt2->pnt, &pnt3->pnt, center_pnt, radius);
  9001.   
  9002.   ang1 = arc_angle (&pnt1->pnt, center_pnt);
  9003.   ang2 = arc_angle (&pnt2->pnt, center_pnt);
  9004.   ang3 = arc_angle (&pnt3->pnt, center_pnt);
  9005.  
  9006.   /* Find min/max angle */
  9007.  
  9008.   maxang = ang1;
  9009.  
  9010.   if (ang3 > maxang)
  9011.     maxang = ang3;
  9012.   
  9013.   *minang = ang1;
  9014.  
  9015.   if (ang3 < *minang)
  9016.     *minang = ang3;
  9017.  
  9018.   if (ang2 > *minang && ang2 < maxang)
  9019.     *arcang = maxang - *minang;
  9020.   else
  9021.     *arcang = maxang - *minang - 360;
  9022. }
  9023.  
  9024. static void
  9025. d_draw_arc (Dobject * obj)
  9026. {
  9027.   GdkPoint center_pnt;
  9028.   gdouble radius, minang, arcang;
  9029.  
  9030.   g_assert (obj != NULL);
  9031.  
  9032.   if (!obj)
  9033.     return;
  9034.  
  9035.   arc_drawing_details (obj, &minang, ¢er_pnt, &arcang, &radius, TRUE, FALSE);
  9036.   
  9037. #ifdef DEBUG
  9038.   printf ("Min ang = %f Arc ang = %f\n", minang, arcang);
  9039. #endif /* DEBUG */
  9040.  
  9041.   if (drawing_pic)
  9042.     {
  9043.       gdk_draw_arc (pic_preview->window,
  9044.             pic_preview->style->black_gc,
  9045.             0,
  9046.             adjust_pic_coords (center_pnt.x - (gint)radius,
  9047.                       preview_width),
  9048.             adjust_pic_coords (center_pnt.y - (gint)radius,
  9049.                       preview_height),
  9050.             adjust_pic_coords ((gint) (radius * 2),
  9051.                       preview_width),
  9052.             adjust_pic_coords ((gint) (radius * 2),
  9053.                       preview_height),
  9054.             (gint) (minang*64),
  9055.             (gint) (arcang*64));
  9056.     }
  9057.   else
  9058.     {
  9059.       gdk_draw_arc (gfig_preview->window,
  9060.             gfig_gc,
  9061.             0,
  9062.             gfig_scale_x (center_pnt.x - (gint)radius),
  9063.             gfig_scale_y (center_pnt.y - (gint)radius),
  9064.             gfig_scale_x ((gint) (radius * 2)),
  9065.             gfig_scale_y ((gint) (radius * 2)),
  9066.             (gint) (minang*64),
  9067.             (gint) (arcang*64));
  9068.     }
  9069. }
  9070.  
  9071. static void
  9072. d_paint_arc (Dobject *obj)
  9073. {
  9074.   /* first point center */
  9075.   /* Next point is radius */
  9076.   gdouble *line_pnts;
  9077.   gint seg_count = 0;
  9078.   gint i = 0;
  9079.   gdouble ang_grid;
  9080.   gdouble ang_loop;
  9081.   gdouble radius;
  9082.   gint loop;
  9083.   GdkPoint first_pnt, last_pnt;
  9084.   gint first = 1;
  9085.   GdkPoint center_pnt;
  9086.   gdouble minang, arcang;
  9087.  
  9088.   g_assert (obj != NULL);
  9089.  
  9090.   if (!obj)
  9091.     return;
  9092.  
  9093.   /* No cnt pnts & must scale */
  9094.   arc_drawing_details (obj, &minang, ¢er_pnt, &arcang, &radius, FALSE, TRUE);
  9095.  
  9096. #ifdef DEBUG
  9097.   printf ("Paint Min ang = %f Arc ang = %f\n", minang, arcang);
  9098. #endif /* DEBUG */
  9099.  
  9100.   seg_count = 360; /* Should make a smoth-ish curve */
  9101.  
  9102.   /* +3 because we MIGHT do pie selection */
  9103.   line_pnts = g_new0 (gdouble, 2 * seg_count + 3);
  9104.  
  9105.   /* Lines */
  9106.   ang_grid = 2*G_PI/(gdouble)360;
  9107.  
  9108.   if (arcang < 0.0)
  9109.     {
  9110.       /* Swap - since we always draw anti-clock wise */
  9111.       minang += arcang;
  9112.       arcang = -arcang;
  9113.     }
  9114.  
  9115.   minang = minang * (2*G_PI/360); /* min ang is in degrees - need in rads*/
  9116.  
  9117.   for (loop = 0 ; loop < abs ((gint)arcang) ; loop++)
  9118.     {
  9119.       gdouble lx, ly;
  9120.       GdkPoint calc_pnt;
  9121.       
  9122.       ang_loop = (gdouble)loop * ang_grid + minang;
  9123.  
  9124.       lx = radius * cos (ang_loop);
  9125.       ly = -radius * sin (ang_loop); /* y grows down screen and angs measured from x clockwise */
  9126.  
  9127.       calc_pnt.x = (gint)RINT (lx + center_pnt.x);
  9128.       calc_pnt.y = (gint)RINT (ly + center_pnt.y);
  9129.  
  9130.       /* Miss out duped pnts */
  9131.       if (!first)
  9132.     {
  9133.       if (calc_pnt.x == last_pnt.x && calc_pnt.y == last_pnt.y)
  9134.         {
  9135.           continue;
  9136.         }
  9137.     }
  9138.  
  9139.       last_pnt.x = line_pnts[i++] = calc_pnt.x;
  9140.       last_pnt.y = line_pnts[i++] = calc_pnt.y;
  9141.  
  9142.       if (first)
  9143.     {
  9144.       first_pnt.x = calc_pnt.x;
  9145.       first_pnt.y = calc_pnt.y;
  9146.       first = 0;
  9147.     }
  9148.     }
  9149.  
  9150.   /* Reverse line if approp */
  9151.   if (selvals.reverselines)
  9152.     reverse_pairs_list (&line_pnts[0], i/2);
  9153.  
  9154.   /* One go */
  9155.   if (selvals.painttype == PAINT_BRUSH_TYPE)
  9156.     {
  9157.       gfig_paint (selvals.brshtype,
  9158.           gfig_drawable,
  9159.           i, line_pnts);
  9160.     }
  9161.   else
  9162.     {
  9163.       if (selopt.as_pie)
  9164.     {
  9165.       /* Add center point - cause a pie like selection... */
  9166.       line_pnts[i++] = center_pnt.x;
  9167.       line_pnts[i++] = center_pnt.y;
  9168.     }
  9169.  
  9170.       gimp_free_select (gfig_image,
  9171.             i, line_pnts,
  9172.             selopt.type,
  9173.             selopt.antia,
  9174.             selopt.feather,
  9175.             selopt.feather_radius);
  9176.     }
  9177.  
  9178.   g_free (line_pnts);
  9179. }
  9180.  
  9181. static Dobject *
  9182. d_copy_arc (Dobject * obj)
  9183. {
  9184.   Dobject *nc;
  9185.  
  9186. #if DEBUG
  9187.   printf ("Copy ellipse\n");
  9188. #endif /*DEBUG*/
  9189.   if (!obj)
  9190.     return (NULL);
  9191.  
  9192.   g_assert (obj->type == ARC);
  9193.  
  9194.   nc = d_new_arc (obj->points->pnt.x, obj->points->pnt.y);
  9195.  
  9196.   nc->points->next = d_copy_dobjpoints (obj->points->next);
  9197.  
  9198. #if DEBUG
  9199.   printf ("Arc (%x,%x), (%x,%x), (%x,%x)\n",
  9200.      nc->points->pnt.x, obj->points->pnt.y,
  9201.      nc->points->next->pnt.x, obj->points->next->pnt.y,
  9202.      nc->points->next->next->pnt.x, obj->points->next->next->pnt.y);
  9203.   printf ("Done copy\n");
  9204. #endif /*DEBUG*/
  9205.   return (nc);
  9206. }
  9207.  
  9208. static Dobject *
  9209. d_new_arc (gint x,
  9210.        gint y)
  9211. {
  9212.   Dobject *nobj;
  9213.   DobjPoints *npnt;
  9214.  
  9215.   /* Get new object and starting point */
  9216.  
  9217.   /* Start point */
  9218.   npnt = g_new0 (DobjPoints, 1);
  9219.  
  9220. #if DEBUG
  9221.   printf ("New arc start at (%x,%x)\n", x, y);
  9222. #endif /* DEBUG */
  9223.   npnt->pnt.x = x;
  9224.   npnt->pnt.y = y;
  9225.  
  9226.   nobj = g_new0 (Dobject, 1);
  9227.  
  9228.   nobj->type = ARC;
  9229.   nobj->points = npnt;
  9230.   nobj->drawfunc  = d_draw_arc;
  9231.   nobj->loadfunc  = d_load_arc;
  9232.   nobj->savefunc  = d_save_arc;
  9233.   nobj->paintfunc = d_paint_arc;
  9234.   nobj->copyfunc  = d_copy_arc;
  9235.  
  9236.   return (nobj);
  9237. }
  9238.  
  9239. static void
  9240. d_update_arc (GdkPoint *pnt)
  9241. {
  9242.   DobjPoints * pnt1 = NULL;
  9243.   DobjPoints * pnt2 = NULL;
  9244.   DobjPoints * pnt3 = NULL;
  9245.  
  9246.   /* First two points as line only become arch when third
  9247.    * point is placed on canvas.
  9248.    */
  9249.  
  9250.   pnt1 = obj_creating->points;
  9251.  
  9252.   if (!pnt1 ||
  9253.      !(pnt2 = pnt1->next) ||
  9254.      !(pnt3 = pnt2->next))
  9255.     {
  9256.       d_update_line (pnt);
  9257.       return; /* Not fully drawn */
  9258.     }
  9259.  
  9260.   /* Update a real curve */
  9261.   /* Nothing to be done ... */
  9262. }
  9263.  
  9264. static void
  9265. d_arc_start (GdkPoint *pnt,
  9266.          gint      shift_down)
  9267. {
  9268.   /* Draw lines to start with -- then convert to an arc */
  9269.   if (!tmp_line)
  9270.     draw_sqr (pnt);
  9271.   d_line_start (pnt, TRUE); /* TRUE means multiple pointed line */
  9272. }
  9273.  
  9274. static void
  9275. d_arc_end (GdkPoint *pnt,
  9276.        gint      shift_down)
  9277. {
  9278.   /* Under contrl point */
  9279.   if (!tmp_line ||
  9280.      !tmp_line->points ||
  9281.      !tmp_line->points->next)
  9282.     {
  9283.       /* No arc created  - yet */
  9284.       /* Must have three points */
  9285. #ifdef DEBUG
  9286.       printf ("No arc created yet\n");
  9287. #endif /* DEBUG */
  9288.       d_line_end (pnt, TRUE);
  9289.     }
  9290.   else
  9291.     {
  9292.       /* Complete arc */
  9293.       /* Convert to an arc ... */
  9294.       tmp_line->type = ARC;
  9295.       tmp_line->drawfunc  = d_draw_arc;
  9296.       tmp_line->loadfunc  = d_load_arc;
  9297.       tmp_line->savefunc  = d_save_arc;
  9298.       tmp_line->paintfunc = d_paint_arc;
  9299.       tmp_line->copyfunc  = d_copy_arc;
  9300.       d_line_end (pnt, FALSE);
  9301.       /*d_draw_line (newarc);  Should undraw line */
  9302.       if (need_to_scale)
  9303.     {
  9304.       selvals.scaletoimage = 0;
  9305.     }
  9306.       /*d_draw_arc (newarc);*/
  9307.       update_draw_area (gfig_preview, NULL);
  9308.       if (need_to_scale)
  9309.     {
  9310.       selvals.scaletoimage = 1;
  9311.     }
  9312.  
  9313.     }
  9314. }
  9315. /*XXXXXXXXXXXXXXXXXXXXXXX*/
  9316. /* Star shape */
  9317.  
  9318. static void
  9319. d_save_star (Dobject *obj,
  9320.          FILE    *to)
  9321. {
  9322.   DobjPoints * spnt;
  9323.   
  9324.   spnt = obj->points;
  9325.  
  9326.   if (!spnt)
  9327.     return; /* End-of-line */
  9328.  
  9329.   fprintf (to, "<STAR>\n");
  9330.  
  9331.   while (spnt)
  9332.     {
  9333.       fprintf (to, "%d %d\n",
  9334.           (gint)spnt->pnt.x,
  9335.           (gint)spnt->pnt.y);
  9336.       spnt = spnt->next;
  9337.     }
  9338.   
  9339.   fprintf (to, "<EXTRA>\n");
  9340.   fprintf (to, "%d\n</EXTRA>\n", (gint)obj->type_data);
  9341.   fprintf (to, "</STAR>\n");
  9342. }
  9343.  
  9344. /* Load a circle from the specified stream */
  9345.  
  9346. static Dobject *
  9347. d_load_star (FILE *from)
  9348. {
  9349.   Dobject *new_obj = NULL;
  9350.   gint xpnt;
  9351.   gint ypnt;
  9352.   gchar buf[MAX_LOAD_LINE];
  9353.  
  9354. #ifdef DEBUG
  9355.   printf ("Load star called\n");
  9356. #endif /* DEBUG */
  9357.  
  9358.   while (get_line (buf, MAX_LOAD_LINE, from, 0))
  9359.     {
  9360.       if (sscanf (buf, "%d %d", &xpnt, &ypnt) != 2)
  9361.     {
  9362.       /* Must be the end */
  9363.       if (!strcmp ("<EXTRA>", buf))
  9364.         {
  9365.           gint nsides = 3;
  9366.           /* Number of sides - data item */
  9367.           if (!new_obj)
  9368.         {
  9369.           g_warning ("[%d] Internal load error while loading star (extra area)",
  9370.                 line_no);
  9371.           return (NULL);
  9372.         }
  9373.           get_line (buf, MAX_LOAD_LINE, from, 0);
  9374.           if (sscanf (buf, "%d", &nsides) != 1)
  9375.         {
  9376.           g_warning ("[%d] Internal load error while loading star (extra area scanf)",
  9377.                 line_no);
  9378.           return (NULL);
  9379.         }
  9380.           new_obj->type_data = (gpointer)nsides;
  9381.           get_line (buf, MAX_LOAD_LINE, from, 0);
  9382.           if (strcmp ("</EXTRA>", buf))
  9383.         {
  9384.           g_warning ("[%d] Internal load error while loading star",
  9385.                 line_no);
  9386.           return (NULL);
  9387.         } 
  9388.           /* Go around and read the last line */
  9389.           continue;
  9390.         }
  9391.       else if (strcmp ("</STAR>", buf))
  9392.         {
  9393.           g_warning ("[%d] Internal load error while loading star",
  9394.             line_no);
  9395.           return (NULL);
  9396.         }
  9397.       return (new_obj);
  9398.     }
  9399.       
  9400.       if (!new_obj)
  9401.     new_obj = d_new_star (xpnt, ypnt);
  9402.       else
  9403.     d_pnt_add_line (new_obj, xpnt, ypnt,-1);
  9404.     }
  9405.   return (new_obj);
  9406. }
  9407.  
  9408. static void
  9409. d_draw_star (Dobject *obj)
  9410. {
  9411.   DobjPoints * center_pnt;
  9412.   DobjPoints * outer_radius_pnt;
  9413.   DobjPoints * inner_radius_pnt;
  9414.   gint16 shift_x;
  9415.   gint16 shift_y;
  9416.   gdouble ang_grid;
  9417.   gdouble ang_loop;
  9418.   gdouble outer_radius;
  9419.   gdouble inner_radius;
  9420.   gdouble offset_angle;
  9421.   gint loop;
  9422.   GdkPoint start_pnt;
  9423.   GdkPoint first_pnt;
  9424.   gint do_line = 0;
  9425.  
  9426.   center_pnt = obj->points;
  9427.  
  9428.   if (!center_pnt)
  9429.     return; /* End-of-line */
  9430.  
  9431.   /* First point is the center */
  9432.   /* Just draw a control point around it */
  9433.  
  9434.   draw_sqr (¢er_pnt->pnt);
  9435.  
  9436.   /* Next point defines the radius */
  9437.   outer_radius_pnt = center_pnt->next; /* this defines the vetices */
  9438.  
  9439.   if (!outer_radius_pnt)
  9440.     {
  9441. #ifdef DEBUG
  9442.       g_warning ("Internal error in star - no outer vertice point \n");
  9443. #endif /* DEBUG */
  9444.       return;
  9445.     }
  9446.  
  9447.   inner_radius_pnt = outer_radius_pnt->next; /* this defines the vetices */
  9448.  
  9449.   if (!inner_radius_pnt)
  9450.     {
  9451. #ifdef DEBUG
  9452.       g_warning ("Internal error in star - no inner vertice point \n");
  9453. #endif /* DEBUG */
  9454.       return;
  9455.     }
  9456.  
  9457.   /* Other control points */
  9458.   draw_sqr (&outer_radius_pnt->pnt);
  9459.   draw_sqr (&inner_radius_pnt->pnt);
  9460.  
  9461.   /* Have center and radius - draw star */
  9462.  
  9463.   shift_x = outer_radius_pnt->pnt.x - center_pnt->pnt.x;
  9464.   shift_y = outer_radius_pnt->pnt.y - center_pnt->pnt.y;
  9465.  
  9466.   outer_radius = sqrt ((shift_x*shift_x) + (shift_y*shift_y));
  9467.  
  9468.   /* Lines */
  9469.   ang_grid = 2*G_PI/(2.0*(gdouble) (gint)obj->type_data);
  9470.   offset_angle = atan2 (shift_y, shift_x);
  9471.  
  9472.   shift_x = inner_radius_pnt->pnt.x - center_pnt->pnt.x;
  9473.   shift_y = inner_radius_pnt->pnt.y - center_pnt->pnt.y;
  9474.  
  9475.   inner_radius = sqrt ((shift_x*shift_x) + (shift_y*shift_y));
  9476.  
  9477.   for (loop = 0 ; loop < 2*(gint)obj->type_data ; loop++)
  9478.     {
  9479.       gdouble lx, ly;
  9480.       GdkPoint calc_pnt;
  9481.  
  9482.       ang_loop = (gdouble)loop * ang_grid + offset_angle;
  9483.     
  9484.       if (loop%2)
  9485.     {
  9486.       lx = inner_radius * cos (ang_loop);
  9487.       ly = inner_radius * sin (ang_loop);
  9488.     }
  9489.       else
  9490.     {
  9491.       lx = outer_radius * cos (ang_loop);
  9492.       ly = outer_radius * sin (ang_loop);
  9493.     }
  9494.  
  9495.       calc_pnt.x = (gint)RINT (lx + center_pnt->pnt.x);
  9496.       calc_pnt.y = (gint)RINT (ly + center_pnt->pnt.y);
  9497.  
  9498.       if (do_line)
  9499.     {
  9500.  
  9501.       /* Miss out points that come to the same location */
  9502.       if (calc_pnt.x == start_pnt.x && calc_pnt.y == start_pnt.y)
  9503.         continue;
  9504.  
  9505.       if (drawing_pic)
  9506.         {
  9507.           gdk_draw_line (pic_preview->window,
  9508.                  pic_preview->style->black_gc,                
  9509.                  adjust_pic_coords (calc_pnt.x,
  9510.                         preview_width),
  9511.                  adjust_pic_coords (calc_pnt.y,
  9512.                         preview_height),
  9513.                  adjust_pic_coords (start_pnt.x,
  9514.                         preview_width),
  9515.                  adjust_pic_coords (start_pnt.y,
  9516.                         preview_height));
  9517.         }
  9518.       else
  9519.         {
  9520.           gdk_draw_line (gfig_preview->window,
  9521.                  gfig_gc,
  9522.                  gfig_scale_x (calc_pnt.x),
  9523.                  gfig_scale_y (calc_pnt.y),
  9524.                  gfig_scale_x (start_pnt.x),
  9525.                  gfig_scale_y (start_pnt.y));
  9526.         }
  9527.     }
  9528.       else
  9529.     {
  9530.       do_line = 1;
  9531.       first_pnt.x = calc_pnt.x;
  9532.       first_pnt.y = calc_pnt.y;
  9533.     }
  9534.       start_pnt.x = calc_pnt.x;
  9535.       start_pnt.y = calc_pnt.y;
  9536.     }
  9537.  
  9538.   /* Join up */
  9539.   if (drawing_pic)
  9540.     {
  9541.       gdk_draw_line (pic_preview->window,
  9542.              pic_preview->style->black_gc,
  9543.              adjust_pic_coords (first_pnt.x, preview_width),
  9544.              adjust_pic_coords (first_pnt.y, preview_width),
  9545.              adjust_pic_coords (start_pnt.x, preview_width),
  9546.              adjust_pic_coords (start_pnt.y, preview_width));
  9547.     }
  9548.   else
  9549.     {
  9550.       gdk_draw_line (gfig_preview->window,
  9551.              gfig_gc,
  9552.              gfig_scale_x (first_pnt.x),
  9553.              gfig_scale_y (first_pnt.y),
  9554.              gfig_scale_x (start_pnt.x),
  9555.              gfig_scale_y (start_pnt.y));
  9556.     }
  9557. }
  9558.  
  9559. static void
  9560. d_paint_star (Dobject *obj)
  9561. {
  9562.   /* first point center */
  9563.   /* Next point is radius */
  9564.   gdouble *line_pnts;
  9565.   gint seg_count = 0;
  9566.   gint i = 0;
  9567.   DobjPoints * center_pnt;
  9568.   DobjPoints * outer_radius_pnt;
  9569.   DobjPoints * inner_radius_pnt;
  9570.   gint16 shift_x;
  9571.   gint16 shift_y;
  9572.   gdouble ang_grid;
  9573.   gdouble ang_loop;
  9574.   gdouble outer_radius;
  9575.   gdouble inner_radius;
  9576.  
  9577.   gdouble offset_angle;
  9578.   gint loop;
  9579.   GdkPoint first_pnt, last_pnt;
  9580.   gint first = 1;
  9581.  
  9582.   g_assert (obj != NULL);
  9583.  
  9584.   /* count - add one to close polygon */
  9585.   seg_count = 2*(gint)obj->type_data + 1;
  9586.  
  9587.   center_pnt = obj->points;
  9588.  
  9589.   if (!center_pnt || !seg_count)
  9590.     return; /* no-line */
  9591.  
  9592.   line_pnts = g_new0 (gdouble, 2 * seg_count + 1);
  9593.   
  9594.   /* Go around all the points drawing a line from one to the next */
  9595.   /* Next point defines the radius */
  9596.   outer_radius_pnt = center_pnt->next; /* this defines the vetices */
  9597.  
  9598.   if (!outer_radius_pnt)
  9599.     {
  9600. #ifdef DEBUG
  9601.       g_warning ("Internal error in star - no outer vertice point \n");
  9602. #endif /* DEBUG */
  9603.       return;
  9604.     }
  9605.  
  9606.   inner_radius_pnt = outer_radius_pnt->next; /* this defines the vetices */
  9607.  
  9608.   if (!inner_radius_pnt)
  9609.     {
  9610. #ifdef DEBUG
  9611.       g_warning ("Internal error in star - no inner vertice point \n");
  9612. #endif /* DEBUG */
  9613.       return;
  9614.     }
  9615.  
  9616.   shift_x = outer_radius_pnt->pnt.x - center_pnt->pnt.x;
  9617.   shift_y = outer_radius_pnt->pnt.y - center_pnt->pnt.y;
  9618.  
  9619.   outer_radius = sqrt ((shift_x*shift_x) + (shift_y*shift_y));
  9620.  
  9621.   /* Lines */
  9622.   ang_grid = 2*G_PI/(2.0*(gdouble) (gint)obj->type_data);
  9623.   offset_angle = atan2 (shift_y, shift_x);
  9624.  
  9625.   shift_x = inner_radius_pnt->pnt.x - center_pnt->pnt.x;
  9626.   shift_y = inner_radius_pnt->pnt.y - center_pnt->pnt.y;
  9627.  
  9628.   inner_radius = sqrt ((shift_x*shift_x) + (shift_y*shift_y));
  9629.  
  9630.   for (loop = 0 ; loop < 2*(gint)obj->type_data ; loop++)
  9631.     {
  9632.       gdouble lx, ly;
  9633.       GdkPoint calc_pnt;
  9634.       
  9635.       ang_loop = (gdouble)loop * ang_grid + offset_angle;
  9636.     
  9637.       if (loop%2)
  9638.     {
  9639.       lx = inner_radius * cos (ang_loop);
  9640.       ly = inner_radius * sin (ang_loop);
  9641.     }
  9642.       else
  9643.     {
  9644.       lx = outer_radius * cos (ang_loop);
  9645.       ly = outer_radius * sin (ang_loop);
  9646.     }
  9647.  
  9648.       calc_pnt.x = (gint)RINT (lx + center_pnt->pnt.x);
  9649.       calc_pnt.y = (gint)RINT (ly + center_pnt->pnt.y);
  9650.  
  9651.       /* Miss out duped pnts */
  9652.       if (!first)
  9653.     {
  9654.       if (calc_pnt.x == last_pnt.x && calc_pnt.y == last_pnt.y)
  9655.         {
  9656.           continue;
  9657.         }
  9658.     }
  9659.  
  9660.       last_pnt.x = line_pnts[i++] = calc_pnt.x;
  9661.       last_pnt.y = line_pnts[i++] = calc_pnt.y;
  9662.  
  9663.       if (first)
  9664.     {
  9665.       first_pnt.x = calc_pnt.x;
  9666.       first_pnt.y = calc_pnt.y;
  9667.       first = 0;
  9668.     }
  9669.     }
  9670.  
  9671.   line_pnts[i++] = first_pnt.x;
  9672.   line_pnts[i++] = first_pnt.y;
  9673.  
  9674.   /* Reverse line if approp */
  9675.   if (selvals.reverselines)
  9676.     reverse_pairs_list (&line_pnts[0], i/2);
  9677.  
  9678.   /* Scale before drawing */
  9679.   if (selvals.scaletoimage)
  9680.     scale_to_original_xy (&line_pnts[0], i/2);
  9681.   else
  9682.     scale_to_xy (&line_pnts[0], i/2);
  9683.  
  9684.   /* One go */
  9685.   if (selvals.painttype == PAINT_BRUSH_TYPE)
  9686.     {
  9687.       gfig_paint (selvals.brshtype,
  9688.           gfig_drawable,
  9689.           i, line_pnts);
  9690.     }
  9691.   else
  9692.     {
  9693.       gimp_free_select (gfig_image,
  9694.             i, line_pnts,
  9695.             selopt.type,
  9696.             selopt.antia,
  9697.             selopt.feather,
  9698.             selopt.feather_radius);
  9699.     }
  9700.  
  9701.   g_free (line_pnts);
  9702. }
  9703.  
  9704. static Dobject *
  9705. d_copy_star (Dobject * obj)
  9706. {
  9707.   Dobject *np;
  9708.  
  9709. #if DEBUG
  9710.   printf ("Copy star\n");
  9711. #endif /*DEBUG*/
  9712.   if (!obj)
  9713.     return (NULL);
  9714.  
  9715.   g_assert (obj->type == STAR);
  9716.  
  9717.   np = d_new_star (obj->points->pnt.x, obj->points->pnt.y);
  9718.  
  9719.   np->points->next = d_copy_dobjpoints (obj->points->next);
  9720.  
  9721.   np->type_data = obj->type_data;
  9722.  
  9723. #if DEBUG
  9724.   printf ("Done star copy\n");
  9725. #endif /*DEBUG*/
  9726.   return (np);
  9727. }
  9728.  
  9729. static Dobject *
  9730. d_new_star (gint x,
  9731.         gint y)
  9732. {
  9733.   Dobject *nobj;
  9734.   DobjPoints *npnt;
  9735.  
  9736.   /* Get new object and starting point */
  9737.  
  9738.   /* Start point */
  9739.   npnt = g_new0 (DobjPoints, 1);
  9740.  
  9741. #if DEBUG
  9742.   printf ("New STAR start at (%x,%x)\n", x, y);
  9743. #endif /* DEBUG */
  9744.   npnt->pnt.x = x;
  9745.   npnt->pnt.y = y;
  9746.  
  9747.   nobj = g_new0 (Dobject, 1);
  9748.  
  9749.   nobj->type = STAR;
  9750.   nobj->type_data = (gpointer)3; /* Default to three sides 6 points*/
  9751.   nobj->points = npnt;
  9752.   nobj->drawfunc  = d_draw_star;
  9753.   nobj->loadfunc  = d_load_star;
  9754.   nobj->savefunc  = d_save_star;
  9755.   nobj->paintfunc = d_paint_star;
  9756.   nobj->copyfunc  = d_copy_star;
  9757.  
  9758.   return (nobj);
  9759. }
  9760.  
  9761. static void
  9762. d_update_star (GdkPoint *pnt)
  9763. {
  9764.   DobjPoints *center_pnt, *inner_pnt, *outer_pnt;
  9765.   gint saved_cnt_pnt = selvals.opts.showcontrol;
  9766.  
  9767.   /* Undraw last one then draw new one */
  9768.   center_pnt = obj_creating->points;
  9769.   
  9770.   if (!center_pnt)
  9771.     return; /* No points */
  9772.  
  9773.   /* Leave the first pnt alone -
  9774.    * Edge point defines "radius"
  9775.    * Only undraw if already have edge point.
  9776.    */
  9777.  
  9778.   /* Hack - turn off cnt points in draw routine 
  9779.    * Looking back over the other update routines I could
  9780.    * use this trick again and cut down on code size!
  9781.    */
  9782.  
  9783.  
  9784.   if ((outer_pnt = center_pnt->next))
  9785.     {
  9786.       /* Undraw */
  9787.       inner_pnt = outer_pnt->next;
  9788.       draw_circle (&inner_pnt->pnt);
  9789.       draw_circle (&outer_pnt->pnt);
  9790.       selvals.opts.showcontrol = 0;
  9791.       d_draw_star (obj_creating);
  9792.       outer_pnt->pnt.x = pnt->x;
  9793.       outer_pnt->pnt.y = pnt->y;
  9794.       inner_pnt->pnt.x = pnt->x + (2*(center_pnt->pnt.x - pnt->x))/3;
  9795.       inner_pnt->pnt.y = pnt->y + (2*(center_pnt->pnt.y - pnt->y))/3;
  9796.     }
  9797.   else
  9798.     {
  9799.       /* Radius is a few pixels away */
  9800.       /* First edge point */
  9801.       d_pnt_add_line (obj_creating, pnt->x, pnt->y,-1);
  9802.       outer_pnt = center_pnt->next;
  9803.       /* Inner radius */
  9804.       d_pnt_add_line (obj_creating,
  9805.               pnt->x + (2*(center_pnt->pnt.x - pnt->x))/3,
  9806.               pnt->y + (2*(center_pnt->pnt.y - pnt->y))/3,
  9807.               -1);
  9808.       inner_pnt = outer_pnt->next;
  9809.     }
  9810.  
  9811.   /* draw it */
  9812.   selvals.opts.showcontrol = 0;
  9813.   d_draw_star (obj_creating);
  9814.   selvals.opts.showcontrol = saved_cnt_pnt;
  9815.  
  9816.   /* Realy draw the control points */
  9817.   draw_circle (&outer_pnt->pnt);
  9818.   draw_circle (&inner_pnt->pnt);
  9819. }
  9820.  
  9821. /* first point is center 
  9822.  * next defines the radius
  9823.  */
  9824.  
  9825. static void
  9826. d_star_start (GdkPoint *pnt,
  9827.           gint      shift_down)
  9828. {
  9829.   gint16 x, y;
  9830.   /* First is center point */
  9831.   obj_creating = d_new_star (x = pnt->x, y = pnt->y);
  9832.   obj_creating->type_data = (gpointer)star_num_sides;
  9833. }
  9834.  
  9835. static void
  9836. d_star_end (GdkPoint *pnt,
  9837.         gint      shift_down)
  9838. {
  9839.   draw_circle (pnt);
  9840.   add_to_all_obj (current_obj, obj_creating);
  9841.   obj_creating = NULL;
  9842. }
  9843.  
  9844.  
  9845. /* Spiral */
  9846.  
  9847. static void
  9848. d_save_spiral (Dobject *obj,
  9849.            FILE    *to)
  9850. {
  9851.   DobjPoints * spnt;
  9852.   
  9853.   spnt = obj->points;
  9854.  
  9855.   if (!spnt)
  9856.     return; /* End-of-line */
  9857.  
  9858.   fprintf (to, "<SPIRAL>\n");
  9859.  
  9860.   while (spnt)
  9861.     {
  9862.       fprintf (to, "%d %d\n",
  9863.            (gint)spnt->pnt.x,
  9864.            (gint)spnt->pnt.y);
  9865.       spnt = spnt->next;
  9866.     }
  9867.   
  9868.   fprintf (to, "<EXTRA>\n");
  9869.   fprintf (to, "%d\n</EXTRA>\n", (gint)obj->type_data);
  9870.   fprintf (to, "</SPIRAL>\n");
  9871.  
  9872. }
  9873.  
  9874. /* Load a spiral from the specified stream */
  9875.  
  9876. static Dobject *
  9877. d_load_spiral (FILE *from)
  9878. {
  9879.   Dobject *new_obj = NULL;
  9880.   gint xpnt;
  9881.   gint ypnt;
  9882.   gchar buf[MAX_LOAD_LINE];
  9883.  
  9884. #ifdef DEBUG
  9885.   printf ("Load spiral called\n");
  9886. #endif /* DEBUG */
  9887.  
  9888.   while (get_line (buf, MAX_LOAD_LINE, from, 0))
  9889.     {
  9890.       if (sscanf (buf, "%d %d", &xpnt, &ypnt) != 2)
  9891.     {
  9892.       /* Must be the end */
  9893.       if (!strcmp ("<EXTRA>", buf))
  9894.         {
  9895.           gint nsides = 3;
  9896.           /* Number of sides - data item */
  9897.           if (!new_obj)
  9898.         {
  9899.           g_warning ("[%d] Internal load error while loading spiral (extra area)",
  9900.                 line_no);
  9901.           return (NULL);
  9902.         }
  9903.           get_line (buf, MAX_LOAD_LINE, from, 0);
  9904.           if (sscanf (buf, "%d", &nsides) != 1)
  9905.         {
  9906.           g_warning ("[%d] Internal load error while loading spiral (extra area scanf)",
  9907.                 line_no);
  9908.           return (NULL);
  9909.         }
  9910.           new_obj->type_data = (gpointer)nsides;
  9911.           get_line (buf, MAX_LOAD_LINE, from, 0);
  9912.           if (strcmp ("</EXTRA>", buf))
  9913.         {
  9914.           g_warning ("[%d] Internal load error while loading spiral",
  9915.                 line_no);
  9916.           return (NULL);
  9917.         } 
  9918.           /* Go around and read the last line */
  9919.           continue;
  9920.         }
  9921.       else if (strcmp ("</SPIRAL>", buf))
  9922.         {
  9923.           g_warning ("[%d] Internal load error while loading spiral",
  9924.             line_no);
  9925.           return (NULL);
  9926.         }
  9927.       return (new_obj);
  9928.     }
  9929.       
  9930.       if (!new_obj)
  9931.     new_obj = d_new_spiral (xpnt, ypnt);
  9932.       else
  9933.     d_pnt_add_line (new_obj, xpnt, ypnt,-1);
  9934.     }
  9935.   return (new_obj);
  9936. }
  9937.  
  9938. static void
  9939. d_draw_spiral (Dobject *obj)
  9940. {
  9941.   DobjPoints * center_pnt;
  9942.   DobjPoints * radius_pnt;
  9943.   gint16 shift_x;
  9944.   gint16 shift_y;
  9945.   gdouble ang_grid;
  9946.   gdouble ang_loop;
  9947.   gdouble radius;
  9948.   gdouble offset_angle;
  9949.   gdouble sp_cons;
  9950.   gint loop;
  9951.   GdkPoint start_pnt;
  9952.   GdkPoint first_pnt;
  9953.   gint do_line = 0;
  9954.   gint clock_wise = 1;
  9955.  
  9956.   center_pnt = obj->points;
  9957.  
  9958.   if (!center_pnt)
  9959.     return; /* End-of-line */
  9960.  
  9961.   /* First point is the center */
  9962.   /* Just draw a control point around it */
  9963.  
  9964.   draw_sqr (¢er_pnt->pnt);
  9965.  
  9966.   /* Next point defines the radius */
  9967.   radius_pnt = center_pnt->next; /* this defines the vetices */
  9968.  
  9969.   if (!radius_pnt)
  9970.     {
  9971. #ifdef DEBUG
  9972.       g_warning ("Internal error in spiral - no vertice point \n");
  9973. #endif /* DEBUG */
  9974.       return;
  9975.     }
  9976.  
  9977.   /* Other control point */
  9978.   draw_sqr (&radius_pnt->pnt);
  9979.  
  9980.   /* Have center and radius - draw spiral */
  9981.  
  9982.   shift_x = radius_pnt->pnt.x - center_pnt->pnt.x;
  9983.   shift_y = radius_pnt->pnt.y - center_pnt->pnt.y;
  9984.  
  9985.   radius = sqrt ((shift_x*shift_x) + (shift_y*shift_y));
  9986.  
  9987.   offset_angle = atan2 (shift_y, shift_x);
  9988.  
  9989.   clock_wise = ((gint)obj->type_data)/(abs ((gint) (obj->type_data)));
  9990.  
  9991.   if (offset_angle < 0)
  9992.     offset_angle += 2*G_PI;
  9993.  
  9994.   sp_cons = radius/((gint)obj->type_data * 2 * G_PI + offset_angle);
  9995.   /* Lines */
  9996.   ang_grid = 2.0*G_PI/(gdouble)180;
  9997.  
  9998.  
  9999.   for (loop = 0 ; loop <= abs ((gint) (obj->type_data)*180) + clock_wise*(gint)RINT (offset_angle/ang_grid) ; loop++)
  10000.     {
  10001.       gdouble lx, ly;
  10002.       GdkPoint calc_pnt;
  10003.  
  10004.       ang_loop = (gdouble)loop * ang_grid;
  10005.     
  10006.       lx = sp_cons * ang_loop * cos (ang_loop)*clock_wise;
  10007.       ly = sp_cons * ang_loop * sin (ang_loop);
  10008.  
  10009.       calc_pnt.x = (gint)RINT (lx + center_pnt->pnt.x);
  10010.       calc_pnt.y = (gint)RINT (ly + center_pnt->pnt.y);
  10011.  
  10012.       if (do_line)
  10013.     {
  10014.  
  10015.       /* Miss out points that come to the same location */
  10016.       if (calc_pnt.x == start_pnt.x && calc_pnt.y == start_pnt.y)
  10017.         continue;
  10018.  
  10019.       if (drawing_pic)
  10020.         {
  10021.           gdk_draw_line (pic_preview->window,
  10022.                  pic_preview->style->black_gc,                
  10023.                  adjust_pic_coords (calc_pnt.x,
  10024.                         preview_width),
  10025.                  adjust_pic_coords (calc_pnt.y,
  10026.                         preview_height),
  10027.                  adjust_pic_coords (start_pnt.x,
  10028.                         preview_width),
  10029.                  adjust_pic_coords (start_pnt.y,
  10030.                         preview_height));
  10031.         }
  10032.       else
  10033.         {
  10034.           gdk_draw_line (gfig_preview->window,
  10035.                  gfig_gc,
  10036.                  gfig_scale_x (calc_pnt.x),
  10037.                  gfig_scale_y (calc_pnt.y),
  10038.                  gfig_scale_x (start_pnt.x),
  10039.                  gfig_scale_y (start_pnt.y));
  10040.         }
  10041.     }
  10042.       else
  10043.     {
  10044.       do_line = 1;
  10045.       first_pnt.x = calc_pnt.x;
  10046.       first_pnt.y = calc_pnt.y;
  10047.     }
  10048.       start_pnt.x = calc_pnt.x;
  10049.       start_pnt.y = calc_pnt.y;
  10050.     }
  10051. }
  10052.  
  10053. static void
  10054. d_paint_spiral (Dobject *obj)
  10055. {
  10056.   /* first point center */
  10057.   /* Next point is radius */
  10058.   gdouble *line_pnts;
  10059.   gint seg_count = 0;
  10060.   gint i = 0;
  10061.   DobjPoints * center_pnt;
  10062.   DobjPoints * radius_pnt;
  10063.   gint16 shift_x;
  10064.   gint16 shift_y;
  10065.   gdouble ang_grid;
  10066.   gdouble ang_loop;
  10067.   gdouble radius;
  10068.   gdouble offset_angle;
  10069.   gdouble sp_cons;
  10070.   gint loop;
  10071.   GdkPoint last_pnt;
  10072.   gint clock_wise = 1;
  10073.  
  10074.   g_assert (obj != NULL);
  10075.  
  10076.   center_pnt = obj->points;
  10077.  
  10078.   if (!center_pnt || !center_pnt->next)
  10079.     return; /* no-line */
  10080.  
  10081.   /* Go around all the points drawing a line from one to the next */
  10082.  
  10083.   radius_pnt = center_pnt->next; /* this defines the vetices */
  10084.  
  10085.   /* Have center and radius - get lines */
  10086.   shift_x = radius_pnt->pnt.x - center_pnt->pnt.x;
  10087.   shift_y = radius_pnt->pnt.y - center_pnt->pnt.y;
  10088.  
  10089.   radius = sqrt ((shift_x*shift_x) + (shift_y*shift_y));
  10090.  
  10091.   clock_wise = ((gint)obj->type_data)/(abs ((gint) (obj->type_data)));
  10092.  
  10093.   offset_angle = atan2 (shift_y, shift_x);
  10094.  
  10095.   if (offset_angle < 0)
  10096.     offset_angle += 2*G_PI;
  10097.  
  10098.   sp_cons = radius/((gint)obj->type_data * 2 * G_PI + offset_angle);
  10099.   /* Lines */
  10100.   ang_grid = 2.0*G_PI/(gdouble)180;
  10101.  
  10102.  
  10103.   /* count - */
  10104.   seg_count = abs ((gint) (obj->type_data)*180) + clock_wise*(gint)RINT (offset_angle/ang_grid);
  10105.  
  10106.   line_pnts = g_new0 (gdouble, 2 * seg_count + 3);
  10107.  
  10108.   for (loop = 0 ; loop <= seg_count; loop++)
  10109.     {
  10110.       gdouble lx, ly;
  10111.       GdkPoint calc_pnt;
  10112.  
  10113.       ang_loop = (gdouble)loop * ang_grid;
  10114.     
  10115.       lx = sp_cons * ang_loop * cos (ang_loop)*clock_wise;
  10116.       ly = sp_cons * ang_loop * sin (ang_loop);
  10117.  
  10118.       calc_pnt.x = (gint)RINT (lx + center_pnt->pnt.x);
  10119.       calc_pnt.y = (gint)RINT (ly + center_pnt->pnt.y);
  10120.  
  10121.       /* Miss out duped pnts */
  10122.       if (!loop)
  10123.     {
  10124.       if (calc_pnt.x == last_pnt.x && calc_pnt.y == last_pnt.y)
  10125.         {
  10126.           continue;
  10127.         }
  10128.     }
  10129.  
  10130.       last_pnt.x = line_pnts[i++] = calc_pnt.x;
  10131.       last_pnt.y = line_pnts[i++] = calc_pnt.y;
  10132.     }
  10133.  
  10134.   /* Reverse line if approp */
  10135.   if (selvals.reverselines)
  10136.     reverse_pairs_list (&line_pnts[0], i/2);
  10137.  
  10138.   /* Scale before drawing */
  10139.   if (selvals.scaletoimage)
  10140.     scale_to_original_xy (&line_pnts[0], i/2);
  10141.   else
  10142.     scale_to_xy (&line_pnts[0], i/2);
  10143.  
  10144.   /* One go */
  10145.   if (selvals.painttype == PAINT_BRUSH_TYPE)
  10146.     {
  10147.       gfig_paint (selvals.brshtype,
  10148.           gfig_drawable,
  10149.           i, line_pnts);
  10150.     }
  10151.   else
  10152.     {
  10153.       gimp_free_select (gfig_image,
  10154.             i, line_pnts,
  10155.             selopt.type,
  10156.             selopt.antia,
  10157.             selopt.feather,
  10158.             selopt.feather_radius);
  10159.     }
  10160.  
  10161.   g_free (line_pnts);
  10162. }
  10163.  
  10164. static Dobject *
  10165. d_copy_spiral (Dobject * obj)
  10166. {
  10167.   Dobject *np;
  10168.  
  10169. #if DEBUG
  10170.   printf ("Copy spiral\n");
  10171. #endif /*DEBUG*/
  10172.   if (!obj)
  10173.     return (NULL);
  10174.  
  10175.   g_assert (obj->type == SPIRAL);
  10176.  
  10177.   np = d_new_spiral (obj->points->pnt.x, obj->points->pnt.y);
  10178.  
  10179.   np->points->next = d_copy_dobjpoints (obj->points->next);
  10180.  
  10181.   np->type_data = obj->type_data;
  10182.  
  10183. #if DEBUG
  10184.   printf ("Done spiral copy\n");
  10185. #endif /*DEBUG*/
  10186.   return (np);
  10187. }
  10188.  
  10189. static Dobject *
  10190. d_new_spiral (gint x,
  10191.           gint y)
  10192. {
  10193.   Dobject *nobj;
  10194.   DobjPoints *npnt;
  10195.  
  10196.   /* Get new object and starting point */
  10197.  
  10198.   /* Start point */
  10199.   npnt = g_new0 (DobjPoints, 1);
  10200.  
  10201. #if DEBUG
  10202.   printf ("New SPIRAL start at (%x,%x)\n", x, y);
  10203. #endif /* DEBUG */
  10204.   npnt->pnt.x = x;
  10205.   npnt->pnt.y = y;
  10206.  
  10207.   nobj = g_new0 (Dobject, 1);
  10208.  
  10209.   nobj->type = SPIRAL;
  10210.   nobj->type_data = (gpointer)4; /* Default to four turns */
  10211.   nobj->points = npnt;
  10212.   nobj->drawfunc  = d_draw_spiral;
  10213.   nobj->loadfunc  = d_load_spiral;
  10214.   nobj->savefunc  = d_save_spiral;
  10215.   nobj->paintfunc = d_paint_spiral;
  10216.   nobj->copyfunc  = d_copy_spiral;
  10217.  
  10218.   return (nobj);
  10219. }
  10220.  
  10221. static void
  10222. d_update_spiral (GdkPoint *pnt)
  10223. {
  10224.   DobjPoints *center_pnt, *edge_pnt;
  10225.   gint saved_cnt_pnt = selvals.opts.showcontrol;
  10226.  
  10227.   /* Undraw last one then draw new one */
  10228.   center_pnt = obj_creating->points;
  10229.   
  10230.   if (!center_pnt)
  10231.     return; /* No points */
  10232.  
  10233.   /* Leave the first pnt alone -
  10234.    * Edge point defines "radius"
  10235.    * Only undraw if already have edge point.
  10236.    */
  10237.  
  10238.   /* Hack - turn off cnt points in draw routine 
  10239.    * Looking back over the other update routines I could
  10240.    * use this trick again and cut down on code size!
  10241.    */
  10242.  
  10243.   if ((edge_pnt = center_pnt->next))
  10244.     {
  10245.       /* Undraw */
  10246.       draw_circle (&edge_pnt->pnt);
  10247.       selvals.opts.showcontrol = 0;
  10248.       d_draw_spiral (obj_creating);
  10249.  
  10250.       edge_pnt->pnt.x = pnt->x;
  10251.       edge_pnt->pnt.y = pnt->y;
  10252.     }
  10253.   else
  10254.     {
  10255.       /* Radius is a few pixels away */
  10256.       /* First edge point */
  10257.       d_pnt_add_line (obj_creating, pnt->x, pnt->y, -1);
  10258.       edge_pnt = center_pnt->next;
  10259.     }
  10260.  
  10261.   /* draw it */
  10262.   selvals.opts.showcontrol = 0;
  10263.   d_draw_spiral (obj_creating);
  10264.   selvals.opts.showcontrol = saved_cnt_pnt;
  10265.  
  10266.   /* Realy draw the control points */
  10267.   draw_circle (&edge_pnt->pnt);
  10268. }
  10269.  
  10270. /* first point is center 
  10271.  * next defines the radius
  10272.  */
  10273.  
  10274. static void
  10275. d_spiral_start (GdkPoint *pnt,
  10276.         gint      shift_down)
  10277. {
  10278.   gint16 x, y;
  10279.   /* First is center point */
  10280.   obj_creating = d_new_spiral (x = pnt->x, y = pnt->y);
  10281.   obj_creating->type_data =
  10282.     (gpointer) (spiral_num_turns * ((spiral_toggle == 0) ? 1 : -1));
  10283. }
  10284.  
  10285. static void
  10286. d_spiral_end (GdkPoint *pnt,
  10287.           gint     shift_down)
  10288. {
  10289.   draw_circle (pnt);
  10290.   add_to_all_obj (current_obj, obj_creating);
  10291.   obj_creating = NULL;
  10292. }
  10293.  
  10294. /* Stuff for bezier curves... */
  10295.  
  10296. static void
  10297. d_save_bezier (Dobject *obj,
  10298.            FILE    *to)
  10299. {
  10300.   DobjPoints *spnt;
  10301.  
  10302.   spnt = obj->points;
  10303.  
  10304.   if (!spnt)
  10305.     return; /* End-of-line */
  10306.  
  10307.   fprintf (to, "<BEZIER>\n");
  10308.  
  10309.   while (spnt)
  10310.     {
  10311.       fprintf (to, "%d %d\n",
  10312.            (gint)spnt->pnt.x,
  10313.            (gint)spnt->pnt.y);
  10314.       spnt = spnt->next;
  10315.     }
  10316.   
  10317.   fprintf (to, "<EXTRA>\n");
  10318.   fprintf (to, "%d\n</EXTRA>\n", (gint) obj->type_data);
  10319.   fprintf (to, "</BEZIER>\n");
  10320. }
  10321.  
  10322. /* Load a bezier from the specified stream */
  10323.  
  10324. static Dobject *
  10325. d_load_bezier (FILE *from)
  10326. {
  10327.   Dobject *new_obj = NULL;
  10328.   gint xpnt;
  10329.   gint ypnt;
  10330.   gchar buf[MAX_LOAD_LINE];
  10331.  
  10332. #ifdef DEBUG
  10333.   printf ("Load bezier called\n");
  10334. #endif /* DEBUG */
  10335.  
  10336.   while (get_line (buf, MAX_LOAD_LINE, from, 0))
  10337.     {
  10338.       if (sscanf (buf, "%d %d", &xpnt, &ypnt) != 2)
  10339.     {
  10340.       /* Must be the end */
  10341.       if (!strcmp ("<EXTRA>", buf))
  10342.         {
  10343.           gint nsides = 3;
  10344.           /* Number of sides - data item */
  10345.           if ( !new_obj)
  10346.         {
  10347.           g_message ("[%d] Internal load error while loading bezier "
  10348.                  "(extra area)", line_no);
  10349.           return NULL;
  10350.         }
  10351.           get_line (buf, MAX_LOAD_LINE, from, 0);
  10352.           if (sscanf (buf, "%d", &nsides) != 1)
  10353.         {
  10354.           g_message ("[%d] Internal load error while loading bezier "
  10355.                  "(extra area scanf)", line_no);
  10356.           return NULL;
  10357.         }
  10358.           new_obj->type_data = (gpointer) nsides;
  10359.           get_line (buf, MAX_LOAD_LINE, from, 0);
  10360.           if (strcmp ("</EXTRA>", buf))
  10361.         {
  10362.           g_message ("[%d] Internal load error while loading bezier",
  10363.                  line_no);
  10364.           return NULL;
  10365.         } 
  10366.           /* Go around and read the last line */
  10367.           continue;
  10368.         }
  10369.       else if (strcmp ("</BEZIER>", buf))
  10370.         {
  10371.           g_message ("[%d] Internal load error while loading bezier",
  10372.              line_no);
  10373.           return NULL;
  10374.         }
  10375.       return new_obj;
  10376.     }
  10377.       
  10378.       if (!new_obj)
  10379.     new_obj = d_new_bezier (xpnt, ypnt);
  10380.       else
  10381.     d_pnt_add_line (new_obj, xpnt, ypnt, -1);
  10382.     }
  10383.  
  10384.   return new_obj;
  10385. }
  10386.  
  10387.  
  10388. #define FP_PNT_MAX  10
  10389.  
  10390. static int fp_pnt_cnt = 0;
  10391. static int fp_pnt_chunk = 0;
  10392. static gdouble *fp_pnt_pnts = NULL;
  10393.  
  10394. static void
  10395. fp_pnt_start (void)
  10396. {
  10397.   fp_pnt_cnt = 0;
  10398. }
  10399.  
  10400. /* Add a line segment to collection array */
  10401. static void
  10402. fp_pnt_add (gdouble p1,
  10403.         gdouble p2,
  10404.         gdouble p3,
  10405.         gdouble p4)
  10406. {
  10407.   if (!fp_pnt_pnts)
  10408.     {
  10409.       fp_pnt_pnts = g_new0 (gdouble, FP_PNT_MAX);
  10410.       fp_pnt_chunk = 1;
  10411.     }
  10412.  
  10413.   if (((fp_pnt_cnt + 4) / FP_PNT_MAX) >= fp_pnt_chunk)
  10414.     {
  10415.       /* more space pls */
  10416.       fp_pnt_chunk++;
  10417.       fp_pnt_pnts =
  10418.     (gdouble *) g_realloc (fp_pnt_pnts,
  10419.                    sizeof (gdouble) * fp_pnt_chunk * FP_PNT_MAX);
  10420.     }
  10421.  
  10422.   fp_pnt_pnts[fp_pnt_cnt++] = p1;
  10423.   fp_pnt_pnts[fp_pnt_cnt++] = p2;
  10424.   fp_pnt_pnts[fp_pnt_cnt++] = p3;
  10425.   fp_pnt_pnts[fp_pnt_cnt++] = p4;
  10426. }
  10427.  
  10428. static gdouble *
  10429. d_bz_get_array (gint *sz)
  10430. {
  10431.   *sz = fp_pnt_cnt;
  10432.   return fp_pnt_pnts;
  10433. }
  10434.  
  10435.  
  10436. static void
  10437. d_bz_line (void)
  10438. {
  10439.   gint i, x0, y0, x1, y1; 
  10440.  
  10441.   g_assert ((fp_pnt_cnt % 4) == 0);
  10442.  
  10443.   for (i = 0 ; i < fp_pnt_cnt; i += 4)
  10444.     {
  10445.       x0 = (gint) fp_pnt_pnts[i];
  10446.       y0 = (gint) fp_pnt_pnts[i + 1];
  10447.       x1 = (gint) fp_pnt_pnts[i + 2];
  10448.       y1 = (gint) fp_pnt_pnts[i + 3];
  10449.  
  10450.       if (drawing_pic)
  10451.     {
  10452.       gdk_draw_line (pic_preview->window,
  10453.              pic_preview->style->black_gc,
  10454.              adjust_pic_coords ((gint) x0,
  10455.                         preview_width),
  10456.              adjust_pic_coords ((gint) y0,
  10457.                         preview_height),
  10458.              adjust_pic_coords ((gint) x1,
  10459.                         preview_width),
  10460.              adjust_pic_coords ((gint) y1,
  10461.                         preview_height));
  10462.     }
  10463.       else
  10464.     {
  10465.       gdk_draw_line (gfig_preview->window,
  10466.              gfig_gc,
  10467.              gfig_scale_x ((gint) x0),
  10468.              gfig_scale_y ((gint) y0),
  10469.              gfig_scale_x ((gint) x1),
  10470.              gfig_scale_y ((gint) y1));
  10471.     }
  10472.     }
  10473. }
  10474.  
  10475. /*  Return points to plot */
  10476. /* Terminate by point with DBL_MAX, DBL_MAX */
  10477. typedef gdouble (*fp_pnt)[2];
  10478.  
  10479. static void
  10480. DrawBezier (gdouble (*points)[2],
  10481.         gint      np,
  10482.         gdouble   mid,
  10483.         gint      depth)
  10484. {
  10485.   gint i, j, x0 = 0, y0 = 0, x1, y1; 
  10486.   fp_pnt left;
  10487.   fp_pnt right;
  10488.   
  10489.     if (depth == 0) /* draw polyline */
  10490.       {
  10491.     for (i = 0; i < np; i++)
  10492.       {
  10493.         x1 = (int) points[i][0];
  10494.         y1 = (int) points[i][1];
  10495.         if (i > 0 && (x1 != x0 || y1 != y0))
  10496.           {
  10497.         /* Add pnts up */
  10498.         fp_pnt_add ((gdouble) x0, (gdouble) y0,
  10499.                 (gdouble) x1, (gdouble) y1);
  10500.           }
  10501.         x0 = x1;
  10502.         y0 = y1;
  10503.       }
  10504.       }
  10505.     else /* subdivide control points at mid */
  10506.       {
  10507.     left = (fp_pnt) g_new (gdouble, np * 2);
  10508.     right = (fp_pnt) g_new (gdouble, np * 2);
  10509.     for (i = 0; i < np; i++)
  10510.       {
  10511.         right[i][0] = points[i][0];
  10512.         right[i][1] = points[i][1];
  10513.       } 
  10514.     left[0][0] = right[0][0];
  10515.     left[0][1] = right[0][1];
  10516.     for (j = np - 1; j >= 1; j--)
  10517.       {
  10518.         for (i = 0; i < j; i++)
  10519.           {
  10520.         right[i][0] = (1 - mid) * right[i][0] + mid * right[i + 1][0];
  10521.         right[i][1] = (1 - mid) * right[i][1] + mid * right[i + 1][1];
  10522.           }
  10523.         left[np - j][0] = right[0][0];
  10524.         left[np - j][1] = right[0][1];
  10525.       }
  10526.     if (depth > 0)
  10527.       {
  10528.         DrawBezier (left, np, mid, depth - 1);
  10529.         DrawBezier (right, np, mid, depth - 1);
  10530.         g_free (left);
  10531.         g_free (right);
  10532.       }
  10533.       }
  10534. }
  10535.  
  10536.  
  10537. static void
  10538. d_draw_bezier (Dobject *obj)
  10539. {
  10540.   DobjPoints * spnt;
  10541.   gint seg_count = 0;
  10542.   gint i = 0;
  10543.   gdouble (*line_pnts)[2];
  10544.  
  10545.   spnt = obj->points;
  10546.  
  10547.   /* First count the number of points */
  10548.  
  10549.   /* count */
  10550.   while (spnt)
  10551.     {
  10552.       seg_count++;
  10553.       spnt = spnt->next;
  10554.     }
  10555.  
  10556.   spnt = obj->points;
  10557.  
  10558.   if (!spnt || !seg_count)
  10559.     return; /* no-line */
  10560.  
  10561.   line_pnts = (fp_pnt) g_new0 (gdouble, 2 * seg_count + 1);
  10562.  
  10563.   /* Go around all the points drawing a line from one to the next */
  10564.   while (spnt)
  10565.     {
  10566.       draw_sqr (&spnt->pnt);
  10567.       line_pnts[i][0] = spnt->pnt.x;
  10568.       line_pnts[i++][1] = spnt->pnt.y;
  10569.       spnt = spnt->next;
  10570.     }
  10571.  
  10572.   /* Generate an array of doubles which are the control points */
  10573.  
  10574.   if (!drawing_pic && bezier_line_frame && tmp_bezier)
  10575.     {
  10576.       fp_pnt_start ();
  10577.       DrawBezier (line_pnts, seg_count, 0.5, 0);
  10578.       d_bz_line ();
  10579.     }
  10580.  
  10581.   fp_pnt_start ();
  10582.   DrawBezier (line_pnts, seg_count, 0.5, 3);
  10583.   d_bz_line ();
  10584.   /*bezier4 (line_pnts, seg_count, 20);*/
  10585.  
  10586.   g_free (line_pnts);
  10587. }
  10588.  
  10589. static void
  10590. d_paint_bezier (Dobject *obj)
  10591. {
  10592.   gdouble *line_pnts;
  10593.   gdouble (*bz_line_pnts)[2];
  10594.   DobjPoints *spnt;
  10595.   gint seg_count = 0;
  10596.  
  10597.   gint i = 0;
  10598.  
  10599.   spnt = obj->points;
  10600.  
  10601.   /* First count the number of points */
  10602.  
  10603.   /* count */
  10604.   while (spnt)
  10605.     {
  10606.       seg_count++;
  10607.       spnt = spnt->next;
  10608.     }
  10609.  
  10610.   spnt = obj->points;
  10611.  
  10612.   if (!spnt || !seg_count)
  10613.     return; /* no-line */
  10614.  
  10615.   bz_line_pnts = (fp_pnt) g_new0 (gdouble, 2 * seg_count + 1);
  10616.  
  10617.   /* Go around all the points drawing a line from one to the next */
  10618.   while (spnt)
  10619.     {
  10620.       bz_line_pnts[i][0] = spnt->pnt.x;
  10621.       bz_line_pnts[i++][1] = spnt->pnt.y;
  10622.       spnt = spnt->next;
  10623.     }
  10624.  
  10625.   fp_pnt_start ();
  10626.   DrawBezier (bz_line_pnts, seg_count, 0.5, 5);
  10627.   line_pnts = d_bz_get_array (&i);
  10628.  
  10629.   /* Reverse line if approp */
  10630.   if (selvals.reverselines)
  10631.     reverse_pairs_list (&line_pnts[0], i / 2);
  10632.  
  10633.   /* Scale before drawing */
  10634.   if (selvals.scaletoimage)
  10635.     scale_to_original_xy (&line_pnts[0], i / 2);
  10636.   else
  10637.     scale_to_xy (&line_pnts[0], i / 2);
  10638.  
  10639.   /* One go */
  10640.   if (selvals.painttype == PAINT_BRUSH_TYPE)
  10641.     {
  10642.       gfig_paint (selvals.brshtype,
  10643.           gfig_drawable,
  10644.           i, line_pnts);
  10645.     }
  10646.   else
  10647.     {
  10648.       gimp_free_select (gfig_image,
  10649.             i, line_pnts,
  10650.             selopt.type,
  10651.             selopt.antia,
  10652.             selopt.feather,
  10653.             selopt.feather_radius);
  10654.     }
  10655.  
  10656.   g_free (bz_line_pnts);
  10657.   /* Don't free line_pnts - may need again */
  10658. }
  10659.  
  10660. static Dobject *
  10661. d_copy_bezier (Dobject * obj)
  10662. {
  10663.   Dobject *np;
  10664.  
  10665. #if DEBUG
  10666.   printf ("Copy bezier\n");
  10667. #endif /*DEBUG*/
  10668.   if (!obj)
  10669.     return (NULL);
  10670.  
  10671.   g_assert (obj->type == BEZIER);
  10672.  
  10673.   np = d_new_bezier (obj->points->pnt.x, obj->points->pnt.y);
  10674.  
  10675.   np->points->next = d_copy_dobjpoints (obj->points->next);
  10676.  
  10677.   np->type_data = obj->type_data;
  10678.  
  10679. #if DEBUG
  10680.   printf ("Done bezier copy\n");
  10681. #endif /*DEBUG*/
  10682.   return np;
  10683. }
  10684.  
  10685. static Dobject *
  10686. d_new_bezier (gint x, gint y)
  10687. {
  10688.   Dobject *nobj;
  10689.   DobjPoints *npnt;
  10690.  
  10691.   /* Get new object and starting point */
  10692.  
  10693.   /* Start point */
  10694.   npnt = g_new0 (DobjPoints, 1);
  10695.  
  10696. #if DEBUG
  10697.   printf ("New BEZIER start at (%x,%x)\n", x, y);
  10698. #endif /* DEBUG */
  10699.   npnt->pnt.x = x;
  10700.   npnt->pnt.y = y;
  10701.  
  10702.   nobj = g_new0 (Dobject, 1);
  10703.  
  10704.   nobj->type = BEZIER;
  10705.   nobj->type_data = (gpointer)4; /* Default to four turns */
  10706.   nobj->points = npnt;
  10707.   nobj->drawfunc  = d_draw_bezier;
  10708.   nobj->loadfunc  = d_load_bezier;
  10709.   nobj->savefunc  = d_save_bezier;
  10710.   nobj->paintfunc = d_paint_bezier;
  10711.   nobj->copyfunc  = d_copy_bezier;
  10712.  
  10713.   return (nobj);
  10714. }
  10715.  
  10716. static void
  10717. d_update_bezier (GdkPoint *pnt)
  10718. {
  10719.   DobjPoints *s_pnt, *l_pnt;
  10720.   gint saved_cnt_pnt = selvals.opts.showcontrol;
  10721.  
  10722.   g_assert (tmp_bezier != NULL);
  10723.  
  10724.   /* Undraw last one then draw new one */
  10725.   s_pnt = tmp_bezier->points;
  10726.   
  10727.   if (!s_pnt)
  10728.     return; /* No points */
  10729.  
  10730.   /* Hack - turn off cnt points in draw routine 
  10731.    */
  10732.  
  10733.   if ((l_pnt = s_pnt->next))
  10734.     {
  10735.       /* Undraw */
  10736.       while (l_pnt->next)
  10737.     {
  10738.       l_pnt = l_pnt->next;
  10739.     }
  10740.  
  10741.       draw_circle (&l_pnt->pnt);
  10742.       selvals.opts.showcontrol = 0;
  10743.       d_draw_bezier (tmp_bezier);
  10744.       l_pnt->pnt.x = pnt->x;
  10745.       l_pnt->pnt.y = pnt->y;
  10746.     }
  10747.   else
  10748.     {
  10749.       /* Radius is a few pixels away */
  10750.       /* First edge point */
  10751.       d_pnt_add_line (tmp_bezier, pnt->x, pnt->y,-1);
  10752.       l_pnt = s_pnt->next;
  10753.     }
  10754.  
  10755.   /* draw it */
  10756.   selvals.opts.showcontrol = 0;
  10757.   d_draw_bezier (tmp_bezier);
  10758.   selvals.opts.showcontrol = saved_cnt_pnt;
  10759.  
  10760.   /* Realy draw the control points */
  10761.   draw_circle (&l_pnt->pnt);
  10762. }
  10763.  
  10764. /* first point is center 
  10765.  * next defines the radius
  10766.  */
  10767.  
  10768. static void
  10769. d_bezier_start (GdkPoint *pnt, gint shift_down)
  10770. {
  10771.   gint16 x, y;
  10772.   /* First is center point */
  10773.   if (!tmp_bezier)
  10774.     {
  10775.       /* New curve */
  10776.       tmp_bezier = obj_creating = d_new_bezier (x = pnt->x, y = pnt->y);
  10777.     }
  10778. }
  10779.  
  10780. static void
  10781. d_bezier_end (GdkPoint *pnt, gint shift_down)
  10782. {
  10783.   DobjPoints *l_pnt;
  10784.  
  10785.   if (!tmp_bezier)
  10786.     {
  10787.       tmp_bezier = obj_creating;
  10788.     }
  10789.   
  10790.   l_pnt = tmp_bezier->points->next;
  10791.  
  10792.   if (!l_pnt) 
  10793.     return;
  10794.  
  10795.   if (shift_down)
  10796.     {
  10797.       /* Undraw circle on last pnt */
  10798.       while (l_pnt->next)
  10799.     {
  10800.       l_pnt = l_pnt->next;
  10801.     }
  10802.  
  10803.       if (l_pnt)
  10804.     {
  10805.       draw_circle (&l_pnt->pnt);
  10806.       draw_sqr (&l_pnt->pnt);
  10807.  
  10808.       if (bezier_closed)
  10809.         {
  10810.           gint tmp_frame = bezier_line_frame;
  10811.           /* if closed then add first point */
  10812.           d_draw_bezier (tmp_bezier);
  10813.           d_pnt_add_line (tmp_bezier,
  10814.                  tmp_bezier->points->pnt.x,
  10815.                  tmp_bezier->points->pnt.y,-1);
  10816.           /* Final has no frame */
  10817.           bezier_line_frame = 0; /* False */
  10818.           d_draw_bezier (tmp_bezier);
  10819.           bezier_line_frame = tmp_frame; /* What is was */
  10820.         }
  10821.       else if (bezier_line_frame)
  10822.         {
  10823.           d_draw_bezier (tmp_bezier);
  10824.           bezier_line_frame = 0; /* False */
  10825.           d_draw_bezier (tmp_bezier);
  10826.           bezier_line_frame = 1; /* What is was */
  10827.         }
  10828.  
  10829.       add_to_all_obj (current_obj, obj_creating);
  10830.     }
  10831.  
  10832.       /* small mem leak if !l_pnt ? */
  10833.       tmp_bezier = NULL;
  10834.       obj_creating = NULL;
  10835.     }
  10836.   else
  10837.     {
  10838.       if (!tmp_bezier->points->next)
  10839.     {
  10840.       draw_circle (&tmp_bezier->points->pnt);
  10841.       draw_sqr (&tmp_bezier->points->pnt);
  10842.     }
  10843.  
  10844.       d_draw_bezier (tmp_bezier);
  10845.       d_pnt_add_line (tmp_bezier, pnt->x, pnt->y,-1);
  10846.       d_draw_bezier (tmp_bezier);
  10847.     }
  10848. }
  10849.  
  10850.  
  10851. /* copy objs */
  10852. static DAllObjs *
  10853. copy_all_objs (DAllObjs *objs)
  10854. {
  10855.   DAllObjs *nobj;
  10856.   DAllObjs *new_all_objs = NULL;
  10857.   DAllObjs *ret = NULL;
  10858.  
  10859.   while (objs)
  10860.     {
  10861.       nobj = g_new0 (DAllObjs, 1);
  10862.  
  10863.      if (!ret)
  10864.     {
  10865.       ret = new_all_objs = nobj;
  10866.     }
  10867.       else
  10868.     {
  10869.       new_all_objs->next = nobj;
  10870.       new_all_objs = nobj;
  10871.     }
  10872.  
  10873.       nobj->obj = (Dobject *) objs->obj->copyfunc (objs->obj);
  10874.  
  10875.       objs = objs->next;
  10876.     }
  10877.  
  10878.   return ret;
  10879. }
  10880.  
  10881. /* Screen refresh */
  10882. static void
  10883. draw_one_obj (Dobject * obj)
  10884. {
  10885.   obj->drawfunc (obj);
  10886. }
  10887.  
  10888. static void
  10889. draw_objects (DAllObjs *objs,
  10890.           gint      show_single)
  10891. {
  10892.   /* Show_single - only one object to draw Unless shift 
  10893.    * is down in whcih case show all.
  10894.    */
  10895.  
  10896.   gint count = 0;
  10897.  
  10898.   while (objs)
  10899.     {
  10900.       if (!show_single || count == obj_show_single || obj_show_single == -1)
  10901.     draw_one_obj (objs->obj);
  10902.       objs = objs->next;
  10903.       count++;
  10904.     }
  10905. }
  10906.  
  10907. static void
  10908. prepend_to_all_obj (GFigObj  *fobj,
  10909.             DAllObjs *nobj)
  10910. {
  10911.   DAllObjs *cobj;
  10912.  
  10913.   setup_undo (); /* Remember ME */
  10914.  
  10915.   if (!fobj->obj_list)
  10916.     {
  10917.       fobj->obj_list = nobj;
  10918.       return;
  10919.     }
  10920.  
  10921.   cobj = fobj->obj_list;
  10922.  
  10923.   while (cobj->next)
  10924.     {
  10925.       cobj = cobj->next;
  10926.     }
  10927.  
  10928.   cobj->next = nobj;
  10929. }
  10930.  
  10931. static void
  10932. add_to_all_obj (GFigObj *fobj,
  10933.         Dobject *obj)
  10934. {
  10935.   DAllObjs *nobj;
  10936.   
  10937.   nobj = g_new0 (DAllObjs, 1);
  10938.  
  10939.   nobj->obj = obj;
  10940.  
  10941.   if (need_to_scale)
  10942.     scale_obj_points (obj->points, scale_x_factor, scale_y_factor);
  10943.  
  10944.   prepend_to_all_obj (fobj, nobj);
  10945. }
  10946.  
  10947. static void
  10948. object_operation_start (GdkPoint *pnt,
  10949.             gint      shift_down)
  10950. {
  10951.   Dobject *new_obj;
  10952.  
  10953.   /* Find point in given object list */
  10954.   operation_obj = get_nearest_objs (current_obj, pnt);
  10955.  
  10956.   /* Special case if shift down && move obj then moving all objs */
  10957.  
  10958.   if (shift_down && selvals.otype == MOVE_OBJ)
  10959.     {
  10960.       move_all_pnt = g_malloc0 (sizeof (*move_all_pnt));
  10961.       *move_all_pnt = *pnt; /* Structure copy */
  10962.       setup_undo ();
  10963.       return;
  10964.     }
  10965.  
  10966.   if (!operation_obj)
  10967.     return;/* None to work on */
  10968.  
  10969.   setup_undo ();
  10970.  
  10971.   switch (selvals.otype)
  10972.     {
  10973.     case MOVE_OBJ:
  10974.       if (operation_obj->type == BEZIER)
  10975.     {
  10976.       d_draw_bezier (operation_obj);
  10977.       tmp_bezier = operation_obj;
  10978.       d_draw_bezier (operation_obj);
  10979.     }
  10980.       break;
  10981.     case MOVE_POINT:
  10982.       if (operation_obj->type == BEZIER)
  10983.     {
  10984.       d_draw_bezier (operation_obj);
  10985.       tmp_bezier = operation_obj;
  10986.       d_draw_bezier (operation_obj);
  10987.     }
  10988.       /* If shift is down the break into sep lines */
  10989.       if ((operation_obj->type == POLY  
  10990.       || operation_obj->type == STAR)
  10991.      && shift_down)
  10992.     {
  10993.       switch (operation_obj->type)
  10994.         {
  10995.         case POLY:
  10996.           d_poly2lines (operation_obj);
  10997.           break;
  10998.         case STAR:
  10999.           d_star2lines (operation_obj);
  11000.           break;
  11001.         default:
  11002.           break;
  11003.         }
  11004.       /* Re calc which object point we are lookin at */
  11005.       scan_obj_points (operation_obj->points, pnt);
  11006.     }
  11007.       break;
  11008.     case COPY_OBJ:
  11009.       /* Copy the "operation object" */
  11010.       /* Then bung us into "copy/move" mode */
  11011. #ifdef DEBUG
  11012.       printf ("In copy obj\n");
  11013. #endif /* DEBUG */
  11014.       new_obj = (Dobject *) operation_obj->copyfunc (operation_obj);
  11015.       if (new_obj)
  11016.     {
  11017.       scan_obj_points (new_obj->points, pnt);
  11018.       add_to_all_obj (current_obj, new_obj);
  11019.       operation_obj = new_obj;
  11020.       selvals.otype = MOVE_COPY_OBJ;
  11021.       new_obj->drawfunc (new_obj);
  11022.     }
  11023.       break;
  11024.     case DEL_OBJ:
  11025.       remove_obj_from_list (current_obj, operation_obj);
  11026.       break;
  11027.     case MOVE_COPY_OBJ: /* Never when button down */
  11028.     default:
  11029.       g_warning ("Internal error selvals.otype object operation start");
  11030.       break;
  11031.     }
  11032. }
  11033.  
  11034. static void
  11035. object_operation_end (GdkPoint *pnt,
  11036.               gint      shift_down)
  11037. {
  11038.   if (selvals.otype != DEL_OBJ && operation_obj && operation_obj->type == BEZIER)
  11039.     {
  11040.       d_draw_bezier (operation_obj);
  11041.       tmp_bezier = NULL; /* use as switch */
  11042.       d_draw_bezier (operation_obj);
  11043.     }
  11044.  
  11045.   operation_obj = NULL;
  11046.  
  11047.   if (move_all_pnt)
  11048.     {
  11049.       g_free (move_all_pnt);
  11050.       move_all_pnt = 0;
  11051.     }
  11052.  
  11053.   /* Special case - if copying mode MUST be copy when button up received */
  11054.   if (selvals.otype == MOVE_COPY_OBJ)
  11055.     selvals.otype = COPY_OBJ;
  11056. }
  11057.  
  11058. /* Move object around */
  11059. static void
  11060. object_operation (GdkPoint *to_pnt,
  11061.           gint      shift_down)
  11062. {
  11063.   /* Must do diffent things depending on object type */
  11064.   /* but must have object to operate on! */
  11065.  
  11066.   /* Special case - if shift own and move_obj then move ALL objects */
  11067.   if (move_all_pnt && shift_down && selvals.otype == MOVE_OBJ)
  11068.     {
  11069.       do_move_all_obj (to_pnt);
  11070.       return;
  11071.     }
  11072.  
  11073.   if (!operation_obj)
  11074.     return;
  11075.  
  11076.   switch (selvals.otype)
  11077.     {
  11078.     case MOVE_OBJ:
  11079.     case MOVE_COPY_OBJ:
  11080.       switch (operation_obj->type)
  11081.     {
  11082.     case LINE:
  11083.     case CIRCLE:
  11084.     case ELLIPSE:
  11085.     case POLY:
  11086.     case ARC:
  11087.     case STAR:
  11088.     case SPIRAL:
  11089.     case BEZIER:
  11090.       do_move_obj (operation_obj, to_pnt);
  11091.       break;
  11092.     default:
  11093.       /* Internal error */
  11094.       g_warning ("Internal error in operation_obj->type");
  11095.       break;
  11096.     }
  11097.       break;
  11098.     case MOVE_POINT:
  11099.       switch (operation_obj->type)
  11100.     {
  11101.     case LINE:
  11102.     case CIRCLE:
  11103.     case ELLIPSE:
  11104.     case POLY:
  11105.     case ARC:
  11106.     case STAR:
  11107.     case SPIRAL:
  11108.     case BEZIER:
  11109.       do_move_obj_pnt (operation_obj, to_pnt);
  11110.       break;
  11111.     default:
  11112.       /* Internal error */
  11113.       g_warning ("Internal error in operation_obj->type");
  11114.       break;
  11115.     }
  11116.       break;
  11117.     case DEL_OBJ:
  11118.       break;
  11119.     case COPY_OBJ: /* Should have been changed to MOVE_COPY_OBJ */
  11120.     default:
  11121.       g_warning ("Internal error selvals.otype");
  11122.       break;
  11123.     }
  11124. }
  11125.  
  11126. /* First button press -- start drawing object */
  11127. static void
  11128. object_start (GdkPoint *pnt,
  11129.           gint      shift_down)
  11130. {
  11131.   /* start for the current object */
  11132.   if (!selvals.scaletoimage)
  11133.     {
  11134.       need_to_scale = 1;
  11135.       selvals.scaletoimage = 1;
  11136.     }
  11137.   else
  11138.     {
  11139.       need_to_scale = 0;
  11140.     }
  11141.  
  11142.   switch (selvals.otype)
  11143.     {
  11144.     case LINE:
  11145.       /* Shift means we are still drawing */
  11146.       if (!shift_down || !obj_creating)
  11147.     draw_sqr (pnt);
  11148.       d_line_start (pnt, shift_down);
  11149.       break;
  11150.     case CIRCLE:
  11151.       draw_sqr (pnt);
  11152.       d_circle_start (pnt, shift_down);
  11153.       break;
  11154.     case ELLIPSE:
  11155.       draw_sqr (pnt);
  11156.       d_ellipse_start (pnt, shift_down);
  11157.       break;
  11158.     case POLY:
  11159.       draw_sqr (pnt);
  11160.       d_poly_start (pnt, shift_down);
  11161.       break;
  11162.     case ARC:
  11163.       d_arc_start (pnt, shift_down);
  11164.       break;
  11165.     case STAR:
  11166.       draw_sqr (pnt);
  11167.       d_star_start (pnt, shift_down);
  11168.       break;
  11169.     case SPIRAL:
  11170.       draw_sqr (pnt);
  11171.       d_spiral_start (pnt, shift_down);
  11172.       break;
  11173.     case BEZIER:
  11174.       if (!tmp_bezier)
  11175.     draw_sqr (pnt);
  11176.       d_bezier_start (pnt, shift_down);
  11177.       break;
  11178.     default:
  11179.       /* Internal error */
  11180.       break;
  11181.     }
  11182. }
  11183.   
  11184. /* Real object now !*/
  11185. static void
  11186. object_end (GdkPoint *pnt,
  11187.         gint      shift_down)
  11188. {
  11189.   /* end for the current object */
  11190.   /* Add onto global object list */
  11191.  
  11192.   /* If shift is down may carry on drawing */
  11193.   switch (selvals.otype)
  11194.     {
  11195.     case LINE:
  11196.       d_line_end (pnt, shift_down);
  11197.       draw_sqr (pnt);
  11198.       break;
  11199.     case CIRCLE:
  11200.       draw_sqr (pnt);
  11201.       d_circle_end (pnt, shift_down);
  11202.       break;
  11203.     case ELLIPSE:
  11204.       draw_sqr (pnt);
  11205.       d_ellipse_end (pnt, shift_down);
  11206.       break;
  11207.     case POLY:
  11208.       draw_sqr (pnt);
  11209.       d_poly_end (pnt, shift_down);
  11210.       break;
  11211.     case STAR:
  11212.       draw_sqr (pnt);
  11213.       d_star_end (pnt, shift_down);
  11214.       break;
  11215.     case ARC:
  11216.       draw_sqr (pnt);
  11217.       d_arc_end (pnt, shift_down);
  11218.       break;
  11219.     case SPIRAL:
  11220.       draw_sqr (pnt);
  11221.       d_spiral_end (pnt, shift_down);
  11222.       break;
  11223.     case BEZIER:
  11224.       d_bezier_end (pnt, shift_down);
  11225.       break;
  11226.     default:
  11227.       /* Internal error */
  11228.       break;
  11229.     }
  11230.  
  11231.   if (need_to_scale)
  11232.     {
  11233.       need_to_scale = 0;
  11234.       selvals.scaletoimage = 0;
  11235.     }
  11236. }
  11237.  
  11238. static void
  11239. object_update (GdkPoint *pnt)
  11240. {
  11241.   /* update for the current object */
  11242.   /* New position xy */
  11243.   switch (selvals.otype)
  11244.     {
  11245.     case LINE:
  11246.       d_update_line (pnt);
  11247.       break;
  11248.     case CIRCLE:
  11249.       d_update_circle (pnt);
  11250.       break;
  11251.     case ELLIPSE:
  11252.       d_update_ellipse (pnt);
  11253.       break;
  11254.     case POLY:
  11255.       d_update_poly (pnt);
  11256.       break;
  11257.     case STAR:
  11258.       d_update_star (pnt);
  11259.       break;
  11260.     case ARC:
  11261.       d_update_arc (pnt);
  11262.       break;
  11263.     case SPIRAL:
  11264.       d_update_spiral (pnt);
  11265.       break;
  11266.     case BEZIER:
  11267.       d_update_bezier (pnt);
  11268.       break;
  11269.     default:
  11270.       /* Internal error */
  11271.       break;
  11272.     }
  11273. }
  11274.