script-fu-scripts.c 62.5 KB
Newer Older
Elliot Lee's avatar
Elliot Lee committed
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
/* The GIMP -- an image manipulation program
 * Copyright (C) 1995 Spencer Kimball and Peter Mattis
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 2 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
16
 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
Elliot Lee's avatar
Elliot Lee committed
17
18
 */

Tor Lillqvist's avatar
Tor Lillqvist committed
19
20
#include "config.h"

Tor Lillqvist's avatar
Tor Lillqvist committed
21
22
#include <glib.h>		/* Include early for obscure Win32
				   build reasons */
Elliot Lee's avatar
Elliot Lee committed
23
24
25
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
Asbjørn Pettersen's avatar
Asbjørn Pettersen committed
26
#include <sys/types.h>
Tor Lillqvist's avatar
Tor Lillqvist committed
27
#if HAVE_DIRENT_H
Elliot Lee's avatar
Elliot Lee committed
28
#include <dirent.h>
Tor Lillqvist's avatar
Tor Lillqvist committed
29
#endif
Elliot Lee's avatar
Elliot Lee committed
30
#include <sys/stat.h>
Sven Neumann's avatar
Sven Neumann committed
31
#include <ctype.h>		/* For toupper() */
Tor Lillqvist's avatar
Tor Lillqvist committed
32

33
#include <gtk/gtk.h>
Tor Lillqvist's avatar
Tor Lillqvist committed
34

35
36
#include <libgimp/gimp.h>
#include <libgimp/gimpui.h>
Tor Lillqvist's avatar
Tor Lillqvist committed
37

Elliot Lee's avatar
Elliot Lee committed
38
39
40
#include "siod.h"
#include "script-fu-scripts.h"

Sven Neumann's avatar
Sven Neumann committed
41
#include "script-fu-intl.h"
42

43
#ifdef G_OS_WIN32
Tor Lillqvist's avatar
Tor Lillqvist committed
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
#define STRICT
#include <windows.h>

#include <io.h>

#ifndef W_OK
#define W_OK 2
#endif
#ifndef S_ISDIR
#define S_ISDIR(m) ((m) & _S_IFDIR)
#endif
#ifndef S_ISREG
#define S_ISREG(m) ((m) & _S_IFREG)
#endif

59
#endif /* G_OS_WIN32 */
Tor Lillqvist's avatar
Tor Lillqvist committed
60

61
#define ESCAPE(string) gimp_strescape (string, NULL)
62

63
64
65
66
67
68
69
#define TEXT_WIDTH           100
#define TEXT_HEIGHT           25
#define COLOR_SAMPLE_WIDTH   100
#define COLOR_SAMPLE_HEIGHT   15
#define SLIDER_WIDTH         100
#define SPINNER_WIDTH         75
#define FONT_PREVIEW_WIDTH   100
Sven Neumann's avatar
Sven Neumann committed
70

71
#define DEFAULT_FONT_SIZE    240
Elliot Lee's avatar
Elliot Lee committed
72

73
#define MAX_STRING_LENGTH   4096
74

Elliot Lee's avatar
Elliot Lee committed
75

76
77
78
79
80
81
82
83
84
85
86
87
typedef struct
{
  GtkAdjustment *adj;
  gfloat         value;
  gfloat         lower;
  gfloat         upper;
  gfloat         step;
  gfloat         page;
  gint           digits;
  SFAdjustmentType type;
} SFAdjustment;

Sven Neumann's avatar
Sven Neumann committed
88
89
90
91
92
93
94
typedef struct
{
  GtkWidget *preview;
  GtkWidget *dialog;
  gchar     *fontname;
} SFFont;

Manish Singh's avatar
Manish Singh committed
95
96
typedef struct
{
97
  GtkWidget *fileselection;
Manish Singh's avatar
Manish Singh committed
98
99
100
  gchar     *filename;
} SFFilename;

101
102
typedef struct 
{
103
  gchar   *name;
104
105
106
107
108
  gdouble  opacity;
  gint     spacing;
  gint     paint_mode;
} SFBrush;

109
110
111
112
113
114
typedef struct 
{
  GSList  *list;
  guint    history;
} SFOption;

Elliot Lee's avatar
Elliot Lee committed
115
116
typedef union
{
117
118
119
120
  gint32        sfa_image;
  gint32        sfa_drawable;
  gint32        sfa_layer;
  gint32        sfa_channel;
121
  guchar        sfa_color[3];
122
  gint32        sfa_toggle;
123
  gchar        *sfa_value;
124
  SFAdjustment  sfa_adjustment;
Sven Neumann's avatar
Sven Neumann committed
125
  SFFont        sfa_font;
Manish Singh's avatar
Manish Singh committed
126
  SFFilename    sfa_file;
127
128
  gchar        *sfa_pattern;
  gchar        *sfa_gradient;
129
  SFBrush       sfa_brush;
130
  SFOption      sfa_option;
Elliot Lee's avatar
Elliot Lee committed
131
132
133
134
} SFArgValue;

typedef struct
{
135
136
137
138
139
140
141
142
143
  GtkWidget  **args_widgets;
  gchar       *script_name;
  gchar       *pdb_name;
  gchar       *description;
  gchar       *help;
  gchar       *author;
  gchar       *copyright;
  gchar       *date;
  gchar       *img_types;
Elliot Lee's avatar
Elliot Lee committed
144
  gint         num_args;
145
146
147
148
  SFArgType   *arg_types;
  gchar      **arg_labels;
  SFArgValue  *arg_defaults;
  SFArgValue  *arg_values;
Elliot Lee's avatar
Elliot Lee committed
149
  gint32       image_based;
150
  GParamDef   *args;     /*  used only temporary until installed  */
Elliot Lee's avatar
Elliot Lee committed
151
152
153
154
} SFScript;

typedef struct
{
155
  GtkWidget *status;
Sven Neumann's avatar
Sven Neumann committed
156
  GtkWidget *about_dialog;
Elliot Lee's avatar
Elliot Lee committed
157
158
159
160
161
  SFScript  *script;
} SFInterface;

/* External functions
 */
162
extern long  nlength (LISP obj);
Elliot Lee's avatar
Elliot Lee committed
163
164
165
166
167

/*
 *  Local Functions
 */

168
169
170
171
172
173
static gint      script_fu_install_script    (gpointer  foo,
					      SFScript *script,
					      gpointer  bar);
static gint      script_fu_remove_script     (gpointer  foo,
					      SFScript *script,
					      gpointer  bar);
174
175
static void       script_fu_script_proc      (gchar     *name,
					      gint       nparams,
176
					      GParam    *params,
177
					      gint      *nreturn_vals,
178
179
					      GParam   **return_vals);

180
static SFScript * script_fu_find_script      (gchar     *script_name);
181
static void       script_fu_free_script      (SFScript  *script);
Elliot Lee's avatar
Elliot Lee committed
182
static void       script_fu_enable_cc        (void);
183
184
static void       script_fu_disable_cc       (gint       err_msg);
static void       script_fu_interface        (SFScript  *script);
Manish Singh's avatar
Manish Singh committed
185
static void       script_fu_font_preview     (GtkWidget *preview,
186
187
					      gchar     *fontname);
