Bug Summary

File:applets/fish/fish.c
Warning:line 1601, column 3
This statement is never executed

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 fish.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/applets/fish -fcoverage-compilation-dir=/rootdir/applets/fish -resource-dir /usr/lib/llvm-19/lib/clang/19 -D HAVE_CONFIG_H -I . -I ../.. -I /usr/include/ctk-3.0 -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 -I /usr/include/atk-1.0 -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/ctk-3.0 -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 -I /usr/include/atk-1.0 -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/cafe-desktop-2.0 -I /usr/include/startup-notification-1.0 -I /usr/include/dconf -I . -I ./../../libcafe-panel-applet -I ../../libcafe-panel-applet -D CAFELOCALEDIR="/usr/share/locale" -D FISH_ICONDIR="/usr/share/cafe-panel/fish" -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/2025-03-30-180740-54439-1 -x c fish.c
1/* fish.c:
2 *
3 * Copyright (C) 1998-2002 Free Software Foundation, Inc.
4 * Copyright (C) 2002-2005 Vincent Untz
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version.
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin St, Fifth Floor,
19 * Boston, MA 02110-1301, USA.
20 *
21 * Authors:
22 * George Lebl <jirka@5z.com>
23 * Mark McLoughlin <mark@skynet.ie>
24 * Vincent Untz <vuntz@gnome.org>
25 * Stefano Karapetsas <stefano@karapetsas.com>
26 */
27
28#include <config.h>
29
30#include <math.h>
31#include <string.h>
32#include <time.h>
33
34#include <cairo.h>
35
36#include <glib/gi18n.h>
37#include <glib-object.h>
38#include <ctk/ctk.h>
39#include <cdk/cdkkeysyms.h>
40#include <gio/gio.h>
41
42#include <cafe-panel-applet.h>
43#include <cafe-panel-applet-gsettings.h>
44
45#define FISH_APPLET(o)((((FishApplet*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((o)), (fish_applet_get_type())))))
\
46 (G_TYPE_CHECK_INSTANCE_CAST((o), fish_applet_get_type(), FishApplet)(((FishApplet*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((o)), (fish_applet_get_type()))))
)
47#define FISH_IS_APPLET(o)(((__extension__ ({ GTypeInstance *__inst = (GTypeInstance*) (
(o)); GType __t = (FISH_TYPE_APPLET); gboolean __r; if (!__inst
) __r = (0); else if (__inst->g_class && __inst->
g_class->g_type == __t) __r = (!(0)); else __r = g_type_check_instance_is_a
(__inst, __t); __r; }))))
\
48 (G_TYPE_CHECK_INSTANCE_TYPE((o), FISH_TYPE_APPLET)((__extension__ ({ GTypeInstance *__inst = (GTypeInstance*) (
(o)); GType __t = (FISH_TYPE_APPLET); gboolean __r; if (!__inst
) __r = (0); else if (__inst->g_class && __inst->
g_class->g_type == __t) __r = (!(0)); else __r = g_type_check_instance_is_a
(__inst, __t); __r; })))
)
49
50#define FISH_ICON"cafe-panel-fish" "cafe-panel-fish"
51#define FISH_RESOURCE_PATH"/org/cafe/panel/applet/fish/" "/org/cafe/panel/applet/fish/"
52
53#define FISH_SCHEMA"org.cafe.panel.applet.fish" "org.cafe.panel.applet.fish"
54#define FISH_NAME_KEY"name" "name"
55#define FISH_IMAGE_KEY"image" "image"
56#define FISH_COMMAND_KEY"command" "command"
57#define FISH_FRAMES_KEY"frames" "frames"
58#define FISH_SPEED_KEY"speed" "speed"
59#define FISH_ROTATE_KEY"rotate" "rotate"
60
61#define LOCKDOWN_SCHEMA"org.cafe.lockdown" "org.cafe.lockdown"
62#define LOCKDOWN_DISABLE_COMMAND_LINE_KEY"disable-command-line" "disable-command-line"
63
64typedef struct {
65 CafePanelApplet applet;
66
67 GSettings *settings;
68 GSettings *lockdown_settings;
69
70 char *name;
71 char *image;
72 char *command;
73 int n_frames;
74 gdouble speed;
75 gboolean rotate;
76
77 CafePanelAppletOrient orientation;
78
79 CtkWidget *frame;
80 CtkWidget *drawing_area;
81 CtkRequisition requisition;
82 CdkRectangle prev_allocation;
83 cairo_surface_t *surface;
84 gint surface_width;
85 gint surface_height;
86
87 guint timeout;
88 int current_frame;
89 gboolean in_applet;
90
91 GdkPixbuf *pixbuf;
92
93 CtkWidget *preferences_dialog;
94 CtkWidget *name_entry;
95 CtkWidget *command_label;
96 CtkWidget *command_entry;
97 CtkWidget *preview_image;
98 CtkWidget *image_chooser;
99 CtkWidget *frames_spin;
100 CtkWidget *speed_spin;
101 CtkWidget *rotate_toggle;
102
103 CtkWidget *fortune_dialog;
104 CtkWidget *fortune_view;
105 CtkWidget *fortune_label;
106 CtkWidget *fortune_cmd_label;
107 CtkTextBuffer *fortune_buffer;
108
109 unsigned int source_id;
110 GIOChannel *io_channel;
111
112 gboolean april_fools;
113} FishApplet;
114
115typedef struct {
116 CafePanelAppletClass klass;
117} FishAppletClass;
118
119
120static gboolean load_fish_image (FishApplet *fish);
121static void update_pixmap (FishApplet *fish);
122static void something_fishy_going_on (FishApplet *fish, const char *message);
123static void display_fortune_dialog (FishApplet *fish);
124static void set_tooltip (FishApplet *fish);
125
126static GType fish_applet_get_type (void);
127
128static GObjectClass *parent_class;
129
130static int fools_day = 0;
131static int fools_month = 0;
132static int fools_hour_start = 0;
133static int fools_hour_end = 0;
134
135static char* get_image_path(FishApplet* fish)
136{
137 char *path;
138
139 if (g_path_is_absolute (fish->image))
140 path = g_strdup (fish->image)g_strdup_inline (fish->image);
141 else
142 path = g_strdup_printf ("%s/%s", FISH_ICONDIR"/usr/share/cafe-panel/fish", fish->image);
143
144 return path;
145}
146
147static void show_help(FishApplet* fish, const char* link_id)
148{
149 GError *error = NULL((void*)0);
150 char *uri;
151#define FISH_HELP_DOC"cafe-fish" "cafe-fish"
152
153 if (link_id)
154 uri = g_strdup_printf ("help:%s/%s", FISH_HELP_DOC"cafe-fish", link_id);
155 else
156 uri = g_strdup_printf ("help:%s", FISH_HELP_DOC"cafe-fish");
157
158 ctk_show_uri_on_window (NULL((void*)0), uri,
159 ctk_get_current_event_time (), &error);
160 g_free (uri);
161
162 if (error &&
163 g_error_matches (error, G_IO_ERRORg_io_error_quark(), G_IO_ERROR_CANCELLED))
164 g_error_free (error);
165 else if (error) {
166 CtkWidget *dialog;
167 char *primary;
168
169 primary = g_markup_printf_escaped (
170 _("Could not display help document '%s'")gettext ("Could not display help document '%s'"),
171 FISH_HELP_DOC"cafe-fish");
172 dialog = ctk_message_dialog_new (
173 NULL((void*)0),
174 CTK_DIALOG_DESTROY_WITH_PARENT,
175 CTK_MESSAGE_ERROR,
176 CTK_BUTTONS_CLOSE,
177 "%s", primary);
178
179 ctk_message_dialog_format_secondary_text (
180 CTK_MESSAGE_DIALOG (dialog)((((CtkMessageDialog*) (void *) g_type_check_instance_cast ((
GTypeInstance*) ((dialog)), ((ctk_message_dialog_get_type ())
)))))
,
181 "%s", error->message);
182
183 g_error_free (error);
184 g_free (primary);
185
186 g_signal_connect (dialog, "response",g_signal_connect_data ((dialog), ("response"), (((GCallback) (
ctk_widget_destroy))), (((void*)0)), ((void*)0), (GConnectFlags
) 0)
187 G_CALLBACK (ctk_widget_destroy),g_signal_connect_data ((dialog), ("response"), (((GCallback) (
ctk_widget_destroy))), (((void*)0)), ((void*)0), (GConnectFlags
) 0)
188 NULL)g_signal_connect_data ((dialog), ("response"), (((GCallback) (
ctk_widget_destroy))), (((void*)0)), ((void*)0), (GConnectFlags
) 0)
;
189
190 ctk_window_set_icon_name (CTK_WINDOW (dialog)((((CtkWindow*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((dialog)), ((ctk_window_get_type ()))))))
, FISH_ICON"cafe-panel-fish");
191 ctk_window_set_screen (CTK_WINDOW (dialog)((((CtkWindow*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((dialog)), ((ctk_window_get_type ()))))))
,
192 ctk_widget_get_screen (CTK_WIDGET (fish)((((CtkWidget*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((fish)), ((ctk_widget_get_type ()))))))
));
193 /* we have no parent window */
194 ctk_window_set_skip_taskbar_hint (CTK_WINDOW (dialog)((((CtkWindow*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((dialog)), ((ctk_window_get_type ()))))))
, FALSE(0));
195 ctk_window_set_title (CTK_WINDOW (dialog)((((CtkWindow*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((dialog)), ((ctk_window_get_type ()))))))
,
196 _("Error displaying help document")gettext ("Error displaying help document"));
197
198 ctk_widget_show (dialog);
199 }
200}
201
202static void name_value_changed(CtkEntry* entry, FishApplet* fish)
203{
204 const char *text;
205
206 text = ctk_entry_get_text (entry);
207
208 if (!text || !text [0])
209 return;
210
211 g_settings_set_string (fish->settings, FISH_NAME_KEY"name", text);
212}
213
214static void image_value_changed(CtkFileChooser* chooser, FishApplet* fish)
215{ char *path;
216 char *image;
217 char *path_gsettings;
218
219 path = ctk_file_chooser_get_filename (CTK_FILE_CHOOSER (chooser)((((CtkFileChooser*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((chooser)), ((ctk_file_chooser_get_type ()))))))
);
220
221 if (!path || !path[0]) {
222 g_free (path);
223 return;
224 }
225
226 path_gsettings = get_image_path (fish);
227 if (!strcmp (path, path_gsettings)) {
228 g_free (path);
229 g_free (path_gsettings);
230 return;
231 }
232 g_free (path_gsettings);
233
234 if (!strncmp (path, FISH_ICONDIR"/usr/share/cafe-panel/fish", strlen (FISH_ICONDIR"/usr/share/cafe-panel/fish"))) {
235 image = path + strlen (FISH_ICONDIR"/usr/share/cafe-panel/fish");
236 while (*image && *image == G_DIR_SEPARATOR'/')
237 image++;
238 } else
239 image = path;
240
241 g_settings_set_string (fish->settings, FISH_IMAGE_KEY"image", image);
242
243 g_free (path);
244}
245
246static void command_value_changed(CtkEntry* entry, FishApplet *fish)
247{
248 const char *text;
249
250 text = ctk_entry_get_text (entry);
251
252 if (!text || !text [0]) {
253 g_settings_set_string (fish->settings, FISH_COMMAND_KEY"command", "");
254 return;
255 }
256
257 if (!strncmp (text, "ps ", 3) ||
258 !strcmp (text, "ps") ||
259 !strncmp (text, "who ", 4) ||
260 !strcmp (text, "who") ||
261 !strcmp (text, "uptime") ||
262 !strncmp (text, "tail ", 5)) {
263 static gboolean message_given = FALSE(0);
264 const char *warning_format =
265 _("Warning: The command "gettext ("Warning: The command " "appears to be something actually useful.\n"
"Since this is a useless applet, you " "may not want to do this.\n"
"We strongly advise you against " "using %s for anything\n" "which would make the applet "
"\"practical\" or useful.")
266 "appears to be something actually useful.\n"gettext ("Warning: The command " "appears to be something actually useful.\n"
"Since this is a useless applet, you " "may not want to do this.\n"
"We strongly advise you against " "using %s for anything\n" "which would make the applet "
"\"practical\" or useful.")
267 "Since this is a useless applet, you "gettext ("Warning: The command " "appears to be something actually useful.\n"
"Since this is a useless applet, you " "may not want to do this.\n"
"We strongly advise you against " "using %s for anything\n" "which would make the applet "
"\"practical\" or useful.")
268 "may not want to do this.\n"gettext ("Warning: The command " "appears to be something actually useful.\n"
"Since this is a useless applet, you " "may not want to do this.\n"
"We strongly advise you against " "using %s for anything\n" "which would make the applet "
"\"practical\" or useful.")
269 "We strongly advise you against "gettext ("Warning: The command " "appears to be something actually useful.\n"
"Since this is a useless applet, you " "may not want to do this.\n"
"We strongly advise you against " "using %s for anything\n" "which would make the applet "
"\"practical\" or useful.")
270 "using %s for anything\n"gettext ("Warning: The command " "appears to be something actually useful.\n"
"Since this is a useless applet, you " "may not want to do this.\n"
"We strongly advise you against " "using %s for anything\n" "which would make the applet "
"\"practical\" or useful.")
271 "which would make the applet "gettext ("Warning: The command " "appears to be something actually useful.\n"
"Since this is a useless applet, you " "may not want to do this.\n"
"We strongly advise you against " "using %s for anything\n" "which would make the applet "
"\"practical\" or useful.")
272 "\"practical\" or useful.")gettext ("Warning: The command " "appears to be something actually useful.\n"
"Since this is a useless applet, you " "may not want to do this.\n"
"We strongly advise you against " "using %s for anything\n" "which would make the applet "
"\"practical\" or useful.")
;
273
274 if ( ! message_given) {
275 char *message;
276
277 message = g_strdup_printf (warning_format, fish->name);
278
279 something_fishy_going_on (fish, message);
280
281 g_free (message);
282
283 message_given = TRUE(!(0));
284 }
285 }
286
287 g_settings_set_string (fish->settings, FISH_COMMAND_KEY"command", text);
288}
289
290static void n_frames_value_changed(CtkSpinButton* button, FishApplet* fish)
291{
292 g_settings_set_int (
293 fish->settings,
294 FISH_FRAMES_KEY"frames",
295 ctk_spin_button_get_value_as_int (button));
296}
297
298static void speed_value_changed (CtkSpinButton* button, FishApplet* fish)
299{
300 g_settings_set_double (
301 fish->settings,
302 FISH_SPEED_KEY"speed",
303 ctk_spin_button_get_value (button));
304}
305
306static void rotate_value_changed(CtkToggleButton* toggle, FishApplet* fish)
307{
308 g_settings_set_boolean (
309 fish->settings,
310 FISH_ROTATE_KEY"rotate",
311 ctk_toggle_button_get_active (toggle));
312}
313
314static gboolean delete_event(CtkWidget *widget,
315 FishApplet *fish G_GNUC_UNUSED__attribute__ ((__unused__)))
316{
317 ctk_widget_hide (widget);
318
319 return TRUE(!(0));
320}
321
322static void handle_response (CtkWidget *widget G_GNUC_UNUSED__attribute__ ((__unused__)),
323 int id,
324 FishApplet *fish)
325{
326 if (id == CTK_RESPONSE_HELP) {
327 show_help (fish, "fish-settings");
328 return;
329 }
330
331 ctk_widget_hide (fish->preferences_dialog);
332}
333
334static void setup_sensitivity(FishApplet* fish, CtkBuilder* builder, const char* wid, const char* label, const char* label_post, const char* key)
335{
336 CtkWidget *w;
337
338 if (g_settings_is_writable (fish->settings, key)) {
339 return;
340 }
341
342 w = CTK_WIDGET (ctk_builder_get_object (builder, wid))((((CtkWidget*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((ctk_builder_get_object (builder, wid))), ((ctk_widget_get_type
()))))))
;
343 g_assert (w != NULL)do { if (w != ((void*)0)) ; else g_assertion_message_expr (((
gchar*) 0), "fish.c", 343, ((const char*) (__func__)), "w != NULL"
); } while (0)
;
344 ctk_widget_set_sensitive (w, FALSE(0));
345
346 if (label != NULL((void*)0)) {
347 w = CTK_WIDGET (ctk_builder_get_object (builder, label))((((CtkWidget*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((ctk_builder_get_object (builder, label))), ((ctk_widget_get_type
()))))))
;
348 g_assert (w != NULL)do { if (w != ((void*)0)) ; else g_assertion_message_expr (((
gchar*) 0), "fish.c", 348, ((const char*) (__func__)), "w != NULL"
); } while (0)
;
349 ctk_widget_set_sensitive (w, FALSE(0));
350 }
351 if (label_post != NULL((void*)0)) {
352 w = CTK_WIDGET (ctk_builder_get_object (builder, label_post))((((CtkWidget*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((ctk_builder_get_object (builder, label_post))), ((ctk_widget_get_type
()))))))
;
353 g_assert (w != NULL)do { if (w != ((void*)0)) ; else g_assertion_message_expr (((
gchar*) 0), "fish.c", 353, ((const char*) (__func__)), "w != NULL"
); } while (0)
;
354 ctk_widget_set_sensitive (w, FALSE(0));
355 }
356
357}
358
359static void chooser_preview_update(CtkFileChooser* file_chooser, gpointer data)
360{
361 CtkWidget *preview;
362 char *filename;
363 GdkPixbuf *pixbuf;
364 gboolean have_preview;
365
366 preview = CTK_WIDGET (data)((((CtkWidget*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((data)), ((ctk_widget_get_type ()))))))
;
367 filename = ctk_file_chooser_get_preview_filename (file_chooser);
368
369 if (filename == NULL((void*)0))
370 return;
371
372 pixbuf = gdk_pixbuf_new_from_file_at_size (filename, 128, 128, NULL((void*)0));
373 have_preview = (pixbuf != NULL((void*)0));
374 g_free (filename);
375
376 ctk_image_set_from_pixbuf (CTK_IMAGE (preview)((((CtkImage*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((preview)), ((ctk_image_get_type ()))))))
, pixbuf);
377 if (pixbuf)
378 g_object_unref (pixbuf);
379
380 ctk_file_chooser_set_preview_widget_active (file_chooser,
381 have_preview);
382}
383
384static void display_preferences_dialog (CtkAction *action G_GNUC_UNUSED__attribute__ ((__unused__)),
385 FishApplet *fish)
386{
387 CtkBuilder *builder;
388 CtkWidget *button;
389 CtkFileFilter *filter;
390 CtkWidget *chooser_preview;
391 char *path;
392
393 if (fish->preferences_dialog) {
394 ctk_window_set_screen (CTK_WINDOW (fish->preferences_dialog)((((CtkWindow*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((fish->preferences_dialog)), ((ctk_window_get_type ())
)))))
,
395 ctk_widget_get_screen (CTK_WIDGET (fish)((((CtkWidget*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((fish)), ((ctk_widget_get_type ()))))))
));
396 ctk_window_present (CTK_WINDOW (fish->preferences_dialog)((((CtkWindow*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((fish->preferences_dialog)), ((ctk_window_get_type ())
)))))
);
397 return;
398 }
399
400 builder = ctk_builder_new ();
401 ctk_builder_set_translation_domain (builder, GETTEXT_PACKAGE"cafe-panel");
402 ctk_builder_add_from_resource (builder, FISH_RESOURCE_PATH"/org/cafe/panel/applet/fish/" "fish.ui", NULL((void*)0));
403
404 fish->preferences_dialog = CTK_WIDGET (ctk_builder_get_object (builder, "fish_preferences_dialog"))((((CtkWidget*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((ctk_builder_get_object (builder, "fish_preferences_dialog"
))), ((ctk_widget_get_type ()))))))
;
405
406 g_object_add_weak_pointer (G_OBJECT (fish->preferences_dialog)((((GObject*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((fish->preferences_dialog)), (((GType) ((20) << (
2))))))))
,
407 (void**) &fish->preferences_dialog);
408
409 ctk_window_set_icon_name (CTK_WINDOW (fish->preferences_dialog)((((CtkWindow*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((fish->preferences_dialog)), ((ctk_window_get_type ())
)))))
,
410 FISH_ICON"cafe-panel-fish");
411 ctk_dialog_set_default_response (
412 CTK_DIALOG (fish->preferences_dialog)((((CtkDialog*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((fish->preferences_dialog)), ((ctk_dialog_get_type ())
)))))
, CTK_RESPONSE_OK);
413
414 fish->name_entry = CTK_WIDGET (ctk_builder_get_object (builder, "name_entry"))((((CtkWidget*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((ctk_builder_get_object (builder, "name_entry"))), ((ctk_widget_get_type
()))))))
;
415 ctk_entry_set_text (CTK_ENTRY (fish->name_entry)((((CtkEntry*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((fish->name_entry)), ((ctk_entry_get_type ()))))))
, fish->name);
416
417 g_signal_connect (fish->name_entry, "changed",g_signal_connect_data ((fish->name_entry), ("changed"), ((
(GCallback) (name_value_changed))), (fish), ((void*)0), (GConnectFlags
) 0)
418 G_CALLBACK (name_value_changed), fish)g_signal_connect_data ((fish->name_entry), ("changed"), ((
(GCallback) (name_value_changed))), (fish), ((void*)0), (GConnectFlags
) 0)
;
419
420 setup_sensitivity (fish, builder,
421 "name_entry" /* wid */,
422 "name_label" /* label */,
423 NULL((void*)0) /* label_post */,
424 FISH_NAME_KEY"name" /* key */);
425
426 fish->preview_image = CTK_WIDGET (ctk_builder_get_object (builder, "preview_image"))((((CtkWidget*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((ctk_builder_get_object (builder, "preview_image"))), ((ctk_widget_get_type
()))))))
;
427 if (fish->pixbuf)
428 ctk_image_set_from_pixbuf (CTK_IMAGE (fish->preview_image)((((CtkImage*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((fish->preview_image)), ((ctk_image_get_type ()))))))
,
429 fish->pixbuf);
430
431 fish->image_chooser = CTK_WIDGET (ctk_builder_get_object (builder, "image_chooser"))((((CtkWidget*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((ctk_builder_get_object (builder, "image_chooser"))), ((ctk_widget_get_type
()))))))
;
432 filter = ctk_file_filter_new ();
433 ctk_file_filter_set_name (filter, _("Images")gettext ("Images"));
434 ctk_file_filter_add_pixbuf_formats (filter);
435 ctk_file_chooser_add_filter (CTK_FILE_CHOOSER (fish->image_chooser)((((CtkFileChooser*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((fish->image_chooser)), ((ctk_file_chooser_get_type ()
))))))
,
436 filter);
437 ctk_file_chooser_set_filter (CTK_FILE_CHOOSER (fish->image_chooser)((((CtkFileChooser*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((fish->image_chooser)), ((ctk_file_chooser_get_type ()
))))))
,
438 filter);
439 chooser_preview = ctk_image_new ();
440 ctk_file_chooser_set_preview_widget (CTK_FILE_CHOOSER (fish->image_chooser)((((CtkFileChooser*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((fish->image_chooser)), ((ctk_file_chooser_get_type ()
))))))
,
441 chooser_preview);
442 g_signal_connect (fish->image_chooser, "update-preview",g_signal_connect_data ((fish->image_chooser), ("update-preview"
), (((GCallback) (chooser_preview_update))), (chooser_preview
), ((void*)0), (GConnectFlags) 0)
443 G_CALLBACK (chooser_preview_update), chooser_preview)g_signal_connect_data ((fish->image_chooser), ("update-preview"
), (((GCallback) (chooser_preview_update))), (chooser_preview
), ((void*)0), (GConnectFlags) 0)
;
444 path = get_image_path (fish);
445 ctk_file_chooser_set_filename (CTK_FILE_CHOOSER (fish->image_chooser)((((CtkFileChooser*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((fish->image_chooser)), ((ctk_file_chooser_get_type ()
))))))
,
446 path);
447 g_free (path);
448
449 g_signal_connect (fish->image_chooser, "selection-changed",g_signal_connect_data ((fish->image_chooser), ("selection-changed"
), (((GCallback) (image_value_changed))), (fish), ((void*)0),
(GConnectFlags) 0)
450 G_CALLBACK (image_value_changed), fish)g_signal_connect_data ((fish->image_chooser), ("selection-changed"
), (((GCallback) (image_value_changed))), (fish), ((void*)0),
(GConnectFlags) 0)
;
451
452 setup_sensitivity (fish, builder,
453 "image_chooser" /* wid */,
454 "image_label" /* label */,
455 NULL((void*)0) /* label_post */,
456 FISH_IMAGE_KEY"image" /* key */);
457
458 fish->command_label = CTK_WIDGET (ctk_builder_get_object (builder, "command_label"))((((CtkWidget*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((ctk_builder_get_object (builder, "command_label"))), ((ctk_widget_get_type
()))))))
;
459 fish->command_entry = CTK_WIDGET (ctk_builder_get_object (builder, "command_entry"))((((CtkWidget*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((ctk_builder_get_object (builder, "command_entry"))), ((ctk_widget_get_type
()))))))
;
460 ctk_entry_set_text (CTK_ENTRY (fish->command_entry)((((CtkEntry*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((fish->command_entry)), ((ctk_entry_get_type ()))))))
, fish->command);
461
462 g_signal_connect (fish->command_entry, "changed",g_signal_connect_data ((fish->command_entry), ("changed"),
(((GCallback) (command_value_changed))), (fish), ((void*)0),
(GConnectFlags) 0)
463 G_CALLBACK (command_value_changed), fish)g_signal_connect_data ((fish->command_entry), ("changed"),
(((GCallback) (command_value_changed))), (fish), ((void*)0),
(GConnectFlags) 0)
;
464
465 setup_sensitivity (fish, builder,
466 "command_entry" /* wid */,
467 "command_label" /* label */,
468 NULL((void*)0) /* label_post */,
469 FISH_COMMAND_KEY"command" /* key */);
470
471 if (g_settings_get_boolean (fish->lockdown_settings, LOCKDOWN_DISABLE_COMMAND_LINE_KEY"disable-command-line")) {
472 ctk_widget_set_sensitive (fish->command_label, FALSE(0));
473 ctk_widget_set_sensitive (fish->command_entry, FALSE(0));
474 }
475
476 fish->frames_spin = CTK_WIDGET (ctk_builder_get_object (builder, "frames_spin"))((((CtkWidget*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((ctk_builder_get_object (builder, "frames_spin"))), ((ctk_widget_get_type
()))))))
;
477 ctk_spin_button_set_value (CTK_SPIN_BUTTON (fish->frames_spin)((((CtkSpinButton*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((fish->frames_spin)), ((ctk_spin_button_get_type ())))
)))
,
478 fish->n_frames);
479
480 g_signal_connect (fish->frames_spin, "value_changed",g_signal_connect_data ((fish->frames_spin), ("value_changed"
), (((GCallback) (n_frames_value_changed))), (fish), ((void*)
0), (GConnectFlags) 0)
481 G_CALLBACK (n_frames_value_changed), fish)g_signal_connect_data ((fish->frames_spin), ("value_changed"
), (((GCallback) (n_frames_value_changed))), (fish), ((void*)
0), (GConnectFlags) 0)
;
482
483 setup_sensitivity (fish, builder,
484 "frames_spin" /* wid */,
485 "frames_label" /* label */,
486 "frames_post_label" /* label_post */,
487 FISH_FRAMES_KEY"frames" /* key */);
488
489 fish->speed_spin = CTK_WIDGET (ctk_builder_get_object (builder, "speed_spin"))((((CtkWidget*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((ctk_builder_get_object (builder, "speed_spin"))), ((ctk_widget_get_type
()))))))
;
490 ctk_spin_button_set_value (CTK_SPIN_BUTTON (fish->speed_spin)((((CtkSpinButton*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((fish->speed_spin)), ((ctk_spin_button_get_type ()))))
))
, fish->speed);
491
492 g_signal_connect (fish->speed_spin, "value_changed",g_signal_connect_data ((fish->speed_spin), ("value_changed"
), (((GCallback) (speed_value_changed))), (fish), ((void*)0),
(GConnectFlags) 0)
493 G_CALLBACK (speed_value_changed), fish)g_signal_connect_data ((fish->speed_spin), ("value_changed"
), (((GCallback) (speed_value_changed))), (fish), ((void*)0),
(GConnectFlags) 0)
;
494
495 setup_sensitivity (fish, builder,
496 "speed_spin" /* wid */,
497 "speed_label" /* label */,
498 "speed_post_label" /* label_post */,
499 FISH_SPEED_KEY"speed" /* key */);
500
501 fish->rotate_toggle = CTK_WIDGET (ctk_builder_get_object (builder, "rotate_toggle"))((((CtkWidget*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((ctk_builder_get_object (builder, "rotate_toggle"))), ((ctk_widget_get_type
()))))))
;
502 ctk_toggle_button_set_active (
503 CTK_TOGGLE_BUTTON (fish->rotate_toggle)((((CtkToggleButton*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((fish->rotate_toggle)), ((ctk_toggle_button_get_type (
)))))))
, fish->rotate);
504
505 g_signal_connect (fish->rotate_toggle, "toggled",g_signal_connect_data ((fish->rotate_toggle), ("toggled"),
(((GCallback) (rotate_value_changed))), (fish), ((void*)0), (
GConnectFlags) 0)
506 G_CALLBACK (rotate_value_changed), fish)g_signal_connect_data ((fish->rotate_toggle), ("toggled"),
(((GCallback) (rotate_value_changed))), (fish), ((void*)0), (
GConnectFlags) 0)
;
507
508 setup_sensitivity (fish, builder,
509 "rotate_toggle" /* wid */,
510 NULL((void*)0) /* label */,
511 NULL((void*)0) /* label_post */,
512 FISH_ROTATE_KEY"rotate" /* key */);
513
514 g_signal_connect (fish->preferences_dialog, "delete_event",g_signal_connect_data ((fish->preferences_dialog), ("delete_event"
), (((GCallback) (delete_event))), (fish), ((void*)0), (GConnectFlags
) 0)
515 G_CALLBACK (delete_event), fish)g_signal_connect_data ((fish->preferences_dialog), ("delete_event"
), (((GCallback) (delete_event))), (fish), ((void*)0), (GConnectFlags
) 0)
;
516 g_signal_connect (fish->preferences_dialog, "response",g_signal_connect_data ((fish->preferences_dialog), ("response"
), (((GCallback) (handle_response))), (fish), ((void*)0), (GConnectFlags
) 0)
517 G_CALLBACK (handle_response), fish)g_signal_connect_data ((fish->preferences_dialog), ("response"
), (((GCallback) (handle_response))), (fish), ((void*)0), (GConnectFlags
) 0)
;
518
519 button = CTK_WIDGET (ctk_builder_get_object (builder, "done_button"))((((CtkWidget*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((ctk_builder_get_object (builder, "done_button"))), ((ctk_widget_get_type
()))))))
;
520 g_signal_connect_swapped (button, "clicked",g_signal_connect_data ((button), ("clicked"), ((GCallback) ctk_widget_hide
), (fish->preferences_dialog), ((void*)0), G_CONNECT_SWAPPED
)
521 (GCallback) ctk_widget_hide,g_signal_connect_data ((button), ("clicked"), ((GCallback) ctk_widget_hide
), (fish->preferences_dialog), ((void*)0), G_CONNECT_SWAPPED
)
522 fish->preferences_dialog)g_signal_connect_data ((button), ("clicked"), ((GCallback) ctk_widget_hide
), (fish->preferences_dialog), ((void*)0), G_CONNECT_SWAPPED
)
;
523
524 ctk_window_set_screen (CTK_WINDOW (fish->preferences_dialog)((((CtkWindow*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((fish->preferences_dialog)), ((ctk_window_get_type ())
)))))
,
525 ctk_widget_get_screen (CTK_WIDGET (fish)((((CtkWidget*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((fish)), ((ctk_widget_get_type ()))))))
));
526 ctk_window_set_resizable (CTK_WINDOW (fish->preferences_dialog)((((CtkWindow*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((fish->preferences_dialog)), ((ctk_window_get_type ())
)))))
, FALSE(0));
527 ctk_window_present (CTK_WINDOW (fish->preferences_dialog)((((CtkWindow*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((fish->preferences_dialog)), ((ctk_window_get_type ())
)))))
);
528
529 g_object_unref (builder);
530}
531
532static void display_help_dialog (CtkAction *action G_GNUC_UNUSED__attribute__ ((__unused__)),
533 FishApplet *fish)
534{
535 show_help(fish, NULL((void*)0));
536}
537
538static void display_about_dialog (CtkAction *action G_GNUC_UNUSED__attribute__ ((__unused__)),
539 FishApplet *fish)
540{
541 const char* author_format = _("%s the Fish")gettext ("%s the Fish");
542 const char* about_format = _("%s has no use what-so-ever. "gettext ("%s has no use what-so-ever. " "It only takes up disk space and "
"compilation time, and if loaded it also " "takes up precious panel space and "
"memory. Anybody found using it should be " "promptly sent for a psychiatric "
"evaluation.")
543 "It only takes up disk space and "gettext ("%s has no use what-so-ever. " "It only takes up disk space and "
"compilation time, and if loaded it also " "takes up precious panel space and "
"memory. Anybody found using it should be " "promptly sent for a psychiatric "
"evaluation.")
544 "compilation time, and if loaded it also "gettext ("%s has no use what-so-ever. " "It only takes up disk space and "
"compilation time, and if loaded it also " "takes up precious panel space and "
"memory. Anybody found using it should be " "promptly sent for a psychiatric "
"evaluation.")
545 "takes up precious panel space and "gettext ("%s has no use what-so-ever. " "It only takes up disk space and "
"compilation time, and if loaded it also " "takes up precious panel space and "
"memory. Anybody found using it should be " "promptly sent for a psychiatric "
"evaluation.")
546 "memory. Anybody found using it should be "gettext ("%s has no use what-so-ever. " "It only takes up disk space and "
"compilation time, and if loaded it also " "takes up precious panel space and "
"memory. Anybody found using it should be " "promptly sent for a psychiatric "
"evaluation.")
547 "promptly sent for a psychiatric "gettext ("%s has no use what-so-ever. " "It only takes up disk space and "
"compilation time, and if loaded it also " "takes up precious panel space and "
"memory. Anybody found using it should be " "promptly sent for a psychiatric "
"evaluation.")
548 "evaluation.")gettext ("%s has no use what-so-ever. " "It only takes up disk space and "
"compilation time, and if loaded it also " "takes up precious panel space and "
"memory. Anybody found using it should be " "promptly sent for a psychiatric "
"evaluation.")
;
549 const char* documenters [] = {
550 "Telsa Gwynne <hobbit@aloss.ukuu.org.uk>",
551 "Sun GNOME Documentation Team <gdocteam@sun.com>",
552 NULL((void*)0)
553 };
554
555 char* authors[3];
556 char* descr;
557
558 authors[0] = g_strdup_printf(author_format, fish->name);
559 authors[1] = _("(with minor help from George)")gettext ("(with minor help from George)");
560 authors[2] = NULL((void*)0);
561
562 descr = g_strdup_printf(about_format, fish->name);
563
564 ctk_show_about_dialog(NULL((void*)0),
565 "program-name", _("Fish")gettext ("Fish"),
566 "title", _("About Fish")gettext ("About Fish"),
567 "authors", authors,
568 "comments", descr,
569 "copyright", _("Copyright \xc2\xa9 1998-2002 Free Software Foundation, Inc.\n"gettext ("Copyright \xc2\xa9 1998-2002 Free Software Foundation, Inc.\n"
"Copyright \xc2\xa9 2002-2005 Vincent Untz\n" "Copyright \xc2\xa9 2012-2020 MATE developers\n"
"Copyright \xc2\xa9 2022-2025 Pablo Barciela")
570 "Copyright \xc2\xa9 2002-2005 Vincent Untz\n"gettext ("Copyright \xc2\xa9 1998-2002 Free Software Foundation, Inc.\n"
"Copyright \xc2\xa9 2002-2005 Vincent Untz\n" "Copyright \xc2\xa9 2012-2020 MATE developers\n"
"Copyright \xc2\xa9 2022-2025 Pablo Barciela")
571 "Copyright \xc2\xa9 2012-2020 MATE developers\n"gettext ("Copyright \xc2\xa9 1998-2002 Free Software Foundation, Inc.\n"
"Copyright \xc2\xa9 2002-2005 Vincent Untz\n" "Copyright \xc2\xa9 2012-2020 MATE developers\n"
"Copyright \xc2\xa9 2022-2025 Pablo Barciela")
572 "Copyright \xc2\xa9 2022-2025 Pablo Barciela")gettext ("Copyright \xc2\xa9 1998-2002 Free Software Foundation, Inc.\n"
"Copyright \xc2\xa9 2002-2005 Vincent Untz\n" "Copyright \xc2\xa9 2012-2020 MATE developers\n"
"Copyright \xc2\xa9 2022-2025 Pablo Barciela")
,
573 "documenters", documenters,
574 "logo-icon-name", FISH_ICON"cafe-panel-fish",
575 "translator-credits", _("translator-credits")gettext ("translator-credits"),
576 "version", VERSION"1.25.0", // "3.4.7.4ac19"
577 "website", "http://cafe-desktop.org/",
578 NULL((void*)0));
579
580 g_free(descr);
581 g_free(authors[0]);
582}
583
584static void set_ally_name_desc(CtkWidget* widget, FishApplet* fish)
585{
586 const char *name_format = _("%s the Fish")gettext ("%s the Fish");
587 const char *desc_format = _("%s the Fish, a contemporary oracle")gettext ("%s the Fish, a contemporary oracle");
588 AtkObject *obj;
589 char *desc, *name;
590
591 obj = ctk_widget_get_accessible (widget);
592 /* Return immediately if GAIL is not loaded */
593 if (!CTK_IS_ACCESSIBLE (obj)(((__extension__ ({ GTypeInstance *__inst = (GTypeInstance*) (
(obj)); GType __t = ((ctk_accessible_get_type ())); gboolean __r
; if (!__inst) __r = (0); else if (__inst->g_class &&
__inst->g_class->g_type == __t) __r = (!(0)); else __r
= g_type_check_instance_is_a (__inst, __t); __r; }))))
)
594 return;
595
596 name = g_strdup_printf (name_format, fish->name);
597 atk_object_set_name (obj, name);
598 g_free (name);
599
600 desc = g_strdup_printf (desc_format, fish->name);
601 atk_object_set_description (obj, desc);
602 g_free (desc);
603}
604
605static void something_fishy_going_on(FishApplet* fish, const char* message)
606{
607 CtkWidget *dialog;
608
609 dialog = ctk_message_dialog_new (NULL((void*)0),
610 CTK_DIALOG_DESTROY_WITH_PARENT,
611 CTK_MESSAGE_ERROR,
612 CTK_BUTTONS_CLOSE,
613 "%s", message);
614
615 g_signal_connect (dialog, "response",g_signal_connect_data ((dialog), ("response"), (((GCallback) (
ctk_widget_destroy))), (((void*)0)), ((void*)0), (GConnectFlags
) 0)
616 G_CALLBACK (ctk_widget_destroy),g_signal_connect_data ((dialog), ("response"), (((GCallback) (
ctk_widget_destroy))), (((void*)0)), ((void*)0), (GConnectFlags
) 0)
617 NULL)g_signal_connect_data ((dialog), ("response"), (((GCallback) (
ctk_widget_destroy))), (((void*)0)), ((void*)0), (GConnectFlags
) 0)
;
618
619 ctk_window_set_icon_name (CTK_WINDOW (dialog)((((CtkWindow*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((dialog)), ((ctk_window_get_type ()))))))
, FISH_ICON"cafe-panel-fish");
620 ctk_window_set_resizable (CTK_WINDOW (dialog)((((CtkWindow*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((dialog)), ((ctk_window_get_type ()))))))
, FALSE(0));
621 ctk_window_set_screen (CTK_WINDOW (dialog)((((CtkWindow*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((dialog)), ((ctk_window_get_type ()))))))
,
622 ctk_widget_get_screen (CTK_WIDGET (fish)((((CtkWidget*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((fish)), ((ctk_widget_get_type ()))))))
));
623 ctk_widget_show (dialog);
624}
625
626static gboolean locate_fortune_command (FishApplet* fish, int* argcp, char*** argvp)
627{
628 char *prog = NULL((void*)0);
629
630 if (fish->command
631 && g_shell_parse_argv (fish->command, argcp, argvp, NULL((void*)0))) {
632 prog = g_find_program_in_path ((*argvp)[0]);
633 if (prog) {
634 g_free (prog);
635 return TRUE(!(0));
636 }
637
638 g_strfreev (*argvp);
639 }
640
641 prog = g_find_program_in_path ("fortune");
642 if (prog) {
643 g_free (prog);
644 if (g_shell_parse_argv ("fortune", argcp, argvp, NULL((void*)0)))
645 return FALSE(0);
646 }
647
648 if (g_file_test ("/usr/games/fortune", G_FILE_TEST_IS_EXECUTABLE)
649 && g_shell_parse_argv ("/usr/games/fortune", argcp, argvp, NULL((void*)0)))
650 return FALSE(0);
651
652 something_fishy_going_on (fish,
653 _("Unable to locate the command to execute")gettext ("Unable to locate the command to execute"));
654 *argvp = NULL((void*)0);
655 return FALSE(0);
656}
657
658#define FISH_RESPONSE_SPEAK1 1
659static inline void fish_close_channel(FishApplet* fish)
660{
661 if (fish->io_channel) {
662 g_io_channel_shutdown (fish->io_channel, TRUE(!(0)), NULL((void*)0));
663 g_io_channel_unref (fish->io_channel);
664 }
665 fish->io_channel = NULL((void*)0);
666}
667
668static void handle_fortune_response (CtkWidget *widget G_GNUC_UNUSED__attribute__ ((__unused__)),
669 int id,
670 FishApplet *fish)
671{
672 if (id == FISH_RESPONSE_SPEAK1)
673 display_fortune_dialog (fish);
674 else {
675 /* if there is still a pipe, close it: if we hide the widget,
676 * the * output can't be seen */
677 if (fish->source_id)
678 g_source_remove (fish->source_id);
679 fish->source_id = 0;
680 fish_close_channel (fish);
681 ctk_widget_hide (fish->fortune_dialog);
682 }
683}
684
685static void update_fortune_dialog(FishApplet* fish)
686{
687 char *label_text;
688 char *text;
689
690 if (!fish->fortune_dialog || !fish->name)
691 return;
692
693 /* xgettext:no-c-format */
694 text = g_strdup_printf (_("%s the Fish")gettext ("%s the Fish"), fish->name);
695 ctk_window_set_title (CTK_WINDOW (fish->fortune_dialog)((((CtkWindow*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((fish->fortune_dialog)), ((ctk_window_get_type ())))))
)
, text);
696 g_free (text);
697
698 /* xgettext:no-c-format */
699 label_text = g_strdup_printf (_("%s the Fish Says:")gettext ("%s the Fish Says:"), fish->name);
700
701 text = g_strdup_printf ("<big><big>%s</big></big>", label_text);
702 ctk_label_set_markup (CTK_LABEL (fish->fortune_label)((((CtkLabel*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((fish->fortune_label)), ((ctk_label_get_type ()))))))
, text);
703 g_free (text);
704
705 g_free (label_text);
706
707 set_ally_name_desc (fish->fortune_view, fish);
708}
709
710static void insert_fortune_text(FishApplet* fish, const char* text)
711{
712 CtkTextIter iter;
713
714 ctk_text_buffer_get_iter_at_offset (fish->fortune_buffer, &iter, -1);
715
716 ctk_text_buffer_insert_with_tags_by_name (fish->fortune_buffer, &iter,
717 text, -1, "monospace_tag",
718 NULL((void*)0));
719
720 while (ctk_events_pending ())
721 ctk_main_iteration ();
722}
723
724static void clear_fortune_text(FishApplet* fish)
725{
726 CtkTextIter begin, end;
727
728 ctk_text_buffer_get_iter_at_offset (fish->fortune_buffer, &begin, 0);
729 ctk_text_buffer_get_iter_at_offset (fish->fortune_buffer, &end, -1);
730
731 ctk_text_buffer_delete (fish->fortune_buffer, &begin, &end);
732 ctk_text_buffer_remove_tag_by_name (fish->fortune_buffer,
733 "monospace_tag", &begin, &end);
734
735 /* insert an empty line */
736 insert_fortune_text (fish, "\n");
737}
738
739static gboolean fish_read_output(GIOChannel* source, GIOCondition condition, gpointer data)
740{
741 char output[4096];
742 gsize bytes_read;
743 GError *error = NULL((void*)0);
744 GIOStatus status;
745 FishApplet *fish;
746
747 fish = (FishApplet *) data;
748
749 if (!(condition & G_IO_IN)) {
750 fish->source_id = 0;
751 fish_close_channel (fish);
752 return FALSE(0);
753 }
754
755 status = g_io_channel_read_chars (source, output, 4096, &bytes_read,
756 &error);
757
758 if (error) {
759 char *message;
760
761 message = g_strdup_printf (_("Unable to read output from command\n\nDetails: %s")gettext ("Unable to read output from command\n\nDetails: %s"),
762 error->message);
763 something_fishy_going_on (fish, message);
764 g_free (message);
765 g_error_free (error);
766 fish->source_id = 0;
767 fish_close_channel (fish);
768 return FALSE(0);
769 }
770
771 if (status == G_IO_STATUS_AGAIN)
772 return TRUE(!(0));
773
774 if (bytes_read > 0) {
775 /* The output is not guarantied to be in UTF-8 format, most
776 * likely it's just in ASCII-7 or in the user locale
777 */
778 char *utf8_output;
779
780 if (!g_utf8_validate (output, -1, NULL((void*)0)))
781 utf8_output = g_locale_to_utf8 (output, bytes_read,
782 NULL((void*)0), NULL((void*)0), NULL((void*)0));
783 else
784 utf8_output = g_strndup (output, bytes_read);
785
786 if (utf8_output)
787 insert_fortune_text (fish, utf8_output);
788
789 g_free (utf8_output);
790 }
791
792 if (status == G_IO_STATUS_EOF) {
793 fish->source_id = 0;
794 fish_close_channel (fish);
795 }
796 return (status != G_IO_STATUS_EOF);
797}
798
799/*
800 * Set the DISPLAY variable, to be use by g_spawn_async.
801 */
802static void
803set_environment (gpointer display)
804{
805 g_setenv ("DISPLAY", display, TRUE(!(0)));
806}
807
808static CtkWidget*
809panel_dialog_add_button (CtkDialog *dialog,
810 const gchar *button_text,
811 const gchar *icon_name,
812 gint response_id)
813{
814 CtkWidget *button;
815
816 button = ctk_button_new_with_mnemonic (button_text);
817 ctk_button_set_image (CTK_BUTTON (button)((((CtkButton*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((button)), ((ctk_button_get_type ()))))))
, ctk_image_new_from_icon_name (icon_name, CTK_ICON_SIZE_BUTTON));
818
819 ctk_button_set_use_underline (CTK_BUTTON (button)((((CtkButton*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((button)), ((ctk_button_get_type ()))))))
, TRUE(!(0)));
820 ctk_style_context_add_class (ctk_widget_get_style_context (button), "text-button");
821 ctk_widget_set_can_default (button, TRUE(!(0)));
822 ctk_widget_show (button);
823 ctk_dialog_add_action_widget (CTK_DIALOG (dialog)((((CtkDialog*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((dialog)), ((ctk_dialog_get_type ()))))))
, button, response_id);
824
825 return button;
826}
827
828static void display_fortune_dialog(FishApplet* fish)
829{
830 GError *error = NULL((void*)0);
831 gboolean user_command;
832 int output;
833 const char *charset;
834 int argc;
835 char **argv;
836 CdkDisplay *display;
837 CdkScreen *screen;
838 char *display_name;
839
840 /* if there is still a pipe, close it */
841 if (fish->source_id)
842 g_source_remove (fish->source_id);
843 fish->source_id = 0;
844 fish_close_channel (fish);
845
846 user_command = locate_fortune_command (fish, &argc, &argv);
847 if (!argv)
848 return;
849
850 if (!fish->fortune_dialog) {
851 CtkWidget *scrolled;
852 CtkWidget *vbox;
853 CdkMonitor *monitor;
854 CdkRectangle monitor_geom;
855
856 fish->fortune_dialog = ctk_dialog_new ();
857 ctk_window_set_title (CTK_WINDOW (fish->fortune_dialog)((((CtkWindow*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((fish->fortune_dialog)), ((ctk_window_get_type ())))))
)
, "");
858
859 ctk_dialog_add_button (CTK_DIALOG (fish->fortune_dialog)((((CtkDialog*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((fish->fortune_dialog)), ((ctk_dialog_get_type ())))))
)
,
860 _("_Speak again")gettext ("_Speak again"),
861 FISH_RESPONSE_SPEAK1);
862
863 panel_dialog_add_button (CTK_DIALOG (fish->fortune_dialog)((((CtkDialog*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((fish->fortune_dialog)), ((ctk_dialog_get_type ())))))
)
,
864 _("_Close")gettext ("_Close"), "window-close",
865 CTK_RESPONSE_CLOSE);
866
867 ctk_window_set_icon_name (CTK_WINDOW (fish->fortune_dialog)((((CtkWindow*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((fish->fortune_dialog)), ((ctk_window_get_type ())))))
)
,
868 FISH_ICON"cafe-panel-fish");
869
870 ctk_dialog_set_default_response (
871 CTK_DIALOG (fish->fortune_dialog)((((CtkDialog*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((fish->fortune_dialog)), ((ctk_dialog_get_type ())))))
)
, CTK_RESPONSE_CLOSE);
872
873 g_signal_connect (fish->fortune_dialog, "delete_event",g_signal_connect_data ((fish->fortune_dialog), ("delete_event"
), (((GCallback) (delete_event))), (fish), ((void*)0), (GConnectFlags
) 0)
874 G_CALLBACK (delete_event), fish)g_signal_connect_data ((fish->fortune_dialog), ("delete_event"
), (((GCallback) (delete_event))), (fish), ((void*)0), (GConnectFlags
) 0)
;
875 g_signal_connect (fish->fortune_dialog, "response",g_signal_connect_data ((fish->fortune_dialog), ("response"
), (((GCallback) (handle_fortune_response))), (fish), ((void*
)0), (GConnectFlags) 0)
876 G_CALLBACK (handle_fortune_response), fish)g_signal_connect_data ((fish->fortune_dialog), ("response"
), (((GCallback) (handle_fortune_response))), (fish), ((void*
)0), (GConnectFlags) 0)
;
877
878 monitor = cdk_display_get_monitor_at_window (ctk_widget_get_display (CTK_WIDGET (fish)((((CtkWidget*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((fish)), ((ctk_widget_get_type ()))))))
),
879 ctk_widget_get_window (CTK_WIDGET (fish)((((CtkWidget*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((fish)), ((ctk_widget_get_type ()))))))
));
880 cdk_monitor_get_geometry(monitor, &monitor_geom);
881 ctk_window_set_default_size (CTK_WINDOW (fish->fortune_dialog)((((CtkWindow*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((fish->fortune_dialog)), ((ctk_window_get_type ())))))
)
,
882 MIN (600, monitor_geom.width * 0.9)(((600) < (monitor_geom.width * 0.9)) ? (600) : (monitor_geom
.width * 0.9))
,
883 MIN (350, monitor_geom.height * 0.9)(((350) < (monitor_geom.height * 0.9)) ? (350) : (monitor_geom
.height * 0.9))
);
884
885 fish->fortune_view = ctk_text_view_new ();
886 ctk_text_view_set_editable (CTK_TEXT_VIEW (fish->fortune_view)((((CtkTextView*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((fish->fortune_view)), ((ctk_text_view_get_type ()))))
))
, FALSE(0));
887 ctk_text_view_set_cursor_visible (CTK_TEXT_VIEW (fish->fortune_view)((((CtkTextView*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((fish->fortune_view)), ((ctk_text_view_get_type ()))))
))
, FALSE(0));
888 ctk_text_view_set_left_margin (CTK_TEXT_VIEW (fish->fortune_view)((((CtkTextView*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((fish->fortune_view)), ((ctk_text_view_get_type ()))))
))
, 10);
889 ctk_text_view_set_right_margin (CTK_TEXT_VIEW (fish->fortune_view)((((CtkTextView*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((fish->fortune_view)), ((ctk_text_view_get_type ()))))
))
, 10);
890 fish->fortune_buffer =
891 ctk_text_view_get_buffer (CTK_TEXT_VIEW (fish->fortune_view)((((CtkTextView*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((fish->fortune_view)), ((ctk_text_view_get_type ()))))
))
);
892
893 ctk_text_buffer_create_tag (CTK_TEXT_BUFFER (fish->fortune_buffer)((((CtkTextBuffer*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((fish->fortune_buffer)), ((ctk_text_buffer_get_type ()
))))))
,
894 "monospace_tag", "family",
895 "Monospace", NULL((void*)0));
896
897 scrolled = ctk_scrolled_window_new (NULL((void*)0), NULL((void*)0));
898 ctk_scrolled_window_set_policy (CTK_SCROLLED_WINDOW (scrolled)((((CtkScrolledWindow*) (void *) g_type_check_instance_cast (
(GTypeInstance*) ((scrolled)), ((ctk_scrolled_window_get_type
()))))))
,
899 CTK_POLICY_AUTOMATIC,
900 CTK_POLICY_AUTOMATIC);
901 ctk_scrolled_window_set_shadow_type (CTK_SCROLLED_WINDOW (scrolled)((((CtkScrolledWindow*) (void *) g_type_check_instance_cast (
(GTypeInstance*) ((scrolled)), ((ctk_scrolled_window_get_type
()))))))
,
902 CTK_SHADOW_IN);
903
904 ctk_container_add (CTK_CONTAINER (scrolled)((((CtkContainer*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((scrolled)), ((ctk_container_get_type ()))))))
, fish->fortune_view);
905
906 fish->fortune_label = ctk_label_new ("");
907 ctk_label_set_ellipsize (CTK_LABEL (fish->fortune_label)((((CtkLabel*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((fish->fortune_label)), ((ctk_label_get_type ()))))))
,
908 PANGO_ELLIPSIZE_MIDDLE);
909 fish->fortune_cmd_label = ctk_label_new ("");
910 ctk_label_set_xalign (CTK_LABEL (fish->fortune_cmd_label)((((CtkLabel*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((fish->fortune_cmd_label)), ((ctk_label_get_type ())))
)))
, 0.0);
911 ctk_label_set_yalign (CTK_LABEL (fish->fortune_cmd_label)((((CtkLabel*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((fish->fortune_cmd_label)), ((ctk_label_get_type ())))
)))
, 0.5);
912
913 vbox = ctk_dialog_get_content_area (CTK_DIALOG (fish->fortune_dialog)((((CtkDialog*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((fish->fortune_dialog)), ((ctk_dialog_get_type ())))))
)
);
914 ctk_box_pack_start (CTK_BOX (vbox)((((CtkBox*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((vbox)), ((ctk_box_get_type ()))))))
,
915 fish->fortune_label,
916 FALSE(0), FALSE(0), 6);
917
918 ctk_box_pack_start (CTK_BOX (vbox)((((CtkBox*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((vbox)), ((ctk_box_get_type ()))))))
,
919 scrolled,
920 TRUE(!(0)), TRUE(!(0)), 6);
921
922 ctk_box_pack_start (CTK_BOX (vbox)((((CtkBox*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((vbox)), ((ctk_box_get_type ()))))))
,
923 fish->fortune_cmd_label,
924 FALSE(0), FALSE(0), 6);
925
926 update_fortune_dialog (fish);
927
928 /* We don't show_all for the dialog since fortune_cmd_label
929 * might need to be hidden
930 * The dialog will be shown with ctk_window_present later */
931 ctk_widget_show (scrolled);
932 ctk_widget_show (fish->fortune_view);
933 ctk_widget_show (fish->fortune_label);
934 }
935
936 if (!user_command) {
937 char *command;
938 char * text;
939
940 command = g_markup_printf_escaped ("<tt>%s</tt>", argv[0]);
941 text = g_strdup_printf (_("The configured command is not "gettext ("The configured command is not " "working and has been replaced by: "
"%s")
942 "working and has been replaced by: "gettext ("The configured command is not " "working and has been replaced by: "
"%s")
943 "%s")gettext ("The configured command is not " "working and has been replaced by: "
"%s")
, command);
944 ctk_label_set_markup (CTK_LABEL (fish->fortune_cmd_label)((((CtkLabel*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((fish->fortune_cmd_label)), ((ctk_label_get_type ())))
)))
,
945 text);
946 g_free (command);
947 g_free (text);
948 ctk_widget_show (fish->fortune_cmd_label);
949 } else {
950 ctk_widget_hide (fish->fortune_cmd_label);
951 }
952
953 clear_fortune_text (fish);
954
955 screen = ctk_widget_get_screen (CTK_WIDGET (fish)((((CtkWidget*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((fish)), ((ctk_widget_get_type ()))))))
);
956 display = cdk_screen_get_display (screen);
957 display_name = g_strdup (cdk_display_get_name (display))g_strdup_inline (cdk_display_get_name (display));
958 g_spawn_async_with_pipes (NULL((void*)0), /* working directory */
959 argv,
960 NULL((void*)0), /* envp */
961 G_SPAWN_SEARCH_PATH|G_SPAWN_STDERR_TO_DEV_NULL,
962 set_environment,
963 &display_name,
964 NULL((void*)0), /* child pid */
965 NULL((void*)0), /* stdin */
966 &output,
967 NULL((void*)0), /* stderr */
968 &error);
969 g_free (display_name);
970
971 if (error) {
972 char *message;
973
974 message = g_strdup_printf (_("Unable to execute '%s'\n\nDetails: %s")gettext ("Unable to execute '%s'\n\nDetails: %s"),
975 argv[0], error->message);
976 something_fishy_going_on (fish, message);
977 g_free (message);
978 g_error_free (error);
979 g_strfreev (argv);
980 return;
981 }
982
983 fish->io_channel = g_io_channel_unix_new (output);
984 /* set the correct encoding if the locale is not using UTF-8 */
985 if (!g_get_charset (&charset))
986 g_io_channel_set_encoding(fish->io_channel, charset, &error);
987 if (error) {
988 char *message;
989
990 message = g_strdup_printf (_("Unable to read from '%s'\n\nDetails: %s")gettext ("Unable to read from '%s'\n\nDetails: %s"),
991 argv[0], error->message);
992 something_fishy_going_on (fish, message);
993 g_free (message);
994 g_error_free (error);
995 g_strfreev (argv);
996 return;
997 }
998
999 g_strfreev (argv);
1000
1001 fish->source_id = g_io_add_watch (fish->io_channel,
1002 G_IO_IN|G_IO_ERR|G_IO_HUP|G_IO_NVAL,
1003 fish_read_output, fish);
1004
1005 ctk_window_set_screen (CTK_WINDOW (fish->fortune_dialog)((((CtkWindow*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((fish->fortune_dialog)), ((ctk_window_get_type ())))))
)
,
1006 ctk_widget_get_screen (CTK_WIDGET (fish)((((CtkWidget*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((fish)), ((ctk_widget_get_type ()))))))
));
1007 ctk_window_present (CTK_WINDOW (fish->fortune_dialog)((((CtkWindow*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((fish->fortune_dialog)), ((ctk_window_get_type ())))))
)
);
1008}
1009
1010static void name_changed_notify(GSettings* settings, gchar* key, FishApplet* fish)
1011{
1012 char *value;
1013
1014 value = g_settings_get_string (settings, key);
1015
1016 if (!value [0] || (fish->name && !strcmp (fish->name, value)))
1017 return;
1018
1019 if (fish->name)
1020 g_free (fish->name);
1021 fish->name = g_strdup (value)g_strdup_inline (value);
1022
1023 update_fortune_dialog (fish);
1024 set_tooltip (fish);
1025 set_ally_name_desc (CTK_WIDGET (fish)((((CtkWidget*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((fish)), ((ctk_widget_get_type ()))))))
, fish);
1026
1027 if (fish->name_entry &&
1028 strcmp (ctk_entry_get_text (CTK_ENTRY (fish->name_entry)((((CtkEntry*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((fish->name_entry)), ((ctk_entry_get_type ()))))))
), fish->name))
1029 ctk_entry_set_text (CTK_ENTRY (fish->name_entry)((((CtkEntry*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((fish->name_entry)), ((ctk_entry_get_type ()))))))
, fish->name);
1030
1031 if (value)
1032 g_free (value);
1033}
1034
1035static void image_changed_notify(GSettings* settings, gchar* key, FishApplet* fish)
1036{
1037 char *value;
1038
1039 value = g_settings_get_string (settings, key);
1040
1041 if (!value [0] || (fish->image && !strcmp (fish->image, value)))
1042 return;
1043
1044 if (fish->image)
1045 g_free (fish->image);
1046 fish->image = g_strdup (value)g_strdup_inline (value);
1047
1048 load_fish_image (fish);
1049 update_pixmap (fish);
1050
1051 if (fish->image_chooser) {
1052 char *path_gsettings;
1053 char *path_chooser;
1054
1055 path_gsettings = get_image_path (fish);
1056 path_chooser = ctk_file_chooser_get_filename (CTK_FILE_CHOOSER (fish->image_chooser)((((CtkFileChooser*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((fish->image_chooser)), ((ctk_file_chooser_get_type ()
))))))
);
1057 if (strcmp (path_gsettings, path_chooser))
1058 ctk_file_chooser_set_filename (CTK_FILE_CHOOSER (fish->image_chooser)((((CtkFileChooser*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((fish->image_chooser)), ((ctk_file_chooser_get_type ()
))))))
,
1059 path_gsettings);
1060
1061 g_free (path_gsettings);
1062 g_free (path_chooser);
1063 }
1064
1065 if (value)
1066 g_free (value);
1067}
1068
1069static void command_changed_notify(GSettings* settings, gchar* key, FishApplet* fish)
1070{
1071 char *value;
1072
1073 value = g_settings_get_string (settings, key);
1074
1075 if (fish->command && !strcmp (fish->command, value))
1076 return;
1077
1078 if (fish->command)
1079 g_free (fish->command);
1080 fish->command = g_strdup (value)g_strdup_inline (value);
1081
1082 if (fish->command_entry &&
1083 strcmp (ctk_entry_get_text (CTK_ENTRY (fish->command_entry)((((CtkEntry*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((fish->command_entry)), ((ctk_entry_get_type ()))))))
), fish->command))
1084 ctk_entry_set_text (CTK_ENTRY (fish->command_entry)((((CtkEntry*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((fish->command_entry)), ((ctk_entry_get_type ()))))))
, fish->command);
1085
1086 if (value)
1087 g_free (value);
1088}
1089
1090static void n_frames_changed_notify(GSettings* settings, gchar* key, FishApplet* fish)
1091{
1092 int value;
1093
1094 value = g_settings_get_int (settings, key);
1095
1096 if (fish->n_frames == value)
1097 return;
1098
1099 fish->n_frames = value;
1100
1101 if (fish->n_frames <= 0)
1102 fish->n_frames = 1;
1103
1104 update_pixmap (fish);
1105
1106 if (fish->frames_spin &&
1107 ctk_spin_button_get_value_as_int (CTK_SPIN_BUTTON (fish->frames_spin)((((CtkSpinButton*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((fish->frames_spin)), ((ctk_spin_button_get_type ())))
)))
) != fish->n_frames)
1108 ctk_spin_button_set_value (CTK_SPIN_BUTTON (fish->frames_spin)((((CtkSpinButton*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((fish->frames_spin)), ((ctk_spin_button_get_type ())))
)))
, fish->n_frames);
1109}
1110
1111static char* get_location(void)
1112{
1113 static char location [256];
1114 char *buffer;
1115 FILE *zone;
1116 int i, len, count;
1117
1118 /* Old method : works for glibc < 2.2 */
1119 zone = fopen("/etc/timezone", "r");
1120 if (zone) {
1121 count = fscanf (zone, "%255s", location);
1122 fclose (zone);
1123 /* if we could read it, we return what we got */
1124 if (count == 1)
1125 return location;
1126 }
1127
1128 /* New method : works for glibc 2.2 */
1129 /* FIXME: this is broken for many distros, see the clock code */
1130 buffer = g_file_read_link ("/etc/localtime", NULL((void*)0));
1131 if (!buffer)
1132 return NULL((void*)0);
1133
1134 len = strlen (buffer);
1135 for (i = len, count = 0; (i > 0) && (count != 2); i--)
1136 if (buffer [i] == '/')
1137 count++;
1138
1139 if (count != 2) {
1140 g_free (buffer);
1141 return NULL((void*)0);
1142 }
1143
1144 memcpy (location, &buffer [i + 2], len - i - 2);
1145 g_free (buffer);
1146
1147 return location;
1148}
1149
1150static void init_fools_day(void)
1151{
1152 const char *spanish_timezones [] = {
1153 "Europe/Madrid",
1154 "Africa/Ceuta",
1155 "Atlantic/Canary",
1156 "America/Mexico_City",
1157 "Mexico/BajaSur",
1158 "Mexico/BajaNorte",
1159 "Mexico/General",
1160 NULL((void*)0)
1161 };
1162 char *location;
1163 int i;
1164
1165 if (!(location = get_location ()))
1166 return;
1167
1168 fools_day = 1; /* 1st */
1169 fools_month = 3; /* April */
1170 fools_hour_start = 0; /* Midnight */
1171 fools_hour_end = 12; /* Apparently jokes should stop at midday */
1172
1173 for (i = 0; spanish_timezones [i]; i++)
1174 if (!g_ascii_strcasecmp (spanish_timezones [i], location)) {
1175 /* Hah!, We are in Spain or Mexico
1176 * Spanish fool's day is 28th December
1177 */
1178 fools_day = 28;
1179 fools_month = 11;
1180 return;
1181 }
1182}
1183
1184static void check_april_fools(FishApplet* fish)
1185{
1186 struct tm *tm;
1187 time_t now;
1188
1189 time (&now);
1190 tm = localtime (&now);
1191
1192 if (fish->april_fools &&
1193 (tm->tm_mon != fools_month ||
1194 tm->tm_mday != fools_day ||
1195 tm->tm_hour >= fools_hour_end)) {
1196 fish->april_fools = FALSE(0);
1197 update_pixmap (fish);
1198 } else if (tm->tm_mon == fools_month &&
1199 tm->tm_mday == fools_day &&
1200 tm->tm_hour >= fools_hour_start &&
1201 tm->tm_hour <= fools_hour_end) {
1202 fish->april_fools = TRUE(!(0));
1203 update_pixmap (fish);
1204 }
1205}
1206
1207static gboolean timeout_handler(gpointer data)
1208{
1209 FishApplet *fish = (FishApplet *) data;
1210
1211 check_april_fools (fish);
1212
1213 if (fish->april_fools)
1214 return TRUE(!(0));
1215
1216 fish->current_frame++;
1217 if (fish->current_frame >= fish->n_frames)
1218 fish->current_frame = 0;
1219
1220 ctk_widget_queue_draw (fish->drawing_area);
1221
1222 return TRUE(!(0));
1223}
1224
1225static void setup_timeout(FishApplet *fish)
1226{
1227 if (fish->timeout)
1228 g_source_remove (fish->timeout);
1229
1230 fish->timeout = g_timeout_add (fish->speed * 1000,
1231 timeout_handler,
1232 fish);
1233}
1234
1235static void speed_changed_notify(GSettings* settings, gchar* key, FishApplet* fish)
1236{
1237 gdouble value;
1238
1239 value = g_settings_get_double (settings, key);
1240
1241 if (fish->speed == value)
1242 return;
1243 fish->speed = value;
1244
1245 setup_timeout (fish);
1246
1247 if (fish->speed_spin &&
1248 ctk_spin_button_get_value (CTK_SPIN_BUTTON (fish->frames_spin)((((CtkSpinButton*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((fish->frames_spin)), ((ctk_spin_button_get_type ())))
)))
) != fish->speed)
1249 ctk_spin_button_set_value (CTK_SPIN_BUTTON (fish->speed_spin)((((CtkSpinButton*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((fish->speed_spin)), ((ctk_spin_button_get_type ()))))
))
, fish->speed);
1250}
1251
1252static void rotate_changed_notify(GSettings* settings, gchar* key, FishApplet* fish)
1253{
1254 gboolean value;
1255
1256 value = g_settings_get_boolean (settings, key);
1257
1258 if (fish->rotate == value)
1259 return;
1260 fish->rotate = value;
1261
1262 if (fish->orientation == CAFE_PANEL_APPLET_ORIENT_LEFT ||
1263 fish->orientation == CAFE_PANEL_APPLET_ORIENT_RIGHT)
1264 update_pixmap (fish);
1265
1266 if (fish->rotate_toggle &&
1267 ctk_toggle_button_get_active (CTK_TOGGLE_BUTTON (fish->rotate_toggle)((((CtkToggleButton*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((fish->rotate_toggle)), ((ctk_toggle_button_get_type (
)))))))
) != fish->rotate)
1268 ctk_toggle_button_set_active (
1269 CTK_TOGGLE_BUTTON (fish->rotate_toggle)((((CtkToggleButton*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((fish->rotate_toggle)), ((ctk_toggle_button_get_type (
)))))))
, fish->rotate);
1270}
1271
1272static void fish_disable_commande_line_notify(GSettings* settings, gchar* key, FishApplet* fish)
1273{
1274 gboolean locked_down;
1275
1276 locked_down = !g_settings_get_boolean (settings, key);
1277
1278 if (fish->command_label != NULL((void*)0))
1279 ctk_widget_set_sensitive (fish->command_label, locked_down);
1280 if (fish->command_entry != NULL((void*)0))
1281 ctk_widget_set_sensitive (fish->command_entry, locked_down);
1282}
1283
1284static void setup_gsettings(FishApplet* fish)
1285{
1286 CafePanelApplet *applet = (CafePanelApplet *) fish;
1287
1288 fish->settings = cafe_panel_applet_settings_new (applet, FISH_SCHEMA"org.cafe.panel.applet.fish");
1289 fish->lockdown_settings = g_settings_new (LOCKDOWN_SCHEMA"org.cafe.lockdown");
1290
1291 g_signal_connect (fish->settings,g_signal_connect_data ((fish->settings), ("changed::" "name"
), (((GCallback) (name_changed_notify))), (fish), ((void*)0),
(GConnectFlags) 0)
1292 "changed::" FISH_NAME_KEY,g_signal_connect_data ((fish->settings), ("changed::" "name"
), (((GCallback) (name_changed_notify))), (fish), ((void*)0),
(GConnectFlags) 0)
1293 G_CALLBACK (name_changed_notify),g_signal_connect_data ((fish->settings), ("changed::" "name"
), (((GCallback) (name_changed_notify))), (fish), ((void*)0),
(GConnectFlags) 0)
1294 fish)g_signal_connect_data ((fish->settings), ("changed::" "name"
), (((GCallback) (name_changed_notify))), (fish), ((void*)0),
(GConnectFlags) 0)
;
1295 g_signal_connect (fish->settings,g_signal_connect_data ((fish->settings), ("changed::" "image"
), (((GCallback) (image_changed_notify))), (fish), ((void*)0)
, (GConnectFlags) 0)
1296 "changed::" FISH_IMAGE_KEY,g_signal_connect_data ((fish->settings), ("changed::" "image"
), (((GCallback) (image_changed_notify))), (fish), ((void*)0)
, (GConnectFlags) 0)
1297 G_CALLBACK (image_changed_notify),g_signal_connect_data ((fish->settings), ("changed::" "image"
), (((GCallback) (image_changed_notify))), (fish), ((void*)0)
, (GConnectFlags) 0)
1298 fish)g_signal_connect_data ((fish->settings), ("changed::" "image"
), (((GCallback) (image_changed_notify))), (fish), ((void*)0)
, (GConnectFlags) 0)
;
1299 g_signal_connect (fish->settings,g_signal_connect_data ((fish->settings), ("changed::" "command"
), (((GCallback) (command_changed_notify))), (fish), ((void*)
0), (GConnectFlags) 0)
1300 "changed::" FISH_COMMAND_KEY,g_signal_connect_data ((fish->settings), ("changed::" "command"
), (((GCallback) (command_changed_notify))), (fish), ((void*)
0), (GConnectFlags) 0)
1301 G_CALLBACK (command_changed_notify),g_signal_connect_data ((fish->settings), ("changed::" "command"
), (((GCallback) (command_changed_notify))), (fish), ((void*)
0), (GConnectFlags) 0)
1302 fish)g_signal_connect_data ((fish->settings), ("changed::" "command"
), (((GCallback) (command_changed_notify))), (fish), ((void*)
0), (GConnectFlags) 0)
;
1303 g_signal_connect (fish->settings,g_signal_connect_data ((fish->settings), ("changed::" "frames"
), (((GCallback) (n_frames_changed_notify))), (fish), ((void*
)0), (GConnectFlags) 0)
1304 "changed::" FISH_FRAMES_KEY,g_signal_connect_data ((fish->settings), ("changed::" "frames"
), (((GCallback) (n_frames_changed_notify))), (fish), ((void*
)0), (GConnectFlags) 0)
1305 G_CALLBACK (n_frames_changed_notify),g_signal_connect_data ((fish->settings), ("changed::" "frames"
), (((GCallback) (n_frames_changed_notify))), (fish), ((void*
)0), (GConnectFlags) 0)
1306 fish)g_signal_connect_data ((fish->settings), ("changed::" "frames"
), (((GCallback) (n_frames_changed_notify))), (fish), ((void*
)0), (GConnectFlags) 0)
;
1307 g_signal_connect (fish->settings,g_signal_connect_data ((fish->settings), ("changed::" "speed"
), (((GCallback) (speed_changed_notify))), (fish), ((void*)0)
, (GConnectFlags) 0)
1308 "changed::" FISH_SPEED_KEY,g_signal_connect_data ((fish->settings), ("changed::" "speed"
), (((GCallback) (speed_changed_notify))), (fish), ((void*)0)
, (GConnectFlags) 0)
1309 G_CALLBACK (speed_changed_notify),g_signal_connect_data ((fish->settings), ("changed::" "speed"
), (((GCallback) (speed_changed_notify))), (fish), ((void*)0)
, (GConnectFlags) 0)
1310 fish)g_signal_connect_data ((fish->settings), ("changed::" "speed"
), (((GCallback) (speed_changed_notify))), (fish), ((void*)0)
, (GConnectFlags) 0)
;
1311 g_signal_connect (fish->settings,g_signal_connect_data ((fish->settings), ("changed::" "rotate"
), (((GCallback) (rotate_changed_notify))), (fish), ((void*)0
), (GConnectFlags) 0)
1312 "changed::" FISH_ROTATE_KEY,g_signal_connect_data ((fish->settings), ("changed::" "rotate"
), (((GCallback) (rotate_changed_notify))), (fish), ((void*)0
), (GConnectFlags) 0)
1313 G_CALLBACK (rotate_changed_notify),g_signal_connect_data ((fish->settings), ("changed::" "rotate"
), (((GCallback) (rotate_changed_notify))), (fish), ((void*)0
), (GConnectFlags) 0)
1314 fish)g_signal_connect_data ((fish->settings), ("changed::" "rotate"
), (((GCallback) (rotate_changed_notify))), (fish), ((void*)0
), (GConnectFlags) 0)
;
1315 g_signal_connect (fish->lockdown_settings,g_signal_connect_data ((fish->lockdown_settings), ("changed::"
"disable-command-line"), (((GCallback) (fish_disable_commande_line_notify
))), (fish), ((void*)0), (GConnectFlags) 0)
1316 "changed::" LOCKDOWN_DISABLE_COMMAND_LINE_KEY,g_signal_connect_data ((fish->lockdown_settings), ("changed::"
"disable-command-line"), (((GCallback) (fish_disable_commande_line_notify
))), (fish), ((void*)0), (GConnectFlags) 0)
1317 G_CALLBACK (fish_disable_commande_line_notify),g_signal_connect_data ((fish->lockdown_settings), ("changed::"
"disable-command-line"), (((GCallback) (fish_disable_commande_line_notify
))), (fish), ((void*)0), (GConnectFlags) 0)
1318 fish)g_signal_connect_data ((fish->lockdown_settings), ("changed::"
"disable-command-line"), (((GCallback) (fish_disable_commande_line_notify
))), (fish), ((void*)0), (GConnectFlags) 0)
;
1319}
1320
1321static gboolean load_fish_image(FishApplet* fish)
1322{
1323 GdkPixbuf *pixbuf;
1324 GError *error = NULL((void*)0);
1325 char *path = NULL((void*)0);
1326
1327 if (!fish->image)
1328 return FALSE(0);
1329
1330 path = get_image_path (fish);
1331
1332 pixbuf = gdk_pixbuf_new_from_file (path, &error);
1333 if (error) {
1334 g_warning ("Cannot load '%s': %s", path, error->message);
1335 g_error_free (error);
1336 g_free (path);
1337 return FALSE(0);
1338 }
1339
1340 if (fish->pixbuf)
1341 g_object_unref (fish->pixbuf);
1342 fish->pixbuf = pixbuf;
1343
1344 if (fish->preview_image)
1345 ctk_image_set_from_pixbuf (CTK_IMAGE (fish->preview_image)((((CtkImage*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((fish->preview_image)), ((ctk_image_get_type ()))))))
,
1346 fish->pixbuf);
1347
1348 g_free (path);
1349
1350 return TRUE(!(0));
1351}
1352
1353static gboolean
1354update_pixmap_in_idle (gpointer data)
1355{
1356 update_pixmap (FISH_APPLET (data)((((FishApplet*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((data)), (fish_applet_get_type())))))
);
1357 return FALSE(0);
1358}
1359
1360static void update_pixmap(FishApplet* fish)
1361{
1362 CtkWidget *widget = fish->drawing_area;
1363 CtkRequisition prev_requisition;
1364 CtkAllocation allocation;
1365 int width = -1;
1366 int height = -1;
1367 int pixbuf_width = -1;
1368 int pixbuf_height = -1;
1369 gboolean rotate = FALSE(0);
1370 cairo_t *cr;
1371 cairo_matrix_t matrix;
1372 cairo_pattern_t *pattern;
1373
1374 ctk_widget_get_allocation (widget, &allocation);
1375
1376 if (!ctk_widget_get_realized (widget) ||
1377 allocation.width <= 0 ||
1378 allocation.height <= 0)
1379 return;
1380
1381 if (!fish->pixbuf && !load_fish_image (fish))
1382 return;
1383
1384 if (fish->rotate &&
1385 (fish->orientation == CAFE_PANEL_APPLET_ORIENT_LEFT ||
1386 fish->orientation == CAFE_PANEL_APPLET_ORIENT_RIGHT))
1387 rotate = TRUE(!(0));
1388
1389 pixbuf_width = gdk_pixbuf_get_width (fish->pixbuf);
1390 pixbuf_height = gdk_pixbuf_get_height (fish->pixbuf);
1391
1392 prev_requisition = fish->requisition;
1393
1394 if (fish->orientation == CAFE_PANEL_APPLET_ORIENT_UP ||
1395 fish->orientation == CAFE_PANEL_APPLET_ORIENT_DOWN) {
1396 height = allocation.height;
1397 width = pixbuf_width * ((gdouble) height / pixbuf_height);
1398 fish->requisition.width = width / fish->n_frames;
1399 fish->requisition.height = height;
1400 } else {
1401 if (!rotate) {
1402 width = allocation.width * fish->n_frames;
1403 height = pixbuf_height * ((gdouble) width / pixbuf_width);
1404 fish->requisition.width = allocation.width;
1405 fish->requisition.height = height;
1406 } else {
1407 width = allocation.width;
1408 height = pixbuf_width * ((gdouble) width / pixbuf_height);
1409 fish->requisition.width = width;
1410 fish->requisition.height = height / fish->n_frames;
1411 }
1412 }
1413
1414 if (prev_requisition.width != fish->requisition.width ||
1415 prev_requisition.height != fish->requisition.height) {
1416 ctk_widget_set_size_request (widget,
1417 fish->requisition.width,
1418 fish->requisition.height);
1419 }
1420
1421 g_assert (width != -1 && height != -1)do { if (width != -1 && height != -1) ; else g_assertion_message_expr
(((gchar*) 0), "fish.c", 1421, ((const char*) (__func__)), "width != -1 && height != -1"
); } while (0)
;
1422
1423 if (width == 0 || height == 0)
1424 return;
1425
1426 if (fish->surface)
1427 cairo_surface_destroy (fish->surface);
1428 fish->surface = cdk_window_create_similar_surface (ctk_widget_get_window (widget),
1429 CAIRO_CONTENT_COLOR_ALPHA,
1430 width, height);
1431 fish->surface_width = width;
1432 fish->surface_height = height;
1433
1434 ctk_widget_queue_resize (widget);
1435
1436 g_assert (pixbuf_width != -1 && pixbuf_height != -1)do { if (pixbuf_width != -1 && pixbuf_height != -1) ;
else g_assertion_message_expr (((gchar*) 0), "fish.c", 1436,
((const char*) (__func__)), "pixbuf_width != -1 && pixbuf_height != -1"
); } while (0)
;
1437
1438 cr = cairo_create (fish->surface);
1439
1440 cairo_set_source_rgb (cr, 1, 1, 1);
1441 cairo_paint (cr);
1442
1443 cdk_cairo_set_source_pixbuf (cr, fish->pixbuf, 0, 0);
1444 pattern = cairo_get_source (cr);
1445 cairo_pattern_set_filter (pattern, CAIRO_FILTER_BEST);
1446
1447 cairo_matrix_init_identity (&matrix);
1448
1449 if (fish->april_fools) {
1450 cairo_matrix_translate (&matrix,
1451 pixbuf_width - 1, pixbuf_height - 1);
1452 cairo_matrix_rotate (&matrix, M_PI3.14159265358979323846);
1453 }
1454
1455 if (rotate) {
1456 if (fish->orientation == CAFE_PANEL_APPLET_ORIENT_RIGHT) {
1457 cairo_matrix_translate (&matrix, pixbuf_width - 1, 0);
1458 cairo_matrix_rotate (&matrix, M_PI3.14159265358979323846 * 0.5);
1459 } else {
1460 cairo_matrix_translate (&matrix, 0, pixbuf_height - 1);
1461 cairo_matrix_rotate (&matrix, M_PI3.14159265358979323846 * 1.5);
1462 }
1463 cairo_matrix_scale (&matrix,
1464 (double) (pixbuf_height - 1) / width,
1465 (double) (pixbuf_width - 1) / height);
1466 } else {
1467 cairo_matrix_scale (&matrix,
1468 (double) (pixbuf_width - 1) / width,
1469 (double) (pixbuf_height - 1) / height);
1470 }
1471
1472 cairo_pattern_set_matrix (pattern, &matrix);
1473
1474 cairo_rectangle (cr, 0, 0, width, height);
1475 cairo_fill (cr);
1476
1477 if (fish->april_fools) {
1478 cairo_set_source_rgb (cr, 1, 0.5, 0);
1479 cairo_paint_with_alpha (cr, 0.25);
1480 }
1481
1482 cairo_destroy (cr);
1483}
1484
1485static gboolean fish_applet_draw (CtkWidget *widget G_GNUC_UNUSED__attribute__ ((__unused__)),
1486 cairo_t *cr,
1487 FishApplet *fish)
1488{
1489 int width, height;
1490 int src_x, src_y;
1491
1492 g_return_val_if_fail (fish->surface != NULL, FALSE)do { if ((fish->surface != ((void*)0))) { } else { g_return_if_fail_warning
(((gchar*) 0), ((const char*) (__func__)), "fish->surface != NULL"
); return ((0)); } } while (0)
;
1493
1494 g_assert (fish->n_frames > 0)do { if (fish->n_frames > 0) ; else g_assertion_message_expr
(((gchar*) 0), "fish.c", 1494, ((const char*) (__func__)), "fish->n_frames > 0"
); } while (0)
;
1495
1496 width = fish->surface_width;
1497 height = fish->surface_height;
1498 src_x = 0;
1499 src_y = 0;
1500
1501 if (fish->rotate) {
1502 if (fish->orientation == CAFE_PANEL_APPLET_ORIENT_RIGHT)
1503 src_y += ((height * (fish->n_frames - 1 - fish->current_frame)) / fish->n_frames);
1504 else if (fish->orientation == CAFE_PANEL_APPLET_ORIENT_LEFT)
1505 src_y += ((height * fish->current_frame) / fish->n_frames);
1506 else
1507 src_x += ((width * fish->current_frame) / fish->n_frames);
1508 } else
1509 src_x += ((width * fish->current_frame) / fish->n_frames);
1510
1511 cairo_save (cr);
1512 cairo_set_source_surface (cr, fish->surface, -src_x, -src_y);
1513 cairo_paint (cr);
1514 cairo_restore (cr);
1515
1516 return FALSE(0);
1517}
1518
1519static void fish_applet_size_allocate (CtkWidget *widget G_GNUC_UNUSED__attribute__ ((__unused__)),
1520 CtkAllocation *allocation,
1521 FishApplet *fish)
1522{
1523 if (allocation->width == fish->prev_allocation.width &&
1524 allocation->height == fish->prev_allocation.height)
1525 return;
1526
1527 fish->prev_allocation = *allocation;
1528 g_idle_add (update_pixmap_in_idle, fish);
1529}
1530
1531static void fish_applet_realize (CtkWidget *widget G_GNUC_UNUSED__attribute__ ((__unused__)),
1532 FishApplet *fish)
1533{
1534 if (!fish->surface)
1535 update_pixmap (fish);
1536}
1537
1538static void fish_applet_unrealize (CtkWidget *widget G_GNUC_UNUSED__attribute__ ((__unused__)),
1539 FishApplet *fish)
1540{
1541 if (fish->surface)
1542 cairo_surface_destroy (fish->surface);
1543 fish->surface = NULL((void*)0);
1544 fish->surface_width = 0;
1545 fish->surface_height = 0;
1546}
1547
1548static void fish_applet_change_orient(CafePanelApplet* applet, CafePanelAppletOrient orientation)
1549{
1550 FishApplet *fish = (FishApplet *) applet;
1551
1552 if (fish->orientation == orientation)
1553 return;
1554
1555 fish->orientation = orientation;
1556
1557 if (fish->surface)
1558 update_pixmap (fish);
1559}
1560
1561static void change_water(FishApplet* fish)
1562{
1563 CtkWidget *dialog;
1564
1565 dialog = ctk_message_dialog_new (
1566 NULL((void*)0), 0, CTK_MESSAGE_INFO,
1567 CTK_BUTTONS_OK,
1568 _("The water needs changing")gettext ("The water needs changing"));
1569 ctk_message_dialog_format_secondary_text (CTK_MESSAGE_DIALOG (dialog)((((CtkMessageDialog*) (void *) g_type_check_instance_cast ((
GTypeInstance*) ((dialog)), ((ctk_message_dialog_get_type ())
)))))
,
1570 _("Look at today's date!")gettext ("Look at today's date!"));
1571 ctk_window_set_icon_name (CTK_WINDOW (dialog)((((CtkWindow*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((dialog)), ((ctk_window_get_type ()))))))
, FISH_ICON"cafe-panel-fish");
1572 ctk_window_set_screen (CTK_WINDOW (dialog)((((CtkWindow*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((dialog)), ((ctk_window_get_type ()))))))
,
1573 ctk_widget_get_screen (CTK_WIDGET (fish)((((CtkWidget*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((fish)), ((ctk_widget_get_type ()))))))
));
1574
1575 ctk_widget_show_all (dialog);
1576
1577 g_signal_connect (dialog, "response",g_signal_connect_data ((dialog), ("response"), (((GCallback) (
ctk_widget_destroy))), (((void*)0)), ((void*)0), (GConnectFlags
) 0)
1578 G_CALLBACK (ctk_widget_destroy), NULL)g_signal_connect_data ((dialog), ("response"), (((GCallback) (
ctk_widget_destroy))), (((void*)0)), ((void*)0), (GConnectFlags
) 0)
;
1579}
1580
1581static gboolean handle_keypress (CtkWidget *widget G_GNUC_UNUSED__attribute__ ((__unused__)),
1582 CdkEventKey *event,
1583 FishApplet *fish)
1584{
1585 switch (event->keyval) {
1586 case CDK_KEY_space0x020:
1587 case CDK_KEY_KP_Space0xff80:
1588 case CDK_KEY_Return0xff0d:
1589 case CDK_KEY_KP_Enter0xff8d:
1590 case CDK_KEY_ISO_Enter0xfe34:
1591 case CDK_KEY_3270_Enter0xfd1e:
1592 if (fish->april_fools) {
1593 change_water (fish);
1594 return TRUE(!(0));
1595 }
1596
1597 display_fortune_dialog (fish);
1598 break;
1599 default:
1600 return FALSE(0);
1601 break;
This statement is never executed
1602 }
1603
1604 return TRUE(!(0));
1605}
1606
1607static gboolean fish_enter_notify(CtkWidget* widget, CdkEventCrossing* event)
1608{
1609 FishApplet *fish;
1610 CtkWidget *event_widget;
1611
1612 fish = FISH_APPLET (widget)((((FishApplet*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((widget)), (fish_applet_get_type())))))
;
1613 event_widget = ctk_get_event_widget ((CdkEvent*) event);
1614
1615 if ((event_widget == widget) &&
1616 (event->detail != CDK_NOTIFY_INFERIOR))
1617 fish->in_applet = TRUE(!(0));
1618
1619 return FALSE(0);
1620}
1621
1622static gboolean fish_leave_notify(CtkWidget* widget, CdkEventCrossing* event)
1623{
1624 FishApplet *fish;
1625 CtkWidget *event_widget;
1626
1627 fish = FISH_APPLET (widget)((((FishApplet*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((widget)), (fish_applet_get_type())))))
;
1628 event_widget = ctk_get_event_widget ((CdkEvent*) event);
1629
1630 if ((event_widget == widget) &&
1631 (event->detail != CDK_NOTIFY_INFERIOR))
1632 fish->in_applet = FALSE(0);
1633
1634 return FALSE(0);
1635}
1636
1637static gboolean handle_button_release(FishApplet* fish, CdkEventButton* event)
1638{
1639 if (!fish->in_applet || event->button != 1)
1640 return FALSE(0);
1641
1642 if (fish->april_fools) {
1643 change_water (fish);
1644 return TRUE(!(0));
1645 }
1646
1647 display_fortune_dialog (fish);
1648
1649 return TRUE(!(0));
1650}
1651
1652static void set_tooltip(FishApplet* fish)
1653{
1654 const char *desc_format = _("%s the Fish, the fortune teller")gettext ("%s the Fish, the fortune teller");
1655 char *desc;
1656
1657 desc = g_markup_printf_escaped (desc_format, fish->name);
1658 ctk_widget_set_tooltip_markup (CTK_WIDGET (fish)((((CtkWidget*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((fish)), ((ctk_widget_get_type ()))))))
, desc);
1659 g_free (desc);
1660}
1661
1662static void setup_fish_widget(FishApplet* fish)
1663{
1664 CtkWidget *widget = (CtkWidget *) fish;
1665
1666 fish->frame = ctk_frame_new (NULL((void*)0));
1667 ctk_frame_set_shadow_type (CTK_FRAME (fish->frame)((((CtkFrame*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((fish->frame)), ((ctk_frame_get_type ()))))))
, CTK_SHADOW_IN);
1668 ctk_container_add (CTK_CONTAINER (widget)((((CtkContainer*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((widget)), ((ctk_container_get_type ()))))))
, fish->frame);
1669
1670 fish->drawing_area = ctk_drawing_area_new ();
1671 ctk_container_add (CTK_CONTAINER (fish->frame)((((CtkContainer*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((fish->frame)), ((ctk_container_get_type ()))))))
, fish->drawing_area);
1672
1673 g_signal_connect (fish->drawing_area, "realize",g_signal_connect_data ((fish->drawing_area), ("realize"), (
((GCallback) (fish_applet_realize))), (fish), ((void*)0), (GConnectFlags
) 0)
1674 G_CALLBACK (fish_applet_realize), fish)g_signal_connect_data ((fish->drawing_area), ("realize"), (
((GCallback) (fish_applet_realize))), (fish), ((void*)0), (GConnectFlags
) 0)
;
1675 g_signal_connect (fish->drawing_area, "unrealize",g_signal_connect_data ((fish->drawing_area), ("unrealize")
, (((GCallback) (fish_applet_unrealize))), (fish), ((void*)0)
, (GConnectFlags) 0)
1676 G_CALLBACK (fish_applet_unrealize), fish)g_signal_connect_data ((fish->drawing_area), ("unrealize")
, (((GCallback) (fish_applet_unrealize))), (fish), ((void*)0)
, (GConnectFlags) 0)
;
1677 g_signal_connect (fish->drawing_area, "size-allocate",g_signal_connect_data ((fish->drawing_area), ("size-allocate"
), (((GCallback) (fish_applet_size_allocate))), (fish), ((void
*)0), (GConnectFlags) 0)
1678 G_CALLBACK (fish_applet_size_allocate), fish)g_signal_connect_data ((fish->drawing_area), ("size-allocate"
), (((GCallback) (fish_applet_size_allocate))), (fish), ((void
*)0), (GConnectFlags) 0)
;
1679 g_signal_connect (fish->drawing_area, "draw",g_signal_connect_data ((fish->drawing_area), ("draw"), (((
GCallback) (fish_applet_draw))), (fish), ((void*)0), (GConnectFlags
) 0)
1680 G_CALLBACK (fish_applet_draw), fish)g_signal_connect_data ((fish->drawing_area), ("draw"), (((
GCallback) (fish_applet_draw))), (fish), ((void*)0), (GConnectFlags
) 0)
;
1681
1682 ctk_widget_add_events (widget, CDK_ENTER_NOTIFY_MASK |
1683 CDK_LEAVE_NOTIFY_MASK |
1684 CDK_BUTTON_RELEASE_MASK);
1685
1686 g_signal_connect_swapped (widget, "enter_notify_event",g_signal_connect_data ((widget), ("enter_notify_event"), (((GCallback
) (fish_enter_notify))), (fish), ((void*)0), G_CONNECT_SWAPPED
)
1687 G_CALLBACK (fish_enter_notify), fish)g_signal_connect_data ((widget), ("enter_notify_event"), (((GCallback
) (fish_enter_notify))), (fish), ((void*)0), G_CONNECT_SWAPPED
)
;
1688 g_signal_connect_swapped (widget, "leave_notify_event",g_signal_connect_data ((widget), ("leave_notify_event"), (((GCallback
) (fish_leave_notify))), (fish), ((void*)0), G_CONNECT_SWAPPED
)
1689 G_CALLBACK (fish_leave_notify), fish)g_signal_connect_data ((widget), ("leave_notify_event"), (((GCallback
) (fish_leave_notify))), (fish), ((void*)0), G_CONNECT_SWAPPED
)
;
1690 g_signal_connect_swapped (widget, "button_release_event",g_signal_connect_data ((widget), ("button_release_event"), ((
(GCallback) (handle_button_release))), (fish), ((void*)0), G_CONNECT_SWAPPED
)
1691 G_CALLBACK (handle_button_release), fish)g_signal_connect_data ((widget), ("button_release_event"), ((
(GCallback) (handle_button_release))), (fish), ((void*)0), G_CONNECT_SWAPPED
)
;
1692
1693 ctk_widget_add_events (fish->drawing_area, CDK_BUTTON_RELEASE_MASK);
1694 g_signal_connect_swapped (fish->drawing_area, "button_release_event",g_signal_connect_data ((fish->drawing_area), ("button_release_event"
), (((GCallback) (handle_button_release))), (fish), ((void*)0
), G_CONNECT_SWAPPED)
1695 G_CALLBACK (handle_button_release), fish)g_signal_connect_data ((fish->drawing_area), ("button_release_event"
), (((GCallback) (handle_button_release))), (fish), ((void*)0
), G_CONNECT_SWAPPED)
;
1696
1697 load_fish_image (fish);
1698
1699 update_pixmap (fish);
1700
1701 setup_timeout (fish);
1702
1703 set_tooltip (fish);
1704 set_ally_name_desc (CTK_WIDGET (fish)((((CtkWidget*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((fish)), ((ctk_widget_get_type ()))))))
, fish);
1705
1706 g_signal_connect (fish, "key_press_event",g_signal_connect_data ((fish), ("key_press_event"), (((GCallback
) (handle_keypress))), (fish), ((void*)0), (GConnectFlags) 0)
1707 G_CALLBACK (handle_keypress), fish)g_signal_connect_data ((fish), ("key_press_event"), (((GCallback
) (handle_keypress))), (fish), ((void*)0), (GConnectFlags) 0)
;
1708
1709 ctk_widget_show_all (widget);
1710}
1711
1712static const CtkActionEntry fish_menu_verbs[] = {
1713 { "FishPreferences", "document-properties", N_("_Preferences")("_Preferences"),
1714 NULL((void*)0), NULL((void*)0),
1715 G_CALLBACK (display_preferences_dialog)((GCallback) (display_preferences_dialog)) },
1716 { "FishHelp", "help-browser", N_("_Help")("_Help"),
1717 NULL((void*)0), NULL((void*)0),
1718 G_CALLBACK (display_help_dialog)((GCallback) (display_help_dialog)) },
1719 { "FishAbout", "help-about", N_("_About")("_About"),
1720 NULL((void*)0), NULL((void*)0),
1721 G_CALLBACK (display_about_dialog)((GCallback) (display_about_dialog)) }
1722};
1723
1724static gboolean fish_applet_fill(FishApplet* fish)
1725{
1726 CafePanelApplet* applet = (CafePanelApplet*) fish;
1727 CtkActionGroup* action_group;
1728
1729 fish->orientation = cafe_panel_applet_get_orient (applet);
1730
1731 setup_gsettings (fish);
1732
1733 fish->name = g_settings_get_string (fish->settings, FISH_NAME_KEY"name");
1734
1735 if (!fish->name)
1736 {
1737 fish->name = g_strdup ("Wanda")g_strdup_inline ("Wanda"); /* Fallback */
1738 }
1739
1740 fish->image = g_settings_get_string (fish->settings, FISH_IMAGE_KEY"image");
1741
1742 if (!fish->image)
1743 fish->image = g_strdup ("fishanim.png")g_strdup_inline ("fishanim.png"); /* Fallback */
1744
1745 fish->command = g_settings_get_string (fish->settings, FISH_COMMAND_KEY"command");
1746
1747 fish->n_frames = g_settings_get_int (fish->settings, FISH_FRAMES_KEY"frames");
1748
1749 if (fish->n_frames <= 0)
1750 fish->n_frames = 1;
1751
1752 fish->speed = g_settings_get_double (fish->settings, FISH_SPEED_KEY"speed");
1753
1754 fish->rotate = g_settings_get_boolean (fish->settings, FISH_ROTATE_KEY"rotate");
1755
1756 action_group = ctk_action_group_new ("Fish Applet Actions");
1757 ctk_action_group_set_translation_domain (action_group, GETTEXT_PACKAGE"cafe-panel");
1758 ctk_action_group_add_actions (action_group,
1759 fish_menu_verbs,
1760 G_N_ELEMENTS (fish_menu_verbs)(sizeof (fish_menu_verbs) / sizeof ((fish_menu_verbs)[0])),
1761 fish);
1762 cafe_panel_applet_setup_menu_from_resource (applet,
1763 FISH_RESOURCE_PATH"/org/cafe/panel/applet/fish/" "fish-menu.xml",
1764 action_group);
1765
1766 if (cafe_panel_applet_get_locked_down (applet)) {
1767 CtkAction *action;
1768
1769 action = ctk_action_group_get_action (action_group, "FishPreferences");
1770 ctk_action_set_visible (action, FALSE(0));
1771 }
1772 g_object_unref (action_group);
1773
1774 #ifndef FISH_INPROCESS
1775 ctk_window_set_default_icon_name(FISH_ICON"cafe-panel-fish");
1776 #endif
1777
1778 setup_fish_widget(fish);
1779
1780 return TRUE(!(0));
1781}
1782
1783static gboolean fishy_factory (CafePanelApplet *applet,
1784 const char *iid,
1785 gpointer data G_GNUC_UNUSED__attribute__ ((__unused__)))
1786{
1787 gboolean retval = FALSE(0);
1788
1789 if (!strcmp(iid, "FishApplet"))
1790 {
1791 retval = fish_applet_fill(FISH_APPLET(applet)((((FishApplet*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((applet)), (fish_applet_get_type())))))
);
1792 }
1793
1794 return retval;
1795}
1796
1797static void fish_applet_dispose (GObject *object)
1798{
1799 FishApplet* fish = (FishApplet*) object;
1800
1801 if (fish->settings != NULL((void*)0))
1802 g_signal_handlers_disconnect_by_data (fish->settings,g_signal_handlers_disconnect_matched ((fish->settings), G_SIGNAL_MATCH_DATA
, 0, 0, ((void*)0), ((void*)0), (fish))
1803 fish)g_signal_handlers_disconnect_matched ((fish->settings), G_SIGNAL_MATCH_DATA
, 0, 0, ((void*)0), ((void*)0), (fish))
;
1804
1805 if (fish->timeout)
1806 {
1807 g_source_remove (fish->timeout);
1808 }
1809
1810 fish->timeout = 0;
1811
1812 if (fish->settings)
1813 g_object_unref (fish->settings);
1814 fish->settings = NULL((void*)0);
1815
1816 if (fish->lockdown_settings)
1817 g_object_unref (fish->lockdown_settings);
1818 fish->lockdown_settings = NULL((void*)0);
1819
1820 if (fish->name)
1821 g_free (fish->name);
1822 fish->name = NULL((void*)0);
1823
1824 if (fish->image)
1825 g_free (fish->image);
1826 fish->image = NULL((void*)0);
1827
1828 if (fish->command)
1829 g_free (fish->command);
1830 fish->command = NULL((void*)0);
1831
1832 if (fish->surface)
1833 cairo_surface_destroy (fish->surface);
1834 fish->surface = NULL((void*)0);
1835 fish->surface_width = 0;
1836 fish->surface_height = 0;
1837
1838 if (fish->pixbuf)
1839 g_object_unref (fish->pixbuf);
1840 fish->pixbuf = NULL((void*)0);
1841
1842 if (fish->preferences_dialog)
1843 ctk_widget_destroy (fish->preferences_dialog);
1844 fish->preferences_dialog = NULL((void*)0);
1845
1846 if (fish->fortune_dialog)
1847 ctk_widget_destroy (fish->fortune_dialog);
1848 fish->fortune_dialog = NULL((void*)0);
1849
1850 if (fish->source_id)
1851 g_source_remove (fish->source_id);
1852 fish->source_id = 0;
1853
1854 fish_close_channel (fish);
1855
1856 G_OBJECT_CLASS (parent_class)((((GObjectClass*) (void *) g_type_check_class_cast ((GTypeClass
*) ((parent_class)), (((GType) ((20) << (2))))))))
->dispose (object);
1857}
1858
1859static void fish_applet_instance_init (FishApplet *fish,
1860 FishAppletClass *klass G_GNUC_UNUSED__attribute__ ((__unused__)))
1861{
1862 fish->name = NULL((void*)0);
1863 fish->image = NULL((void*)0);
1864 fish->command = NULL((void*)0);
1865 fish->n_frames = 1;
1866 fish->speed = 0.0;
1867 fish->rotate = FALSE(0);
1868
1869 fish->orientation = CAFE_PANEL_APPLET_ORIENT_UP;
1870
1871 fish->frame = NULL((void*)0);
1872 fish->drawing_area = NULL((void*)0);
1873 fish->surface = NULL((void*)0);
1874 fish->timeout = 0;
1875 fish->current_frame = 0;
1876 fish->in_applet = FALSE(0);
1877
1878 fish->requisition.width = -1;
1879 fish->requisition.height = -1;
1880
1881 fish->prev_allocation.x = -1;
1882 fish->prev_allocation.y = -1;
1883 fish->prev_allocation.width = -1;
1884 fish->prev_allocation.height = -1;
1885
1886 fish->pixbuf = NULL((void*)0);
1887
1888 fish->preferences_dialog = NULL((void*)0);
1889 fish->name_entry = NULL((void*)0);
1890 fish->command_label = NULL((void*)0);
1891 fish->command_entry = NULL((void*)0);
1892 fish->preview_image = NULL((void*)0);
1893 fish->image_chooser = NULL((void*)0);
1894 fish->frames_spin = NULL((void*)0);
1895 fish->speed_spin = NULL((void*)0);
1896 fish->rotate_toggle = NULL((void*)0);
1897
1898 fish->fortune_dialog = NULL((void*)0);
1899 fish->fortune_view = NULL((void*)0);
1900 fish->fortune_label = NULL((void*)0);
1901 fish->fortune_cmd_label = NULL((void*)0);
1902 fish->fortune_buffer = NULL((void*)0);
1903
1904 fish->source_id = 0;
1905 fish->io_channel = NULL((void*)0);
1906
1907 fish->april_fools = FALSE(0);
1908
1909 cafe_panel_applet_set_flags (CAFE_PANEL_APPLET (fish)((((CafePanelApplet*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((fish)), ((cafe_panel_applet_get_type ()))))))
, CAFE_PANEL_APPLET_EXPAND_MINOR);
1910
1911 cafe_panel_applet_set_background_widget(CAFE_PANEL_APPLET(fish)((((CafePanelApplet*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((fish)), ((cafe_panel_applet_get_type ()))))))
, CTK_WIDGET(fish)((((CtkWidget*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((fish)), ((ctk_widget_get_type ()))))))
);
1912}
1913
1914static void fish_applet_class_init(FishAppletClass* klass)
1915{
1916 CafePanelAppletClass* applet_class = (CafePanelAppletClass*) klass;
1917 GObjectClass *gobject_class = (GObjectClass *) klass;
1918
1919 parent_class = g_type_class_peek_parent(klass);
1920
1921 applet_class->change_orient = fish_applet_change_orient;
1922
1923 gobject_class->dispose = fish_applet_dispose;
1924
1925 init_fools_day();
1926}
1927
1928static GType fish_applet_get_type(void)
1929{
1930 static GType type = 0;
1931
1932 if (!type)
1933 {
1934 static const GTypeInfo info = {
1935 sizeof(CafePanelAppletClass),
1936 NULL((void*)0), NULL((void*)0),
1937 (GClassInitFunc) fish_applet_class_init,
1938 NULL((void*)0), NULL((void*)0),
1939 sizeof(FishApplet),
1940 0,
1941 (GInstanceInitFunc) fish_applet_instance_init,
1942 NULL((void*)0)
1943 };
1944
1945 type = g_type_register_static(PANEL_TYPE_APPLET(cafe_panel_applet_get_type ()), "FishApplet", &info, 0);
1946 }
1947
1948 return type;
1949}
1950
1951#ifdef FISH_INPROCESS
1952 CAFE_PANEL_APPLET_IN_PROCESS_FACTORY("FishAppletFactory", fish_applet_get_type(), "That-stupid-fish", fishy_factory, NULL)gboolean _cafe_panel_applet_shlib_factory (void); __attribute__
((visibility("default"))) gint _cafe_panel_applet_shlib_factory
(void) { do { bindtextdomain ("cafe-panel", "/usr/share/locale"
); bind_textdomain_codeset ("cafe-panel", "UTF-8"); if ((0)) textdomain
("cafe-panel"); } while (0); return cafe_panel_applet_factory_setup_in_process
("FishAppletFactory", fish_applet_get_type(), fishy_factory,
((void*)0)); }
1953#else
1954 CAFE_PANEL_APPLET_OUT_PROCESS_FACTORY("FishAppletFactory", fish_applet_get_type(), "That-stupid-fish", fishy_factory, NULL)int main(int argc, char* argv[]) { GOptionContext* context; GError
* error; int retval; do { bindtextdomain ("cafe-panel", "/usr/share/locale"
); bind_textdomain_codeset ("cafe-panel", "UTF-8"); if ((!(0)
)) textdomain ("cafe-panel"); } while (0); context = g_option_context_new
(""); g_option_context_add_group (context, ctk_get_option_group
((!(0)))); error = ((void*)0); if (!g_option_context_parse (context
, &argc, &argv, &error)) { if (error) { g_printerr
("Cannot parse arguments: %s.\n", error->message); g_error_free
(error); } else { g_printerr ("Cannot parse arguments.\n"); }
g_option_context_free (context); return 1; } ctk_init (&
argc, &argv); retval = cafe_panel_applet_factory_main ("FishAppletFactory"
,(!(0)), fish_applet_get_type(), fishy_factory, ((void*)0)); g_option_context_free
(context); return retval; }
1955#endif