Bug Summary

File:weather.c
Warning:line 497, column 9
Value stored to 'location' is never read

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 weather.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 -fhalf-no-semantic-interposition -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 -fcoverage-compilation-dir=/rootdir/libcafeweather -resource-dir /usr/lib/llvm-16/lib/clang/16 -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/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 .. -I . -I /usr/include/libxml2 -I /usr/include/libsoup-3.0 -I /usr/include/glib-2.0 -I /usr/lib/x86_64-linux-gnu/glib-2.0/include -I /usr/include/libmount -I /usr/include/blkid -I /usr/include/sysprof-6 -I /usr/include/glib-2.0 -I /usr/lib/x86_64-linux-gnu/glib-2.0/include -I /usr/include/libmount -I /usr/include/blkid -D G_LOG_DOMAIN="CafeWeather" -D CAFELOCALEDIR="/usr/share/locale" -D CAFEWEATHER_XML_LOCATION_DIR="/usr/share/libcafeweather" -D PIC -internal-isystem /usr/lib/llvm-16/lib/clang/16/include -internal-isystem /usr/local/include -internal-isystem /usr/lib/gcc/x86_64-linux-gnu/13/../../../../x86_64-linux-gnu/include -internal-externc-isystem /usr/include/x86_64-linux-gnu -internal-externc-isystem /include -internal-externc-isystem /usr/include -fdebug-compilation-dir=/rootdir/libcafeweather -ferror-limit 19 -fgnuc-version=4.2.1 -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.core.SizeofPtr -analyzer-checker alpha.security.ArrayBoundV2 -analyzer-checker alpha.security.MallocOverflow -analyzer-checker alpha.security.ReturnPtrRange -analyzer-checker alpha.unix.SimpleStream -analyzer-checker alpha.unix.cstring.BufferOverlap -analyzer-checker alpha.unix.cstring.NotNullTerminated -analyzer-checker alpha.unix.cstring.OutOfBounds -analyzer-checker alpha.core.FixedAddr -analyzer-output=html -faddrsig -D__GCC_HAVE_DWARF2_CFI_ASM=1 -o /rootdir/html-report/2024-02-11-172650-15479-1 -x c weather.c
1/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 4 -*- */
2/* weather.c - Overall weather server functions
3 *
4 * This program is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU General Public License as
6 * published by the Free Software Foundation; either version 2 of the
7 * License, or (at your option) any later version.
8 *
9 * This program is distributed in the hope that it will be useful, but
10 * WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * General Public License for more details.
13 *
14 * You should have received a copy of the GNU General Public License
15 * along with this program; if not, see
16 * <http://www.gnu.org/licenses/>.
17 */
18
19#ifdef HAVE_CONFIG_H1
20#include <config.h>
21#endif
22
23#include <stdio.h>
24#include <stdlib.h>
25#include <assert.h>
26#include <string.h>
27#include <ctype.h>
28#include <math.h>
29
30#ifdef HAVE_VALUES_H
31#include <values.h>
32#endif
33
34#include <time.h>
35#include <unistd.h>
36
37#include <gdk-pixbuf/gdk-pixbuf.h>
38
39#define CAFEWEATHER_I_KNOW_THIS_IS_UNSTABLE
40#include "weather.h"
41#include "weather-priv.h"
42
43#define MOON_PHASES36 36
44
45/**
46 * SECTION:weather
47 * @Title: weather
48 */
49
50static void _weather_internal_check (void);
51
52
53static inline void
54cafeweather_gettext_init (void)
55{
56 static gsize cafeweather_gettext_initialized = FALSE(0);
57
58 if (G_UNLIKELY (g_once_init_enter (&cafeweather_gettext_initialized))((__extension__ ({ _Static_assert (sizeof *(&cafeweather_gettext_initialized
) == sizeof (gpointer), "Expression evaluates to false"); (void
) (0 ? (gpointer) *(&cafeweather_gettext_initialized) : (
(void*)0)); (!(__extension__ ({ _Static_assert (sizeof *(&
cafeweather_gettext_initialized) == sizeof (gpointer), "Expression evaluates to false"
); __typeof__ (*(&cafeweather_gettext_initialized)) gapg_temp_newval
; __typeof__ ((&cafeweather_gettext_initialized)) gapg_temp_atomic
= (&cafeweather_gettext_initialized); __atomic_load (gapg_temp_atomic
, &gapg_temp_newval, 5); gapg_temp_newval; })) &&
g_once_init_enter (&cafeweather_gettext_initialized)); }
)))
) {
59 bindtextdomain (GETTEXT_PACKAGE"libcafeweather", CAFELOCALEDIR"/usr/share/locale");
60#ifdef HAVE_BIND_TEXTDOMAIN_CODESET
61 bind_textdomain_codeset (GETTEXT_PACKAGE"libcafeweather", "UTF-8");
62#endif
63 g_once_init_leave (&cafeweather_gettext_initialized, TRUE)(__extension__ ({ _Static_assert (sizeof *(&cafeweather_gettext_initialized
) == sizeof (gpointer), "Expression evaluates to false"); 0 ?
(void) (*(&cafeweather_gettext_initialized) = ((!(0)))) :
(void) 0; g_once_init_leave ((&cafeweather_gettext_initialized
), (gsize) ((!(0)))); }))
;
64 }
65}
66
67const char *
68cafeweather_gettext (const char *str)
69{
70 cafeweather_gettext_init ();
71 return dgettext (GETTEXT_PACKAGE"libcafeweather", str);
72}
73
74const char *
75cafeweather_dpgettext (const char *context,
76 const char *str)
77{
78 cafeweather_gettext_init ();
79 return g_dpgettext2 (GETTEXT_PACKAGE"libcafeweather", context, str);
80}
81
82/*
83 * Convert string of the form "DD-MM-SSH" to radians
84 * DD:degrees (to 3 digits), MM:minutes, SS:seconds H:hemisphere (NESW)
85 * Return value is positive for N,E; negative for S,W.
86 */
87static gdouble
88dmsh2rad (const gchar *latlon)
89{
90 char *p1, *p2;
91 int deg, min, sec, dir;
92 gdouble value;
93
94 if (latlon == NULL((void*)0))
95 return DBL_MAX1.7976931348623157e+308;
96 p1 = strchr (latlon, '-');
97 p2 = strrchr (latlon, '-');
98 if (p1 == NULL((void*)0) || p1 == latlon) {
99 return DBL_MAX1.7976931348623157e+308;
100 } else if (p1 == p2) {
101 sscanf (latlon, "%d-%d", &deg, &min);
102 sec = 0;
103 } else if (p2 == 1 + p1) {
104 return DBL_MAX1.7976931348623157e+308;
105 } else {
106 sscanf (latlon, "%d-%d-%d", &deg, &min, &sec);
107 }
108 if (deg > 180 || min >= 60 || sec >= 60)
109 return DBL_MAX1.7976931348623157e+308;
110 value = (gdouble)((deg * 60 + min) * 60 + sec) * M_PI3.14159265358979323846 / 648000.;
111
112 dir = g_ascii_toupper (latlon[strlen (latlon) - 1]);
113 if (dir == 'W' || dir == 'S')
114 value = -value;
115 else if (dir != 'E' && dir != 'N' && (value != 0.0 || dir != '0'))
116 value = DBL_MAX1.7976931348623157e+308;
117 return value;
118}
119
120WeatherLocation *
121weather_location_new (const gchar *name, const gchar *code,
122 const gchar *zone, const gchar *radar,
123 const gchar *coordinates,
124 const gchar *country_code,
125 const gchar *tz_hint)
126{
127 WeatherLocation *location;
128
129 _weather_internal_check ();
130
131 location = g_new (WeatherLocation, 1)((WeatherLocation *) g_malloc_n ((1), sizeof (WeatherLocation
)))
;
132
133 /* name and metar code must be set */
134 location->name = g_strdup (name)g_strdup_inline (name);
135 location->code = g_strdup (code)g_strdup_inline (code);
136
137 if (zone) {
138 location->zone = g_strdup (zone)g_strdup_inline (zone);
139 } else {
140 location->zone = g_strdup ("------")g_strdup_inline ("------");
141 }
142
143 if (radar) {
144 location->radar = g_strdup (radar)g_strdup_inline (radar);
145 } else {
146 location->radar = g_strdup ("---")g_strdup_inline ("---");
147 }
148
149 if (location->zone[0] == '-') {
150 location->zone_valid = FALSE(0);
151 } else {
152 location->zone_valid = TRUE(!(0));
153 }
154
155 location->coordinates = NULL((void*)0);
156 if (coordinates)
157 {
158 char **pieces;
159
160 pieces = g_strsplit (coordinates, " ", -1);
161
162 if (g_strv_length (pieces) == 2)
163 {
164 location->coordinates = g_strdup (coordinates)g_strdup_inline (coordinates);
165 location->latitude = dmsh2rad (pieces[0]);
166 location->longitude = dmsh2rad (pieces[1]);
167 }
168
169 g_strfreev (pieces);
170 }
171
172 if (!location->coordinates)
173 {
174 location->coordinates = g_strdup ("---")g_strdup_inline ("---");
175 location->latitude = DBL_MAX1.7976931348623157e+308;
176 location->longitude = DBL_MAX1.7976931348623157e+308;
177 }
178
179 location->latlon_valid = (location->latitude < DBL_MAX1.7976931348623157e+308 && location->longitude < DBL_MAX1.7976931348623157e+308);
180
181 location->country_code = g_strdup (country_code)g_strdup_inline (country_code);
182 location->tz_hint = g_strdup (tz_hint)g_strdup_inline (tz_hint);
183
184 return location;
185}
186
187WeatherLocation *
188weather_location_clone (const WeatherLocation *location)
189{
190 WeatherLocation *clone;
191
192 g_return_val_if_fail (location != NULL, NULL)do { if ((location != ((void*)0))) { } else { g_return_if_fail_warning
("CafeWeather", ((const char*) (__func__)), "location != NULL"
); return (((void*)0)); } } while (0)
;
193
194 clone = weather_location_new (location->name,
195 location->code, location->zone,
196 location->radar, location->coordinates,
197 location->country_code, location->tz_hint);
198 clone->latitude = location->latitude;
199 clone->longitude = location->longitude;
200 clone->latlon_valid = location->latlon_valid;
201 return clone;
202}
203
204void
205weather_location_free (WeatherLocation *location)
206{
207 if (location) {
208 g_free (location->name);
209 g_free (location->code);
210 g_free (location->zone);
211 g_free (location->radar);
212 g_free (location->coordinates);
213 g_free (location->country_code);
214 g_free (location->tz_hint);
215
216 g_free (location);
217 }
218}
219
220gboolean
221weather_location_equal (const WeatherLocation *location1, const WeatherLocation *location2)
222{
223 /* if something is NULL, then it's TRUE if and only if both are NULL) */
224 if (location1 == NULL((void*)0) || location2 == NULL((void*)0))
225 return (location1 == location2);
226 if (!location1->code || !location2->code)
227 return (location1->code == location2->code);
228 if (!location1->name || !location2->name)
229 return (location1->name == location2->name);
230
231 return ((strcmp (location1->code, location2->code) == 0) &&
232 (strcmp (location1->name, location2->name) == 0));
233}
234
235static const gchar *wind_direction_str[] = {
236 N_("Variable")("Variable"),
237 N_("North")("North"), N_("North - NorthEast")("North - NorthEast"), N_("Northeast")("Northeast"), N_("East - NorthEast")("East - NorthEast"),
238 N_("East")("East"), N_("East - Southeast")("East - Southeast"), N_("Southeast")("Southeast"), N_("South - Southeast")("South - Southeast"),
239 N_("South")("South"), N_("South - Southwest")("South - Southwest"), N_("Southwest")("Southwest"), N_("West - Southwest")("West - Southwest"),
240 N_("West")("West"), N_("West - Northwest")("West - Northwest"), N_("Northwest")("Northwest"), N_("North - Northwest")("North - Northwest")
241};
242
243const gchar *
244weather_wind_direction_string (WeatherWindDirection wind)
245{
246 if (wind <= WIND_INVALID || wind >= WIND_LAST)
247 return _("Invalid")(cafeweather_gettext ("Invalid"));
248
249 return _(wind_direction_str[(int)wind])(cafeweather_gettext (wind_direction_str[(int)wind]));
250}
251
252static const gchar *sky_str[] = {
253 N_("Clear Sky")("Clear Sky"),
254 N_("Broken clouds")("Broken clouds"),
255 N_("Scattered clouds")("Scattered clouds"),
256 N_("Few clouds")("Few clouds"),
257 N_("Overcast")("Overcast")
258};
259
260const gchar *
261weather_sky_string (WeatherSky sky)
262{
263 if (sky <= SKY_INVALID || sky >= SKY_LAST)
264 return _("Invalid")(cafeweather_gettext ("Invalid"));
265
266 return _(sky_str[(int)sky])(cafeweather_gettext (sky_str[(int)sky]));
267}
268
269
270/*
271 * Even though tedious, I switched to a 2D array for weather condition
272 * strings, in order to facilitate internationalization, esp. for languages
273 * with genders.
274 */
275
276/*
277 * Almost all reportable combinations listed in
278 * http://www.crh.noaa.gov/arx/wx.tbl.php are entered below, except those
279 * having 2 qualifiers mixed together [such as "Blowing snow in vicinity"
280 * (VCBLSN), "Thunderstorm in vicinity" (VCTS), etc].
281 * Combinations that are not possible are filled in with "??".
282 * Some other exceptions not handled yet, such as "SN BLSN" which has
283 * special meaning.
284 */
285
286/*
287 * Note, magic numbers, when you change the size here, make sure to change
288 * the below function so that new values are recognized
289 */
290/* NONE VICINITY LIGHT MODERATE HEAVY SHALLOW PATCHES PARTIAL THUNDERSTORM BLOWING SHOWERS DRIFTING FREEZING */
291/* *******************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************/
292static const gchar *conditions_str[24][13] = {
293/* Translators: If you want to know what "blowing" "shallow" "partial"
294 * etc means, you can go to http://www.weather.com/glossary/ and
295 * http://www.crh.noaa.gov/arx/wx.tbl.php */
296 /* NONE */ {"??", "??", "??", "??", "??", "??", "??", "??", N_("Thunderstorm")("Thunderstorm"), "??", "??", "??", "??" },
297 /* DRIZZLE */ {N_("Drizzle")("Drizzle"), "??", N_("Light drizzle")("Light drizzle"), N_("Moderate drizzle")("Moderate drizzle"), N_("Heavy drizzle")("Heavy drizzle"), "??", "??", "??", "??", "??", "??", "??", N_("Freezing drizzle")("Freezing drizzle") },
298 /* RAIN */ {N_("Rain")("Rain"), "??", N_("Light rain")("Light rain"), N_("Moderate rain")("Moderate rain"), N_("Heavy rain")("Heavy rain"), "??", "??", "??", N_("Thunderstorm")("Thunderstorm"), "??", N_("Rain showers")("Rain showers"), "??", N_("Freezing rain")("Freezing rain") },
299 /* SNOW */ {N_("Snow")("Snow"), "??", N_("Light snow")("Light snow"), N_("Moderate snow")("Moderate snow"), N_("Heavy snow")("Heavy snow"), "??", "??", "??", N_("Snowstorm")("Snowstorm"), N_("Blowing snowfall")("Blowing snowfall"), N_("Snow showers")("Snow showers"), N_("Drifting snow")("Drifting snow"), "??" },
300 /* SNOW_GRAINS */ {N_("Snow grains")("Snow grains"), "??", N_("Light snow grains")("Light snow grains"), N_("Moderate snow grains")("Moderate snow grains"), N_("Heavy snow grains")("Heavy snow grains"), "??", "??", "??", "??", "??", "??", "??", "??" },
301 /* ICE_CRYSTALS */ {N_("Ice crystals")("Ice crystals"), "??", "??", N_("Ice crystals")("Ice crystals"), "??", "??", "??", "??", "??", "??", "??", "??", "??" },
302 /* ICE_PELLETS */ {N_("Ice pellets")("Ice pellets"), "??", N_("Few ice pellets")("Few ice pellets"), N_("Moderate ice pellets")("Moderate ice pellets"), N_("Heavy ice pellets")("Heavy ice pellets"), "??", "??", "??", N_("Ice pellet storm")("Ice pellet storm"), "??", N_("Showers of ice pellets")("Showers of ice pellets"), "??", "??" },
303 /* HAIL */ {N_("Hail")("Hail"), "??", "??", N_("Hail")("Hail"), "??", "??", "??", "??", N_("Hailstorm")("Hailstorm"), "??", N_("Hail showers")("Hail showers"), "??", "??", },
304 /* SMALL_HAIL */ {N_("Small hail")("Small hail"), "??", "??", N_("Small hail")("Small hail"), "??", "??", "??", "??", N_("Small hailstorm")("Small hailstorm"), "??", N_("Showers of small hail")("Showers of small hail"), "??", "??" },
305 /* PRECIPITATION */ {N_("Unknown precipitation")("Unknown precipitation"), "??", "??", "??", "??", "??", "??", "??", "??", "??", "??", "??", "??" },
306 /* MIST */ {N_("Mist")("Mist"), "??", "??", N_("Mist")("Mist"), "??", "??", "??", "??", "??", "??", "??", "??", "??" },
307 /* FOG */ {N_("Fog")("Fog"), N_("Fog in the vicinity")("Fog in the vicinity") , "??", N_("Fog")("Fog"), "??", N_("Shallow fog")("Shallow fog"), N_("Patches of fog")("Patches of fog"), N_("Partial fog")("Partial fog"), "??", "??", "??", "??", N_("Freezing fog")("Freezing fog") },
308 /* SMOKE */ {N_("Smoke")("Smoke"), "??", "??", N_("Smoke")("Smoke"), "??", "??", "??", "??", "??", "??", "??", "??", "??" },
309 /* VOLCANIC_ASH */ {N_("Volcanic ash")("Volcanic ash"), "??", "??", N_("Volcanic ash")("Volcanic ash"), "??", "??", "??", "??", "??", "??", "??", "??", "??" },
310 /* SAND */ {N_("Sand")("Sand"), "??", "??", N_("Sand")("Sand"), "??", "??", "??", "??", "??", N_("Blowing sand")("Blowing sand"), "", N_("Drifting sand")("Drifting sand"), "??" },
311 /* HAZE */ {N_("Haze")("Haze"), "??", "??", N_("Haze")("Haze"), "??", "??", "??", "??", "??", "??", "??", "??", "??" },
312 /* SPRAY */ {"??", "??", "??", "??", "??", "??", "??", "??", "??", N_("Blowing sprays")("Blowing sprays"), "??", "??", "??" },
313 /* DUST */ {N_("Dust")("Dust"), "??", "??", N_("Dust")("Dust"), "??", "??", "??", "??", "??", N_("Blowing dust")("Blowing dust"), "??", N_("Drifting dust")("Drifting dust"), "??" },
314 /* SQUALL */ {N_("Squall")("Squall"), "??", "??", N_("Squall")("Squall"), "??", "??", "??", "??", "??", "??", "??", "??", "??" },
315 /* SANDSTORM */ {N_("Sandstorm")("Sandstorm"), N_("Sandstorm in the vicinity")("Sandstorm in the vicinity") , "??", N_("Sandstorm")("Sandstorm"), N_("Heavy sandstorm")("Heavy sandstorm"), "??", "??", "??", "??", "??", "??", "??", "??" },
316 /* DUSTSTORM */ {N_("Duststorm")("Duststorm"), N_("Duststorm in the vicinity")("Duststorm in the vicinity") , "??", N_("Duststorm")("Duststorm"), N_("Heavy duststorm")("Heavy duststorm"), "??", "??", "??", "??", "??", "??", "??", "??" },
317 /* FUNNEL_CLOUD */ {N_("Funnel cloud")("Funnel cloud"), "??", "??", "??", "??", "??", "??", "??", "??", "??", "??", "??", "??" },
318 /* TORNADO */ {N_("Tornado")("Tornado"), "??", "??", "??", "??", "??", "??", "??", "??", "??", "??", "??", "??" },
319 /* DUST_WHIRLS */ {N_("Dust whirls")("Dust whirls"), N_("Dust whirls in the vicinity")("Dust whirls in the vicinity") , "??", N_("Dust whirls")("Dust whirls"), "??", "??", "??", "??", "??", "??", "??", "??", "??" }
320};
321
322const gchar *
323weather_conditions_string (WeatherConditions cond)
324{
325 const gchar *str;
326
327 if (!cond.significant) {
328 return "-";
329 } else {
330 if (cond.phenomenon > PHENOMENON_INVALID &&
331 cond.phenomenon < PHENOMENON_LAST &&
332 cond.qualifier > QUALIFIER_INVALID &&
333 cond.qualifier < QUALIFIER_LAST)
334 str = _(conditions_str[(int)cond.phenomenon][(int)cond.qualifier])(cafeweather_gettext (conditions_str[(int)cond.phenomenon][(int
)cond.qualifier]))
;
335 else
336 str = _("Invalid")(cafeweather_gettext ("Invalid"));
337 return (strlen (str) > 0) ? str : "-";
338 }
339}
340
341/* Locals turned global to facilitate asynchronous HTTP requests */
342
343
344gboolean
345requests_init (WeatherInfo *info)
346{
347 if (info->requests_pending)
348 return FALSE(0);
349
350 return TRUE(!(0));
351}
352
353void request_done (WeatherInfo *info, gboolean ok)
354{
355 if (ok) {
356 (void) calc_sun (info);
357 info->moonValid = info->valid && calc_moon (info);
358 }
359 if (!--info->requests_pending)
360 info->finish_cb (info, info->cb_data);
361}
362
363/* it's OK to pass in NULL */
364void
365free_forecast_list (WeatherInfo *info)
366{
367 GSList *p;
368
369 if (!info)
370 return;
371
372 for (p = info->forecast_list; p; p = p->next)
373 weather_info_free (p->data);
374
375 if (info->forecast_list) {
376 g_slist_free (info->forecast_list);
377 info->forecast_list = NULL((void*)0);
378 }
379}
380
381/* Relative humidity computation - thanks to <Olof.Oberg@modopaper.modogroup.com> */
382
383static inline gdouble
384calc_humidity (gdouble temp, gdouble dewp)
385{
386 gdouble esat, esurf;
387
388 if (temp > -500.0 && dewp > -500.0) {
389 temp = TEMP_F_TO_C (temp)(((temp) - 32.0) * 0.555556);
390 dewp = TEMP_F_TO_C (dewp)(((dewp) - 32.0) * 0.555556);
391
392 esat = 6.11 * pow (10.0, (7.5 * temp) / (237.7 + temp));
393 esurf = 6.11 * pow (10.0, (7.5 * dewp) / (237.7 + dewp));
394 } else {
395 esurf = -1.0;
396 esat = 1.0;
397 }
398 return ((esurf/esat) * 100.0);
399}
400
401static inline gdouble
402calc_apparent (WeatherInfo *info)
403{
404 gdouble temp = info->temp;
405 gdouble wind = WINDSPEED_KNOTS_TO_MPH (info->windspeed)((info->windspeed) * 1.150779);
406 gdouble apparent = -1000.;
407
408 /*
409 * Wind chill calculations as of 01-Nov-2001
410 * http://www.nws.noaa.gov/om/windchill/index.shtml
411 * Some pages suggest that the formula will soon be adjusted
412 * to account for solar radiation (bright sun vs cloudy sky)
413 */
414 if (temp <= 50.0) {
415 if (wind > 3.0) {
416 gdouble v = pow (wind, 0.16);
417 apparent = 35.74 + 0.6215 * temp - 35.75 * v + 0.4275 * temp * v;
418 } else if (wind >= 0.) {
419 apparent = temp;
420 }
421 }
422 /*
423 * Heat index calculations:
424 * http://www.srh.noaa.gov/fwd/heatindex/heat5.html
425 */
426 else if (temp >= 80.0) {
427 if (info->temp >= -500. && info->dew >= -500.) {
428 gdouble humidity = calc_humidity (info->temp, info->dew);
429 gdouble t2 = temp * temp;
430 gdouble h2 = humidity * humidity;
431
432#if 1
433 /*
434 * A really precise formula. Note that overall precision is
435 * constrained by the accuracy of the instruments and that the
436 * we receive the temperature and dewpoints as integers.
437 */
438 gdouble t3 = t2 * temp;
439 gdouble h3 = h2 * temp;
440
441 apparent = 16.923
442 + 0.185212 * temp
443 + 5.37941 * humidity
444 - 0.100254 * temp * humidity
445 + 9.41695e-3 * t2
446 + 7.28898e-3 * h2
447 + 3.45372e-4 * t2 * humidity
448 - 8.14971e-4 * temp * h2
449 + 1.02102e-5 * t2 * h2
450 - 3.8646e-5 * t3
451 + 2.91583e-5 * h3
452 + 1.42721e-6 * t3 * humidity
453 + 1.97483e-7 * temp * h3
454 - 2.18429e-8 * t3 * h2
455 + 8.43296e-10 * t2 * h3
456 - 4.81975e-11 * t3 * h3;
457#else
458 /*
459 * An often cited alternative: values are within 5 degrees for
460 * most ranges between 10% and 70% humidity and to 110 degrees.
461 */
462 apparent = - 42.379
463 + 2.04901523 * temp
464 + 10.14333127 * humidity
465 - 0.22475541 * temp * humidity
466 - 6.83783e-3 * t2
467 - 5.481717e-2 * h2
468 + 1.22874e-3 * t2 * humidity
469 + 8.5282e-4 * temp * h2
470 - 1.99e-6 * t2 * h2;
471#endif
472 }
473 } else {
474 apparent = temp;
475 }
476
477 return apparent;
478}
479
480WeatherInfo *
481_weather_info_fill (WeatherInfo *info,
482 WeatherLocation *location,
483 const WeatherPrefs *prefs,
484 WeatherInfoFunc cb,
485 gpointer data)
486{
487 g_return_val_if_fail (((info == NULL) && (location != NULL)) || \do { if ((((info == ((void*)0)) && (location != ((void
*)0))) || ((info != ((void*)0)) && (location == ((void
*)0))))) { } else { g_return_if_fail_warning ("CafeWeather", (
(const char*) (__func__)), "((info == NULL) && (location != NULL)) || ((info != NULL) && (location == NULL))"
); return (((void*)0)); } } while (0)
488 ((info != NULL) && (location == NULL)), NULL)do { if ((((info == ((void*)0)) && (location != ((void
*)0))) || ((info != ((void*)0)) && (location == ((void
*)0))))) { } else { g_return_if_fail_warning ("CafeWeather", (
(const char*) (__func__)), "((info == NULL) && (location != NULL)) || ((info != NULL) && (location == NULL))"
); return (((void*)0)); } } while (0)
;
489 g_return_val_if_fail (prefs != NULL, NULL)do { if ((prefs != ((void*)0))) { } else { g_return_if_fail_warning
("CafeWeather", ((const char*) (__func__)), "prefs != NULL")
; return (((void*)0)); } } while (0)
;
490
491 /* FIXME: i'm not sure this works as intended anymore */
492 if (!info) {
493 info = g_new0 (WeatherInfo, 1)((WeatherInfo *) g_malloc0_n ((1), sizeof (WeatherInfo)));
494 info->requests_pending = 0;
495 info->location = weather_location_clone (location);
496 } else {
497 location = info->location;
Value stored to 'location' is never read
498 if (info->forecast)
499 g_free (info->forecast);
500 info->forecast = NULL((void*)0);
501
502 free_forecast_list (info);
503
504 if (info->radar != NULL((void*)0)) {
505 g_object_unref (info->radar);
506 info->radar = NULL((void*)0);
507 }
508 }
509
510 /* Update in progress */
511 if (!requests_init (info)) {
512 return NULL((void*)0);
513 }
514
515 /* Defaults (just in case...) */
516 /* Well, no just in case anymore. We may actually fail to fetch some
517 * fields. */
518 info->forecast_type = prefs->type;
519
520 info->temperature_unit = prefs->temperature_unit;
521 info->speed_unit = prefs->speed_unit;
522 info->pressure_unit = prefs->pressure_unit;
523 info->distance_unit = prefs->distance_unit;
524
525 info->update = 0;
526 info->sky = -1;
527 info->cond.significant = FALSE(0);
528 info->cond.phenomenon = PHENOMENON_NONE;
529 info->cond.qualifier = QUALIFIER_NONE;
530 info->temp = -1000.0;
531 info->tempMinMaxValid = FALSE(0);
532 info->temp_min = -1000.0;
533 info->temp_max = -1000.0;
534 info->dew = -1000.0;
535 info->wind = -1;
536 info->windspeed = -1;
537 info->pressure = -1.0;
538 info->visibility = -1.0;
539 info->sunriseValid = FALSE(0);
540 info->sunsetValid = FALSE(0);
541 info->moonValid = FALSE(0);
542 info->sunrise = 0;
543 info->sunset = 0;
544 info->moonphase = 0;
545 info->moonlatitude = 0;
546 info->forecast = NULL((void*)0);
547 info->forecast_list = NULL((void*)0);
548 info->radar = NULL((void*)0);
549 info->radar_url = prefs->radar && prefs->radar_custom_url ?
550 g_strdup (prefs->radar_custom_url)g_strdup_inline (prefs->radar_custom_url) : NULL((void*)0);
551 info->finish_cb = cb;
552 info->cb_data = data;
553
554 if (!info->session) {
555 info->session = soup_session_new ();
556 soup_session_add_feature_by_type (info->session, G_TYPE_PROXY_RESOLVER(g_proxy_resolver_get_type ()));
557 }
558
559 metar_start_open (info);
560 iwin_start_open (info);
561
562 if (prefs->radar) {
563 wx_start_open (info);
564 }
565
566 return info;
567}
568
569void
570weather_info_abort (WeatherInfo *info)
571{
572 g_return_if_fail (info != NULL)do { if ((info != ((void*)0))) { } else { g_return_if_fail_warning
("CafeWeather", ((const char*) (__func__)), "info != NULL");
return; } } while (0)
;
573
574 if (info->session) {
575 soup_session_abort (info->session);
576 info->requests_pending = 0;
577 }
578}
579
580WeatherInfo *
581weather_info_clone (const WeatherInfo *info)
582{
583 WeatherInfo *clone;
584
585 g_return_val_if_fail (info != NULL, NULL)do { if ((info != ((void*)0))) { } else { g_return_if_fail_warning
("CafeWeather", ((const char*) (__func__)), "info != NULL");
return (((void*)0)); } } while (0)
;
586
587 clone = g_new (WeatherInfo, 1)((WeatherInfo *) g_malloc_n ((1), sizeof (WeatherInfo)));
588
589
590 /* move everything */
591 memmove (clone, info, sizeof (WeatherInfo));
592
593
594 /* special moves */
595 clone->location = weather_location_clone (info->location);
596 /* This handles null correctly */
597 clone->forecast = g_strdup (info->forecast)g_strdup_inline (info->forecast);
598 clone->radar_url = g_strdup (info->radar_url)g_strdup_inline (info->radar_url);
599
600 if (info->forecast_list) {
601 GSList *p;
602
603 clone->forecast_list = NULL((void*)0);
604 for (p = info->forecast_list; p; p = p->next) {
605 clone->forecast_list = g_slist_prepend (clone->forecast_list, weather_info_clone (p->data));
606 }
607
608 clone->forecast_list = g_slist_reverse (clone->forecast_list);
609 }
610
611 clone->radar = info->radar;
612 if (clone->radar != NULL((void*)0))
613 g_object_ref (clone->radar)((__typeof__ (clone->radar)) (g_object_ref) (clone->radar
))
;
614
615 return clone;
616}
617
618void
619weather_info_free (WeatherInfo *info)
620{
621 if (!info)
622 return;
623
624 weather_info_abort (info);
625 if (info->session)
626 g_object_unref (info->session);
627
628 weather_location_free (info->location);
629 info->location = NULL((void*)0);
630
631 g_free (info->forecast);
632 info->forecast = NULL((void*)0);
633
634 free_forecast_list (info);
635
636 if (info->radar != NULL((void*)0)) {
637 g_object_unref (info->radar);
638 info->radar = NULL((void*)0);
639 }
640
641 g_free (info);
642}
643
644gboolean
645weather_info_is_valid (WeatherInfo *info)
646{
647 g_return_val_if_fail (info != NULL, FALSE)do { if ((info != ((void*)0))) { } else { g_return_if_fail_warning
("CafeWeather", ((const char*) (__func__)), "info != NULL");
return ((0)); } } while (0)
;
648 return info->valid;
649}
650
651gboolean
652weather_info_network_error (WeatherInfo *info)
653{
654 g_return_val_if_fail (info != NULL, FALSE)do { if ((info != ((void*)0))) { } else { g_return_if_fail_warning
("CafeWeather", ((const char*) (__func__)), "info != NULL");
return ((0)); } } while (0)
;
655 return info->network_error;
656}
657
658void
659weather_info_to_metric (WeatherInfo *info)
660{
661 g_return_if_fail (info != NULL)do { if ((info != ((void*)0))) { } else { g_return_if_fail_warning
("CafeWeather", ((const char*) (__func__)), "info != NULL");
return; } } while (0)
;
662
663 info->temperature_unit = TEMP_UNIT_CENTIGRADE;
664 info->speed_unit = SPEED_UNIT_MS;
665 info->pressure_unit = PRESSURE_UNIT_HPA;
666 info->distance_unit = DISTANCE_UNIT_METERS;
667}
668
669void
670weather_info_to_imperial (WeatherInfo *info)
671{
672 g_return_if_fail (info != NULL)do { if ((info != ((void*)0))) { } else { g_return_if_fail_warning
("CafeWeather", ((const char*) (__func__)), "info != NULL");
return; } } while (0)
;
673
674 info->temperature_unit = TEMP_UNIT_FAHRENHEIT;
675 info->speed_unit = SPEED_UNIT_MPH;
676 info->pressure_unit = PRESSURE_UNIT_INCH_HG;
677 info->distance_unit = DISTANCE_UNIT_MILES;
678}
679
680const WeatherLocation *
681weather_info_get_location (WeatherInfo *info)
682{
683 g_return_val_if_fail (info != NULL, NULL)do { if ((info != ((void*)0))) { } else { g_return_if_fail_warning
("CafeWeather", ((const char*) (__func__)), "info != NULL");
return (((void*)0)); } } while (0)
;
684 return info->location;
685}
686
687const gchar *
688weather_info_get_location_name (WeatherInfo *info)
689{
690 g_return_val_if_fail (info != NULL, NULL)do { if ((info != ((void*)0))) { } else { g_return_if_fail_warning
("CafeWeather", ((const char*) (__func__)), "info != NULL");
return (((void*)0)); } } while (0)
;
691 g_return_val_if_fail (info->location != NULL, NULL)do { if ((info->location != ((void*)0))) { } else { g_return_if_fail_warning
("CafeWeather", ((const char*) (__func__)), "info->location != NULL"
); return (((void*)0)); } } while (0)
;
692 return info->location->name;
693}
694
695const gchar *
696weather_info_get_update (WeatherInfo *info)
697{
698 static gchar buf[200];
699 char *utf8, *timeformat;
700
701 g_return_val_if_fail (info != NULL, NULL)do { if ((info != ((void*)0))) { } else { g_return_if_fail_warning
("CafeWeather", ((const char*) (__func__)), "info != NULL");
return (((void*)0)); } } while (0)
;
702
703 if (!info->valid)
704 return "-";
705
706 if (info->update != 0) {
707 struct tm tm;
708 localtime_r (&info->update, &tm);
709 /* Translators: this is a format string for strftime
710 * see `man 3 strftime` for more details
711 */
712 timeformat = g_locale_from_utf8 (_("%a, %b %d / %H:%M")(cafeweather_gettext ("%a, %b %d / %H:%M")), -1,
713 NULL((void*)0), NULL((void*)0), NULL((void*)0));
714 if (!timeformat) {
715 strcpy (buf, "???");
716 }
717 else if (strftime (buf, sizeof (buf), timeformat, &tm) <= 0) {
718 strcpy (buf, "???");
719 }
720 g_free (timeformat);
721
722 /* Convert to UTF-8 */
723 utf8 = g_locale_to_utf8 (buf, -1, NULL((void*)0), NULL((void*)0), NULL((void*)0));
724 strcpy (buf, utf8);
725 g_free (utf8);
726 } else {
727 strncpy (buf, _("Unknown observation time")(cafeweather_gettext ("Unknown observation time")), sizeof (buf));
728 buf[sizeof (buf)-1] = '\0';
729 }
730
731 return buf;
732}
733
734const gchar *
735weather_info_get_sky (WeatherInfo *info)
736{
737 g_return_val_if_fail (info != NULL, NULL)do { if ((info != ((void*)0))) { } else { g_return_if_fail_warning
("CafeWeather", ((const char*) (__func__)), "info != NULL");
return (((void*)0)); } } while (0)
;
738 if (!info->valid)
739 return "-";
740 if (info->sky < 0)
741 return _("Unknown")(cafeweather_gettext ("Unknown"));
742 return weather_sky_string (info->sky);
743}
744
745const gchar *
746weather_info_get_conditions (WeatherInfo *info)
747{
748 g_return_val_if_fail (info != NULL, NULL)do { if ((info != ((void*)0))) { } else { g_return_if_fail_warning
("CafeWeather", ((const char*) (__func__)), "info != NULL");
return (((void*)0)); } } while (0)
;
749 if (!info->valid)
750 return "-";
751 return weather_conditions_string (info->cond);
752}
753
754static const gchar *
755temperature_string (gfloat temp_f, TempUnit to_unit, gboolean want_round)
756{
757 static gchar buf[100];
758
759 switch (to_unit) {
760 case TEMP_UNIT_FAHRENHEIT:
761 if (!want_round) {
762 /* Translators: This is the temperature in degrees Fahrenheit (\302\260 is U+00B0 DEGREE SIGN) */
763 g_snprintf (buf, sizeof (buf), _("%.1f \302\260F")(cafeweather_gettext ("%.1f \302\260F")), temp_f);
764 } else {
765 /* Translators: This is the temperature in degrees Fahrenheit (\302\260 is U+00B0 DEGREE SIGN) */
766 g_snprintf (buf, sizeof (buf), _("%d \302\260F")(cafeweather_gettext ("%d \302\260F")), (int)floor (temp_f + 0.5));
767 }
768 break;
769 case TEMP_UNIT_CENTIGRADE:
770 if (!want_round) {
771 /* Translators: This is the temperature in degrees Celsius (\302\260 is U+00B0 DEGREE SIGN) */
772 g_snprintf (buf, sizeof (buf), _("%.1f \302\260C")(cafeweather_gettext ("%.1f \302\260C")), TEMP_F_TO_C (temp_f)(((temp_f) - 32.0) * 0.555556));
773 } else {
774 /* Translators: This is the temperature in degrees Celsius (\302\260 is U+00B0 DEGREE SIGN) */
775 g_snprintf (buf, sizeof (buf), _("%d \302\260C")(cafeweather_gettext ("%d \302\260C")), (int)floor (TEMP_F_TO_C (temp_f)(((temp_f) - 32.0) * 0.555556) + 0.5));
776 }
777 break;
778 case TEMP_UNIT_KELVIN:
779 if (!want_round) {
780 /* Translators: This is the temperature in kelvin */
781 g_snprintf (buf, sizeof (buf), _("%.1f K")(cafeweather_gettext ("%.1f K")), TEMP_F_TO_K (temp_f)((((temp_f) - 32.0) * 0.555556) + 273.15));
782 } else {
783 /* Translators: This is the temperature in kelvin */
784 g_snprintf (buf, sizeof (buf), _("%d K")(cafeweather_gettext ("%d K")), (int)floor (TEMP_F_TO_K (temp_f)((((temp_f) - 32.0) * 0.555556) + 273.15)));
785 }
786 break;
787
788 case TEMP_UNIT_INVALID:
789 case TEMP_UNIT_DEFAULT:
790 default:
791 g_warning ("Conversion to illegal temperature unit: %d", to_unit);
792 return _("Unknown")(cafeweather_gettext ("Unknown"));
793 }
794
795 return buf;
796}
797
798const gchar *
799weather_info_get_temp (WeatherInfo *info)
800{
801 g_return_val_if_fail (info != NULL, NULL)do { if ((info != ((void*)0))) { } else { g_return_if_fail_warning
("CafeWeather", ((const char*) (__func__)), "info != NULL");
return (((void*)0)); } } while (0)
;
802
803 if (!info->valid)
804 return "-";
805 if (info->temp < -500.0)
806 return _("Unknown")(cafeweather_gettext ("Unknown"));
807
808 return temperature_string (info->temp, info->temperature_unit, FALSE(0));
809}
810
811const gchar *
812weather_info_get_temp_min (WeatherInfo *info)
813{
814 g_return_val_if_fail (info != NULL, NULL)do { if ((info != ((void*)0))) { } else { g_return_if_fail_warning
("CafeWeather", ((const char*) (__func__)), "info != NULL");
return (((void*)0)); } } while (0)
;
815
816 if (!info->valid || !info->tempMinMaxValid)
817 return "-";
818 if (info->temp_min < -500.0)
819 return _("Unknown")(cafeweather_gettext ("Unknown"));
820
821 return temperature_string (info->temp_min, info->temperature_unit, FALSE(0));
822}
823
824const gchar *
825weather_info_get_temp_max (WeatherInfo *info)
826{
827 g_return_val_if_fail (info != NULL, NULL)do { if ((info != ((void*)0))) { } else { g_return_if_fail_warning
("CafeWeather", ((const char*) (__func__)), "info != NULL");
return (((void*)0)); } } while (0)
;
828
829 if (!info->valid || !info->tempMinMaxValid)
830 return "-";
831 if (info->temp_max < -500.0)
832 return _("Unknown")(cafeweather_gettext ("Unknown"));
833
834 return temperature_string (info->temp_max, info->temperature_unit, FALSE(0));
835}
836
837const gchar *
838weather_info_get_dew (WeatherInfo *info)
839{
840 g_return_val_if_fail (info != NULL, NULL)do { if ((info != ((void*)0))) { } else { g_return_if_fail_warning
("CafeWeather", ((const char*) (__func__)), "info != NULL");
return (((void*)0)); } } while (0)
;
841
842 if (!info->valid)
843 return "-";
844 if (info->dew < -500.0)
845 return _("Unknown")(cafeweather_gettext ("Unknown"));
846
847 return temperature_string (info->dew, info->temperature_unit, FALSE(0));
848}
849
850const gchar *
851weather_info_get_humidity (WeatherInfo *info)
852{
853 static gchar buf[20];
854 gdouble humidity;
855
856 g_return_val_if_fail (info != NULL, NULL)do { if ((info != ((void*)0))) { } else { g_return_if_fail_warning
("CafeWeather", ((const char*) (__func__)), "info != NULL");
return (((void*)0)); } } while (0)
;
857
858 if (!info->valid)
859 return "-";
860
861 humidity = calc_humidity (info->temp, info->dew);
862 if (humidity < 0.0)
863 return _("Unknown")(cafeweather_gettext ("Unknown"));
864
865 /* Translators: This is the humidity in percent */
866 g_snprintf (buf, sizeof (buf), _("%.f%%")(cafeweather_gettext ("%.f%%")), humidity);
867 return buf;
868}
869
870const gchar *
871weather_info_get_apparent (WeatherInfo *info)
872{
873 gdouble apparent;
874
875 g_return_val_if_fail (info != NULL, NULL)do { if ((info != ((void*)0))) { } else { g_return_if_fail_warning
("CafeWeather", ((const char*) (__func__)), "info != NULL");
return (((void*)0)); } } while (0)
;
876 if (!info->valid)
877 return "-";
878
879 apparent = calc_apparent (info);
880 if (apparent < -500.0)
881 return _("Unknown")(cafeweather_gettext ("Unknown"));
882
883 return temperature_string (apparent, info->temperature_unit, FALSE(0));
884}
885
886static const gchar *
887windspeed_string (gfloat knots, SpeedUnit to_unit)
888{
889 static gchar buf[100];
890
891 switch (to_unit) {
892 case SPEED_UNIT_KNOTS:
893 /* Translators: This is the wind speed in knots */
894 g_snprintf (buf, sizeof (buf), _("%0.1f knots")(cafeweather_gettext ("%0.1f knots")), knots);
895 break;
896 case SPEED_UNIT_MPH:
897 /* Translators: This is the wind speed in miles per hour */
898 g_snprintf (buf, sizeof (buf), _("%.1f mph")(cafeweather_gettext ("%.1f mph")), WINDSPEED_KNOTS_TO_MPH (knots)((knots) * 1.150779));
899 break;
900 case SPEED_UNIT_KPH:
901 /* Translators: This is the wind speed in kilometers per hour */
902 g_snprintf (buf, sizeof (buf), _("%.1f km/h")(cafeweather_gettext ("%.1f km/h")), WINDSPEED_KNOTS_TO_KPH (knots)((knots) * 1.851965));
903 break;
904 case SPEED_UNIT_MS:
905 /* Translators: This is the wind speed in meters per second */
906 g_snprintf (buf, sizeof (buf), _("%.1f m/s")(cafeweather_gettext ("%.1f m/s")), WINDSPEED_KNOTS_TO_MS (knots)((knots) * 0.514444));
907 break;
908 case SPEED_UNIT_BFT:
909 /* Translators: This is the wind speed as a Beaufort force factor
910 * (commonly used in nautical wind estimation).
911 */
912 g_snprintf (buf, sizeof (buf), _("Beaufort force %.1f")(cafeweather_gettext ("Beaufort force %.1f")),
913 WINDSPEED_KNOTS_TO_BFT (knots)(pow ((knots) * 0.615363, 0.666666)));
914 break;
915 case SPEED_UNIT_INVALID:
916 case SPEED_UNIT_DEFAULT:
917 default:
918 g_warning ("Conversion to illegal speed unit: %d", to_unit);
919 return _("Unknown")(cafeweather_gettext ("Unknown"));
920 }
921
922 return buf;
923}
924
925const gchar *
926weather_info_get_wind (WeatherInfo *info)
927{
928 static gchar buf[200];
929
930 g_return_val_if_fail (info != NULL, NULL)do { if ((info != ((void*)0))) { } else { g_return_if_fail_warning
("CafeWeather", ((const char*) (__func__)), "info != NULL");
return (((void*)0)); } } while (0)
;
931
932 if (!info->valid)
933 return "-";
934 if (info->windspeed < 0.0 || info->wind < 0)
935 return _("Unknown")(cafeweather_gettext ("Unknown"));
936 if (info->windspeed == 0.00) {
937 strncpy (buf, _("Calm")(cafeweather_gettext ("Calm")), sizeof (buf));
938 buf[sizeof (buf)-1] = '\0';
939 } else {
940 /* Translators: This is 'wind direction' / 'wind speed' */
941 g_snprintf (buf, sizeof (buf), _("%s / %s")(cafeweather_gettext ("%s / %s")),
942 weather_wind_direction_string (info->wind),
943 windspeed_string (info->windspeed, info->speed_unit));
944 }
945 return buf;
946}
947
948const gchar *
949weather_info_get_pressure (WeatherInfo *info)
950{
951 static gchar buf[100];
952
953 g_return_val_if_fail (info != NULL, NULL)do { if ((info != ((void*)0))) { } else { g_return_if_fail_warning
("CafeWeather", ((const char*) (__func__)), "info != NULL");
return (((void*)0)); } } while (0)
;
954
955 if (!info->valid)
956 return "-";
957 if (info->pressure < 0.0)
958 return _("Unknown")(cafeweather_gettext ("Unknown"));
959
960 switch (info->pressure_unit) {
961 case PRESSURE_UNIT_INCH_HG:
962 /* Translators: This is pressure in inches of mercury */
963 g_snprintf (buf, sizeof (buf), _("%.2f inHg")(cafeweather_gettext ("%.2f inHg")), info->pressure);
964 break;
965 case PRESSURE_UNIT_MM_HG:
966 /* Translators: This is pressure in millimeters of mercury */
967 g_snprintf (buf, sizeof (buf), _("%.1f mmHg")(cafeweather_gettext ("%.1f mmHg")), PRESSURE_INCH_TO_MM (info->pressure)((info->pressure) * 25.40005));
968 break;
969 case PRESSURE_UNIT_KPA:
970 /* Translators: This is pressure in kiloPascals */
971 g_snprintf (buf, sizeof (buf), _("%.2f kPa")(cafeweather_gettext ("%.2f kPa")), PRESSURE_INCH_TO_KPA (info->pressure)((info->pressure) * 3.386));
972 break;
973 case PRESSURE_UNIT_HPA:
974 /* Translators: This is pressure in hectoPascals */
975 g_snprintf (buf, sizeof (buf), _("%.2f hPa")(cafeweather_gettext ("%.2f hPa")), PRESSURE_INCH_TO_HPA (info->pressure)((info->pressure) * 33.86));
976 break;
977 case PRESSURE_UNIT_MB:
978 /* Translators: This is pressure in millibars */
979 g_snprintf (buf, sizeof (buf), _("%.2f mb")(cafeweather_gettext ("%.2f mb")), PRESSURE_INCH_TO_MB (info->pressure)(((info->pressure) * 33.86)));
980 break;
981 case PRESSURE_UNIT_ATM:
982 /* Translators: This is pressure in atmospheres */
983 g_snprintf (buf, sizeof (buf), _("%.3f atm")(cafeweather_gettext ("%.3f atm")), PRESSURE_INCH_TO_ATM (info->pressure)((info->pressure) * 0.033421052));
984 break;
985
986 case PRESSURE_UNIT_INVALID:
987 case PRESSURE_UNIT_DEFAULT:
988 default:
989 g_warning ("Conversion to illegal pressure unit: %d", info->pressure_unit);
990 return _("Unknown")(cafeweather_gettext ("Unknown"));
991 }
992
993 return buf;
994}
995
996const gchar *
997weather_info_get_visibility (WeatherInfo *info)
998{
999 static gchar buf[100];
1000
1001 g_return_val_if_fail (info != NULL, NULL)do { if ((info != ((void*)0))) { } else { g_return_if_fail_warning
("CafeWeather", ((const char*) (__func__)), "info != NULL");
return (((void*)0)); } } while (0)
;
1002
1003 if (!info->valid)
1004 return "-";
1005 if (info->visibility < 0.0)
1006 return _("Unknown")(cafeweather_gettext ("Unknown"));
1007
1008 switch (info->distance_unit) {
1009 case DISTANCE_UNIT_MILES:
1010 /* Translators: This is the visibility in miles */
1011 g_snprintf (buf, sizeof (buf), _("%.1f miles")(cafeweather_gettext ("%.1f miles")), info->visibility);
1012 break;
1013 case DISTANCE_UNIT_KM:
1014 /* Translators: This is the visibility in kilometers */
1015 g_snprintf (buf, sizeof (buf), _("%.1f km")(cafeweather_gettext ("%.1f km")), VISIBILITY_SM_TO_KM (info->visibility)((info->visibility) * 1.609344));
1016 break;
1017 case DISTANCE_UNIT_METERS:
1018 /* Translators: This is the visibility in meters */
1019 g_snprintf (buf, sizeof (buf), _("%.0fm")(cafeweather_gettext ("%.0fm")), VISIBILITY_SM_TO_M (info->visibility)(((info->visibility) * 1.609344) * 1000));
1020 break;
1021
1022 case DISTANCE_UNIT_INVALID:
1023 case DISTANCE_UNIT_DEFAULT:
1024 default:
1025 g_warning ("Conversion to illegal visibility unit: %d", info->pressure_unit);
1026 return _("Unknown")(cafeweather_gettext ("Unknown"));
1027 }
1028
1029 return buf;
1030}
1031
1032const gchar *
1033weather_info_get_sunrise (WeatherInfo *info)
1034{
1035 static gchar buf[200];
1036 struct tm tm;
1037
1038 g_return_val_if_fail (info && info->location, NULL)do { if ((info && info->location)) { } else { g_return_if_fail_warning
("CafeWeather", ((const char*) (__func__)), "info && info->location"
); return (((void*)0)); } } while (0)
;
1039
1040 if (!info->location->latlon_valid)
1041 return "-";
1042 if (!info->valid)
1043 return "-";
1044 if (!calc_sun (info))
1045 return "-";
1046
1047 localtime_r (&info->sunrise, &tm);
1048 if (strftime (buf, sizeof (buf), _("%H:%M")(cafeweather_gettext ("%H:%M")), &tm) <= 0)
1049 return "-";
1050 return buf;
1051}
1052
1053const gchar *
1054weather_info_get_sunset (WeatherInfo *info)
1055{
1056 static gchar buf[200];
1057 struct tm tm;
1058
1059 g_return_val_if_fail (info && info->location, NULL)do { if ((info && info->location)) { } else { g_return_if_fail_warning
("CafeWeather", ((const char*) (__func__)), "info && info->location"
); return (((void*)0)); } } while (0)
;
1060
1061 if (!info->location->latlon_valid)
1062 return "-";
1063 if (!info->valid)
1064 return "-";
1065 if (!calc_sun (info))
1066 return "-";
1067
1068 localtime_r (&info->sunset, &tm);
1069 if (strftime (buf, sizeof (buf), _("%H:%M")(cafeweather_gettext ("%H:%M")), &tm) <= 0)
1070 return "-";
1071 return buf;
1072}
1073
1074const gchar *
1075weather_info_get_forecast (WeatherInfo *info)
1076{
1077 g_return_val_if_fail (info != NULL, NULL)do { if ((info != ((void*)0))) { } else { g_return_if_fail_warning
("CafeWeather", ((const char*) (__func__)), "info != NULL");
return (((void*)0)); } } while (0)
;
1078 return info->forecast;
1079}
1080
1081/**
1082 * weather_info_get_forecast_list:
1083 * Returns list of WeatherInfo* objects for the forecast.
1084 * The list is owned by the 'info' object thus is alive as long
1085 * as the 'info'. This list is filled only when requested with
1086 * type FORECAST_LIST and if available for given location.
1087 * The 'update' property is the date/time when the forecast info
1088 * is used for.
1089 **/
1090GSList *
1091weather_info_get_forecast_list (WeatherInfo *info)
1092{
1093 g_return_val_if_fail (info != NULL, NULL)do { if ((info != ((void*)0))) { } else { g_return_if_fail_warning
("CafeWeather", ((const char*) (__func__)), "info != NULL");
return (((void*)0)); } } while (0)
;
1094
1095 if (!info->valid)
1096 return NULL((void*)0);
1097
1098 return info->forecast_list;
1099}
1100
1101GdkPixbufAnimation *
1102weather_info_get_radar (WeatherInfo *info)
1103{
1104 g_return_val_if_fail (info != NULL, NULL)do { if ((info != ((void*)0))) { } else { g_return_if_fail_warning
("CafeWeather", ((const char*) (__func__)), "info != NULL");
return (((void*)0)); } } while (0)
;
1105 return info->radar;
1106}
1107
1108const gchar *
1109weather_info_get_temp_summary (WeatherInfo *info)
1110{
1111 g_return_val_if_fail (info != NULL, NULL)do { if ((info != ((void*)0))) { } else { g_return_if_fail_warning
("CafeWeather", ((const char*) (__func__)), "info != NULL");
return (((void*)0)); } } while (0)
;
1112
1113 if (!info->valid || info->temp < -500.0)
1114 return "--";
1115
1116 return temperature_string (info->temp, info->temperature_unit, TRUE(!(0)));
1117
1118}
1119
1120gchar *
1121weather_info_get_weather_summary (WeatherInfo *info)
1122{
1123 const gchar *buf;
1124
1125 g_return_val_if_fail (info != NULL, NULL)do { if ((info != ((void*)0))) { } else { g_return_if_fail_warning
("CafeWeather", ((const char*) (__func__)), "info != NULL");
return (((void*)0)); } } while (0)
;
1126
1127 if (!info->valid)
1128 return g_strdup (_("Retrieval failed"))g_strdup_inline ((cafeweather_gettext ("Retrieval failed")));
1129 buf = weather_info_get_conditions (info);
1130 if (!strcmp (buf, "-"))
1131 buf = weather_info_get_sky (info);
1132 return g_strdup_printf ("%s: %s", weather_info_get_location_name (info), buf);
1133}
1134
1135const gchar *
1136weather_info_get_icon_name (WeatherInfo *info)
1137{
1138 WeatherConditions cond;
1139 WeatherSky sky;
1140 time_t current_time;
1141 gboolean daytime;
1142 gchar* icon;
1143 static gchar icon_buffer[32];
1144 WeatherMoonPhase moonPhase;
1145 WeatherMoonLatitude moonLat;
1146 gint phase;
1147
1148 g_return_val_if_fail (info != NULL, NULL)do { if ((info != ((void*)0))) { } else { g_return_if_fail_warning
("CafeWeather", ((const char*) (__func__)), "info != NULL");
return (((void*)0)); } } while (0)
;
1149
1150 if (!info->valid)
1151 return NULL((void*)0);
1152
1153 cond = info->cond;
1154 sky = info->sky;
1155
1156 if (cond.significant) {
1157 if (cond.phenomenon != PHENOMENON_NONE &&
1158 cond.qualifier == QUALIFIER_THUNDERSTORM)
1159 return "weather-storm";
1160
1161 switch (cond.phenomenon) {
1162 case PHENOMENON_INVALID:
1163 case PHENOMENON_LAST:
1164 case PHENOMENON_NONE:
1165 break;
1166
1167 case PHENOMENON_DRIZZLE:
1168 case PHENOMENON_RAIN:
1169 case PHENOMENON_UNKNOWN_PRECIPITATION:
1170 case PHENOMENON_HAIL:
1171 case PHENOMENON_SMALL_HAIL:
1172 return "weather-showers";
1173
1174 case PHENOMENON_SNOW:
1175 case PHENOMENON_SNOW_GRAINS:
1176 case PHENOMENON_ICE_PELLETS:
1177 case PHENOMENON_ICE_CRYSTALS:
1178 return "weather-snow";
1179
1180 case PHENOMENON_TORNADO:
1181 case PHENOMENON_SQUALL:
1182 return "weather-storm";
1183
1184 case PHENOMENON_MIST:
1185 case PHENOMENON_FOG:
1186 case PHENOMENON_SMOKE:
1187 case PHENOMENON_VOLCANIC_ASH:
1188 case PHENOMENON_SAND:
1189 case PHENOMENON_HAZE:
1190 case PHENOMENON_SPRAY:
1191 case PHENOMENON_DUST:
1192 case PHENOMENON_SANDSTORM:
1193 case PHENOMENON_DUSTSTORM:
1194 case PHENOMENON_FUNNEL_CLOUD:
1195 case PHENOMENON_DUST_WHIRLS:
1196 return "weather-fog";
1197 }
1198 }
1199
1200 if (info->midnightSun ||
1201 (!info->sunriseValid && !info->sunsetValid))
1202 daytime = TRUE(!(0));
1203 else if (info->polarNight)
1204 daytime = FALSE(0);
1205 else {
1206 current_time = time (NULL((void*)0));
1207 daytime =
1208 ( !info->sunriseValid || (current_time >= info->sunrise) ) &&
1209 ( !info->sunsetValid || (current_time < info->sunset) );
1210 }
1211
1212 switch (sky) {
1213 case SKY_INVALID:
1214 case SKY_LAST:
1215 case SKY_CLEAR:
1216 if (daytime)
1217 return "weather-clear";
1218 else {
1219 icon = g_stpcpy(icon_buffer, "weather-clear-night");
1220 break;
1221 }
1222
1223 case SKY_BROKEN:
1224 case SKY_SCATTERED:
1225 case SKY_FEW:
1226 if (daytime)
1227 return "weather-few-clouds";
1228 else {
1229 icon = g_stpcpy(icon_buffer, "weather-few-clouds-night");
1230 break;
1231 }
1232
1233 case SKY_OVERCAST:
1234 return "weather-overcast";
1235
1236 default: /* unrecognized */
1237 return NULL((void*)0);
1238 }
1239
1240 /*
1241 * A phase-of-moon icon is to be returned.
1242 * Determine which one based on the moon's location
1243 */
1244 if (info->moonValid && weather_info_get_value_moonphase(info, &moonPhase, &moonLat)) {
1245 phase = (gint)((moonPhase * MOON_PHASES36 / 360.) + 0.5);
1246 if (phase == MOON_PHASES36) {
1247 phase = 0;
1248 } else if (phase > 0 &&
1249 (RADIANS_TO_DEGREES(weather_info_get_location(info)->latitude)((weather_info_get_location(info)->latitude) * 180. / 3.14159265358979323846
)
1250 < moonLat)) {
1251 /*
1252 * Locations south of the moon's latitude will see the moon in the
1253 * northern sky. The moon waxes and wanes from left to right
1254 * so we reference an icon running in the opposite direction.
1255 */
1256 phase = MOON_PHASES36 - phase;
1257 }
1258
1259 /*
1260 * If the moon is not full then append the angle to the icon string.
1261 * Note that an icon by this name is not required to exist:
1262 * the caller can use CTK_ICON_LOOKUP_GENERIC_FALLBACK to fall back to
1263 * the full moon image.
1264 */
1265 if ((0 == (MOON_PHASES36 & 0x1)) && (MOON_PHASES36/2 != phase)) {
1266 g_snprintf(icon, sizeof(icon_buffer) - strlen(icon_buffer),
1267 "-%03d", phase * 360 / MOON_PHASES36);
1268 }
1269 }
1270 return icon_buffer;
1271}
1272
1273static gboolean
1274temperature_value (gdouble temp_f,
1275 TempUnit to_unit,
1276 gdouble *value,
1277 TempUnit def_unit)
1278{
1279 gboolean ok = TRUE(!(0));
1280
1281 *value = 0.0;
1282 if (temp_f < -500.0)
1283 return FALSE(0);
1284
1285 if (to_unit == TEMP_UNIT_DEFAULT)
1286 to_unit = def_unit;
1287
1288 switch (to_unit) {
1289 case TEMP_UNIT_FAHRENHEIT:
1290 *value = temp_f;
1291 break;
1292 case TEMP_UNIT_CENTIGRADE:
1293 *value = TEMP_F_TO_C (temp_f)(((temp_f) - 32.0) * 0.555556);
1294 break;
1295 case TEMP_UNIT_KELVIN:
1296 *value = TEMP_F_TO_K (temp_f)((((temp_f) - 32.0) * 0.555556) + 273.15);
1297 break;
1298 case TEMP_UNIT_INVALID:
1299 case TEMP_UNIT_DEFAULT:
1300 default:
1301 ok = FALSE(0);
1302 break;
1303 }
1304
1305 return ok;
1306}
1307
1308static gboolean
1309speed_value (gdouble knots, SpeedUnit to_unit, gdouble *value, SpeedUnit def_unit)
1310{
1311 gboolean ok = TRUE(!(0));
1312
1313 *value = -1.0;
1314
1315 if (knots < 0.0)
1316 return FALSE(0);
1317
1318 if (to_unit == SPEED_UNIT_DEFAULT)
1319 to_unit = def_unit;
1320
1321 switch (to_unit) {
1322 case SPEED_UNIT_KNOTS:
1323 *value = knots;
1324 break;
1325 case SPEED_UNIT_MPH:
1326 *value = WINDSPEED_KNOTS_TO_MPH (knots)((knots) * 1.150779);
1327 break;
1328 case SPEED_UNIT_KPH:
1329 *value = WINDSPEED_KNOTS_TO_KPH (knots)((knots) * 1.851965);
1330 break;
1331 case SPEED_UNIT_MS:
1332 *value = WINDSPEED_KNOTS_TO_MS (knots)((knots) * 0.514444);
1333 break;
1334 case SPEED_UNIT_BFT:
1335 *value = WINDSPEED_KNOTS_TO_BFT (knots)(pow ((knots) * 0.615363, 0.666666));
1336 break;
1337 case SPEED_UNIT_INVALID:
1338 case SPEED_UNIT_DEFAULT:
1339 default:
1340 ok = FALSE(0);
1341 break;
1342 }
1343
1344 return ok;
1345}
1346
1347static gboolean
1348pressure_value (gdouble inHg, PressureUnit to_unit, gdouble *value, PressureUnit def_unit)
1349{
1350 gboolean ok = TRUE(!(0));
1351
1352 *value = -1.0;
1353
1354 if (inHg < 0.0)
1355 return FALSE(0);
1356
1357 if (to_unit == PRESSURE_UNIT_DEFAULT)
1358 to_unit = def_unit;
1359
1360 switch (to_unit) {
1361 case PRESSURE_UNIT_INCH_HG:
1362 *value = inHg;
1363 break;
1364 case PRESSURE_UNIT_MM_HG:
1365 *value = PRESSURE_INCH_TO_MM (inHg)((inHg) * 25.40005);
1366 break;
1367 case PRESSURE_UNIT_KPA:
1368 *value = PRESSURE_INCH_TO_KPA (inHg)((inHg) * 3.386);
1369 break;
1370 case PRESSURE_UNIT_HPA:
1371 *value = PRESSURE_INCH_TO_HPA (inHg)((inHg) * 33.86);
1372 break;
1373 case PRESSURE_UNIT_MB:
1374 *value = PRESSURE_INCH_TO_MB (inHg)(((inHg) * 33.86));
1375 break;
1376 case PRESSURE_UNIT_ATM:
1377 *value = PRESSURE_INCH_TO_ATM (inHg)((inHg) * 0.033421052);
1378 break;
1379 case PRESSURE_UNIT_INVALID:
1380 case PRESSURE_UNIT_DEFAULT:
1381 default:
1382 ok = FALSE(0);
1383 break;
1384 }
1385
1386 return ok;
1387}
1388
1389static gboolean
1390distance_value (gdouble miles, DistanceUnit to_unit, gdouble *value, DistanceUnit def_unit)
1391{
1392 gboolean ok = TRUE(!(0));
1393
1394 *value = -1.0;
1395
1396 if (miles < 0.0)
1397 return FALSE(0);
1398
1399 if (to_unit == DISTANCE_UNIT_DEFAULT)
1400 to_unit = def_unit;
1401
1402 switch (to_unit) {
1403 case DISTANCE_UNIT_MILES:
1404 *value = miles;
1405 break;
1406 case DISTANCE_UNIT_KM:
1407 *value = VISIBILITY_SM_TO_KM (miles)((miles) * 1.609344);
1408 break;
1409 case DISTANCE_UNIT_METERS:
1410 *value = VISIBILITY_SM_TO_M (miles)(((miles) * 1.609344) * 1000);
1411 break;
1412 case DISTANCE_UNIT_INVALID:
1413 case DISTANCE_UNIT_DEFAULT:
1414 default:
1415 ok = FALSE(0);
1416 break;
1417 }
1418
1419 return ok;
1420}
1421
1422gboolean
1423weather_info_get_value_sky (WeatherInfo *info, WeatherSky *sky)
1424{
1425 g_return_val_if_fail (info != NULL, FALSE)do { if ((info != ((void*)0))) { } else { g_return_if_fail_warning
("CafeWeather", ((const char*) (__func__)), "info != NULL");
return ((0)); } } while (0)
;
1426 g_return_val_if_fail (sky != NULL, FALSE)do { if ((sky != ((void*)0))) { } else { g_return_if_fail_warning
("CafeWeather", ((const char*) (__func__)), "sky != NULL"); return
((0)); } } while (0)
;
1427
1428 if (!info->valid)
1429 return FALSE(0);
1430
1431 if (info->sky <= SKY_INVALID || info->sky >= SKY_LAST)
1432 return FALSE(0);
1433
1434 *sky = info->sky;
1435
1436 return TRUE(!(0));
1437}
1438
1439gboolean
1440weather_info_get_value_conditions (WeatherInfo *info, WeatherConditionPhenomenon *phenomenon, WeatherConditionQualifier *qualifier)
1441{
1442 g_return_val_if_fail (info != NULL, FALSE)do { if ((info != ((void*)0))) { } else { g_return_if_fail_warning
("CafeWeather", ((const char*) (__func__)), "info != NULL");
return ((0)); } } while (0)
;
1443 g_return_val_if_fail (phenomenon != NULL, FALSE)do { if ((phenomenon != ((void*)0))) { } else { g_return_if_fail_warning
("CafeWeather", ((const char*) (__func__)), "phenomenon != NULL"
); return ((0)); } } while (0)
;
1444 g_return_val_if_fail (qualifier != NULL, FALSE)do { if ((qualifier != ((void*)0))) { } else { g_return_if_fail_warning
("CafeWeather", ((const char*) (__func__)), "qualifier != NULL"
); return ((0)); } } while (0)
;
1445
1446 if (!info->valid)
1447 return FALSE(0);
1448
1449 if (!info->cond.significant)
1450 return FALSE(0);
1451
1452 if (!(info->cond.phenomenon > PHENOMENON_INVALID &&
1453 info->cond.phenomenon < PHENOMENON_LAST &&
1454 info->cond.qualifier > QUALIFIER_INVALID &&
1455 info->cond.qualifier < QUALIFIER_LAST))
1456 return FALSE(0);
1457
1458 *phenomenon = info->cond.phenomenon;
1459 *qualifier = info->cond.qualifier;
1460
1461 return TRUE(!(0));
1462}
1463
1464gboolean
1465weather_info_get_value_temp (WeatherInfo *info, TempUnit unit, gdouble *value)
1466{
1467 g_return_val_if_fail (info != NULL, FALSE)do { if ((info != ((void*)0))) { } else { g_return_if_fail_warning
("CafeWeather", ((const char*) (__func__)), "info != NULL");
return ((0)); } } while (0)
;
1468 g_return_val_if_fail (value != NULL, FALSE)do { if ((value != ((void*)0))) { } else { g_return_if_fail_warning
("CafeWeather", ((const char*) (__func__)), "value != NULL")
; return ((0)); } } while (0)
;
1469
1470 if (!info->valid)
1471 return FALSE(0);
1472
1473 return temperature_value (info->temp, unit, value, info->temperature_unit);
1474}
1475
1476gboolean
1477weather_info_get_value_temp_min (WeatherInfo *info, TempUnit unit, gdouble *value)
1478{
1479 g_return_val_if_fail (info != NULL, FALSE)do { if ((info != ((void*)0))) { } else { g_return_if_fail_warning
("CafeWeather", ((const char*) (__func__)), "info != NULL");
return ((0)); } } while (0)
;
1480 g_return_val_if_fail (value != NULL, FALSE)do { if ((value != ((void*)0))) { } else { g_return_if_fail_warning
("CafeWeather", ((const char*) (__func__)), "value != NULL")
; return ((0)); } } while (0)
;
1481
1482 if (!info->valid || !info->tempMinMaxValid)
1483 return FALSE(0);
1484
1485 return temperature_value (info->temp_min, unit, value, info->temperature_unit);
1486}
1487
1488gboolean
1489weather_info_get_value_temp_max (WeatherInfo *info, TempUnit unit, gdouble *value)
1490{
1491 g_return_val_if_fail (info != NULL, FALSE)do { if ((info != ((void*)0))) { } else { g_return_if_fail_warning
("CafeWeather", ((const char*) (__func__)), "info != NULL");
return ((0)); } } while (0)
;
1492 g_return_val_if_fail (value != NULL, FALSE)do { if ((value != ((void*)0))) { } else { g_return_if_fail_warning
("CafeWeather", ((const char*) (__func__)), "value != NULL")
; return ((0)); } } while (0)
;
1493
1494 if (!info->valid || !info->tempMinMaxValid)
1495 return FALSE(0);
1496
1497 return temperature_value (info->temp_max, unit, value, info->temperature_unit);
1498}
1499
1500gboolean
1501weather_info_get_value_dew (WeatherInfo *info, TempUnit unit, gdouble *value)
1502{
1503 g_return_val_if_fail (info != NULL, FALSE)do { if ((info != ((void*)0))) { } else { g_return_if_fail_warning
("CafeWeather", ((const char*) (__func__)), "info != NULL");
return ((0)); } } while (0)
;
1504 g_return_val_if_fail (value != NULL, FALSE)do { if ((value != ((void*)0))) { } else { g_return_if_fail_warning
("CafeWeather", ((const char*) (__func__)), "value != NULL")
; return ((0)); } } while (0)
;
1505
1506 if (!info->valid)
1507 return FALSE(0);
1508
1509 return temperature_value (info->dew, unit, value, info->temperature_unit);
1510}
1511
1512gboolean
1513weather_info_get_value_apparent (WeatherInfo *info, TempUnit unit, gdouble *value)
1514{
1515 g_return_val_if_fail (info != NULL, FALSE)do { if ((info != ((void*)0))) { } else { g_return_if_fail_warning
("CafeWeather", ((const char*) (__func__)), "info != NULL");
return ((0)); } } while (0)
;
1516 g_return_val_if_fail (value != NULL, FALSE)do { if ((value != ((void*)0))) { } else { g_return_if_fail_warning
("CafeWeather", ((const char*) (__func__)), "value != NULL")
; return ((0)); } } while (0)
;
1517
1518 if (!info->valid)
1519 return FALSE(0);
1520
1521 return temperature_value (calc_apparent (info), unit, value, info->temperature_unit);
1522}
1523
1524gboolean
1525weather_info_get_value_update (WeatherInfo *info, time_t *value)
1526{
1527 g_return_val_if_fail (info != NULL, FALSE)do { if ((info != ((void*)0))) { } else { g_return_if_fail_warning
("CafeWeather", ((const char*) (__func__)), "info != NULL");
return ((0)); } } while (0)
;
1528 g_return_val_if_fail (value != NULL, FALSE)do { if ((value != ((void*)0))) { } else { g_return_if_fail_warning
("CafeWeather", ((const char*) (__func__)), "value != NULL")
; return ((0)); } } while (0)
;
1529
1530 if (!info->valid)
1531 return FALSE(0);
1532
1533 *value = info->update;
1534
1535 return TRUE(!(0));
1536}
1537
1538gboolean
1539weather_info_get_value_sunrise (WeatherInfo *info, time_t *value)
1540{
1541 g_return_val_if_fail (info != NULL, FALSE)do { if ((info != ((void*)0))) { } else { g_return_if_fail_warning
("CafeWeather", ((const char*) (__func__)), "info != NULL");
return ((0)); } } while (0)
;
1542 g_return_val_if_fail (value != NULL, FALSE)do { if ((value != ((void*)0))) { } else { g_return_if_fail_warning
("CafeWeather", ((const char*) (__func__)), "value != NULL")
; return ((0)); } } while (0)
;
1543
1544 if (!info->valid || !info->sunriseValid)
1545 return FALSE(0);
1546
1547 *value = info->sunrise;
1548
1549 return TRUE(!(0));
1550}
1551
1552gboolean
1553weather_info_get_value_sunset (WeatherInfo *info, time_t *value)
1554{
1555 g_return_val_if_fail (info != NULL, FALSE)do { if ((info != ((void*)0))) { } else { g_return_if_fail_warning
("CafeWeather", ((const char*) (__func__)), "info != NULL");
return ((0)); } } while (0)
;
1556 g_return_val_if_fail (value != NULL, FALSE)do { if ((value != ((void*)0))) { } else { g_return_if_fail_warning
("CafeWeather", ((const char*) (__func__)), "value != NULL")
; return ((0)); } } while (0)
;
1557
1558 if (!info->valid || !info->sunsetValid)
1559 return FALSE(0);
1560
1561 *value = info->sunset;
1562
1563 return TRUE(!(0));
1564}
1565
1566gboolean
1567weather_info_get_value_moonphase (WeatherInfo *info,
1568 WeatherMoonPhase *value,
1569 WeatherMoonLatitude *lat)
1570{
1571 g_return_val_if_fail (info != NULL, FALSE)do { if ((info != ((void*)0))) { } else { g_return_if_fail_warning
("CafeWeather", ((const char*) (__func__)), "info != NULL");
return ((0)); } } while (0)
;
1572 g_return_val_if_fail (value != NULL, FALSE)do { if ((value != ((void*)0))) { } else { g_return_if_fail_warning
("CafeWeather", ((const char*) (__func__)), "value != NULL")
; return ((0)); } } while (0)
;
1573
1574 if (!info->valid || !info->moonValid)
1575 return FALSE(0);
1576
1577 *value = info->moonphase;
1578 *lat = info->moonlatitude;
1579
1580 return TRUE(!(0));
1581}
1582
1583gboolean
1584weather_info_get_value_wind (WeatherInfo *info, SpeedUnit unit, gdouble *speed, WeatherWindDirection *direction)
1585{
1586 gboolean res = FALSE(0);
1587
1588 g_return_val_if_fail (info != NULL, FALSE)do { if ((info != ((void*)0))) { } else { g_return_if_fail_warning
("CafeWeather", ((const char*) (__func__)), "info != NULL");
return ((0)); } } while (0)
;
1589 g_return_val_if_fail (speed != NULL, FALSE)do { if ((speed != ((void*)0))) { } else { g_return_if_fail_warning
("CafeWeather", ((const char*) (__func__)), "speed != NULL")
; return ((0)); } } while (0)
;
1590 g_return_val_if_fail (direction != NULL, FALSE)do { if ((direction != ((void*)0))) { } else { g_return_if_fail_warning
("CafeWeather", ((const char*) (__func__)), "direction != NULL"
); return ((0)); } } while (0)
;
1591
1592 if (!info->valid)
1593 return FALSE(0);
1594
1595 if (info->windspeed < 0.0 || info->wind <= WIND_INVALID || info->wind >= WIND_LAST)
1596 return FALSE(0);
1597
1598 res = speed_value (info->windspeed, unit, speed, info->speed_unit);
1599 *direction = info->wind;
1600
1601 return res;
1602}
1603
1604gboolean
1605weather_info_get_value_pressure (WeatherInfo *info, PressureUnit unit, gdouble *value)
1606{
1607 g_return_val_if_fail (info != NULL, FALSE)do { if ((info != ((void*)0))) { } else { g_return_if_fail_warning
("CafeWeather", ((const char*) (__func__)), "info != NULL");
return ((0)); } } while (0)
;
1608 g_return_val_if_fail (value != NULL, FALSE)do { if ((value != ((void*)0))) { } else { g_return_if_fail_warning
("CafeWeather", ((const char*) (__func__)), "value != NULL")
; return ((0)); } } while (0)
;
1609
1610 if (!info->valid)
1611 return FALSE(0);
1612
1613 return pressure_value (info->pressure, unit, value, info->pressure_unit);
1614}
1615
1616gboolean
1617weather_info_get_value_visibility (WeatherInfo *info, DistanceUnit unit, gdouble *value)
1618{
1619 g_return_val_if_fail (info != NULL, FALSE)do { if ((info != ((void*)0))) { } else { g_return_if_fail_warning
("CafeWeather", ((const char*) (__func__)), "info != NULL");
return ((0)); } } while (0)
;
1620 g_return_val_if_fail (value != NULL, FALSE)do { if ((value != ((void*)0))) { } else { g_return_if_fail_warning
("CafeWeather", ((const char*) (__func__)), "value != NULL")
; return ((0)); } } while (0)
;
1621
1622 if (!info->valid)
1623 return FALSE(0);
1624
1625 return distance_value (info->visibility, unit, value, info->distance_unit);
1626}
1627
1628/**
1629 * weather_info_get_upcoming_moonphases:
1630 * @info: WeatherInfo containing the time_t of interest
1631 * @phases: An array of four time_t values that will hold the returned values.
1632 * The values are esticafes of the time of the next new, quarter, full and
1633 * three-quarter moons.
1634 *
1635 * Returns: gboolean indicating success or failure
1636 */
1637gboolean
1638weather_info_get_upcoming_moonphases (WeatherInfo *info, time_t *phases)
1639{
1640 g_return_val_if_fail (info != NULL, FALSE)do { if ((info != ((void*)0))) { } else { g_return_if_fail_warning
("CafeWeather", ((const char*) (__func__)), "info != NULL");
return ((0)); } } while (0)
;
1641 g_return_val_if_fail (phases != NULL, FALSE)do { if ((phases != ((void*)0))) { } else { g_return_if_fail_warning
("CafeWeather", ((const char*) (__func__)), "phases != NULL"
); return ((0)); } } while (0)
;
1642
1643 return calc_moon_phases(info, phases);
1644}
1645
1646static void
1647_weather_internal_check (void)
1648{
1649 g_assert (G_N_ELEMENTS (wind_direction_str) == WIND_LAST)do { if ((sizeof (wind_direction_str) / sizeof ((wind_direction_str
)[0])) == WIND_LAST) ; else g_assertion_message_expr ("CafeWeather"
, "weather.c", 1649, ((const char*) (__func__)), "G_N_ELEMENTS (wind_direction_str) == WIND_LAST"
); } while (0)
;
1650 g_assert (G_N_ELEMENTS (sky_str) == SKY_LAST)do { if ((sizeof (sky_str) / sizeof ((sky_str)[0])) == SKY_LAST
) ; else g_assertion_message_expr ("CafeWeather", "weather.c"
, 1650, ((const char*) (__func__)), "G_N_ELEMENTS (sky_str) == SKY_LAST"
); } while (0)
;
1651 g_assert (G_N_ELEMENTS (conditions_str) == PHENOMENON_LAST)do { if ((sizeof (conditions_str) / sizeof ((conditions_str)[
0])) == PHENOMENON_LAST) ; else g_assertion_message_expr ("CafeWeather"
, "weather.c", 1651, ((const char*) (__func__)), "G_N_ELEMENTS (conditions_str) == PHENOMENON_LAST"
); } while (0)
;
1652 g_assert (G_N_ELEMENTS (conditions_str[0]) == QUALIFIER_LAST)do { if ((sizeof (conditions_str[0]) / sizeof ((conditions_str
[0])[0])) == QUALIFIER_LAST) ; else g_assertion_message_expr (
"CafeWeather", "weather.c", 1652, ((const char*) (__func__)),
"G_N_ELEMENTS (conditions_str[0]) == QUALIFIER_LAST"); } while
(0)
;
1653}