static void       script_fu_cleanup_widgets  (SFScript  *script);
Elliot Lee's avatar
Elliot Lee committed
188
189
static void       script_fu_ok_callback      (GtkWidget *widget,
					      gpointer   data);
190
191
static gint       script_fu_destroy_callback (GtkWidget *widget,
					      gpointer   data);
Sven Neumann's avatar
Sven Neumann committed
192
193
static void       script_fu_about_callback   (GtkWidget *widget,
					      gpointer   data);
194
195
static void       script_fu_reset_callback   (GtkWidget *widget,
					      gpointer   data);
Elliot Lee's avatar
Elliot Lee committed
196
197
static void       script_fu_menu_callback    (gint32     id,
					      gpointer   data);
198
static void       script_fu_file_selection_callback(GtkWidget *widget,
Manish Singh's avatar
Manish Singh committed
199
						    gpointer   data);
Sven Neumann's avatar
Sven Neumann committed
200
201
202
203
204
205
206
207
208
static void       script_fu_font_preview_callback  (GtkWidget *widget,
						    gpointer   data);
static void       script_fu_font_dialog_ok         (GtkWidget *widget,
						    gpointer   data);
static void       script_fu_font_dialog_cancel     (GtkWidget *widget,
						    gpointer   data);
static gint       script_fu_font_dialog_delete     (GtkWidget *widget,
						    GdkEvent  *event,
						    gpointer   data);
Sven Neumann's avatar
Sven Neumann committed
209
210
211
212
213
static void       script_fu_about_dialog_close     (GtkWidget *widget,
						    gpointer   data);
static gint       script_fu_about_dialog_delete    (GtkWidget *widget,
						    GdkEvent  *event,
						    gpointer   data);
214
215
216
217
218
219
static void       script_fu_pattern_preview        (gchar     *name,
						    gint      width,
						    gint      height,
						    gint      bytes,
						    gchar    *mask_data,
						    gint      closing,
220
						    gpointer  data);
221
222

static void       script_fu_gradient_preview       (gchar    *name,
223
224
225
						    gint      width,
						    gdouble  *mask_data,
						    gint      closing,
226
						    gpointer  data);
227

228
229
230
231
232
233
234
235
236
static void       script_fu_brush_preview          (gchar    *name,
						    gdouble   opacity,
						    gint      spacing,
						    gint      paint_mode,
						    gint      width,
						    gint      height,
						    gchar    *mask_data,
						    gint      closing,
						    gpointer  data);
237

Elliot Lee's avatar
Elliot Lee committed
238
239
240
241
242
243
244

/*
 *  Local variables
 */

static SFInterface sf_interface =
{
245
  NULL,  /*  status (current command) */
246
247
  NULL,  /*  about_dialog             */
  NULL   /*  active script            */
Elliot Lee's avatar
Elliot Lee committed
248
249
};

250
251
252
253
254
static struct stat  filestat;
static gboolean     current_command_enabled = FALSE;
static gint         command_count           = 0;
static gint         consec_command_count    = 0;
static gchar       *last_command            = NULL;
255
static GTree       *script_list             = NULL;
Elliot Lee's avatar
Elliot Lee committed
256

257
extern gchar        siod_err_msg[];
Elliot Lee's avatar
Elliot Lee committed
258
259
260
261
262
263

/*
 *  Function definitions
 */

void
264
script_fu_find_scripts (void)
Elliot Lee's avatar
Elliot Lee committed
265
266
267
268
269
270
271
272
273
{
  gchar *path_str;
  gchar *home;
  gchar *local_path;
  gchar *path;
  gchar *filename;
  gchar *token;
  gchar *next_token;
  gchar *command;
274
  gint   my_err;
Elliot Lee's avatar
Elliot Lee committed
275
276
277
278
279
280
  DIR   *dir;
  struct dirent *dir_ent;

  /*  Make sure to clear any existing scripts  */
  if (script_list != NULL)
    {
281
282
283
      g_tree_traverse (script_list, 
		       (GTraverseFunc)script_fu_remove_script, G_IN_ORDER, NULL);
      g_tree_destroy (script_list);
Elliot Lee's avatar
Elliot Lee committed
284
285
    }

286
287
288
289
290
291
#ifdef ENABLE_NLS
  script_list = g_tree_new ((GCompareFunc)strcoll);
#else
  script_list = g_tree_new ((GCompareFunc)strcmp);
#endif

292
  path_str = gimp_gimprc_query ("script-fu-path");
Elliot Lee's avatar
Elliot Lee committed
293

294
295
  if (path_str == NULL)
    return;
Elliot Lee's avatar
Elliot Lee committed
296

297
298
299
300
301
302
303
304
305
306
307
  /* Set local path to contain temp_path, where (supposedly)
   * there may be working files.
   */
  home = g_get_home_dir ();
  local_path = g_strdup (path_str);
  
  /* Search through all directories in the local path */
  
  next_token = local_path;
  
  token = strtok (next_token, G_SEARCHPATH_SEPARATOR_S);
Elliot Lee's avatar
Elliot Lee committed
308

309
310
311
  while (token)
    {
      if (*token == '~')
Elliot Lee's avatar
Elliot Lee committed
312
	{
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
	  path = g_malloc (strlen (home) + strlen (token) + 2);
	  sprintf (path, "%s%s", home, token + 1);
	}
      else
	{
	  path = g_malloc (strlen (token) + 2);
	  strcpy (path, token);
	} /* else */
      
      /* Check if directory exists and if it has any items in it */
      my_err = stat (path, &filestat);
      
      if (!my_err && S_ISDIR (filestat.st_mode))
	{
	  if (path[strlen (path) - 1] != G_DIR_SEPARATOR)
	    strcat (path, G_DIR_SEPARATOR_S);
	  
	  /* Open directory */
	  dir = opendir (path);
	  
	  if (!dir)
	    g_message ("error reading script directory \"%s\"", path);
Elliot Lee's avatar
Elliot Lee committed
335
336
	  else
	    {
337
	      while ((dir_ent = readdir (dir)))
Elliot Lee's avatar
Elliot Lee committed
338
		{
339
340
341
		  filename = g_strdup_printf ("%s%s", path, dir_ent->d_name);
		  
		  if (g_strcasecmp (filename + strlen (filename) - 4, ".scm") == 0)
Elliot Lee's avatar
Elliot Lee committed
342
		    {
343
344
345
346
		      /* Check the file and see that it is not a sub-directory */
		      my_err = stat (filename, &filestat);
		      
		      if (!my_err && S_ISREG (filestat.st_mode))
Elliot Lee's avatar
Elliot Lee committed
347
			{
348
			  char *qf = ESCAPE (filename);
Asbjørn Pettersen's avatar
Asbjørn Pettersen committed
349
#ifdef __EMX__
350
			  _fnslashify(qf);
Asbjørn Pettersen's avatar
Asbjørn Pettersen committed
351
#endif
352
353
354
			  command = g_strdup_printf ("(load \"%s\")", qf);
			  g_free (qf);
			  repl_c_string (command, 0, 0, 1);
355
#ifdef G_OS_WIN32
356
357
358
359
			  /* No, I don't know why, but this is 
			   * necessary on NT 4.0.
			   */
			  Sleep(0);
Tor Lillqvist's avatar
Tor Lillqvist committed
360
#endif
361
			  g_free (command);
Elliot Lee's avatar
Elliot Lee committed
362
			}
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
		    }
		  
		  g_free (filename);
		} /* while */
	      
	      closedir (dir);
	    } /* else */
	} /* if */

      g_free (path);
      
      token = strtok (NULL, G_SEARCHPATH_SEPARATOR_S);
    } /* while */
  
  g_free (local_path);
  g_free (path_str);
379
380
381
382

  /*  now that all scripts are read in and sorted, tell gimp about them  */
  g_tree_traverse (script_list, 
		   (GTraverseFunc)script_fu_install_script, G_IN_ORDER, NULL);
Elliot Lee's avatar
Elliot Lee committed
383
384
385
386
387
388
}

