Bug Summary

File:tests/testfilechooser.c
Warning:line 202, column 12
File position of the stream might be 'indeterminate' after a failed operation. Can cause undefined behavior

Annotated Source Code

Press '?' to see keyboard shortcuts

clang -cc1 -cc1 -triple x86_64-pc-linux-gnu -analyze -disable-free -clear-ast-before-backend -disable-llvm-verifier -discard-value-names -main-file-name testfilechooser.c -analyzer-checker=core -analyzer-checker=apiModeling -analyzer-checker=unix -analyzer-checker=deadcode -analyzer-checker=security.insecureAPI.UncheckedReturn -analyzer-checker=security.insecureAPI.getpw -analyzer-checker=security.insecureAPI.gets -analyzer-checker=security.insecureAPI.mktemp -analyzer-checker=security.insecureAPI.mkstemp -analyzer-checker=security.insecureAPI.vfork -analyzer-checker=nullability.NullPassedToNonnull -analyzer-checker=nullability.NullReturnedFromNonnull -analyzer-output plist -w -setup-static-analyzer -mrelocation-model pic -pic-level 2 -pic-is-pie -mframe-pointer=all -fmath-errno -ffp-contract=on -fno-rounding-math -mconstructor-aliases -funwind-tables=2 -target-cpu x86-64 -tune-cpu generic -debugger-tuning=gdb -fdebug-compilation-dir=/rootdir/tests -fcoverage-compilation-dir=/rootdir/tests -resource-dir /usr/lib/llvm-19/lib/clang/19 -D HAVE_CONFIG_H -I . -I .. -I .. -I ../cdk -I ../cdk -D G_ENABLE_DEBUG -D G_ENABLE_CONSISTENCY_CHECKS -D GLIB_MIN_REQUIRED_VERSION=GLIB_VERSION_2_66 -D GLIB_MAX_ALLOWED_VERSION=GLIB_VERSION_2_66 -I /usr/include/pango-1.0 -I /usr/include/glib-2.0 -I /usr/lib/x86_64-linux-gnu/glib-2.0/include -I /usr/include/sysprof-6 -I /usr/include/harfbuzz -I /usr/include/freetype2 -I /usr/include/libpng16 -I /usr/include/libmount -I /usr/include/blkid -I /usr/include/fribidi -I /usr/include/cairo -I /usr/include/pixman-1 -I /usr/include/atk-1.0 -I /usr/include/gdk-pixbuf-2.0 -I /usr/include/x86_64-linux-gnu -I /usr/include/webp -I /usr/include/at-spi2-atk/2.0 -I /usr/include/at-spi-2.0 -I /usr/include/dbus-1.0 -I /usr/lib/x86_64-linux-gnu/dbus-1.0/include -I /usr/include/gio-unix-2.0 -I /usr/include/harfbuzz -I /usr/include/freetype2 -I /usr/include/libpng16 -I /usr/include/glib-2.0 -I /usr/lib/x86_64-linux-gnu/glib-2.0/include -I /usr/include/sysprof-6 -I /usr/include/pango-1.0 -I /usr/include/libmount -I /usr/include/blkid -I /usr/include/fribidi -I /usr/include/cairo -I /usr/include/pixman-1 -I /usr/include/pango-1.0 -I /usr/include/glib-2.0 -I /usr/lib/x86_64-linux-gnu/glib-2.0/include -I /usr/include/sysprof-6 -I /usr/include/harfbuzz -I /usr/include/freetype2 -I /usr/include/libpng16 -I /usr/include/libmount -I /usr/include/blkid -I /usr/include/fribidi -I /usr/include/cairo -I /usr/include/pixman-1 -I /usr/include/gdk-pixbuf-2.0 -I /usr/include/x86_64-linux-gnu -I /usr/include/webp -I /usr/include/gio-unix-2.0 -internal-isystem /usr/lib/llvm-19/lib/clang/19/include -internal-isystem /usr/local/include -internal-isystem /usr/lib/gcc/x86_64-linux-gnu/14/../../../../x86_64-linux-gnu/include -internal-externc-isystem /usr/include/x86_64-linux-gnu -internal-externc-isystem /include -internal-externc-isystem /usr/include -ferror-limit 19 -fgnuc-version=4.2.1 -fskip-odr-check-in-gmf -analyzer-checker deadcode.DeadStores -analyzer-checker alpha.deadcode.UnreachableCode -analyzer-checker alpha.core.CastSize -analyzer-checker alpha.core.CastToStruct -analyzer-checker alpha.core.IdenticalExpr -analyzer-checker alpha.security.ArrayBoundV2 -analyzer-checker alpha.security.MallocOverflow -analyzer-checker alpha.security.ReturnPtrRange -analyzer-checker alpha.unix.SimpleStream -analyzer-checker alpha.unix.cstring.BufferOverlap -analyzer-checker alpha.unix.cstring.NotNullTerminated -analyzer-checker alpha.unix.cstring.OutOfBounds -analyzer-checker alpha.core.FixedAddr -analyzer-output=html -faddrsig -D__GCC_HAVE_DWARF2_CFI_ASM=1 -o /rootdir/html-report/2024-12-18-092428-43636-1 -x c testfilechooser.c
1/* testfilechooser.c
2 * Copyright (C) 2003 Red Hat, Inc.
3 * Author: Owen Taylor
4 *
5 * This library is free software; you can redistribute it and/or
6 * modify it under the terms of the GNU Library General Public
7 * License as published by the Free Software Foundation; either
8 * version 2 of the License, or (at your option) any later version.
9 *
10 * This library is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 * Library General Public License for more details.
14 *
15 * You should have received a copy of the GNU Library General Public
16 * License along with this library. If not, see <http://www.gnu.org/licenses/>.
17 */
18#include "config.h"
19
20#include <string.h>
21#include <sys/types.h>
22#include <sys/stat.h>
23#include <stdlib.h>
24#include <time.h>
25#ifdef HAVE_UNISTD_H1
26#include <unistd.h>
27#endif
28#include <ctk/ctk.h>
29
30#ifdef G_OS_WIN32
31# include <io.h>
32# define localtime_r(t,b) *(b) = *localtime (t)
33# ifndef S_ISREG
34# define S_ISREG(m)((((m)) & 0170000) == (0100000)) ((m) & _S_IFREG)
35# endif
36#endif
37
38#if 0
39static CtkWidget *preview_label;
40static CtkWidget *preview_image;
41#endif
42static CtkFileChooserAction action;
43
44static void
45print_current_folder (CtkFileChooser *chooser)
46{
47 gchar *uri;
48
49 uri = ctk_file_chooser_get_current_folder_uri (chooser);
50 g_print ("Current folder changed :\n %s\n", uri ? uri : "(null)");
51 g_free (uri);
52}
53
54static void
55print_selected (CtkFileChooser *chooser)
56{
57 GSList *uris = ctk_file_chooser_get_uris (chooser);
58 GSList *tmp_list;
59
60 g_print ("Selection changed :\n");
61 for (tmp_list = uris; tmp_list; tmp_list = tmp_list->next)
62 {
63 gchar *uri = tmp_list->data;
64 g_print (" %s\n", uri);
65 g_free (uri);
66 }
67 g_print ("\n");
68 g_slist_free (uris);
69}
70
71static void
72response_cb (CtkDialog *dialog,
73 gint response_id)
74{
75 if (response_id == CTK_RESPONSE_OK)
76 {
77 GSList *list;
78
79 list = ctk_file_chooser_get_uris (CTK_FILE_CHOOSER (dialog)((((CtkFileChooser*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((dialog)), ((ctk_file_chooser_get_type ()))))))
);
80
81 if (list)
82 {
83 GSList *l;
84
85 g_print ("Selected files:\n");
86
87 for (l = list; l; l = l->next)
88 {
89 g_print ("%s\n", (char *) l->data);
90 g_free (l->data);
91 }
92
93 g_slist_free (list);
94 }
95 else
96 g_print ("No selected files\n");
97 }
98 else
99 g_print ("Dialog was closed\n");
100
101 ctk_main_quit ();
102}
103
104static gboolean
105no_backup_files_filter (const CtkFileFilterInfo *filter_info,
106 gpointer data G_GNUC_UNUSED__attribute__ ((__unused__)))
107{
108 gsize len = filter_info->display_name ? strlen (filter_info->display_name) : 0;
109 if (len > 0 && filter_info->display_name[len - 1] == '~')
110 return 0;
111 else
112 return 1;
113}
114
115static void
116filter_changed (CtkFileChooserDialog *dialog G_GNUC_UNUSED__attribute__ ((__unused__)),
117 gpointer data G_GNUC_UNUSED__attribute__ ((__unused__)))
118{
119 g_print ("file filter changed\n");
120}
121
122#include <stdio.h>
123#include <errno(*__errno_location ()).h>
124#define _(s)(s) (s)
125
126static void
127size_prepared_cb (GdkPixbufLoader *loader,
128 int width,
129 int height,
130 int *data)
131{
132 int des_width = data[0];
133 int des_height = data[1];
134
135 if (des_height >= height && des_width >= width) {
136 /* Nothing */
137 } else if ((double)height * des_width > (double)width * des_height) {
138 width = 0.5 + (double)width * des_height / (double)height;
139 height = des_height;
140 } else {
141 height = 0.5 + (double)height * des_width / (double)width;
142 width = des_width;
143 }
144
145 gdk_pixbuf_loader_set_size (loader, width, height);
146}
147
148GdkPixbuf *
149my_new_from_file_at_size (const char *filename,
150 int width,
151 int height,
152 GError **error)
153{
154 GdkPixbufLoader *loader;
155 GdkPixbuf *pixbuf;
156 int info[2];
157 struct stat st;
158
159 guchar buffer [4096];
160 int length;
161 FILE *f;
162
163 g_return_val_if_fail (filename != NULL, NULL)do { if ((filename != ((void*)0))) { } else { g_return_if_fail_warning
(((gchar*) 0), ((const char*) (__func__)), "filename != NULL"
); return (((void*)0)); } } while (0)
;
1
Assuming 'filename' is not equal to null
2
Taking true branch
164 g_return_val_if_fail (width > 0 && height > 0, NULL)do { if ((width > 0 && height > 0)) { } else { g_return_if_fail_warning
(((gchar*) 0), ((const char*) (__func__)), "width > 0 && height > 0"
); return (((void*)0)); } } while (0)
;
3
Loop condition is false. Exiting loop
4
Assuming 'width' is > 0
5
Assuming 'height' is > 0
6
Taking true branch
7
Loop condition is false. Exiting loop
165
166 if (stat (filename, &st) != 0) {
8
Taking false branch
167 int errsv = errno(*__errno_location ());
168
169 g_set_error (error,
170 G_FILE_ERRORg_file_error_quark (),
171 g_file_error_from_errno (errsv),
172 _("Could not get information for file '%s': %s")("Could not get information for file '%s': %s"),
173 filename, g_strerror (errsv));
174 return NULL((void*)0);
175 }
176
177 if (!S_ISREG (st.st_mode)((((st.st_mode)) & 0170000) == (0100000)))
9
Assuming the condition is true
10
Taking false branch
178 return NULL((void*)0);
179
180 f = fopen (filename, "rb");
181 if (!f
10.1
'f' is non-null
) {
11
Taking false branch
182 int errsv = errno(*__errno_location ());
183
184 g_set_error (error,
185 G_FILE_ERRORg_file_error_quark (),
186 g_file_error_from_errno (errsv),
187 _("Failed to open file '%s': %s")("Failed to open file '%s': %s"),
188 filename, g_strerror (errsv));
189 return NULL((void*)0);
190 }
191
192 loader = gdk_pixbuf_loader_new ();
193#ifdef DONT_PRESERVE_ASPECT
194 gdk_pixbuf_loader_set_size (loader, width, height);
195#else
196 info[0] = width;
197 info[1] = height;
198 g_signal_connect (loader, "size-prepared", G_CALLBACK (size_prepared_cb), info)g_signal_connect_data ((loader), ("size-prepared"), (((GCallback
) (size_prepared_cb))), (info), ((void*)0), (GConnectFlags) 0
)
;
199#endif
200
201 while (!feof (f)) {
12
Loop condition is true. Entering loop body
16
Loop condition is true. Entering loop body
202 length = fread (buffer, 1, sizeof (buffer), f);
13
Assuming this stream operation fails
17
File position of the stream might be 'indeterminate' after a failed operation. Can cause undefined behavior
203 if (length > 0)
14
Assuming 'length' is <= 0
15
Taking false branch
204 if (!gdk_pixbuf_loader_write (loader, buffer, length, error)) {
205 gdk_pixbuf_loader_close (loader, NULL((void*)0));
206 fclose (f);
207 g_object_unref (loader);
208 return NULL((void*)0);
209 }
210 }
211
212 fclose (f);
213
214 g_assert (*error == NULL)do { if (*error == ((void*)0)) ; else g_assertion_message_expr
(((gchar*) 0), "testfilechooser.c", 214, ((const char*) (__func__
)), "*error == NULL"); } while (0)
;
215 if (!gdk_pixbuf_loader_close (loader, error)) {
216 g_object_unref (loader);
217 return NULL((void*)0);
218 }
219
220 pixbuf = gdk_pixbuf_loader_get_pixbuf (loader);
221
222 if (!pixbuf) {
223 g_object_unref (loader);
224
225 /* did the loader set an error? */
226 if (*error != NULL((void*)0))
227 return NULL((void*)0);
228
229 g_set_error (error,
230 GDK_PIXBUF_ERRORgdk_pixbuf_error_quark (),
231 GDK_PIXBUF_ERROR_FAILED,
232 _("Failed to load image '%s': reason not known, probably a corrupt image file")("Failed to load image '%s': reason not known, probably a corrupt image file"
)
,
233 filename);
234 return NULL((void*)0);
235 }
236
237 g_object_ref (pixbuf)((__typeof__ (pixbuf)) (g_object_ref) (pixbuf));
238
239 g_object_unref (loader);
240
241 return pixbuf;
242}
243
244#if 0
245static char *
246format_time (time_t t)
247{
248 gchar buf[128];
249 struct tm tm_buf;
250 time_t now = time (NULL((void*)0));
251 const char *format;
252
253 if (abs (now - t) < 24*60*60)
254 format = "%X";
255 else
256 format = "%x";
257
258 localtime_r (&t, &tm_buf);
259 if (strftime (buf, sizeof (buf), format, &tm_buf) == 0)
260 return g_strdup ("<unknown>")g_strdup_inline ("<unknown>");
261 else
262 return g_strdup (buf)g_strdup_inline (buf);
263}
264
265static char *
266format_size (gint64 size)
267{
268 if (size < (gint64)1024)
269 return g_strdup_printf ("%d bytes", (gint)size);
270 else if (size < (gint64)1024*1024)
271 return g_strdup_printf ("%.1f K", size / (1024.));
272 else if (size < (gint64)1024*1024*1024)
273 return g_strdup_printf ("%.1f M", size / (1024.*1024.));
274 else
275 return g_strdup_printf ("%.1f G", size / (1024.*1024.*1024.));
276}
277
278static void
279update_preview_cb (CtkFileChooser *chooser)
280{
281 gchar *filename = ctk_file_chooser_get_preview_filename (chooser);
282 gboolean have_preview = FALSE(0);
283
284 if (filename)
285 {
286 GdkPixbuf *pixbuf;
287 GError *error = NULL((void*)0);
288
289 pixbuf = my_new_from_file_at_size (filename, 128, 128, &error);
290 if (pixbuf)
291 {
292 ctk_image_set_from_pixbuf (CTK_IMAGE (preview_image)((((CtkImage*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((preview_image)), ((ctk_image_get_type ()))))))
, pixbuf);
293 g_object_unref (pixbuf);
294 ctk_widget_show (preview_image);
295 ctk_widget_hide (preview_label);
296 have_preview = TRUE(!(0));
297 }
298 else
299 {
300 struct stat buf;
301 if (stat (filename, &buf) == 0)
302 {
303 gchar *preview_text;
304 gchar *size_str;
305 gchar *modified_time;
306
307 size_str = format_size (buf.st_size);
308 modified_time = format_time (buf.st_mtimest_mtim.tv_sec);
309
310 preview_text = g_strdup_printf ("<i>Modified:</i>\t%s\n"
311 "<i>Size:</i>\t%s\n",
312 modified_time,
313 size_str);
314 ctk_label_set_markup (CTK_LABEL (preview_label)((((CtkLabel*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((preview_label)), ((ctk_label_get_type ()))))))
, preview_text);
315 g_free (modified_time);
316 g_free (size_str);
317 g_free (preview_text);
318
319 ctk_widget_hide (preview_image);
320 ctk_widget_show (preview_label);
321 have_preview = TRUE(!(0));
322 }
323 }
324
325 g_free (filename);
326
327 if (error)
328 g_error_free (error);
329 }
330
331 ctk_file_chooser_set_preview_widget_active (chooser, have_preview);
332}
333#endif
334
335static void
336set_current_folder (CtkFileChooser *chooser,
337 const char *name)
338{
339 if (!ctk_file_chooser_set_current_folder (chooser, name))
340 {
341 CtkWidget *dialog;
342
343 dialog = ctk_message_dialog_new (CTK_WINDOW (chooser)((((CtkWindow*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((chooser)), ((ctk_window_get_type ()))))))
,
344 CTK_DIALOG_MODAL | CTK_DIALOG_DESTROY_WITH_PARENT,
345 CTK_MESSAGE_ERROR,
346 CTK_BUTTONS_CLOSE,
347 "Could not set the folder to %s",
348 name);
349 ctk_dialog_run (CTK_DIALOG (dialog)((((CtkDialog*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((dialog)), ((ctk_dialog_get_type ()))))))
);
350 ctk_widget_destroy (dialog);
351 }
352}
353
354static void
355set_folder_nonexistent_cb (CtkButton *button G_GNUC_UNUSED__attribute__ ((__unused__)),
356 CtkFileChooser *chooser)
357{
358 set_current_folder (chooser, "/nonexistent");
359}
360
361static void
362set_folder_existing_nonexistent_cb (CtkButton *button G_GNUC_UNUSED__attribute__ ((__unused__)),
363 CtkFileChooser *chooser)
364{
365 set_current_folder (chooser, "/usr/nonexistent");
366}
367
368static void
369set_filename (CtkFileChooser *chooser,
370 const char *name)
371{
372 if (!ctk_file_chooser_set_filename (chooser, name))
373 {
374 CtkWidget *dialog;
375
376 dialog = ctk_message_dialog_new (CTK_WINDOW (chooser)((((CtkWindow*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((chooser)), ((ctk_window_get_type ()))))))
,
377 CTK_DIALOG_MODAL | CTK_DIALOG_DESTROY_WITH_PARENT,
378 CTK_MESSAGE_ERROR,
379 CTK_BUTTONS_CLOSE,
380 "Could not select %s",
381 name);
382 ctk_dialog_run (CTK_DIALOG (dialog)((((CtkDialog*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((dialog)), ((ctk_dialog_get_type ()))))))
);
383 ctk_widget_destroy (dialog);
384 }
385}
386
387static void
388set_filename_nonexistent_cb (CtkButton *button G_GNUC_UNUSED__attribute__ ((__unused__)),
389 CtkFileChooser *chooser)
390{
391 set_filename (chooser, "/nonexistent");
392}
393
394static void
395set_filename_existing_nonexistent_cb (CtkButton *button G_GNUC_UNUSED__attribute__ ((__unused__)),
396 CtkFileChooser *chooser)
397{
398 set_filename (chooser, "/usr/nonexistent");
399}
400
401static void
402get_selection_cb (CtkButton *button G_GNUC_UNUSED__attribute__ ((__unused__)),
403 CtkFileChooser *chooser)
404{
405 GSList *selection;
406
407 selection = ctk_file_chooser_get_uris (chooser);
408
409 g_print ("Selection: ");
410
411 if (selection == NULL((void*)0))
412 g_print ("empty\n");
413 else
414 {
415 GSList *l;
416
417 for (l = selection; l; l = l->next)
418 {
419 char *uri = l->data;
420
421 g_print ("%s\n", uri);
422
423 if (l->next)
424 g_print (" ");
425 }
426 }
427
428 g_slist_free_full (selection, g_free);
429}
430
431static void
432get_current_name_cb (CtkButton *button G_GNUC_UNUSED__attribute__ ((__unused__)),
433 CtkFileChooser *chooser)
434{
435 char *name;
436
437 name = ctk_file_chooser_get_current_name (chooser);
438 g_print ("Current name: %s\n", name ? name : "NULL");
439 g_free (name);
440}
441
442static void
443unmap_and_remap_cb (CtkButton *button G_GNUC_UNUSED__attribute__ ((__unused__)),
444 CtkFileChooser *chooser)
445{
446 ctk_widget_hide (CTK_WIDGET (chooser)((((CtkWidget*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((chooser)), ((ctk_widget_get_type ()))))))
);
447 ctk_widget_show (CTK_WIDGET (chooser)((((CtkWidget*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((chooser)), ((ctk_widget_get_type ()))))))
);
448}
449
450static void
451kill_dependent (CtkWindow *win G_GNUC_UNUSED__attribute__ ((__unused__)),
452 CtkWidget *dep)
453{
454 ctk_widget_destroy (dep);
455 g_object_unref (dep);
456}
457
458static void
459notify_multiple_cb (CtkWidget *dialog,
460 GParamSpec *pspec G_GNUC_UNUSED__attribute__ ((__unused__)),
461 CtkWidget *button)
462{
463 gboolean multiple;
464
465 multiple = ctk_file_chooser_get_select_multiple (CTK_FILE_CHOOSER (dialog)((((CtkFileChooser*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((dialog)), ((ctk_file_chooser_get_type ()))))))
);
466
467 ctk_widget_set_sensitive (button, multiple);
468}
469
470static CtkFileChooserConfirmation
471confirm_overwrite_cb (CtkFileChooser *chooser,
472 gpointer data G_GNUC_UNUSED__attribute__ ((__unused__)))
473{
474 CtkWidget *dialog;
475 CtkWidget *button;
476 int response;
477 CtkFileChooserConfirmation conf;
478
479 dialog = ctk_message_dialog_new (CTK_WINDOW (ctk_widget_get_toplevel (CTK_WIDGET (chooser)))((((CtkWindow*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((ctk_widget_get_toplevel (((((CtkWidget*) (void *) g_type_check_instance_cast
((GTypeInstance*) ((chooser)), ((ctk_widget_get_type ())))))
)))), ((ctk_window_get_type ()))))))
,
480 CTK_DIALOG_MODAL | CTK_DIALOG_DESTROY_WITH_PARENT,
481 CTK_MESSAGE_QUESTION,
482 CTK_BUTTONS_NONE,
483 "What do you want to do?");
484
485 button = ctk_button_new_with_label ("Use the stock confirmation dialog");
486 ctk_widget_show (button);
487 ctk_dialog_add_action_widget (CTK_DIALOG (dialog)((((CtkDialog*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((dialog)), ((ctk_dialog_get_type ()))))))
, button, 1);
488
489 button = ctk_button_new_with_label ("Type a new file name");
490 ctk_widget_show (button);
491 ctk_dialog_add_action_widget (CTK_DIALOG (dialog)((((CtkDialog*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((dialog)), ((ctk_dialog_get_type ()))))))
, button, 2);
492
493 button = ctk_button_new_with_label ("Accept the file name");
494 ctk_widget_show (button);
495 ctk_dialog_add_action_widget (CTK_DIALOG (dialog)((((CtkDialog*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((dialog)), ((ctk_dialog_get_type ()))))))
, button, 3);
496
497 response = ctk_dialog_run (CTK_DIALOG (dialog)((((CtkDialog*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((dialog)), ((ctk_dialog_get_type ()))))))
);
498
499 switch (response)
500 {
501 case 1:
502 conf = CTK_FILE_CHOOSER_CONFIRMATION_CONFIRM;
503 break;
504
505 case 3:
506 conf = CTK_FILE_CHOOSER_CONFIRMATION_ACCEPT_FILENAME;
507 break;
508
509 default:
510 conf = CTK_FILE_CHOOSER_CONFIRMATION_SELECT_AGAIN;
511 break;
512 }
513
514 ctk_widget_destroy (dialog);
515
516 return conf;
517}
518
519int
520main (int argc, char **argv)
521{
522 CtkWidget *control_window;
523 CtkWidget *vbbox;
524 CtkWidget *button;
525 CtkWidget *dialog;
526 CtkWidget *extra;
527 CtkFileFilter *filter;
528 gboolean force_rtl = FALSE(0);
529 gboolean multiple = FALSE(0);
530 gboolean local_only = FALSE(0);
531 char *action_arg = NULL((void*)0);
532 char *initial_filename = NULL((void*)0);
533 char *initial_folder = NULL((void*)0);
534 GError *error = NULL((void*)0);
535 GOptionEntry options[] = {
536 { "action", 'a', 0, G_OPTION_ARG_STRING, &action_arg, "Filechooser action", "ACTION" },
537 { "multiple", 'm', 0, G_OPTION_ARG_NONE, &multiple, "Select multiple", NULL((void*)0) },
538 { "local-only", 'l', 0, G_OPTION_ARG_NONE, &local_only, "Local only", NULL((void*)0) },
539 { "right-to-left", 'r', 0, G_OPTION_ARG_NONE, &force_rtl, "Force right-to-left layout.", NULL((void*)0) },
540 { "initial-filename", 'f', 0, G_OPTION_ARG_FILENAME, &initial_filename, "Initial filename to select", "FILENAME" },
541 { "initial-folder", 'F', 0, G_OPTION_ARG_FILENAME, &initial_folder, "Initial folder to show", "FILENAME" },
542 { NULL((void*)0) }
543 };
544
545 if (!ctk_init_with_args (&argc, &argv, "", options, NULL((void*)0), &error))
546 {
547 g_print ("Failed to parse args: %s\n", error->message);
548 g_error_free (error);
549 return 1;
550 }
551
552 if (initial_filename && initial_folder)
553 {
554 g_print ("Only one of --initial-filename and --initial-folder may be specified");
555 return 1;
556 }
557
558 if (force_rtl)
559 ctk_widget_set_default_direction (CTK_TEXT_DIR_RTL);
560
561 action = CTK_FILE_CHOOSER_ACTION_OPEN;
562
563 if (action_arg != NULL((void*)0))
564 {
565 if (! strcmp ("open", action_arg))
566 action = CTK_FILE_CHOOSER_ACTION_OPEN;
567 else if (! strcmp ("save", action_arg))
568 action = CTK_FILE_CHOOSER_ACTION_SAVE;
569 else if (! strcmp ("select_folder", action_arg))
570 action = CTK_FILE_CHOOSER_ACTION_SELECT_FOLDER;
571 else if (! strcmp ("create_folder", action_arg))
572 action = CTK_FILE_CHOOSER_ACTION_CREATE_FOLDER;
573 else
574 {
575 g_print ("--action must be one of \"open\", \"save\", \"select_folder\", \"create_folder\"\n");
576 return 1;
577 }
578
579 g_free (action_arg);
580 }
581
582 dialog = g_object_new (CTK_TYPE_FILE_CHOOSER_DIALOG(ctk_file_chooser_dialog_get_type ()),
583 "action", action,
584 "select-multiple", multiple,
585 "local-only", local_only,
586 NULL((void*)0));
587
588 switch (action)
589 {
590 case CTK_FILE_CHOOSER_ACTION_OPEN:
591 case CTK_FILE_CHOOSER_ACTION_SELECT_FOLDER:
592 ctk_window_set_title (CTK_WINDOW (dialog)((((CtkWindow*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((dialog)), ((ctk_window_get_type ()))))))
, "Select a file");
593 ctk_dialog_add_buttons (CTK_DIALOG (dialog)((((CtkDialog*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((dialog)), ((ctk_dialog_get_type ()))))))
,
594 _("_Cancel")("_Cancel"), CTK_RESPONSE_CANCEL,
595 _("_Open")("_Open"), CTK_RESPONSE_OK,
596 NULL((void*)0));
597 break;
598 case CTK_FILE_CHOOSER_ACTION_SAVE:
599 case CTK_FILE_CHOOSER_ACTION_CREATE_FOLDER:
600 ctk_window_set_title (CTK_WINDOW (dialog)((((CtkWindow*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((dialog)), ((ctk_window_get_type ()))))))
, "Save a file");
601 ctk_dialog_add_buttons (CTK_DIALOG (dialog)((((CtkDialog*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((dialog)), ((ctk_dialog_get_type ()))))))
,
602 _("_Cancel")("_Cancel"), CTK_RESPONSE_CANCEL,
603 _("_Save")("_Save"), CTK_RESPONSE_OK,
604 NULL((void*)0));
605 break;
606 }
607 ctk_dialog_set_default_response (CTK_DIALOG (dialog)((((CtkDialog*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((dialog)), ((ctk_dialog_get_type ()))))))
, CTK_RESPONSE_OK);
608
609 g_signal_connect (dialog, "selection-changed",g_signal_connect_data ((dialog), ("selection-changed"), (((GCallback
) (print_selected))), (((void*)0)), ((void*)0), (GConnectFlags
) 0)
610 G_CALLBACK (print_selected), NULL)g_signal_connect_data ((dialog), ("selection-changed"), (((GCallback
) (print_selected))), (((void*)0)), ((void*)0), (GConnectFlags
) 0)
;
611 g_signal_connect (dialog, "current-folder-changed",g_signal_connect_data ((dialog), ("current-folder-changed"), (
((GCallback) (print_current_folder))), (((void*)0)), ((void*)
0), (GConnectFlags) 0)
612 G_CALLBACK (print_current_folder), NULL)g_signal_connect_data ((dialog), ("current-folder-changed"), (
((GCallback) (print_current_folder))), (((void*)0)), ((void*)
0), (GConnectFlags) 0)
;
613 g_signal_connect (dialog, "response",g_signal_connect_data ((dialog), ("response"), (((GCallback) (
response_cb))), (((void*)0)), ((void*)0), (GConnectFlags) 0)
614 G_CALLBACK (response_cb), NULL)g_signal_connect_data ((dialog), ("response"), (((GCallback) (
response_cb))), (((void*)0)), ((void*)0), (GConnectFlags) 0)
;
615 g_signal_connect (dialog, "confirm-overwrite",g_signal_connect_data ((dialog), ("confirm-overwrite"), (((GCallback
) (confirm_overwrite_cb))), (((void*)0)), ((void*)0), (GConnectFlags
) 0)
616 G_CALLBACK (confirm_overwrite_cb), NULL)g_signal_connect_data ((dialog), ("confirm-overwrite"), (((GCallback
) (confirm_overwrite_cb))), (((void*)0)), ((void*)0), (GConnectFlags
) 0)
;
617
618 /* Filters */
619 filter = ctk_file_filter_new ();
620 ctk_file_filter_set_name (filter, "All Files");
621 ctk_file_filter_add_pattern (filter, "*");
622 ctk_file_chooser_add_filter (CTK_FILE_CHOOSER (dialog)((((CtkFileChooser*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((dialog)), ((ctk_file_chooser_get_type ()))))))
, filter);
623
624 /* Make this filter the default */
625 ctk_file_chooser_set_filter (CTK_FILE_CHOOSER (dialog)((((CtkFileChooser*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((dialog)), ((ctk_file_chooser_get_type ()))))))
, filter);
626
627 filter = ctk_file_filter_new ();
628 ctk_file_filter_set_name (filter, "No backup files");
629 ctk_file_filter_add_custom (filter, CTK_FILE_FILTER_DISPLAY_NAME,
630 no_backup_files_filter, NULL((void*)0), NULL((void*)0));
631 ctk_file_filter_add_mime_type (filter, "image/png");
632 ctk_file_chooser_add_filter (CTK_FILE_CHOOSER (dialog)((((CtkFileChooser*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((dialog)), ((ctk_file_chooser_get_type ()))))))
, filter);
633
634 filter = ctk_file_filter_new ();
635 ctk_file_filter_set_name (filter, "Starts with D");
636 ctk_file_filter_add_pattern (filter, "D*");
637 ctk_file_chooser_add_filter (CTK_FILE_CHOOSER (dialog)((((CtkFileChooser*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((dialog)), ((ctk_file_chooser_get_type ()))))))
, filter);
638
639 g_signal_connect (dialog, "notify::filter",g_signal_connect_data ((dialog), ("notify::filter"), (((GCallback
) (filter_changed))), (((void*)0)), ((void*)0), (GConnectFlags
) 0)
640 G_CALLBACK (filter_changed), NULL)g_signal_connect_data ((dialog), ("notify::filter"), (((GCallback
) (filter_changed))), (((void*)0)), ((void*)0), (GConnectFlags
) 0)
;
641
642 filter = ctk_file_filter_new ();
643 ctk_file_filter_set_name (filter, "PNG and JPEG");
644 ctk_file_filter_add_mime_type (filter, "image/jpeg");
645 ctk_file_filter_add_mime_type (filter, "image/png");
646 ctk_file_chooser_add_filter (CTK_FILE_CHOOSER (dialog)((((CtkFileChooser*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((dialog)), ((ctk_file_chooser_get_type ()))))))
, filter);
647
648 filter = ctk_file_filter_new ();
649 ctk_file_filter_set_name (filter, "Images");
650 ctk_file_filter_add_pixbuf_formats (filter);
651 ctk_file_chooser_add_filter (CTK_FILE_CHOOSER (dialog)((((CtkFileChooser*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((dialog)), ((ctk_file_chooser_get_type ()))))))
, filter);
652
653#if 0
654 /* Preview widget */
655 /* THIS IS A TERRIBLE PREVIEW WIDGET, AND SHOULD NOT BE COPIED AT ALL.
656 */
657 preview_vbox = ctk_box_new (CTK_ORIENTATION_VERTICAL, 0);
658 ctk_file_chooser_set_preview_widget (CTK_FILE_CHOOSER (dialog)((((CtkFileChooser*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((dialog)), ((ctk_file_chooser_get_type ()))))))
, preview_vbox);
659
660 preview_label = ctk_label_new (NULL((void*)0));
661 ctk_box_pack_start (CTK_BOX (preview_vbox)((((CtkBox*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((preview_vbox)), ((ctk_box_get_type ()))))))
, preview_label, TRUE(!(0)), TRUE(!(0)), 0);
662 g_object_set (preview_label, "margin", 6, NULL((void*)0));
663
664 preview_image = ctk_image_new ();
665 ctk_box_pack_start (CTK_BOX (preview_vbox)((((CtkBox*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((preview_vbox)), ((ctk_box_get_type ()))))))
, preview_image, TRUE(!(0)), TRUE(!(0)), 0);
666 g_object_set (preview_image, "margin", 6, NULL((void*)0));
667
668 update_preview_cb (CTK_FILE_CHOOSER (dialog)((((CtkFileChooser*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((dialog)), ((ctk_file_chooser_get_type ()))))))
);
669 g_signal_connect (dialog, "update-preview",g_signal_connect_data ((dialog), ("update-preview"), (((GCallback
) (update_preview_cb))), (((void*)0)), ((void*)0), (GConnectFlags
) 0)
670 G_CALLBACK (update_preview_cb), NULL)g_signal_connect_data ((dialog), ("update-preview"), (((GCallback
) (update_preview_cb))), (((void*)0)), ((void*)0), (GConnectFlags
) 0)
;
671#endif
672
673 /* Extra widget */
674
675 extra = ctk_check_button_new_with_mnemonic ("Lar_t whoever asks about this button");
676 ctk_toggle_button_set_active (CTK_TOGGLE_BUTTON (extra)((((CtkToggleButton*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((extra)), ((ctk_toggle_button_get_type ()))))))
, TRUE(!(0)));
677 ctk_file_chooser_set_extra_widget (CTK_FILE_CHOOSER (dialog)((((CtkFileChooser*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((dialog)), ((ctk_file_chooser_get_type ()))))))
, extra);
678
679 /* Shortcuts */
680
681 ctk_file_chooser_add_shortcut_folder_uri (CTK_FILE_CHOOSER (dialog)((((CtkFileChooser*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((dialog)), ((ctk_file_chooser_get_type ()))))))
,
682 "file:///usr/share/pixmaps",
683 NULL((void*)0));
684 ctk_file_chooser_add_shortcut_folder (CTK_FILE_CHOOSER (dialog)((((CtkFileChooser*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((dialog)), ((ctk_file_chooser_get_type ()))))))
,
685 g_get_user_special_dir (G_USER_DIRECTORY_MUSIC),
686 NULL((void*)0));
687
688 /* Initial filename or folder */
689
690 if (initial_filename)
691 set_filename (CTK_FILE_CHOOSER (dialog)((((CtkFileChooser*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((dialog)), ((ctk_file_chooser_get_type ()))))))
, initial_filename);
692
693 if (initial_folder)
694 set_current_folder (CTK_FILE_CHOOSER (dialog)((((CtkFileChooser*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((dialog)), ((ctk_file_chooser_get_type ()))))))
, initial_folder);
695
696 /* show_all() to reveal bugs in composite widget handling */
697 ctk_widget_show_all (dialog);
698
699 /* Extra controls for manipulating the test environment
700 */
701
702 control_window = ctk_window_new (CTK_WINDOW_TOPLEVEL);
703
704 vbbox = ctk_button_box_new (CTK_ORIENTATION_VERTICAL);
705 ctk_container_add (CTK_CONTAINER (control_window)((((CtkContainer*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((control_window)), ((ctk_container_get_type ()))))))
, vbbox);
706
707 button = ctk_button_new_with_mnemonic ("_Select all");
708 ctk_widget_set_sensitive (button, multiple);
709 ctk_container_add (CTK_CONTAINER (vbbox)((((CtkContainer*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((vbbox)), ((ctk_container_get_type ()))))))
, button);
710 g_signal_connect_swapped (button, "clicked",g_signal_connect_data ((button), ("clicked"), (((GCallback) (
ctk_file_chooser_select_all))), (dialog), ((void*)0), G_CONNECT_SWAPPED
)
711 G_CALLBACK (ctk_file_chooser_select_all), dialog)g_signal_connect_data ((button), ("clicked"), (((GCallback) (
ctk_file_chooser_select_all))), (dialog), ((void*)0), G_CONNECT_SWAPPED
)
;
712 g_signal_connect (dialog, "notify::select-multiple",g_signal_connect_data ((dialog), ("notify::select-multiple"),
(((GCallback) (notify_multiple_cb))), (button), ((void*)0), (
GConnectFlags) 0)
713 G_CALLBACK (notify_multiple_cb), button)g_signal_connect_data ((dialog), ("notify::select-multiple"),
(((GCallback) (notify_multiple_cb))), (button), ((void*)0), (
GConnectFlags) 0)
;
714
715 button = ctk_button_new_with_mnemonic ("_Unselect all");
716 ctk_container_add (CTK_CONTAINER (vbbox)((((CtkContainer*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((vbbox)), ((ctk_container_get_type ()))))))
, button);
717 g_signal_connect_swapped (button, "clicked",g_signal_connect_data ((button), ("clicked"), (((GCallback) (
ctk_file_chooser_unselect_all))), (dialog), ((void*)0), G_CONNECT_SWAPPED
)
718 G_CALLBACK (ctk_file_chooser_unselect_all), dialog)g_signal_connect_data ((button), ("clicked"), (((GCallback) (
ctk_file_chooser_unselect_all))), (dialog), ((void*)0), G_CONNECT_SWAPPED
)
;
719
720 button = ctk_button_new_with_label ("set_current_folder (\"/nonexistent\")");
721 ctk_container_add (CTK_CONTAINER (vbbox)((((CtkContainer*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((vbbox)), ((ctk_container_get_type ()))))))
, button);
722 g_signal_connect (button, "clicked",g_signal_connect_data ((button), ("clicked"), (((GCallback) (
set_folder_nonexistent_cb))), (dialog), ((void*)0), (GConnectFlags
) 0)
723 G_CALLBACK (set_folder_nonexistent_cb), dialog)g_signal_connect_data ((button), ("clicked"), (((GCallback) (
set_folder_nonexistent_cb))), (dialog), ((void*)0), (GConnectFlags
) 0)
;
724
725 button = ctk_button_new_with_label ("set_current_folder (\"/usr/nonexistent\")");
726 ctk_container_add (CTK_CONTAINER (vbbox)((((CtkContainer*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((vbbox)), ((ctk_container_get_type ()))))))
, button);
727 g_signal_connect (button, "clicked",g_signal_connect_data ((button), ("clicked"), (((GCallback) (
set_folder_existing_nonexistent_cb))), (dialog), ((void*)0), (
GConnectFlags) 0)
728 G_CALLBACK (set_folder_existing_nonexistent_cb), dialog)g_signal_connect_data ((button), ("clicked"), (((GCallback) (
set_folder_existing_nonexistent_cb))), (dialog), ((void*)0), (
GConnectFlags) 0)
;
729
730 button = ctk_button_new_with_label ("set_filename (\"/nonexistent\")");
731 ctk_container_add (CTK_CONTAINER (vbbox)((((CtkContainer*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((vbbox)), ((ctk_container_get_type ()))))))
, button);
732 g_signal_connect (button, "clicked",g_signal_connect_data ((button), ("clicked"), (((GCallback) (
set_filename_nonexistent_cb))), (dialog), ((void*)0), (GConnectFlags
) 0)
733 G_CALLBACK (set_filename_nonexistent_cb), dialog)g_signal_connect_data ((button), ("clicked"), (((GCallback) (
set_filename_nonexistent_cb))), (dialog), ((void*)0), (GConnectFlags
) 0)
;
734
735 button = ctk_button_new_with_label ("set_filename (\"/usr/nonexistent\")");
736 ctk_container_add (CTK_CONTAINER (vbbox)((((CtkContainer*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((vbbox)), ((ctk_container_get_type ()))))))
, button);
737 g_signal_connect (button, "clicked",g_signal_connect_data ((button), ("clicked"), (((GCallback) (
set_filename_existing_nonexistent_cb))), (dialog), ((void*)0)
, (GConnectFlags) 0)
738 G_CALLBACK (set_filename_existing_nonexistent_cb), dialog)g_signal_connect_data ((button), ("clicked"), (((GCallback) (
set_filename_existing_nonexistent_cb))), (dialog), ((void*)0)
, (GConnectFlags) 0)
;
739
740 button = ctk_button_new_with_label ("Get selection");
741 ctk_container_add (CTK_CONTAINER (vbbox)((((CtkContainer*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((vbbox)), ((ctk_container_get_type ()))))))
, button);
742 g_signal_connect (button, "clicked",g_signal_connect_data ((button), ("clicked"), (((GCallback) (
get_selection_cb))), (dialog), ((void*)0), (GConnectFlags) 0)
743 G_CALLBACK (get_selection_cb), dialog)g_signal_connect_data ((button), ("clicked"), (((GCallback) (
get_selection_cb))), (dialog), ((void*)0), (GConnectFlags) 0)
;
744
745 button = ctk_button_new_with_label ("Get current name");
746 ctk_container_add (CTK_CONTAINER (vbbox)((((CtkContainer*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((vbbox)), ((ctk_container_get_type ()))))))
, button);
747 g_signal_connect (button, "clicked",g_signal_connect_data ((button), ("clicked"), (((GCallback) (
get_current_name_cb))), (dialog), ((void*)0), (GConnectFlags)
0)
748 G_CALLBACK (get_current_name_cb), dialog)g_signal_connect_data ((button), ("clicked"), (((GCallback) (
get_current_name_cb))), (dialog), ((void*)0), (GConnectFlags)
0)
;
749
750 button = ctk_button_new_with_label ("Unmap and remap");
751 ctk_container_add (CTK_CONTAINER (vbbox)((((CtkContainer*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((vbbox)), ((ctk_container_get_type ()))))))
, button);
752 g_signal_connect (button, "clicked",g_signal_connect_data ((button), ("clicked"), (((GCallback) (
unmap_and_remap_cb))), (dialog), ((void*)0), (GConnectFlags) 0
)
753 G_CALLBACK (unmap_and_remap_cb), dialog)g_signal_connect_data ((button), ("clicked"), (((GCallback) (
unmap_and_remap_cb))), (dialog), ((void*)0), (GConnectFlags) 0
)
;
754
755 ctk_widget_show_all (control_window);
756
757 g_object_ref (control_window)((__typeof__ (control_window)) (g_object_ref) (control_window
))
;
758 g_signal_connect (dialog, "destroy",g_signal_connect_data ((dialog), ("destroy"), (((GCallback) (
kill_dependent))), (control_window), ((void*)0), (GConnectFlags
) 0)
759 G_CALLBACK (kill_dependent), control_window)g_signal_connect_data ((dialog), ("destroy"), (((GCallback) (
kill_dependent))), (control_window), ((void*)0), (GConnectFlags
) 0)
;
760
761 /* We need to hold a ref until we have destroyed the widgets, just in case
762 * someone else destroys them. We explicitly destroy windows to catch leaks.
763 */
764 g_object_ref (dialog)((__typeof__ (dialog)) (g_object_ref) (dialog));
765 ctk_main ();
766 ctk_widget_destroy (dialog);
767 g_object_unref (dialog);
768
769 return 0;
770}