home *** CD-ROM | disk | FTP | other *** search
/ PC Pro 2002 April / pcpro0402.iso / essentials / graphics / Gimp / gimp-src-20001226.exe / src / gimp / app / gdisplay.c < prev    next >
Encoding:
C/C++ Source or Header  |  2000-12-25  |  60.8 KB  |  2,420 lines

  1. /* The GIMP -- an image manipulation program
  2.  * Copyright (C) 1995 Spencer Kimball and Peter Mattis
  3.  *
  4.  * This program is free software; you can redistribute it and/or modify
  5.  * it under the terms of the GNU General Public License as published by
  6.  * the Free Software Foundation; either version 2 of the License, or
  7.  * (at your option) any later version.
  8.  *
  9.  * This program is distributed in the hope that it will be useful,
  10.  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  11.  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  12.  * GNU General Public License for more details.
  13.  *
  14.  * You should have received a copy of the GNU General Public License
  15.  * along with this program; if not, write to the Free Software
  16.  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
  17.  */
  18.  
  19. #include "config.h"
  20.  
  21. #include <stdlib.h>
  22. #include <string.h>
  23.  
  24. #include <gtk/gtk.h>
  25.  
  26. #include "apptypes.h"
  27.  
  28. #include "appenv.h"
  29. #include "colormaps.h"
  30. #include "cursorutil.h"
  31. #include "disp_callbacks.h"
  32. #include "drawable.h"
  33. #include "draw_core.h"
  34. #include "gdisplay.h"
  35. #include "gdisplayP.h"
  36. #include "gdisplay_ops.h"
  37. #include "gimage_mask.h"
  38. #include "gimpcontext.h"
  39. #include "gimprc.h"
  40. #include "gximage.h"
  41. #include "image_render.h"
  42. #include "info_window.h"
  43. #include "interface.h"
  44. #include "lc_dialog.h"
  45. #include "menus.h"
  46. #include "nav_window.h"
  47. #include "plug_in.h"
  48. #include "qmask.h"
  49. #include "scale.h"
  50. #include "scroll.h"
  51. #include "tools.h"
  52. #include "undo.h"
  53.  
  54. #ifdef DISPLAY_FILTERS
  55. #include "gdisplay_color.h"
  56. #endif /* DISPLAY_FILTERS */
  57.  
  58. #include "bezier_selectP.h"
  59. #include "layer_pvt.h"            /* ick. (not alone either) */
  60.  
  61. #include "libgimp/gimpmath.h"
  62.  
  63. #include "libgimp/gimpintl.h"
  64.  
  65.  
  66. #define OVERHEAD          25  /*  in units of pixel area  */
  67. #define EPSILON           5
  68.  
  69. #define MAX_TITLE_BUF 256
  70.  
  71. /* variable declarations */
  72. GSList *               display_list = NULL;
  73. static gint            display_num  = 1;
  74. static GdkCursorType   default_gdisplay_cursor = GDK_TOP_LEFT_ARROW;
  75.  
  76. /*  Local functions  */
  77. static void       gdisplay_format_title       (GDisplay *, char *, int);
  78. static void       gdisplay_delete             (GDisplay *);
  79. static GSList *   gdisplay_free_area_list     (GSList *);
  80. static GSList *   gdisplay_process_area_list  (GSList *, GimpArea *);
  81. static void       gdisplay_add_update_area    (GDisplay *, int, int, int, int);
  82. static void       gdisplay_add_display_area   (GDisplay *, int, int, int, int);
  83. static void       gdisplay_paint_area         (GDisplay *, int, int, int, int);
  84. static void      gdisplay_draw_cursor          (GDisplay *);
  85. static void       gdisplay_display_area       (GDisplay *, int, int, int, int);
  86. static guint      gdisplay_hash               (GDisplay *);
  87. static void       gdisplay_cleandirty_handler (GimpImage *, void *);
  88.  
  89.  
  90. static GHashTable *display_ht = NULL;
  91.  
  92. /* FIXME: GDisplays really need to be GtkObjects */
  93.  
  94. GDisplay*
  95. gdisplay_new (GimpImage *gimage,
  96.           guint      scale)
  97. {
  98.   GDisplay *gdisp;
  99.   gchar title [MAX_TITLE_BUF];
  100.  
  101.   /*  If there isn't an interface, never create a gdisplay  */
  102.   if (no_interface)
  103.     return NULL;
  104.  
  105.   /*
  106.    *  Set all GDisplay parameters...
  107.    */
  108.   gdisp = g_new (GDisplay, 1);
  109.  
  110.   gdisp->offset_x           = 0;
  111.   gdisp->offset_y           = 0;
  112.   gdisp->scale              = scale;
  113.   gdisp->dot_for_dot        = default_dot_for_dot;
  114.   gdisp->gimage             = gimage;
  115.   gdisp->window_info_dialog = NULL;
  116.   gdisp->window_nav_dialog  = NULL;
  117.   gdisp->nav_popup          = NULL;
  118.   gdisp->depth              = g_visual->depth;
  119.   gdisp->select             = NULL;
  120.   gdisp->ID                 = display_num++;
  121.   gdisp->instance           = gimage->instance_count;
  122.   gdisp->update_areas       = NULL;
  123.   gdisp->display_areas      = NULL;
  124.   gdisp->disp_xoffset       = 0;
  125.   gdisp->disp_yoffset       = 0;
  126.   gdisp->current_cursor     = (GdkCursorType) -1;
  127.   gdisp->cursor_tool        = TOOL_TYPE_NONE;
  128.   gdisp->cursor_modifier    = CURSOR_MODIFIER_NONE;
  129.   gdisp->toggle_cursor      = FALSE;
  130.   gdisp->draw_guides        = TRUE;
  131.   gdisp->snap_to_guides     = TRUE;
  132.  
  133.   gdisp->draw_cursor           = FALSE;
  134.   gdisp->proximity             = FALSE;
  135.   gdisp->have_cursor           = FALSE;
  136.   gdisp->using_override_cursor = FALSE;
  137.  
  138.   gdisp->progressid = FALSE;
  139.  
  140.   gdisp->idle_render.idleid       = -1;
  141.   /*gdisp->idle_render.handlerid = -1;*/
  142.   gdisp->idle_render.update_areas = NULL;
  143.   gdisp->idle_render.active       = FALSE;
  144.  
  145. #ifdef DISPLAY_FILTERS
  146.   gdisp->cd_list = NULL;
  147.   gdisp->cd_ui   = NULL;
  148. #endif /* DISPLAY_FILTERS */
  149.  
  150.   gdisp->warning_dialog = NULL;
  151.  
  152.   /* format the title */
  153.   gdisplay_format_title (gdisp, title, MAX_TITLE_BUF);
  154.  
  155.   /*  add the new display to the list so that it isn't lost  */
  156.   display_list = g_slist_append (display_list, (void *) gdisp);
  157.  
  158.   /*  create the shell for the image  */
  159.   create_display_shell (gdisp, gimage->width, gimage->height,
  160.             title, gimage_base_type (gimage));
  161.  
  162.   /* update the title to correct the initially displayed scale */
  163.   gdisplay_update_title (gdisp);
  164.  
  165.   /*  set the gdisplay colormap type and install the appropriate colormap  */
  166.   gdisp->color_type = (gimage_base_type (gimage) == GRAY) ? GRAY : RGB;
  167.  
  168.   /* set the qmask buttons */
  169.   qmask_buttons_update(gdisp);
  170.  
  171.   /*  set the user data  */
  172.   if (!display_ht)
  173.     display_ht = g_hash_table_new ((GHashFunc) gdisplay_hash, NULL);
  174.  
  175.   g_hash_table_insert (display_ht, gdisp->shell, gdisp);
  176.   g_hash_table_insert (display_ht, gdisp->canvas, gdisp);
  177.  
  178.   /*  set the current tool cursor  */
  179.   gdisplay_install_tool_cursor (gdisp, default_gdisplay_cursor,
  180.                 TOOL_TYPE_NONE,
  181.                 CURSOR_MODIFIER_NONE,
  182.                 FALSE);
  183.  
  184.   gimage->instance_count++;   /* this is obsolete */
  185.   gimage->disp_count++;
  186.  
  187.   lc_dialog_preview_update(gimage);
  188.  
  189.   /* We're interested in clean and dirty signals so we can update the
  190.    * title if need be. */
  191.   gtk_signal_connect (GTK_OBJECT (gimage), "dirty",
  192.               GTK_SIGNAL_FUNC (gdisplay_cleandirty_handler), gdisp);
  193.   gtk_signal_connect (GTK_OBJECT (gimage), "clean",
  194.               GTK_SIGNAL_FUNC (gdisplay_cleandirty_handler), gdisp);
  195.  
  196.   return gdisp;
  197. }
  198.  
  199.  
  200. static int print (char *, int, int, const char *, ...) G_GNUC_PRINTF (4, 5);
  201.  
  202. static int
  203. print (char *buf, int len, int start, const char *fmt, ...)
  204. {
  205.   va_list args;
  206.   int printed;
  207.  
  208.   va_start (args, fmt);
  209.  
  210.   printed = g_vsnprintf (buf + start, len - start, fmt, args);
  211.   if (printed < 0)
  212.     printed = len - start;
  213.  
  214.   va_end (args);
  215.  
  216.   return printed;
  217. }
  218.  
  219. static void
  220. gdisplay_format_title (GDisplay *gdisp,
  221.                gchar    *title,
  222.                gint      title_len)
  223. {
  224.   GimpImage *gimage;
  225.   char *image_type_str;
  226.   int empty;
  227.   int i;
  228.   char *format;
  229.  
  230.   gimage = gdisp->gimage;
  231.  
  232.   empty = gimage_is_empty (gimage);
  233.  
  234.   switch (gimage_base_type (gimage))
  235.     {
  236.     case RGB:
  237.       image_type_str = (empty) ? _("RGB-empty") : _("RGB");
  238.       break;
  239.     case GRAY:
  240.       image_type_str = (empty) ? _("grayscale-empty") : _("grayscale");
  241.       break;
  242.     case INDEXED:
  243.       image_type_str = (empty) ? _("indexed-empty") : _("indexed");
  244.       break;
  245.     default:
  246.       image_type_str = NULL;
  247.     }
  248.  
  249.   i = 0;
  250.   format = image_title_format;
  251.  
  252.   while (i < title_len && *format)
  253.   {
  254.     switch (*format) {
  255.     case '%':
  256.       format++;
  257.       switch (*format) {
  258.       case 0:
  259.       g_warning ("image-title-format string ended within %%-sequence");
  260.       break;
  261.  
  262.       case '%':
  263.       title[i++] = '%';
  264.       break;
  265.  
  266.       case 'f': /* pruned filename */
  267.       i += print (title, title_len, i,
  268.               "%s", g_basename (gimage_filename (gimage)));
  269.       break;
  270.  
  271.       case 'F': /* full filename */
  272.       i += print (title, title_len, i, "%s", gimage_filename (gimage));
  273.       break;
  274.  
  275.       case 'p': /* PDB id */
  276.       i += print (title, title_len, i, "%d", pdb_image_to_id (gimage));
  277.       break;
  278.  
  279.       case 'i': /* instance */
  280.       i += print (title, title_len, i, "%d", gdisp->instance);
  281.       break;
  282.  
  283.       case 't': /* type */
  284.       i += print (title, title_len, i, "%s", image_type_str);
  285.       break;
  286.  
  287.       case 's': /* user source zoom factor */
  288.       i += print (title, title_len, i, "%d", SCALESRC (gdisp));
  289.       break;
  290.  
  291.       case 'd': /* user destination zoom factor */
  292.       i += print (title, title_len, i, "%d", SCALEDEST (gdisp));
  293.       break;
  294.  
  295.       case 'z': /* user zoom factor (percentage) */
  296.       i += print (title, title_len, i,
  297.               "%d", 100 * SCALEDEST (gdisp) / SCALESRC (gdisp));
  298.       break;
  299.  
  300.       case 'D': /* dirty flag */
  301.       if (format[1] == 0)
  302.       {
  303.           g_warning("image-title-format string ended within %%D-sequence");
  304.           break;
  305.       }
  306.       if (gimage->dirty)
  307.           title[i++] = format[1];
  308.       format++;
  309.       break;
  310.  
  311.       /* Other cool things to be added:
  312.        * %m = memory used by picture
  313.        * some kind of resolution / image size thing
  314.        * people seem to want to know the active layer name
  315.        */
  316.  
  317.       default:
  318.       g_warning ("image-title-format contains unknown format sequence '%%%c'", *format);
  319.       break;
  320.       }
  321.       break;
  322.  
  323.     default:
  324.       title[i++] = *format;
  325.       break;
  326.     }
  327.  
  328.     format++;
  329.   }
  330.  
  331.   title[MIN(i, title_len-1)] = 0;
  332. }
  333.  
  334.  
  335. static void
  336. gdisplay_delete (GDisplay *gdisp)
  337. {
  338.   g_hash_table_remove (display_ht, gdisp->shell);
  339.   g_hash_table_remove (display_ht, gdisp->canvas);
  340.  
  341.   /*  stop any active tool  */
  342.   active_tool_control (HALT, (void *) gdisp);
  343.  
  344.   /*  clear out the pointer to this gdisp from the active tool  */
  345.   if (active_tool &&
  346.       active_tool->gdisp_ptr == gdisp)
  347.     {
  348.       active_tool->drawable = NULL;
  349.       active_tool->gdisp_ptr = NULL;
  350.     }
  351.  
  352.   /*  free the selection structure  */
  353.   selection_free (gdisp->select);
  354.  
  355.   /* If this gdisplay was idlerendering at the time when it was deleted,
  356.      deactivate the idlerendering thread before deletion! */
  357.   if (gdisp->idle_render.active)
  358.     {
  359.       gtk_idle_remove (gdisp->idle_render.idleid);
  360.       gdisp->idle_render.active = FALSE;
  361.     }
  362.  
  363. #ifdef DISPLAY_FILTERS
  364.   /* detach any color displays */
  365.   gdisplay_color_detach_all (gdisp);
  366. #endif /* DISPLAY_FILTERS */
  367.  
  368.   /* get rid of signals handled by this display */
  369.   gtk_signal_disconnect_by_data (GTK_OBJECT (gdisp->gimage), gdisp);
  370.  
  371.   if (gdisp->scroll_gc)
  372.     gdk_gc_destroy (gdisp->scroll_gc);
  373.  
  374.   /*  free the area lists  */
  375.   gdisplay_free_area_list (gdisp->update_areas);
  376.   gdisplay_free_area_list (gdisp->display_areas);
  377.  
  378.   gdisplay_free_area_list (gdisp->idle_render.update_areas);
  379.  
  380.   /*  remove dialogs before removing the image because they may want to
  381.    *  disconnect from image signals
  382.    */
  383.  
  384.   /*  insure that if a window information dialog exists, it is removed  */
  385.   info_window_free (gdisp->window_info_dialog);
  386.  
  387.   /* Remove navigation dialog */
  388.   nav_window_free (gdisp, gdisp->window_nav_dialog);
  389.  
  390.   /*  free the gimage  */
  391.   gdisp->gimage->disp_count--;
  392.   gimage_delete (gdisp->gimage);
  393.  
  394.   if (gdisp->nav_popup)
  395.     nav_popup_free (gdisp->nav_popup);
  396.  
  397.   gtk_widget_unref (gdisp->shell);
  398.  
  399.   g_free (gdisp);
  400. }
  401.  
  402.  
  403. static GSList *
  404. gdisplay_free_area_list (GSList *list)
  405. {
  406.   GSList *l = list;
  407.   GimpArea *ga;
  408.  
  409.   while (l)
  410.     {
  411.       /*  free the data  */
  412.       ga = (GimpArea *) l->data;
  413.       g_free (ga);
  414.  
  415.       l = g_slist_next (l);
  416.     }
  417.  
  418.   if (list)
  419.     g_slist_free (list);
  420.  
  421.   return NULL;
  422. }
  423.  
  424.  
  425. /*
  426.  *  As far as I can tell, this function takes a GimpArea and unifies it with
  427.  *  an existing list of GimpAreas, trying to avoid overdraw.  [adam]
  428.  */
  429. static GSList *
  430. gdisplay_process_area_list (GSList *list,
  431.                 GimpArea  *ga1)
  432. {
  433.   GSList *new_list;
  434.   GSList *l = list;
  435.   gint area1, area2, area3;
  436.   GimpArea *ga2;
  437.  
  438.   /*  start new list off  */
  439.   new_list = g_slist_prepend (NULL, ga1);
  440.   while (l)
  441.     {
  442.       /*  process the data  */
  443.       ga2 = (GimpArea *) l->data;
  444.       area1 = (ga1->x2 - ga1->x1) * (ga1->y2 - ga1->y1) + OVERHEAD;
  445.       area2 = (ga2->x2 - ga2->x1) * (ga2->y2 - ga2->y1) + OVERHEAD;
  446.       area3 = (MAX (ga2->x2, ga1->x2) - MIN (ga2->x1, ga1->x1)) *
  447.     (MAX (ga2->y2, ga1->y2) - MIN (ga2->y1, ga1->y1)) + OVERHEAD;
  448.  
  449.       if ((area1 + area2) < area3)
  450.     new_list = g_slist_prepend (new_list, ga2);
  451.       else
  452.     {
  453.       ga1->x1 = MIN (ga1->x1, ga2->x1);
  454.       ga1->y1 = MIN (ga1->y1, ga2->y1);
  455.       ga1->x2 = MAX (ga1->x2, ga2->x2);
  456.       ga1->y2 = MAX (ga1->y2, ga2->y2);
  457.  
  458.       g_free (ga2);
  459.     }
  460.  
  461.       l = g_slist_next (l);
  462.     }
  463.  
  464.   if (list)
  465.     g_slist_free (list);
  466.  
  467.   return new_list;
  468. }
  469.  
  470.  
  471. static int
  472. idle_render_next_area (GDisplay *gdisp)
  473. {
  474.   GimpArea  *ga;
  475.   GSList *list;
  476.   
  477.   list = gdisp->idle_render.update_areas;
  478.  
  479.   if (list == NULL)
  480.     {
  481.       return (-1);
  482.     }
  483.  
  484.   ga = (GimpArea*) list->data;
  485.  
  486.   gdisp->idle_render.update_areas =
  487.     g_slist_remove (gdisp->idle_render.update_areas, ga);
  488.  
  489.   gdisp->idle_render.x = gdisp->idle_render.basex = ga->x1;
  490.   gdisp->idle_render.y = gdisp->idle_render.basey = ga->y1;
  491.   gdisp->idle_render.width = ga->x2 - ga->x1;
  492.   gdisp->idle_render.height = ga->y2 - ga->y1;
  493.  
  494.   g_free (ga);
  495.  
  496.   return (0);
  497. }
  498.  
  499.  
  500. /* Unless specified otherwise, display re-rendering is organised
  501.  by IdleRender, which amalgamates areas to be re-rendered and
  502.  breaks them into bite-sized chunks which are chewed on in a low-
  503.  priority idle thread.  This greatly improves responsiveness for
  504.  many GIMP operations.  -- Adam */
  505. static int
  506. idlerender_callback (gpointer data)
  507. {
  508.   const gint CHUNK_WIDTH = 256;
  509.   const gint CHUNK_HEIGHT = 128;
  510.   gint workx, worky, workw, workh;
  511.   GDisplay* gdisp = data;
  512.  
  513.   workw = CHUNK_WIDTH;
  514.   workh = CHUNK_HEIGHT;
  515.   workx = gdisp->idle_render.x;
  516.   worky = gdisp->idle_render.y;
  517.  
  518.   if (workx+workw > gdisp->idle_render.basex+gdisp->idle_render.width)
  519.     {
  520.       workw = gdisp->idle_render.basex+gdisp->idle_render.width-workx;
  521.     }
  522.  
  523.   if (worky+workh > gdisp->idle_render.basey+gdisp->idle_render.height)
  524.     {
  525.       workh = gdisp->idle_render.basey+gdisp->idle_render.height-worky;
  526.     }  
  527.  
  528.   gdisplay_paint_area (gdisp, workx, worky,
  529.                workw, workh);
  530.   gdisplay_flush_displays_only (gdisp);
  531.  
  532.   gdisp->idle_render.x += CHUNK_WIDTH;
  533.   if (gdisp->idle_render.x >= gdisp->idle_render.basex+gdisp->idle_render.width)
  534.     {
  535.       gdisp->idle_render.x = gdisp->idle_render.basex;
  536.       gdisp->idle_render.y += CHUNK_HEIGHT;
  537.       if (gdisp->idle_render.y >=
  538.       gdisp->idle_render.basey + gdisp->idle_render.height)
  539.     {
  540.       if (idle_render_next_area(gdisp) != 0)
  541.         {
  542.           /* FINISHED */
  543.           gdisp->idle_render.active = FALSE;
  544.  
  545.           return 0;
  546.         }
  547.     }
  548.     }
  549.  
  550.   /* Still work to do. */
  551.   return 1;
  552. }
  553.  
  554.  
  555. static void
  556. gdisplay_idlerender_init (GDisplay *gdisp)
  557. {
  558.   GSList *list;
  559.   GimpArea  *ga, *new_ga;
  560.  
  561. /*  gdisplay_install_override_cursor(gdisp, GDK_CIRCLE); */
  562.  
  563.   /* We need to merge the IdleRender's and the GDisplay's update_areas list
  564.      to keep track of which of the updates have been flushed and hence need
  565.      to be drawn.   */
  566.   list = gdisp->update_areas;
  567.   while (list)
  568.     {
  569.       ga = (GimpArea *) list->data;
  570.       new_ga = g_malloc (sizeof(GimpArea));
  571.       memcpy (new_ga, ga, sizeof(GimpArea));
  572.  
  573.       gdisp->idle_render.update_areas =
  574.     gdisplay_process_area_list (gdisp->idle_render.update_areas, new_ga);
  575.  
  576.       list = g_slist_next (list);
  577.     }
  578.  
  579.   /* If an idlerender was already running, merge the remainder of its
  580.      unrendered area with the update_areas list, and make it start work
  581.      on the next unrendered area in the list. */
  582.   if (gdisp->idle_render.active)
  583.     {
  584.       new_ga = g_malloc (sizeof(GimpArea));
  585.       new_ga->x1 = gdisp->idle_render.basex;
  586.       new_ga->y1 = gdisp->idle_render.y;
  587.       new_ga->x2 = gdisp->idle_render.basex + gdisp->idle_render.width;
  588.       new_ga->y2 = gdisp->idle_render.y +
  589.     (gdisp->idle_render.height -
  590.      (gdisp->idle_render.y - gdisp->idle_render.basey)
  591.      );
  592.       
  593.       gdisp->idle_render.update_areas =
  594.     gdisplay_process_area_list (gdisp->idle_render.update_areas, new_ga);
  595.  
  596.       idle_render_next_area(gdisp);
  597.     }
  598.   else
  599.     {
  600.       if (gdisp->idle_render.update_areas == NULL)
  601.     {
  602.       g_warning ("Wanted to start idlerender thread with no update_areas. (+memleak)");
  603.       return;
  604.     }
  605.       
  606.       idle_render_next_area(gdisp);
  607.       
  608.       gdisp->idle_render.active = TRUE;
  609.       
  610.       gdisp->idle_render.idleid =
  611.     gtk_idle_add_priority (GTK_PRIORITY_LOW,
  612.                    idlerender_callback, gdisp);
  613.     }
  614.  
  615.   /* Caller frees gdisp->update_areas */
  616. }
  617.  
  618.  
  619. void
  620. gdisplay_flush_displays_only (GDisplay *gdisp)
  621. {
  622.   GSList *list;
  623.   GimpArea  *ga;
  624.  
  625.   list = gdisp->display_areas;
  626.  
  627.   if (list)
  628.     {
  629.       /*  stop the currently active tool  */
  630.       active_tool_control (PAUSE, (void *) gdisp);
  631.  
  632.       while (list)
  633.     {
  634.       /*  Paint the area specified by the GimpArea  */
  635.       ga = (GimpArea *) list->data;
  636.       gdisplay_display_area (gdisp, ga->x1, ga->y1,
  637.                  (ga->x2 - ga->x1), (ga->y2 - ga->y1));
  638.  
  639.       list = g_slist_next (list);
  640.     }
  641.       /*  Free the update lists  */
  642.       gdisp->display_areas = gdisplay_free_area_list (gdisp->display_areas);
  643.  
  644.       /* draw the guides */
  645.       gdisplay_draw_guides (gdisp);
  646.  
  647.       /* and the cursor (if we have a software cursor */
  648.       if (gdisp->have_cursor)
  649.     gdisplay_draw_cursor (gdisp);
  650.  
  651.       /* restart (and recalculate) the selection boundaries */
  652.       selection_start (gdisp->select, TRUE);
  653.  
  654.       /* start the currently active tool */
  655.       active_tool_control (RESUME, (void *) gdisp);
  656.     }  
  657. }
  658.  
  659.  
  660. static void
  661. gdisplay_flush_whenever (GDisplay *gdisp, 
  662.              gboolean  now)
  663. {
  664.   GSList *list;
  665.   GimpArea  *ga;
  666.  
  667.   /*  Flush the items in the displays and updates lists -
  668.    *  but only if gdisplay has been mapped and exposed
  669.    */
  670.   if (!gdisp->select)
  671.     return;
  672.  
  673.   /*  First the updates...  */
  674.   if (now)
  675.     { /* Synchronous */
  676.       list = gdisp->update_areas;
  677.       while (list)
  678.     {
  679.       /*  Paint the area specified by the GimpArea  */
  680.       ga = (GimpArea *) list->data;
  681.       
  682.       if ((ga->x1 != ga->x2) && (ga->y1 != ga->y2))
  683.         {
  684.           gdisplay_paint_area (gdisp, ga->x1, ga->y1,
  685.                    (ga->x2 - ga->x1), (ga->y2 - ga->y1));
  686.         }
  687.       
  688.       list = g_slist_next (list);
  689.     }
  690.     }
  691.   else
  692.     { /* Asynchronous */
  693.       if (gdisp->update_areas)
  694.     gdisplay_idlerender_init (gdisp);
  695.     }
  696.   /*  Free the update lists  */
  697.   gdisp->update_areas = gdisplay_free_area_list (gdisp->update_areas);
  698.  
  699.   /*  Next the displays...  */
  700.   gdisplay_flush_displays_only (gdisp);
  701.  
  702.   /*  update the gdisplay's info dialog  */
  703.   info_window_update (gdisp);
  704.  
  705.   /* update the gdisplay's qmask buttons */
  706.   qmask_buttons_update (gdisp);
  707.  
  708.   /*  ensure the consistency of the tear-off menus  */
  709.   if (!now && gimp_context_get_display (gimp_context_get_user ()) == gdisp)
  710.     gdisplay_set_menu_sensitivity (gdisp);
  711. }
  712.  
  713. void
  714. gdisplay_flush (GDisplay *gdisp)
  715. {
  716.   /* Redraw on idle time */
  717.   gdisplay_flush_whenever (gdisp, FALSE);
  718. }
  719.  
  720. void
  721. gdisplay_flush_now (GDisplay *gdisp)
  722. {
  723.   /* Redraw NOW */
  724.   gdisplay_flush_whenever (gdisp, TRUE);
  725. }
  726.  
  727. /* Force all gdisplays to finish their idlerender projection */
  728. void 
  729. gdisplays_finish_draw (void)
  730. {
  731.   GSList *list = display_list;
  732.   GDisplay* gdisp;
  733.  
  734.   while (list)
  735.     {
  736.       gdisp = (GDisplay*) list->data;
  737.       
  738.       if (gdisp->idle_render.active)
  739.     {
  740.       gtk_idle_remove (gdisp->idle_render.idleid);
  741.       while (idlerender_callback(gdisp));
  742.     }
  743.       list = g_slist_next (list);
  744.     }
  745. }
  746.  
  747. void
  748. gdisplay_draw_guides (GDisplay *gdisp)
  749. {
  750.   GList *tmp_list;
  751.   Guide *guide;
  752.  
  753.   if (gdisp->draw_guides)
  754.     {
  755.       tmp_list = gdisp->gimage->guides;
  756.       while (tmp_list)
  757.     {
  758.       guide = tmp_list->data;
  759.       tmp_list = tmp_list->next;
  760.       gdisplay_draw_guide (gdisp, guide, FALSE);
  761.     }
  762.     }
  763. }
  764.  
  765. void
  766. gdisplay_draw_guide (GDisplay *gdisp,
  767.              Guide    *guide,
  768.              gboolean  active)
  769. {
  770.   static GdkGC *normal_hgc = NULL;
  771.   static GdkGC *active_hgc = NULL;
  772.   static GdkGC *normal_vgc = NULL;
  773.   static GdkGC *active_vgc = NULL;
  774.   static int initialize = TRUE;
  775.   gint x1, x2;
  776.   gint y1, y2;
  777.   gint w, h;
  778.   gint x, y;
  779.  
  780.   if (guide->position < 0)
  781.     return;
  782.  
  783.   if (initialize)
  784.     {
  785.       GdkGCValues values;
  786.       const char stipple[] =
  787.       {
  788.     0xF0,    /*  ####----  */
  789.     0xE1,    /*  ###----#  */
  790.     0xC3,    /*  ##----##  */
  791.     0x87,    /*  #----###  */
  792.     0x0F,    /*  ----####  */
  793.     0x1E,    /*  ---####-  */
  794.     0x3C,    /*  --####--  */
  795.     0x78,    /*  -####---  */
  796.       };
  797.  
  798.       initialize = FALSE;
  799.  
  800.       values.foreground.pixel = gdisplay_black_pixel (gdisp);
  801.       values.background.pixel = g_normal_guide_pixel;
  802.       values.fill = GDK_OPAQUE_STIPPLED;
  803.       values.stipple = gdk_bitmap_create_from_data (gdisp->canvas->window,
  804.                             (char*) stipple, 8, 1);
  805.       normal_hgc = gdk_gc_new_with_values (gdisp->canvas->window, &values,
  806.                       GDK_GC_FOREGROUND |
  807.                       GDK_GC_BACKGROUND |
  808.                       GDK_GC_FILL |
  809.                       GDK_GC_STIPPLE);
  810.  
  811.       values.background.pixel = g_active_guide_pixel;
  812.       active_hgc = gdk_gc_new_with_values (gdisp->canvas->window, &values,
  813.                        GDK_GC_FOREGROUND |
  814.                        GDK_GC_BACKGROUND |
  815.                        GDK_GC_FILL |
  816.                        GDK_GC_STIPPLE);
  817.  
  818.       values.foreground.pixel = gdisplay_black_pixel (gdisp);
  819.       values.background.pixel = g_normal_guide_pixel;
  820.       values.fill = GDK_OPAQUE_STIPPLED;
  821.       values.stipple = gdk_bitmap_create_from_data (gdisp->canvas->window,
  822.                             (char*) stipple, 1, 8);
  823.       normal_vgc = gdk_gc_new_with_values (gdisp->canvas->window, &values,
  824.                       GDK_GC_FOREGROUND |
  825.                       GDK_GC_BACKGROUND |
  826.                       GDK_GC_FILL |
  827.                       GDK_GC_STIPPLE);
  828.  
  829.       values.background.pixel = g_active_guide_pixel;
  830.       active_vgc = gdk_gc_new_with_values (gdisp->canvas->window, &values,
  831.                        GDK_GC_FOREGROUND |
  832.                        GDK_GC_BACKGROUND |
  833.                        GDK_GC_FILL |
  834.                        GDK_GC_STIPPLE);
  835.     }
  836.  
  837.   gdisplay_transform_coords (gdisp, 0, 0, &x1, &y1, FALSE);
  838.   gdisplay_transform_coords (gdisp,
  839.                  gdisp->gimage->width, gdisp->gimage->height,
  840.                  &x2, &y2, FALSE);
  841.   gdk_window_get_size (gdisp->canvas->window, &w, &h);
  842.  
  843.   if (x1 < 0) x1 = 0;
  844.   if (y1 < 0) y1 = 0;
  845.   if (x2 > w) x2 = w;
  846.   if (y2 > h) y2 = h;
  847.  
  848.   if (guide->orientation == ORIENTATION_HORIZONTAL)
  849.     {
  850.       gdisplay_transform_coords (gdisp, 0, guide->position, &x, &y, FALSE);
  851.  
  852.       if (active)
  853.     gdk_draw_line (gdisp->canvas->window, active_hgc, x1, y, x2, y);
  854.       else
  855.     gdk_draw_line (gdisp->canvas->window, normal_hgc, x1, y, x2, y);
  856.     }
  857.   else if (guide->orientation == ORIENTATION_VERTICAL)
  858.     {
  859.       gdisplay_transform_coords (gdisp, guide->position, 0, &x, &y, FALSE);
  860.  
  861.       if (active)
  862.     gdk_draw_line (gdisp->canvas->window, active_vgc, x, y1, x, y2);
  863.       else
  864.     gdk_draw_line (gdisp->canvas->window, normal_vgc, x, y1, x, y2);
  865.     }
  866. }
  867.  
  868. Guide*
  869. gdisplay_find_guide (GDisplay *gdisp,
  870.              gdouble   x,
  871.              gdouble   y)
  872. {
  873.   GList *tmp_list;
  874.   Guide *guide;
  875.   gint offset_x, offset_y;
  876.   gdouble scalex, scaley;
  877.   gdouble pos;
  878.  
  879.   if (gdisp->draw_guides)
  880.     {
  881.       offset_x = gdisp->offset_x - gdisp->disp_xoffset;
  882.       offset_y = gdisp->offset_y - gdisp->disp_yoffset;
  883.       scalex = SCALEFACTOR_X (gdisp);
  884.       scaley = SCALEFACTOR_Y (gdisp);
  885.  
  886.       tmp_list = gdisp->gimage->guides;
  887.       while (tmp_list)
  888.     {
  889.       guide = tmp_list->data;
  890.       tmp_list = tmp_list->next;
  891.  
  892.       switch (guide->orientation)
  893.         {
  894.         case ORIENTATION_HORIZONTAL:
  895.           pos = scaley * guide->position - offset_y;
  896.           if ((guide->position != -1) &&
  897.           (pos > (y - EPSILON)) &&
  898.           (pos < (y + EPSILON)))
  899.         return guide;
  900.           break;
  901.         case ORIENTATION_VERTICAL:
  902.           pos = scalex * guide->position - offset_x;
  903.           if ((guide->position != -1) &&
  904.           (pos > (x - EPSILON)) &&
  905.           (pos < (x + EPSILON)))
  906.         return guide;
  907.           break;
  908.         }
  909.     }
  910.     }
  911.  
  912.   return NULL;
  913. }
  914.  
  915. gboolean
  916. gdisplay_snap_point (GDisplay *gdisp,
  917.              gdouble   x,
  918.              gdouble   y,
  919.              gdouble  *tx,
  920.              gdouble  *ty)
  921. {
  922.   GList *tmp_list;
  923.   Guide *guide;
  924.   gdouble scalex, scaley;
  925.   gdouble pos;
  926.   gint offset_x, offset_y;
  927.   gint minhdist, minvdist;
  928.   gint dist;
  929.   gboolean snapped = FALSE;
  930.  
  931.   *tx = x;
  932.   *ty = y;
  933.  
  934.   if (gdisp->draw_guides &&
  935.       gdisp->snap_to_guides &&
  936.       gdisp->gimage->guides)
  937.     {
  938.       offset_x = gdisp->offset_x - gdisp->disp_xoffset;
  939.       offset_y = gdisp->offset_y - gdisp->disp_yoffset;
  940.       scalex = SCALEFACTOR_X (gdisp);
  941.       scaley = SCALEFACTOR_Y (gdisp);
  942.  
  943.       minhdist = G_MAXINT;
  944.       minvdist = G_MAXINT;
  945.  
  946.       tmp_list = gdisp->gimage->guides;
  947.       while (tmp_list)
  948.     {
  949.       guide = tmp_list->data;
  950.       tmp_list = tmp_list->next;
  951.  
  952.       switch (guide->orientation)
  953.         {
  954.         case ORIENTATION_HORIZONTAL:
  955.           pos = scaley * guide->position - offset_y;
  956.  
  957.           if ((pos > (y - EPSILON)) &&
  958.           (pos < (y + EPSILON)))
  959.         {
  960.           dist = (int) pos - y;
  961.           dist = ABS (dist);
  962.  
  963.           if (dist < minhdist)
  964.             {
  965.               minhdist = dist;
  966.               *ty = pos;
  967.               snapped = TRUE;
  968.             }
  969.         }
  970.           break;
  971.         case ORIENTATION_VERTICAL:
  972.           pos = scalex * guide->position - offset_x;
  973.  
  974.           if ((pos > (x - EPSILON)) &&
  975.           (pos < (x + EPSILON)))
  976.         {
  977.           dist = (int) pos - x;
  978.           dist = ABS (dist);
  979.  
  980.           if (dist < minvdist)
  981.             {
  982.               minvdist = dist;
  983.               *tx = pos; 
  984.               snapped = TRUE;
  985.             }
  986.         }
  987.           break;
  988.         }
  989.     }
  990.     }
  991.   return snapped;
  992. }
  993.  
  994. void
  995. gdisplay_snap_rectangle (GDisplay *gdisp,
  996.              gdouble   x1,
  997.              gdouble   y1,
  998.              gdouble   x2,
  999.              gdouble   y2,
  1000.              gdouble  *tx1,
  1001.              gdouble  *ty1)
  1002. {
  1003.   gdouble nx1, ny1;
  1004.   gdouble nx2, ny2;
  1005.   gboolean snap1, snap2;
  1006.  
  1007.   *tx1 = x1;
  1008.   *ty1 = y1;
  1009.  
  1010.   snap1 = gdisplay_snap_point (gdisp, x1, y1, &nx1, &ny1);
  1011.   snap2 = gdisplay_snap_point (gdisp, x2, y2, &nx2, &ny2);
  1012.   
  1013.   if (snap1 || snap2)
  1014.     {
  1015.       if (x1 != nx1)
  1016.     *tx1 = nx1;
  1017.       else if (x2 != nx2)
  1018.     *tx1 = x1 + (nx2 - x2);
  1019.   
  1020.       if (y1 != ny1)
  1021.     *ty1 = ny1;
  1022.       else if (y2 != ny2)
  1023.     *ty1 = y1 + (ny2 - y2);
  1024.     }
  1025. }
  1026.  
  1027. void
  1028. gdisplay_draw_cursor (GDisplay *gdisp)
  1029. {
  1030.   gint x = gdisp->cursor_x;
  1031.   gint y = gdisp->cursor_y;
  1032.   
  1033.   gdk_draw_line (gdisp->canvas->window,
  1034.          gdisp->canvas->style->white_gc,
  1035.          x - 7, y-1, x + 7, y-1);
  1036.   gdk_draw_line (gdisp->canvas->window,
  1037.          gdisp->canvas->style->black_gc,
  1038.          x - 7, y, x + 7, y);
  1039.   gdk_draw_line (gdisp->canvas->window,
  1040.          gdisp->canvas->style->white_gc,
  1041.          x - 7, y+1, x + 7, y+1);
  1042.   gdk_draw_line (gdisp->canvas->window,
  1043.          gdisp->canvas->style->white_gc,
  1044.          x-1, y - 7, x-1, y + 7);
  1045.   gdk_draw_line (gdisp->canvas->window,
  1046.          gdisp->canvas->style->black_gc,
  1047.          x, y - 7, x, y + 7);
  1048.   gdk_draw_line (gdisp->canvas->window,
  1049.          gdisp->canvas->style->white_gc,
  1050.          x+1, y - 7, x+1, y + 7);
  1051. }
  1052.  
  1053. void
  1054. gdisplay_update_cursor (GDisplay *gdisp, 
  1055.             gint      x, 
  1056.             gint      y)
  1057. {
  1058.   gint new_cursor;
  1059.   gchar buffer[CURSOR_STR_LENGTH];
  1060.   gint t_x;
  1061.   gint t_y;
  1062.  
  1063.   new_cursor = gdisp->draw_cursor && gdisp->proximity;
  1064.   
  1065.   /* Erase old cursor, if necessary */
  1066.  
  1067.   if (gdisp->have_cursor && (!new_cursor || x != gdisp->cursor_x ||
  1068.                  y != gdisp->cursor_y))
  1069.     {
  1070.       gdisplay_expose_area (gdisp, gdisp->cursor_x - 7,
  1071.                 gdisp->cursor_y - 7,
  1072.                 15, 15);
  1073.       if (!new_cursor)
  1074.     {
  1075.       gdisp->have_cursor = FALSE;
  1076.       gdisplay_flush (gdisp);
  1077.     }
  1078.     }
  1079.  
  1080.   gdisplay_untransform_coords (gdisp, x, y, &t_x, &t_y, FALSE, FALSE);
  1081.  
  1082.   if (t_x < 0 ||
  1083.       t_y < 0 ||
  1084.       t_x >= gdisp->gimage->width ||
  1085.       t_y >= gdisp->gimage->height)
  1086.     {
  1087.       gtk_label_set_text (GTK_LABEL (gdisp->cursor_label), "");
  1088.       info_window_update_RGB (gdisp, -1, -1);
  1089.     } 
  1090.   else 
  1091.     {
  1092.       if (gdisp->dot_for_dot)
  1093.     {
  1094.       g_snprintf (buffer, CURSOR_STR_LENGTH, 
  1095.               gdisp->cursor_format_str, "", t_x, ", ", t_y);
  1096.     }
  1097.       else /* show real world units */
  1098.     {
  1099.       gdouble unit_factor = gimp_unit_get_factor (gdisp->gimage->unit);
  1100.       
  1101.       g_snprintf
  1102.         (buffer, CURSOR_STR_LENGTH, gdisp->cursor_format_str,
  1103.          "",
  1104.          (gdouble) t_x * unit_factor / gdisp->gimage->xresolution,
  1105.          ", ",
  1106.          (gdouble) t_y * unit_factor / gdisp->gimage->yresolution);
  1107.     }
  1108.       gtk_label_set_text (GTK_LABEL (gdisp->cursor_label), buffer);
  1109.       info_window_update_RGB (gdisp, t_x, t_y);
  1110.     }
  1111.  
  1112.   gdisp->have_cursor = new_cursor;
  1113.   gdisp->cursor_x = x;
  1114.   gdisp->cursor_y = y;
  1115.   
  1116.   if (new_cursor)
  1117.     gdisplay_flush (gdisp);
  1118. }
  1119.  
  1120.  
  1121. void
  1122. gdisplay_set_dot_for_dot (GDisplay *gdisp, 
  1123.               gboolean  value)
  1124. {
  1125.   if (value != gdisp->dot_for_dot)
  1126.     {
  1127.       gdisp->dot_for_dot = value;
  1128.  
  1129.       gdisplay_resize_cursor_label (gdisp);
  1130.       resize_display (gdisp, allow_resize_windows, TRUE);
  1131.     }
  1132. }
  1133.  
  1134.  
  1135. void
  1136. gdisplay_resize_cursor_label (GDisplay *gdisp)
  1137. {
  1138.   /* Set a proper size for the coordinates display in the statusbar. */
  1139.   gchar buffer[CURSOR_STR_LENGTH];
  1140.   gint cursor_label_width;
  1141.   gint label_frame_size_difference;
  1142.  
  1143.   if (gdisp->dot_for_dot)
  1144.     {
  1145.       g_snprintf (gdisp->cursor_format_str, sizeof (gdisp->cursor_format_str),
  1146.           "%%s%%d%%s%%d");
  1147.       g_snprintf (buffer, sizeof (buffer), gdisp->cursor_format_str,
  1148.           "", gdisp->gimage->width, ", ", gdisp->gimage->height);
  1149.     }
  1150.   else /* show real world units */
  1151.     {
  1152.       gdouble unit_factor = gimp_unit_get_factor (gdisp->gimage->unit);
  1153.  
  1154.       g_snprintf (gdisp->cursor_format_str, sizeof (gdisp->cursor_format_str),
  1155.           "%%s%%.%df%%s%%.%df %s",
  1156.           gimp_unit_get_digits (gdisp->gimage->unit),
  1157.           gimp_unit_get_digits (gdisp->gimage->unit),
  1158.           gimp_unit_get_symbol (gdisp->gimage->unit));
  1159.  
  1160.       g_snprintf (buffer, sizeof (buffer), gdisp->cursor_format_str,
  1161.           "",
  1162.           (gdouble) gdisp->gimage->width * unit_factor /
  1163.           gdisp->gimage->xresolution,
  1164.           ", ",
  1165.           (gdouble) gdisp->gimage->height * unit_factor /
  1166.           gdisp->gimage->yresolution);
  1167.     }
  1168.   cursor_label_width = 
  1169.     gdk_string_width (gtk_widget_get_style (gdisp->cursor_label)->font, buffer);
  1170.   
  1171.   /*  find out how many pixels the label's parent frame is bigger than
  1172.    *  the label itself
  1173.    */
  1174.   label_frame_size_difference =
  1175.     gdisp->cursor_label->parent->allocation.width -
  1176.     gdisp->cursor_label->allocation.width;
  1177.  
  1178.   gtk_widget_set_usize (gdisp->cursor_label, cursor_label_width, -1);
  1179.   if (label_frame_size_difference) /* don't resize if this is a new display */
  1180.     gtk_widget_set_usize (gdisp->cursor_label->parent,
  1181.               cursor_label_width + label_frame_size_difference, -1);
  1182.  
  1183.   gdisplay_update_cursor (gdisp, gdisp->cursor_x, gdisp->cursor_y);
  1184. }
  1185.  
  1186. void
  1187. gdisplay_remove_and_delete (GDisplay *gdisp)
  1188. {
  1189.   /* remove the display from the list */
  1190.   display_list = g_slist_remove (display_list, (void *) gdisp);
  1191.   gdisplay_delete (gdisp);
  1192. }
  1193.  
  1194.  
  1195. static void
  1196. gdisplay_add_update_area (GDisplay *gdisp,
  1197.               gint      x,
  1198.               gint      y,
  1199.               gint      w,
  1200.               gint      h)
  1201. {
  1202.   GimpArea * ga;
  1203.  
  1204.   ga = (GimpArea *) g_malloc (sizeof (GimpArea));
  1205.   ga->x1 = CLAMP (x, 0, gdisp->gimage->width);
  1206.   ga->y1 = CLAMP (y, 0, gdisp->gimage->height);
  1207.   ga->x2 = CLAMP (x + w, 0, gdisp->gimage->width);
  1208.   ga->y2 = CLAMP (y + h, 0, gdisp->gimage->height);
  1209.  
  1210.   gdisp->update_areas = gdisplay_process_area_list (gdisp->update_areas, ga);
  1211. }
  1212.  
  1213.  
  1214. static void
  1215. gdisplay_add_display_area (GDisplay *gdisp,
  1216.                gint      x,
  1217.                gint      y,
  1218.                gint      w,
  1219.                gint      h)
  1220. {
  1221.   GimpArea * ga;
  1222.  
  1223.   ga = g_new (GimpArea, 1);
  1224.  
  1225.   ga->x1 = CLAMP (x, 0, gdisp->disp_width);
  1226.   ga->y1 = CLAMP (y, 0, gdisp->disp_height);
  1227.   ga->x2 = CLAMP (x + w, 0, gdisp->disp_width);
  1228.   ga->y2 = CLAMP (y + h, 0, gdisp->disp_height);
  1229.  
  1230.   gdisp->display_areas = gdisplay_process_area_list (gdisp->display_areas, ga);
  1231. }
  1232.  
  1233.  
  1234. static void
  1235. gdisplay_paint_area (GDisplay *gdisp,
  1236.              gint      x,
  1237.              gint      y,
  1238.              gint      w,
  1239.              gint      h)
  1240. {
  1241.   gint x1, y1, x2, y2;
  1242.  
  1243.   /*  Bounds check  */
  1244.   x1 = CLAMP (x, 0, gdisp->gimage->width);
  1245.   y1 = CLAMP (y, 0, gdisp->gimage->height);
  1246.   x2 = CLAMP (x + w, 0, gdisp->gimage->width);
  1247.   y2 = CLAMP (y + h, 0, gdisp->gimage->height);
  1248.   x = x1;
  1249.   y = y1;
  1250.   w = (x2 - x1);
  1251.   h = (y2 - y1);
  1252.  
  1253.   /*  calculate the extents of the update as limited by what's visible  */
  1254.   gdisplay_untransform_coords (gdisp, 0, 0, &x1, &y1, FALSE, FALSE);
  1255.   gdisplay_untransform_coords (gdisp, gdisp->disp_width, gdisp->disp_height,
  1256.                    &x2, &y2, FALSE, FALSE);
  1257.  
  1258.   gimage_invalidate (gdisp->gimage, x, y, w, h, x1, y1, x2, y2);
  1259.  
  1260.     /*  display the area  */
  1261.   gdisplay_transform_coords (gdisp, x, y, &x1, &y1, FALSE);
  1262.   gdisplay_transform_coords (gdisp, x + w, y + h, &x2, &y2, FALSE);
  1263.  
  1264.   gdisplay_expose_area (gdisp, x1, y1, (x2 - x1), (y2 - y1));
  1265. }
  1266.  
  1267.  
  1268. static void
  1269. gdisplay_display_area (GDisplay *gdisp,
  1270.                gint      x,
  1271.                gint      y,
  1272.                gint      w,
  1273.                gint      h)
  1274. {
  1275.   gint sx, sy;
  1276.   gint x1, y1;
  1277.   gint x2, y2;
  1278.   gint dx, dy;
  1279.   gint i, j;
  1280.   guchar *buf;
  1281.   gint bpp, bpl;
  1282. #ifdef DISPLAY_FILTERS
  1283.   GList *list;
  1284. #endif /* DISPLAY_FILTERS */
  1285.  
  1286.   buf = gximage_get_data ();
  1287.   bpp = gximage_get_bpp ();
  1288.   bpl = gximage_get_bpl ();
  1289.  
  1290.   sx = SCALEX (gdisp, gdisp->gimage->width);
  1291.   sy = SCALEY (gdisp, gdisp->gimage->height);
  1292.  
  1293.   /*  Bounds check  */
  1294.   x1 = CLAMP (x, 0, gdisp->disp_width);
  1295.   y1 = CLAMP (y, 0, gdisp->disp_height);
  1296.   x2 = CLAMP (x + w, 0, gdisp->disp_width);
  1297.   y2 = CLAMP (y + h, 0, gdisp->disp_height);
  1298.  
  1299.   if (y1 < gdisp->disp_yoffset)
  1300.     {
  1301.       gdk_draw_rectangle (gdisp->canvas->window,
  1302.               gdisp->canvas->style->bg_gc[GTK_STATE_NORMAL], 1,
  1303.               x, y, w, gdisp->disp_yoffset - y);
  1304.       /* X X X
  1305.          . # .
  1306.          . . . */
  1307.  
  1308.       y1 = gdisp->disp_yoffset;
  1309.     }
  1310.  
  1311.   if (x1 < gdisp->disp_xoffset)
  1312.     {
  1313.       gdk_draw_rectangle (gdisp->canvas->window,
  1314.               gdisp->canvas->style->bg_gc[GTK_STATE_NORMAL], 1,
  1315.               x, y1, gdisp->disp_xoffset - x, h);
  1316.       /* . . .
  1317.          X # .
  1318.          X . . */
  1319.  
  1320.       x1 = gdisp->disp_xoffset;
  1321.     }
  1322.  
  1323.   if (x2 > (gdisp->disp_xoffset + sx))
  1324.     {
  1325.       gdk_draw_rectangle (gdisp->canvas->window,
  1326.               gdisp->canvas->style->bg_gc[GTK_STATE_NORMAL], 1,
  1327.               gdisp->disp_xoffset + sx, y1,
  1328.               x2 - (gdisp->disp_xoffset + sx), h - (y1-y));
  1329.       /* . . .
  1330.          . # X
  1331.          . . X */
  1332.  
  1333.       x2 = gdisp->disp_xoffset + sx;
  1334.     }
  1335.  
  1336.   if (y2 > (gdisp->disp_yoffset + sy))
  1337.     {
  1338.       gdk_draw_rectangle (gdisp->canvas->window,
  1339.               gdisp->canvas->style->bg_gc[GTK_STATE_NORMAL], 1,
  1340.               x1, gdisp->disp_yoffset + sy,
  1341.               x2-x1,
  1342.               y2 - (gdisp->disp_yoffset + sy));
  1343.       /* . . .
  1344.          . # .
  1345.          . X . */
  1346.  
  1347.       y2 = gdisp->disp_yoffset + sy;
  1348.     }
  1349.  
  1350.   /*  display the image in GXIMAGE_WIDTH x GXIMAGE_HEIGHT sized chunks */
  1351.   for (i = y1; i < y2; i += GXIMAGE_HEIGHT)
  1352.     for (j = x1; j < x2; j += GXIMAGE_WIDTH)
  1353.       {
  1354.     dx = MIN (x2 - j, GXIMAGE_WIDTH);
  1355.     dy = MIN (y2 - i, GXIMAGE_HEIGHT);
  1356.     render_image (gdisp, j - gdisp->disp_xoffset, i - gdisp->disp_yoffset,
  1357.               dx, dy);
  1358. #if 0
  1359.         /* Invalidate the projection just after we render it! */
  1360.         gimage_invalidate_without_render (gdisp->gimage,
  1361.                           j - gdisp->disp_xoffset,
  1362.                           i - gdisp->disp_yoffset,
  1363.                           dx, dy,
  1364.                           0, 0, 0, 0);
  1365. #endif
  1366.  
  1367. #ifdef DISPLAY_FILTERS
  1368.     list = gdisp->cd_list;
  1369.     while (list)
  1370.       {
  1371.         ColorDisplayNode *node = (ColorDisplayNode *) list->data;
  1372.         node->cd_convert (node->cd_ID, buf, dx, dy, bpp, bpl);
  1373.         list = list->next;
  1374.       }
  1375. #endif /* DISPLAY_FILTERS */
  1376.  
  1377.     gximage_put (gdisp->canvas->window,
  1378.              j, i, dx, dy,
  1379.              gdisp->offset_x,
  1380.              gdisp->offset_y);
  1381.       }
  1382. }
  1383.  
  1384.  
  1385. gint
  1386. gdisplay_mask_value (GDisplay *gdisp,
  1387.              gint      x,
  1388.              gint      y)
  1389. {
  1390.   /*  move the coordinates from screen space to image space  */
  1391.   gdisplay_untransform_coords (gdisp, x, y, &x, &y, FALSE, 0);
  1392.  
  1393.   return gimage_mask_value (gdisp->gimage, x, y);
  1394. }
  1395.  
  1396.  
  1397. gint
  1398. gdisplay_mask_bounds (GDisplay *gdisp,
  1399.               gint     *x1,
  1400.               gint     *y1,
  1401.               gint     *x2,
  1402.               gint     *y2)
  1403. {
  1404.   Layer *layer;
  1405.   gint off_x;
  1406.   gint off_y;
  1407.  
  1408.   /*  If there is a floating selection, handle things differently  */
  1409.   if ((layer = gimage_floating_sel (gdisp->gimage)))
  1410.     {
  1411.       drawable_offsets (GIMP_DRAWABLE(layer), &off_x, &off_y);
  1412.       if (! channel_bounds (gimage_get_mask (gdisp->gimage), x1, y1, x2, y2))
  1413.     {
  1414.       *x1 = off_x;
  1415.       *y1 = off_y;
  1416.       *x2 = off_x + drawable_width (GIMP_DRAWABLE (layer));
  1417.       *y2 = off_y + drawable_height (GIMP_DRAWABLE (layer));
  1418.     }
  1419.       else
  1420.     {
  1421.       *x1 = MIN (off_x, *x1);
  1422.       *y1 = MIN (off_y, *y1);
  1423.       *x2 = MAX (off_x + drawable_width (GIMP_DRAWABLE (layer)), *x2);
  1424.       *y2 = MAX (off_y + drawable_height (GIMP_DRAWABLE (layer)), *y2);
  1425.     }
  1426.     }
  1427.   else if (! channel_bounds (gimage_get_mask (gdisp->gimage), x1, y1, x2, y2))
  1428.     return FALSE;
  1429.  
  1430.   gdisplay_transform_coords (gdisp, *x1, *y1, x1, y1, 0);
  1431.   gdisplay_transform_coords (gdisp, *x2, *y2, x2, y2, 0);
  1432.  
  1433.   /*  Make sure the extents are within bounds  */
  1434.   *x1 = CLAMP (*x1, 0, gdisp->disp_width);
  1435.   *y1 = CLAMP (*y1, 0, gdisp->disp_height);
  1436.   *x2 = CLAMP (*x2, 0, gdisp->disp_width);
  1437.   *y2 = CLAMP (*y2, 0, gdisp->disp_height);
  1438.  
  1439.   return TRUE;
  1440. }
  1441.  
  1442.  
  1443. void
  1444. gdisplay_transform_coords (GDisplay *gdisp,
  1445.                gint      x,
  1446.                gint      y,
  1447.                gint     *nx,
  1448.                gint     *ny,
  1449.                gboolean  use_offsets)
  1450. {
  1451.   gdouble scalex;
  1452.   gdouble scaley;
  1453.   gint offset_x;
  1454.   gint offset_y;
  1455.  
  1456.   /*  transform from image coordinates to screen coordinates  */
  1457.   scalex = SCALEFACTOR_X (gdisp);
  1458.   scaley = SCALEFACTOR_Y (gdisp);
  1459.  
  1460.   if (use_offsets)
  1461.     drawable_offsets (gimage_active_drawable (gdisp->gimage), &offset_x, &offset_y);
  1462.   else
  1463.     {
  1464.       offset_x = offset_y = 0;
  1465.     }
  1466.  
  1467.   *nx = (int) (scalex * (x + offset_x) - gdisp->offset_x);
  1468.   *ny = (int) (scaley * (y + offset_y) - gdisp->offset_y);
  1469.  
  1470.   *nx += gdisp->disp_xoffset;
  1471.   *ny += gdisp->disp_yoffset;
  1472. }
  1473.  
  1474.  
  1475. void
  1476. gdisplay_untransform_coords (GDisplay *gdisp,
  1477.                  gint       x,
  1478.                  gint       y,
  1479.                  gint      *nx,
  1480.                  gint      *ny,
  1481.                  gboolean   round,
  1482.                  gboolean   use_offsets)
  1483. {
  1484.   gdouble scalex;
  1485.   gdouble scaley;
  1486.   gint offset_x;
  1487.   gint offset_y;
  1488.  
  1489.   x -= gdisp->disp_xoffset;
  1490.   y -= gdisp->disp_yoffset;
  1491.  
  1492.   /*  transform from screen coordinates to image coordinates  */
  1493.   scalex = SCALEFACTOR_X (gdisp);
  1494.   scaley = SCALEFACTOR_Y (gdisp);
  1495.  
  1496.   if (use_offsets)
  1497.     drawable_offsets (gimage_active_drawable (gdisp->gimage), &offset_x, &offset_y);
  1498.   else
  1499.     {
  1500.       offset_x = offset_y = 0;
  1501.     }
  1502.  
  1503.   if (round)
  1504.     {
  1505.       *nx = ROUND ((x + gdisp->offset_x) / scalex - offset_x);
  1506.       *ny = ROUND ((y + gdisp->offset_y) / scaley - offset_y);
  1507.     }
  1508.   else
  1509.     {
  1510.       *nx = (int) ((x + gdisp->offset_x) / scalex - offset_x);
  1511.       *ny = (int) ((y + gdisp->offset_y) / scaley - offset_y);
  1512.     }
  1513. }
  1514.  
  1515.  
  1516. void
  1517. gdisplay_transform_coords_f (GDisplay *gdisp,
  1518.                  gdouble   x,
  1519.                  gdouble   y,
  1520.                  gdouble  *nx,
  1521.                  gdouble  *ny,
  1522.                  gboolean  use_offsets)
  1523. {
  1524.   gdouble scalex;
  1525.   gdouble scaley;
  1526.   gint offset_x;
  1527.   gint offset_y;
  1528.  
  1529.   /*  transform from gimp coordinates to screen coordinates  */
  1530.   scalex = SCALEFACTOR_X (gdisp);
  1531.   scaley = SCALEFACTOR_Y (gdisp);
  1532.  
  1533.   if (use_offsets)
  1534.     drawable_offsets (gimage_active_drawable (gdisp->gimage), &offset_x, &offset_y);
  1535.   else
  1536.     {
  1537.       offset_x = offset_y = 0;
  1538.     }
  1539.  
  1540.   *nx = scalex * (x + offset_x) - gdisp->offset_x;
  1541.   *ny = scaley * (y + offset_y) - gdisp->offset_y;
  1542.  
  1543.   *nx += gdisp->disp_xoffset;
  1544.   *ny += gdisp->disp_yoffset;
  1545. }
  1546.  
  1547.  
  1548. void
  1549. gdisplay_untransform_coords_f (GDisplay *gdisp,
  1550.                    gdouble    x,
  1551.                    gdouble    y,
  1552.                    gdouble   *nx,
  1553.                    gdouble   *ny,
  1554.                    gboolean   use_offsets)
  1555. {
  1556.   gdouble scalex;
  1557.   gdouble scaley;
  1558.   gint offset_x;
  1559.   gint offset_y;
  1560.  
  1561.   x -= gdisp->disp_xoffset;
  1562.   y -= gdisp->disp_yoffset;
  1563.  
  1564.   /*  transform from screen coordinates to gimp coordinates  */
  1565.   scalex = SCALEFACTOR_X (gdisp);
  1566.   scaley = SCALEFACTOR_Y (gdisp);
  1567.  
  1568.   if (use_offsets)
  1569.     drawable_offsets (gimage_active_drawable (gdisp->gimage), &offset_x, &offset_y);
  1570.   else
  1571.     {
  1572.       offset_x = offset_y = 0;
  1573.     }
  1574.  
  1575.   *nx = (x + gdisp->offset_x) / scalex - offset_x;
  1576.   *ny = (y + gdisp->offset_y) / scaley - offset_y;
  1577. }
  1578.  
  1579.  
  1580. /*  install and remove tool cursor from gdisplay...  */
  1581. void
  1582. gdisplay_real_install_tool_cursor (GDisplay      *gdisp,
  1583.                    GdkCursorType  cursor_type,
  1584.                    ToolType       tool_type,
  1585.                    CursorModifier modifier,
  1586.                    gboolean       toggle_cursor,
  1587.                    gboolean       always_install)
  1588. {
  1589.   if (cursor_type != GIMP_BAD_CURSOR)
  1590.     {
  1591.       switch (cursor_mode)
  1592.     {
  1593.     case CURSOR_MODE_TOOL_ICON:
  1594.       break;
  1595.  
  1596.     case CURSOR_MODE_TOOL_CROSSHAIR:
  1597.       cursor_type = GIMP_CROSSHAIR_SMALL_CURSOR;
  1598.       break;
  1599.  
  1600.     case CURSOR_MODE_CROSSHAIR:
  1601.       cursor_type = GIMP_CROSSHAIR_CURSOR;
  1602.       tool_type   = TOOL_TYPE_NONE;
  1603.       modifier    = CURSOR_MODIFIER_NONE;
  1604.       break;
  1605.     }
  1606.     }
  1607.  
  1608.   if (gdisp->current_cursor  != cursor_type   ||
  1609.       gdisp->cursor_tool     != tool_type     ||
  1610.       gdisp->cursor_modifier != modifier      ||
  1611.       gdisp->toggle_cursor   != toggle_cursor ||
  1612.       always_install)
  1613.     {
  1614.       gdisp->current_cursor  = cursor_type;
  1615.       gdisp->cursor_tool     = tool_type;
  1616.       gdisp->cursor_modifier = modifier;
  1617.       gdisp->toggle_cursor   = toggle_cursor;
  1618.  
  1619.       change_win_cursor (gdisp->canvas->window,
  1620.              cursor_type,
  1621.              tool_type,
  1622.              modifier,
  1623.              toggle_cursor);
  1624.     }
  1625. }
  1626.  
  1627. void
  1628. gdisplay_install_tool_cursor (GDisplay       *gdisp,
  1629.                   GdkCursorType   cursor_type,
  1630.                   ToolType        tool_type,
  1631.                   CursorModifier  modifier,
  1632.                   gboolean        toggle_cursor)
  1633. {
  1634.   if (!gdisp->using_override_cursor)
  1635.     gdisplay_real_install_tool_cursor (gdisp,
  1636.                        cursor_type,
  1637.                        tool_type,
  1638.                        modifier,
  1639.                        toggle_cursor,
  1640.                        FALSE);
  1641. }
  1642.  
  1643.  
  1644. /*  install an override-cursor on gdisplay...  */
  1645. void
  1646. gdisplay_install_override_cursor (GDisplay      *gdisp,
  1647.                   GdkCursorType  cursor_type)
  1648. {
  1649.   if (!gdisp->using_override_cursor ||
  1650.       (gdisp->using_override_cursor &&
  1651.        (gdisp->override_cursor != cursor_type)))
  1652.     {
  1653.       gdisp->override_cursor       = cursor_type;
  1654.       gdisp->using_override_cursor = TRUE;
  1655.       change_win_cursor (gdisp->canvas->window,
  1656.              cursor_type,
  1657.              TOOL_TYPE_NONE,
  1658.              CURSOR_MODIFIER_NONE,
  1659.              FALSE);
  1660.     }
  1661. }
  1662.  
  1663.  
  1664. /*  remove an override-cursor from gdisplay...  */
  1665. void
  1666. gdisplay_remove_override_cursor (GDisplay *gdisp)
  1667. {
  1668.   if (gdisp->using_override_cursor)
  1669.     {
  1670.       gdisp->using_override_cursor = FALSE;
  1671.       gdisplay_real_install_tool_cursor (gdisp,
  1672.                      gdisp->current_cursor,
  1673.                      gdisp->cursor_tool,
  1674.                      gdisp->cursor_modifier,
  1675.                      gdisp->toggle_cursor,
  1676.                      TRUE);
  1677.     }
  1678. }
  1679.  
  1680.  
  1681. void
  1682. gdisplay_remove_tool_cursor (GDisplay *gdisp)
  1683. {
  1684.   unset_win_cursor (gdisp->canvas->window);
  1685. }
  1686.  
  1687.  
  1688. void
  1689. gdisplay_set_menu_sensitivity (GDisplay *gdisp)
  1690. {
  1691.   GimpImageBaseType  base_type = 0;
  1692.   GimpImageType      type      = -1;
  1693.   GimpDrawable      *drawable  = NULL;
  1694.   Layer             *layer     = NULL;
  1695.   gboolean fs    = FALSE;
  1696.   gboolean aux   = FALSE;
  1697.   gboolean lm    = FALSE;
  1698.   gboolean lp    = FALSE;
  1699.   gboolean alpha = FALSE;
  1700.   gint     lind  = -1;
  1701.   gint     lnum  = -1;
  1702.  
  1703.   if (gdisp)
  1704.     {
  1705.       base_type = gimage_base_type (gdisp->gimage);
  1706.  
  1707.       fs  = (gimage_floating_sel (gdisp->gimage) != NULL);
  1708.       aux = (gimage_get_active_channel (gdisp->gimage) != NULL);
  1709.       lp  = (gdisp->gimage->layers != NULL);
  1710.  
  1711.       drawable = gimage_active_drawable (gdisp->gimage);
  1712.       if (drawable)
  1713.     type = drawable_type (drawable);
  1714.  
  1715.       if (lp)
  1716.     {
  1717.       layer = gimage_get_active_layer (gdisp->gimage);
  1718.       if (layer)
  1719.         {
  1720.           lm    = layer_get_mask (layer) ? TRUE : FALSE;
  1721.           alpha = layer_has_alpha (layer);
  1722.         }
  1723.  
  1724.       lind = gimage_get_layer_index (gdisp->gimage,
  1725.                      gdisp->gimage->active_layer);
  1726.       lnum = g_slist_length (gdisp->gimage->layers);
  1727.     }
  1728.     }
  1729.  
  1730. #define SET_SENSITIVE(menu,condition) \
  1731.         menus_set_sensitive ("<Image>/" menu, (condition) != 0)
  1732. #define SET_STATE(menu,condition) \
  1733.         menus_set_state ("<Image>/" menu, (condition) != 0)
  1734.  
  1735.   SET_SENSITIVE ("File/Save", gdisp && drawable);
  1736.   SET_SENSITIVE ("File/Save As...", gdisp && drawable);
  1737.   SET_SENSITIVE ("File/Revert...", gdisp && gdisp->gimage->filename);
  1738.   SET_SENSITIVE ("File/Close", gdisp);
  1739.  
  1740.   SET_SENSITIVE ("Edit", gdisp);
  1741.   SET_SENSITIVE ("Edit/Buffer", gdisp);
  1742.   if (gdisp)
  1743.     {
  1744.       /* Interactive tools such as CURVES, COLOR_BALANCE, LEVELS disable */
  1745.       /* undo to fake some kind of atomic behaviour. G. R. Osgood #14072  */
  1746.  
  1747.       if (gimp_image_undo_is_enabled (gdisp->gimage))
  1748.     {
  1749.       /* If undo/redo stacks are empty, disable respective menu */
  1750.  
  1751.       SET_SENSITIVE ("Edit/Undo", undo_get_undo_name (gdisp->gimage));
  1752.       SET_SENSITIVE ("Edit/Redo", undo_get_redo_name (gdisp->gimage));
  1753.     }
  1754.       else
  1755.     {
  1756.       SET_SENSITIVE ("Edit/Undo", FALSE);
  1757.       SET_SENSITIVE ("Edit/Redo", FALSE);
  1758.     }
  1759.       SET_SENSITIVE ("Edit/Cut", lp);
  1760.       SET_SENSITIVE ("Edit/Copy", lp);
  1761.       SET_SENSITIVE ("Edit/Buffer/Cut Named...", lp);
  1762.       SET_SENSITIVE ("Edit/Buffer/Copy Named...", lp);
  1763.       SET_SENSITIVE ("Edit/Clear", lp);
  1764.       SET_SENSITIVE ("Edit/Fill with FG Color", lp);
  1765.       SET_SENSITIVE ("Edit/Fill with BG Color", lp);
  1766.       SET_SENSITIVE ("Edit/Stroke", lp);
  1767.     }
  1768.  
  1769.   SET_SENSITIVE ("Select", gdisp && lp);
  1770.   SET_SENSITIVE ("Select/Save to Channel", !fs);
  1771.  
  1772.   SET_SENSITIVE ("View", gdisp);
  1773.   SET_SENSITIVE ("View/Zoom", gdisp);
  1774.   if (gdisp)
  1775.     {
  1776.       SET_STATE ("View/Toggle Selection", !gdisp->select->hidden);
  1777.       SET_STATE ("View/Toggle Rulers",
  1778.          GTK_WIDGET_VISIBLE (gdisp->origin) ? 1 : 0);
  1779.       SET_STATE ("View/Toggle Guides", gdisp->draw_guides);
  1780.       SET_STATE ("View/Snap to Guides", gdisp->snap_to_guides);
  1781.       SET_STATE ("View/Toggle Statusbar",
  1782.          GTK_WIDGET_VISIBLE (gdisp->statusarea) ? 1 : 0);
  1783.       SET_STATE ("View/Dot for Dot", gdisp->dot_for_dot);
  1784.     }
  1785.  
  1786.   SET_SENSITIVE ("Image", gdisp);
  1787.   SET_SENSITIVE ("Image/Mode", gdisp);
  1788.   SET_SENSITIVE ("Image/Colors", gdisp);
  1789.   SET_SENSITIVE ("Image/Colors/Auto", gdisp);
  1790.   SET_SENSITIVE ("Image/Alpha", gdisp);
  1791.   SET_SENSITIVE ("Image/Transforms", gdisp);
  1792.   SET_SENSITIVE ("Image/Transforms/Rotate", gdisp);
  1793.   if (gdisp)
  1794.     {
  1795.       SET_SENSITIVE ("Image/Mode/RGB", (base_type != RGB));
  1796.       SET_SENSITIVE ("Image/Mode/Grayscale", (base_type != GRAY));
  1797.       SET_SENSITIVE ("Image/Mode/Indexed...", (base_type != INDEXED));
  1798.       SET_SENSITIVE ("Image/Histogram...", lp);
  1799.  
  1800.       SET_SENSITIVE ("Image/Colors", lp);
  1801.       SET_SENSITIVE ("Image/Colors/Color Balance...", (base_type == RGB));
  1802.       SET_SENSITIVE ("Image/Colors/Hue-Saturation...", (base_type == RGB));
  1803.       SET_SENSITIVE ("Image/Colors/Brightness-Contrast...", (base_type != INDEXED));
  1804.       SET_SENSITIVE ("Image/Colors/Threshold...", (base_type != INDEXED));
  1805.       SET_SENSITIVE ("Image/Colors/Levels...", (base_type != INDEXED));
  1806.       SET_SENSITIVE ("Image/Colors/Curves...", (base_type != INDEXED));
  1807.       SET_SENSITIVE ("Image/Colors/Desaturate", (base_type == RGB));
  1808.       SET_SENSITIVE ("Image/Colors/Posterize...", (base_type != INDEXED));
  1809.       SET_SENSITIVE ("Image/Colors/Invert", (base_type != INDEXED));
  1810.       SET_SENSITIVE ("Image/Colors/Auto/Equalize", (base_type != INDEXED));
  1811.  
  1812.       SET_SENSITIVE ("Image/Alpha/Add Alpha Channel",
  1813.              !fs && !aux && lp && !lm && !alpha);
  1814.  
  1815.       SET_SENSITIVE ("Image/Transforms/Offset...", lp);
  1816.     }
  1817.  
  1818.   SET_SENSITIVE ("Layers/Stack", gdisp);
  1819.   if (gdisp)
  1820.     {
  1821.       SET_SENSITIVE ("Layers/Stack/Previous Layer",
  1822.              !fs && !aux && lp && lind > 0);
  1823.       SET_SENSITIVE ("Layers/Stack/Next Layer",
  1824.              !fs && !aux && lp && lind < (lnum - 1));
  1825.       SET_SENSITIVE ("Layers/Stack/Raise Layer",
  1826.              !fs && !aux && lp && alpha && lind > 0);
  1827.       SET_SENSITIVE ("Layers/Stack/Lower Layer",
  1828.              !fs && !aux && lp && alpha && lind < (lnum - 1));
  1829.       SET_SENSITIVE ("Layers/Stack/Layer to Top",
  1830.              !fs && !aux && lp && alpha && lind > 0);
  1831.       SET_SENSITIVE ("Layers/Stack/Layer to Bottom",
  1832.              !fs && !aux && lp && alpha && lind < (lnum - 1));
  1833.     }
  1834.   SET_SENSITIVE ("Layers/Rotate", gdisp && !aux && !lm & lp);
  1835.   SET_SENSITIVE ("Layers/Layer to Imagesize", gdisp && !aux && lp);
  1836.  
  1837.   SET_SENSITIVE ("Layers/Anchor Layer", gdisp && fs && !aux && lp);
  1838.   SET_SENSITIVE ("Layers/Merge Visible Layers...", gdisp && !fs && !aux && lp);
  1839.   SET_SENSITIVE ("Layers/Flatten Image", gdisp && !fs && !aux && lp);
  1840.   SET_SENSITIVE ("Layers/Alpha to Selection", gdisp && !aux && lp && alpha);
  1841.   SET_SENSITIVE ("Layers/Mask to Selection", gdisp && !aux && lm && lp);
  1842.   SET_SENSITIVE ("Layers/Add Alpha Channel",
  1843.          gdisp && !fs && !aux && lp && !lm && !alpha);
  1844.  
  1845.   SET_SENSITIVE ("Filters", gdisp && lp);
  1846.  
  1847.   SET_SENSITIVE ("Script-Fu", gdisp && lp);
  1848.  
  1849. #undef SET_STATE
  1850. #undef SET_SENSITIVE
  1851.  
  1852.   plug_in_set_menu_sensitivity (type);
  1853. }
  1854.  
  1855. void
  1856. gdisplay_expose_area (GDisplay *gdisp,
  1857.               gint      x,
  1858.               gint      y,
  1859.               gint      w,
  1860.               gint      h)
  1861. {
  1862.   gdisplay_add_display_area (gdisp, x, y, w, h);
  1863. }
  1864.  
  1865. void
  1866. gdisplay_expose_guide (GDisplay *gdisp,
  1867.                Guide    *guide)
  1868. {
  1869.   gint x;
  1870.   gint y;
  1871.  
  1872.   if (guide->position < 0)
  1873.     return;
  1874.  
  1875.   gdisplay_transform_coords (gdisp, guide->position,
  1876.                  guide->position, &x, &y, FALSE);
  1877.  
  1878.   switch (guide->orientation)
  1879.     {
  1880.     case ORIENTATION_HORIZONTAL:
  1881.       gdisplay_expose_area (gdisp, 0, y, gdisp->disp_width, 1);
  1882.       break;
  1883.     case ORIENTATION_VERTICAL:
  1884.       gdisplay_expose_area (gdisp, x, 0, 1, gdisp->disp_height);
  1885.       break;
  1886.     }
  1887. }
  1888.  
  1889. void
  1890. gdisplay_expose_full (GDisplay *gdisp)
  1891. {
  1892.   gdisplay_add_display_area (gdisp, 0, 0,
  1893.                  gdisp->disp_width,
  1894.                  gdisp->disp_height);
  1895. }
  1896.  
  1897. /**************************************************/
  1898. /*  Functions independent of a specific gdisplay  */
  1899. /**************************************************/
  1900.  
  1901. GDisplay *
  1902. gdisplay_active (void)
  1903. {
  1904.   GdkEvent *event;
  1905.  
  1906.   /*  Whoever finds out why we do this (see below) gets a free beer.
  1907.    *  Report back the reason to Sven and Mitch ... 
  1908.    */
  1909.   event = gtk_get_current_event ();
  1910.   if (event != NULL)
  1911.     {
  1912.       gdk_event_free (event);
  1913.     }
  1914.  
  1915.   return gimp_context_get_display (gimp_context_get_user ());
  1916. }
  1917.  
  1918.  
  1919. GDisplay *
  1920. gdisplay_get_ID (gint ID)
  1921. {
  1922.   GDisplay *gdisp;
  1923.   GSList *list = display_list;
  1924.  
  1925.   /*  Traverse the list of displays, returning the one that matches the ID  */
  1926.   /*  If no display in the list is a match, return NULL.                    */
  1927.   while (list)
  1928.     {
  1929.       gdisp = (GDisplay *) list->data;
  1930.       if (gdisp->ID == ID)
  1931.     return gdisp;
  1932.  
  1933.       list = g_slist_next (list);
  1934.     }
  1935.  
  1936.   return NULL;
  1937. }
  1938.  
  1939.  
  1940. void
  1941. gdisplay_update_title (GDisplay *gdisp)
  1942. {
  1943.   gchar title [MAX_TITLE_BUF];
  1944.   guint context_id;
  1945.  
  1946.   /* format the title */
  1947.   gdisplay_format_title (gdisp, title, MAX_TITLE_BUF);
  1948.   gdk_window_set_title (gdisp->shell->window, title);
  1949.  
  1950.   /* update the statusbar */
  1951.   context_id =
  1952.     gtk_statusbar_get_context_id (GTK_STATUSBAR (gdisp->statusbar), "title");
  1953.   gtk_statusbar_pop (GTK_STATUSBAR (gdisp->statusbar), context_id);
  1954.   gtk_statusbar_push (GTK_STATUSBAR (gdisp->statusbar), context_id, title);
  1955. }
  1956.  
  1957.  
  1958. void
  1959. gdisplays_update_title (GimpImage *gimage)
  1960. {
  1961.   GDisplay *gdisp;
  1962.   GSList *list = display_list;
  1963.  
  1964.   /*  traverse the linked list of displays, handling each one  */
  1965.   while (list)
  1966.     {
  1967.       gdisp = (GDisplay *) list->data;
  1968.       if (gdisp->gimage == gimage)
  1969.        gdisplay_update_title (gdisp);
  1970.  
  1971.       list = g_slist_next (list);
  1972.     }
  1973. }
  1974.  
  1975. void
  1976. gdisplays_resize_cursor_label (GimpImage *gimage)
  1977. {
  1978.   GDisplay *gdisp;
  1979.   GSList *list = display_list;
  1980.  
  1981.   /*  traverse the linked list of displays, handling each one  */
  1982.   while (list)
  1983.     {
  1984.       gdisp = (GDisplay *) list->data;
  1985.       if (gdisp->gimage == gimage)
  1986.     gdisplay_resize_cursor_label (gdisp);
  1987.  
  1988.       list = g_slist_next (list);
  1989.     }
  1990. }
  1991.  
  1992. void
  1993. gdisplays_setup_scale (GimpImage *gimage)
  1994. {
  1995.   GDisplay *gdisp;
  1996.   GSList *list = display_list;
  1997.  
  1998.   /*  traverse the linked list of displays, handling each one  */
  1999.   while (list)
  2000.     {
  2001.       gdisp = (GDisplay *) list->data;
  2002.       if (gdisp->gimage == gimage)
  2003.     setup_scale (gdisp);
  2004.  
  2005.       list = g_slist_next (list);
  2006.     }
  2007. }
  2008.  
  2009. void
  2010. gdisplays_update_area (GimpImage *gimage,
  2011.                gint       x,
  2012.                gint       y,
  2013.                gint       w,
  2014.                gint       h)
  2015. {
  2016.   GDisplay *gdisp;
  2017.   GSList *list = display_list;
  2018.   /* int x1, y1, x2, y2; */
  2019.   /*  int count = 0; */
  2020.  
  2021.   /*  traverse the linked list of displays  */
  2022.   while (list)
  2023.     {
  2024.       gdisp = (GDisplay *) list->data;
  2025.       if (gdisp->gimage == gimage)
  2026.     {
  2027.       /*  We only need to update the first instance that
  2028.           we find of this gimage ID.  Otherwise, we would
  2029.           be reconverting the same region unnecessarily.   */
  2030.  
  2031.       /* Um.. I don't think so. If you only do this to the first
  2032.          instance, you don't update other gdisplays pointing to this
  2033.          gimage.  I'm going to comment this out to show how it was in
  2034.          case we need to change it back.  msw 4/15/1998
  2035.       */
  2036.       /*
  2037.       if (! count)
  2038.         gdisplay_add_update_area (gdisp, x, y, w, h);
  2039.       else
  2040.         {
  2041.           gdisplay_transform_coords (gdisp, x, y, &x1, &y1, 0);
  2042.           gdisplay_transform_coords (gdisp, x + w, y + h, &x2, &y2, 0);
  2043.           gdisplay_add_display_area (gdisp, x1, y1, (x2 - x1), (y2 - y1));
  2044.         }
  2045.       */
  2046.  
  2047.       gdisplay_add_update_area (gdisp, x, y, w, h);
  2048.       /* Seems like this isn't needed, it's done in
  2049.          gdisplay_flush. -la
  2050.       gdisplay_transform_coords (gdisp, x, y, &x1, &y1, 0);
  2051.       gdisplay_transform_coords (gdisp, x + w, y + h, &x2, &y2, 0);
  2052.       gdisplay_add_display_area (gdisp, x1, y1, (x2 - x1), (y2 - y1));
  2053.       */
  2054.     }
  2055.       list = g_slist_next (list);
  2056.     }
  2057. }
  2058.  
  2059.  
  2060. void
  2061. gdisplays_expose_guides (GimpImage *gimage)
  2062. {
  2063.   GDisplay *gdisp;
  2064.   GList *tmp_list;
  2065.   GSList *list;
  2066.  
  2067.   /*  traverse the linked list of displays, handling each one  */
  2068.   list = display_list;
  2069.   while (list)
  2070.     {
  2071.       gdisp = (GDisplay *) list->data;
  2072.       if (gdisp->gimage == gimage)
  2073.     {
  2074.       tmp_list = gdisp->gimage->guides;
  2075.       while (tmp_list)
  2076.         {
  2077.           gdisplay_expose_guide (gdisp, tmp_list->data);
  2078.           tmp_list = tmp_list->next;
  2079.         }
  2080.     }
  2081.  
  2082.       list = g_slist_next (list);
  2083.     }
  2084. }
  2085.  
  2086.  
  2087. void
  2088. gdisplays_expose_guide (GimpImage *gimage,
  2089.             Guide     *guide)
  2090. {
  2091.   GDisplay *gdisp;
  2092.   GSList *list;
  2093.  
  2094.   /*  traverse the linked list of displays, handling each one  */
  2095.   list = display_list;
  2096.   while (list)
  2097.     {
  2098.       gdisp = (GDisplay *) list->data;
  2099.       if (gdisp->gimage == gimage)
  2100.     {
  2101.       gdisplay_expose_guide (gdisp, guide);
  2102.     }
  2103.       
  2104.       list = g_slist_next (list);
  2105.     }
  2106. }
  2107.  
  2108.  
  2109. void
  2110. gdisplays_update_full (GimpImage* gimage)
  2111. {
  2112.   GDisplay *gdisp;
  2113.   GSList *list = display_list;
  2114.   gint count = 0;
  2115.  
  2116.   /*  traverse the linked list of displays, handling each one  */
  2117.   while (list)
  2118.     {
  2119.       gdisp = (GDisplay *) list->data;
  2120.       if (gdisp->gimage == gimage)
  2121.     {
  2122.       if (! count)
  2123.         gdisplay_add_update_area (gdisp, 0, 0,
  2124.                       gdisp->gimage->width,
  2125.                       gdisp->gimage->height);
  2126.       else
  2127.         gdisplay_add_display_area (gdisp, 0, 0,
  2128.                        gdisp->disp_width,
  2129.                        gdisp->disp_height);
  2130.  
  2131.       count++;
  2132.     }
  2133.  
  2134.       list = g_slist_next (list);
  2135.     }
  2136. }
  2137.  
  2138.  
  2139. void
  2140. gdisplays_shrink_wrap (GimpImage *gimage)
  2141. {
  2142.   GDisplay *gdisp;
  2143.   GSList *list = display_list;
  2144.  
  2145.   /*  traverse the linked list of displays, handling each one  */
  2146.   while (list)
  2147.     {
  2148.       gdisp = (GDisplay *) list->data;
  2149.       if (gdisp->gimage == gimage)
  2150.     shrink_wrap_display (gdisp);
  2151.  
  2152.       list = g_slist_next (list);
  2153.     }
  2154. }
  2155.  
  2156.  
  2157. void
  2158. gdisplays_expose_full (void)
  2159. {
  2160.   GDisplay *gdisp;
  2161.   GSList *list = display_list;
  2162.  
  2163.   /*  traverse the linked list of displays, handling each one  */
  2164.   while (list)
  2165.     {
  2166.       gdisp = (GDisplay *) list->data;
  2167.       gdisplay_expose_full (gdisp);
  2168.       list = g_slist_next (list);
  2169.     }
  2170. }
  2171.  
  2172. void
  2173. gdisplays_nav_preview_resized (void)
  2174. {
  2175.   GDisplay *gdisp;
  2176.   GSList *list = display_list;
  2177.  
  2178.   /*  traverse the linked list of displays, handling each one  */
  2179.   while (list)
  2180.     {
  2181.       gdisp = (GDisplay *) list->data;
  2182.  
  2183.       if (gdisp->window_nav_dialog)
  2184.     nav_window_preview_resized (gdisp->window_nav_dialog);
  2185.       
  2186.       if (gdisp->nav_popup)
  2187.     nav_window_popup_preview_resized (&gdisp->nav_popup);
  2188.  
  2189.       list = g_slist_next (list);
  2190.     }
  2191. }
  2192.  
  2193. void
  2194. gdisplays_selection_visibility (GimpImage        *gimage,
  2195.                 SelectionControl  function)
  2196. {
  2197.   GDisplay *gdisp;
  2198.   GSList *list = display_list;
  2199.   gint count = 0;
  2200.  
  2201.   /*  traverse the linked list of displays, handling each one  */
  2202.   while (list)
  2203.     {
  2204.       gdisp = (GDisplay *) list->data;
  2205.       if (gdisp->gimage == gimage && gdisp->select)
  2206.     {
  2207.       switch (function)
  2208.         {
  2209.         case SelectionOff:
  2210.           selection_invis (gdisp->select);
  2211.           break;
  2212.         case SelectionLayerOff:
  2213.           selection_layer_invis (gdisp->select);
  2214.           break;
  2215.         case SelectionOn:
  2216.           selection_start (gdisp->select, TRUE);
  2217.           break;
  2218.         case SelectionPause:
  2219.           selection_pause (gdisp->select);
  2220.           break;
  2221.         case SelectionResume:
  2222.           selection_resume (gdisp->select);
  2223.           break;
  2224.         }
  2225.       count++;
  2226.     }
  2227.  
  2228.       list = g_slist_next (list);
  2229.     }
  2230. }
  2231.  
  2232.  
  2233. gboolean
  2234. gdisplays_dirty (void)
  2235. {
  2236.   gboolean dirty = FALSE;
  2237.   GSList *list = display_list;
  2238.  
  2239.   /*  traverse the linked list of displays  */
  2240.   while (list)
  2241.     {
  2242.       if (((GDisplay *) list->data)->gimage->dirty != 0)
  2243.     dirty = TRUE;
  2244.       list = g_slist_next (list);
  2245.     }
  2246.  
  2247.   return dirty;
  2248. }
  2249.  
  2250.  
  2251. void
  2252. gdisplays_delete (void)
  2253. {
  2254.   GSList *list = display_list;
  2255.   GDisplay *gdisp;
  2256.  
  2257.   /*  traverse the linked list of displays  */
  2258.   while (list)
  2259.     {
  2260.       gdisp = (GDisplay *) list->data;
  2261.       list = g_slist_next (list);
  2262.       gtk_widget_destroy (gdisp->shell);
  2263.     }
  2264.  
  2265.   /*  free up linked list data  */
  2266.   g_slist_free (display_list);
  2267. }
  2268.  
  2269.  
  2270. GDisplay *
  2271. gdisplays_check_valid (GDisplay  *gtest, 
  2272.                GimpImage *gimage)
  2273. {
  2274.   /* Give a gdisp check that it is still valid and points to the required
  2275.    * GimpImage. If not return the first gDisplay that does point to the 
  2276.    * gimage. If none found return NULL;
  2277.    */
  2278.  
  2279.   GSList *list = display_list;
  2280.   GDisplay *gdisp;
  2281.   GDisplay *gdisp_found = NULL;
  2282.  
  2283.   /*  traverse the linked list of displays  */
  2284.   while (list)
  2285.     {
  2286.       gdisp = (GDisplay *) list->data;
  2287.       if (gdisp == gtest)
  2288.     return (gtest);
  2289.       if (!gdisp_found && gdisp->gimage == gimage)
  2290.     gdisp_found = gdisp;
  2291.       list = g_slist_next (list);
  2292.     }
  2293.  
  2294.   return (gdisp_found);
  2295. }
  2296.  
  2297.  
  2298. static void
  2299. gdisplays_flush_whenever (gboolean now)
  2300. {
  2301.   static gboolean flushing = FALSE;
  2302.   GSList *list = display_list;
  2303.  
  2304.   /*  no flushing necessary without an interface  */
  2305.   if (no_interface)
  2306.     return;
  2307.  
  2308.   /*  this prevents multiple recursive calls to this procedure  */
  2309.   if (flushing == TRUE)
  2310.     {
  2311.       g_warning ("gdisplays_flush() called recursively.");
  2312.       return;
  2313.     }
  2314.  
  2315.   flushing = TRUE;
  2316.  
  2317.   /*  traverse the linked list of displays  */
  2318.   while (list)
  2319.     {
  2320.       gdisplay_flush_whenever ((GDisplay *) list->data, now);
  2321.       list = g_slist_next (list);
  2322.     }
  2323.  
  2324.   /*  for convenience, we call the L&C flush here  */
  2325.   lc_dialog_flush ();
  2326.  
  2327.   flushing = FALSE;
  2328. }
  2329.  
  2330. void
  2331. gdisplays_flush (void)
  2332. {
  2333.   gdisplays_flush_whenever (FALSE);
  2334. }
  2335.  
  2336. void
  2337. gdisplays_flush_now (void)
  2338. {
  2339.   gdisplays_flush_whenever (TRUE);
  2340. }
  2341.  
  2342. static guint
  2343. gdisplay_hash (GDisplay *display)
  2344. {
  2345.   return (gulong) display;
  2346. }
  2347.  
  2348. void
  2349. gdisplay_reconnect (GDisplay  *gdisp, 
  2350.             GimpImage *gimage)
  2351. {
  2352.   gint instance;
  2353.  
  2354.   g_return_if_fail (gdisp != NULL && gimage != NULL);
  2355.  
  2356.   if (gdisp->idle_render.active)
  2357.     {
  2358.       gtk_idle_remove (gdisp->idle_render.idleid);
  2359.       gdisp->idle_render.active = FALSE;
  2360.     }
  2361.  
  2362.   gtk_signal_disconnect_by_data (GTK_OBJECT (gdisp->gimage), gdisp);
  2363.   gdisp->gimage->disp_count--;
  2364.   gimage_delete (gdisp->gimage);
  2365.  
  2366.   instance = gimage->instance_count;
  2367.   gimage->instance_count++;
  2368.   gimage->disp_count++;
  2369.  
  2370.   gdisp->gimage = gimage;
  2371.   gdisp->instance = instance;
  2372.  
  2373.   /* reconnect our clean / dirty signals */
  2374.   gtk_signal_connect (GTK_OBJECT (gimage), "dirty",
  2375.               GTK_SIGNAL_FUNC(gdisplay_cleandirty_handler), gdisp);
  2376.   gtk_signal_connect (GTK_OBJECT (gimage), "clean",
  2377.               GTK_SIGNAL_FUNC(gdisplay_cleandirty_handler), gdisp);
  2378.  
  2379.   gdisplays_update_title (gimage);
  2380.  
  2381.   gdisplay_expose_full (gdisp);
  2382.   gdisplay_flush (gdisp);
  2383. }
  2384.  
  2385.  
  2386. void
  2387. gdisplays_reconnect (GimpImage *old,
  2388.              GimpImage *new)
  2389. {
  2390.   GSList   *list;
  2391.   GDisplay *gdisp;
  2392.  
  2393.   g_return_if_fail (old != NULL && new != NULL);
  2394.   
  2395.   for (list = display_list; list; list = g_slist_next (list))
  2396.     {
  2397.       gdisp = list->data;
  2398.       
  2399.       if (gdisp->gimage == old)
  2400.     gdisplay_reconnect (gdisp, new);
  2401.     }
  2402. }
  2403.  
  2404. /* Called whenever the underlying gimage is dirtied or cleaned */
  2405. static void
  2406. gdisplay_cleandirty_handler (GimpImage *gimage, 
  2407.                  void      *data)
  2408. {
  2409.   GDisplay *gdisp = data;
  2410.  
  2411.   gdisplay_update_title (gdisp);
  2412. }
  2413.  
  2414. void
  2415. gdisplays_foreach (GFunc    func, 
  2416.            gpointer user_data)
  2417. {
  2418.   g_slist_foreach (display_list, func, user_data);
  2419. }
  2420.