LISP
script_fu_add_script (LISP a)
{
  GParamDef *args;
389
  SFScript  *script;
390
391
  gchar *val;
  gint i;
392
  guchar color[3];
Elliot Lee's avatar
Elliot Lee committed
393
  LISP color_list;
394
  LISP adj_list;
395
  LISP brush_list;
396
397
  LISP option_list;
  gchar *s;
Elliot Lee's avatar
Elliot Lee committed
398
399
400

  /*  Check the length of a  */
  if (nlength (a) < 7)
401
    return my_err ("Too few arguments to script-fu-register", NIL);
Elliot Lee's avatar
Elliot Lee committed
402
403
404
405
406
407
408
409
410

  /*  Create a new script  */
  script = g_new (SFScript, 1);

  /*  Find the script name  */
  val = get_c_string (car (a));
  script->script_name = g_strdup (val);
  a = cdr (a);

Marc Lehmann's avatar
Marc Lehmann committed
411
412
413
414
415
416
417
418
419
  /* transform the function name into a name containing "_" for each "-".
   * this does not hurt anybody, yet improves the life of many... ;)
   */
  script->pdb_name = g_strdup (val);

  for (s = script->pdb_name; *s; s++)
    if (*s == '-')
      *s = '_';

Elliot Lee's avatar
Elliot Lee committed
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
  /*  Find the script description  */
  val = get_c_string (car (a));
  script->description = g_strdup (val);
  a = cdr (a);

  /*  Find the script help  */
  val = get_c_string (car (a));
  script->help = g_strdup (val);
  a = cdr (a);

  /*  Find the script author  */
  val = get_c_string (car (a));
  script->author = g_strdup (val);
  a = cdr (a);

  /*  Find the script copyright  */
  val = get_c_string (car (a));
  script->copyright = g_strdup (val);
  a = cdr (a);

  /*  Find the script date  */
  val = get_c_string (car (a));
  script->date = g_strdup (val);
  a = cdr (a);

  /*  Find the script image types  */
  if (TYPEP (a, tc_cons))
    {
      val = get_c_string (car (a));
      a = cdr (a);
    }
  else
    {
      val = get_c_string (a);
      a = NIL;
    }
  script->img_types = g_strdup (val);

  /*  Check the supplied number of arguments  */
  script->num_args = nlength (a) / 3;

461
462
463
464
465
466
  args = g_new (GParamDef, script->num_args + 1);
  args[0].type = PARAM_INT32;
  args[0].name = "run_mode";
  args[0].description = "Interactive, non-interactive";

  script->args_widgets = NULL;
467
  script->arg_types    = g_new (SFArgType, script->num_args);
468
  script->arg_labels   = g_new (gchar *, script->num_args);
469
470
  script->arg_defaults = g_new0 (SFArgValue, script->num_args);
  script->arg_values   = g_new0 (SFArgValue, script->num_args);
471

Elliot Lee's avatar
Elliot Lee committed
472
473
474
475
476
477
478
  if (script->num_args > 0)
    {
      for (i = 0; i < script->num_args; i++)
	{
	  if (a != NIL)
	    {
	      if (!TYPEP (car (a), tc_flonum))
479
		return my_err ("script-fu-register: argument types must be integer values", NIL);
Elliot Lee's avatar
Elliot Lee committed
480
481
482
483
	      script->arg_types[i] = get_c_long (car (a));
	      a = cdr (a);
	    }
	  else
484
	    return my_err ("script-fu-register: missing type specifier", NIL);
Elliot Lee's avatar
Elliot Lee committed
485
486
487
488

	  if (a != NIL)
	    {
	      if (!TYPEP (car (a), tc_string))
489
		return my_err ("script-fu-register: argument labels must be strings", NIL);
Elliot Lee's avatar
Elliot Lee committed
490
491
492
493
	      script->arg_labels[i] = g_strdup (get_c_string (car (a)));
	      a = cdr (a);
	    }
	  else
494
	    return my_err ("script-fu-register: missing arguments label", NIL);
Elliot Lee's avatar
Elliot Lee committed
495
496
497
498
499
500
501
502
503
504

	  if (a != NIL)
	    {
	      switch (script->arg_types[i])
		{
		case SF_IMAGE:
		case SF_DRAWABLE:
		case SF_LAYER:
		case SF_CHANNEL:
		  if (!TYPEP (car (a), tc_flonum))
505
		    return my_err ("script-fu-register: drawable defaults must be integer values", NIL);
Elliot Lee's avatar
Elliot Lee committed
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
		  script->arg_defaults[i].sfa_image = get_c_long (car (a));
		  script->arg_values[i].sfa_image = script->arg_defaults[i].sfa_image;

		  switch (script->arg_types[i])
		    {
		    case SF_IMAGE:
		      args[i + 1].type = PARAM_IMAGE;
		      args[i + 1].name = "image";
		      break;
		    case SF_DRAWABLE:
		      args[i + 1].type = PARAM_DRAWABLE;
		      args[i + 1].name = "drawable";
		      break;
		    case SF_LAYER:
		      args[i + 1].type = PARAM_LAYER;
		      args[i + 1].name = "layer";
		      break;
		    case SF_CHANNEL:
		      args[i + 1].type = PARAM_CHANNEL;
		      args[i + 1].name = "channel";
		      break;
		    default:
		      break;
		    }

		  args[i + 1].description = script->arg_labels[i];
		  break;

		case SF_COLOR:
		  if (!TYPEP (car (a), tc_cons))
536
		    return my_err ("script-fu-register: color defaults must be a list of 3 integers", NIL);
Elliot Lee's avatar
Elliot Lee committed
537
		  color_list = car (a);
538
		  color[0] = (guchar)(CLAMP (get_c_long (car (color_list)), 0, 255));
Elliot Lee's avatar
Elliot Lee committed
539
		  color_list = cdr (color_list);
540
		  color[1] = (guchar)(CLAMP (get_c_long (car (color_list)), 0, 255));
Elliot Lee's avatar
Elliot Lee committed
541
		  color_list = cdr (color_list);
542
543
544
		  color[2] = (guchar)(CLAMP (get_c_long (car (color_list)), 0, 255));
		  memcpy (script->arg_defaults[i].sfa_color, color, sizeof (guchar) * 3);
		  memcpy (script->arg_values[i].sfa_color, color, sizeof (guchar) * 3);
Elliot Lee's avatar
Elliot Lee committed
545
546
547
548
549
550
551
552

		  args[i + 1].type = PARAM_COLOR;
		  args[i + 1].name = "color";
		  args[i + 1].description = script->arg_labels[i];
		  break;

		case SF_TOGGLE:
		  if (!TYPEP (car (a), tc_flonum))
553
		    return my_err ("script-fu-register: toggle default must be an integer value", NIL);
Elliot Lee's avatar
Elliot Lee committed
554
555
556
557
558
559
560
561
		  script->arg_defaults[i].sfa_toggle = (get_c_long (car (a))) ? TRUE : FALSE;
		  script->arg_values[i].sfa_toggle = script->arg_defaults[i].sfa_toggle;

		  args[i + 1].type = PARAM_INT32;
		  args[i + 1].name = "toggle";
		  args[i + 1].description = script->arg_labels[i];
		  break;

Sven Neumann's avatar
Sven Neumann committed
562
		case SF_VALUE:  
Elliot Lee's avatar
Elliot Lee committed
563
		  if (!TYPEP (car (a), tc_string))
564
		    return my_err ("script-fu-register: value defaults must be string values", NIL);
Elliot Lee's avatar
Elliot Lee committed
565
		  script->arg_defaults[i].sfa_value = g_strdup (get_c_string (car (a)));
566
		  script->arg_values[i].sfa_value =  g_strdup (script->arg_defaults[i].sfa_value);
Elliot Lee's avatar
Elliot Lee committed
567
568
569
570
571

		  args[i + 1].type = PARAM_STRING;
		  args[i + 1].name = "value";
		  args[i + 1].description = script->arg_labels[i];
		  break;
572
573
574
575

		case SF_STRING:
		  if (!TYPEP (car (a), tc_string))
		    return my_err ("script-fu-register: string defaults must be string values", NIL);
576
577
		  script->arg_defaults[i].sfa_value = g_strdup (get_c_string (car (a)));
		  script->arg_values[i].sfa_value =  g_strdup (script->arg_defaults[i].sfa_value);
578
579
580
581
582
583

		  args[i + 1].type = PARAM_STRING;
		  args[i + 1].name = "string";
		  args[i + 1].description = script->arg_labels[i];
		  break;

584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
		case SF_ADJUSTMENT:
		  if (!TYPEP (car (a), tc_cons))
		    return my_err ("script-fu-register: adjustment defaults must be a list", NIL);
		  adj_list = car (a);
		  script->arg_defaults[i].sfa_adjustment.value = get_c_double (car (adj_list));
		  adj_list = cdr (adj_list);
		  script->arg_defaults[i].sfa_adjustment.lower = get_c_double (car (adj_list));
		  adj_list = cdr (adj_list);
		  script->arg_defaults[i].sfa_adjustment.upper = get_c_double (car (adj_list));
		  adj_list = cdr (adj_list);
		  script->arg_defaults[i].sfa_adjustment.step = get_c_double (car (adj_list));
		  adj_list = cdr (adj_list);
		  script->arg_defaults[i].sfa_adjustment.page = get_c_double (car (adj_list));
		  adj_list = cdr (adj_list);
		  script->arg_defaults[i].sfa_adjustment.digits = get_c_long (car (adj_list));
		  adj_list = cdr (adj_list);
		  script->arg_defaults[i].sfa_adjustment.type = get_c_long (car (adj_list));
		  script->arg_values[i].sfa_adjustment.adj = NULL;
		  script->arg_values[i].sfa_adjustment.value = script->arg_defaults[i].sfa_adjustment.value;

		  args[i + 1].type = PARAM_STRING;
		  args[i + 1].name = "value";
		  args[i + 1].description = script->arg_labels[i];
		  break;

Manish Singh's avatar
Manish Singh committed
609
610
611
612
		case SF_FILENAME:
		  if (!TYPEP (car (a), tc_string))
		    return my_err ("script-fu-register: filename defaults must be string values", NIL);
		  script->arg_defaults[i].sfa_file.filename = g_strdup (get_c_string (car (a)));
Tor Lillqvist's avatar
Tor Lillqvist committed
613

614
#ifdef G_OS_WIN32
Tor Lillqvist's avatar
Tor Lillqvist committed
615
616
617
618
619
620
621
622
623
624
625
626
		  /* Replace POSIX slashes with Win32 backslashes. This
		   * is just so script-fus can be written with only
		   * POSIX directory separators.
		   */
		  val = script->arg_defaults[i].sfa_file.filename;
		  while (*val)
		    {
		      if (*val == '/')
			*val = '\\';
		      val++;
		    }
#endif
627
628
		  script->arg_values[i].sfa_file.filename =  g_strdup (script->arg_defaults[i].sfa_file.filename);
		  script->arg_values[i].sfa_file.fileselection = NULL;
Manish Singh's avatar
Manish Singh committed
629

630
631
632
		  args[i + 1].type = PARAM_STRING;
		  args[i + 1].name = "filename";
		  args[i + 1].description = script->arg_labels[i];
Manish Singh's avatar
Manish Singh committed
633
634
		 break;

Sven Neumann's avatar
Sven Neumann committed
635
636
637
638
639
640
641
642
643
644
645
646
		case SF_FONT:
		  if (!TYPEP (car (a), tc_string))
		    return my_err ("script-fu-register: font defaults must be string values", NIL);
		  script->arg_defaults[i].sfa_font.fontname = g_strdup (get_c_string (car (a)));
		  script->arg_values[i].sfa_font.fontname =  g_strdup (script->arg_defaults[i].sfa_font.fontname);
		  script->arg_values[i].sfa_font.preview = NULL;
		  script->arg_values[i].sfa_font.dialog = NULL;
		  
		  args[i + 1].type = PARAM_STRING;
		  args[i + 1].name = "font";
		  args[i + 1].description = script->arg_labels[i];
		  break;
647
648
649
650
651
652
653
654
655
656
657
658

		case SF_PATTERN:
		  if (!TYPEP (car (a), tc_string))
		    return my_err ("script-fu-register: pattern defaults must be string values", NIL);
		  script->arg_defaults[i].sfa_pattern = g_strdup (get_c_string (car (a)));
		  script->arg_values[i].sfa_pattern =  g_strdup (script->arg_defaults[i].sfa_pattern);

		  args[i + 1].type = PARAM_STRING;
		  args[i + 1].name = "pattern";
		  args[i + 1].description = script->arg_labels[i];
		  break;

659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
		case SF_BRUSH:
		  if (!TYPEP (car (a), tc_cons))
		    return my_err ("script-fu-register: brush defaults must be a list", NIL);
		  brush_list = car (a);
		  script->arg_defaults[i].sfa_brush.name = g_strdup (get_c_string (car (brush_list)));
		  brush_list = cdr (brush_list);
		  script->arg_defaults[i].sfa_brush.opacity = get_c_double (car (brush_list));
		  brush_list = cdr (brush_list);
		  script->arg_defaults[i].sfa_brush.spacing = get_c_long (car (brush_list));
		  brush_list = cdr (brush_list);
		  script->arg_defaults[i].sfa_brush.paint_mode = get_c_long (car (brush_list));
		  script->arg_values[i].sfa_brush = script->arg_defaults[i].sfa_brush;
		  /* Need this since we need a copy of the string
		   * in the values area. We could free it later but the
		   * default one must hang around.
		   */
		  script->arg_values[i].sfa_brush.name = g_strdup(script->arg_defaults[i].sfa_brush.name);

		  args[i + 1].type = PARAM_STRING;
		  args[i + 1].name = "brush";
		  args[i + 1].description = script->arg_labels[i];
Sven Neumann's avatar
Sven Neumann committed
680
		  break;
681

682
683
684
685
686
687
688
689
690
691
692
		case SF_GRADIENT:
		  if (!TYPEP (car (a), tc_string))
		    return my_err ("script-fu-register: gradient defaults must be string values", NIL);
		  script->arg_defaults[i].sfa_gradient = g_strdup (get_c_string (car (a)));
		  script->arg_values[i].sfa_gradient =  g_strdup (script->arg_defaults[i].sfa_pattern);
		  
		  args[i + 1].type = PARAM_STRING;
		  args[i + 1].name = "gradient";
		  args[i + 1].description = script->arg_labels[i];
		  break;

693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
		case SF_OPTION:
		  if (!TYPEP (car (a), tc_cons))
		    return my_err ("script-fu-register: option defaults must be a list", NIL);
		  for (option_list = car (a); option_list; option_list = cdr (option_list))
		    {
		      script->arg_defaults[i].sfa_option.list = 
			g_slist_append (script->arg_defaults[i].sfa_option.list, 
					g_strdup (get_c_string (car (option_list))));
		    }
		  script->arg_defaults[i].sfa_option.history = 0;
		  script->arg_values[i].sfa_option.history = 0;

		  args[i + 1].type = PARAM_INT32;
		  args[i + 1].name = "option";
		  args[i + 1].description = script->arg_labels[i];
		  break;

Elliot Lee's avatar
Elliot Lee committed
710
711
712
713
714
715
716
		default:
		  break;
		}

	      a = cdr (a);
	    }
	  else
717
	    return my_err ("script-fu-register: missing default argument", NIL);
Elliot Lee's avatar
Elliot Lee committed
718
719
720
	}
    }

721
722
  script->args = args;
  g_tree_insert (script_list, gettext (script->description), script);
Elliot Lee's avatar
Elliot Lee committed
723
724
725
726
727
728
729
730
731

  return NIL;
}

