2 * This program is free software; you can redistribute it and/or
3 * modify it under the terms of the GNU General Public License
4 * as published by the Free Software Foundation; either version 2
5 * of the License, or (at your option) any later version.
7 * This program is distributed in the hope that it will be useful,
8 * but WITHOUT ANY WARRANTY; without even the implied warranty of
9 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10 * GNU General Public License for more details.
12 * You should have received a copy of the GNU General Public License
13 * along with this program; if not, write to the Free Software
14 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
16 * See the COPYING file for license information.
18 * Guillaume Chazarain <guichaz@yahoo.fr>
25 #include <unistd.h> /* close(), dup(), dup2(), STDERR_FILENO */
26 #include <stdlib.h> /* exit() */
27 #include <gtk/gtkgl.h>
33 #include "gliv_image.h"
35 #include "files_list.h"
41 options_struct
*options
;
42 gliv_image
*current_image
= NULL
;
47 * This is borrowed from gtk+-2, without the gtk_grab_notify() calls.
48 * They slow down things a lot when the images menus are built with many files.
50 GtkWindowGroup
*_gtk_window_get_group(GtkWindow
* window
)
52 if (window
&& window
->group
)
55 static GtkWindowGroup
*default_group
= NULL
;
58 default_group
= gtk_window_group_new();
64 static GtkWindowGroup
*gtk_main_get_window_group(GtkWidget
* widget
)
66 GtkWidget
*toplevel
= NULL
;
69 toplevel
= gtk_widget_get_toplevel(widget
);
71 if (toplevel
&& GTK_IS_WINDOW(toplevel
))
72 return _gtk_window_get_group(GTK_WINDOW(toplevel
));
74 return _gtk_window_get_group(NULL
);
77 void gtk_grab_add(GtkWidget
* widget
)
79 GtkWindowGroup
*group
;
81 g_return_if_fail(widget
!= NULL
);
83 if (!GTK_WIDGET_HAS_GRAB(widget
) && GTK_WIDGET_IS_SENSITIVE(widget
)) {
84 GTK_WIDGET_SET_FLAGS(widget
, GTK_HAS_GRAB
);
86 group
= gtk_main_get_window_group(widget
);
89 group
->grabs
= g_slist_prepend(group
->grabs
, widget
);
91 /* gtk_grab_notify (group, widget, FALSE); */
95 void gtk_grab_remove(GtkWidget
* widget
)
97 GtkWindowGroup
*group
;
99 g_return_if_fail(widget
!= NULL
);
101 if (GTK_WIDGET_HAS_GRAB(widget
)) {
102 GTK_WIDGET_UNSET_FLAGS(widget
, GTK_HAS_GRAB
);
104 group
= gtk_main_get_window_group(widget
);
105 group
->grabs
= g_slist_remove(group
->grabs
, widget
);
107 g_object_unref(widget
);
109 /* gtk_grab_notify (group, widget, TRUE); */
113 void destroy_ggo_inputs(struct gengetopt_args_info
*ggo
)
117 for (i
= 0; i
< ggo
->inputs_num
; i
++)
118 g_free(ggo
->inputs
[i
]);
125 void destroy_ggo_flags(struct gengetopt_args_info
*ggo
)
127 g_free(ggo
->menu_arg
);
128 g_free(ggo
->client_arg
);
129 g_free(ggo
->alpha_checks_arg
);
130 g_free(ggo
->build_menus_arg
);
131 g_free(ggo
->force_load_arg
);
132 g_free(ggo
->full_screen_arg
);
133 g_free(ggo
->glivrc_arg
);
134 g_free(ggo
->info_arg
);
135 g_free(ggo
->loop_arg
);
136 g_free(ggo
->scale_down_arg
);
137 g_free(ggo
->maximize_arg
);
138 g_free(ggo
->make_fit_arg
);
139 g_free(ggo
->mnemonics_arg
);
140 g_free(ggo
->scrollbars_arg
);
141 g_free(ggo
->mipmap_arg
);
142 g_free(ggo
->recursive_arg
);
143 g_free(ggo
->sort_arg
);
144 g_free(ggo
->shuffle_arg
);
145 g_free(ggo
->thumbnails_arg
);
146 g_free(ggo
->dither_arg
);
147 g_free(ggo
->resize_win_arg
);
148 g_free(ggo
->slide_show_arg
);
149 g_free(ggo
->zoom_pointer_arg
);
150 g_free(ggo
->null_arg
);
151 g_free(ggo
->one_image_arg
);
152 g_free(ggo
->no_center_arg
);
156 gboolean
get_on_off(const gchar
* str
)
161 while (*str
== '=' || *str
== ' ')
164 if (g_str_equal(str
, "on"))
167 if (g_str_equal(str
, "off"))
170 ERROR_MSG(_("Command line flags should be on or off, not %s\n"), str
);
188 static void fill_options(struct gengetopt_args_info
*ggo
)
192 { ggo
->full_screen_given
, &options
->fullscreen
, ggo
->full_screen_arg
, 0 },
193 { ggo
->scale_down_given
, &options
->scaledown
, ggo
->scale_down_arg
, 0 },
194 { ggo
->maximize_given
, &options
->maximize
, ggo
->maximize_arg
, 0 },
195 { ggo
->zoom_pointer_given
, &options
->zoom_pointer
, ggo
->zoom_pointer_arg
, 0 },
196 { ggo
->dither_given
, &options
->dither
, ggo
->dither_arg
, 0 },
197 { ggo
->force_load_given
, &options
->force
, ggo
->force_load_arg
, 0 },
198 { ggo
->mipmap_given
, &options
->mipmap
, ggo
->mipmap_arg
, 0 },
199 { ggo
->build_menus_given
, &options
->build_menus
, ggo
->build_menus_arg
, 1 },
200 { ggo
->mnemonics_given
, &options
->mnemonics
, ggo
->mnemonics_arg
, 1 },
201 { ggo
->menu_given
, &options
->menu_bar
, ggo
->menu_arg
, 1 },
202 { ggo
->info_given
, &options
->status_bar
, ggo
->info_arg
, 1 },
203 { ggo
->scrollbars_given
, &options
->scrollbars
, ggo
->scrollbars_arg
, 1 },
204 { ggo
->alpha_checks_given
, &options
->alpha_checks
, ggo
->alpha_checks_arg
, 1 },
205 { ggo
->loop_given
, &options
->loop
, ggo
->loop_arg
, 0 },
206 { ggo
->one_image_given
, &options
->one_image
, ggo
->one_image_arg
, 0 },
207 { ggo
->thumbnails_given
, &options
->thumbnails
, ggo
->thumbnails_arg
, 1 },
208 { ggo
->slide_show_given
, &options
->start_show
, ggo
->slide_show_arg
, 0 },
209 { ggo
->resize_win_given
, &options
->resize_win
, ggo
->resize_win_arg
, 1 },
210 { ggo
->make_fit_given
, &options
->maximize
, ggo
->make_fit_arg
, 0 },
211 { ggo
->make_fit_given
, &options
->scaledown
, ggo
->make_fit_arg
, 0 },
212 { ggo
->no_center_given
, &options
->no_center
, ggo
->no_center_arg
, 0 },
213 { FALSE
, NULL
, NULL
, }
219 { ggo
->delay_given
, &options
->delay
, ggo
->delay_arg
, 0 },
220 { ggo
->history_given
, &options
->history_size
, ggo
->history_arg
, -1 },
221 { ggo
->duration_given
, &options
->duration
, ggo
->duration_arg
, 0 },
222 { ggo
->fps_given
, &options
->fps
, ggo
->fps_arg
, -1 },
223 { FALSE
, NULL
, FALSE
, 0 }
230 for (flag
= flags
; flag
->flag
!= NULL
; flag
++)
232 *flag
->flag
= get_on_off(flag
->str
);
237 for (opt_int
= ints
; opt_int
->opt_val
!= NULL
; opt_int
++)
238 if (opt_int
->given
&& opt_int
->value
>= opt_int
->minimum
)
239 *opt_int
->opt_val
= opt_int
->value
;
242 #define FLAG_ON(flag) (flag##_given && get_on_off(flag##_arg))
244 static void init_args(gint argc
, gchar
** argv
)
246 struct gengetopt_args_info ggo
;
247 options_struct
*rc_file
;
249 /* Command line (some flags only). */
251 if (cmdline_parser(argc
, argv
, &ggo
) != 0)
254 if (FLAG_ON(ggo
.sort
) && FLAG_ON(ggo
.shuffle
)) {
255 g_printerr(_("Cannot sort and shuffle at the same time\n"));
259 if (FLAG_ON(ggo
.client
) && connect_server(argc
, argv
))
260 /* Successfully reused a GLiv window. */
263 /* Configuration file. */
264 rc_file
= load_rc(!FLAG_ON(ggo
.glivrc
));
265 options
= g_memdup(rc_file
, sizeof(options_struct
));
267 /* Command line (remaining options). */
270 rt
= g_new(rt_struct
, 1);
272 rt
->cursor_hidden
= FALSE
;
274 rt
->alpha_checks_changed
= TRUE
;
275 rt
->scr_width
= gdk_screen_width();
276 rt
->scr_height
= gdk_screen_height();
278 if (FLAG_ON(ggo
.null
)) {
279 read_null_filenames(FLAG_ON(ggo
.recursive
), FLAG_ON(ggo
.shuffle
),
282 insert_after_current(ggo
.inputs
, ggo
.inputs_num
,
283 FLAG_ON(ggo
.recursive
),
284 FLAG_ON(ggo
.shuffle
), FLAG_ON(ggo
.sort
), TRUE
);
286 } else if (ggo
.inputs_num
> 0)
287 /* There are filenames on the command line. */
288 init_list(ggo
.inputs
, ggo
.inputs_num
,
289 FLAG_ON(ggo
.recursive
),
290 FLAG_ON(ggo
.shuffle
), FLAG_ON(ggo
.sort
));
292 destroy_ggo_inputs(&ggo
);
293 destroy_ggo_flags(&ggo
);
297 * We call cmdline_parser() a first time to quickly exit if --help or --version
298 * was given. We do the real work after the next call in init_args(), after
299 * gtk_init() removed the gtk arguments.
301 * We temporarily close stderr because unknown and gtk arguments are handled
304 static void check_quick_exit(gint argc
, gchar
** argv
)
306 struct gengetopt_args_info ggo
;
309 /* Silence stderr. */
310 fd
= dup(STDERR_FILENO
);
311 close(STDERR_FILENO
);
313 cmdline_parser(argc
, argv
, &ggo
);
315 /* Restore stderr. */
316 dup2(fd
, STDERR_FILENO
);
319 destroy_ggo_inputs(&ggo
);
320 destroy_ggo_flags(&ggo
);
323 G_GNUC_NORETURN
void quit(gint code
)
328 gboolean
gui_quit(void)
330 GtkMessageDialog
*dialog
;
333 if (options
->confirm_quit
== FALSE
)
336 msg
= _("Do you really want to quit GLiv?");
338 dialog
= GTK_MESSAGE_DIALOG(gtk_message_dialog_new(get_current_window(),
340 GTK_MESSAGE_QUESTION
,
344 gtk_dialog_set_default_response(GTK_DIALOG(dialog
), GTK_RESPONSE_YES
);
346 set_hide_cursor_enabled(FALSE
);
347 if (gtk_dialog_run(GTK_DIALOG(dialog
)) == GTK_RESPONSE_YES
)
350 gtk_widget_destroy(GTK_WIDGET(dialog
));
351 set_hide_cursor_enabled(TRUE
);
355 gint
main(gint argc
, gchar
** argv
)
357 check_quick_exit(argc
, argv
);
363 bindtextdomain(PACKAGE
, LOCALEDIR
);
366 bind_textdomain_codeset(PACKAGE
, "UTF-8");
370 gtk_init(&argc
, &argv
);
371 gtk_gl_init(&argc
, &argv
);
373 init_args(argc
, argv
);