1 /* GIMP - The GNU Image Manipulation Program
2  * Copyright (C) 1995 Spencer Kimball and Peter Mattis
3  *
4  * gimppluginprocedure.c
5  *
6  * This program is free software: you can redistribute it and/or modify
7  * it under the terms of the GNU General Public License as published by
8  * the Free Software Foundation; either version 3 of the License, or
9  * (at your option) any later version.
10  *
11  * This program is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14  * GNU General Public License for more details.
15  *
16  * You should have received a copy of the GNU General Public License
17  * along with this program.  If not, see <https://www.gnu.org/licenses/>.
18  */
19 
20 #include "config.h"
21 
22 #include <string.h>
23 
24 #include <gegl.h>
25 #include <gdk-pixbuf/gdk-pixbuf.h>
26 
27 #include "libgimpbase/gimpbase.h"
28 
29 #include "plug-in-types.h"
30 
31 #include "gegl/gimp-babl-compat.h"
32 
33 #include "core/gimp.h"
34 #include "core/gimp-memsize.h"
35 #include "core/gimpdrawable.h"
36 #include "core/gimpmarshal.h"
37 #include "core/gimpparamspecs.h"
38 
39 #include "file/file-utils.h"
40 
41 #define __YES_I_NEED_GIMP_PLUG_IN_MANAGER_CALL__
42 #include "gimppluginmanager-call.h"
43 
44 #include "gimppluginerror.h"
45 #include "gimppluginprocedure.h"
46 #include "plug-in-menu-path.h"
47 
48 #include "gimp-intl.h"
49 
50 
51 enum
52 {
53   MENU_PATH_ADDED,
54   LAST_SIGNAL
55 };
56 
57 
58 static void     gimp_plug_in_procedure_finalize        (GObject        *object);
59 
60 static gint64   gimp_plug_in_procedure_get_memsize     (GimpObject     *object,
61                                                         gint64         *gui_size);
62 
63 static gchar  * gimp_plug_in_procedure_get_description (GimpViewable   *viewable,
64                                                         gchar         **tooltip);
65 
66 static const gchar * gimp_plug_in_procedure_get_label  (GimpProcedure  *procedure);
67 static const gchar * gimp_plug_in_procedure_get_menu_label
68                                                        (GimpProcedure  *procedure);
69 static const gchar * gimp_plug_in_procedure_get_blurb  (GimpProcedure  *procedure);
70 static const gchar * gimp_plug_in_procedure_get_help_id(GimpProcedure  *procedure);
71 static gboolean   gimp_plug_in_procedure_get_sensitive (GimpProcedure  *procedure,
72                                                         GimpObject     *object,
73                                                         const gchar  **tooltip);
74 static GimpValueArray * gimp_plug_in_procedure_execute (GimpProcedure  *procedure,
75                                                         Gimp           *gimp,
76                                                         GimpContext    *context,
77                                                         GimpProgress   *progress,
78                                                         GimpValueArray *args,
79                                                         GError        **error);
80 static void     gimp_plug_in_procedure_execute_async   (GimpProcedure  *procedure,
81                                                         Gimp           *gimp,
82                                                         GimpContext    *context,
83                                                         GimpProgress   *progress,
84                                                         GimpValueArray *args,
85                                                         GimpObject     *display);
86 
87 static GFile  * gimp_plug_in_procedure_real_get_file   (GimpPlugInProcedure *procedure);
88 
89 static gboolean gimp_plug_in_procedure_validate_args   (GimpPlugInProcedure *proc,
90                                                         Gimp                *gimp,
91                                                         GimpValueArray      *args,
92                                                         GError             **error);
93 
94 
95 G_DEFINE_TYPE (GimpPlugInProcedure, gimp_plug_in_procedure,
96                GIMP_TYPE_PROCEDURE)
97 
98 #define parent_class gimp_plug_in_procedure_parent_class
99 
100 static guint gimp_plug_in_procedure_signals[LAST_SIGNAL] = { 0 };
101 
102 
103 static void
gimp_plug_in_procedure_class_init(GimpPlugInProcedureClass * klass)104 gimp_plug_in_procedure_class_init (GimpPlugInProcedureClass *klass)
105 {
106   GObjectClass       *object_class      = G_OBJECT_CLASS (klass);
107   GimpObjectClass    *gimp_object_class = GIMP_OBJECT_CLASS (klass);
108   GimpViewableClass  *viewable_class    = GIMP_VIEWABLE_CLASS (klass);
109   GimpProcedureClass *proc_class        = GIMP_PROCEDURE_CLASS (klass);
110 
111   gimp_plug_in_procedure_signals[MENU_PATH_ADDED] =
112     g_signal_new ("menu-path-added",
113                   G_TYPE_FROM_CLASS (klass),
114                   G_SIGNAL_RUN_FIRST,
115                   G_STRUCT_OFFSET (GimpPlugInProcedureClass, menu_path_added),
116                   NULL, NULL,
117                   gimp_marshal_VOID__STRING,
118                   G_TYPE_NONE, 1,
119                   G_TYPE_STRING);
120 
121   object_class->finalize            = gimp_plug_in_procedure_finalize;
122 
123   gimp_object_class->get_memsize    = gimp_plug_in_procedure_get_memsize;
124 
125   viewable_class->default_icon_name = "system-run";
126   viewable_class->get_description   = gimp_plug_in_procedure_get_description;
127 
128   proc_class->get_label             = gimp_plug_in_procedure_get_label;
129   proc_class->get_menu_label        = gimp_plug_in_procedure_get_menu_label;
130   proc_class->get_blurb             = gimp_plug_in_procedure_get_blurb;
131   proc_class->get_help_id           = gimp_plug_in_procedure_get_help_id;
132   proc_class->get_sensitive         = gimp_plug_in_procedure_get_sensitive;
133   proc_class->execute               = gimp_plug_in_procedure_execute;
134   proc_class->execute_async         = gimp_plug_in_procedure_execute_async;
135 
136   klass->get_file                   = gimp_plug_in_procedure_real_get_file;
137   klass->menu_path_added            = NULL;
138 }
139 
140 static void
gimp_plug_in_procedure_init(GimpPlugInProcedure * proc)141 gimp_plug_in_procedure_init (GimpPlugInProcedure *proc)
142 {
143   GIMP_PROCEDURE (proc)->proc_type = GIMP_PLUGIN;
144 
145   proc->icon_data_length = -1;
146 }
147 
148 static void
gimp_plug_in_procedure_finalize(GObject * object)149 gimp_plug_in_procedure_finalize (GObject *object)
150 {
151   GimpPlugInProcedure *proc = GIMP_PLUG_IN_PROCEDURE (object);
152 
153   g_object_unref (proc->file);
154   g_free (proc->menu_label);
155 
156   g_list_free_full (proc->menu_paths, (GDestroyNotify) g_free);
157 
158   g_free (proc->label);
159   g_free (proc->help_id);
160 
161   g_free (proc->icon_data);
162   g_free (proc->image_types);
163   g_free (proc->image_types_tooltip);
164 
165   g_free (proc->extensions);
166   g_free (proc->prefixes);
167   g_free (proc->magics);
168   g_free (proc->mime_types);
169 
170   g_slist_free_full (proc->extensions_list, (GDestroyNotify) g_free);
171   g_slist_free_full (proc->prefixes_list, (GDestroyNotify) g_free);
172   g_slist_free_full (proc->magics_list, (GDestroyNotify) g_free);
173   g_slist_free_full (proc->mime_types_list, (GDestroyNotify) g_free);
174 
175   g_free (proc->thumb_loader);
176 
177   G_OBJECT_CLASS (parent_class)->finalize (object);
178 }
179 
180 static gint64
gimp_plug_in_procedure_get_memsize(GimpObject * object,gint64 * gui_size)181 gimp_plug_in_procedure_get_memsize (GimpObject *object,
182                                     gint64     *gui_size)
183 {
184   GimpPlugInProcedure *proc    = GIMP_PLUG_IN_PROCEDURE (object);
185   gint64               memsize = 0;
186   GList               *list;
187   GSList              *slist;
188 
189   memsize += gimp_g_object_get_memsize (G_OBJECT (proc->file));
190   memsize += gimp_string_get_memsize (proc->menu_label);
191 
192   for (list = proc->menu_paths; list; list = g_list_next (list))
193     memsize += sizeof (GList) + gimp_string_get_memsize (list->data);
194 
195   switch (proc->icon_type)
196     {
197     case GIMP_ICON_TYPE_ICON_NAME:
198     case GIMP_ICON_TYPE_IMAGE_FILE:
199       memsize += gimp_string_get_memsize ((const gchar *) proc->icon_data);
200       break;
201 
202     case GIMP_ICON_TYPE_INLINE_PIXBUF:
203       memsize += proc->icon_data_length;
204       break;
205     }
206 
207   memsize += gimp_string_get_memsize (proc->extensions);
208   memsize += gimp_string_get_memsize (proc->prefixes);
209   memsize += gimp_string_get_memsize (proc->magics);
210   memsize += gimp_string_get_memsize (proc->mime_types);
211   memsize += gimp_string_get_memsize (proc->thumb_loader);
212 
213   for (slist = proc->extensions_list; slist; slist = g_slist_next (slist))
214     memsize += sizeof (GSList) + gimp_string_get_memsize (slist->data);
215 
216   for (slist = proc->prefixes_list; slist; slist = g_slist_next (slist))
217     memsize += sizeof (GSList) + gimp_string_get_memsize (slist->data);
218 
219   for (slist = proc->magics_list; slist; slist = g_slist_next (slist))
220     memsize += sizeof (GSList) + gimp_string_get_memsize (slist->data);
221 
222   for (slist = proc->mime_types_list; slist; slist = g_slist_next (slist))
223     memsize += sizeof (GSList) + gimp_string_get_memsize (slist->data);
224 
225   return memsize + GIMP_OBJECT_CLASS (parent_class)->get_memsize (object,
226                                                                   gui_size);
227 }
228 
229 static gchar *
gimp_plug_in_procedure_get_description(GimpViewable * viewable,gchar ** tooltip)230 gimp_plug_in_procedure_get_description (GimpViewable  *viewable,
231                                         gchar        **tooltip)
232 {
233   GimpProcedure *procedure = GIMP_PROCEDURE (viewable);
234 
235   if (tooltip)
236     *tooltip = g_strdup (gimp_procedure_get_blurb (procedure));
237 
238   return g_strdup (gimp_procedure_get_label (procedure));
239 }
240 
241 static const gchar *
gimp_plug_in_procedure_get_label(GimpProcedure * procedure)242 gimp_plug_in_procedure_get_label (GimpProcedure *procedure)
243 {
244   GimpPlugInProcedure *proc = GIMP_PLUG_IN_PROCEDURE (procedure);
245   const gchar         *path;
246   gchar               *stripped;
247   gchar               *ellipsis;
248   gchar               *label;
249 
250   if (proc->label)
251     return proc->label;
252 
253   if (proc->menu_label)
254     path = dgettext (gimp_plug_in_procedure_get_locale_domain (proc),
255                      proc->menu_label);
256   else if (proc->menu_paths)
257     path = dgettext (gimp_plug_in_procedure_get_locale_domain (proc),
258                      proc->menu_paths->data);
259   else
260     return NULL;
261 
262   stripped = gimp_strip_uline (path);
263 
264   if (proc->menu_label)
265     label = g_strdup (stripped);
266   else
267     label = g_path_get_basename (stripped);
268 
269   g_free (stripped);
270 
271   ellipsis = strstr (label, "...");
272 
273   if (! ellipsis)
274     ellipsis = strstr (label, "\342\200\246" /* U+2026 HORIZONTAL ELLIPSIS */);
275 
276   if (ellipsis && ellipsis == (label + strlen (label) - 3))
277     *ellipsis = '\0';
278 
279   proc->label = label;
280 
281   return proc->label;
282 }
283 
284 static const gchar *
gimp_plug_in_procedure_get_menu_label(GimpProcedure * procedure)285 gimp_plug_in_procedure_get_menu_label (GimpProcedure *procedure)
286 {
287   GimpPlugInProcedure *proc = GIMP_PLUG_IN_PROCEDURE (procedure);
288 
289   if (proc->menu_label)
290     {
291       return dgettext (gimp_plug_in_procedure_get_locale_domain (proc),
292                        proc->menu_label);
293     }
294   else if (proc->menu_paths)
295     {
296       const gchar *translated;
297 
298       translated = dgettext (gimp_plug_in_procedure_get_locale_domain (proc),
299                              proc->menu_paths->data);
300 
301       translated = strrchr (translated, '/');
302 
303       if (translated)
304         return translated + 1;
305     }
306 
307   return GIMP_PROCEDURE_CLASS (parent_class)->get_menu_label (procedure);
308 }
309 
310 static const gchar *
gimp_plug_in_procedure_get_blurb(GimpProcedure * procedure)311 gimp_plug_in_procedure_get_blurb (GimpProcedure *procedure)
312 {
313   GimpPlugInProcedure *proc = GIMP_PLUG_IN_PROCEDURE (procedure);
314 
315   /*  do not to pass the empty string to gettext()  */
316   if (procedure->blurb && strlen (procedure->blurb))
317     return dgettext (gimp_plug_in_procedure_get_locale_domain (proc),
318                      procedure->blurb);
319 
320   return NULL;
321 }
322 
323 static const gchar *
gimp_plug_in_procedure_get_help_id(GimpProcedure * procedure)324 gimp_plug_in_procedure_get_help_id (GimpProcedure *procedure)
325 {
326   GimpPlugInProcedure *proc = GIMP_PLUG_IN_PROCEDURE (procedure);
327   const gchar         *domain;
328 
329   if (proc->help_id)
330     return proc->help_id;
331 
332   domain = gimp_plug_in_procedure_get_help_domain (proc);
333 
334   if (domain)
335     proc->help_id = g_strconcat (domain, "?", gimp_object_get_name (proc), NULL);
336   else
337     proc->help_id = g_strdup (gimp_object_get_name (proc));
338 
339   return proc->help_id;
340 }
341 
342 static gboolean
gimp_plug_in_procedure_get_sensitive(GimpProcedure * procedure,GimpObject * object,const gchar ** tooltip)343 gimp_plug_in_procedure_get_sensitive (GimpProcedure  *procedure,
344                                       GimpObject     *object,
345                                       const gchar   **tooltip)
346 {
347   GimpPlugInProcedure *proc       = GIMP_PLUG_IN_PROCEDURE (procedure);
348   GimpDrawable        *drawable;
349   GimpImageType        image_type = -1;
350   gboolean             sensitive  = FALSE;
351 
352   g_return_val_if_fail (object == NULL || GIMP_IS_DRAWABLE (object), FALSE);
353 
354   drawable = GIMP_DRAWABLE (object);
355 
356   if (drawable)
357     {
358       const Babl *format = gimp_drawable_get_format (drawable);
359 
360       image_type = gimp_babl_format_get_image_type (format);
361     }
362 
363   switch (image_type)
364     {
365     case GIMP_RGB_IMAGE:
366       sensitive = proc->image_types_val & GIMP_PLUG_IN_RGB_IMAGE;
367       break;
368     case GIMP_RGBA_IMAGE:
369       sensitive = proc->image_types_val & GIMP_PLUG_IN_RGBA_IMAGE;
370       break;
371     case GIMP_GRAY_IMAGE:
372       sensitive = proc->image_types_val & GIMP_PLUG_IN_GRAY_IMAGE;
373       break;
374     case GIMP_GRAYA_IMAGE:
375       sensitive = proc->image_types_val & GIMP_PLUG_IN_GRAYA_IMAGE;
376       break;
377     case GIMP_INDEXED_IMAGE:
378       sensitive = proc->image_types_val & GIMP_PLUG_IN_INDEXED_IMAGE;
379       break;
380     case GIMP_INDEXEDA_IMAGE:
381       sensitive = proc->image_types_val & GIMP_PLUG_IN_INDEXEDA_IMAGE;
382       break;
383     default:
384       break;
385     }
386 
387   if (! sensitive)
388     *tooltip = proc->image_types_tooltip;
389 
390   return sensitive ? TRUE : FALSE;
391 }
392 
393 static GimpValueArray *
gimp_plug_in_procedure_execute(GimpProcedure * procedure,Gimp * gimp,GimpContext * context,GimpProgress * progress,GimpValueArray * args,GError ** error)394 gimp_plug_in_procedure_execute (GimpProcedure  *procedure,
395                                 Gimp           *gimp,
396                                 GimpContext    *context,
397                                 GimpProgress   *progress,
398                                 GimpValueArray *args,
399                                 GError        **error)
400 {
401   GimpPlugInProcedure *plug_in_procedure = GIMP_PLUG_IN_PROCEDURE (procedure);
402   GError              *pdb_error         = NULL;
403 
404   if (! gimp_plug_in_procedure_validate_args (plug_in_procedure, gimp,
405                                               args, &pdb_error))
406     {
407       GimpValueArray *return_vals;
408 
409       return_vals = gimp_procedure_get_return_values (procedure, FALSE,
410                                                       pdb_error);
411       g_propagate_error (error, pdb_error);
412 
413       return return_vals;
414     }
415 
416   if (procedure->proc_type == GIMP_INTERNAL)
417     return GIMP_PROCEDURE_CLASS (parent_class)->execute (procedure, gimp,
418                                                          context, progress,
419                                                          args, error);
420 
421   return gimp_plug_in_manager_call_run (gimp->plug_in_manager,
422                                         context, progress,
423                                         GIMP_PLUG_IN_PROCEDURE (procedure),
424                                         args, TRUE, NULL);
425 }
426 
427 static void
gimp_plug_in_procedure_execute_async(GimpProcedure * procedure,Gimp * gimp,GimpContext * context,GimpProgress * progress,GimpValueArray * args,GimpObject * display)428 gimp_plug_in_procedure_execute_async (GimpProcedure  *procedure,
429                                       Gimp           *gimp,
430                                       GimpContext    *context,
431                                       GimpProgress   *progress,
432                                       GimpValueArray *args,
433                                       GimpObject     *display)
434 {
435   GimpPlugInProcedure *plug_in_procedure = GIMP_PLUG_IN_PROCEDURE (procedure);
436   GError              *error             = NULL;
437 
438   if (gimp_plug_in_procedure_validate_args (plug_in_procedure, gimp,
439                                             args, &error))
440     {
441       GimpValueArray *return_vals;
442 
443       return_vals = gimp_plug_in_manager_call_run (gimp->plug_in_manager,
444                                                    context, progress,
445                                                    plug_in_procedure,
446                                                    args, FALSE, display);
447 
448       if (return_vals)
449         {
450           gimp_plug_in_procedure_handle_return_values (plug_in_procedure,
451                                                        gimp, progress,
452                                                        return_vals);
453           gimp_value_array_unref (return_vals);
454         }
455     }
456   else
457     {
458       gimp_message_literal (gimp, G_OBJECT (progress), GIMP_MESSAGE_ERROR,
459                             error->message);
460       g_error_free (error);
461     }
462 }
463 
464 static GFile *
gimp_plug_in_procedure_real_get_file(GimpPlugInProcedure * procedure)465 gimp_plug_in_procedure_real_get_file (GimpPlugInProcedure *procedure)
466 {
467   return procedure->file;
468 }
469 
470 static gboolean
gimp_plug_in_procedure_validate_args(GimpPlugInProcedure * proc,Gimp * gimp,GimpValueArray * args,GError ** error)471 gimp_plug_in_procedure_validate_args (GimpPlugInProcedure *proc,
472                                       Gimp                *gimp,
473                                       GimpValueArray      *args,
474                                       GError             **error)
475 {
476   if (proc->file_proc && proc->handles_uri)
477     {
478       /*  for file procedures that handle URIs, make sure that the
479        *  passed string actually is an URI, not just a file path
480        *  (bug 758685)
481        */
482       GimpProcedure *procedure = GIMP_PROCEDURE (proc);
483       GValue        *uri_value = NULL;
484 
485       if ((procedure->num_args   >= 3)                     &&
486           (procedure->num_values >= 1)                     &&
487           GIMP_IS_PARAM_SPEC_INT32    (procedure->args[0]) &&
488           G_IS_PARAM_SPEC_STRING      (procedure->args[1]) &&
489           G_IS_PARAM_SPEC_STRING      (procedure->args[2]) &&
490           GIMP_IS_PARAM_SPEC_IMAGE_ID (procedure->values[0]))
491         {
492           uri_value = gimp_value_array_index (args, 1);
493         }
494       else if ((procedure->num_args >= 5)                          &&
495                GIMP_IS_PARAM_SPEC_INT32       (procedure->args[0]) &&
496                GIMP_IS_PARAM_SPEC_IMAGE_ID    (procedure->args[1]) &&
497                GIMP_IS_PARAM_SPEC_DRAWABLE_ID (procedure->args[2]) &&
498                G_IS_PARAM_SPEC_STRING         (procedure->args[3]) &&
499                G_IS_PARAM_SPEC_STRING         (procedure->args[4]))
500         {
501           uri_value = gimp_value_array_index (args, 3);
502         }
503 
504       if (uri_value)
505         {
506           GFile *file;
507 
508           file = file_utils_filename_to_file (gimp,
509                                               g_value_get_string (uri_value),
510                                               error);
511 
512           if (! file)
513             return FALSE;
514 
515           g_value_take_string (uri_value, g_file_get_uri (file));
516           g_object_unref (file);
517         }
518     }
519 
520   return TRUE;
521 }
522 
523 
524 /*  public functions  */
525 
526 GimpProcedure *
gimp_plug_in_procedure_new(GimpPDBProcType proc_type,GFile * file)527 gimp_plug_in_procedure_new (GimpPDBProcType  proc_type,
528                             GFile           *file)
529 {
530   GimpPlugInProcedure *proc;
531 
532   g_return_val_if_fail (proc_type == GIMP_PLUGIN ||
533                         proc_type == GIMP_EXTENSION, NULL);
534   g_return_val_if_fail (G_IS_FILE (file), NULL);
535 
536   proc = g_object_new (GIMP_TYPE_PLUG_IN_PROCEDURE, NULL);
537 
538   proc->file = g_object_ref (file);
539 
540   GIMP_PROCEDURE (proc)->proc_type = proc_type;
541 
542   return GIMP_PROCEDURE (proc);
543 }
544 
545 GimpPlugInProcedure *
gimp_plug_in_procedure_find(GSList * list,const gchar * proc_name)546 gimp_plug_in_procedure_find (GSList      *list,
547                              const gchar *proc_name)
548 {
549   GSList *l;
550 
551   for (l = list; l; l = g_slist_next (l))
552     {
553       GimpObject *object = l->data;
554 
555       if (! strcmp (proc_name, gimp_object_get_name (object)))
556         return GIMP_PLUG_IN_PROCEDURE (object);
557     }
558 
559   return NULL;
560 }
561 
562 GFile *
gimp_plug_in_procedure_get_file(GimpPlugInProcedure * proc)563 gimp_plug_in_procedure_get_file (GimpPlugInProcedure *proc)
564 {
565   g_return_val_if_fail (GIMP_IS_PLUG_IN_PROCEDURE (proc), NULL);
566 
567   return GIMP_PLUG_IN_PROCEDURE_GET_CLASS (proc)->get_file (proc);
568 }
569 
570 void
gimp_plug_in_procedure_set_locale_domain(GimpPlugInProcedure * proc,const gchar * locale_domain)571 gimp_plug_in_procedure_set_locale_domain (GimpPlugInProcedure *proc,
572                                           const gchar         *locale_domain)
573 {
574   g_return_if_fail (GIMP_IS_PLUG_IN_PROCEDURE (proc));
575 
576   proc->locale_domain = locale_domain ? g_quark_from_string (locale_domain) : 0;
577 }
578 
579 const gchar *
gimp_plug_in_procedure_get_locale_domain(GimpPlugInProcedure * proc)580 gimp_plug_in_procedure_get_locale_domain (GimpPlugInProcedure *proc)
581 {
582   g_return_val_if_fail (GIMP_IS_PLUG_IN_PROCEDURE (proc), NULL);
583 
584   return g_quark_to_string (proc->locale_domain);
585 }
586 
587 void
gimp_plug_in_procedure_set_help_domain(GimpPlugInProcedure * proc,const gchar * help_domain)588 gimp_plug_in_procedure_set_help_domain (GimpPlugInProcedure *proc,
589                                         const gchar         *help_domain)
590 {
591   g_return_if_fail (GIMP_IS_PLUG_IN_PROCEDURE (proc));
592 
593   proc->help_domain = help_domain ? g_quark_from_string (help_domain) : 0;
594 }
595 
596 const gchar *
gimp_plug_in_procedure_get_help_domain(GimpPlugInProcedure * proc)597 gimp_plug_in_procedure_get_help_domain (GimpPlugInProcedure *proc)
598 {
599   g_return_val_if_fail (GIMP_IS_PLUG_IN_PROCEDURE (proc), NULL);
600 
601   return g_quark_to_string (proc->help_domain);
602 }
603 
604 gboolean
gimp_plug_in_procedure_add_menu_path(GimpPlugInProcedure * proc,const gchar * menu_path,GError ** error)605 gimp_plug_in_procedure_add_menu_path (GimpPlugInProcedure  *proc,
606                                       const gchar          *menu_path,
607                                       GError              **error)
608 {
609   GimpProcedure *procedure;
610   gchar         *basename = NULL;
611   const gchar   *required = NULL;
612   gchar         *p;
613   gchar         *mapped_path;
614 
615   g_return_val_if_fail (GIMP_IS_PLUG_IN_PROCEDURE (proc), FALSE);
616   g_return_val_if_fail (menu_path != NULL, FALSE);
617   g_return_val_if_fail (error == NULL || *error == NULL, FALSE);
618 
619   procedure = GIMP_PROCEDURE (proc);
620 
621   p = strchr (menu_path, '>');
622   if (p == NULL || (*(++p) && *p != '/'))
623     {
624       basename = g_path_get_basename (gimp_file_get_utf8_name (proc->file));
625 
626       g_set_error (error, GIMP_PLUG_IN_ERROR, GIMP_PLUG_IN_FAILED,
627                    "Plug-in \"%s\"\n(%s)\n"
628                    "attempted to install procedure \"%s\"\n"
629                    "in the invalid menu location \"%s\".\n"
630                    "The menu path must look like either \"<Prefix>\" "
631                    "or \"<Prefix>/path/to/item\".",
632                    basename, gimp_file_get_utf8_name (proc->file),
633                    gimp_object_get_name (proc),
634                    menu_path);
635       goto failure;
636     }
637 
638   if (g_str_has_prefix (menu_path, "<Toolbox>") ||
639       g_str_has_prefix (menu_path, "<Image>"))
640     {
641       if ((procedure->num_args < 1) ||
642           ! GIMP_IS_PARAM_SPEC_INT32 (procedure->args[0]))
643         {
644           required = "INT32";
645           goto failure;
646         }
647     }
648   else if (g_str_has_prefix (menu_path, "<Layers>"))
649     {
650       if ((procedure->num_args < 3)                             ||
651           ! GIMP_IS_PARAM_SPEC_INT32       (procedure->args[0]) ||
652           ! GIMP_IS_PARAM_SPEC_IMAGE_ID    (procedure->args[1]) ||
653           ! (G_TYPE_FROM_INSTANCE (procedure->args[2])
654                                == GIMP_TYPE_PARAM_LAYER_ID ||
655              G_TYPE_FROM_INSTANCE (procedure->args[2])
656                                == GIMP_TYPE_PARAM_DRAWABLE_ID))
657         {
658           required = "INT32, IMAGE, (LAYER | DRAWABLE)";
659           goto failure;
660         }
661     }
662   else if (g_str_has_prefix (menu_path, "<Channels>"))
663     {
664       if ((procedure->num_args < 3)                             ||
665           ! GIMP_IS_PARAM_SPEC_INT32       (procedure->args[0]) ||
666           ! GIMP_IS_PARAM_SPEC_IMAGE_ID    (procedure->args[1]) ||
667           ! (G_TYPE_FROM_INSTANCE (procedure->args[2])
668                                == GIMP_TYPE_PARAM_CHANNEL_ID ||
669              G_TYPE_FROM_INSTANCE (procedure->args[2])
670                                == GIMP_TYPE_PARAM_DRAWABLE_ID))
671         {
672           required = "INT32, IMAGE, (CHANNEL | DRAWABLE)";
673           goto failure;
674         }
675     }
676   else if (g_str_has_prefix (menu_path, "<Vectors>"))
677     {
678       if ((procedure->num_args < 3)                            ||
679           ! GIMP_IS_PARAM_SPEC_INT32      (procedure->args[0]) ||
680           ! GIMP_IS_PARAM_SPEC_IMAGE_ID   (procedure->args[1]) ||
681           ! GIMP_IS_PARAM_SPEC_VECTORS_ID (procedure->args[2]))
682         {
683           required = "INT32, IMAGE, VECTORS";
684           goto failure;
685         }
686     }
687   else if (g_str_has_prefix (menu_path, "<Colormap>"))
688     {
689       if ((procedure->num_args < 2)                            ||
690           ! GIMP_IS_PARAM_SPEC_INT32      (procedure->args[0]) ||
691           ! GIMP_IS_PARAM_SPEC_IMAGE_ID   (procedure->args[1]))
692         {
693           required = "INT32, IMAGE";
694           goto failure;
695         }
696     }
697   else if (g_str_has_prefix (menu_path, "<Load>"))
698     {
699       if ((procedure->num_args < 3)                       ||
700           ! GIMP_IS_PARAM_SPEC_INT32 (procedure->args[0]) ||
701           ! G_IS_PARAM_SPEC_STRING   (procedure->args[1]) ||
702           ! G_IS_PARAM_SPEC_STRING   (procedure->args[2]))
703         {
704           required = "INT32, STRING, STRING";
705           goto failure;
706         }
707 
708       if ((procedure->num_values < 1) ||
709           ! GIMP_IS_PARAM_SPEC_IMAGE_ID (procedure->values[0]))
710         {
711           required = "IMAGE";
712           goto failure;
713         }
714     }
715   else if (g_str_has_prefix (menu_path, "<Save>"))
716     {
717       if ((procedure->num_args < 5)                             ||
718           ! GIMP_IS_PARAM_SPEC_INT32       (procedure->args[0]) ||
719           ! GIMP_IS_PARAM_SPEC_IMAGE_ID    (procedure->args[1]) ||
720           ! GIMP_IS_PARAM_SPEC_DRAWABLE_ID (procedure->args[2]) ||
721           ! G_IS_PARAM_SPEC_STRING         (procedure->args[3]) ||
722           ! G_IS_PARAM_SPEC_STRING         (procedure->args[4]))
723         {
724           required = "INT32, IMAGE, DRAWABLE, STRING, STRING";
725           goto failure;
726         }
727     }
728   else if (g_str_has_prefix (menu_path, "<Brushes>")        ||
729            g_str_has_prefix (menu_path, "<Dynamics>")       ||
730            g_str_has_prefix (menu_path, "<MyPaintBrushes>") ||
731            g_str_has_prefix (menu_path, "<Gradients>")      ||
732            g_str_has_prefix (menu_path, "<Palettes>")       ||
733            g_str_has_prefix (menu_path, "<Patterns>")       ||
734            g_str_has_prefix (menu_path, "<ToolPresets>")    ||
735            g_str_has_prefix (menu_path, "<Fonts>")          ||
736            g_str_has_prefix (menu_path, "<Buffers>"))
737     {
738       if ((procedure->num_args < 1) ||
739           ! GIMP_IS_PARAM_SPEC_INT32 (procedure->args[0]))
740         {
741           required = "INT32";
742           goto failure;
743         }
744     }
745   else
746     {
747       basename = g_path_get_basename (gimp_file_get_utf8_name (proc->file));
748 
749       g_set_error (error, GIMP_PLUG_IN_ERROR, GIMP_PLUG_IN_FAILED,
750                    "Plug-in \"%s\"\n(%s)\n"
751                    "attempted to install procedure \"%s\" "
752                    "in the invalid menu location \"%s\".\n"
753                    "Use either \"<Image>\", "
754                    "\"<Layers>\", \"<Channels>\", \"<Vectors>\", "
755                    "\"<Colormap>\", \"<Brushes>\", \"<Dynamics>\", "
756                    "\"<MyPaintBrushes>\", \"<Gradients>\", \"<Palettes>\", "
757                    "\"<Patterns>\", \"<ToolPresets>\", \"<Fonts>\" "
758                    "or \"<Buffers>\".",
759                    basename, gimp_file_get_utf8_name (proc->file),
760                    gimp_object_get_name (proc),
761                    menu_path);
762       goto failure;
763     }
764 
765   g_free (basename);
766 
767   mapped_path = plug_in_menu_path_map (menu_path, NULL);
768 
769   proc->menu_paths = g_list_append (proc->menu_paths, mapped_path);
770 
771   g_signal_emit (proc, gimp_plug_in_procedure_signals[MENU_PATH_ADDED], 0,
772                  mapped_path);
773 
774   return TRUE;
775 
776  failure:
777   if (required)
778     {
779       gchar *prefix = g_strdup (menu_path);
780 
781       p = strchr (prefix, '>') + 1;
782       *p = '\0';
783 
784       basename = g_path_get_basename (gimp_file_get_utf8_name (proc->file));
785 
786       g_set_error (error, GIMP_PLUG_IN_ERROR, GIMP_PLUG_IN_FAILED,
787                    "Plug-in \"%s\"\n(%s)\n\n"
788                    "attempted to install %s procedure \"%s\" "
789                    "which does not take the standard %s plug-in's "
790                    "arguments: (%s).",
791                    basename, gimp_file_get_utf8_name (proc->file),
792                    prefix, gimp_object_get_name (proc), prefix,
793                    required);
794 
795       g_free (prefix);
796     }
797 
798   g_free (basename);
799 
800   return FALSE;
801 }
802 
803 void
gimp_plug_in_procedure_set_icon(GimpPlugInProcedure * proc,GimpIconType icon_type,const guint8 * icon_data,gint icon_data_length)804 gimp_plug_in_procedure_set_icon (GimpPlugInProcedure *proc,
805                                  GimpIconType         icon_type,
806                                  const guint8        *icon_data,
807                                  gint                 icon_data_length)
808 {
809   guint8 *data_copy = NULL;
810 
811   g_return_if_fail (GIMP_IS_PLUG_IN_PROCEDURE (proc));
812 
813   switch (icon_type)
814     {
815     case GIMP_ICON_TYPE_ICON_NAME:
816       data_copy = (guint8 *) g_strdup ((gchar *) icon_data);
817       break;
818 
819     case GIMP_ICON_TYPE_INLINE_PIXBUF:
820       data_copy = g_memdup (icon_data, icon_data_length);
821       break;
822 
823     case GIMP_ICON_TYPE_IMAGE_FILE:
824       data_copy = (guint8 *) g_strdup ((gchar *) icon_data);
825       break;
826 
827     default:
828       g_return_if_reached ();
829     }
830 
831   gimp_plug_in_procedure_take_icon (proc, icon_type,
832                                     data_copy, icon_data_length);
833 }
834 
835 void
gimp_plug_in_procedure_take_icon(GimpPlugInProcedure * proc,GimpIconType icon_type,guint8 * icon_data,gint icon_data_length)836 gimp_plug_in_procedure_take_icon (GimpPlugInProcedure *proc,
837                                   GimpIconType         icon_type,
838                                   guint8              *icon_data,
839                                   gint                 icon_data_length)
840 {
841   const gchar *icon_name   = NULL;
842   GdkPixbuf   *icon_pixbuf = NULL;
843   GError      *error       = NULL;
844 
845   g_return_if_fail (GIMP_IS_PLUG_IN_PROCEDURE (proc));
846 
847   if (proc->icon_data)
848     {
849       g_free (proc->icon_data);
850       proc->icon_data_length = -1;
851       proc->icon_data        = NULL;
852     }
853 
854   proc->icon_type = icon_type;
855 
856   switch (proc->icon_type)
857     {
858     case GIMP_ICON_TYPE_ICON_NAME:
859       proc->icon_data_length = -1;
860       proc->icon_data        = icon_data;
861 
862       icon_name = (const gchar *) proc->icon_data;
863       break;
864 
865     case GIMP_ICON_TYPE_INLINE_PIXBUF:
866       proc->icon_data_length = icon_data_length;
867       proc->icon_data        = icon_data;
868 
869       icon_pixbuf = gdk_pixbuf_new_from_inline (proc->icon_data_length,
870                                                 proc->icon_data, TRUE, &error);
871       break;
872 
873     case GIMP_ICON_TYPE_IMAGE_FILE:
874       proc->icon_data_length = -1;
875       proc->icon_data        = icon_data;
876 
877       icon_pixbuf = gdk_pixbuf_new_from_file ((gchar *) proc->icon_data,
878                                               &error);
879       break;
880     }
881 
882   if (! icon_pixbuf && error)
883     {
884       g_printerr ("gimp_plug_in_procedure_take_icon: %s\n", error->message);
885       g_clear_error (&error);
886     }
887 
888   gimp_viewable_set_icon_name (GIMP_VIEWABLE (proc), icon_name);
889   g_object_set (proc, "icon-pixbuf", icon_pixbuf, NULL);
890 
891   if (icon_pixbuf)
892     g_object_unref (icon_pixbuf);
893 }
894 
895 static GimpPlugInImageType
image_types_parse(const gchar * name,const gchar * image_types)896 image_types_parse (const gchar *name,
897                    const gchar *image_types)
898 {
899   const gchar         *type_spec = image_types;
900   GimpPlugInImageType  types     = 0;
901 
902   /*  If the plug_in registers with image_type == NULL or "", return 0
903    *  By doing so it won't be touched by plug_in_set_menu_sensitivity()
904    */
905   if (! image_types)
906     return types;
907 
908   while (*image_types)
909     {
910       while (*image_types &&
911              ((*image_types == ' ') ||
912               (*image_types == '\t') ||
913               (*image_types == ',')))
914         image_types++;
915 
916       if (*image_types)
917         {
918           if (g_str_has_prefix (image_types, "RGBA"))
919             {
920               types |= GIMP_PLUG_IN_RGBA_IMAGE;
921               image_types += strlen ("RGBA");
922             }
923           else if (g_str_has_prefix (image_types, "RGB*"))
924             {
925               types |= GIMP_PLUG_IN_RGB_IMAGE | GIMP_PLUG_IN_RGBA_IMAGE;
926               image_types += strlen ("RGB*");
927             }
928           else if (g_str_has_prefix (image_types, "RGB"))
929             {
930               types |= GIMP_PLUG_IN_RGB_IMAGE;
931               image_types += strlen ("RGB");
932             }
933           else if (g_str_has_prefix (image_types, "GRAYA"))
934             {
935               types |= GIMP_PLUG_IN_GRAYA_IMAGE;
936               image_types += strlen ("GRAYA");
937             }
938           else if (g_str_has_prefix (image_types, "GRAY*"))
939             {
940               types |= GIMP_PLUG_IN_GRAY_IMAGE | GIMP_PLUG_IN_GRAYA_IMAGE;
941               image_types += strlen ("GRAY*");
942             }
943           else if (g_str_has_prefix (image_types, "GRAY"))
944             {
945               types |= GIMP_PLUG_IN_GRAY_IMAGE;
946               image_types += strlen ("GRAY");
947             }
948           else if (g_str_has_prefix (image_types, "INDEXEDA"))
949             {
950               types |= GIMP_PLUG_IN_INDEXEDA_IMAGE;
951               image_types += strlen ("INDEXEDA");
952             }
953           else if (g_str_has_prefix (image_types, "INDEXED*"))
954             {
955               types |= GIMP_PLUG_IN_INDEXED_IMAGE | GIMP_PLUG_IN_INDEXEDA_IMAGE;
956               image_types += strlen ("INDEXED*");
957             }
958           else if (g_str_has_prefix (image_types, "INDEXED"))
959             {
960               types |= GIMP_PLUG_IN_INDEXED_IMAGE;
961               image_types += strlen ("INDEXED");
962             }
963           else if (g_str_has_prefix (image_types, "*"))
964             {
965               types |= (GIMP_PLUG_IN_RGB_IMAGE     | GIMP_PLUG_IN_RGBA_IMAGE  |
966                         GIMP_PLUG_IN_GRAY_IMAGE    | GIMP_PLUG_IN_GRAYA_IMAGE |
967                         GIMP_PLUG_IN_INDEXED_IMAGE | GIMP_PLUG_IN_INDEXEDA_IMAGE);
968               image_types += strlen ("*");
969             }
970           else
971             {
972               g_printerr ("%s: image-type contains unrecognizable parts:"
973                           "'%s'\n", name, type_spec);
974 
975               /* skip to next token */
976               while (*image_types &&
977                      *image_types != ' '  &&
978                      *image_types != '\t' &&
979                      *image_types != ',')
980                 {
981                   image_types++;
982                 }
983             }
984         }
985     }
986 
987   return types;
988 }
989 
990 void
gimp_plug_in_procedure_set_image_types(GimpPlugInProcedure * proc,const gchar * image_types)991 gimp_plug_in_procedure_set_image_types (GimpPlugInProcedure *proc,
992                                         const gchar         *image_types)
993 {
994   GList *types = NULL;
995 
996   g_return_if_fail (GIMP_IS_PLUG_IN_PROCEDURE (proc));
997 
998   if (proc->image_types)
999     g_free (proc->image_types);
1000 
1001   proc->image_types     = g_strdup (image_types);
1002   proc->image_types_val = image_types_parse (gimp_object_get_name (proc),
1003                                              proc->image_types);
1004 
1005   g_clear_pointer (&proc->image_types_tooltip, g_free);
1006 
1007   if (proc->image_types_val &
1008       (GIMP_PLUG_IN_RGB_IMAGE | GIMP_PLUG_IN_RGBA_IMAGE))
1009     {
1010       if ((proc->image_types_val & GIMP_PLUG_IN_RGB_IMAGE) &&
1011           (proc->image_types_val & GIMP_PLUG_IN_RGBA_IMAGE))
1012         {
1013           types = g_list_prepend (types, _("RGB"));
1014         }
1015       else if (proc->image_types_val & GIMP_PLUG_IN_RGB_IMAGE)
1016         {
1017           types = g_list_prepend (types, _("RGB without alpha"));
1018         }
1019       else
1020         {
1021           types = g_list_prepend (types, _("RGB with alpha"));
1022         }
1023     }
1024 
1025   if (proc->image_types_val &
1026       (GIMP_PLUG_IN_GRAY_IMAGE | GIMP_PLUG_IN_GRAYA_IMAGE))
1027     {
1028       if ((proc->image_types_val & GIMP_PLUG_IN_GRAY_IMAGE) &&
1029           (proc->image_types_val & GIMP_PLUG_IN_GRAYA_IMAGE))
1030         {
1031           types = g_list_prepend (types, _("Grayscale"));
1032         }
1033       else if (proc->image_types_val & GIMP_PLUG_IN_GRAY_IMAGE)
1034         {
1035           types = g_list_prepend (types, _("Grayscale without alpha"));
1036         }
1037       else
1038         {
1039           types = g_list_prepend (types, _("Grayscale with alpha"));
1040         }
1041     }
1042 
1043   if (proc->image_types_val &
1044       (GIMP_PLUG_IN_INDEXED_IMAGE | GIMP_PLUG_IN_INDEXEDA_IMAGE))
1045     {
1046       if ((proc->image_types_val & GIMP_PLUG_IN_INDEXED_IMAGE) &&
1047           (proc->image_types_val & GIMP_PLUG_IN_INDEXEDA_IMAGE))
1048         {
1049           types = g_list_prepend (types, _("Indexed"));
1050         }
1051       else if (proc->image_types_val & GIMP_PLUG_IN_INDEXED_IMAGE)
1052         {
1053           types = g_list_prepend (types, _("Indexed without alpha"));
1054         }
1055       else
1056         {
1057           types = g_list_prepend (types, _("Indexed with alpha"));
1058         }
1059     }
1060 
1061   if (types)
1062     {
1063       GString *string;
1064       GList   *list;
1065 
1066       types = g_list_reverse (types);
1067 
1068       string = g_string_new (gimp_procedure_get_blurb (GIMP_PROCEDURE (proc)));
1069 
1070       g_string_append (string, "\n\n");
1071       g_string_append (string, _("This plug-in only works on the "
1072                                  "following layer types:"));
1073       g_string_append (string, "\n");
1074 
1075       for (list = types; list; list = g_list_next (list))
1076         {
1077           g_string_append (string, list->data);
1078 
1079           if (list->next)
1080             g_string_append (string, ", ");
1081           else
1082             g_string_append (string, ".");
1083         }
1084 
1085       g_list_free (types);
1086 
1087       proc->image_types_tooltip = g_string_free (string, FALSE);
1088     }
1089 }
1090 
1091 static GSList *
extensions_parse(gchar * extensions)1092 extensions_parse (gchar *extensions)
1093 {
1094   GSList *list = NULL;
1095 
1096   /*  extensions can be NULL.  Avoid calling strtok if it is.  */
1097   if (extensions)
1098     {
1099       gchar *extension;
1100       gchar *next_token;
1101 
1102       /*  work on a copy  */
1103       extensions = g_strdup (extensions);
1104 
1105       next_token = extensions;
1106       extension = strtok (next_token, " \t,");
1107 
1108       while (extension)
1109         {
1110           list = g_slist_prepend (list, g_strdup (extension));
1111           extension = strtok (NULL, " \t,");
1112         }
1113 
1114       g_free (extensions);
1115     }
1116 
1117   return g_slist_reverse (list);
1118 }
1119 
1120 void
gimp_plug_in_procedure_set_file_proc(GimpPlugInProcedure * proc,const gchar * extensions,const gchar * prefixes,const gchar * magics)1121 gimp_plug_in_procedure_set_file_proc (GimpPlugInProcedure *proc,
1122                                       const gchar         *extensions,
1123                                       const gchar         *prefixes,
1124                                       const gchar         *magics)
1125 {
1126   GSList *list;
1127 
1128   g_return_if_fail (GIMP_IS_PLUG_IN_PROCEDURE (proc));
1129 
1130   proc->file_proc = TRUE;
1131 
1132   /*  extensions  */
1133 
1134   if (proc->extensions != extensions)
1135     {
1136       if (proc->extensions)
1137         g_free (proc->extensions);
1138 
1139       proc->extensions = g_strdup (extensions);
1140     }
1141 
1142   if (proc->extensions_list)
1143     g_slist_free_full (proc->extensions_list, (GDestroyNotify) g_free);
1144 
1145   proc->extensions_list = extensions_parse (proc->extensions);
1146 
1147   /*  prefixes  */
1148 
1149   if (proc->prefixes != prefixes)
1150     {
1151       if (proc->prefixes)
1152         g_free (proc->prefixes);
1153 
1154       proc->prefixes = g_strdup (prefixes);
1155     }
1156 
1157   if (proc->prefixes_list)
1158     g_slist_free_full (proc->prefixes_list, (GDestroyNotify) g_free);
1159 
1160   proc->prefixes_list = extensions_parse (proc->prefixes);
1161 
1162   /* don't allow "file:" to be registered as prefix */
1163   for (list = proc->prefixes_list; list; list = g_slist_next (list))
1164     {
1165       const gchar *prefix = list->data;
1166 
1167       if (prefix && strcmp (prefix, "file:") == 0)
1168         {
1169           g_free (list->data);
1170           proc->prefixes_list = g_slist_delete_link (proc->prefixes_list, list);
1171           break;
1172         }
1173     }
1174 
1175   /*  magics  */
1176 
1177   if (proc->magics != magics)
1178     {
1179       if (proc->magics)
1180         g_free (proc->magics);
1181 
1182       proc->magics = g_strdup (magics);
1183     }
1184 
1185   if (proc->magics_list)
1186     g_slist_free_full (proc->magics_list, (GDestroyNotify) g_free);
1187 
1188   proc->magics_list = extensions_parse (proc->magics);
1189 }
1190 
1191 void
gimp_plug_in_procedure_set_priority(GimpPlugInProcedure * proc,gint priority)1192 gimp_plug_in_procedure_set_priority (GimpPlugInProcedure *proc,
1193                                      gint                 priority)
1194 {
1195   g_return_if_fail (GIMP_IS_PLUG_IN_PROCEDURE (proc));
1196 
1197   proc->priority = priority;
1198 }
1199 
1200 void
gimp_plug_in_procedure_set_mime_types(GimpPlugInProcedure * proc,const gchar * mime_types)1201 gimp_plug_in_procedure_set_mime_types (GimpPlugInProcedure *proc,
1202                                        const gchar         *mime_types)
1203 {
1204   g_return_if_fail (GIMP_IS_PLUG_IN_PROCEDURE (proc));
1205 
1206   if (proc->mime_types != mime_types)
1207     {
1208       if (proc->mime_types)
1209         g_free (proc->mime_types);
1210 
1211       proc->mime_types = g_strdup (mime_types);
1212     }
1213 
1214   if (proc->mime_types_list)
1215     g_slist_free_full (proc->mime_types_list, (GDestroyNotify) g_free);
1216 
1217   proc->mime_types_list = extensions_parse (proc->mime_types);
1218 }
1219 
1220 void
gimp_plug_in_procedure_set_handles_uri(GimpPlugInProcedure * proc)1221 gimp_plug_in_procedure_set_handles_uri (GimpPlugInProcedure *proc)
1222 {
1223   g_return_if_fail (GIMP_IS_PLUG_IN_PROCEDURE (proc));
1224 
1225   proc->handles_uri = TRUE;
1226 }
1227 
1228 void
gimp_plug_in_procedure_set_handles_raw(GimpPlugInProcedure * proc)1229 gimp_plug_in_procedure_set_handles_raw (GimpPlugInProcedure *proc)
1230 {
1231   g_return_if_fail (GIMP_IS_PLUG_IN_PROCEDURE (proc));
1232 
1233   proc->handles_raw = TRUE;
1234 }
1235 
1236 void
gimp_plug_in_procedure_set_thumb_loader(GimpPlugInProcedure * proc,const gchar * thumb_loader)1237 gimp_plug_in_procedure_set_thumb_loader (GimpPlugInProcedure *proc,
1238                                          const gchar         *thumb_loader)
1239 {
1240   g_return_if_fail (GIMP_IS_PLUG_IN_PROCEDURE (proc));
1241 
1242   if (proc->thumb_loader)
1243     g_free (proc->thumb_loader);
1244 
1245   proc->thumb_loader = g_strdup (thumb_loader);
1246 }
1247 
1248 void
gimp_plug_in_procedure_handle_return_values(GimpPlugInProcedure * proc,Gimp * gimp,GimpProgress * progress,GimpValueArray * return_vals)1249 gimp_plug_in_procedure_handle_return_values (GimpPlugInProcedure *proc,
1250                                              Gimp                *gimp,
1251                                              GimpProgress        *progress,
1252                                              GimpValueArray      *return_vals)
1253 {
1254   g_return_if_fail (GIMP_IS_PLUG_IN_PROCEDURE (proc));
1255   g_return_if_fail (return_vals != NULL);
1256 
1257   if (gimp_value_array_length (return_vals) == 0 ||
1258       G_VALUE_TYPE (gimp_value_array_index (return_vals, 0)) !=
1259       GIMP_TYPE_PDB_STATUS_TYPE)
1260     {
1261       return;
1262     }
1263 
1264   switch (g_value_get_enum (gimp_value_array_index (return_vals, 0)))
1265     {
1266     case GIMP_PDB_SUCCESS:
1267       break;
1268 
1269     case GIMP_PDB_CALLING_ERROR:
1270       if (gimp_value_array_length (return_vals) > 1 &&
1271           G_VALUE_HOLDS_STRING (gimp_value_array_index (return_vals, 1)))
1272         {
1273           gimp_message (gimp, G_OBJECT (progress), GIMP_MESSAGE_ERROR,
1274                         _("Calling error for '%s':\n"
1275                           "%s"),
1276                         gimp_procedure_get_label (GIMP_PROCEDURE (proc)),
1277                         g_value_get_string (gimp_value_array_index (return_vals, 1)));
1278         }
1279       break;
1280 
1281     case GIMP_PDB_EXECUTION_ERROR:
1282       if (gimp_value_array_length (return_vals) > 1 &&
1283           G_VALUE_HOLDS_STRING (gimp_value_array_index (return_vals, 1)))
1284         {
1285           gimp_message (gimp, G_OBJECT (progress), GIMP_MESSAGE_ERROR,
1286                         _("Execution error for '%s':\n"
1287                           "%s"),
1288                         gimp_procedure_get_label (GIMP_PROCEDURE (proc)),
1289                         g_value_get_string (gimp_value_array_index (return_vals, 1)));
1290         }
1291       break;
1292     }
1293 }
1294