void
script_fu_report_cc (gchar *command)
{
  if (last_command && strcmp (last_command, command) == 0)
    {
732
      gchar *new_command;
Elliot Lee's avatar
Elliot Lee committed
733
734
735
736

      new_command = g_new (gchar, strlen (command) + 10);
      sprintf (new_command, "%s <%d>", command, ++consec_command_count);
      if (current_command_enabled == TRUE)
737
738
739
	{
	  gtk_entry_set_text (GTK_ENTRY (sf_interface.status), new_command);
	}
Elliot Lee's avatar
Elliot Lee committed
740
741
742
743
744
745
746
      g_free (new_command);
      g_free (last_command);
    }
  else
    {
      consec_command_count = 1;
      if (current_command_enabled == TRUE)
747
	gtk_entry_set_text (GTK_ENTRY (sf_interface.status), command);
Elliot Lee's avatar
Elliot Lee committed
748
749
750
751
752
753
754
755
756
757
      if (last_command)
	g_free (last_command);
    }
  last_command = g_strdup (command);
  command_count++;

  if (current_command_enabled == TRUE)
    gdk_flush ();
}

758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806

/* 
 *  The following function is a GTraverseFunction, Please 
 *  note that it frees the script->args strcuture.  --Sven 
 */
static gint
script_fu_install_script (gpointer  foo,
			  SFScript *script,
			  gpointer  bar)
{
  gchar *menu_path = NULL;

  /* Allow scripts with no menus */
  if (strncmp (script->description, "<None>", 6) != 0)
    menu_path = script->description;

  gimp_install_temp_proc (script->pdb_name,
                          script->description,
                          script->help,
                          script->author,
                          script->copyright,
                          script->date,
                          menu_path,
                          script->img_types,
                          PROC_TEMPORARY,
                          script->num_args + 1, 0,
                          script->args, NULL,
                          script_fu_script_proc);
  g_free (script->args);
  script->args = NULL;

  return FALSE;
}

