]> Pileus Git - ~andy/gtk/blob - gtk/gtkfilechooserdialog.c
Apply a patch by Carlos Garnacho to fix several problems with filechooser
[~andy/gtk] / gtk / gtkfilechooserdialog.c
1 /* -*- Mode: C; c-file-style: "gnu"; tab-width: 8 -*- */
2 /* GTK - The GIMP Toolkit
3  * gtkfilechooserdialog.c: File selector dialog
4  * Copyright (C) 2003, Red Hat, Inc.
5  *
6  * This library is free software; you can redistribute it and/or
7  * modify it under the terms of the GNU Lesser General Public
8  * License as published by the Free Software Foundation; either
9  * version 2 of the License, or (at your option) any later version.
10  *
11  * This library 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 GNU
14  * Lesser General Public License for more details.
15  *
16  * You should have received a copy of the GNU Lesser General Public
17  * License along with this library; if not, write to the
18  * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
19  * Boston, MA 02111-1307, USA.
20  */
21
22 #include <config.h>
23 #include "gtkfilechooserprivate.h"
24 #include "gtkfilechooserdialog.h"
25 #include "gtkfilechooserwidget.h"
26 #include "gtkfilechooserutils.h"
27 #include "gtkfilechooserembed.h"
28 #include "gtkfilesystem.h"
29 #include "gtktypebuiltins.h"
30 #include "gtkintl.h"
31 #include "gtkalias.h"
32
33 #include <stdarg.h>
34
35 #define GTK_FILE_CHOOSER_DIALOG_GET_PRIVATE(o)  (GTK_FILE_CHOOSER_DIALOG (o)->priv)
36
37 static void gtk_file_chooser_dialog_finalize   (GObject                   *object);
38
39 static GObject* gtk_file_chooser_dialog_constructor  (GType                  type,
40                                                       guint                  n_construct_properties,
41                                                       GObjectConstructParam *construct_params);
42 static void     gtk_file_chooser_dialog_set_property (GObject               *object,
43                                                       guint                  prop_id,
44                                                       const GValue          *value,
45                                                       GParamSpec            *pspec);
46 static void     gtk_file_chooser_dialog_get_property (GObject               *object,
47                                                       guint                  prop_id,
48                                                       GValue                *value,
49                                                       GParamSpec            *pspec);
50
51 static void     gtk_file_chooser_dialog_map          (GtkWidget             *widget);
52 static void     gtk_file_chooser_dialog_unmap        (GtkWidget             *widget);
53
54 static void response_cb (GtkDialog *dialog,
55                          gint       response_id);
56
57 G_DEFINE_TYPE_WITH_CODE (GtkFileChooserDialog, gtk_file_chooser_dialog, GTK_TYPE_DIALOG,
58                          G_IMPLEMENT_INTERFACE (GTK_TYPE_FILE_CHOOSER,
59                                                 _gtk_file_chooser_delegate_iface_init))
60
61 static void
62 gtk_file_chooser_dialog_class_init (GtkFileChooserDialogClass *class)
63 {
64   GObjectClass *gobject_class = G_OBJECT_CLASS (class);
65   GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (class);
66
67   gobject_class->constructor = gtk_file_chooser_dialog_constructor;
68   gobject_class->set_property = gtk_file_chooser_dialog_set_property;
69   gobject_class->get_property = gtk_file_chooser_dialog_get_property;
70   gobject_class->finalize = gtk_file_chooser_dialog_finalize;
71
72   widget_class->map       = gtk_file_chooser_dialog_map;
73   widget_class->unmap     = gtk_file_chooser_dialog_unmap;
74
75   _gtk_file_chooser_install_properties (gobject_class);
76
77   g_type_class_add_private (class, sizeof (GtkFileChooserDialogPrivate));
78 }
79
80 static void
81 gtk_file_chooser_dialog_init (GtkFileChooserDialog *dialog)
82 {
83   GtkFileChooserDialogPrivate *priv = G_TYPE_INSTANCE_GET_PRIVATE (dialog,
84                                                                    GTK_TYPE_FILE_CHOOSER_DIALOG,
85                                                                    GtkFileChooserDialogPrivate);
86   GtkDialog *fc_dialog = GTK_DIALOG (dialog);
87
88   dialog->priv = priv;
89   dialog->priv->default_width = -1;
90   dialog->priv->default_height = -1;
91   dialog->priv->resize_horizontally = TRUE;
92   dialog->priv->resize_vertically = TRUE;
93   dialog->priv->response_requested = FALSE;
94
95   gtk_dialog_set_has_separator (fc_dialog, FALSE);
96   gtk_container_set_border_width (GTK_CONTAINER (fc_dialog), 5);
97   gtk_box_set_spacing (GTK_BOX (fc_dialog->vbox), 2); /* 2 * 5 + 2 = 12 */
98   gtk_container_set_border_width (GTK_CONTAINER (fc_dialog->action_area), 5);
99
100   /* We do a signal connection here rather than overriding the method in
101    * class_init because GtkDialog::response is a RUN_LAST signal.  We want *our*
102    * handler to be run *first*, regardless of whether the user installs response
103    * handlers of his own.
104    */
105   g_signal_connect (dialog, "response",
106                     G_CALLBACK (response_cb), NULL);
107 }
108
109 static void
110 gtk_file_chooser_dialog_finalize (GObject *object)
111 {
112   GtkFileChooserDialog *dialog = GTK_FILE_CHOOSER_DIALOG (object);
113
114   g_free (dialog->priv->file_system);
115
116   G_OBJECT_CLASS (gtk_file_chooser_dialog_parent_class)->finalize (object);  
117 }
118
119 /* Callback used when the user activates a file in the file chooser widget */
120 static void
121 file_chooser_widget_file_activated (GtkFileChooser       *chooser,
122                                     GtkFileChooserDialog *dialog)
123 {
124   GList *children, *l;
125
126   if (gtk_window_activate_default (GTK_WINDOW (dialog)))
127     return;
128
129   /* There probably isn't a default widget, so make things easier for the
130    * programmer by looking for a reasonable button on our own.
131    */
132
133   children = gtk_container_get_children (GTK_CONTAINER (GTK_DIALOG (dialog)->action_area));
134
135   for (l = children; l; l = l->next)
136     {
137       GtkWidget *widget;
138       int response_id;
139
140       widget = GTK_WIDGET (l->data);
141       response_id = gtk_dialog_get_response_for_widget (GTK_DIALOG (dialog), widget);
142       if (response_id == GTK_RESPONSE_ACCEPT
143           || response_id == GTK_RESPONSE_OK
144           || response_id == GTK_RESPONSE_YES
145           || response_id == GTK_RESPONSE_APPLY)
146         {
147           gtk_widget_activate (widget); /* Should we gtk_dialog_response (dialog, response_id) instead? */
148           break;
149         }
150     }
151
152   g_list_free (children);
153 }
154
155 static void
156 file_chooser_widget_update_hints (GtkFileChooserDialog *dialog,
157                                   gint                  width)
158 {
159   GtkFileChooserDialogPrivate *priv;
160   GdkGeometry geometry;
161
162   priv = GTK_FILE_CHOOSER_DIALOG_GET_PRIVATE (dialog);
163
164   geometry.min_width = (!priv->resize_horizontally ? width : -1);
165   geometry.min_height = -1;
166   geometry.max_width = (priv->resize_horizontally?G_MAXSHORT:-1);
167   geometry.max_height = (priv->resize_vertically?G_MAXSHORT:-1);
168
169   gtk_window_set_geometry_hints (GTK_WINDOW (dialog), NULL,
170                                  &geometry,
171                                  GDK_HINT_MIN_SIZE | GDK_HINT_MAX_SIZE);
172 }
173
174 static void
175 clamp_to_screen (GtkWidget *widget,
176                  gint      *width,
177                  gint      *height)
178 {
179   GdkScreen *screen;
180   int monitor_num;
181   GdkRectangle monitor;
182
183   g_return_if_fail (GTK_WIDGET_REALIZED (widget));
184   
185   screen = gtk_widget_get_screen (widget);
186   monitor_num = gdk_screen_get_monitor_at_window (screen, widget->window);
187
188   gdk_screen_get_monitor_geometry (screen, monitor_num, &monitor);
189
190   if (width)
191     *width = MIN (*width, (monitor.width * 3) / 4);
192
193   if (height)
194     *height = MIN (*height, (monitor.height * 3) / 4);
195 }
196
197 static void
198 file_chooser_widget_default_realized_size_changed (GtkWidget            *widget,
199                                                    GtkFileChooserDialog *dialog)
200 {
201   GtkFileChooserDialogPrivate *priv;
202   gint width;
203   gint height;
204   gint default_width, default_height;
205   GtkRequisition req;
206   gboolean resize_horizontally;
207   gboolean resize_vertically;
208   gboolean update_hints;
209   gint dx = 0, dy = 0;
210   gint cur_width, cur_height;
211
212   priv = GTK_FILE_CHOOSER_DIALOG_GET_PRIVATE (dialog);
213
214   /* Force a size request of everything before we start.  This will make sure
215    * that widget->requisition is meaningful. */
216   gtk_widget_size_request (GTK_WIDGET (dialog), &req);
217   gtk_window_get_size (GTK_WINDOW (dialog), &cur_width, &cur_height);
218   width = GTK_WIDGET (dialog)->requisition.width - priv->widget->requisition.width;
219   height = GTK_WIDGET (dialog)->requisition.height - priv->widget->requisition.height;
220   _gtk_file_chooser_embed_get_default_size (GTK_FILE_CHOOSER_EMBED (priv->widget),
221                                             &default_width, &default_height);
222
223   /* Ideal target size modulo any resizing */
224   width = default_width + width;
225   height = default_height + height;
226
227   /* Now, we test for resizability */
228   update_hints = FALSE;
229   _gtk_file_chooser_embed_get_resizable_hints (GTK_FILE_CHOOSER_EMBED (priv->widget),
230                                                &resize_horizontally,
231                                                &resize_vertically);
232   resize_vertically = (!! resize_vertically);     /* normalize */
233   resize_horizontally = (!! resize_horizontally);
234
235   if (resize_horizontally && priv->resize_horizontally)
236     {
237       dx = default_width - priv->default_width;
238       priv->default_width = default_width;
239     }
240   else if (resize_horizontally && ! priv->resize_horizontally)
241     {
242       /* We restore to the ideal size + any change in default_size (which is not
243        * expected).  It would be nicer to store the older size to restore to in
244        * the future. */
245       dx = default_width - priv->default_width;
246       dx += width - cur_width;
247       priv->default_width = default_width;
248       update_hints = TRUE;
249     }
250   else
251     {
252       update_hints = TRUE;
253     }
254
255   if (resize_vertically && priv->resize_vertically)
256     {
257       dy = default_height - priv->default_height;
258       priv->default_height = default_height;
259     }
260   else if (resize_vertically && ! priv->resize_vertically)
261     {
262       dy = default_height - priv->default_height;
263       dy += height - cur_height;
264       priv->default_height = default_height;
265       update_hints = TRUE;
266     }
267   else
268     {
269       update_hints = TRUE;
270     }
271
272   priv->resize_horizontally = resize_horizontally;
273   priv->resize_vertically = resize_vertically;
274
275   if (dx != 0 || dy != 0)
276     {
277       gint new_width = cur_width + dx;
278       gint new_height = cur_height + dy;
279
280       clamp_to_screen (GTK_WIDGET (dialog), &new_width, &new_height);
281       
282       gtk_window_resize (GTK_WINDOW (dialog), new_width, new_height);
283     }
284
285   /* Only store the size if we can resize in that direction. */
286   if (update_hints)
287     file_chooser_widget_update_hints (dialog, width);
288 }
289
290 static void
291 file_chooser_widget_default_unrealized_size_changed (GtkWidget            *widget,
292                                                      GtkFileChooserDialog *dialog)
293 {
294   GtkFileChooserDialogPrivate *priv;
295   GtkRequisition req;
296   gint width, height;
297
298   priv = GTK_FILE_CHOOSER_DIALOG_GET_PRIVATE (dialog);
299   gtk_widget_size_request (GTK_WIDGET (dialog), &req);
300
301   _gtk_file_chooser_embed_get_resizable_hints (GTK_FILE_CHOOSER_EMBED (priv->widget),
302                                                &(priv->resize_horizontally),
303                                                &(priv->resize_vertically));
304   _gtk_file_chooser_embed_get_default_size (GTK_FILE_CHOOSER_EMBED (priv->widget),
305                                             &(priv->default_width), &(priv->default_height));
306   
307   /* Determine how much space the rest of the dialog uses compared to priv->widget */
308   width = priv->default_width + GTK_WIDGET (dialog)->requisition.width - priv->widget->requisition.width;
309   height = priv->default_height + GTK_WIDGET (dialog)->requisition.height - priv->widget->requisition.height;
310
311   gtk_window_set_default_size (GTK_WINDOW (dialog), width, height);
312   file_chooser_widget_update_hints (dialog, width);
313 }
314
315 static void
316 file_chooser_widget_default_size_changed (GtkWidget            *widget,
317                                           GtkFileChooserDialog *dialog)
318 {
319   if (GTK_WIDGET_REALIZED (dialog))
320     file_chooser_widget_default_realized_size_changed (widget, dialog);
321   else
322     file_chooser_widget_default_unrealized_size_changed (widget, dialog);
323 }
324
325 static void
326 file_chooser_widget_response_requested (GtkWidget            *widget,
327                                         GtkFileChooserDialog *dialog)
328 {
329   GList *children, *l;
330
331   /* There probably isn't a default widget, so make things easier for the
332    * programmer by looking for a reasonable button on our own.
333    */
334
335   children = gtk_container_get_children (GTK_CONTAINER (GTK_DIALOG (dialog)->action_area));
336
337   for (l = children; l; l = l->next)
338     {
339       GtkWidget *widget;
340       int response_id;
341
342       widget = GTK_WIDGET (l->data);
343       response_id = gtk_dialog_get_response_for_widget (GTK_DIALOG (dialog), widget);
344       if (response_id == GTK_RESPONSE_ACCEPT
345           || response_id == GTK_RESPONSE_OK
346           || response_id == GTK_RESPONSE_YES
347           || response_id == GTK_RESPONSE_APPLY)
348         {
349           dialog->priv->response_requested = TRUE;
350           gtk_widget_activate (widget); /* Should we gtk_dialog_response (dialog, response_id) instead? */
351           break;
352         }
353     }
354
355   g_list_free (children);
356 }
357   
358 static GObject*
359 gtk_file_chooser_dialog_constructor (GType                  type,
360                                      guint                  n_construct_properties,
361                                      GObjectConstructParam *construct_params)
362 {
363   GtkFileChooserDialogPrivate *priv;
364   GObject *object;
365
366   object = G_OBJECT_CLASS (gtk_file_chooser_dialog_parent_class)->constructor (type,
367                                                                                n_construct_properties,
368                                                                                construct_params);
369   priv = GTK_FILE_CHOOSER_DIALOG_GET_PRIVATE (object);
370
371   gtk_widget_push_composite_child ();
372
373   if (priv->file_system)
374     priv->widget = g_object_new (GTK_TYPE_FILE_CHOOSER_WIDGET,
375                                  "file-system-backend", priv->file_system,
376                                  NULL);
377   else
378     priv->widget = g_object_new (GTK_TYPE_FILE_CHOOSER_WIDGET, NULL);
379
380   g_signal_connect (priv->widget, "file-activated",
381                     G_CALLBACK (file_chooser_widget_file_activated), object);
382   g_signal_connect (priv->widget, "default-size-changed",
383                     G_CALLBACK (file_chooser_widget_default_size_changed), object);
384   g_signal_connect (priv->widget, "response-requested",
385                     G_CALLBACK (file_chooser_widget_response_requested), object);
386
387   gtk_container_set_border_width (GTK_CONTAINER (priv->widget), 5);
388   gtk_box_pack_start (GTK_BOX (GTK_DIALOG (object)->vbox), priv->widget, TRUE, TRUE, 0);
389
390   gtk_widget_show (priv->widget);
391
392   _gtk_file_chooser_set_delegate (GTK_FILE_CHOOSER (object),
393                                   GTK_FILE_CHOOSER (priv->widget));
394
395   gtk_widget_pop_composite_child ();
396
397   return object;
398 }
399
400 static void
401 gtk_file_chooser_dialog_set_property (GObject         *object,
402                                       guint            prop_id,
403                                       const GValue    *value,
404                                       GParamSpec      *pspec)
405
406 {
407   GtkFileChooserDialogPrivate *priv = GTK_FILE_CHOOSER_DIALOG_GET_PRIVATE (object);
408
409   switch (prop_id)
410     {
411     case GTK_FILE_CHOOSER_PROP_FILE_SYSTEM_BACKEND:
412       g_free (priv->file_system);
413       priv->file_system = g_value_dup_string (value);
414       break;
415     default:
416       g_object_set_property (G_OBJECT (priv->widget), pspec->name, value);
417       break;
418     }
419 }
420
421 static void
422 gtk_file_chooser_dialog_get_property (GObject         *object,
423                                       guint            prop_id,
424                                       GValue          *value,
425                                       GParamSpec      *pspec)
426 {
427   GtkFileChooserDialogPrivate *priv = GTK_FILE_CHOOSER_DIALOG_GET_PRIVATE (object);
428
429   g_object_get_property (G_OBJECT (priv->widget), pspec->name, value);
430 }
431
432 #if 0
433 static void
434 set_default_size (GtkFileChooserDialog *dialog)
435 {
436   GtkWidget *widget;
437   GtkWindow *window;
438   int default_width, default_height;
439   int width, height;
440   int font_size;
441   GdkScreen *screen;
442   int monitor_num;
443   GtkRequisition req;
444   GdkRectangle monitor;
445
446   widget = GTK_WIDGET (dialog);
447   window = GTK_WINDOW (dialog);
448
449   /* Size based on characters */
450
451   font_size = pango_font_description_get_size (widget->style->font_desc);
452   font_size = PANGO_PIXELS (font_size);
453
454   width = font_size * NUM_CHARS;
455   height = font_size * NUM_LINES;
456
457   /* Use at least the requisition size... */
458
459   gtk_widget_size_request (widget, &req);
460   width = MAX (width, req.width);
461   height = MAX (height, req.height);
462
463   /* ... but no larger than the monitor */
464
465   screen = gtk_widget_get_screen (widget);
466   monitor_num = gdk_screen_get_monitor_at_window (screen, widget->window);
467
468   gdk_screen_get_monitor_geometry (screen, monitor_num, &monitor);
469
470   width = MIN (width, monitor.width * 3 / 4);
471   height = MIN (height, monitor.height * 3 / 4);
472
473   /* Set size */
474
475   gtk_window_get_default_size (window, &default_width, &default_height);
476
477   gtk_window_set_default_size (window,
478                                (default_width == -1) ? width : default_width,
479                                (default_height == -1) ? height : default_height);
480 }
481 #endif
482
483 /* GtkWidget::map handler */
484 static void
485 gtk_file_chooser_dialog_map (GtkWidget *widget)
486 {
487   GtkFileChooserDialog *dialog = GTK_FILE_CHOOSER_DIALOG (widget);
488   GtkFileChooserDialogPrivate *priv = GTK_FILE_CHOOSER_DIALOG_GET_PRIVATE (dialog);
489
490   if (!GTK_WIDGET_MAPPED (priv->widget))
491     gtk_widget_map (priv->widget);
492
493   _gtk_file_chooser_embed_initial_focus (GTK_FILE_CHOOSER_EMBED (priv->widget));
494
495   GTK_WIDGET_CLASS (gtk_file_chooser_dialog_parent_class)->map (widget);
496 }
497
498 /* GtkWidget::unmap handler */
499 static void
500 gtk_file_chooser_dialog_unmap (GtkWidget *widget)
501 {
502   GtkFileChooserDialog *dialog = GTK_FILE_CHOOSER_DIALOG (widget);
503   GtkFileChooserDialogPrivate *priv = GTK_FILE_CHOOSER_DIALOG_GET_PRIVATE (dialog);
504
505   GTK_WIDGET_CLASS (gtk_file_chooser_dialog_parent_class)->unmap (widget);
506
507   /* See bug #145470.  We unmap the GtkFileChooserWidget so that if the dialog
508    * is remapped, the widget will be remapped as well.  Implementations should
509    * refresh their contents when this happens, as some applications keep a
510    * single file chooser alive and map/unmap it as needed, rather than creating
511    * a new file chooser every time they need one.
512    */
513   gtk_widget_unmap (priv->widget);
514 }
515
516 /* GtkDialog::response handler */
517 static void
518 response_cb (GtkDialog *dialog,
519              gint       response_id)
520 {
521   GtkFileChooserDialogPrivate *priv;
522
523   priv = GTK_FILE_CHOOSER_DIALOG_GET_PRIVATE (dialog);
524
525   /* Act only on response IDs we recognize */
526   if (!(response_id == GTK_RESPONSE_ACCEPT
527         || response_id == GTK_RESPONSE_OK
528         || response_id == GTK_RESPONSE_YES
529         || response_id == GTK_RESPONSE_APPLY))
530     return;
531
532   if (!priv->response_requested && !_gtk_file_chooser_embed_should_respond (GTK_FILE_CHOOSER_EMBED (priv->widget)))
533     {
534       g_signal_stop_emission_by_name (dialog, "response");
535       priv->response_requested = FALSE;
536     }
537 }
538
539 static GtkWidget *
540 gtk_file_chooser_dialog_new_valist (const gchar          *title,
541                                     GtkWindow            *parent,
542                                     GtkFileChooserAction  action,
543                                     const gchar          *backend,
544                                     const gchar          *first_button_text,
545                                     va_list               varargs)
546 {
547   GtkWidget *result;
548   const char *button_text = first_button_text;
549   gint response_id;
550
551   result = g_object_new (GTK_TYPE_FILE_CHOOSER_DIALOG,
552                          "title", title,
553                          "action", action,
554                          "file-system-backend", backend,
555                          NULL);
556
557   if (parent)
558     gtk_window_set_transient_for (GTK_WINDOW (result), parent);
559
560   while (button_text)
561     {
562       response_id = va_arg (varargs, gint);
563       gtk_dialog_add_button (GTK_DIALOG (result), button_text, response_id);
564       button_text = va_arg (varargs, const gchar *);
565     }
566
567   return result;
568 }
569
570 /**
571  * gtk_file_chooser_dialog_new:
572  * @title: Title of the dialog, or %NULL
573  * @parent: Transient parent of the dialog, or %NULL
574  * @action: Open or save mode for the dialog
575  * @first_button_text: stock ID or text to go in the first button, or %NULL
576  * @Varargs: response ID for the first button, then additional (button, id) pairs, ending with %NULL
577  *
578  * Creates a new #GtkFileChooserDialog.  This function is analogous to
579  * gtk_dialog_new_with_buttons().
580  *
581  * Return value: a new #GtkFileChooserDialog
582  *
583  * Since: 2.4
584  **/
585 GtkWidget *
586 gtk_file_chooser_dialog_new (const gchar         *title,
587                              GtkWindow           *parent,
588                              GtkFileChooserAction action,
589                              const gchar         *first_button_text,
590                              ...)
591 {
592   GtkWidget *result;
593   va_list varargs;
594   
595   va_start (varargs, first_button_text);
596   result = gtk_file_chooser_dialog_new_valist (title, parent, action,
597                                                NULL, first_button_text,
598                                                varargs);
599   va_end (varargs);
600
601   return result;
602 }
603
604 /**
605  * gtk_file_chooser_dialog_new_with_backend:
606  * @title: Title of the dialog, or %NULL
607  * @parent: Transient parent of the dialog, or %NULL
608  * @action: Open or save mode for the dialog
609  * @backend: The name of the specific filesystem backend to use.
610  * @first_button_text: stock ID or text to go in the first button, or %NULL
611  * @Varargs: response ID for the first button, then additional (button, id) pairs, ending with %NULL
612  *
613  * Creates a new #GtkFileChooserDialog with a specified backend. This is
614  * especially useful if you use gtk_file_chooser_set_local_only() to allow
615  * non-local files and you use a more expressive vfs, such as gnome-vfs,
616  * to load files.
617  *
618  * Return value: a new #GtkFileChooserDialog
619  *
620  * Since: 2.4
621  **/
622 GtkWidget *
623 gtk_file_chooser_dialog_new_with_backend (const gchar          *title,
624                                           GtkWindow            *parent,
625                                           GtkFileChooserAction  action,
626                                           const gchar          *backend,
627                                           const gchar          *first_button_text,
628                                           ...)
629 {
630   GtkWidget *result;
631   va_list varargs;
632   
633   va_start (varargs, first_button_text);
634   result = gtk_file_chooser_dialog_new_valist (title, parent, action,
635                                                backend, first_button_text,
636                                                varargs);
637   va_end (varargs);
638
639   return result;
640 }
641
642 #define __GTK_FILE_CHOOSER_DIALOG_C__
643 #include "gtkaliasdef.c"