Bug Summary

File:capplets/time-admin/src/time-map.c
Warning:line 620, column 9
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 time-map.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/capplets/time-admin/src -fcoverage-compilation-dir=/rootdir/capplets/time-admin/src -resource-dir /usr/lib/llvm-21/lib/clang/21 -D HAVE_CONFIG_H -I . -I ../../.. -I ../../../capplets/common -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/libxml2 -I /usr/include/cafe-desktop-2.0 -I /usr/include/startup-notification-1.0 -I /usr/include/dconf -I ../../../ -D G_LOG_DOMAIN="time-admin-properties" -I /usr/include/dbus-1.0 -I /usr/lib/x86_64-linux-gnu/dbus-1.0/include -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/polkit-1 -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/libmount -I /usr/include/blkid -I /usr/include/gio-unix-2.0 -D TIMPZONEDIR="/usr/share/cafe-time-admin/map/" -internal-isystem /usr/lib/llvm-21/lib/clang/21/include -internal-isystem /usr/local/include -internal-isystem /usr/lib/gcc/x86_64-linux-gnu/15/../../../../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 security.ArrayBound -analyzer-checker unix.cstring.NotNullTerminated -analyzer-checker alpha.deadcode.UnreachableCode -analyzer-checker alpha.core.CastToStruct -analyzer-checker alpha.security.ReturnPtrRange -analyzer-checker alpha.unix.SimpleStream -analyzer-checker alpha.unix.cstring.BufferOverlap -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/2026-01-01-163305-110760-1 -x c time-map.c
1/*
2 * Copyright (C) 2022 Pablo Barciela
3 * Copyright (C) 2019-2020 MATE Developers
4 * Copyright (C) 2018, 2019 zhuyaliang https://github.com/zhuyaliang/
5 * Copyright (C) 2010-2018 The GNOME Project
6 * Copyright (C) 2010 Intel, Inc
7 *
8 * Portions from Ubiquity, Copyright (C) 2009 Canonical Ltd.
9 * Written by Evan Dandrea <evand@ubuntu.com>
10 *
11 * This program is free software: you can redistribute it and/or modify
12 * it under the terms of the GNU General Public License as published by
13 * the Free Software Foundation, either version 3 of the License, or
14 * (at your option) any later version.
15 *
16 * This program is distributed in the hope that it will be useful,
17 * but WITHOUT ANY WARRANTY; without even the implied warranty of
18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 * GNU General Public License for more details.
20 *
21 * You should have received a copy of the GNU General Public License
22 * along with this program. If not, see <https://www.gnu.org/licenses/>.
23 *
24 * Author: Thomas Wood <thomas.wood@intel.com>
25 *
26 */
27
28#ifdef HAVE_CONFIG_H1
29#include "config.h"
30#endif
31#include "time-map.h"
32#include <math.h>
33
34#define PIN_HOT_POINT_X8 8
35#define PIN_HOT_POINT_Y15 15
36
37typedef struct
38{
39 gdouble offset;
40 guchar red;
41 guchar green;
42 guchar blue;
43 guchar alpha;
44}TimezoneMapOffset;
45enum
46{
47 LOCATION_CHANGED,
48 LAST_SIGNAL
49};
50
51G_DEFINE_TYPE (TimezoneMap, timezone_map, CTK_TYPE_WIDGET)static void timezone_map_init (TimezoneMap *self); static void
timezone_map_class_init (TimezoneMapClass *klass); static GType
timezone_map_get_type_once (void); static gpointer timezone_map_parent_class
= ((void*)0); static gint TimezoneMap_private_offset; static
void timezone_map_class_intern_init (gpointer klass) { timezone_map_parent_class
= g_type_class_peek_parent (klass); if (TimezoneMap_private_offset
!= 0) g_type_class_adjust_private_offset (klass, &TimezoneMap_private_offset
); timezone_map_class_init ((TimezoneMapClass*) klass); } __attribute__
((__unused__)) static inline gpointer timezone_map_get_instance_private
(TimezoneMap *self) { return (((gpointer) ((guint8*) (self) +
(glong) (TimezoneMap_private_offset)))); } GType timezone_map_get_type
(void) { static GType static_g_define_type_id = 0; if ((__extension__
({ _Static_assert (sizeof *(&static_g_define_type_id) ==
sizeof (gpointer), "Expression evaluates to false"); (void) (
0 ? (gpointer) * (&static_g_define_type_id) : ((void*)0))
; (!(__extension__ ({ _Static_assert (sizeof *(&static_g_define_type_id
) == sizeof (gpointer), "Expression evaluates to false"); __typeof__
(*(&static_g_define_type_id)) gapg_temp_newval; __typeof__
((&static_g_define_type_id)) gapg_temp_atomic = (&static_g_define_type_id
); __atomic_load (gapg_temp_atomic, &gapg_temp_newval, 5)
; gapg_temp_newval; })) && g_once_init_enter_pointer (
&static_g_define_type_id)); })) ) { GType g_define_type_id
= timezone_map_get_type_once (); (__extension__ ({ _Static_assert
(sizeof *(&static_g_define_type_id) == sizeof (gpointer)
, "Expression evaluates to false"); 0 ? (void) (*(&static_g_define_type_id
) = (g_define_type_id)) : (void) 0; g_once_init_leave_pointer
((&static_g_define_type_id), (gpointer) (guintptr) (g_define_type_id
)); })) ; } return static_g_define_type_id; } __attribute__ (
(__noinline__)) static GType timezone_map_get_type_once (void
) { GType g_define_type_id = g_type_register_static_simple ((
ctk_widget_get_type ()), g_intern_static_string ("TimezoneMap"
), sizeof (TimezoneMapClass), (GClassInitFunc)(void (*)(void)
) timezone_map_class_intern_init, sizeof (TimezoneMap), (GInstanceInitFunc
)(void (*)(void)) timezone_map_init, (GTypeFlags) 0); { {{};}
} return g_define_type_id; }
52static guint signals[LAST_SIGNAL];
53static TimezoneMapOffset color_codes[] =
54{
55 {-11.0, 43, 0, 0, 255 },
56 {-10.0, 85, 0, 0, 255 },
57 {-9.5, 102, 255, 0, 255 },
58 {-9.0, 128, 0, 0, 255 },
59 {-8.0, 170, 0, 0, 255 },
60 {-7.0, 212, 0, 0, 255 },
61 {-6.0, 255, 0, 1, 255 }, // north
62 {-6.0, 255, 0, 0, 255 }, // south
63 {-5.0, 255, 42, 42, 255 },
64 {-4.5, 192, 255, 0, 255 },
65 {-4.0, 255, 85, 85, 255 },
66 {-3.5, 0, 255, 0, 255 },
67 {-3.0, 255, 128, 128, 255 },
68 {-2.0, 255, 170, 170, 255 },
69 {-1.0, 255, 213, 213, 255 },
70 {0.0, 43, 17, 0, 255 },
71 {1.0, 85, 34, 0, 255 },
72 {2.0, 128, 51, 0, 255 },
73 {3.0, 170, 68, 0, 255 },
74 {3.5, 0, 255, 102, 255 },
75 {4.0, 212, 85, 0, 255 },
76 {4.5, 0, 204, 255, 255 },
77 {5.0, 255, 102, 0, 255 },
78 {5.5, 0, 102, 255, 255 },
79 {5.75, 0, 238, 207, 247 },
80 {6.0, 255, 127, 42, 255 },
81 {6.5, 204, 0, 254, 254 },
82 {7.0, 255, 153, 85, 255 },
83 {8.0, 255, 179, 128, 255 },
84 {9.0, 255, 204, 170, 255 },
85 {9.5, 170, 0, 68, 250 },
86 {10.0, 255, 230, 213, 255 },
87 {10.5, 212, 124, 21, 250 },
88 {11.0, 212, 170, 0, 255 },
89 {11.5, 249, 25, 87, 253 },
90 {12.0, 255, 204, 0, 255 },
91 {12.75, 254, 74, 100, 248 },
92 {13.0, 255, 85, 153, 250 },
93 {-100, 0, 0, 0, 0 }
94};
95static void
96cc_timezone_map_dispose (GObject *object)
97{
98 TimezoneMap *self = TIMEZONEMAP (object)((((TimezoneMap*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((object)), ((timezone_map_get_type ()))))))
;
99
100 g_clear_object (&self->orig_background)do { _Static_assert (sizeof *((&self->orig_background)
) == sizeof (gpointer), "Expression evaluates to false"); __typeof__
(((&self->orig_background))) _pp = ((&self->orig_background
)); __typeof__ (*((&self->orig_background))) _ptr = *_pp
; *_pp = ((void*)0); if (_ptr) (g_object_unref) (_ptr); } while
(0)
;
101 g_clear_object (&self->orig_background_dim)do { _Static_assert (sizeof *((&self->orig_background_dim
)) == sizeof (gpointer), "Expression evaluates to false"); __typeof__
(((&self->orig_background_dim))) _pp = ((&self->
orig_background_dim)); __typeof__ (*((&self->orig_background_dim
))) _ptr = *_pp; *_pp = ((void*)0); if (_ptr) (g_object_unref
) (_ptr); } while (0)
;
102 g_clear_object (&self->orig_color_map)do { _Static_assert (sizeof *((&self->orig_color_map))
== sizeof (gpointer), "Expression evaluates to false"); __typeof__
(((&self->orig_color_map))) _pp = ((&self->orig_color_map
)); __typeof__ (*((&self->orig_color_map))) _ptr = *_pp
; *_pp = ((void*)0); if (_ptr) (g_object_unref) (_ptr); } while
(0)
;
103 g_clear_object (&self->background)do { _Static_assert (sizeof *((&self->background)) == sizeof
(gpointer), "Expression evaluates to false"); __typeof__ (((
&self->background))) _pp = ((&self->background)
); __typeof__ (*((&self->background))) _ptr = *_pp; *_pp
= ((void*)0); if (_ptr) (g_object_unref) (_ptr); } while (0)
;
104 g_clear_object (&self->pin)do { _Static_assert (sizeof *((&self->pin)) == sizeof (
gpointer), "Expression evaluates to false"); __typeof__ (((&
self->pin))) _pp = ((&self->pin)); __typeof__ (*((&
self->pin))) _ptr = *_pp; *_pp = ((void*)0); if (_ptr) (g_object_unref
) (_ptr); } while (0)
;
105 g_clear_pointer (&self->bubble_text, g_free)do { _Static_assert (sizeof *(&self->bubble_text) == sizeof
(gpointer), "Expression evaluates to false"); __typeof__ ((&
self->bubble_text)) _pp = (&self->bubble_text); __typeof__
(*(&self->bubble_text)) _ptr = *_pp; *_pp = ((void*)0
); if (_ptr) (g_free) (_ptr); } while (0)
;
106
107 if (self->color_map)
108 {
109 g_clear_object (&self->color_map)do { _Static_assert (sizeof *((&self->color_map)) == sizeof
(gpointer), "Expression evaluates to false"); __typeof__ (((
&self->color_map))) _pp = ((&self->color_map));
__typeof__ (*((&self->color_map))) _ptr = *_pp; *_pp =
((void*)0); if (_ptr) (g_object_unref) (_ptr); } while (0)
;
110
111 self->visible_map_pixels = NULL((void*)0);
112 self->visible_map_rowstride = 0;
113 }
114
115 G_OBJECT_CLASS (timezone_map_parent_class)((((GObjectClass*) (void *) g_type_check_class_cast ((GTypeClass
*) ((timezone_map_parent_class)), (((GType) ((20) << (2
))))))))
->dispose (object);
116}
117static void
118timezone_map_finalize (GObject *object)
119{
120 TimezoneMap *self = TIMEZONEMAP (object)((((TimezoneMap*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((object)), ((timezone_map_get_type ()))))))
;
121
122 g_clear_pointer (&self->tzdb, TimeZoneDateBaseFree)do { _Static_assert (sizeof *(&self->tzdb) == sizeof (
gpointer), "Expression evaluates to false"); __typeof__ ((&
self->tzdb)) _pp = (&self->tzdb); __typeof__ (*(&
self->tzdb)) _ptr = *_pp; *_pp = ((void*)0); if (_ptr) (TimeZoneDateBaseFree
) (_ptr); } while (0)
;
123
124 G_OBJECT_CLASS (timezone_map_parent_class)((((GObjectClass*) (void *) g_type_check_class_cast ((GTypeClass
*) ((timezone_map_parent_class)), (((GType) ((20) << (2
))))))))
->finalize (object);
125}
126static void
127cc_timezone_map_get_preferred_width (CtkWidget *widget,
128 gint *minimum,
129 gint *natural)
130{
131 TimezoneMap *map = TIMEZONEMAP (widget)((((TimezoneMap*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((widget)), ((timezone_map_get_type ()))))))
;
132 gint size;
133
134 size = gdk_pixbuf_get_width (map->orig_background);
135
136 if (minimum != NULL((void*)0))
137 *minimum = size;
138 if (natural != NULL((void*)0))
139 *natural = size;
140}
141
142static void
143cc_timezone_map_get_preferred_height (CtkWidget *widget,
144 gint *minimum,
145 gint *natural)
146{
147 TimezoneMap *map = TIMEZONEMAP (widget)((((TimezoneMap*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((widget)), ((timezone_map_get_type ()))))))
;
148 gint size;
149
150 size = gdk_pixbuf_get_height (map->orig_background);
151
152 if (minimum != NULL((void*)0))
153 *minimum = size;
154 if (natural != NULL((void*)0))
155 *natural = size;
156}
157static void
158cc_timezone_map_size_allocate (CtkWidget *widget,
159 CtkAllocation *allocation)
160{
161 TimezoneMap *map = TIMEZONEMAP (widget)((((TimezoneMap*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((widget)), ((timezone_map_get_type ()))))))
;
162 GdkPixbuf *pixbuf;
163
164 if (map->background)
165 g_object_unref (map->background);
166
167 if (!ctk_widget_is_sensitive (widget))
168 pixbuf = map->orig_background_dim;
169 else
170 pixbuf = map->orig_background;
171
172 map->background = gdk_pixbuf_scale_simple (pixbuf,
173 allocation->width,
174 allocation->height,
175 GDK_INTERP_BILINEAR);
176
177 if (map->color_map)
178 g_object_unref (map->color_map);
179
180 map->color_map = gdk_pixbuf_scale_simple (map->orig_color_map,
181 allocation->width,
182 allocation->height,
183 GDK_INTERP_BILINEAR);
184
185 map->visible_map_pixels = gdk_pixbuf_get_pixels (map->color_map);
186 map->visible_map_rowstride = gdk_pixbuf_get_rowstride (map->color_map);
187 CTK_WIDGET_CLASS (timezone_map_parent_class)((((CtkWidgetClass*) (void *) g_type_check_class_cast ((GTypeClass
*) ((timezone_map_parent_class)), ((ctk_widget_get_type ())))
)))
->size_allocate (widget,
188 allocation);
189}
190
191static void
192cc_timezone_map_realize (CtkWidget *widget)
193{
194 CdkWindowAttr attr = { 0, };
195 CtkAllocation allocation;
196 CdkWindow *window;
197
198 ctk_widget_get_allocation (widget, &allocation);
199
200 ctk_widget_set_realized (widget, TRUE(!(0)));
201
202 attr.window_type = CDK_WINDOW_CHILD;
203 attr.wclass = CDK_INPUT_OUTPUT;
204 attr.width = allocation.width;
205 attr.height = allocation.height;
206 attr.x = allocation.x;
207 attr.y = allocation.y;
208 attr.event_mask = ctk_widget_get_events (widget)
209 | CDK_EXPOSURE_MASK | CDK_BUTTON_PRESS_MASK;
210
211 window = cdk_window_new (ctk_widget_get_parent_window (widget), &attr,
212 CDK_WA_X | CDK_WA_Y);
213
214 cdk_window_set_user_data (window, widget);
215 ctk_widget_set_window (widget, window);
216}
217static gdouble
218convert_longitude_to_x (gdouble longitude, gint map_width)
219{
220 const gdouble xdeg_offset = -6;
221 gdouble x;
222
223 x = (map_width * (180.0 + longitude) / 360.0)
224 + (map_width * xdeg_offset / 180.0);
225
226 return x;
227}
228
229static gdouble
230radians (gdouble degrees)
231{
232 return (degrees / 360.0) * G_PI3.1415926535897932384626433832795028841971693993751 * 2;
233}
234
235static gdouble
236convert_latitude_to_y (gdouble latitude, gdouble map_height)
237{
238 gdouble bottom_lat = -59;
239 gdouble top_lat = 81;
240 gdouble top_per, y, full_range, top_offset, map_range;
241
242 top_per = top_lat / 180.0;
243 y = 1.25 * log (tan (G_PI_40.78539816339744830961566084581987572104929234984378 + 0.4 * radians (latitude)));
244 full_range = 4.6068250867599998;
245 top_offset = full_range * top_per;
246 map_range = fabs (1.25 * log (tan (G_PI_40.78539816339744830961566084581987572104929234984378 + 0.4 * radians (bottom_lat))) - top_offset);
247 y = fabs (y - top_offset);
248 y = y / map_range;
249 y = y * map_height;
250 return y;
251}
252
253
254static void
255draw_text_bubble (cairo_t *cr,
256 CtkWidget *widget,
257 gdouble pointx,
258 gdouble pointy)
259{
260 static const double corner_radius = 9.0;
261 static const double margin_top = 12.0;
262 static const double margin_bottom = 12.0;
263 static const double margin_left = 24.0;
264 static const double margin_right = 24.0;
265
266 TimezoneMap *map = TIMEZONEMAP (widget)((((TimezoneMap*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((widget)), ((timezone_map_get_type ()))))))
;
267 CtkAllocation alloc;
268 PangoLayout *layout;
269 PangoRectangle text_rect;
270 double x;
271 double y;
272 double width;
273 double height;
274
275 if (!map->bubble_text)
276 return;
277
278 ctk_widget_get_allocation (widget, &alloc);
279 layout = ctk_widget_create_pango_layout (widget, NULL((void*)0));
280 /* Layout the text */
281 pango_layout_set_alignment (layout, PANGO_ALIGN_CENTER);
282 pango_layout_set_spacing (layout, 3);
283 pango_layout_set_markup (layout, map->bubble_text, -1);
284
285 pango_layout_get_pixel_extents (layout, NULL((void*)0), &text_rect);
286
287 /* Calculate the bubble size based on the text layout size */
288 width = text_rect.width + margin_left + margin_right;
289 height = text_rect.height + margin_top + margin_bottom;
290
291 if (pointx < alloc.width / 2)
292 x = pointx + 25;
293 else
294 x = pointx - width - 25;
295
296 y = pointy - height / 2;
297
298 /* Make sure it fits in the visible area */
299 x = CLAMP (x, 0, alloc.width - width)(((x) > (alloc.width - width)) ? (alloc.width - width) : (
((x) < (0)) ? (0) : (x)))
;
300 y = CLAMP (y, 0, alloc.height - height)(((y) > (alloc.height - height)) ? (alloc.height - height)
: (((y) < (0)) ? (0) : (y)))
;
301
302 cairo_save (cr);
303 cairo_translate (cr, x, y);
304
305 /* Draw the bubble */
306 cairo_new_sub_path (cr);
307 cairo_arc (cr, width - corner_radius, corner_radius, corner_radius, radians (-90), radians (0));
308 cairo_arc (cr, width - corner_radius, height - corner_radius, corner_radius, radians (0), radians (90));
309 cairo_arc (cr, corner_radius, height - corner_radius, corner_radius, radians (90), radians (180));
310 cairo_arc (cr, corner_radius, corner_radius, corner_radius, radians (180), radians (270));
311 cairo_close_path (cr);
312
313 cairo_set_source_rgba (cr, 0.2, 0.2, 0.2, 0.7);
314 cairo_fill (cr);
315
316 /* And finally draw the text */
317 cairo_set_source_rgb (cr, 1, 1, 1);
318 cairo_move_to (cr, margin_left, margin_top);
319 pango_cairo_show_layout (cr, layout);
320
321 g_object_unref (layout);
322 cairo_restore (cr);
323}
324
325static gboolean
326cc_timezone_map_draw (CtkWidget *widget,
327 cairo_t *cr)
328{
329 TimezoneMap *map = TIMEZONEMAP (widget)((((TimezoneMap*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((widget)), ((timezone_map_get_type ()))))))
;
330 g_autoptr(GdkPixbuf)__attribute__((cleanup(glib_autoptr_cleanup_GdkPixbuf))) GdkPixbuf_autoptr orig_hilight = NULL((void*)0);
331 CtkAllocation alloc;
332 g_autofree__attribute__((cleanup(g_autoptr_cleanup_generic_gfree))) gchar *file = NULL((void*)0);
333 g_autoptr(GError)__attribute__((cleanup(glib_autoptr_cleanup_GError))) GError_autoptr err = NULL((void*)0);
334 gdouble pointx, pointy;
335 char buf[16];
336
337 ctk_widget_get_allocation (widget, &alloc);
338
339 /* paint background */
340 cdk_cairo_set_source_pixbuf (cr, map->background, 0, 0);
341 cairo_paint (cr);
342
343 /* paint hilight */
344 if (ctk_widget_is_sensitive (widget))
345 {
346 file = g_strdup_printf (TIMPZONEDIR"/usr/share/cafe-time-admin/map/""timezone_%s.png",
347 g_ascii_formatd (buf, sizeof (buf),
348 "%g", map->selected_offset));
349 }
350 else
351 {
352 file = g_strdup_printf (TIMPZONEDIR"/usr/share/cafe-time-admin/map/""timezone_%s_dim.png",
353 g_ascii_formatd (buf, sizeof (buf),
354 "%g", map->selected_offset));
355 }
356
357 orig_hilight = gdk_pixbuf_new_from_file (file, &err);
358
359 if (!orig_hilight)
360 {
361 g_warning ("Could not load hilight: %s",
362 (err) ? err->message : "Unknown Error");
363 }
364 else
365 {
366 g_autoptr(GdkPixbuf)__attribute__((cleanup(glib_autoptr_cleanup_GdkPixbuf))) GdkPixbuf_autoptr hilight = NULL((void*)0);
367
368 hilight = gdk_pixbuf_scale_simple (orig_hilight, alloc.width,
369 alloc.height, GDK_INTERP_BILINEAR);
370 cdk_cairo_set_source_pixbuf (cr, hilight, 0, 0);
371
372 cairo_paint (cr);
373 }
374
375 if (map->location)
376 {
377 pointx = convert_longitude_to_x (map->location->longitude, alloc.width);
378 pointy = convert_latitude_to_y (map->location->latitude, alloc.height);
379
380 pointx = CLAMP (floor (pointx), 0, alloc.width)(((floor (pointx)) > (alloc.width)) ? (alloc.width) : (((floor
(pointx)) < (0)) ? (0) : (floor (pointx))))
;
381 pointy = CLAMP (floor (pointy), 0, alloc.height)(((floor (pointy)) > (alloc.height)) ? (alloc.height) : ((
(floor (pointy)) < (0)) ? (0) : (floor (pointy))))
;
382
383 draw_text_bubble (cr, widget, pointx, pointy);
384 if (map->pin)
385 {
386 cdk_cairo_set_source_pixbuf (cr, map->pin,
387 pointx - PIN_HOT_POINT_X8,
388 pointy - PIN_HOT_POINT_Y15);
389 cairo_paint (cr);
390 }
391 }
392
393 return TRUE(!(0));
394}
395static void
396update_cursor (CtkWidget *widget)
397{
398 CdkWindow *window;
399 g_autoptr(CdkCursor)__attribute__((cleanup(glib_autoptr_cleanup_CdkCursor))) CdkCursor_autoptr cursor = NULL((void*)0);
400
401 if (!ctk_widget_get_realized (widget))
402 return;
403
404 if (ctk_widget_is_sensitive (widget))
405 {
406 CdkDisplay *display;
407 display = ctk_widget_get_display (widget);
408 cursor = cdk_cursor_new_for_display (display, CDK_HAND2);
409 }
410
411 window = ctk_widget_get_window (widget);
412 cdk_window_set_cursor (window, cursor);
413}
414
415static void
416cc_timezone_map_state_flags_changed (CtkWidget *widget,
417 CtkStateFlags prev_state)
418{
419 update_cursor (widget);
420
421 if (CTK_WIDGET_CLASS (timezone_map_parent_class)((((CtkWidgetClass*) (void *) g_type_check_class_cast ((GTypeClass
*) ((timezone_map_parent_class)), ((ctk_widget_get_type ())))
)))
->state_flags_changed)
422 CTK_WIDGET_CLASS (timezone_map_parent_class)((((CtkWidgetClass*) (void *) g_type_check_class_cast ((GTypeClass
*) ((timezone_map_parent_class)), ((ctk_widget_get_type ())))
)))
->state_flags_changed (widget, prev_state);
423}
424static gint sort_locations (TzLocation *a,
425 TzLocation *b)
426{
427 if (a->dist > b->dist)
428 return 1;
429
430 if (a->dist < b->dist)
431 return -1;
432
433 return 0;
434}
435
436static void
437set_location (TimezoneMap *map,
438 TzLocation *location)
439{
440 g_autoptr(TzInfo)__attribute__((cleanup(glib_autoptr_cleanup_TzInfo))) TzInfo_autoptr info = NULL((void*)0);
441
442 map->location = location;
443 info = tz_info_from_location (map->location);
444 map->selected_offset = tz_location_get_utc_offset (map->location)
445 / (60.0*60.0) +
446 ((info->daylight) ? -1.0 : 0.0);
447
448 g_signal_emit (map, signals[LOCATION_CHANGED], 0, map->location,NULL((void*)0));
449}
450
451static gboolean
452button_press_event (TimezoneMap *map,
453 CdkEventButton *event)
454{
455 gint x, y;
456 guchar r, g, b, a;
457 guchar *pixels;
458 gint rowstride;
459 guint i;
460
461 const GPtrArray *array;
462 gint width, height;
463 GList *distances = NULL((void*)0);
464 CtkAllocation alloc;
465
466 x = event->x;
467 y = event->y;
468
469
470 rowstride = map->visible_map_rowstride;
471 pixels = map->visible_map_pixels;
472
473 r = pixels[(rowstride * y + x * 4)];
474 g = pixels[(rowstride * y + x * 4) + 1];
475 b = pixels[(rowstride * y + x * 4) + 2];
476 a = pixels[(rowstride * y + x * 4) + 3];
477
478
479 for (i = 0; color_codes[i].offset != -100; i++)
480 {
481 if (color_codes[i].red == r && color_codes[i].green == g
482 && color_codes[i].blue == b && color_codes[i].alpha == a)
483 {
484 map->selected_offset = color_codes[i].offset;
485 }
486 }
487
488 ctk_widget_queue_draw (CTK_WIDGET (map)((((CtkWidget*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((map)), ((ctk_widget_get_type ()))))))
);
489
490 /* work out the co-ordinates */
491
492 array = tz_get_locations (map->tzdb);
493
494 ctk_widget_get_allocation (CTK_WIDGET (map)((((CtkWidget*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((map)), ((ctk_widget_get_type ()))))))
, &alloc);
495 width = alloc.width;
496 height = alloc.height;
497
498 for (i = 0; i < array->len; i++)
499 {
500 gdouble pointx, pointy, dx, dy;
501 TzLocation *loc = array->pdata[i];
502
503 pointx = convert_longitude_to_x (loc->longitude, width);
504 pointy = convert_latitude_to_y (loc->latitude, height);
505
506 dx = pointx - x;
507 dy = pointy - y;
508
509 loc->dist = dx * dx + dy * dy;
510 distances = g_list_prepend (distances, loc);
511
512 }
513 distances = g_list_sort (distances, (GCompareFunc) sort_locations);
514
515 set_location (map, (TzLocation*) distances->data);
516
517 g_list_free (distances);
518
519 return TRUE(!(0));
520}
521
522static void
523timezone_map_class_init (TimezoneMapClass *klass)
524{
525 GObjectClass *object_class = G_OBJECT_CLASS (klass)((((GObjectClass*) (void *) g_type_check_class_cast ((GTypeClass
*) ((klass)), (((GType) ((20) << (2))))))))
;
526 CtkWidgetClass *widget_class = CTK_WIDGET_CLASS (klass)((((CtkWidgetClass*) (void *) g_type_check_class_cast ((GTypeClass
*) ((klass)), ((ctk_widget_get_type ()))))))
;
527
528 object_class->dispose = cc_timezone_map_dispose;
529 object_class->finalize = timezone_map_finalize;
530
531 widget_class->get_preferred_width = cc_timezone_map_get_preferred_width;
532 widget_class->get_preferred_height = cc_timezone_map_get_preferred_height;
533 widget_class->size_allocate = cc_timezone_map_size_allocate;
534 widget_class->realize = cc_timezone_map_realize;
535 widget_class->draw = cc_timezone_map_draw;
536 widget_class->state_flags_changed = cc_timezone_map_state_flags_changed;
537
538
539 signals[LOCATION_CHANGED] = g_signal_new ("location-changed",
540 TYPE_TIMEZONE_MAP(timezone_map_get_type ()),
541 G_SIGNAL_RUN_FIRST,
542 0,
543 NULL((void*)0),
544 NULL((void*)0),
545 g_cclosure_marshal_VOID__POINTER,
546 G_TYPE_NONE((GType) ((1) << (2))), 1,
547 G_TYPE_POINTER((GType) ((17) << (2))));
548}
549
550static void
551timezone_map_init (TimezoneMap *map)
552{
553 GError *err = NULL((void*)0);
554
555 map->orig_background = gdk_pixbuf_new_from_file (TIMPZONEDIR"/usr/share/cafe-time-admin/map/""bg.png",&err);
556 if (!map->orig_background)
557 {
558 g_warning ("Could not load background image: %s",
559 (err) ? err->message : "Unknown error");
560 g_clear_error (&err);
561 }
562 map->orig_background_dim = gdk_pixbuf_new_from_file(TIMPZONEDIR"/usr/share/cafe-time-admin/map/""bg_dim.png",&err);
563 if (!map->orig_background_dim)
564 {
565 g_warning ("Could not load background image: %s",
566 (err) ? err->message : "Unknown error");
567 g_clear_error (&err);
568 }
569
570 map->orig_color_map = gdk_pixbuf_new_from_file (TIMPZONEDIR"/usr/share/cafe-time-admin/map/""cc.png",&err);
571 if (!map->orig_color_map)
572 {
573 g_warning ("Could not load background image: %s",
574 (err) ? err->message : "Unknown error");
575 g_clear_error (&err);
576 }
577
578 map->pin = gdk_pixbuf_new_from_file (TIMPZONEDIR"/usr/share/cafe-time-admin/map/""pin.png",&err);
579 if (!map->pin)
580 {
581 g_warning ("Could not load pin icon: %s",
582 (err) ? err->message : "Unknown error");
583 g_clear_error (&err);
584 }
585
586 map->tzdb = tz_load_db ();
587
588 g_signal_connect_object (map,
589 "button-press-event",
590 G_CALLBACK (button_press_event)((GCallback) (button_press_event)),
591 map,
592 G_CONNECT_SWAPPED);
593}
594gboolean timezone_map_set_timezone (TimezoneMap *map,
595 const gchar *timezone)
596{
597 GPtrArray *locations;
598 guint i;
599 g_autofree__attribute__((cleanup(g_autoptr_cleanup_generic_gfree))) gchar *real_tz = NULL((void*)0);
600 gboolean ret;
601
602 real_tz = tz_info_get_clean_name (map->tzdb, timezone);
603
604 locations = tz_get_locations (map->tzdb);
605 ret = FALSE(0);
606
607 for (i = 0; i < locations->len; i++)
608 {
609 TzLocation *loc = locations->pdata[i];
610
611 if (!g_strcmp0 (loc->zone, real_tz ? real_tz : timezone))
612 {
613 set_location (map, loc);
614 ret = TRUE(!(0));
615 break;
616 }
617 }
618
619 if (ret)
620 ctk_widget_queue_draw (CTK_WIDGET (map)((((CtkWidget*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((map)), ((ctk_widget_get_type ()))))))
);
This statement is never executed
621
622 return ret;
623}
624TzLocation *timezone_map_get_location (TimezoneMap *map)
625{
626 return map->location;
627}
628void timezone_map_set_bubble_text (TimezoneMap *map,
629 const gchar *text)
630{
631 g_free (map->bubble_text);
632 map->bubble_text = g_strdup (text)g_strdup_inline (text);
633 ctk_widget_queue_draw (CTK_WIDGET (map)((((CtkWidget*) (void *) g_type_check_instance_cast ((GTypeInstance
*) ((map)), ((ctk_widget_get_type ()))))))
);
634}
635
636TimezoneMap * timezone_map_new (void)
637{
638 return g_object_new (TYPE_TIMEZONE_MAP(timezone_map_get_type ()), NULL((void*)0));
639}