/* 
 *  The following function is a GTraverseFunction.
 */
static gint
script_fu_remove_script (gpointer  foo,
			 SFScript *script,
			 gpointer  bar)
{
  script_fu_free_script (script);

  return FALSE;
}



Elliot Lee's avatar
Elliot Lee committed
807
static void
808
809
script_fu_script_proc (gchar    *name,
		       gint      nparams,
Elliot Lee's avatar
Elliot Lee committed
810
		       GParam   *params,
811
		       gint     *nreturn_vals,
Elliot Lee's avatar
Elliot Lee committed
812
813
814
815
816
817
		       GParam  **return_vals)
{
  static GParam values[1];
  GStatusType status = STATUS_SUCCESS;
  GRunModeType run_mode;
  SFScript *script;
818
819
  gint min_args;
  gchar *escaped;
Elliot Lee's avatar
Elliot Lee committed
820
821
822
823
824
825
826

  run_mode = params[0].data.d_int32;

  if (! (script = script_fu_find_script (name)))
    status = STATUS_CALLING_ERROR;
  else
    {
827
828
829
      if (script->num_args == 0)
	run_mode = RUN_NONINTERACTIVE;

Elliot Lee's avatar
Elliot Lee committed
830
831
832
833
834
835
836
      switch (run_mode)
	{
	case RUN_INTERACTIVE:
	case RUN_WITH_LAST_VALS:
	  /*  Determine whether the script is image based (runs on an image)  */
	  if (strncmp (script->description, "<Image>", 7) == 0)
	    {
837
	      script->arg_values[0].sfa_image    = params[1].data.d_image;
Elliot Lee's avatar
Elliot Lee committed
838
839
840
841
842
843
844
	      script->arg_values[1].sfa_drawable = params[2].data.d_drawable;
	      script->image_based = TRUE;
	    }
	  else
	    script->image_based = FALSE;

	  /*  First acquire information with a dialog  */
845
846
	  /*  Skip this part if the script takes no parameters */ 
	  min_args = (script->image_based) ? 2 : 0;
847
848
849
850
851
	  if (script->num_args > min_args) 
	    {
	      script_fu_interface (script); 
	      break;
	    }
Elliot Lee's avatar
Elliot Lee committed
852
853
854
855
856
857
858

	case RUN_NONINTERACTIVE:
	  /*  Make sure all the arguments are there!  */
	  if (nparams != (script->num_args + 1))
	    status = STATUS_CALLING_ERROR;
	  if (status == STATUS_SUCCESS)
	    {
859
860
861
862
863
864
865
	      gchar *text = NULL;
	      gchar *command;
	      gchar *c;
	      gchar  buffer[MAX_STRING_LENGTH];
	      gint   err_msg;
	      gint   length;
	      gint   i;
Elliot Lee's avatar
Elliot Lee committed
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886

	      length = strlen (script->script_name) + 3;

	      for (i = 0; i < script->num_args; i++)
		switch (script->arg_types[i])
		  {
		  case SF_IMAGE:
		  case SF_DRAWABLE:
		  case SF_LAYER:
		  case SF_CHANNEL:
		    length += 12;  /*  Maximum size of integer value will not exceed this many characters  */
		    break;
		  case SF_COLOR:
		    length += 16;  /*  Maximum size of color string: '(XXX XXX XXX)  */
		    break;
		  case SF_TOGGLE:
		    length += 6;   /*  Maximum size of (TRUE, FALSE)  */
		    break;
		  case SF_VALUE:
		    length += strlen (params[i + 1].data.d_string) + 1;
		    break;
887
		  case SF_STRING:
Manish Singh's avatar
Manish Singh committed
888
		  case SF_FILENAME:
889
		    escaped = ESCAPE (params[i + 1].data.d_string);
Tor Lillqvist's avatar
Tor Lillqvist committed
890
891
		    length += strlen (escaped) + 3;
		    g_free (escaped);
Manish Singh's avatar
Manish Singh committed
892
		    break;
893
894
895
		  case SF_ADJUSTMENT:
		    length += strlen (params[i + 1].data.d_string) + 1;
		    break;
Sven Neumann's avatar
Sven Neumann committed
896
		  case SF_FONT:
897
		  case SF_PATTERN:
898
		  case SF_GRADIENT:
899
900
		  case SF_BRUSH:
		    length += strlen (params[i + 1].data.d_string) + 3;
901
902
903
		    break;		    
		  case SF_OPTION:
		    length += strlen (params[i + 1].data.d_string) + 1;
904
		    break;
Elliot Lee's avatar
Elliot Lee committed
905
906
907
908
		  default:
		    break;
		  }

909
	      c = command = g_new (gchar, length);
Elliot Lee's avatar
Elliot Lee committed
910

911
	      if (script->num_args)
Marc Lehmann's avatar
Marc Lehmann committed
912
913
914
915
916
917
918
919
920
921
922
                {
                  sprintf (command, "(%s ", script->script_name);
                  c += strlen (script->script_name) + 2;
                  for (i = 0; i < script->num_args; i++)
                    {
                      switch (script->arg_types[i])
                        {
                        case SF_IMAGE:
                        case SF_DRAWABLE:
                        case SF_LAYER:
                        case SF_CHANNEL:
923
924
                          g_snprintf (buffer, sizeof (buffer), "%d",
				      params[i + 1].data.d_image);
Marc Lehmann's avatar
Marc Lehmann committed
925
926
927
                          text = buffer;
                          break;
                        case SF_COLOR:
928
929
930
931
                          g_snprintf (buffer, sizeof (buffer), "'(%d %d %d)",
				      params[i + 1].data.d_color.red,
				      params[i + 1].data.d_color.green,
				      params[i + 1].data.d_color.blue);
Marc Lehmann's avatar
Marc Lehmann committed
932
933
934
                          text = buffer;
                          break;
                        case SF_TOGGLE:
935
936
                          g_snprintf (buffer, sizeof (buffer), "%s",
				      (params[i + 1].data.d_int32) ? "TRUE" : "FALSE");
Marc Lehmann's avatar
Marc Lehmann committed
937
938
939
940
941
942
943
944
                          text = buffer;
                          break;
                        case SF_VALUE:
                          text = params[i + 1].data.d_string;
                          break;
                        case SF_STRING:
                        case SF_FILENAME:
                          escaped = ESCAPE (params[i + 1].data.d_string);
945
946
                          g_snprintf (buffer, sizeof (buffer), "\"%s\"",
				      escaped);
Marc Lehmann's avatar
Marc Lehmann committed
947
948
949
950
951
952
953
954
955
956
                          g_free (escaped);
                          text = buffer;
                          break;
                        case SF_ADJUSTMENT:
                          text = params[i + 1].data.d_string;
                          break;
                        case SF_FONT:
                        case SF_PATTERN:
                        case SF_GRADIENT:
                        case SF_BRUSH:
957
958
                          g_snprintf (buffer, sizeof (buffer), "\"%s\"",
				      params[i + 1].data.d_string);
Marc Lehmann's avatar
Marc Lehmann committed
959
960
                          text = buffer;
                          break;
961
962
963
                        case SF_OPTION:
                          text = params[i + 1].data.d_string;
                          break;
Marc Lehmann's avatar
Marc Lehmann committed
964
965
966
967
968
969
970
971
972
973
974
                        default:
                          break;
                        }

                      if (i == script->num_args - 1)
                        sprintf (c, "%s)", text);
                      else
                        sprintf (c, "%s ", text);
                      c += strlen (text) + 1;
                    }
                }
975
976
	      else
		sprintf (command, "(%s)", script->script_name);
Elliot Lee's avatar
Elliot Lee committed
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996

	      /*  run the command through the interpreter  */
	      err_msg = (repl_c_string (command, 0, 0, 1) != 0) ? TRUE : FALSE;

	      g_free (command);
	    }
	  break;

	default:
	  break;
	}
    }

  *nreturn_vals = 1;
  *return_vals = values;

  values[0].type = PARAM_STATUS;
  values[0].data.d_status = status;
}

