home *** CD-ROM | disk | FTP | other *** search
/ PC Pro 2002 April / pcpro0402.iso / essentials / graphics / Gimp / gimp-src-20001226.exe / src / gimp / plug-ins / gap / gap_mod_layer.c < prev    next >
Encoding:
C/C++ Source or Header  |  2000-12-10  |  39.2 KB  |  1,222 lines

  1. /* gap_mod_layer.c
  2.  * 1998.10.14 hof (Wolfgang Hofer)
  3.  *
  4.  * GAP ... Gimp Animation Plugins
  5.  *
  6.  * This Module contains:
  7.  * modify Layer (perform actions (like raise, set visible, apply filter)
  8.  *               - foreach selected layer
  9.  *               - in each frame of the selected framerange)
  10.  *
  11.  */
  12. /* The GIMP -- an image manipulation program
  13.  * Copyright (C) 1995 Spencer Kimball and Peter Mattis
  14.  *
  15.  * This program is free software; you can redistribute it and/or modify
  16.  * it under the terms of the GNU General Public License as published by
  17.  * the Free Software Foundation; either version 2 of the License, or
  18.  * (at your option) any later version.
  19.  *
  20.  * This program is distributed in the hope that it will be useful,
  21.  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  22.  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  23.  * GNU General Public License for more details.
  24.  *
  25.  * You should have received a copy of the GNU General Public License
  26.  * along with this program; if not, write to the Free Software
  27.  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
  28.  */
  29.  
  30. /* revision history:
  31.  * gimp   1.1.29b;   2000/11/30  hof: use g_snprintf
  32.  * gimp   1.1.28a;   2000/11/05  hof: check for GIMP_PDB_SUCCESS (not for FALSE)
  33.  * gimp   1.1.6;     1999/06/21  hof: bugix: wrong iterator total_steps and direction
  34.  * gimp   1.1.15.1;  1999/05/08  hof: bugix (dont mix GimpImageType with GimpImageBaseType)
  35.  * version 0.98.00   1998.11.27  hof: - use new module gap_pdb_calls.h
  36.  * version 0.97.00   1998.10.19  hof: - created module
  37.  */
  38.  
  39. /* SYTEM (UNIX) includes */ 
  40. #include <stdio.h>
  41. #include <stdlib.h>
  42. #include <string.h>
  43. #include <sys/types.h>
  44.  
  45. /* GIMP includes */
  46. #include "gtk/gtk.h"
  47. #include "config.h"
  48. #include "libgimp/stdplugins-intl.h"
  49. #include "libgimp/gimp.h"
  50.  
  51. /* GAP includes */
  52. #include "gap_arr_dialog.h"
  53. #include "gap_filter.h"
  54. #include "gap_filter_pdb.h"
  55. #include "gap_pdb_calls.h"
  56. #include "gap_match.h"
  57. #include "gap_lib.h"
  58. #include "gap_range_ops.h"
  59. #include "gap_mod_layer.h"
  60.  
  61.  
  62. extern      int gap_debug; /* ==0  ... dont print debug infos */
  63.  
  64.  
  65. /* ============================================================================
  66.  * p_layer_modify_dialog
  67.  *   retcode    
  68.  *               0   ... Generate Paramfile
  69.  *               1   ... Generate Paramfile and start mpeg_encode
  70.  * ============================================================================
  71.  */
  72. static
  73. int p_layer_modify_dialog(t_anim_info *ainfo_ptr,
  74.                    gint32 *range_from,  gint32 *range_to,
  75.                    gint32 *action_mode, gint32 *sel_mode,
  76.                    gint32 *sel_case,    gint32 *sel_invert,
  77.                    char *sel_pattern,   char   *new_layername)
  78. {
  79.   static t_arr_arg  argv[9];
  80.   static t_but_arg  b_argv[2];
  81.   gint   l_rc;
  82.  
  83.   /* Layer select modes */
  84.   static char *sel_args[7]    = { N_("Pattern is equal to LayerName"),
  85.                                   N_("Pattern is Start of LayerName"),
  86.                                   N_("Pattern is End of Layername"),
  87.                                   N_("Pattern is a Part of LayerName"),
  88.                                   N_("Pattern is LayerstackNumber List"),
  89.                                   N_("Pattern is REVERSE-stack List"),
  90.                                   N_("All Visible (ignore Pattern)")
  91.                                   };
  92.   static char *sel_help[7]    = { N_("Select all Layers where Layername is equal to Pattern"),
  93.                                   N_("Select all Layers where Layername starts with Pattern"),
  94.                                   N_("Select all Layers where Layername ends up with Pattern"),
  95.                                   N_("Select all Layers where Layername contains Pattern"),
  96.                                   N_("Select Layerstack positions.\n0, 4-5, 8\nwhere 0 == Top-layer"),
  97.                                   N_("Select Layerstack positions.\n0, 4-5, 8\nwhere 0 == BG-layer"),
  98.                                   N_("Select all visible Layers")
  99.                                   };
  100.  
  101.   /* action items what to do with the selected layer(s) */
  102.   static char *action_args[13]  = { N_("Set Layer(s) visible"),
  103.                                     N_("Set Layer(s) invisible"),
  104.                                   N_("Set Layer(s) linked"),
  105.                                   N_("Set Layer(s) unlinked"),
  106.                                   N_("Raise Layer(s)"),
  107.                                   N_("Lower Layer(s)"),
  108.                                   N_("Merge Layer(s) expand as necessary"),
  109.                                   N_("Merge Layer(s) clipped to image"),
  110.                                   N_("Merge Layer(s) clipped to bg-layer"),
  111.                                   N_("Apply filter on Layer(s)"),
  112.                                   N_("Duplicate Layer(s)"),
  113.                                   N_("Delete Layer(s)"),
  114.                                   N_("Rename Layer(s)")
  115.                                   };
  116.                                   
  117.  
  118. /*                                                                   
  119.   static char *action_help[13]  = {"set all selected layers visible",
  120.                                   "set all selected layers  invisible",
  121.                                   "set all selected layers  linked",
  122.                                   "set all selected layers  unlinked",
  123.                                   "raise all selected layers",
  124.                                   "lower all selected layers",
  125.                                   "merge expand as necessary",
  126.                                   "merge clipped to image",
  127.                                   "merge clipped to bg-layer",
  128.                                   "APPLY FILTER to all selected layers",
  129.                                   "duplicate all selected layers",
  130.                                   "delete REMOVES all selected layers",
  131.                                   "rename all selected layers\nto NewLayername."
  132.                                   };
  133. */
  134.  
  135.   int get_textize_loop;
  136.  
  137.   for (get_textize_loop = 0; get_textize_loop < 7; get_textize_loop++) {
  138.     sel_args[get_textize_loop] = gettext(sel_args[get_textize_loop]);
  139.     sel_help[get_textize_loop] = gettext(sel_help[get_textize_loop]);
  140.   }
  141.   for (get_textize_loop = 0; get_textize_loop < 13; get_textize_loop++)
  142.     action_args[get_textize_loop] = gettext(action_args[get_textize_loop]);
  143.  
  144.   l_rc = -1;
  145.   
  146.   /* the 3 Action Buttons */
  147.     b_argv[0].but_txt  = _("OK");
  148.     b_argv[0].but_val  = 0;
  149.     b_argv[1].but_txt  = _("Cancel");
  150.     b_argv[1].but_val  = -1;
  151.   
  152.   p_init_arr_arg(&argv[0], WGT_LABEL);
  153.   argv[0].label_txt = _("Perform function on one or more Layer(s)\nin all frames of the selected frame range\n");
  154.  
  155.   p_init_arr_arg(&argv[1], WGT_INT_PAIR);
  156.   argv[1].constraint = TRUE;
  157.   argv[1].label_txt = _("From Frame:");
  158.   argv[1].help_txt  = _("first handled frame");
  159.   argv[1].int_min   = (gint)ainfo_ptr->first_frame_nr;
  160.   argv[1].int_max   = (gint)ainfo_ptr->last_frame_nr;
  161.   argv[1].int_ret   = (gint)ainfo_ptr->curr_frame_nr;
  162.  
  163.   p_init_arr_arg(&argv[2], WGT_INT_PAIR);
  164.   argv[2].constraint = TRUE;
  165.   argv[2].label_txt = _("To Frame:");
  166.   argv[2].help_txt  = _("last handled frame");
  167.   argv[2].int_min   = (gint)ainfo_ptr->first_frame_nr;
  168.   argv[2].int_max   = (gint)ainfo_ptr->last_frame_nr;
  169.   argv[2].int_ret   = (gint)ainfo_ptr->last_frame_nr;
  170.  
  171.  
  172.   /* Layer select mode RADIO buttons */
  173.   p_init_arr_arg(&argv[3], WGT_RADIO);
  174.   argv[3].label_txt = _("Select Layer(s):");
  175.   argv[3].radio_argc = 7;
  176.   argv[3].radio_argv = sel_args;
  177.   argv[3].radio_help_argv = sel_help;
  178.   argv[3].radio_ret  = 4;
  179.  
  180.   /* Layer select pattern string */
  181.   sel_pattern[0] = '0';
  182.   sel_pattern[1] = '\0';
  183.   p_init_arr_arg(&argv[4], WGT_TEXT);
  184.   argv[4].label_txt = _("Select Pattern:");
  185.   argv[4].entry_width = 140;       /* pixel */
  186.   argv[4].help_txt  = _("String to identify layer names    \nor layerstack position numbers\n0,3-5");
  187.   argv[4].text_buf_len = MAX_LAYERNAME;
  188.   argv[4].text_buf_ret = sel_pattern;
  189.  
  190.   /* case sensitive checkbutton */
  191.   p_init_arr_arg(&argv[5], WGT_TOGGLE);
  192.   argv[5].label_txt = _("Case sensitive");
  193.   argv[5].help_txt  = _("Lowercase and UPPERCASE letters are considered as different");
  194.   argv[5].int_ret   = 1;
  195.  
  196.   /* invert selection checkbutton */
  197.   p_init_arr_arg(&argv[6], WGT_TOGGLE);
  198.   argv[6].label_txt = _("Invert Selection");
  199.   argv[6].help_txt  = _("Perform actions on all unselected Layers");
  200.   argv[6].int_ret   = 0;
  201.  
  202.   /* desired action to perform OPTIONMENU  */
  203.   p_init_arr_arg(&argv[7], WGT_OPTIONMENU);
  204.   argv[7].label_txt = _("Function:");
  205.   argv[7].radio_argc = 13;
  206.   argv[7].radio_argv = action_args;
  207.   /* argv[7].radio_help_argv = action_help */
  208.   argv[7].help_txt = _("Function to be performed on all selected layers");
  209.   argv[7].radio_ret  = 0;
  210.  
  211.   /* a new name for the handled Layer(s) */
  212.   *new_layername = '\0';
  213.   p_init_arr_arg(&argv[8], WGT_TEXT);
  214.   argv[8].label_txt = _("New Layername:");
  215.   argv[8].entry_width = 140;       /* pixel */
  216.   argv[8].help_txt  = _("New Layername for all handled layers \n[####] is replaced by frame number\n(is used on function rename only)");
  217.   argv[8].text_buf_len = MAX_LAYERNAME;
  218.   argv[8].text_buf_ret = new_layername;
  219.  
  220.  
  221.   l_rc =  p_array_std_dialog( _("Frames Modify"),
  222.                                 _("Settings"),
  223.                                  9,   argv,      /* widget array */
  224.                                  2,   b_argv,    /* button array */
  225.                                  0);
  226.  
  227.   /* return the entered values */
  228.   *range_from           = argv[1].int_ret;
  229.   *range_to             = argv[2].int_ret;
  230.   *sel_mode             = argv[3].int_ret;
  231.                        /*     [4] sel_pattern  */
  232.   *sel_case             = argv[5].int_ret;
  233.   *sel_invert           = argv[6].int_ret;
  234.   *action_mode          = argv[7].int_ret;
  235.                        /*     [8] l_new_layername */
  236.        
  237.   
  238.   return (l_rc);   
  239. }    /* end p_layer_modify_dialog */
  240.  
  241.  
  242. /* ============================================================================
  243.  * p_pitstop_dialog
  244.  *   return -1  on CANCEL
  245.  *           0  on Continue (OK)
  246.  * ============================================================================
  247.  */
  248. static gint
  249. p_pitstop_dialog(gint text_flag, char *filter_procname)
  250. {
  251.   gchar *l_env;
  252.   gchar *l_msg;
  253.   static t_but_arg  l_but_argv[2];
  254.   gint              l_but_argc;
  255.   gint              l_argc;
  256.   static t_arr_arg  l_argv[1];
  257.   int               l_continue;
  258.   
  259.     
  260.  
  261.  
  262.   l_but_argv[0].but_txt  = _("Continue");
  263.   l_but_argv[0].but_val  = 0;
  264.   l_but_argv[1].but_txt  = _("Cancel");
  265.   l_but_argv[1].but_val  = -1;
  266.  
  267.   l_but_argc = 2;
  268.   l_argc = 0;
  269.  
  270.   /* optional dialog between both calls (to see the effect of 1.call) */
  271.   l_env = g_getenv("GAP_FILTER_PITSTOP");
  272.   if(l_env != NULL)
  273.   {
  274.      if((*l_env == 'N') || (*l_env == 'n'))
  275.      {
  276.        return 0;  /* continue without question */
  277.      }
  278.   }
  279.   if(text_flag == 0)
  280.   {
  281.      l_msg = g_strdup_printf (_("2nd call of %s\n(define end-settings)"), filter_procname);
  282.   }
  283.   else
  284.   {
  285.      l_msg = g_strdup_printf ( _("Non-Interactive call of %s\n(for all selected layers)"), filter_procname);
  286.   }
  287.   l_continue = p_array_std_dialog ( _("Animated Filter apply"), l_msg,
  288.                      l_argc,     l_argv, 
  289.                      l_but_argc, l_but_argv, 0);
  290.   g_free (l_msg);
  291.   
  292.   return (l_continue);
  293.     
  294. }    /* end p_pitstop_dialog */
  295.  
  296.  
  297. /* ============================================================================
  298.  * p_get_1st_selected
  299.  *   return index of the 1.st selected layer
  300.  *   or -1 if no selection was found
  301.  * ============================================================================
  302.  */
  303. int
  304. p_get_1st_selected (t_LayliElem * layli_ptr, gint nlayers)
  305. {
  306.   int  l_idx;
  307.  
  308.   for(l_idx = 0; l_idx < nlayers; l_idx++)
  309.   {
  310.     if(layli_ptr[l_idx].selected != FALSE)
  311.     {
  312.       return (l_idx);
  313.     }
  314.   }
  315.   return(-1);
  316. }    /* end p_get_1st_selected */
  317.  
  318.  
  319. /* ============================================================================
  320.  * p_alloc_layli
  321.  * returns   pointer to a new allocated image_id of the new created multilayer image
  322.  *           (or NULL on error)
  323.  * ============================================================================
  324.  */
  325.  
  326. t_LayliElem *
  327. p_alloc_layli(gint32 image_id, gint32 *l_sel_cnt, gint *nlayers,
  328.               gint32 sel_mode,
  329.               gint32 sel_case,
  330.           gint32 sel_invert,
  331.               char *sel_pattern )
  332. {
  333.   gint32 *l_layers_list;
  334.   gint32  l_layer_id;
  335.   gint32  l_idx;
  336.   t_LayliElem *l_layli_ptr;
  337.   char      *l_layername;
  338.  
  339.   *l_sel_cnt = 0;
  340.  
  341.   l_layers_list = gimp_image_get_layers(image_id, nlayers);
  342.   if(l_layers_list == NULL)
  343.   {
  344.     return(NULL);
  345.   }
  346.   
  347.   l_layli_ptr = g_new0(t_LayliElem, (*nlayers));
  348.   if(l_layli_ptr == NULL)
  349.   {
  350.      g_free (l_layers_list);
  351.      return(NULL); 
  352.   }
  353.  
  354.   for(l_idx = 0; l_idx < (*nlayers); l_idx++)
  355.   {
  356.     l_layer_id = l_layers_list[l_idx];
  357.     l_layername = gimp_layer_get_name(l_layer_id); 
  358.     l_layli_ptr[l_idx].layer_id  = l_layer_id;
  359.     l_layli_ptr[l_idx].visible   = gimp_layer_get_visible(l_layer_id);
  360.     l_layli_ptr[l_idx].selected  = p_match_layer(l_idx,
  361.                                                  l_layername,
  362.                                                  sel_pattern,
  363.                          sel_mode,
  364.                          sel_case,
  365.                          sel_invert,
  366.                          *nlayers, l_layer_id);
  367.     if(l_layli_ptr[l_idx].selected != FALSE)
  368.     {
  369.       (*l_sel_cnt)++;  /* count all selected layers */
  370.     }
  371.     if(gap_debug) printf("gap: p_alloc_layli [%d] id:%d, sel:%d %s\n",
  372.                          (int)l_idx, (int)l_layer_id,
  373.              (int)l_layli_ptr[l_idx].selected, l_layername);
  374.     g_free (l_layername);
  375.   }
  376.  
  377.   g_free (l_layers_list);
  378.  
  379.   return( l_layli_ptr );
  380. }        /* end p_alloc_layli */
  381.  
  382. /* ============================================================================
  383.  * p_prevent_empty_image
  384.  *    check if the resulting image has at least one layer
  385.  *    (gimp 1.0.0 tends to crash on layerless images)
  386.  * ============================================================================
  387.  */
  388.  
  389. void p_prevent_empty_image(gint32 image_id)
  390. {
  391.   GimpImageBaseType l_type;
  392.   guint   l_width, l_height;
  393.   gint32  l_layer_id;
  394.   gint    l_nlayers;
  395.   gint32 *l_layers_list;
  396.  
  397.   l_layers_list = gimp_image_get_layers(image_id, &l_nlayers);
  398.   if(l_layers_list != NULL)
  399.   {
  400.      g_free (l_layers_list);
  401.   }
  402.   else l_nlayers = 0;
  403.   
  404.   if(l_nlayers == 0)
  405.   {
  406.      /* the resulting image has no layer, add a transparent dummy layer */
  407.  
  408.      /* get info about the image */
  409.      l_width  = gimp_image_width(image_id);
  410.      l_height = gimp_image_height(image_id);
  411.      l_type   = gimp_image_base_type(image_id);
  412.  
  413.      l_type   = (l_type * 2); /* convert from GimpImageBaseType to GimpImageType */
  414.  
  415.      /* add a transparent dummy layer */
  416.      l_layer_id = gimp_layer_new(image_id, "dummy",
  417.                                     l_width, l_height,  l_type,
  418.                                     0.0,       /* Opacity full transparent */     
  419.                                     0);        /* NORMAL */
  420.      gimp_image_add_layer(image_id, l_layer_id, 0);
  421.   }
  422.  
  423. }    /* end p_prevent_empty_image */
  424.  
  425.  
  426. /* ============================================================================
  427.  * p_raise_layer
  428.  *   raise layer (check if possible before)
  429.  *   (without the check each failed attempt would open an inf window)
  430.  * ============================================================================
  431.  */
  432. static void
  433. p_raise_layer (gint32 image_id, gint32 layer_id, t_LayliElem * layli_ptr, gint nlayers)
  434. {
  435.   if(! gimp_drawable_has_alpha (layer_id)) return; /* has no alpha channel */
  436.  
  437.   if(layli_ptr[0].layer_id == layer_id)  return;   /* is already on top */
  438.  
  439.   gimp_image_raise_layer(image_id, layer_id);
  440. }    /* end p_raise_layer */
  441.  
  442. static void
  443. p_lower_layer (gint32 image_id, gint32 layer_id, t_LayliElem * layli_ptr, gint nlayers)
  444. {
  445.   if(! gimp_drawable_has_alpha (layer_id)) return; /* has no alpha channel */
  446.  
  447.   if(layli_ptr[nlayers-1].layer_id == layer_id)  return;   /* is already on bottom */
  448.  
  449.   if(nlayers > 1)
  450.   {
  451.     if((layli_ptr[nlayers-2].layer_id == layer_id)
  452.     && (! gimp_drawable_has_alpha (layli_ptr[nlayers-1].layer_id)))
  453.     {
  454.       /* the layer is one step above a "bottom-layer without alpha" */
  455.       return;
  456.     }
  457.   }
  458.  
  459.   gimp_image_lower_layer(image_id, layer_id);
  460. }    /* end p_lower_layer */
  461.  
  462. /* ============================================================================
  463.  * p_apply_action
  464.  *
  465.  *    perform function (defined by action_mode)
  466.  *    on all selcted layer(s)
  467.  *   
  468.  * returns   0 if all done OK
  469.  *           (or -1 on error)
  470.  * ============================================================================
  471.  */
  472.  
  473. static int 
  474. p_apply_action(gint32 image_id,
  475.           gint32 action_mode,
  476.           t_LayliElem *layli_ptr,
  477.           gint nlayers,
  478.           gint32 sel_cnt,
  479.           
  480.           long  from,
  481.           long  to,
  482.           long  curr,
  483.           char *new_layername,
  484.           char *filter_procname
  485.           )
  486. {
  487.   int   l_idx;
  488.   int   l_rc;
  489.   gint32  l_layer_id;
  490.   gint32  l_new_layer_id;
  491.   gint    l_merge_mode;
  492.   gint    l_vis_result;
  493.   char    l_name_buff[MAX_LAYERNAME];
  494.   
  495.   if(gap_debug) fprintf(stderr, "gap: p_apply_action START\n");      
  496.  
  497.   l_rc = 0; 
  498.   l_merge_mode = -44; /* none of the flatten modes */
  499.  
  500.   if(action_mode == ACM_MERGE_EXPAND) l_merge_mode = FLAM_MERG_EXPAND;
  501.   if(action_mode == ACM_MERGE_IMG)    l_merge_mode = FLAM_MERG_CLIP_IMG;
  502.   if(action_mode == ACM_MERGE_BG)     l_merge_mode = FLAM_MERG_CLIP_BG;
  503.  
  504.   /* merge actions require one call per image */  
  505.   if(l_merge_mode != (-44))
  506.   {
  507.       if(sel_cnt < 2)
  508.       {
  509.         return(0);  /* OK, nothing to merge */
  510.       }
  511.      
  512.      l_vis_result = FALSE;
  513.      
  514.      /* set selected layers visible, all others invisible for merge */
  515.      for(l_idx = 0; l_idx < nlayers; l_idx++)
  516.      {
  517.        if(layli_ptr[l_idx].selected == FALSE)
  518.        {
  519.           gimp_layer_set_visible(layli_ptr[l_idx].layer_id, FALSE);
  520.        }
  521.        else
  522.        {
  523.           if(gimp_layer_get_visible(layli_ptr[l_idx].layer_id))
  524.       {
  525.         /* result will we visible if at least one of the
  526.          * selected layers was visible before
  527.          */
  528.         l_vis_result = TRUE;
  529.       }
  530.           gimp_layer_set_visible(layli_ptr[l_idx].layer_id, TRUE);
  531.        }
  532.      }
  533.  
  534.      /* merge all visible layers (i.e. all selected layers) */
  535.      l_layer_id = gimp_image_merge_visible_layers (image_id, l_merge_mode);
  536.      if(l_vis_result == FALSE)
  537.      {
  538.         gimp_layer_set_visible(l_layer_id, FALSE);
  539.      }
  540.      
  541.      /* if new_layername is available use that name
  542.       * for the new merged layer
  543.       */
  544.      if (!p_is_empty (new_layername))
  545.      {
  546.      p_substitute_framenr(&l_name_buff[0], sizeof(l_name_buff),
  547.                           new_layername, curr);
  548.      gimp_layer_set_name(l_layer_id, &l_name_buff[0]);
  549.      }
  550.  
  551.      /* restore visibility flags after merge */
  552.      for(l_idx = 0; l_idx < nlayers; l_idx++)
  553.      {
  554.        if(layli_ptr[l_idx].selected == FALSE)
  555.        {
  556.          gimp_layer_set_visible(layli_ptr[l_idx].layer_id, 
  557.                             layli_ptr[l_idx].visible);
  558.        }
  559.      }
  560.      
  561.      return(0);
  562.   }
  563.  
  564.   /* -----------------------------*/  
  565.   /* non-merge actions require calls foreach selected layer */  
  566.   for(l_idx = 0; (l_idx < nlayers) && (l_rc == 0); l_idx++)
  567.   {
  568.     l_layer_id = layli_ptr[l_idx].layer_id;
  569.  
  570.     /* apply function defined by action_mode */
  571.     if(layli_ptr[l_idx].selected != FALSE)
  572.     {
  573.       if(gap_debug) fprintf(stderr, "gap: p_apply_action on selected LayerID:%d layerstack:%d\n",
  574.                            (int)l_layer_id, (int)l_idx);      
  575.       switch(action_mode)
  576.       {
  577.         case ACM_SET_VISIBLE:
  578.           gimp_layer_set_visible(l_layer_id, TRUE);
  579.       break;
  580.         case ACM_SET_INVISIBLE:
  581.           gimp_layer_set_visible(l_layer_id, FALSE);
  582.       break;
  583.         case ACM_SET_LINKED:
  584.           l_rc = p_layer_set_linked (l_layer_id, TRUE);
  585.       break;
  586.         case ACM_SET_UNLINKED:
  587.           l_rc = p_layer_set_linked (l_layer_id, FALSE);
  588.       break;
  589.         case ACM_RAISE:
  590.       p_raise_layer(image_id, l_layer_id, layli_ptr, nlayers);
  591.       break;
  592.         case ACM_LOWER:
  593.       p_lower_layer(image_id, l_layer_id, layli_ptr, nlayers);
  594.       break;
  595.         case ACM_APPLY_FILTER:
  596.       l_rc = p_call_plugin(filter_procname,
  597.                            image_id,
  598.                    l_layer_id,
  599.                    GIMP_RUN_WITH_LAST_VALS);
  600.           if(gap_debug) fprintf(stderr, "gap: p_apply_action FILTER:%s rc =%d\n",
  601.                                 filter_procname, (int)l_rc);      
  602.       break;
  603.         case ACM_DUPLICATE:
  604.       l_new_layer_id = gimp_layer_copy(l_layer_id);
  605.       gimp_image_add_layer (image_id, l_new_layer_id, -1); 
  606.       if (!p_is_empty (new_layername))
  607.       {
  608.           p_substitute_framenr(&l_name_buff[0], sizeof(l_name_buff),
  609.                                new_layername, curr);
  610.           gimp_layer_set_name(l_new_layer_id, &l_name_buff[0]);
  611.       }
  612.       break;
  613.         case ACM_DELETE:
  614.       gimp_image_remove_layer(image_id, l_layer_id);
  615.       break;
  616.         case ACM_RENAME:
  617.       p_substitute_framenr(&l_name_buff[0], sizeof(l_name_buff),
  618.                             new_layername, curr);
  619.       gimp_layer_set_name(l_layer_id, &l_name_buff[0]);
  620.       break;
  621.         default:
  622.       break;
  623.       }
  624.     }
  625.   }
  626.  
  627.   return (l_rc); 
  628. }    /* end p_apply_action */
  629.  
  630.  
  631. /* ============================================================================
  632.  * p_do_filter_dialogs
  633.  *    additional dialog steps
  634.  *    a) gap_pdb_browser (select the filter)
  635.  *    b) 1st interactive filtercall
  636.  *    c) 1st pitstop dialog
  637.  * ============================================================================
  638.  */
  639. static int
  640. p_do_filter_dialogs(t_anim_info *ainfo_ptr, 
  641.                     gint32 image_id, gint32 *dpy_id, 
  642.                     t_LayliElem * layli_ptr, gint nlayers ,
  643.                     char *filter_procname, int filt_len,
  644.             gint *plugin_data_len,
  645.             t_apply_mode *apply_mode
  646.             )
  647. {
  648.   t_gap_db_browse_result  l_browser_result;
  649.   gint32   l_layer_id;
  650.   int      l_rc;
  651.   int      l_idx;
  652.   static char l_key_from[512];
  653.   static gint l_gtk_init = TRUE;   /* gkt_init at 1.st call */
  654.  
  655.   if(ainfo_ptr->run_mode == GIMP_RUN_INTERACTIVE)
  656.   { 
  657.     l_gtk_init = FALSE;  /* gtk_init was done in 1.st modify dialog before */
  658.   }
  659.  
  660.  
  661.   /* GAP-PDB-Browser Dialog */
  662.   /* ---------------------- */
  663.   if(gap_db_browser_dialog( _("Select Filter for Animated frames-apply"),
  664.                                  _("Apply Constant"),
  665.                                  _("Apply Varying"),
  666.                                  p_constraint_proc,
  667.                                  p_constraint_proc_sel1,
  668.                                  p_constraint_proc_sel2,
  669.                                  &l_browser_result,
  670.                  l_gtk_init   /* do not call gtk_init */
  671.               ) 
  672.     < 0)
  673.   {
  674.       if(gap_debug) fprintf(stderr, "DEBUG: gap_db_browser_dialog cancelled\n");
  675.       return -1;
  676.   }
  677.     
  678.   p_arr_gtk_init(FALSE); /* disable the initial gtk_init in gap_arr_dialog's
  679.                           * (gtk_init was done before)
  680.                           */
  681.  
  682.   strncpy(filter_procname, l_browser_result.selected_proc_name, filt_len-1);
  683.   filter_procname[filt_len-1] = '\0';
  684.   if(l_browser_result.button_nr == 1) *apply_mode = PTYP_VARYING_LINEAR;
  685.   else                                *apply_mode = PAPP_CONSTANT;
  686.  
  687.   /* 1.st INTERACTIV Filtercall dialog */
  688.   /* --------------------------------- */
  689.   /* check for the Plugin */
  690.  
  691.   l_rc = p_procedure_available(filter_procname, PTYP_CAN_OPERATE_ON_DRAWABLE);
  692.   if(l_rc < 0)
  693.   {
  694.      fprintf(stderr, "ERROR: Plugin not available or wrong type %s\n", filter_procname);
  695.      return -1;
  696.   }
  697.  
  698.   /* get 1.st selected layer (of 1.st handled frame in range ) */
  699.   l_idx = p_get_1st_selected(layli_ptr, nlayers);
  700.   if(l_idx < 0)
  701.   {
  702.      fprintf(stderr, "ERROR: No layer selected in 1.st handled frame\n");
  703.      return (-1);
  704.   }
  705.   l_layer_id = layli_ptr[l_idx].layer_id;
  706.   
  707.   /* open a view for the 1.st handled frame */
  708.   *dpy_id = gimp_display_new (image_id);
  709.  
  710.   l_rc = p_call_plugin(filter_procname, image_id, l_layer_id, GIMP_RUN_INTERACTIVE);
  711.  
  712.   /* OOPS: cant delete the display here, because
  713.    *       closing the last display seems to free up
  714.    *       at least parts of the image,
  715.    *       and causes crashes if the image_id is used
  716.    *       in further gimp procedures
  717.    */
  718.   /* gimp_display_delete(*dpy_id); */
  719.  
  720.   /* get values, then store with suffix "_ITER_FROM" */
  721.   *plugin_data_len = p_get_data(filter_procname);
  722.   if(*plugin_data_len > 0)
  723.   {
  724.      g_snprintf(l_key_from, sizeof(l_key_from), "%s_ITER_FROM", filter_procname);
  725.      p_set_data(l_key_from, *plugin_data_len);
  726.   }
  727.   else
  728.   {
  729.     return (-1);
  730.   }
  731.  
  732.   if(*apply_mode != PTYP_VARYING_LINEAR)
  733.   {
  734.     return (p_pitstop_dialog(1, filter_procname));
  735.   }
  736.  
  737.   return(0);
  738. }    /* end p_do_filter_dialogs */
  739.  
  740.  
  741. /* ============================================================================
  742.  * p_do_2nd_filter_dialogs
  743.  *    d) [ 2nd interactive filtercall
  744.  *    e)   2nd pitstop dialog ]
  745.  *
  746.  *   (temporary) open the last frame of the range
  747.  *   get its 1.st selected laye
  748.  *   and do the Interctive Filtercall (to get the end-values)
  749.  *
  750.  * then close everything (without save).
  751.  * (the last frame will be processed later, with all its selected layers)
  752.  * ============================================================================
  753.  */
  754. static gint
  755. p_do_2nd_filter_dialogs(char *filter_procname,
  756.                         t_apply_mode  l_apply_mode,
  757.             char *last_frame_filename,
  758.             gint32 sel_mode, gint32 sel_case,
  759.             gint32 sel_invert, char *sel_pattern
  760.                        )
  761. {
  762.   gint32   l_layer_id;
  763.   gint32   l_dpy_id;
  764.   int      l_rc;
  765.   int      l_idx;
  766.   static char l_key_to[512];
  767.   static char l_key_from[512];
  768.   gint32  l_last_image_id;
  769.   t_LayliElem *l_layli_ptr;
  770.   gint       l_nlayers;
  771.   gint32     l_sel_cnt;
  772.   gint       l_plugin_data_len;
  773.  
  774.   l_layli_ptr = NULL;
  775.   l_rc = -1;       /* assume cancel or error */
  776.   l_last_image_id = -1;
  777.   l_dpy_id = -1;
  778.   
  779.   /* 2.nd INTERACTIV Filtercall dialog */
  780.   /* --------------------------------- */
  781.   if(last_frame_filename == NULL)
  782.   {
  783.     return (-1);  /* there is no 2.nd frame for 2.nd filter call */
  784.   }
  785.  
  786.   if(p_pitstop_dialog(0, filter_procname) < 0)
  787.      goto cleanup;
  788.  
  789.   /* load last frame into temporary image */
  790.   l_last_image_id = p_load_image(last_frame_filename);
  791.   if (l_last_image_id < 0)
  792.      goto cleanup;
  793.  
  794.   /* get informations (id, visible, selected) about all layers */
  795.   l_layli_ptr = p_alloc_layli(l_last_image_id, &l_sel_cnt, &l_nlayers,
  796.                                sel_mode, sel_case, sel_invert, sel_pattern);
  797.  
  798.   if (l_layli_ptr == NULL)
  799.      goto cleanup;
  800.  
  801.   /* get 1.st selected layer (of last handled frame in range ) */
  802.   l_idx = p_get_1st_selected(l_layli_ptr, l_nlayers);
  803.   if(l_idx < 0)
  804.   {
  805.      p_msg_win (GIMP_RUN_INTERACTIVE, _("GAP Modify: No layer selected in last handled frame"));
  806.      goto cleanup;
  807.   }
  808.   l_layer_id = l_layli_ptr[l_idx].layer_id;
  809.  
  810.   /* open a view for the last handled frame */
  811.   l_dpy_id = gimp_display_new (l_last_image_id);
  812.  
  813.   /* 2.nd INTERACTIV Filtercall dialog */
  814.   /* --------------------------------- */
  815.   l_rc = p_call_plugin(filter_procname, l_last_image_id, l_layer_id, GIMP_RUN_INTERACTIVE);
  816.  
  817.   /* get values, then store with suffix "_ITER_TO" */
  818.   l_plugin_data_len = p_get_data(filter_procname);
  819.   if(l_plugin_data_len <= 0)
  820.      goto cleanup;
  821.  
  822.    g_snprintf(l_key_to, sizeof(l_key_to), "%s_ITER_TO", filter_procname);
  823.    p_set_data(l_key_to, l_plugin_data_len);
  824.  
  825.    /* get FROM values */
  826.    g_snprintf(l_key_from, sizeof(l_key_from), "%s_ITER_FROM", filter_procname);
  827.    l_plugin_data_len = p_get_data(l_key_from);
  828.    p_set_data(filter_procname, l_plugin_data_len);
  829.  
  830.   l_rc = p_pitstop_dialog(1, filter_procname);
  831.   
  832. cleanup:
  833.   if(l_dpy_id >= 0)        gimp_display_delete(l_dpy_id);
  834.   if(l_last_image_id >= 0) gimp_image_delete(l_last_image_id);
  835.   if(l_layli_ptr != NULL)  g_free(l_layli_ptr);
  836.  
  837.   return (l_rc);
  838.  
  839.     
  840. }    /* end p_do_2nd_filter_dialogs */
  841.  
  842.  
  843. /* ============================================================================
  844.  * p_frames_modify
  845.  *
  846.  *   foreach frame of the range (given by range_from and range_to)
  847.  *   perform function defined by action_mode
  848.  *   on all selected layer(s) described by sel_mode, sel_case
  849.  *                                         sel_invert and sel_pattern
  850.  * returns   0 if all done OK
  851.  *           (or -1 on error or cancel)
  852.  * ============================================================================
  853.  */
  854. static gint32
  855. p_frames_modify(t_anim_info *ainfo_ptr,
  856.                    long range_from, long range_to,
  857.                    gint32 action_mode, gint32 sel_mode,
  858.                    gint32 sel_case, gint32 sel_invert,
  859.                    char *sel_pattern, char *new_layername)
  860. {
  861.   long    l_cur_frame_nr;
  862.   long    l_step, l_begin, l_end;
  863.   gint32  l_tmp_image_id;
  864.   gint32  l_dpy_id;
  865.   gint       l_nlayers;
  866.   gdouble    l_percentage, l_percentage_step;  
  867.   int        l_rc;
  868.   int        l_idx;
  869.   gint32     l_sel_cnt;
  870.   t_LayliElem *l_layli_ptr;
  871.  
  872.   GimpParam     *l_params;
  873.   gint        l_retvals;
  874.   gint        l_plugin_data_len;
  875.   char       l_filter_procname[256];
  876.   char      *l_plugin_iterator;
  877.   gdouble    l_cur_step;
  878.   gint       l_total_steps;
  879.   t_apply_mode  l_apply_mode;
  880.   char         *l_last_frame_filename;
  881.  
  882.   
  883.  
  884.  
  885.   if(gap_debug) fprintf(stderr, "gap: p_frames_modify START, action_mode=%d  sel_mode=%d case=%d, invert=%d patt:%s:\n",
  886.         (int)action_mode, (int)sel_mode, (int)sel_case, (int)sel_invert, sel_pattern);
  887.  
  888.   l_percentage = 0.0;
  889.   if(ainfo_ptr->run_mode == GIMP_RUN_INTERACTIVE)
  890.   { 
  891.     gimp_progress_init( _("Modifying Frames/Layer(s)..."));
  892.   }
  893.  
  894.  
  895.   l_begin = range_from;
  896.   l_end   = range_to;
  897.   l_tmp_image_id = -1;
  898.   l_layli_ptr = NULL;
  899.   l_rc = 0;
  900.   l_plugin_iterator = NULL;
  901.   l_plugin_data_len = 0;
  902.   l_apply_mode = PAPP_CONSTANT;
  903.   l_dpy_id = -1;
  904.   l_last_frame_filename = NULL;
  905.  
  906.   /* init step direction */  
  907.   if(range_from > range_to)
  908.   {
  909.     l_step  = -1;     /* operate in descending (reverse) order */
  910.     l_percentage_step = 1.0 / ((1.0 + range_from) - range_to);
  911.  
  912.     if(range_to < ainfo_ptr->first_frame_nr)
  913.     { l_begin = ainfo_ptr->first_frame_nr;
  914.     }
  915.     if(range_from > ainfo_ptr->last_frame_nr)
  916.     { l_end = ainfo_ptr->last_frame_nr;
  917.     }
  918.  
  919.     l_total_steps = l_begin - l_end;
  920.   }
  921.   else
  922.   {
  923.     l_step  = 1;      /* operate in ascending order */
  924.     l_percentage_step = 1.0 / ((1.0 + range_to) - range_from);
  925.  
  926.     if(range_from < ainfo_ptr->first_frame_nr)
  927.     { l_begin = ainfo_ptr->first_frame_nr;
  928.     }
  929.     if(range_to > ainfo_ptr->last_frame_nr)
  930.     { l_end = ainfo_ptr->last_frame_nr;
  931.     }
  932.  
  933.     l_total_steps = l_end - l_begin;
  934.   }
  935.   
  936.   l_cur_step = l_total_steps;
  937.  
  938.   l_cur_frame_nr = l_begin;
  939.   while(1)              /* loop foreach frame in range */
  940.   {
  941.     if(gap_debug) fprintf(stderr, "p_frames_modify While l_cur_frame_nr = %d\n", (int)l_cur_frame_nr);
  942.  
  943.     /* build the frame name */
  944.     if(ainfo_ptr->new_filename != NULL) g_free(ainfo_ptr->new_filename);
  945.     ainfo_ptr->new_filename = p_alloc_fname(ainfo_ptr->basename,
  946.                                         l_cur_frame_nr,
  947.                                         ainfo_ptr->extension);
  948.     if(ainfo_ptr->new_filename == NULL)
  949.        goto error;
  950.  
  951.     /* load current frame into temporary image */
  952.     l_tmp_image_id = p_load_image(ainfo_ptr->new_filename);
  953.     if(l_tmp_image_id < 0)
  954.        goto error;
  955.  
  956.     /* get informations (id, visible, selected) about all layers */
  957.     l_layli_ptr = p_alloc_layli(l_tmp_image_id, &l_sel_cnt, &l_nlayers,
  958.                                 sel_mode, sel_case, sel_invert, sel_pattern);
  959.  
  960.     if(l_layli_ptr == NULL)
  961.     {
  962.        printf("gap: p_frames_modify: cant alloc layer info list\n");
  963.        goto error;
  964.     }
  965.  
  966.     if((l_cur_frame_nr == l_begin) && (action_mode == ACM_APPLY_FILTER))
  967.     {
  968.       /* ------------- 1.st frame: extra dialogs for APPLY_FILTER ---------- */
  969.  
  970.       if(l_sel_cnt < 1)
  971.       {
  972.          p_msg_win(GIMP_RUN_INTERACTIVE, _("No selected Layer in start frame"));
  973.          goto error;
  974.       }
  975.       
  976.       if(l_begin != l_end)
  977.       {
  978.         l_last_frame_filename = p_alloc_fname(ainfo_ptr->basename,
  979.                                         l_end,
  980.                                         ainfo_ptr->extension);
  981.       }
  982.       
  983.       /* additional dialog steps  a) gap_pdb_browser (select the filter)
  984.        *                          b) 1st interactive filtercall
  985.        *                          c) 1st pitstop dialog
  986.        *                          d) [ 2nd interactive filtercall
  987.        *                          e)   2nd pitstop dialog ]
  988.        */
  989.  
  990.       l_rc = p_do_filter_dialogs(ainfo_ptr,
  991.                                  l_tmp_image_id, &l_dpy_id,
  992.                                  l_layli_ptr, l_nlayers,
  993.                                 &l_filter_procname[0], sizeof(l_filter_procname),
  994.                                 &l_plugin_data_len,
  995.                 &l_apply_mode
  996.                  );
  997.  
  998.       if(l_last_frame_filename != NULL)
  999.       {
  1000.         if((l_rc == 0) && (l_apply_mode == PTYP_VARYING_LINEAR))
  1001.     {
  1002.           l_rc = p_do_2nd_filter_dialogs(&l_filter_procname[0],
  1003.                    l_apply_mode,
  1004.                    l_last_frame_filename,
  1005.                    sel_mode, sel_case, sel_invert, sel_pattern
  1006.                   );
  1007.         }
  1008.  
  1009.         g_free(l_last_frame_filename);
  1010.         l_last_frame_filename = NULL;
  1011.       }
  1012.  
  1013.       /* the 1st selected layer has been filtered
  1014.        * in the INTERACTIVE call b)
  1015.        * therefore we unselect this layer, to avoid
  1016.        * a 2nd processing
  1017.        */
  1018.       l_idx = p_get_1st_selected(l_layli_ptr, l_nlayers);
  1019.       if(l_idx >= 0)
  1020.       {
  1021.         l_layli_ptr[l_idx].selected = FALSE;
  1022.         l_sel_cnt--;
  1023.       }
  1024.  
  1025.       /* check for matching Iterator PluginProcedures */
  1026.       if(l_apply_mode == PTYP_VARYING_LINEAR )
  1027.       {
  1028.         l_plugin_iterator =  p_get_iterator_proc(&l_filter_procname[0]);
  1029.       }
  1030.     }
  1031.  
  1032.     if(l_rc != 0)
  1033.       goto error;
  1034.  
  1035.     /* perform function (defined by action_mode) on selcted layer(s) */
  1036.     l_rc = p_apply_action(l_tmp_image_id,
  1037.            action_mode,
  1038.            l_layli_ptr,
  1039.            l_nlayers,
  1040.            l_sel_cnt,
  1041.            l_begin, l_end, l_cur_frame_nr,
  1042.            new_layername,
  1043.            &l_filter_procname[0]
  1044.            );
  1045.     if(l_rc != 0)
  1046.     {
  1047.       if(gap_debug) fprintf(stderr, "gap: p_frames_modify p_apply-action failed. rc=%d\n", (int)l_rc);
  1048.       goto error;
  1049.     }
  1050.  
  1051.     /* free layli info table for the current frame */ 
  1052.     if(l_layli_ptr != NULL)
  1053.     {
  1054.       g_free(l_layli_ptr);
  1055.       l_layli_ptr = NULL;
  1056.     }
  1057.  
  1058.     /* check if the resulting image has at least one layer */
  1059.     p_prevent_empty_image(l_tmp_image_id);
  1060.   
  1061.     /* save current frame with same name */
  1062.     l_rc = p_save_named_frame(l_tmp_image_id, ainfo_ptr->new_filename);
  1063.     if(l_rc < 0)
  1064.     {
  1065.       printf("gap: p_frames_modify save frame %d failed.\n", (int)l_cur_frame_nr);
  1066.       goto error;
  1067.     }
  1068.     else l_rc = 0;
  1069.  
  1070.     /* iterator call (for filter apply with varying values) */
  1071.     if((action_mode == ACM_APPLY_FILTER)
  1072.     && (l_plugin_iterator != NULL) && (l_apply_mode == PTYP_VARYING_LINEAR ))
  1073.     {
  1074.        l_cur_step -= 1.0;
  1075.         /* call plugin-specific iterator, to modify
  1076.          * the plugin's last_values
  1077.          */
  1078.        if(gap_debug) fprintf(stderr, "DEBUG: calling iterator %s  current frame:%d\n",
  1079.                        l_plugin_iterator, (int)l_cur_frame_nr);
  1080.        l_params = gimp_run_procedure (l_plugin_iterator,
  1081.                    &l_retvals,
  1082.                    GIMP_PDB_INT32,   GIMP_RUN_NONINTERACTIVE,
  1083.                    GIMP_PDB_INT32,   l_total_steps,          /* total steps  */
  1084.                    GIMP_PDB_FLOAT,   (gdouble)l_cur_step,    /* current step */
  1085.                    GIMP_PDB_INT32,   l_plugin_data_len, /* length of stored data struct */
  1086.                    GIMP_PDB_END);
  1087.        if (l_params[0].data.d_status != GIMP_PDB_SUCCESS) 
  1088.        { 
  1089.          fprintf(stderr, "ERROR: iterator %s  failed\n", l_plugin_iterator);
  1090.          l_rc = -1;
  1091.        }
  1092.  
  1093.        g_free(l_params);
  1094.     }
  1095.  
  1096.  
  1097.     /* close display (if open) */
  1098.     if (l_dpy_id >= 0)
  1099.     {
  1100.       gimp_display_delete(l_dpy_id);
  1101.       l_dpy_id = -1;
  1102.     }
  1103.  
  1104.     /* destroy the tmp image */
  1105.     gimp_image_delete(l_tmp_image_id);
  1106.  
  1107.     if(l_rc != 0)
  1108.       goto error;
  1109.  
  1110.  
  1111.     
  1112.     if(ainfo_ptr->run_mode == GIMP_RUN_INTERACTIVE)
  1113.     { 
  1114.       l_percentage += l_percentage_step;
  1115.       gimp_progress_update (l_percentage);
  1116.     }
  1117.  
  1118.     /* advance to next frame */
  1119.     if(l_cur_frame_nr == l_end)
  1120.        break;
  1121.     l_cur_frame_nr += l_step;
  1122.  
  1123.   }        /* end while(1)  loop foreach frame in range */
  1124.  
  1125.   if(gap_debug) fprintf(stderr, "p_frames_modify End OK\n");
  1126.  
  1127.   return 0;
  1128.  
  1129. error:
  1130.   if(gap_debug) fprintf(stderr, "gap: p_frames_modify exit with Error\n");
  1131.  
  1132.   if (l_dpy_id >= 0)
  1133.   {
  1134.       gimp_display_delete(l_dpy_id);
  1135.       l_dpy_id = -1;
  1136.   }
  1137.   if(l_tmp_image_id >= 0) gimp_image_delete(l_tmp_image_id);
  1138.   if(l_layli_ptr != NULL) g_free(l_layli_ptr);
  1139.   if(l_plugin_iterator != NULL)  g_free(l_plugin_iterator);
  1140.   return -1;
  1141.   
  1142. }        /* end p_frames_modify */
  1143.  
  1144.  
  1145. /* ============================================================================
  1146.  * gap_mod_layer
  1147.  * ============================================================================
  1148.  */
  1149.  
  1150. gint gap_mod_layer(GimpRunModeType run_mode, gint32 image_id,
  1151.                    gint32 range_from,  gint32 range_to,
  1152.                    gint32 action_mode, gint32 sel_mode,
  1153.                    gint32 sel_case, gint32 sel_invert,
  1154.                    char *sel_pattern, char *new_layername)
  1155. {
  1156.   int    l_rc;
  1157.   t_anim_info *ainfo_ptr;
  1158.   gint32    l_from;
  1159.   gint32    l_to;
  1160.   gint32    l_action_mode;
  1161.   gint32    l_sel_mode;
  1162.   gint32    l_sel_case;
  1163.   gint32    l_sel_invert;
  1164.   
  1165.   char      l_sel_pattern[MAX_LAYERNAME];
  1166.   char      l_new_layername[MAX_LAYERNAME];
  1167.   
  1168.   l_rc = 0;
  1169.   
  1170.   
  1171.   ainfo_ptr = p_alloc_ainfo(image_id, run_mode);
  1172.   if(ainfo_ptr != NULL)
  1173.   {
  1174.  
  1175.     if (0 == p_dir_ainfo(ainfo_ptr))
  1176.     {
  1177.       if(run_mode == GIMP_RUN_INTERACTIVE)
  1178.       {
  1179.          l_rc = p_layer_modify_dialog (ainfo_ptr, &l_from, &l_to,
  1180.                                    &l_action_mode,
  1181.                        &l_sel_mode, &sel_case, &sel_invert,
  1182.                        &l_sel_pattern[0], &l_new_layername[0]);
  1183.  
  1184.       }
  1185.       else
  1186.       {
  1187.          l_from        = range_from;
  1188.          l_to          = range_to;
  1189.      l_action_mode = action_mode;
  1190.      l_sel_mode    = sel_mode;
  1191.      l_sel_case    = sel_case;
  1192.      l_sel_invert  = sel_invert;
  1193.   
  1194.          strncpy(&l_sel_pattern[0], sel_pattern, sizeof(l_sel_pattern) -1);
  1195.      l_sel_pattern[sizeof(l_sel_pattern) -1] = '\0';
  1196.          strncpy(&l_new_layername[0], new_layername, sizeof(l_new_layername) -1);
  1197.      l_new_layername[sizeof(l_new_layername) -1] = '\0';
  1198.       }
  1199.  
  1200.       if(l_rc >= 0)
  1201.       {
  1202.          l_rc = p_save_named_frame(ainfo_ptr->image_id, ainfo_ptr->old_filename);
  1203.          if(l_rc >= 0)
  1204.          {
  1205.            l_rc = p_frames_modify(ainfo_ptr, l_from, l_to,
  1206.                               l_action_mode, 
  1207.                   l_sel_mode, sel_case, sel_invert,
  1208.                   &l_sel_pattern[0], &l_new_layername[0]
  1209.                  );
  1210.            p_load_named_frame(ainfo_ptr->image_id, ainfo_ptr->old_filename);
  1211.          }
  1212.       }
  1213.  
  1214.  
  1215.     }
  1216.     p_free_ainfo(&ainfo_ptr);
  1217.   }
  1218.   
  1219.  
  1220.   return(l_rc);   
  1221. }
  1222.