home *** CD-ROM | disk | FTP | other *** search
/ PC Pro 2002 April / pcpro0402.iso / essentials / graphics / Gimp / gimp-src-20001226.exe / src / gimp / plug-ins / imagemap / imap_main.c < prev    next >
Encoding:
C/C++ Source or Header  |  2000-11-19  |  35.2 KB  |  1,453 lines

  1. /*
  2.  * This is a plug-in for the GIMP.
  3.  *
  4.  * Generates clickable image maps.
  5.  *
  6.  * Copyright (C) 1998-1999 Maurits Rijk  lpeek.mrijk@consunet.nl
  7.  *
  8.  * This program is free software; you can redistribute it and/or modify
  9.  * it under the terms of the GNU General Public License as published by
  10.  * the Free Software Foundation; either version 2 of the License, or
  11.  * (at your option) any later version.
  12.  *
  13.  * This program is distributed in the hope that it will be useful,
  14.  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  15.  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  16.  * GNU General Public License for more details.
  17.  *
  18.  * You should have received a copy of the GNU General Public License
  19.  * along with this program; if not, write to the Free Software
  20.  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
  21.  *
  22.  */
  23. #include "config.h"
  24.  
  25. #include <stdarg.h>
  26. #include <stdlib.h>
  27. #include <stdio.h>
  28. #include <string.h>
  29.  
  30. #include <gtk/gtk.h>
  31. #include <gdk/gdkkeysyms.h> /* for keyboard values */
  32.  
  33. #include <libgimp/gimp.h>
  34. #include <libgimp/gimpui.h>
  35.  
  36. #include "imap_about.h"
  37. #include "imap_circle.h"
  38. #include "imap_cmd_clear.h"
  39. #include "imap_cmd_copy.h"
  40. #include "imap_cmd_cut.h"
  41. #include "imap_cmd_create.h"
  42. #include "imap_cmd_guides.h"
  43. #include "imap_cmd_move.h"
  44. #include "imap_cmd_move_down.h"
  45. #include "imap_cmd_move_sash.h"
  46. #include "imap_cmd_move_selected.h"
  47. #include "imap_cmd_move_to_front.h"
  48. #include "imap_cmd_move_up.h"
  49. #include "imap_cmd_object_move.h"
  50. #include "imap_cmd_paste.h"
  51. #include "imap_cmd_select.h"
  52. #include "imap_cmd_select_all.h"
  53. #include "imap_cmd_select_next.h"
  54. #include "imap_cmd_select_prev.h"
  55. #include "imap_cmd_select_region.h"
  56. #include "imap_cmd_send_to_back.h"
  57. #include "imap_cmd_unselect.h"
  58. #include "imap_cmd_unselect_all.h"
  59. #include "imap_default_dialog.h"
  60. #include "imap_edit_area_info.h"
  61. #include "imap_file.h"
  62. #include "imap_grid.h"
  63. #include "imap_main.h"
  64. #include "imap_menu.h"
  65. #include "imap_object.h"
  66. #include "imap_polygon.h"
  67. #include "imap_popup.h"
  68. #include "imap_preview.h"
  69. #include "imap_rectangle.h"
  70. #include "imap_selection.h"
  71. #include "imap_settings.h"
  72. #include "imap_source.h"
  73. #include "imap_statusbar.h"
  74. #include "imap_string.h"
  75. #include "imap_toolbar.h"
  76. #include "imap_tools.h"
  77.  
  78. #include "libgimp/stdplugins-intl.h"
  79.  
  80.  
  81. #define MAX_ZOOM_FACTOR 8
  82. #define ZOOMED(x) (_zoom_factor * (x))
  83. #define GET_REAL_COORD(x) ((x) / _zoom_factor)
  84.  
  85. /* Global variables */
  86. static MapInfo_t   _map_info;
  87. static PreferencesData_t _preferences = {CSIM, TRUE, FALSE, TRUE, TRUE, FALSE,
  88. FALSE, DEFAULT_UNDO_LEVELS, DEFAULT_MRU_SIZE};
  89. static MRU_t *_mru;
  90.  
  91. static GdkCursorType _cursor;
  92. static gboolean        _show_url = TRUE;
  93. static gchar       *_filename = NULL;
  94. static char       *_image_name;
  95. static gint       _image_width;
  96. static gint       _image_height;
  97. static GtkWidget   *_dlg;
  98. static Preview_t   *_preview;
  99. static Selection_t *_selection;
  100. static StatusBar_t *_statusbar;
  101. static ToolBar_t   *_toolbar;
  102. static ObjectList_t *_shapes;
  103. static gint        _zoom_factor = 1;
  104. static void (*_button_press_func)(GtkWidget*, GdkEventButton*, gpointer);
  105. static gpointer _button_press_param;
  106.  
  107. /* Declare local functions. */
  108. static void query (void);
  109. static void run (char *name,
  110.          int nparams,
  111.          GimpParam * param,
  112.          int *nreturn_vals,
  113.          GimpParam ** return_vals);
  114. static gint dialog(GimpDrawable *drawable);
  115.  
  116. GimpPlugInInfo PLUG_IN_INFO = {
  117.    NULL,            /* init_proc */
  118.    NULL,            /* quit_proc */
  119.    query,            /* query_proc */
  120.    run,                /* run_proc */
  121. };
  122.  
  123. static int run_flag = 0;
  124.  
  125.  
  126. MAIN ()
  127.  
  128. static void query()
  129. {
  130.    static GimpParamDef args[] = {
  131.       {GIMP_PDB_INT32, "run_mode", "Interactive"},
  132.       {GIMP_PDB_IMAGE, "image", "Input image (unused)"},
  133.       {GIMP_PDB_DRAWABLE, "drawable", "Input drawable"},
  134.    };
  135.    static GimpParamDef *return_vals = NULL;
  136.    static int nargs = sizeof (args) / sizeof (args[0]);
  137.    static int nreturn_vals = 0;
  138.    
  139.    gimp_install_procedure("plug_in_imagemap",
  140.               "Creates a clickable imagemap.",
  141.               "",
  142.               "Maurits Rijk",
  143.               "Maurits Rijk",
  144.               "1998-1999",
  145.               N_("<Image>/Filters/Web/ImageMap..."),
  146.               "RGB*, GRAY*, INDEXED*",
  147.               GIMP_PLUGIN,
  148.               nargs, nreturn_vals,
  149.               args, return_vals);
  150. }
  151.  
  152. static void
  153. run(char *name, int n_params, GimpParam *param, int *nreturn_vals,
  154.     GimpParam **return_vals)
  155. {
  156.    static GimpParam values[1];
  157.    GimpDrawable *drawable;
  158.    GimpRunModeType run_mode;
  159.    GimpPDBStatusType status = GIMP_PDB_SUCCESS;
  160.  
  161.    INIT_I18N_UI();
  162.  
  163.    *nreturn_vals = 1;
  164.    *return_vals = values;
  165.    
  166.    /*  Get the specified drawable  */
  167.    drawable = gimp_drawable_get(param[2].data.d_drawable);
  168.    _image_name = gimp_image_get_filename(param[1].data.d_image);
  169.    _image_width = gimp_image_width(param[1].data.d_image);
  170.    _image_height = gimp_image_height(param[1].data.d_image);
  171.  
  172.    _map_info.color = gimp_drawable_is_rgb(drawable->id);
  173.  
  174.    run_mode = (GimpRunModeType) param[0].data.d_int32;
  175.    
  176.    if (run_mode == GIMP_RUN_INTERACTIVE) {
  177.       if (!dialog(drawable)) {
  178.      /* The dialog was closed, or something similarly evil happened. */
  179.      status = GIMP_PDB_EXECUTION_ERROR;
  180.       }
  181.    }
  182.       
  183.    if (status == GIMP_PDB_SUCCESS) {
  184.       gimp_drawable_detach(drawable);
  185.    }
  186.    
  187.    values[0].type = GIMP_PDB_STATUS;
  188.    values[0].data.d_status = status;
  189. }
  190.  
  191. MRU_t*
  192. get_mru(void)
  193. {
  194.    if (!_mru)
  195.       _mru = mru_create();
  196.    return _mru;
  197. }
  198.  
  199. MapInfo_t*
  200. get_map_info(void)
  201. {
  202.    return &_map_info;
  203. }
  204.  
  205. PreferencesData_t*
  206. get_preferences(void)
  207. {
  208.    return &_preferences;
  209. }
  210.  
  211. static void
  212. init_preferences(void)
  213. {
  214.    GdkColormap *colormap = gdk_window_get_colormap(_dlg->window);
  215.    ColorSelData_t *colors = &_preferences.colors;
  216.  
  217.    colors->normal_fg.red = 0;
  218.    colors->normal_fg.green = 0xFFFF;
  219.    colors->normal_fg.blue = 0;
  220.    
  221.    colors->normal_bg.red = 0;
  222.    colors->normal_bg.green = 0;
  223.    colors->normal_bg.blue = 0xFFFF;
  224.    
  225.    colors->selected_fg.red = 0xFFFF;
  226.    colors->selected_fg.green = 0;
  227.    colors->selected_fg.blue = 0;
  228.    
  229.    colors->selected_bg.red = 0;
  230.    colors->selected_bg.green = 0;
  231.    colors->selected_bg.blue = 0xFFFF;
  232.    
  233.    preferences_load(&_preferences);
  234.  
  235.    gdk_color_alloc(colormap, &colors->normal_fg);
  236.    gdk_color_alloc(colormap, &colors->normal_bg);
  237.    gdk_color_alloc(colormap, &colors->selected_fg);
  238.    gdk_color_alloc(colormap, &colors->selected_bg);
  239.  
  240.    _preferences.normal_gc = gdk_gc_new(_preview->preview->window);
  241.    _preferences.selected_gc = gdk_gc_new(_preview->preview->window);
  242.  
  243.    gdk_gc_set_line_attributes(_preferences.normal_gc, 1, GDK_LINE_DOUBLE_DASH,
  244.                   GDK_CAP_BUTT, GDK_JOIN_BEVEL);
  245.    gdk_gc_set_line_attributes(_preferences.selected_gc, 1, 
  246.                   GDK_LINE_DOUBLE_DASH, GDK_CAP_BUTT, 
  247.                   GDK_JOIN_BEVEL);
  248.    
  249.    gdk_gc_set_foreground(_preferences.normal_gc, &colors->normal_fg);
  250.    gdk_gc_set_background(_preferences.normal_gc, &colors->normal_bg);
  251.    gdk_gc_set_foreground(_preferences.selected_gc, &colors->selected_fg);
  252.    gdk_gc_set_background(_preferences.selected_gc, &colors->selected_bg);
  253.  
  254.    mru_set_size(_mru, _preferences.mru_size);
  255.    command_list_set_undo_level(_preferences.undo_levels);
  256. }
  257.  
  258.  
  259. gint
  260. get_image_width(void)
  261. {
  262.    return _image_width;
  263. }
  264.  
  265. gint
  266. get_image_height(void)
  267. {
  268.    return _image_height;
  269. }
  270.  
  271. void 
  272. set_busy_cursor(void)
  273. {
  274.    preview_set_cursor(_preview, GDK_WATCH);
  275. }
  276.  
  277. void 
  278. remove_busy_cursor(void)
  279. {
  280.    gdk_window_set_cursor(_dlg->window, NULL);
  281. }
  282.  
  283. static gint
  284. zoom_in(void)
  285. {
  286.    if (_zoom_factor < MAX_ZOOM_FACTOR) {
  287.       set_zoom(_zoom_factor + 1);
  288.       menu_set_zoom(_zoom_factor);
  289.    }
  290.    return _zoom_factor;
  291. }
  292.  
  293. static gint
  294. zoom_out(void)
  295. {
  296.    if (_zoom_factor > 1) {
  297.       set_zoom(_zoom_factor - 1);
  298.       menu_set_zoom(_zoom_factor);
  299.    }
  300.    return _zoom_factor;
  301. }
  302.  
  303. void
  304. set_zoom(gint zoom_factor)
  305. {
  306.    set_busy_cursor();
  307.    _zoom_factor = zoom_factor;
  308.    toolbar_set_zoom_sensitivity(_toolbar, zoom_factor);
  309.    preview_zoom(_preview, zoom_factor);
  310.    statusbar_set_zoom(_statusbar, zoom_factor);
  311.    remove_busy_cursor();
  312. }
  313.  
  314. void
  315. main_toolbar_set_grid(gboolean active)
  316. {
  317.    toolbar_set_grid(_toolbar, active);
  318. }
  319.  
  320. gint
  321. get_real_coord(gint coord)
  322. {
  323.    return GET_REAL_COORD(coord);
  324. }
  325.  
  326. void
  327. draw_line(GdkWindow *window, GdkGC *gc, gint x1, gint y1, gint x2, gint y2)
  328. {
  329.    gdk_draw_line(window, gc, ZOOMED(x1), ZOOMED(y1), ZOOMED(x2), ZOOMED(y2));
  330. }
  331.  
  332. void
  333. draw_rectangle(GdkWindow *window, GdkGC    *gc, gint filled, gint x, gint y,
  334.            gint width, gint    height)
  335. {
  336.    gdk_draw_rectangle(window, gc, filled, ZOOMED(x), ZOOMED(y),
  337.               ZOOMED(width), ZOOMED(height));
  338. }
  339.  
  340. void
  341. draw_arc(GdkWindow *window, GdkGC *gc, gint filled, gint x, gint y,
  342.      gint width, gint height, gint angle1, gint angle2)
  343. {
  344.    gdk_draw_arc(window, gc, filled, ZOOMED(x), ZOOMED(y),
  345.         ZOOMED(width), ZOOMED(height), angle1, angle2);
  346. }
  347.  
  348. void
  349. draw_circle(GdkWindow *window, GdkGC *gc, gint filled, gint x, gint y, gint r)
  350. {
  351.    draw_arc(window, gc, filled, x - r, y - r, 2 * r, 2 * r, 0, 360 * 64);
  352. }
  353.  
  354. void
  355. draw_polygon(GdkWindow *window, GdkGC *gc, GList *list)
  356. {
  357.    gint       npoints = g_list_length(list);
  358.    GdkPoint  *points = g_new(GdkPoint, npoints);
  359.    GdkPoint  *des = points;
  360.    GList     *p;
  361.  
  362.    for (p = list; p; p = p->next, des++) {
  363.       GdkPoint *src = (GdkPoint*) p->data;
  364.       des->x = ZOOMED(src->x);
  365.       des->y = ZOOMED(src->y);
  366.    }
  367.    gdk_draw_polygon(window, gc, FALSE, points, npoints);
  368.    g_free(points);
  369. }
  370.  
  371. static gboolean _preview_redraw_blocked = FALSE;
  372. static gboolean _pending_redraw = FALSE;
  373.  
  374. void
  375. preview_freeze(void)
  376. {
  377.    _preview_redraw_blocked = TRUE;
  378. }
  379.  
  380. void
  381. preview_thaw(void)
  382. {
  383.    _preview_redraw_blocked = FALSE;
  384.    if (_pending_redraw) {
  385.       _pending_redraw = FALSE;
  386.       redraw_preview();
  387.    }
  388. }
  389.  
  390. void 
  391. redraw_preview(void)
  392. {
  393.    if (_preview_redraw_blocked)
  394.       _pending_redraw = TRUE;
  395.    else
  396.       preview_redraw(_preview);
  397. }
  398.  
  399. static void
  400. set_preview_gray(void)
  401. {
  402.    _map_info.show_gray = TRUE;
  403.    set_zoom(_zoom_factor);
  404. }
  405.  
  406. static void
  407. set_preview_color(void)
  408. {
  409.    _map_info.show_gray = FALSE;
  410.    set_zoom(_zoom_factor);
  411. }
  412.  
  413. const char*
  414. get_image_name(void)
  415. {
  416.    return _image_name;
  417. }
  418.  
  419. const char*
  420. get_filename(void)
  421. {
  422.    return _filename;
  423. }
  424.  
  425. void
  426. set_arrow_func(void)
  427. {
  428.    _button_press_func = arrow_on_button_press;
  429.    _cursor = GDK_TOP_LEFT_ARROW;
  430. }
  431.  
  432. static void 
  433. set_object_func(void (*func)(GtkWidget*, GdkEventButton*, 
  434.                  gpointer), gpointer param)
  435. {
  436.    _button_press_func = func;
  437.    _button_press_param = param;
  438.    _cursor = GDK_CROSSHAIR;
  439. }
  440.  
  441. void
  442. set_rectangle_func(void)
  443. {
  444.    set_object_func(object_on_button_press, get_rectangle_factory);
  445. }
  446.  
  447. void
  448. set_circle_func(void)
  449. {
  450.    set_object_func(object_on_button_press, get_circle_factory);
  451. }
  452.  
  453. void
  454. set_polygon_func(void)
  455. {
  456.    set_object_func(object_on_button_press, get_polygon_factory);
  457. }
  458.  
  459. void
  460. add_shape(Object_t *obj)
  461. {
  462.    object_list_append(_shapes, obj);
  463. }
  464.  
  465. ObjectList_t*
  466. get_shapes(void)
  467. {
  468.    return _shapes;
  469. }
  470.  
  471. void
  472. update_shape(Object_t *obj)
  473. {
  474.    object_list_update(_shapes, obj);
  475. }
  476.  
  477. static void
  478. edit_selected_shape(void)
  479. {
  480.    object_list_edit_selected(_shapes);
  481. }
  482.  
  483. void
  484. do_popup_menu(GdkEventButton *event)
  485. {
  486.    gint x = GET_REAL_COORD((gint) event->x);
  487.    gint y = GET_REAL_COORD((gint) event->y);
  488.    Object_t *obj = object_list_find(_shapes, x, y);
  489.    if (obj) {
  490.       obj->class->do_popup(obj, event);
  491.    } else {
  492.       do_main_popup_menu(event);
  493.    }
  494. }
  495.  
  496. static void
  497. set_all_sensitivities(void)
  498. {
  499.    gint count = object_list_nr_selected(_shapes);
  500.    menu_shapes_selected(count);
  501.    toolbar_shapes_selected(_toolbar, count);
  502.    tools_set_sensitive(count);
  503. }
  504.  
  505. static void
  506. main_set_title(const char *filename)
  507. {
  508.    char *title, *p;
  509.    
  510.    g_strreplace(&_filename, filename);
  511.    p = (filename) ? g_basename(filename) : _("<Untitled>");
  512.    title = g_strdup_printf("%s - ImageMap 1.3", p);
  513.    gtk_window_set_title(GTK_WINDOW(_dlg), title);
  514.    g_free(title);
  515. }
  516.  
  517. void 
  518. main_set_dimension(gint width, gint height)
  519. {
  520.    statusbar_set_dimension(_statusbar, width / _zoom_factor, 
  521.                height / _zoom_factor);
  522. }
  523.  
  524. void
  525. main_clear_dimension(void)
  526. {
  527.    statusbar_clear_dimension(_statusbar);
  528. }
  529.  
  530. void
  531. show_url(void)
  532. {
  533.    _show_url = TRUE;
  534. }
  535.  
  536. void
  537. hide_url(void)
  538. {
  539.    _show_url = FALSE;
  540.    statusbar_clear_status(_statusbar);
  541. }
  542.  
  543. void 
  544. select_shape(GtkWidget *widget, GdkEventButton *event)
  545. {
  546.    Object_t *obj;
  547.    gint x = GET_REAL_COORD((gint) event->x);
  548.    gint y = GET_REAL_COORD((gint) event->y);
  549.    MoveSashFunc_t sash_func;
  550.  
  551.    obj = object_list_near_sash(_shapes, x, y, &sash_func);
  552.    if (obj) {            /* Start resizing */
  553.       Command_t *command = move_sash_command_new(widget, obj, x, y, sash_func);
  554.       command_execute(command);
  555.    } else {
  556.       Command_t *command;
  557.  
  558.       obj = object_list_find(_shapes, x, y);
  559.       if (obj) {
  560.      if (event->state & GDK_SHIFT_MASK) {
  561.         if (obj->selected)
  562.            command = unselect_command_new(obj);
  563.         else
  564.            command = select_command_new(obj);
  565.      } else {        /* No Shift key pressed */
  566.         if (obj->selected) {
  567.            command = unselect_all_command_new(_shapes, obj);
  568.         } else {
  569.            Command_t *sub_command;
  570.  
  571.            command = subcommand_start(NULL);
  572.            sub_command = unselect_all_command_new(_shapes, NULL);
  573.            command_add_subcommand(command, sub_command);
  574.            sub_command = select_command_new(obj);
  575.            command_add_subcommand(command, sub_command);
  576.            command_set_name(command, sub_command->name);
  577.            subcommand_end();
  578.         }
  579.      }
  580.      command_execute(command);
  581.  
  582.      command = move_command_new(_preview, obj, x, y);
  583.      command_execute(command);
  584.       } else { /* Start selection rectangle */
  585.      command = select_region_command_new(widget, _shapes, x, y);
  586.      command_execute(command);
  587.       }
  588.    }
  589. }
  590.  
  591. void
  592. edit_shape(gint x, gint y)
  593. {
  594.    Object_t *obj;
  595.  
  596.    x = GET_REAL_COORD(x);
  597.    y = GET_REAL_COORD(y);
  598.  
  599.    obj = object_list_find(_shapes, x, y);
  600.    if (obj) {
  601.       object_select(obj);
  602.       object_edit(obj, TRUE);
  603.    }
  604. }
  605.  
  606. static void
  607. toolbar_grid(void)
  608. {
  609.    gint grid = toggle_grid();
  610.    popup_check_grid(grid);
  611.    menu_check_grid(grid);
  612. }
  613.  
  614. static void
  615. menu_zoom_in(void)
  616. {
  617.    gint factor = zoom_in();
  618.    menu_set_zoom_sensitivity(factor);
  619.    popup_set_zoom_sensitivity(factor);
  620. }
  621.  
  622. static void
  623. menu_zoom_out(void)
  624. {
  625.    gint factor = zoom_out();
  626.    menu_set_zoom_sensitivity(factor);
  627.    popup_set_zoom_sensitivity(factor);
  628. }
  629.  
  630. void 
  631. draw_shapes(GtkWidget *preview)
  632. {
  633.    if (!_preview_redraw_blocked)
  634.       object_list_draw(_shapes, preview->window);
  635. }
  636.  
  637. static void
  638. clear_map_info(void)
  639. {
  640.    gchar *author = g_get_real_name();
  641.  
  642.    if (!*author)
  643.       author = g_get_user_name();
  644.    g_strreplace(&_map_info.image_name, _image_name);
  645.    g_strreplace(&_map_info.title, "map");
  646.    g_strreplace(&_map_info.author, author);
  647.    g_strreplace(&_map_info.default_url, "");
  648.    g_strreplace(&_map_info.description, "");
  649.  
  650.    _map_info.map_format = CSIM;
  651.    _map_info.show_gray = FALSE;
  652. }
  653.  
  654. static void
  655. do_data_changed_dialog(void (*continue_cb)(gpointer), gpointer param)
  656. {
  657.    static DefaultDialog_t *dialog;
  658.  
  659.    if (!dialog) {
  660.       dialog = make_default_dialog(_("Data changed"));
  661.       default_dialog_hide_apply_button(dialog);
  662.       default_dialog_set_label(
  663.      dialog,
  664.      _("Some data has been changed.\n"
  665.        "Do you really want to continue?"));
  666.    }
  667.    default_dialog_set_ok_cb(dialog, continue_cb, param);
  668.    default_dialog_show(dialog);
  669. }
  670.  
  671. static void
  672. check_if_changed(void (*func)(gpointer), gpointer param)
  673. {
  674.    if (object_list_get_changed(_shapes))
  675.       do_data_changed_dialog(func, param);
  676.    else
  677.       func(param);
  678. }
  679.  
  680. static void
  681. close_current(void)
  682. {
  683.    selection_freeze(_selection);
  684.    object_list_remove_all(_shapes);
  685.    selection_thaw(_selection);
  686.    clear_map_info();
  687.    main_set_title(NULL);
  688.    set_all_sensitivities();
  689.    redraw_preview();
  690.    object_list_clear_changed(_shapes);
  691.    command_list_remove_all();
  692. }
  693.  
  694. static void
  695. really_close(gpointer data)
  696. {
  697.    close_current();
  698. }
  699.  
  700. static void
  701. do_close(void)
  702. {
  703.    check_if_changed(really_close, NULL);
  704. }
  705.  
  706. static void
  707. really_quit(gpointer data)
  708. {
  709.    preferences_save(&_preferences);
  710.    run_flag = 1;
  711.    gtk_widget_destroy(_dlg);
  712. }
  713.  
  714. static void
  715. do_quit(void)
  716. {
  717.    check_if_changed(really_quit, NULL);
  718. }
  719.  
  720. static void
  721. do_undo(void)
  722. {
  723.    preview_freeze();
  724.    selection_freeze(_selection);
  725.    last_command_undo();
  726.    selection_thaw(_selection);
  727.    preview_thaw();
  728. }
  729.  
  730. static void
  731. do_redo(void)
  732. {
  733.    preview_freeze();
  734.    selection_freeze(_selection);
  735.    last_command_redo();
  736.    selection_thaw(_selection);
  737.    preview_thaw();
  738. }
  739.  
  740. static void
  741. save(void)
  742. {
  743.    if (_filename)
  744.       save_as(_filename);
  745.    else
  746.       do_file_save_as_dialog();
  747. }
  748.  
  749. static void
  750. write_cern_comment(gpointer param, OutputFunc_t output)
  751. {
  752.    output(param, "rect (4096,4096) (4096,4096) imap:#$");   
  753. }
  754.  
  755. static void
  756. save_as_cern(gpointer param, OutputFunc_t output)
  757. {
  758.    char *p;
  759.    gchar *description;
  760.    gchar *next_token;
  761.  
  762.    write_cern_comment(param, output);
  763.    output(param, "-:Image Map file created by GIMP Imagemap Plugin\n");
  764.    write_cern_comment(param, output);
  765.    output(param, "-:GIMP Imagemap Plugin by Maurits Rijk\n");
  766.    write_cern_comment(param, output);
  767.    output(param, "-:Please do not edit lines starting with \"#$\"\n");
  768.    write_cern_comment(param, output);
  769.    output(param, "VERSION:1.3\n");
  770.    write_cern_comment(param, output);
  771.    output(param, "TITLE:%s\n", _map_info.title);
  772.    write_cern_comment(param, output);
  773.    output(param, "AUTHOR:%s\n", _map_info.author);
  774.    write_cern_comment(param, output);
  775.    output(param, "FORMAT:cern\n");
  776.    
  777.    description = g_strdup(_map_info.description);
  778.    next_token = description;
  779.    for (p = strtok (next_token, "\n"); p; p = strtok(NULL, "\n")) {
  780.       write_cern_comment(param, output);
  781.       output(param, "DESCRIPTION:%s\n", p);
  782.    }
  783.    g_free(description);
  784.  
  785.    if (*_map_info.default_url)
  786.       output(param, "default %s\n", _map_info.default_url);
  787.    object_list_write_cern(_shapes, param, output);
  788. }
  789.  
  790. static void
  791. save_as_csim(gpointer param, OutputFunc_t output)
  792. {
  793.    char *p;
  794.    gchar *description;
  795.    
  796.    output(param, "<IMG SRC=\"%s\" WIDTH=%d HEIGHT=%d BORDER=0 "
  797.       "USEMAP=\"#%s\">\n\n", _map_info.image_name,
  798.       _image_width, _image_height, _map_info.title);
  799.    output(param, "<MAP NAME=\"%s\">\n", _map_info.title);
  800.    output(param, 
  801.       "<!-- #$-:Image Map file created by GIMP Imagemap Plugin -->\n");
  802.    output(param, "<!-- #$-:GIMP Imagemap Plugin by Maurits Rijk -->\n");
  803.    output(param, 
  804.       "<!-- #$-:Please do not edit lines starting with \"#$\" -->\n");
  805.    output(param, "<!-- #$VERSION:1.3 -->\n");
  806.    output(param, "<!-- #$AUTHOR:%s -->\n", _map_info.author);
  807.    
  808.    description = g_strdup(_map_info.description);
  809.    for (p = strtok(description, "\n"); p; p = strtok(NULL, "\n"))
  810.       output(param, "<!-- #$DESCRIPTION:%s -->\n", p);
  811.    g_free(description);
  812.    
  813.    object_list_write_csim(_shapes, param, output);
  814.    if (*_map_info.default_url)
  815.       output(param, "<AREA SHAPE=\"DEFAULT\" HREF=\"%s\">\n",
  816.          _map_info.default_url);
  817.    output(param, "</MAP>\n");
  818. }
  819.  
  820. static void
  821. save_as_ncsa(gpointer param, OutputFunc_t output)
  822. {
  823.    char *p;
  824.    gchar *description;
  825.  
  826.    output(param, "#$-:Image Map file created by GIMP Imagemap Plugin\n");
  827.    output(param, "#$-:GIMP Imagemap Plugin by Maurits Rijk\n");
  828.    output(param, "#$-:Please do not edit lines starting with \"#$\"\n");
  829.    output(param, "#$VERSION:1.3\n");
  830.    output(param, "#$TITLE:%s\n", _map_info.title);
  831.    output(param, "#$AUTHOR:%s\n", _map_info.author);
  832.    output(param, "#$FORMAT:ncsa\n");
  833.    
  834.    description = g_strdup(_map_info.description);
  835.    for (p = strtok(description, "\n"); p; p = strtok(NULL, "\n"))
  836.       output(param, "#$DESCRIPTION:%s\n", p);
  837.    g_free(description);
  838.  
  839.    if (*_map_info.default_url)
  840.       output(param, "default %s\n", _map_info.default_url);
  841.    object_list_write_ncsa(_shapes, param, output);
  842. }
  843.  
  844. static void 
  845. save_to_file(gpointer param, const char* format, ...)
  846. {
  847.    va_list ap;
  848.  
  849.    va_start(ap, format);
  850.    vfprintf((FILE*)param, format, ap);
  851.    va_end(ap);
  852. }
  853.  
  854. void
  855. dump_output(gpointer param, OutputFunc_t output)
  856. {
  857.    if (_map_info.map_format == NCSA)
  858.       save_as_ncsa(param, output);
  859.    else if (_map_info.map_format == CERN)
  860.       save_as_cern(param, output);
  861.    else if (_map_info.map_format == CSIM)
  862.       save_as_csim(param, output);
  863. }
  864.  
  865. void
  866. save_as(const gchar *filename)
  867. {
  868.    FILE *out = fopen(filename, "w");
  869.    if (out) {
  870.       dump_output(out, save_to_file);
  871.       fclose(out);
  872.  
  873.       statusbar_set_status(_statusbar, _("File \"%s\" saved."), filename);
  874.       main_set_title(filename);
  875.       object_list_clear_changed(_shapes);
  876.    } else {
  877.       do_file_error_dialog( _("Couldn't save file:"), filename);
  878.    }
  879. }
  880.  
  881. static void
  882. resize_image_ok_cb(gpointer data)
  883. {
  884.    gint per_x = _image_width * 100 / _map_info.old_image_width;
  885.    gint per_y = _image_height * 100 / _map_info.old_image_height;
  886.    object_list_resize(_shapes, per_x, per_y);
  887.    preview_thaw();
  888. }
  889.  
  890. static void
  891. resize_image_cancel_cb(gpointer data)
  892. {
  893.    preview_thaw();
  894. }
  895.  
  896. static void
  897. do_image_size_changed_dialog(void)
  898. {
  899.    static DefaultDialog_t *dialog;
  900.  
  901.    if (!dialog) {
  902.       dialog = make_default_dialog( _("Image size changed"));
  903.       default_dialog_hide_apply_button(dialog);
  904.       default_dialog_set_label(
  905.      dialog,
  906.      _("Image size has changed.\n"
  907.        "Resize Area's?"));
  908.  
  909.       default_dialog_set_ok_cb(dialog, resize_image_ok_cb, NULL);
  910.       default_dialog_set_cancel_cb(dialog, resize_image_cancel_cb, NULL);
  911.    }
  912.    default_dialog_show(dialog);
  913.  
  914. }
  915.  
  916. static void
  917. really_load(gpointer data)
  918. {
  919.    gchar *filename = (gchar*) data;
  920.    close_current();
  921.  
  922.    selection_freeze(_selection);
  923.    _map_info.old_image_width = _image_width;
  924.    _map_info.old_image_height = _image_height;
  925.    if (load_csim(filename)) {
  926.       _map_info.map_format = CSIM;
  927.       if (_image_width != _map_info.old_image_width ||
  928.       _image_height != _map_info.old_image_height) {
  929.      preview_freeze();
  930.      do_image_size_changed_dialog();
  931.       }
  932.    } else if (load_ncsa(filename)) {
  933.       _map_info.map_format = NCSA;
  934.    } else if (load_cern(filename)) {
  935.       _map_info.map_format = CERN;
  936.    } else {
  937.       do_file_error_dialog( _("Couldn't read file:"), filename);
  938.       selection_thaw(_selection);
  939.       close_current();
  940.       return;
  941.    }
  942.    mru_set_first(_mru, filename);
  943.    menu_build_mru_items(_mru);
  944.  
  945.    selection_thaw(_selection);
  946.    main_set_title(filename);
  947.    object_list_clear_changed(_shapes);
  948.    redraw_preview();
  949. }
  950.  
  951. void
  952. load(const gchar *filename)
  953. {
  954.    static gchar *tmp_filename;
  955.    g_strreplace(&tmp_filename, filename);
  956.    check_if_changed(really_load, (gpointer) tmp_filename);
  957. }
  958.  
  959. static void 
  960. toggle_area_list(void)
  961. {
  962.    selection_toggle_visibility(_selection);
  963. }
  964.  
  965. static void
  966. close_callback(GtkWidget *widget, gpointer data)
  967. {
  968.    gtk_main_quit();
  969. }
  970.  
  971. static void
  972. preview_move(GtkWidget *widget, GdkEventMotion *event)
  973. {
  974.    gint x = GET_REAL_COORD((gint) event->x);
  975.    gint y = GET_REAL_COORD((gint) event->y);
  976.    static Object_t *prev_obj = NULL;
  977.    Object_t *obj = object_list_find(_shapes, x, y);
  978.  
  979.    statusbar_set_xy(_statusbar, x, y);
  980.    if (obj != prev_obj) {
  981.       prev_obj = obj;
  982.       if (obj && _show_url) {
  983.      statusbar_set_status(_statusbar, _("URL: %s"), obj->url);
  984.       } else {
  985.      statusbar_clear_status(_statusbar);
  986.       }
  987.    }
  988. #ifdef _NOT_READY_YET_
  989.    if (!obj) {
  990.       if (grid_near_x(x)) {
  991.      preview_set_cursor(_preview, GDK_SB_H_DOUBLE_ARROW);
  992.       } else if (grid_near_y(y)) {
  993.      preview_set_cursor(_preview, GDK_SB_V_DOUBLE_ARROW);
  994.       } else {
  995.      preview_set_cursor(_preview, _cursor);
  996.       }
  997.    }
  998. #endif
  999. }
  1000.  
  1001. static void
  1002. preview_enter(GtkWidget *widget, GdkEventCrossing *event)
  1003. {
  1004.    preview_set_cursor(_preview, _cursor);
  1005. }
  1006.  
  1007. static void
  1008. preview_leave(GtkWidget *widget, GdkEventCrossing *event)
  1009. {
  1010.    gdk_window_set_cursor(_dlg->window, NULL);
  1011.    statusbar_clear_xy(_statusbar);
  1012. }
  1013.  
  1014. static void 
  1015. button_press(GtkWidget* widget, GdkEventButton* event, gpointer data)
  1016. {
  1017.    _button_press_func(widget, event, _button_press_param);
  1018. }
  1019.  
  1020. /* A few global vars for key movement */
  1021.  
  1022. static gint _timeout;
  1023. static guint _keyval;
  1024. static gint _dx, _dy;
  1025.  
  1026. static void
  1027. move_selected_objects(gint dx, gint dy, gboolean fast)
  1028. {
  1029.    if (fast) {
  1030.       dx *= 5;
  1031.       dy *= 5;
  1032.    }
  1033.    _dx += dx;
  1034.    _dy += dy;
  1035.  
  1036.    gdk_gc_set_function(_preferences.normal_gc, GDK_EQUIV);
  1037.    gdk_gc_set_function(_preferences.selected_gc, GDK_EQUIV);
  1038.    object_list_draw_selected(_shapes, _preview->preview->window);
  1039.    object_list_move_selected(_shapes, dx, dy);
  1040.    object_list_draw_selected(_shapes, _preview->preview->window);
  1041.    gdk_gc_set_function(_preferences.normal_gc, GDK_COPY);
  1042.    gdk_gc_set_function(_preferences.selected_gc, GDK_COPY);
  1043. }
  1044.  
  1045. static gboolean
  1046. key_timeout_cb(gpointer data)
  1047. {
  1048.    switch (_keyval) {
  1049.    case GDK_Left:
  1050.    case GDK_Right:
  1051.    case GDK_Up:
  1052.    case GDK_Down:
  1053.       command_list_add(move_selected_command_new(_shapes, _dx, _dy));
  1054.       _dx = _dy = 0;
  1055.       break;
  1056.    }
  1057.    preview_thaw();
  1058.    return FALSE;
  1059. }
  1060.  
  1061. static gboolean 
  1062. key_press_cb(GtkWidget *widget, GdkEventKey *event)
  1063. {
  1064.    gint handled = FALSE;
  1065.    gboolean shift = event->state & GDK_SHIFT_MASK;
  1066.    Command_t *command;
  1067.  
  1068.    preview_freeze();
  1069.    if (_timeout)
  1070.       gtk_timeout_remove(_timeout);
  1071.  
  1072.    switch (event->keyval) {
  1073.    case GDK_Left:
  1074.       move_selected_objects(-1, 0, shift);
  1075.       handled = TRUE;
  1076.       break;
  1077.    case GDK_Right:
  1078.       move_selected_objects(1, 0, shift);
  1079.       handled = TRUE;
  1080.       break;
  1081.    case GDK_Up:
  1082.       move_selected_objects(0, -1, shift);
  1083.       handled = TRUE;
  1084.       break;
  1085.    case GDK_Down:
  1086.       move_selected_objects(0, 1, shift);
  1087.       handled = TRUE;
  1088.       break;
  1089.    case GDK_Tab:
  1090.       if (shift)
  1091.      command = select_prev_command_new(_shapes);
  1092.       else
  1093.      command = select_next_command_new(_shapes);
  1094.       command_execute(command);
  1095.       handled = TRUE;
  1096.       break;
  1097.    }
  1098.    if (handled)
  1099.       gtk_signal_emit_stop_by_name(GTK_OBJECT(widget), "key_press_event");
  1100.  
  1101.    return handled;
  1102. }
  1103.  
  1104. static gboolean 
  1105. key_release_cb(GtkWidget *widget, GdkEventKey *event)
  1106. {
  1107.    _keyval = event->keyval;
  1108.    _timeout = gtk_timeout_add(250, key_timeout_cb, NULL);
  1109.    return FALSE;
  1110. }
  1111.  
  1112. static void
  1113. geometry_changed(Object_t *obj, gpointer data)
  1114. {
  1115.    redraw_preview();        /* Fix me! */
  1116. }
  1117.  
  1118. static void
  1119. data_changed(Object_t *obj, gpointer data)
  1120. {
  1121.    set_all_sensitivities();
  1122. }
  1123.  
  1124. static void
  1125. data_selected(Object_t *obj, gpointer data)
  1126. {
  1127.    set_all_sensitivities();
  1128. }
  1129.  
  1130. static Command_t*
  1131. factory_file_open_dialog(void)
  1132. {
  1133.    return command_new(do_file_open_dialog);
  1134. }
  1135.  
  1136. static Command_t*
  1137. factory_save(void)
  1138. {
  1139.    return command_new(save);
  1140. }
  1141.  
  1142. static Command_t*
  1143. factory_save_as(void)
  1144. {
  1145.    return command_new(do_file_save_as_dialog);
  1146. }
  1147.  
  1148. static Command_t*
  1149. factory_preferences_dialog(void)
  1150. {
  1151.    return command_new(do_preferences_dialog);
  1152. }
  1153.  
  1154. static Command_t*
  1155. factory_close(void)
  1156. {
  1157.    return command_new(do_close);
  1158. }
  1159.  
  1160. static Command_t*
  1161. factory_quit(void)
  1162. {
  1163.    return command_new(do_quit);
  1164. }
  1165.  
  1166.  
  1167. static Command_t*
  1168. factory_undo(void)
  1169. {
  1170.    return command_new(do_undo);
  1171. }
  1172.  
  1173. static Command_t*
  1174. factory_redo(void)
  1175. {
  1176.    return command_new(do_redo);
  1177. }
  1178.  
  1179. static Command_t*
  1180. factory_cut(void)
  1181. {
  1182.    return cut_command_new(_shapes);
  1183. }
  1184.  
  1185. static Command_t*
  1186. factory_copy(void)
  1187. {
  1188.    return copy_command_new(_shapes);
  1189. }
  1190.  
  1191. static Command_t*
  1192. factory_paste(void)
  1193. {
  1194.    return paste_command_new(_shapes);
  1195. }
  1196.  
  1197. static Command_t*
  1198. factory_select_all(void)
  1199. {
  1200.    return select_all_command_new(_shapes);
  1201. }
  1202.  
  1203. static Command_t*
  1204. factory_clear(void)
  1205. {
  1206.    return clear_command_new(_shapes);
  1207. }
  1208.  
  1209. static Command_t*
  1210. factory_edit(void)
  1211. {
  1212.    return command_new(edit_selected_shape);
  1213. }
  1214.  
  1215. static Command_t*
  1216. factory_toggle_area_list(void)
  1217. {
  1218.    return command_new(toggle_area_list);
  1219. }
  1220.  
  1221. static Command_t*
  1222. factory_source_dialog(void)
  1223. {
  1224.    return command_new(do_source_dialog);
  1225. }
  1226.  
  1227. static Command_t*
  1228. factory_preview_color(void)
  1229. {
  1230.    return command_new(set_preview_color);
  1231. }
  1232.  
  1233. static Command_t*
  1234. factory_preview_gray(void)
  1235. {
  1236.    return command_new(set_preview_gray);
  1237. }
  1238.  
  1239. static Command_t*
  1240. factory_menu_zoom_in(void)
  1241. {
  1242.    return command_new(menu_zoom_in);
  1243. }
  1244.  
  1245. static Command_t*
  1246. factory_menu_zoom_out(void)
  1247. {
  1248.    return command_new(menu_zoom_out);
  1249. }
  1250.  
  1251. static Command_t*
  1252. factory_zoom_in(void)
  1253. {
  1254.    return command_new((void (*)(void)) zoom_in);
  1255. }
  1256.  
  1257. static Command_t*
  1258. factory_zoom_out(void)
  1259. {
  1260.    return command_new((void (*)(void)) zoom_out);
  1261. }
  1262.  
  1263. static Command_t*
  1264. factory_settings_dialog(void)
  1265. {
  1266.    return command_new(do_settings_dialog);
  1267. }
  1268.  
  1269. static Command_t*
  1270. factory_move_to_front(void)
  1271. {
  1272.    return move_to_front_command_new(_shapes);
  1273. }
  1274.  
  1275. static Command_t*
  1276. factory_send_to_back(void)
  1277. {
  1278.    return send_to_back_command_new(_shapes);
  1279. }
  1280.  
  1281. static Command_t*
  1282. factory_toolbar_grid(void)
  1283. {
  1284.    return command_new(toolbar_grid);
  1285. }
  1286.  
  1287. static Command_t*
  1288. factory_grid_settings_dialog(void)
  1289. {
  1290.    return command_new(do_grid_settings_dialog);
  1291. }
  1292.  
  1293. static Command_t*
  1294. factory_create_guides_dialog(void)
  1295. {
  1296.    return guides_command_new(_shapes);
  1297. }
  1298.  
  1299. static Command_t*
  1300. factory_about_dialog(void)
  1301. {
  1302.    return command_new(do_about_dialog);
  1303. }
  1304.  
  1305. static Command_t*
  1306. factory_move_up(void)
  1307. {
  1308.    return move_up_command_new(_shapes);
  1309. }
  1310.  
  1311. static Command_t*
  1312. factory_move_down(void)
  1313. {
  1314.    return move_down_command_new(_shapes);
  1315. }
  1316.  
  1317. static gint
  1318. dialog(GimpDrawable *drawable)
  1319. {
  1320.    GtkWidget     *dlg;
  1321.    GtkWidget     *hbox;
  1322.    GtkWidget     *main_vbox;
  1323.    Tools_t    *tools;
  1324.    Menu_t    *menu;
  1325.    PopupMenu_t  *popup;
  1326.  
  1327.    gimp_ui_init ("imagemap", TRUE);
  1328.  
  1329.    _shapes = make_object_list();
  1330.  
  1331.    _dlg = dlg = gtk_window_new(GTK_WINDOW_TOPLEVEL);
  1332.    gtk_window_set_policy(GTK_WINDOW(dlg), TRUE, TRUE, FALSE);
  1333.    gtk_widget_realize(dlg);
  1334.  
  1335.    main_set_title(NULL);
  1336.    gimp_help_connect_help_accel (dlg, gimp_standard_help_func, "filters/imagemap.html");
  1337.  
  1338.    gtk_window_set_position(GTK_WINDOW(dlg), GTK_WIN_POS_MOUSE);
  1339.    gtk_signal_connect(GTK_OBJECT(dlg), "destroy",
  1340.               (GtkSignalFunc) close_callback, NULL);
  1341.    gtk_signal_connect(GTK_OBJECT(dlg), "key_press_event", 
  1342.               (GtkSignalFunc) key_press_cb, NULL);
  1343.    gtk_signal_connect(GTK_OBJECT(dlg), "key_release_event", 
  1344.               (GtkSignalFunc) key_release_cb, NULL);
  1345.  
  1346.    main_vbox = gtk_vbox_new(FALSE, 1);
  1347.    gtk_container_set_border_width(GTK_CONTAINER(main_vbox), 1);
  1348.    gtk_container_add(GTK_CONTAINER(dlg), main_vbox);
  1349.    gtk_widget_show(main_vbox);
  1350.  
  1351.    /* Create menu */
  1352.    menu = make_menu(main_vbox, dlg);
  1353.    menu_set_open_command(menu, factory_file_open_dialog);
  1354.    menu_set_save_command(menu, factory_save);
  1355.    menu_set_save_as_command(menu, factory_save_as);
  1356.    menu_set_preferences_command(menu, factory_preferences_dialog);
  1357.    menu_set_close_command(menu, factory_close);
  1358.    menu_set_quit_command(menu, factory_quit);
  1359.    menu_set_undo_command(menu, factory_undo);
  1360.    menu_set_redo_command(menu, factory_redo);
  1361.    menu_set_cut_command(menu, factory_cut);
  1362.    menu_set_copy_command(menu, factory_copy);
  1363.    menu_set_paste_command(menu, factory_paste);
  1364.    menu_set_select_all_command(menu, factory_select_all);
  1365.    menu_set_clear_command(menu, factory_clear);
  1366.    menu_set_edit_erea_info_command(menu, factory_edit);
  1367.    menu_set_area_list_command(menu, factory_toggle_area_list);
  1368.    menu_set_source_command(menu, factory_source_dialog);
  1369.    menu_set_color_command(menu, factory_preview_color);
  1370.    menu_set_gray_command(menu, factory_preview_gray);
  1371.    menu_set_zoom_in_command(menu, factory_menu_zoom_in);
  1372.    menu_set_zoom_out_command(menu, factory_menu_zoom_out);
  1373.    menu_set_edit_map_info_command(menu, factory_settings_dialog);
  1374.    menu_set_grid_settings_command(menu, factory_grid_settings_dialog);
  1375.    menu_set_create_guides_command(menu, factory_create_guides_dialog);
  1376.    menu_set_about_command(menu, factory_about_dialog);
  1377.  
  1378.    /* Create popup */
  1379.    popup = create_main_popup_menu();
  1380.    popup_set_zoom_in_command(popup, factory_zoom_in);
  1381.    popup_set_zoom_out_command(popup, factory_zoom_out);
  1382.    popup_set_edit_map_info_command(popup, factory_settings_dialog);
  1383.    popup_set_grid_settings_command(popup, factory_grid_settings_dialog);
  1384.    popup_set_create_guides_command(popup, factory_create_guides_dialog);
  1385.    popup_set_paste_command(popup, factory_paste);
  1386.  
  1387.    /* Create toolbar */
  1388.    _toolbar = make_toolbar(main_vbox, dlg);
  1389.    toolbar_set_open_command(_toolbar, factory_file_open_dialog);
  1390.    toolbar_set_save_command(_toolbar, factory_save);
  1391.    toolbar_set_preferences_command(_toolbar, factory_preferences_dialog);
  1392.    toolbar_set_undo_command(_toolbar, factory_undo);
  1393.    toolbar_set_redo_command(_toolbar, factory_redo);
  1394.    toolbar_set_cut_command(_toolbar, factory_cut);
  1395.    toolbar_set_copy_command(_toolbar, factory_copy);
  1396.    toolbar_set_paste_command(_toolbar, factory_paste);
  1397.    toolbar_set_zoom_in_command(_toolbar, factory_zoom_in);
  1398.    toolbar_set_zoom_out_command(_toolbar, factory_zoom_out);
  1399.    toolbar_set_edit_map_info_command(_toolbar, factory_settings_dialog);
  1400.    toolbar_set_move_to_front_command(_toolbar, factory_move_to_front);
  1401.    toolbar_set_send_to_back_command(_toolbar, factory_send_to_back);
  1402.    toolbar_set_grid_command(_toolbar, factory_toolbar_grid);
  1403.  
  1404.    /*  Dialog area  */
  1405.    hbox = gtk_hbox_new(FALSE, 1);
  1406.    gtk_container_add(GTK_CONTAINER(main_vbox), hbox);
  1407.    gtk_widget_show(hbox);
  1408.  
  1409.    tools = make_tools(dlg);
  1410.    selection_set_delete_command(tools, factory_clear);
  1411.    selection_set_edit_command(tools, factory_edit);
  1412.    gtk_box_pack_start(GTK_BOX(hbox), tools->container, FALSE, FALSE, 0);
  1413.  
  1414.    _preview = make_preview(drawable);
  1415.    add_preview_motion_event(_preview, (GtkSignalFunc) preview_move);
  1416.    add_enter_notify_event(_preview, (GtkSignalFunc) preview_enter);
  1417.    add_leave_notify_event(_preview, (GtkSignalFunc) preview_leave);
  1418.    add_preview_button_press_event(_preview, (GtkSignalFunc) button_press);
  1419.    gtk_container_add(GTK_CONTAINER(hbox), _preview->window);
  1420.  
  1421.    object_list_add_geometry_cb(_shapes, geometry_changed, NULL);
  1422.    object_list_add_update_cb(_shapes, data_changed, NULL);
  1423.    object_list_add_add_cb(_shapes, data_changed, NULL);
  1424.    object_list_add_remove_cb(_shapes, data_changed, NULL);
  1425.    object_list_add_move_cb(_shapes, data_changed, NULL);
  1426.    object_list_add_select_cb(_shapes, data_selected, NULL);
  1427.  
  1428.    /* Selection */
  1429.    _selection = make_selection(dlg, _shapes);
  1430.    selection_set_move_up_command(_selection, factory_move_up);
  1431.    selection_set_move_down_command(_selection, factory_move_down);
  1432.    selection_set_delete_command(_selection, factory_clear);
  1433.    selection_set_edit_command(_selection, factory_edit);
  1434.    gtk_box_pack_start(GTK_BOX(hbox), _selection->container, FALSE, FALSE, 0);
  1435.  
  1436.    _statusbar = make_statusbar(main_vbox, dlg);
  1437.    statusbar_set_zoom(_statusbar, 1);
  1438.  
  1439.    clear_map_info();
  1440.  
  1441.    gtk_widget_show(dlg);
  1442.  
  1443.    _mru = mru_create();
  1444.    init_preferences();
  1445.    if (!mru_empty(_mru))
  1446.       menu_build_mru_items(_mru);
  1447.  
  1448.    gtk_main();
  1449.    gdk_flush();
  1450.    
  1451.    return run_flag;
  1452. }
  1453.