997
998
999
1000
1001
/* this is a GTraverseFunction */
static gint
script_fu_lookup_script (gpointer  *foo,
			 SFScript  *script,
			 gchar    **name)
Elliot Lee's avatar
Elliot Lee committed
1002
{
1003
1004
1005
1006
1007
  if (strcmp (script->pdb_name, *name) == 0)
    {  
      /* store the script in the name pointer and stop the traversal */
      *name = (gchar *)script;
      return TRUE;
Elliot Lee's avatar
Elliot Lee committed
1008
    }
1009
1010
1011
  else
    return FALSE;
}
Elliot Lee's avatar
Elliot Lee committed
1012

1013
1014
1015
1016
1017
1018
1019
1020
1021
1022
1023
1024
static SFScript *
script_fu_find_script (gchar *pdb_name)
{
  gchar *script;
  
  script = pdb_name;
  g_tree_traverse (script_list, 
		   (GTraverseFunc)script_fu_lookup_script, G_IN_ORDER, &script);
  if (script == pdb_name)
    return NULL;
  else
    return (SFScript *)script;
Elliot Lee's avatar
Elliot Lee committed
1025
1026
1027
1028
1029
}

static void
script_fu_free_script (SFScript *script)
{
1030
  gint i;
Elliot Lee's avatar
Elliot Lee committed
1031
1032
1033
1034
1035
1036
1037
1038
1039
1040
1041
1042
1043
1044
1045
1046
1047
1048
1049
1050
1051
1052
1053
1054
1055
1056
1057

  /*  Uninstall the temporary procedure for this script  */
  gimp_uninstall_temp_proc (script->script_name);

  if (script)
    {
      g_free (script->script_name);
      g_free (script->description);
      g_free (script->help);
      g_free (script->author);
      g_free (script->copyright);
      g_free (script->date);
      g_free (script->img_types);
      g_free (script->arg_types);

      for (i = 0; i < script->num_args; i++)
	{
	  g_free (script->arg_labels[i]);
	  switch (script->arg_types[i])
	    {
	    case SF_IMAGE:
	    case SF_DRAWABLE:
	    case SF_LAYER:
	    case SF_CHANNEL:
	    case SF_COLOR:
	      break;
	    case SF_VALUE:
Sven Neumann's avatar
Sven Neumann committed
1058
	    case SF_STRING:
Elliot Lee's avatar
Elliot Lee committed
1059
	      g_free (script->arg_defaults[i].sfa_value);
1060
	      g_free (script->arg_values[i].sfa_value);
1061
	      break;
1062
1063
	    case SF_ADJUSTMENT:
	      break;
Manish Singh's avatar
Manish Singh committed
1064
1065
1066
1067
	    case SF_FILENAME:
	      g_free (script->arg_defaults[i].sfa_file.filename);
	      g_free (script->arg_values[i].sfa_file.filename);
	      break;
Sven Neumann's avatar
Sven Neumann committed
1068
1069
1070
1071
	    case SF_FONT:
	      g_free (script->arg_defaults[i].sfa_font.fontname);
	      g_free (script->arg_values[i].sfa_font.fontname);
	      break;
1072
1073
1074
	    case SF_PATTERN:
	      g_free (script->arg_defaults[i].sfa_pattern);
	      g_free (script->arg_values[i].sfa_pattern);
1075
	      break;
1076
1077
1078
1079
	    case SF_GRADIENT:
	      g_free (script->arg_defaults[i].sfa_gradient);
	      g_free (script->arg_values[i].sfa_gradient);
	      break;
1080
1081
1082
1083
	    case SF_BRUSH:
	      g_free (script->arg_defaults[i].sfa_brush.name);
	      g_free (script->arg_values[i].sfa_brush.name);
	      break;
1084
1085
1086
1087
1088
1089
	    case SF_OPTION:
	      g_slist_foreach (script->arg_defaults[i].sfa_option.list, 
			       (GFunc)g_free, NULL);
	      if (script->arg_defaults[i].sfa_option.list)
		g_slist_free (script->arg_defaults[i].sfa_option.list);
	      break;
Elliot Lee's avatar
Elliot Lee committed
1090
1091
1092
1093
1094
1095
1096
1097
1098
1099
1100
1101
1102
1103
	    default:
	      break;
	    }
	}

      g_free (script->arg_labels);
      g_free (script->arg_defaults);
      g_free (script->arg_values);

      g_free (script);
    }
}

static void
1104
script_fu_enable_cc (void)
Elliot Lee's avatar
Elliot Lee committed
1105
1106
1107
1108
1109
1110
1111
1112
{
  current_command_enabled = TRUE;
}

static void
script_fu_disable_cc (gint err_msg)
{
  if (err_msg)
1113
    g_message (_("Script-Fu Error\n%s"), siod_err_msg);
Elliot Lee's avatar
Elliot Lee committed
1114
1115
1116
1117
1118
1119
1120
1121
1122
1123
1124
1125
1126
1127

  current_command_enabled = FALSE;

  if (last_command)
    g_free (last_command);
  last_command = NULL;
  command_count = 0;
  consec_command_count = 0;
}

static void
script_fu_interface (SFScript *script)
{
  GtkWidget *dlg;
1128
1129
1130
  GtkWidget *main_box;
  GtkWidget *frame;
  GtkWidget *sep;
Elliot Lee's avatar
Elliot Lee committed
1131
1132
1133
  GtkWidget *button;
  GtkWidget *menu;
  GtkWidget *table;
1134
1135
  GtkWidget *vbox;
  GtkWidget *hbox;
Sven Neumann's avatar
Sven Neumann committed
1136
  GtkWidget *bbox;
1137
1138
  GtkWidget *menu_item;
  GSList *list;
1139
1140
  gchar  *title;
  gchar  *buf;
1141
1142
  gint    start_args;
  gint    i;
1143
  guint   j;
Elliot Lee's avatar
Elliot Lee committed
1144

1145
  static gboolean gtk_initted = FALSE;
Elliot Lee's avatar
Elliot Lee committed
1146

1147
1148
  g_return_if_fail (script != NULL);

Elliot Lee's avatar
Elliot Lee committed
1149
1150
  if (!gtk_initted)
    {
1151
      INIT_I18N_UI();
1152

1153
1154
      gimp_ui_init ("script-fu", TRUE);

Elliot Lee's avatar
Elliot Lee committed
1155
1156
1157
1158
      gtk_initted = TRUE;
    }

  sf_interface.script = script;
1159
  sf_interface.about_dialog = NULL;
1160
  
Sven Neumann's avatar
Sven Neumann committed
1161
1162
  /* strip the first part of the menupath if it contains _("/Script-Fu/") */
  buf = strstr (gettext (script->description), _("/Script-Fu/"));
1163
  if (buf)
Sven Neumann's avatar
Sven Neumann committed
1164
    title = g_strdup_printf (_("Script-Fu: %s"), (buf + strlen (_("/Script-Fu/"))));
1165
  else 
Sven Neumann's avatar
Sven Neumann committed
1166
1167
1168
1169
1170
    title = g_strdup_printf (_("Script-Fu: %s"), gettext (script->description));

  buf = strstr (title, "...");
  if (buf)
    *buf = '\0';
1171
1172

  dlg = gtk_window_new (GTK_WINDOW_TOPLEVEL);
1173
  gtk_quit_add_destroy (1, GTK_OBJECT (dlg));
1174
  gtk_window_set_title (GTK_WINDOW (dlg), title);
1175
1176
  gtk_window_set_wmclass (GTK_WINDOW (dlg), "script_fu", "Gimp");
  gtk_signal_connect (GTK_OBJECT (dlg), "delete_event",
1177
		      GTK_SIGNAL_FUNC (gtk_main_quit),
1178
		      NULL);
Elliot Lee's avatar
Elliot Lee committed
1179
  gtk_signal_connect (GTK_OBJECT (dlg), "destroy",
1180
		      GTK_SIGNAL_FUNC (script_fu_destroy_callback),
Elliot Lee's avatar
Elliot Lee committed
1181
		      NULL);
1182

1183
  gimp_help_connect_help_accel (dlg, gimp_standard_help_func,
1184
				"filters/script-fu.html");
Sven Neumann's avatar
Sven Neumann committed
1185
1186
  
  /* the vbox holding all widgets */
1187
  main_box = gtk_vbox_new (FALSE, 0);
Sven Neumann's avatar
Sven Neumann committed
1188
1189
1190
  gtk_container_add (GTK_CONTAINER (dlg), main_box);
 
  /* the script arguments frame */
1191
  frame = gtk_frame_new (_("Script Arguments"));
1192
  gtk_container_set_border_width (GTK_CONTAINER (frame), 4);
Sven Neumann's avatar
Sven Neumann committed
1193
  gtk_box_pack_start (GTK_BOX (main_box), frame, TRUE, TRUE, 0);
Elliot Lee's avatar
Elliot Lee committed
1194

1195
  /* the vbox holding all widgets */
1196
  vbox = gtk_vbox_new (FALSE, 2);
Sven Neumann's avatar
Sven Neumann committed
1197
  gtk_container_add (GTK_CONTAINER (frame), vbox);
1198
  gtk_container_set_border_width (GTK_CONTAINER (vbox), 2);
Elliot Lee's avatar
Elliot Lee committed
1199
1200

  /*  The argument table  */
1201
  table = gtk_table_new (script->num_args + 1, 2, FALSE);
1202
1203
  gtk_table_set_col_spacings (GTK_TABLE (table), 4);
  gtk_table_set_row_spacings (GTK_TABLE (table), 2);
1204
  gtk_container_set_border_width (GTK_CONTAINER (table), 4);
1205
  gtk_box_pack_start (GTK_BOX (vbox), table, TRUE, TRUE, 0);
Elliot Lee's avatar
Elliot Lee committed
1206
1207
1208
1209
1210
1211
1212

  script->args_widgets = g_new (GtkWidget *, script->num_args);

  start_args = (script->image_based) ? 2 : 0;

  for (i = start_args; i < script->num_args; i++)
    {
1213
1214
1215
1216
      /*  we add a colon after the label; some languages want an extra space here */
      gchar     *label_text = g_strdup_printf (_("%s:"), gettext (script->arg_labels[i]));
      gfloat     label_yalign = 0.5;
      gboolean   widget_leftalign = TRUE;
Elliot Lee's avatar
Elliot Lee committed
1217
1218
1219
1220
1221
1222
1223
1224
1225
1226
1227
1228
1229

      switch (script->arg_types[i])
	{
	case SF_IMAGE:
	case SF_DRAWABLE:
	case SF_LAYER:
	case SF_CHANNEL:
	  script->args_widgets[i] = gtk_option_menu_new ();
	  switch (script->arg_types[i])
	    {
	    case SF_IMAGE:
	      menu = gimp_image_menu_new (NULL, script_fu_menu_callback,
					  &script->arg_values[i].sfa_image,
1230
					  script->arg_values[i].sfa_image);
Elliot Lee's avatar
Elliot Lee committed
1231
1232
1233
1234
	      break;
	    case SF_DRAWABLE:
	      menu = gimp_drawable_menu_new (NULL, script_fu_menu_callback,
					     &script->arg_values[i].sfa_drawable,
1235
					     script->arg_values[i].sfa_drawable);
Elliot Lee's avatar
Elliot Lee committed
1236
1237
1238
1239
	      break;
	    case SF_LAYER:
	      menu = gimp_layer_menu_new (NULL, script_fu_menu_callback,
					  &script->arg_values[i].sfa_layer,
1240
					  script->arg_values[i].sfa_layer);
Elliot Lee's avatar
Elliot Lee committed
1241
1242
1243
1244
	      break;
	    case SF_CHANNEL:
	      menu = gimp_channel_menu_new (NULL, script_fu_menu_callback,
					    &script->arg_values[i].sfa_channel,
1245
					    script->arg_values[i].sfa_channel);
Elliot Lee's avatar
Elliot Lee committed
1246
1247
1248
1249
1250
1251
1252
1253
1254
	      break;
	    default:
	      menu = NULL;
	      break;
	    }
	  gtk_option_menu_set_menu (GTK_OPTION_MENU (script->args_widgets[i]), menu);
	  break;

	case SF_COLOR:
1255
1256
1257
1258
	  script->args_widgets[i] =
	    gimp_color_button_new (_("Script-Fu Color Selection"),
				   COLOR_SAMPLE_WIDTH, COLOR_SAMPLE_HEIGHT,
				   script->arg_values[i].sfa_color, 3);
Elliot Lee's avatar
Elliot Lee committed
1259
1260
1261
	  break;

	case SF_TOGGLE:
1262
1263
	  g_free (label_text);
	  label_text = NULL;
1264
	  script->args_widgets[i] =
Sven Neumann's avatar
Sven Neumann committed
1265
	    gtk_check_button_new_with_label (gettext (script->arg_labels[i]));
1266
	  gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (script->args_widgets[i]),
Elliot Lee's avatar
Elliot Lee committed
1267
1268
				       script->arg_values[i].sfa_toggle);
	  gtk_signal_connect (GTK_OBJECT (script->args_widgets[i]), "toggled",
1269
			      GTK_SIGNAL_FUNC (gimp_toggle_button_update),
Elliot Lee's avatar
Elliot Lee committed
1270
1271
1272
1273
			      &script->arg_values[i].sfa_toggle);
	  break;

	case SF_VALUE:
1274
	case SF_STRING:
1275
1276
	  widget_leftalign = FALSE;

1277
1278
1279
	  script->args_widgets[i] = gtk_entry_new ();
	  gtk_widget_set_usize (script->args_widgets[i], TEXT_WIDTH, 0);
	  gtk_entry_set_text (GTK_ENTRY (script->args_widgets[i]),
1280
			      script->arg_values[i].sfa_value);
1281
	  break;
1282
1283

	case SF_ADJUSTMENT:
1284
1285
1286
1287
1288
1289
	  script->arg_values[i].sfa_adjustment.adj = (GtkAdjustment *)
	    gtk_adjustment_new (script->arg_values[i].sfa_adjustment.value, 
				script->arg_defaults[i].sfa_adjustment.lower, 
				script->arg_defaults[i].sfa_adjustment.upper, 
				script->arg_defaults[i].sfa_adjustment.step, 
				script->arg_defaults[i].sfa_adjustment.page, 0);
1290
1291
1292
	  switch (script->arg_defaults[i].sfa_adjustment.type)
	    {
	    case SF_SLIDER:
1293
	      label_yalign = 1.0;
1294
	      widget_leftalign = FALSE;
1295
1296
1297

	      script->args_widgets[i] =
		gtk_hscale_new (script->arg_values[i].sfa_adjustment.adj);
1298
	      gtk_widget_set_usize (GTK_WIDGET (script->args_widgets[i]), 
1299
				    SLIDER_WIDTH, -1);
1300
1301
1302
1303
1304
1305
	      gtk_scale_set_digits (GTK_SCALE (script->args_widgets[i]), 
				    script->arg_defaults[i].sfa_adjustment.digits);
	      gtk_scale_set_draw_value (GTK_SCALE (script->args_widgets[i]), TRUE);
	      gtk_range_set_update_policy (GTK_RANGE (script->args_widgets[i]), 
					   GTK_UPDATE_DELAYED);
	      break;