diff options
| author | mbkma <[email protected]> | 2026-01-31 11:39:20 +0100 |
|---|---|---|
| committer | mbkma <[email protected]> | 2026-01-31 11:39:20 +0100 |
| commit | 065b480128dfe0fbfdb45b996b1be695225d7f2c (patch) | |
| tree | b524d8058615781fab795ab5b9756db17674008e | |
| parent | 636cd88ac33b7e54fad01b616e6dc8875b0e32ea (diff) | |
| download | libmateweather-clang.tar.bz2 libmateweather-clang.tar.xz | |
use consistent formating: clang-format LLVM styleclang
27 files changed, 5110 insertions, 5404 deletions
diff --git a/libmateweather/location-entry.c b/libmateweather/location-entry.c index f88cbbb..ffe45db 100644 --- a/libmateweather/location-entry.c +++ b/libmateweather/location-entry.c @@ -35,169 +35,153 @@ * #MateWeatherLocation<!-- -->s */ -G_DEFINE_TYPE (MateWeatherLocationEntry, mateweather_location_entry, GTK_TYPE_ENTRY) +G_DEFINE_TYPE(MateWeatherLocationEntry, mateweather_location_entry, + GTK_TYPE_ENTRY) enum { - PROP_0, + PROP_0, - PROP_TOP, - PROP_LOCATION, + PROP_TOP, + PROP_LOCATION, - LAST_PROP + LAST_PROP }; -static void mateweather_location_entry_build_model (MateWeatherLocationEntry *entry, - MateWeatherLocation *top); -static void set_property (GObject *object, guint prop_id, - const GValue *value, GParamSpec *pspec); -static void get_property (GObject *object, guint prop_id, - GValue *value, GParamSpec *pspec); - -enum -{ - MATEWEATHER_LOCATION_ENTRY_COL_DISPLAY_NAME = 0, - MATEWEATHER_LOCATION_ENTRY_COL_LOCATION, - MATEWEATHER_LOCATION_ENTRY_COL_COMPARE_NAME, - MATEWEATHER_LOCATION_ENTRY_COL_SORT_NAME, - MATEWEATHER_LOCATION_ENTRY_NUM_COLUMNS +static void +mateweather_location_entry_build_model(MateWeatherLocationEntry *entry, + MateWeatherLocation *top); +static void set_property(GObject *object, guint prop_id, const GValue *value, + GParamSpec *pspec); +static void get_property(GObject *object, guint prop_id, GValue *value, + GParamSpec *pspec); + +enum { + MATEWEATHER_LOCATION_ENTRY_COL_DISPLAY_NAME = 0, + MATEWEATHER_LOCATION_ENTRY_COL_LOCATION, + MATEWEATHER_LOCATION_ENTRY_COL_COMPARE_NAME, + MATEWEATHER_LOCATION_ENTRY_COL_SORT_NAME, + MATEWEATHER_LOCATION_ENTRY_NUM_COLUMNS }; -static gboolean matcher (GtkEntryCompletion *completion, const char *key, - GtkTreeIter *iter, gpointer user_data); -static gboolean match_selected (GtkEntryCompletion *completion, - GtkTreeModel *model, - GtkTreeIter *iter, - gpointer entry); -static void entry_changed (MateWeatherLocationEntry *entry); +static gboolean matcher(GtkEntryCompletion *completion, const char *key, + GtkTreeIter *iter, gpointer user_data); +static gboolean match_selected(GtkEntryCompletion *completion, + GtkTreeModel *model, GtkTreeIter *iter, + gpointer entry); +static void entry_changed(MateWeatherLocationEntry *entry); -static void -mateweather_location_entry_init (MateWeatherLocationEntry *entry) -{ - GtkEntryCompletion *completion; +static void mateweather_location_entry_init(MateWeatherLocationEntry *entry) { + GtkEntryCompletion *completion; - completion = gtk_entry_completion_new (); + completion = gtk_entry_completion_new(); - gtk_entry_completion_set_popup_set_width (completion, FALSE); - gtk_entry_completion_set_text_column (completion, MATEWEATHER_LOCATION_ENTRY_COL_DISPLAY_NAME); - gtk_entry_completion_set_match_func (completion, matcher, NULL, NULL); + gtk_entry_completion_set_popup_set_width(completion, FALSE); + gtk_entry_completion_set_text_column( + completion, MATEWEATHER_LOCATION_ENTRY_COL_DISPLAY_NAME); + gtk_entry_completion_set_match_func(completion, matcher, NULL, NULL); - g_signal_connect (completion, "match_selected", - G_CALLBACK (match_selected), entry); + g_signal_connect(completion, "match_selected", G_CALLBACK(match_selected), + entry); - gtk_entry_set_completion (GTK_ENTRY (entry), completion); - g_object_unref (completion); + gtk_entry_set_completion(GTK_ENTRY(entry), completion); + g_object_unref(completion); - entry->custom_text = FALSE; - g_signal_connect (entry, "changed", - G_CALLBACK (entry_changed), NULL); + entry->custom_text = FALSE; + g_signal_connect(entry, "changed", G_CALLBACK(entry_changed), NULL); } -static void -finalize (GObject *object) -{ - MateWeatherLocationEntry *entry = MATEWEATHER_LOCATION_ENTRY (object); +static void finalize(GObject *object) { + MateWeatherLocationEntry *entry = MATEWEATHER_LOCATION_ENTRY(object); - if (entry->location) - mateweather_location_unref (entry->location); - if (entry->top) - mateweather_location_unref (entry->top); + if (entry->location) + mateweather_location_unref(entry->location); + if (entry->top) + mateweather_location_unref(entry->top); - G_OBJECT_CLASS (mateweather_location_entry_parent_class)->finalize (object); + G_OBJECT_CLASS(mateweather_location_entry_parent_class)->finalize(object); } -static void -mateweather_location_entry_class_init (MateWeatherLocationEntryClass *location_entry_class) -{ - GObjectClass *object_class = G_OBJECT_CLASS (location_entry_class); - - object_class->finalize = finalize; - object_class->set_property = set_property; - object_class->get_property = get_property; - - /* properties */ - g_object_class_install_property ( - object_class, PROP_TOP, - g_param_spec_pointer ("top", - "Top Location", - "The MateWeatherLocation whose children will be used to fill in the entry", - G_PARAM_WRITABLE | G_PARAM_CONSTRUCT_ONLY)); - g_object_class_install_property ( - object_class, PROP_LOCATION, - g_param_spec_pointer ("location", - "Location", - "The selected MateWeatherLocation", - G_PARAM_READWRITE)); +static void mateweather_location_entry_class_init( + MateWeatherLocationEntryClass *location_entry_class) { + GObjectClass *object_class = G_OBJECT_CLASS(location_entry_class); + + object_class->finalize = finalize; + object_class->set_property = set_property; + object_class->get_property = get_property; + + /* properties */ + g_object_class_install_property( + object_class, PROP_TOP, + g_param_spec_pointer("top", "Top Location", + "The MateWeatherLocation whose children will be " + "used to fill in the entry", + G_PARAM_WRITABLE | G_PARAM_CONSTRUCT_ONLY)); + g_object_class_install_property( + object_class, PROP_LOCATION, + g_param_spec_pointer("location", "Location", + "The selected MateWeatherLocation", + G_PARAM_READWRITE)); } -static void -set_property (GObject *object, guint prop_id, - const GValue *value, GParamSpec *pspec) -{ - switch (prop_id) { - case PROP_TOP: - mateweather_location_entry_build_model (MATEWEATHER_LOCATION_ENTRY (object), - g_value_get_pointer (value)); - break; - case PROP_LOCATION: - mateweather_location_entry_set_location (MATEWEATHER_LOCATION_ENTRY (object), - g_value_get_pointer (value)); - break; - default: - G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); - break; - } +static void set_property(GObject *object, guint prop_id, const GValue *value, + GParamSpec *pspec) { + switch (prop_id) { + case PROP_TOP: + mateweather_location_entry_build_model(MATEWEATHER_LOCATION_ENTRY(object), + g_value_get_pointer(value)); + break; + case PROP_LOCATION: + mateweather_location_entry_set_location(MATEWEATHER_LOCATION_ENTRY(object), + g_value_get_pointer(value)); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec); + break; + } } -static void -get_property (GObject *object, guint prop_id, - GValue *value, GParamSpec *pspec) -{ - MateWeatherLocationEntry *entry = MATEWEATHER_LOCATION_ENTRY (object); - - switch (prop_id) { - case PROP_LOCATION: - g_value_set_pointer (value, entry->location); - break; - default: - G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); - break; - } +static void get_property(GObject *object, guint prop_id, GValue *value, + GParamSpec *pspec) { + MateWeatherLocationEntry *entry = MATEWEATHER_LOCATION_ENTRY(object); + + switch (prop_id) { + case PROP_LOCATION: + g_value_set_pointer(value, entry->location); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec); + break; + } } -static void -entry_changed (MateWeatherLocationEntry *entry) -{ - entry->custom_text = TRUE; +static void entry_changed(MateWeatherLocationEntry *entry) { + entry->custom_text = TRUE; } -static void -set_location_internal (MateWeatherLocationEntry *entry, - GtkTreeModel *model, - GtkTreeIter *iter) -{ - MateWeatherLocation *loc; - char *name; - - if (entry->location) - mateweather_location_unref (entry->location); - - if (iter) { - gtk_tree_model_get (model, iter, - MATEWEATHER_LOCATION_ENTRY_COL_DISPLAY_NAME, &name, - MATEWEATHER_LOCATION_ENTRY_COL_LOCATION, &loc, - -1); - entry->location = mateweather_location_ref (loc); - gtk_entry_set_text (GTK_ENTRY (entry), name); - entry->custom_text = FALSE; - g_free (name); - } else { - entry->location = NULL; - gtk_entry_set_text (GTK_ENTRY (entry), ""); - entry->custom_text = TRUE; - } +static void set_location_internal(MateWeatherLocationEntry *entry, + GtkTreeModel *model, GtkTreeIter *iter) { + MateWeatherLocation *loc; + char *name; + + if (entry->location) + mateweather_location_unref(entry->location); - gtk_editable_select_region (GTK_EDITABLE (entry), 0, -1); - g_object_notify (G_OBJECT (entry), "location"); + if (iter) { + gtk_tree_model_get(model, iter, MATEWEATHER_LOCATION_ENTRY_COL_DISPLAY_NAME, + &name, MATEWEATHER_LOCATION_ENTRY_COL_LOCATION, &loc, + -1); + entry->location = mateweather_location_ref(loc); + gtk_entry_set_text(GTK_ENTRY(entry), name); + entry->custom_text = FALSE; + g_free(name); + } else { + entry->location = NULL; + gtk_entry_set_text(GTK_ENTRY(entry), ""); + entry->custom_text = TRUE; + } + + gtk_editable_select_region(GTK_EDITABLE(entry), 0, -1); + g_object_notify(G_OBJECT(entry), "location"); } /** @@ -209,33 +193,30 @@ set_location_internal (MateWeatherLocationEntry *entry, * Sets @entry's location to @loc, and updates the text of the * entry accordingly. **/ -void -mateweather_location_entry_set_location (MateWeatherLocationEntry *entry, - MateWeatherLocation *loc) -{ - GtkEntryCompletion *completion; - GtkTreeModel *model; - GtkTreeIter iter; - MateWeatherLocation *cmploc; - - g_return_if_fail (MATEWEATHER_IS_LOCATION_ENTRY (entry)); - - completion = gtk_entry_get_completion (GTK_ENTRY (entry)); - model = gtk_entry_completion_get_model (completion); - - if (gtk_tree_model_get_iter_first (model, &iter)) { - do { - gtk_tree_model_get (model, &iter, - MATEWEATHER_LOCATION_ENTRY_COL_LOCATION, &cmploc, - -1); - if (loc == cmploc) { - set_location_internal (entry, model, &iter); - return; - } - } while (gtk_tree_model_iter_next (model, &iter)); - } - - set_location_internal (entry, model, NULL); +void mateweather_location_entry_set_location(MateWeatherLocationEntry *entry, + MateWeatherLocation *loc) { + GtkEntryCompletion *completion; + GtkTreeModel *model; + GtkTreeIter iter; + MateWeatherLocation *cmploc; + + g_return_if_fail(MATEWEATHER_IS_LOCATION_ENTRY(entry)); + + completion = gtk_entry_get_completion(GTK_ENTRY(entry)); + model = gtk_entry_completion_get_model(completion); + + if (gtk_tree_model_get_iter_first(model, &iter)) { + do { + gtk_tree_model_get(model, &iter, MATEWEATHER_LOCATION_ENTRY_COL_LOCATION, + &cmploc, -1); + if (loc == cmploc) { + set_location_internal(entry, model, &iter); + return; + } + } while (gtk_tree_model_iter_next(model, &iter)); + } + + set_location_internal(entry, model, NULL); } /** @@ -250,14 +231,13 @@ mateweather_location_entry_set_location (MateWeatherLocationEntry *entry, * location is selected. **/ MateWeatherLocation * -mateweather_location_entry_get_location (MateWeatherLocationEntry *entry) -{ - g_return_val_if_fail (MATEWEATHER_IS_LOCATION_ENTRY (entry), NULL); - - if (entry->location) - return mateweather_location_ref (entry->location); - else - return NULL; +mateweather_location_entry_get_location(MateWeatherLocationEntry *entry) { + g_return_val_if_fail(MATEWEATHER_IS_LOCATION_ENTRY(entry), NULL); + + if (entry->location) + return mateweather_location_ref(entry->location); + else + return NULL; } /** @@ -272,11 +252,10 @@ mateweather_location_entry_get_location (MateWeatherLocationEntry *entry) * it's set to the default text of a location. **/ gboolean -mateweather_location_entry_has_custom_text (MateWeatherLocationEntry *entry) -{ - g_return_val_if_fail (MATEWEATHER_IS_LOCATION_ENTRY (entry), FALSE); +mateweather_location_entry_has_custom_text(MateWeatherLocationEntry *entry) { + g_return_val_if_fail(MATEWEATHER_IS_LOCATION_ENTRY(entry), FALSE); - return entry->custom_text; + return entry->custom_text; } /** @@ -292,286 +271,267 @@ mateweather_location_entry_has_custom_text (MateWeatherLocationEntry *entry) * Return value: %TRUE if @entry's location could be set to a matching city, * %FALSE otherwise. **/ -gboolean -mateweather_location_entry_set_city (MateWeatherLocationEntry *entry, - const char *city_name, - const char *code) -{ - GtkEntryCompletion *completion; - GtkTreeModel *model; - GtkTreeIter iter; - MateWeatherLocation *cmploc; - const char *cmpcode; - char *cmpname; - - g_return_val_if_fail (MATEWEATHER_IS_LOCATION_ENTRY (entry), FALSE); - g_return_val_if_fail (code != NULL, FALSE); - - completion = gtk_entry_get_completion (GTK_ENTRY (entry)); - model = gtk_entry_completion_get_model (completion); - - if (gtk_tree_model_get_iter_first (model, &iter)) { - do { - gtk_tree_model_get (model, &iter, - MATEWEATHER_LOCATION_ENTRY_COL_LOCATION, &cmploc, - -1); - - cmpcode = mateweather_location_get_code (cmploc); - if (!cmpcode || strcmp (cmpcode, code) != 0) - continue; - - if (city_name) { - cmpname = mateweather_location_get_city_name (cmploc); - if (!cmpname || strcmp (cmpname, city_name) != 0) { - g_free (cmpname); - continue; - } - g_free (cmpname); - } - - set_location_internal (entry, model, &iter); - return TRUE; - } while (gtk_tree_model_iter_next (model, &iter)); +gboolean mateweather_location_entry_set_city(MateWeatherLocationEntry *entry, + const char *city_name, + const char *code) { + GtkEntryCompletion *completion; + GtkTreeModel *model; + GtkTreeIter iter; + MateWeatherLocation *cmploc; + const char *cmpcode; + char *cmpname; + + g_return_val_if_fail(MATEWEATHER_IS_LOCATION_ENTRY(entry), FALSE); + g_return_val_if_fail(code != NULL, FALSE); + + completion = gtk_entry_get_completion(GTK_ENTRY(entry)); + model = gtk_entry_completion_get_model(completion); + + if (gtk_tree_model_get_iter_first(model, &iter)) { + do { + gtk_tree_model_get(model, &iter, MATEWEATHER_LOCATION_ENTRY_COL_LOCATION, + &cmploc, -1); + + cmpcode = mateweather_location_get_code(cmploc); + if (!cmpcode || strcmp(cmpcode, code) != 0) + continue; + + if (city_name) { + cmpname = mateweather_location_get_city_name(cmploc); + if (!cmpname || strcmp(cmpname, city_name) != 0) { + g_free(cmpname); + continue; + } + g_free(cmpname); + } + + set_location_internal(entry, model, &iter); + return TRUE; + } while (gtk_tree_model_iter_next(model, &iter)); + } + + set_location_internal(entry, model, NULL); + + return FALSE; +} + +static void fill_location_entry_model(GtkTreeStore *store, + MateWeatherLocation *loc, + const char *parent_display_name, + const char *parent_compare_name) { + MateWeatherLocation **children; + char *display_name, *compare_name; + GtkTreeIter iter; + int i; + + children = mateweather_location_get_children(loc); + + switch (mateweather_location_get_level(loc)) { + case MATEWEATHER_LOCATION_WORLD: + case MATEWEATHER_LOCATION_REGION: + case MATEWEATHER_LOCATION_ADM2: + /* Ignore these levels of hierarchy; just recurse, passing on + * the names from the parent node. + */ + for (i = 0; children[i]; i++) { + fill_location_entry_model(store, children[i], parent_display_name, + parent_compare_name); } + break; + + case MATEWEATHER_LOCATION_COUNTRY: + /* Recurse, initializing the names to the country name */ + for (i = 0; children[i]; i++) { + fill_location_entry_model(store, children[i], + mateweather_location_get_name(loc), + mateweather_location_get_sort_name(loc)); + } + break; - set_location_internal (entry, model, NULL); + case MATEWEATHER_LOCATION_ADM1: + /* Recurse, adding the ADM1 name to the country name */ + display_name = g_strdup_printf("%s, %s", mateweather_location_get_name(loc), + parent_display_name); + compare_name = g_strdup_printf( + "%s, %s", mateweather_location_get_sort_name(loc), parent_compare_name); - return FALSE; -} + for (i = 0; children[i]; i++) { + fill_location_entry_model(store, children[i], display_name, compare_name); + } -static void -fill_location_entry_model (GtkTreeStore *store, MateWeatherLocation *loc, - const char *parent_display_name, - const char *parent_compare_name) -{ - MateWeatherLocation **children; - char *display_name, *compare_name; - GtkTreeIter iter; - int i; - - children = mateweather_location_get_children (loc); - - switch (mateweather_location_get_level (loc)) { - case MATEWEATHER_LOCATION_WORLD: - case MATEWEATHER_LOCATION_REGION: - case MATEWEATHER_LOCATION_ADM2: - /* Ignore these levels of hierarchy; just recurse, passing on - * the names from the parent node. - */ - for (i = 0; children[i]; i++) { - fill_location_entry_model (store, children[i], - parent_display_name, - parent_compare_name); - } - break; - - case MATEWEATHER_LOCATION_COUNTRY: - /* Recurse, initializing the names to the country name */ - for (i = 0; children[i]; i++) { - fill_location_entry_model (store, children[i], - mateweather_location_get_name (loc), - mateweather_location_get_sort_name (loc)); - } - break; - - case MATEWEATHER_LOCATION_ADM1: - /* Recurse, adding the ADM1 name to the country name */ - display_name = g_strdup_printf ("%s, %s", mateweather_location_get_name (loc), parent_display_name); - compare_name = g_strdup_printf ("%s, %s", mateweather_location_get_sort_name (loc), parent_compare_name); - - for (i = 0; children[i]; i++) { - fill_location_entry_model (store, children[i], - display_name, compare_name); - } - - g_free (display_name); - g_free (compare_name); - break; - - case MATEWEATHER_LOCATION_CITY: - if (children[0] && children[1]) { - /* If there are multiple (<location>) children, add a line - * for each of them. - */ - for (i = 0; children[i]; i++) { - display_name = g_strdup_printf ("%s (%s), %s", - mateweather_location_get_name (loc), - mateweather_location_get_name (children[i]), - parent_display_name); - compare_name = g_strdup_printf ("%s (%s), %s", - mateweather_location_get_sort_name (loc), - mateweather_location_get_sort_name (children[i]), - parent_compare_name); - - gtk_tree_store_append (store, &iter, NULL); - gtk_tree_store_set (store, &iter, - MATEWEATHER_LOCATION_ENTRY_COL_LOCATION, children[i], - MATEWEATHER_LOCATION_ENTRY_COL_DISPLAY_NAME, display_name, - MATEWEATHER_LOCATION_ENTRY_COL_COMPARE_NAME, compare_name, - -1); - - g_free (display_name); - g_free (compare_name); - } - } else if (children[0]) { - /* Else there's only one location. This is a mix of the - * city-with-multiple-location case above and the - * location-with-no-city case below. - */ - display_name = g_strdup_printf ("%s, %s", - mateweather_location_get_name (loc), - parent_display_name); - compare_name = g_strdup_printf ("%s, %s", - mateweather_location_get_sort_name (loc), - parent_compare_name); - - gtk_tree_store_append (store, &iter, NULL); - gtk_tree_store_set (store, &iter, - MATEWEATHER_LOCATION_ENTRY_COL_LOCATION, children[0], - MATEWEATHER_LOCATION_ENTRY_COL_DISPLAY_NAME, display_name, - MATEWEATHER_LOCATION_ENTRY_COL_COMPARE_NAME, compare_name, - -1); - - g_free (display_name); - g_free (compare_name); - } - break; - - case MATEWEATHER_LOCATION_WEATHER_STATION: - /* <location> with no parent <city>, or <city> with a single - * child <location>. - */ - display_name = g_strdup_printf ("%s, %s", - mateweather_location_get_name (loc), - parent_display_name); - compare_name = g_strdup_printf ("%s, %s", - mateweather_location_get_sort_name (loc), - parent_compare_name); - - gtk_tree_store_append (store, &iter, NULL); - gtk_tree_store_set (store, &iter, - MATEWEATHER_LOCATION_ENTRY_COL_LOCATION, loc, - MATEWEATHER_LOCATION_ENTRY_COL_DISPLAY_NAME, display_name, - MATEWEATHER_LOCATION_ENTRY_COL_COMPARE_NAME, compare_name, - -1); - - g_free (display_name); - g_free (compare_name); - break; + g_free(display_name); + g_free(compare_name); + break; + + case MATEWEATHER_LOCATION_CITY: + if (children[0] && children[1]) { + /* If there are multiple (<location>) children, add a line + * for each of them. + */ + for (i = 0; children[i]; i++) { + display_name = g_strdup_printf( + "%s (%s), %s", mateweather_location_get_name(loc), + mateweather_location_get_name(children[i]), parent_display_name); + compare_name = g_strdup_printf( + "%s (%s), %s", mateweather_location_get_sort_name(loc), + mateweather_location_get_sort_name(children[i]), + parent_compare_name); + + gtk_tree_store_append(store, &iter, NULL); + gtk_tree_store_set( + store, &iter, MATEWEATHER_LOCATION_ENTRY_COL_LOCATION, children[i], + MATEWEATHER_LOCATION_ENTRY_COL_DISPLAY_NAME, display_name, + MATEWEATHER_LOCATION_ENTRY_COL_COMPARE_NAME, compare_name, -1); + + g_free(display_name); + g_free(compare_name); + } + } else if (children[0]) { + /* Else there's only one location. This is a mix of the + * city-with-multiple-location case above and the + * location-with-no-city case below. + */ + display_name = g_strdup_printf( + "%s, %s", mateweather_location_get_name(loc), parent_display_name); + compare_name = + g_strdup_printf("%s, %s", mateweather_location_get_sort_name(loc), + parent_compare_name); + + gtk_tree_store_append(store, &iter, NULL); + gtk_tree_store_set( + store, &iter, MATEWEATHER_LOCATION_ENTRY_COL_LOCATION, children[0], + MATEWEATHER_LOCATION_ENTRY_COL_DISPLAY_NAME, display_name, + MATEWEATHER_LOCATION_ENTRY_COL_COMPARE_NAME, compare_name, -1); + + g_free(display_name); + g_free(compare_name); } + break; - mateweather_location_free_children (loc, children); + case MATEWEATHER_LOCATION_WEATHER_STATION: + /* <location> with no parent <city>, or <city> with a single + * child <location>. + */ + display_name = g_strdup_printf("%s, %s", mateweather_location_get_name(loc), + parent_display_name); + compare_name = g_strdup_printf( + "%s, %s", mateweather_location_get_sort_name(loc), parent_compare_name); + + gtk_tree_store_append(store, &iter, NULL); + gtk_tree_store_set( + store, &iter, MATEWEATHER_LOCATION_ENTRY_COL_LOCATION, loc, + MATEWEATHER_LOCATION_ENTRY_COL_DISPLAY_NAME, display_name, + MATEWEATHER_LOCATION_ENTRY_COL_COMPARE_NAME, compare_name, -1); + + g_free(display_name); + g_free(compare_name); + break; + } + + mateweather_location_free_children(loc, children); } static void -mateweather_location_entry_build_model (MateWeatherLocationEntry *entry, - MateWeatherLocation *top) -{ - GtkTreeStore *store = NULL; - - g_return_if_fail (MATEWEATHER_IS_LOCATION_ENTRY (entry)); - entry->top = mateweather_location_ref (top); - - store = gtk_tree_store_new (4, G_TYPE_STRING, G_TYPE_POINTER, G_TYPE_STRING, G_TYPE_STRING); - fill_location_entry_model (store, top, NULL, NULL); - gtk_entry_completion_set_model (gtk_entry_get_completion (GTK_ENTRY (entry)), - GTK_TREE_MODEL (store)); - g_object_unref (store); +mateweather_location_entry_build_model(MateWeatherLocationEntry *entry, + MateWeatherLocation *top) { + GtkTreeStore *store = NULL; + + g_return_if_fail(MATEWEATHER_IS_LOCATION_ENTRY(entry)); + entry->top = mateweather_location_ref(top); + + store = gtk_tree_store_new(4, G_TYPE_STRING, G_TYPE_POINTER, G_TYPE_STRING, + G_TYPE_STRING); + fill_location_entry_model(store, top, NULL, NULL); + gtk_entry_completion_set_model(gtk_entry_get_completion(GTK_ENTRY(entry)), + GTK_TREE_MODEL(store)); + g_object_unref(store); } -static char * -find_word (const char *full_name, const char *word, int word_len, - gboolean whole_word, gboolean is_first_word) -{ - char *p = (char *)full_name - 1; - - while ((p = strchr (p + 1, *word))) { - if (strncmp (p, word, word_len) != 0) - continue; - - if (p > (char *)full_name) { - char *prev = g_utf8_prev_char (p); - - /* Make sure p points to the start of a word */ - if (g_unichar_isalpha (g_utf8_get_char (prev))) - continue; - - /* If we're matching the first word of the key, it has to - * match the first word of the location, city, state, or - * country. Eg, it either matches the start of the string - * (which we already know it doesn't at this point) or - * it is preceded by the string ", " (which isn't actually - * a perfect test. FIXME) - */ - if (is_first_word) { - if (prev == (char *)full_name || strncmp (prev - 1, ", ", 2) != 0) - continue; - } - } - - if (whole_word && g_unichar_isalpha (g_utf8_get_char (p + word_len))) - continue; - - return p; +static char *find_word(const char *full_name, const char *word, int word_len, + gboolean whole_word, gboolean is_first_word) { + char *p = (char *)full_name - 1; + + while ((p = strchr(p + 1, *word))) { + if (strncmp(p, word, word_len) != 0) + continue; + + if (p > (char *)full_name) { + char *prev = g_utf8_prev_char(p); + + /* Make sure p points to the start of a word */ + if (g_unichar_isalpha(g_utf8_get_char(prev))) + continue; + + /* If we're matching the first word of the key, it has to + * match the first word of the location, city, state, or + * country. Eg, it either matches the start of the string + * (which we already know it doesn't at this point) or + * it is preceded by the string ", " (which isn't actually + * a perfect test. FIXME) + */ + if (is_first_word) { + if (prev == (char *)full_name || strncmp(prev - 1, ", ", 2) != 0) + continue; + } } - return NULL; + + if (whole_word && g_unichar_isalpha(g_utf8_get_char(p + word_len))) + continue; + + return p; + } + return NULL; } -static gboolean -matcher (GtkEntryCompletion *completion, const char *key, - GtkTreeIter *iter, gpointer user_data) -{ - char *name, *name_mem; - MateWeatherLocation *loc; - gboolean is_first_word = TRUE, match; - int len; - - gtk_tree_model_get (gtk_entry_completion_get_model (completion), iter, - MATEWEATHER_LOCATION_ENTRY_COL_COMPARE_NAME, &name_mem, - MATEWEATHER_LOCATION_ENTRY_COL_LOCATION, &loc, - -1); - name = name_mem; - - if (!loc) { - g_free (name_mem); - return FALSE; - } +static gboolean matcher(GtkEntryCompletion *completion, const char *key, + GtkTreeIter *iter, gpointer user_data) { + char *name, *name_mem; + MateWeatherLocation *loc; + gboolean is_first_word = TRUE, match; + int len; - /* All but the last word in KEY must match a full word from NAME, - * in order (but possibly skipping some words from NAME). - */ - len = strcspn (key, " "); - while (key[len]) { - name = find_word (name, key, len, TRUE, is_first_word); - if (!name) { - g_free (name_mem); - return FALSE; - } - - key += len; - while (*key && !g_unichar_isalpha (g_utf8_get_char (key))) - key = g_utf8_next_char (key); - while (*name && !g_unichar_isalpha (g_utf8_get_char (name))) - name = g_utf8_next_char (name); - - len = strcspn (key, " "); - is_first_word = FALSE; + gtk_tree_model_get(gtk_entry_completion_get_model(completion), iter, + MATEWEATHER_LOCATION_ENTRY_COL_COMPARE_NAME, &name_mem, + MATEWEATHER_LOCATION_ENTRY_COL_LOCATION, &loc, -1); + name = name_mem; + + if (!loc) { + g_free(name_mem); + return FALSE; + } + + /* All but the last word in KEY must match a full word from NAME, + * in order (but possibly skipping some words from NAME). + */ + len = strcspn(key, " "); + while (key[len]) { + name = find_word(name, key, len, TRUE, is_first_word); + if (!name) { + g_free(name_mem); + return FALSE; } - /* The last word in KEY must match a prefix of a following word in NAME */ - match = find_word (name, key, strlen (key), FALSE, is_first_word) != NULL; - g_free (name_mem); - return match; + key += len; + while (*key && !g_unichar_isalpha(g_utf8_get_char(key))) + key = g_utf8_next_char(key); + while (*name && !g_unichar_isalpha(g_utf8_get_char(name))) + name = g_utf8_next_char(name); + + len = strcspn(key, " "); + is_first_word = FALSE; + } + + /* The last word in KEY must match a prefix of a following word in NAME */ + match = find_word(name, key, strlen(key), FALSE, is_first_word) != NULL; + g_free(name_mem); + return match; } -static gboolean -match_selected (GtkEntryCompletion *completion, - GtkTreeModel *model, - GtkTreeIter *iter, - gpointer entry) -{ - set_location_internal (entry, model, iter); - return TRUE; +static gboolean match_selected(GtkEntryCompletion *completion, + GtkTreeModel *model, GtkTreeIter *iter, + gpointer entry) { + set_location_internal(entry, model, iter); + return TRUE; } /** @@ -586,10 +546,6 @@ match_selected (GtkEntryCompletion *completion, * * Return value: the new #MateWeatherLocationEntry **/ -GtkWidget * -mateweather_location_entry_new (MateWeatherLocation *top) -{ - return g_object_new (MATEWEATHER_TYPE_LOCATION_ENTRY, - "top", top, - NULL); +GtkWidget *mateweather_location_entry_new(MateWeatherLocation *top) { + return g_object_new(MATEWEATHER_TYPE_LOCATION_ENTRY, "top", top, NULL); } diff --git a/libmateweather/location-entry.h b/libmateweather/location-entry.h index 9f1e3a0..98cbf2c 100644 --- a/libmateweather/location-entry.h +++ b/libmateweather/location-entry.h @@ -24,38 +24,48 @@ #include <gtk/gtk.h> #include <libmateweather/mateweather-location.h> -#define MATEWEATHER_TYPE_LOCATION_ENTRY (mateweather_location_entry_get_type ()) -#define MATEWEATHER_LOCATION_ENTRY(object) (G_TYPE_CHECK_INSTANCE_CAST ((object), MATEWEATHER_TYPE_LOCATION_ENTRY, MateWeatherLocationEntry)) -#define MATEWEATHER_LOCATION_ENTRY_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), MATEWEATHER_TYPE_LOCATION_ENTRY, MateWeatherLocationEntryClass)) -#define MATEWEATHER_IS_LOCATION_ENTRY(object) (G_TYPE_CHECK_INSTANCE_TYPE ((object), MATEWEATHER_TYPE_LOCATION_ENTRY)) -#define MATEWEATHER_IS_LOCATION_ENTRY_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), MATEWEATHER_TYPE_LOCATION_ENTRY)) -#define MATEWEATHER_LOCATION_ENTRY_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), MATEWEATHER_TYPE_LOCATION_ENTRY, MateWeatherLocationEntryClass)) +#define MATEWEATHER_TYPE_LOCATION_ENTRY (mateweather_location_entry_get_type()) +#define MATEWEATHER_LOCATION_ENTRY(object) \ + (G_TYPE_CHECK_INSTANCE_CAST((object), MATEWEATHER_TYPE_LOCATION_ENTRY, \ + MateWeatherLocationEntry)) +#define MATEWEATHER_LOCATION_ENTRY_CLASS(klass) \ + (G_TYPE_CHECK_CLASS_CAST((klass), MATEWEATHER_TYPE_LOCATION_ENTRY, \ + MateWeatherLocationEntryClass)) +#define MATEWEATHER_IS_LOCATION_ENTRY(object) \ + (G_TYPE_CHECK_INSTANCE_TYPE((object), MATEWEATHER_TYPE_LOCATION_ENTRY)) +#define MATEWEATHER_IS_LOCATION_ENTRY_CLASS(klass) \ + (G_TYPE_CHECK_CLASS_TYPE((klass), MATEWEATHER_TYPE_LOCATION_ENTRY)) +#define MATEWEATHER_LOCATION_ENTRY_GET_CLASS(obj) \ + (G_TYPE_INSTANCE_GET_CLASS((obj), MATEWEATHER_TYPE_LOCATION_ENTRY, \ + MateWeatherLocationEntryClass)) typedef struct { - GtkEntry parent; + GtkEntry parent; - /*< private >*/ - MateWeatherLocation *location, *top; - guint custom_text : 1; + /*< private >*/ + MateWeatherLocation *location, *top; + guint custom_text : 1; } MateWeatherLocationEntry; typedef struct { - GtkEntryClass parent_class; + GtkEntryClass parent_class; } MateWeatherLocationEntryClass; -GType mateweather_location_entry_get_type (void); +GType mateweather_location_entry_get_type(void); -GtkWidget *mateweather_location_entry_new (MateWeatherLocation *top); +GtkWidget *mateweather_location_entry_new(MateWeatherLocation *top); -void mateweather_location_entry_set_location (MateWeatherLocationEntry *entry, - MateWeatherLocation *loc); -MateWeatherLocation *mateweather_location_entry_get_location (MateWeatherLocationEntry *entry); +void mateweather_location_entry_set_location(MateWeatherLocationEntry *entry, + MateWeatherLocation *loc); +MateWeatherLocation * +mateweather_location_entry_get_location(MateWeatherLocationEntry *entry); -gboolean mateweather_location_entry_has_custom_text (MateWeatherLocationEntry *entry); +gboolean +mateweather_location_entry_has_custom_text(MateWeatherLocationEntry *entry); -gboolean mateweather_location_entry_set_city (MateWeatherLocationEntry *entry, - const char *city_name, - const char *code); +gboolean mateweather_location_entry_set_city(MateWeatherLocationEntry *entry, + const char *city_name, + const char *code); #endif diff --git a/libmateweather/mateweather-location.c b/libmateweather/mateweather-location.c index e5fd511..99787f7 100644 --- a/libmateweather/mateweather-location.c +++ b/libmateweather/mateweather-location.c @@ -22,10 +22,10 @@ #include <config.h> #endif -#include <string.h> -#include <math.h> -#include <locale.h> #include <libxml/xmlreader.h> +#include <locale.h> +#include <math.h> +#include <string.h> #define MATEWEATHER_I_KNOW_THIS_IS_UNSTABLE #include "mateweather-location.h" @@ -44,16 +44,16 @@ */ struct _MateWeatherLocation { - char *name, *sort_name; - MateWeatherLocation *parent, **children; - MateWeatherLocationLevel level; - char *country_code, *tz_hint; - char *station_code, *forecast_zone, *radar; - double latitude, longitude; - gboolean latlon_valid; - MateWeatherTimezone **zones; - - int ref_count; + char *name, *sort_name; + MateWeatherLocation *parent, **children; + MateWeatherLocationLevel level; + char *country_code, *tz_hint; + char *station_code, *forecast_zone, *radar; + double latitude, longitude; + gboolean latlon_valid; + MateWeatherTimezone **zones; + + int ref_count; }; /** @@ -82,222 +82,215 @@ struct _MateWeatherLocation { * will never appear outside of cities. **/ -static int -sort_locations_by_name (gconstpointer a, gconstpointer b) -{ - MateWeatherLocation *loc_a = *(MateWeatherLocation **)a; - MateWeatherLocation *loc_b = *(MateWeatherLocation **)b; +static int sort_locations_by_name(gconstpointer a, gconstpointer b) { + MateWeatherLocation *loc_a = *(MateWeatherLocation **)a; + MateWeatherLocation *loc_b = *(MateWeatherLocation **)b; - return g_utf8_collate (loc_a->sort_name, loc_b->sort_name); + return g_utf8_collate(loc_a->sort_name, loc_b->sort_name); } -static int -sort_locations_by_distance (gconstpointer a, gconstpointer b, gpointer user_data) -{ - MateWeatherLocation *loc_a = *(MateWeatherLocation **)a; - MateWeatherLocation *loc_b = *(MateWeatherLocation **)b; - MateWeatherLocation *city = (MateWeatherLocation *)user_data; - double dist_a, dist_b; - - dist_a = mateweather_location_get_distance (loc_a, city); - dist_b = mateweather_location_get_distance (loc_b, city); - if (dist_a < dist_b) - return -1; - else if (dist_a > dist_b) - return 1; - else - return 0; +static int sort_locations_by_distance(gconstpointer a, gconstpointer b, + gpointer user_data) { + MateWeatherLocation *loc_a = *(MateWeatherLocation **)a; + MateWeatherLocation *loc_b = *(MateWeatherLocation **)b; + MateWeatherLocation *city = (MateWeatherLocation *)user_data; + double dist_a, dist_b; + + dist_a = mateweather_location_get_distance(loc_a, city); + dist_b = mateweather_location_get_distance(loc_b, city); + if (dist_a < dist_b) + return -1; + else if (dist_a > dist_b) + return 1; + else + return 0; } -static gboolean -parse_coordinates (const char *coordinates, - double *latitude, double *longitude) -{ - char *p; - - *latitude = g_ascii_strtod (coordinates, &p) * M_PI / 180.0; - if (p == (char *)coordinates) - return FALSE; - if (*p++ != ' ') - return FALSE; - *longitude = g_ascii_strtod (p, &p) * M_PI / 180.0; - return !*p; +static gboolean parse_coordinates(const char *coordinates, double *latitude, + double *longitude) { + char *p; + + *latitude = g_ascii_strtod(coordinates, &p) * M_PI / 180.0; + if (p == (char *)coordinates) + return FALSE; + if (*p++ != ' ') + return FALSE; + *longitude = g_ascii_strtod(p, &p) * M_PI / 180.0; + return !*p; } -static char * -unparse_coordinates (double latitude, double longitude) -{ - int lat_d, lat_m, lat_s, lon_d, lon_m, lon_s; - char lat_dir, lon_dir; - - latitude = latitude * 180.0 / M_PI; - longitude = longitude * 180.0 / M_PI; - - if (latitude < 0.0) { - lat_dir = 'S'; - latitude = -latitude; - } else - lat_dir = 'N'; - if (longitude < 0.0) { - lon_dir = 'W'; - longitude = -longitude; - } else - lon_dir = 'E'; - - lat_d = (int)latitude; - lat_m = (int)(latitude * 60.0) - lat_d * 60; - lat_s = (int)(latitude * 3600.0) - lat_d * 3600 - lat_m * 60; - lon_d = (int)longitude; - lon_m = (int)(longitude * 60.0) - lon_d * 60; - lon_s = (int)(longitude * 3600.0) - lon_d * 3600 - lon_m * 60; - - return g_strdup_printf ("%02d-%02d-%02d%c %03d-%02d-%02d%c", - lat_d, lat_m, lat_s, lat_dir, - lon_d, lon_m, lon_s, lon_dir); +static char *unparse_coordinates(double latitude, double longitude) { + int lat_d, lat_m, lat_s, lon_d, lon_m, lon_s; + char lat_dir, lon_dir; + + latitude = latitude * 180.0 / M_PI; + longitude = longitude * 180.0 / M_PI; + + if (latitude < 0.0) { + lat_dir = 'S'; + latitude = -latitude; + } else + lat_dir = 'N'; + if (longitude < 0.0) { + lon_dir = 'W'; + longitude = -longitude; + } else + lon_dir = 'E'; + + lat_d = (int)latitude; + lat_m = (int)(latitude * 60.0) - lat_d * 60; + lat_s = (int)(latitude * 3600.0) - lat_d * 3600 - lat_m * 60; + lon_d = (int)longitude; + lon_m = (int)(longitude * 60.0) - lon_d * 60; + lon_s = (int)(longitude * 3600.0) - lon_d * 3600 - lon_m * 60; + + return g_strdup_printf("%02d-%02d-%02d%c %03d-%02d-%02d%c", lat_d, lat_m, + lat_s, lat_dir, lon_d, lon_m, lon_s, lon_dir); } static MateWeatherLocation * -location_new_from_xml (MateWeatherParser *parser, MateWeatherLocationLevel level, - MateWeatherLocation *parent) -{ - MateWeatherLocation *loc, *child; - GPtrArray *children = NULL; - const char *tagname; - char *value, *normalized; - int tagtype, i; - - loc = g_slice_new0 (MateWeatherLocation); - loc->parent = parent; - loc->level = level; - loc->ref_count = 1; - children = g_ptr_array_new (); - - if (xmlTextReaderRead (parser->xml) != 1) - goto error_out; - while ((tagtype = xmlTextReaderNodeType (parser->xml)) != - XML_READER_TYPE_END_ELEMENT) { - if (tagtype != XML_READER_TYPE_ELEMENT) { - if (xmlTextReaderRead (parser->xml) != 1) - goto error_out; - continue; - } - - tagname = (const char *) xmlTextReaderConstName (parser->xml); - if (!strcmp (tagname, "name") && !loc->name) { - value = mateweather_parser_get_localized_value (parser); - if (!value) - goto error_out; - loc->name = g_strdup (value); - xmlFree (value); - normalized = g_utf8_normalize (loc->name, -1, G_NORMALIZE_ALL); - loc->sort_name = g_utf8_casefold (normalized, -1); - g_free (normalized); - - } else if (!strcmp (tagname, "iso-code") && !loc->country_code) { - value = mateweather_parser_get_value (parser); - if (!value) - goto error_out; - loc->country_code = g_strdup (value); - xmlFree (value); - } else if (!strcmp (tagname, "tz-hint") && !loc->tz_hint) { - value = mateweather_parser_get_value (parser); - if (!value) - goto error_out; - loc->tz_hint = g_strdup (value); - xmlFree (value); - } else if (!strcmp (tagname, "code") && !loc->station_code) { - value = mateweather_parser_get_value (parser); - if (!value) - goto error_out; - loc->station_code = g_strdup (value); - xmlFree (value); - } else if (!strcmp (tagname, "coordinates") && !loc->latlon_valid) { - value = mateweather_parser_get_value (parser); - if (!value) - goto error_out; - if (parse_coordinates (value, &loc->latitude, &loc->longitude)) - loc->latlon_valid = TRUE; - xmlFree (value); - } else if (!strcmp (tagname, "zone") && !loc->forecast_zone) { - value = mateweather_parser_get_value (parser); - if (!value) - goto error_out; - loc->forecast_zone = g_strdup (value); - xmlFree (value); - } else if (!strcmp (tagname, "radar") && !loc->radar) { - value = mateweather_parser_get_value (parser); - if (!value) - goto error_out; - loc->radar = g_strdup (value); - xmlFree (value); - - } else if (!strcmp (tagname, "region")) { - child = location_new_from_xml (parser, MATEWEATHER_LOCATION_REGION, loc); - if (!child) - goto error_out; - if (parser->use_regions) - g_ptr_array_add (children, child); - else { - if (child->children) { - for (i = 0; child->children[i]; i++) - g_ptr_array_add (children, mateweather_location_ref (child->children[i])); - } - mateweather_location_unref (child); - } - } else if (!strcmp (tagname, "country")) { - child = location_new_from_xml (parser, MATEWEATHER_LOCATION_COUNTRY, loc); - if (!child) - goto error_out; - g_ptr_array_add (children, child); - } else if (!strcmp (tagname, "state")) { - child = location_new_from_xml (parser, MATEWEATHER_LOCATION_ADM1, loc); - if (!child) - goto error_out; - g_ptr_array_add (children, child); - } else if (!strcmp (tagname, "city")) { - child = location_new_from_xml (parser, MATEWEATHER_LOCATION_CITY, loc); - if (!child) - goto error_out; - g_ptr_array_add (children, child); - } else if (!strcmp (tagname, "location")) { - child = location_new_from_xml (parser, MATEWEATHER_LOCATION_WEATHER_STATION, loc); - if (!child) - goto error_out; - g_ptr_array_add (children, child); - - } else if (!strcmp (tagname, "timezones")) { - loc->zones = mateweather_timezones_parse_xml (parser); - if (!loc->zones) - goto error_out; - - } else { - if (xmlTextReaderNext (parser->xml) != 1) - goto error_out; - } +location_new_from_xml(MateWeatherParser *parser, MateWeatherLocationLevel level, + MateWeatherLocation *parent) { + MateWeatherLocation *loc, *child; + GPtrArray *children = NULL; + const char *tagname; + char *value, *normalized; + int tagtype, i; + + loc = g_slice_new0(MateWeatherLocation); + loc->parent = parent; + loc->level = level; + loc->ref_count = 1; + children = g_ptr_array_new(); + + if (xmlTextReaderRead(parser->xml) != 1) + goto error_out; + while ((tagtype = xmlTextReaderNodeType(parser->xml)) != + XML_READER_TYPE_END_ELEMENT) { + if (tagtype != XML_READER_TYPE_ELEMENT) { + if (xmlTextReaderRead(parser->xml) != 1) + goto error_out; + continue; + } + + tagname = (const char *)xmlTextReaderConstName(parser->xml); + if (!strcmp(tagname, "name") && !loc->name) { + value = mateweather_parser_get_localized_value(parser); + if (!value) + goto error_out; + loc->name = g_strdup(value); + xmlFree(value); + normalized = g_utf8_normalize(loc->name, -1, G_NORMALIZE_ALL); + loc->sort_name = g_utf8_casefold(normalized, -1); + g_free(normalized); + + } else if (!strcmp(tagname, "iso-code") && !loc->country_code) { + value = mateweather_parser_get_value(parser); + if (!value) + goto error_out; + loc->country_code = g_strdup(value); + xmlFree(value); + } else if (!strcmp(tagname, "tz-hint") && !loc->tz_hint) { + value = mateweather_parser_get_value(parser); + if (!value) + goto error_out; + loc->tz_hint = g_strdup(value); + xmlFree(value); + } else if (!strcmp(tagname, "code") && !loc->station_code) { + value = mateweather_parser_get_value(parser); + if (!value) + goto error_out; + loc->station_code = g_strdup(value); + xmlFree(value); + } else if (!strcmp(tagname, "coordinates") && !loc->latlon_valid) { + value = mateweather_parser_get_value(parser); + if (!value) + goto error_out; + if (parse_coordinates(value, &loc->latitude, &loc->longitude)) + loc->latlon_valid = TRUE; + xmlFree(value); + } else if (!strcmp(tagname, "zone") && !loc->forecast_zone) { + value = mateweather_parser_get_value(parser); + if (!value) + goto error_out; + loc->forecast_zone = g_strdup(value); + xmlFree(value); + } else if (!strcmp(tagname, "radar") && !loc->radar) { + value = mateweather_parser_get_value(parser); + if (!value) + goto error_out; + loc->radar = g_strdup(value); + xmlFree(value); + + } else if (!strcmp(tagname, "region")) { + child = location_new_from_xml(parser, MATEWEATHER_LOCATION_REGION, loc); + if (!child) + goto error_out; + if (parser->use_regions) + g_ptr_array_add(children, child); + else { + if (child->children) { + for (i = 0; child->children[i]; i++) + g_ptr_array_add(children, + mateweather_location_ref(child->children[i])); + } + mateweather_location_unref(child); + } + } else if (!strcmp(tagname, "country")) { + child = location_new_from_xml(parser, MATEWEATHER_LOCATION_COUNTRY, loc); + if (!child) + goto error_out; + g_ptr_array_add(children, child); + } else if (!strcmp(tagname, "state")) { + child = location_new_from_xml(parser, MATEWEATHER_LOCATION_ADM1, loc); + if (!child) + goto error_out; + g_ptr_array_add(children, child); + } else if (!strcmp(tagname, "city")) { + child = location_new_from_xml(parser, MATEWEATHER_LOCATION_CITY, loc); + if (!child) + goto error_out; + g_ptr_array_add(children, child); + } else if (!strcmp(tagname, "location")) { + child = location_new_from_xml(parser, + MATEWEATHER_LOCATION_WEATHER_STATION, loc); + if (!child) + goto error_out; + g_ptr_array_add(children, child); + + } else if (!strcmp(tagname, "timezones")) { + loc->zones = mateweather_timezones_parse_xml(parser); + if (!loc->zones) + goto error_out; + + } else { + if (xmlTextReaderNext(parser->xml) != 1) + goto error_out; } - if (xmlTextReaderRead (parser->xml) != 1 && parent) - goto error_out; + } + if (xmlTextReaderRead(parser->xml) != 1 && parent) + goto error_out; - if (children->len) { - if (level == MATEWEATHER_LOCATION_CITY) - g_ptr_array_sort_with_data (children, sort_locations_by_distance, loc); - else - g_ptr_array_sort (children, sort_locations_by_name); + if (children->len) { + if (level == MATEWEATHER_LOCATION_CITY) + g_ptr_array_sort_with_data(children, sort_locations_by_distance, loc); + else + g_ptr_array_sort(children, sort_locations_by_name); - g_ptr_array_add (children, NULL); - loc->children = (MateWeatherLocation **)g_ptr_array_free (children, FALSE); - } else - g_ptr_array_free (children, TRUE); + g_ptr_array_add(children, NULL); + loc->children = (MateWeatherLocation **)g_ptr_array_free(children, FALSE); + } else + g_ptr_array_free(children, TRUE); - return loc; + return loc; error_out: - mateweather_location_unref (loc); - for (i = 0; i < children->len; i++) - mateweather_location_unref (children->pdata[i]); - g_ptr_array_free (children, TRUE); + mateweather_location_unref(loc); + for (i = 0; i < children->len; i++) + mateweather_location_unref(children->pdata[i]); + g_ptr_array_free(children, TRUE); - return NULL; + return NULL; } /** @@ -319,20 +312,18 @@ error_out: * Return value: (allow-none): a %MATEWEATHER_LOCATION_WORLD location, or * %NULL if Locations.xml could not be found or could not be parsed. **/ -MateWeatherLocation * -mateweather_location_new_world (gboolean use_regions) -{ - MateWeatherParser *parser; - MateWeatherLocation *world; +MateWeatherLocation *mateweather_location_new_world(gboolean use_regions) { + MateWeatherParser *parser; + MateWeatherLocation *world; - parser = mateweather_parser_new (use_regions); - if (!parser) - return NULL; + parser = mateweather_parser_new(use_regions); + if (!parser) + return NULL; - world = location_new_from_xml (parser, MATEWEATHER_LOCATION_WORLD, NULL); + world = location_new_from_xml(parser, MATEWEATHER_LOCATION_WORLD, NULL); - mateweather_parser_free (parser); - return world; + mateweather_parser_free(parser); + return world; } /** @@ -343,13 +334,11 @@ mateweather_location_new_world (gboolean use_regions) * * Return value: @loc **/ -MateWeatherLocation * -mateweather_location_ref (MateWeatherLocation *loc) -{ - g_return_val_if_fail (loc != NULL, NULL); +MateWeatherLocation *mateweather_location_ref(MateWeatherLocation *loc) { + g_return_val_if_fail(loc != NULL, NULL); - loc->ref_count++; - return loc; + loc->ref_count++; + return loc; } /** @@ -359,54 +348,50 @@ mateweather_location_ref (MateWeatherLocation *loc) * Subtracts 1 from @loc's reference count, and frees it if the * reference count reaches 0. **/ -void -mateweather_location_unref (MateWeatherLocation *loc) -{ - int i; - - g_return_if_fail (loc != NULL); - - if (--loc->ref_count) - return; - - g_free (loc->name); - g_free (loc->sort_name); - g_free (loc->country_code); - g_free (loc->tz_hint); - g_free (loc->station_code); - g_free (loc->forecast_zone); - g_free (loc->radar); - - if (loc->children) { - for (i = 0; loc->children[i]; i++) { - loc->children[i]->parent = NULL; - mateweather_location_unref (loc->children[i]); - } - g_free (loc->children); +void mateweather_location_unref(MateWeatherLocation *loc) { + int i; + + g_return_if_fail(loc != NULL); + + if (--loc->ref_count) + return; + + g_free(loc->name); + g_free(loc->sort_name); + g_free(loc->country_code); + g_free(loc->tz_hint); + g_free(loc->station_code); + g_free(loc->forecast_zone); + g_free(loc->radar); + + if (loc->children) { + for (i = 0; loc->children[i]; i++) { + loc->children[i]->parent = NULL; + mateweather_location_unref(loc->children[i]); } + g_free(loc->children); + } - if (loc->zones) { - for (i = 0; loc->zones[i]; i++) - mateweather_timezone_unref (loc->zones[i]); - g_free (loc->zones); - } + if (loc->zones) { + for (i = 0; loc->zones[i]; i++) + mateweather_timezone_unref(loc->zones[i]); + g_free(loc->zones); + } - g_slice_free (MateWeatherLocation, loc); + g_slice_free(MateWeatherLocation, loc); } -GType -mateweather_location_get_type (void) -{ - static gsize initialization_value = 0; - - if (g_once_init_enter (&initialization_value)) { - GType type = g_boxed_type_register_static ( - g_intern_static_string ("MateWeatherLocation"), - (GBoxedCopyFunc) mateweather_location_ref, - (GBoxedFreeFunc) mateweather_location_unref); - g_once_init_leave (&initialization_value, type); - } - return initialization_value; +GType mateweather_location_get_type(void) { + static gsize initialization_value = 0; + + if (g_once_init_enter(&initialization_value)) { + GType type = g_boxed_type_register_static( + g_intern_static_string("MateWeatherLocation"), + (GBoxedCopyFunc)mateweather_location_ref, + (GBoxedFreeFunc)mateweather_location_unref); + g_once_init_leave(&initialization_value, type); + } + return initialization_value; } /** @@ -422,11 +407,9 @@ mateweather_location_get_type (void) * * Return value: @loc's name **/ -const char * -mateweather_location_get_name (MateWeatherLocation *loc) -{ - g_return_val_if_fail (loc != NULL, NULL); - return loc->name; +const char *mateweather_location_get_name(MateWeatherLocation *loc) { + g_return_val_if_fail(loc != NULL, NULL); + return loc->name; } /** @@ -440,11 +423,9 @@ mateweather_location_get_name (MateWeatherLocation *loc) * * Return value: @loc's sort name **/ -const char * -mateweather_location_get_sort_name (MateWeatherLocation *loc) -{ - g_return_val_if_fail (loc != NULL, NULL); - return loc->sort_name; +const char *mateweather_location_get_sort_name(MateWeatherLocation *loc) { + g_return_val_if_fail(loc != NULL, NULL); + return loc->sort_name; } /** @@ -457,10 +438,9 @@ mateweather_location_get_sort_name (MateWeatherLocation *loc) * Return value: @loc's level **/ MateWeatherLocationLevel -mateweather_location_get_level (MateWeatherLocation *loc) -{ - g_return_val_if_fail (loc != NULL, MATEWEATHER_LOCATION_WORLD); - return loc->level; +mateweather_location_get_level(MateWeatherLocation *loc) { + g_return_val_if_fail(loc != NULL, MATEWEATHER_LOCATION_WORLD); + return loc->level; } /** @@ -472,11 +452,9 @@ mateweather_location_get_level (MateWeatherLocation *loc) * Return value: (transfer none) (allow-none): @loc's parent, or %NULL * if @loc is a %MATEWEATHER_LOCATION_WORLD node. **/ -MateWeatherLocation * -mateweather_location_get_parent (MateWeatherLocation *loc) -{ - g_return_val_if_fail (loc != NULL, NULL); - return loc->parent; +MateWeatherLocation *mateweather_location_get_parent(MateWeatherLocation *loc) { + g_return_val_if_fail(loc != NULL, NULL); + return loc->parent; } /** @@ -490,16 +468,15 @@ mateweather_location_get_parent (MateWeatherLocation *loc) * children. (May be empty, but will not be %NULL.) **/ MateWeatherLocation ** -mateweather_location_get_children (MateWeatherLocation *loc) -{ - static MateWeatherLocation *no_children = NULL; +mateweather_location_get_children(MateWeatherLocation *loc) { + static MateWeatherLocation *no_children = NULL; - g_return_val_if_fail (loc != NULL, &no_children); + g_return_val_if_fail(loc != NULL, &no_children); - if (loc->children) - return loc->children; - else - return &no_children; + if (loc->children) + return loc->children; + else + return &no_children; } /** @@ -511,11 +488,9 @@ mateweather_location_get_children (MateWeatherLocation *loc) * * Deprecated: This is a no-op. **/ -void -mateweather_location_free_children (MateWeatherLocation *loc, - MateWeatherLocation **children) -{ - ; +void mateweather_location_free_children(MateWeatherLocation *loc, + MateWeatherLocation **children) { + ; } /** @@ -526,11 +501,9 @@ mateweather_location_free_children (MateWeatherLocation *loc, * * Return value: %TRUE if @loc has valid latitude and longitude. **/ -gboolean -mateweather_location_has_coords (MateWeatherLocation *loc) -{ - g_return_val_if_fail (loc != NULL, FALSE); - return loc->latlon_valid; +gboolean mateweather_location_has_coords(MateWeatherLocation *loc) { + g_return_val_if_fail(loc != NULL, FALSE); + return loc->latlon_valid; } /** @@ -542,17 +515,15 @@ mateweather_location_has_coords (MateWeatherLocation *loc) * Gets @loc's coordinates; you must check * mateweather_location_has_coords() before calling this. **/ -void -mateweather_location_get_coords (MateWeatherLocation *loc, - double *latitude, double *longitude) -{ - //g_return_if_fail (loc->latlon_valid); - g_return_if_fail (loc != NULL); - g_return_if_fail (latitude != NULL); - g_return_if_fail (longitude != NULL); - - *latitude = loc->latitude / M_PI * 180.0; - *longitude = loc->longitude / M_PI * 180.0; +void mateweather_location_get_coords(MateWeatherLocation *loc, double *latitude, + double *longitude) { + // g_return_if_fail (loc->latlon_valid); + g_return_if_fail(loc != NULL); + g_return_if_fail(latitude != NULL); + g_return_if_fail(longitude != NULL); + + *latitude = loc->latitude / M_PI * 180.0; + *longitude = loc->longitude / M_PI * 180.0; } /** @@ -564,20 +535,21 @@ mateweather_location_get_coords (MateWeatherLocation *loc, * * Return value: the distance between @loc and @loc2. **/ -double -mateweather_location_get_distance (MateWeatherLocation *loc, MateWeatherLocation *loc2) -{ - /* average radius of the earth in km */ - static const double radius = 6372.795; +double mateweather_location_get_distance(MateWeatherLocation *loc, + MateWeatherLocation *loc2) { + /* average radius of the earth in km */ + static const double radius = 6372.795; - g_return_val_if_fail (loc != NULL, 0); - g_return_val_if_fail (loc2 != NULL, 0); + g_return_val_if_fail(loc != NULL, 0); + g_return_val_if_fail(loc2 != NULL, 0); - //g_return_val_if_fail (loc->latlon_valid, 0.0); - //g_return_val_if_fail (loc2->latlon_valid, 0.0); + // g_return_val_if_fail (loc->latlon_valid, 0.0); + // g_return_val_if_fail (loc2->latlon_valid, 0.0); - return acos (cos (loc->latitude) * cos (loc2->latitude) * cos (loc->longitude - loc2->longitude) + - sin (loc->latitude) * sin (loc2->latitude)) * radius; + return acos(cos(loc->latitude) * cos(loc2->latitude) * + cos(loc->longitude - loc2->longitude) + + sin(loc->latitude) * sin(loc2->latitude)) * + radius; } /** @@ -590,14 +562,12 @@ mateweather_location_get_distance (MateWeatherLocation *loc, MateWeatherLocation * Return value: (allow-none): @loc's country code (or %NULL if @loc * is a region- or world-level location) **/ -const char * -mateweather_location_get_country (MateWeatherLocation *loc) -{ - g_return_val_if_fail (loc != NULL, NULL); - - while (loc->parent && !loc->country_code) - loc = loc->parent; - return loc->country_code; +const char *mateweather_location_get_country(MateWeatherLocation *loc) { + g_return_val_if_fail(loc != NULL, NULL); + + while (loc->parent && !loc->country_code) + loc = loc->parent; + return loc->country_code; } /** @@ -613,47 +583,44 @@ mateweather_location_get_country (MateWeatherLocation *loc) * %NULL **/ MateWeatherTimezone * -mateweather_location_get_timezone (MateWeatherLocation *loc) -{ - const char *tz_hint; - int i; +mateweather_location_get_timezone(MateWeatherLocation *loc) { + const char *tz_hint; + int i; - g_return_val_if_fail (loc != NULL, NULL); + g_return_val_if_fail(loc != NULL, NULL); + + while (loc && !loc->tz_hint) + loc = loc->parent; + if (!loc) + return NULL; + tz_hint = loc->tz_hint; - while (loc && !loc->tz_hint) - loc = loc->parent; + while (loc) { + while (loc && !loc->zones) + loc = loc->parent; if (!loc) - return NULL; - tz_hint = loc->tz_hint; - - while (loc) { - while (loc && !loc->zones) - loc = loc->parent; - if (!loc) - return NULL; - for (i = 0; loc->zones[i]; i++) { - if (!strcmp (tz_hint, mateweather_timezone_get_tzid (loc->zones[i]))) - return loc->zones[i]; - } - loc = loc->parent; + return NULL; + for (i = 0; loc->zones[i]; i++) { + if (!strcmp(tz_hint, mateweather_timezone_get_tzid(loc->zones[i]))) + return loc->zones[i]; } + loc = loc->parent; + } - return NULL; + return NULL; } -static void -add_timezones (MateWeatherLocation *loc, GPtrArray *zones) -{ - int i; - - if (loc->zones) { - for (i = 0; loc->zones[i]; i++) - g_ptr_array_add (zones, mateweather_timezone_ref (loc->zones[i])); - } - if (loc->level < MATEWEATHER_LOCATION_COUNTRY && loc->children) { - for (i = 0; loc->children[i]; i++) - add_timezones (loc->children[i], zones); - } +static void add_timezones(MateWeatherLocation *loc, GPtrArray *zones) { + int i; + + if (loc->zones) { + for (i = 0; loc->zones[i]; i++) + g_ptr_array_add(zones, mateweather_timezone_ref(loc->zones[i])); + } + if (loc->level < MATEWEATHER_LOCATION_COUNTRY && loc->children) { + for (i = 0; loc->children[i]; i++) + add_timezones(loc->children[i], zones); + } } /** @@ -668,16 +635,15 @@ add_timezones (MateWeatherLocation *loc, GPtrArray *zones) * of timezones. May be empty but will not be %NULL. **/ MateWeatherTimezone ** -mateweather_location_get_timezones (MateWeatherLocation *loc) -{ - GPtrArray *zones; +mateweather_location_get_timezones(MateWeatherLocation *loc) { + GPtrArray *zones; - g_return_val_if_fail (loc != NULL, NULL); + g_return_val_if_fail(loc != NULL, NULL); - zones = g_ptr_array_new (); - add_timezones (loc, zones); - g_ptr_array_add (zones, NULL); - return (MateWeatherTimezone **)g_ptr_array_free (zones, FALSE); + zones = g_ptr_array_new(); + add_timezones(loc, zones); + g_ptr_array_add(zones, NULL); + return (MateWeatherTimezone **)g_ptr_array_free(zones, FALSE); } /** @@ -688,18 +654,16 @@ mateweather_location_get_timezones (MateWeatherLocation *loc) * Frees the array of timezones returned by * mateweather_location_get_timezones(). **/ -void -mateweather_location_free_timezones (MateWeatherLocation *loc, - MateWeatherTimezone **zones) -{ - int i; - - g_return_if_fail (loc != NULL); - g_return_if_fail (zones != NULL); - - for (i = 0; zones[i]; i++) - mateweather_timezone_unref (zones[i]); - g_free (zones); +void mateweather_location_free_timezones(MateWeatherLocation *loc, + MateWeatherTimezone **zones) { + int i; + + g_return_if_fail(loc != NULL); + g_return_if_fail(zones != NULL); + + for (i = 0; zones[i]; i++) + mateweather_timezone_unref(zones[i]); + g_free(zones); } /** @@ -711,11 +675,9 @@ mateweather_location_free_timezones (MateWeatherLocation *loc, * * Return value: (allow-none): @loc's METAR station code, or %NULL **/ -const char * -mateweather_location_get_code (MateWeatherLocation *loc) -{ - g_return_val_if_fail (loc != NULL, NULL); - return loc->station_code; +const char *mateweather_location_get_code(MateWeatherLocation *loc) { + g_return_val_if_fail(loc != NULL, NULL); + return loc->station_code; } /** @@ -730,62 +692,57 @@ mateweather_location_get_code (MateWeatherLocation *loc) * * Return value: (allow-none) @loc's city name, or %NULL **/ -char * -mateweather_location_get_city_name (MateWeatherLocation *loc) -{ - g_return_val_if_fail (loc != NULL, NULL); - - if (loc->level == MATEWEATHER_LOCATION_CITY) - return g_strdup (loc->name); - else if (loc->level == MATEWEATHER_LOCATION_WEATHER_STATION && - loc->parent && - loc->parent->level == MATEWEATHER_LOCATION_CITY) - return g_strdup (loc->parent->name); - else - return NULL; +char *mateweather_location_get_city_name(MateWeatherLocation *loc) { + g_return_val_if_fail(loc != NULL, NULL); + + if (loc->level == MATEWEATHER_LOCATION_CITY) + return g_strdup(loc->name); + else if (loc->level == MATEWEATHER_LOCATION_WEATHER_STATION && loc->parent && + loc->parent->level == MATEWEATHER_LOCATION_CITY) + return g_strdup(loc->parent->name); + else + return NULL; } WeatherLocation * -mateweather_location_to_weather_location (MateWeatherLocation *gloc, - const char *name) -{ - const char *code = NULL, *zone = NULL, *radar = NULL, *tz_hint = NULL; - MateWeatherLocation *l; - WeatherLocation *wloc; - char *coords; - - g_return_val_if_fail (gloc != NULL, NULL); - - if (!name) - name = mateweather_location_get_name (gloc); - - if (gloc->level == MATEWEATHER_LOCATION_CITY && gloc->children) - l = gloc->children[0]; - else - l = gloc; - - if (l->latlon_valid) - coords = unparse_coordinates (l->latitude, l->longitude); - else - coords = NULL; - - while (l && (!code || !zone || !radar || !tz_hint)) { - if (!code && l->station_code) - code = l->station_code; - if (!zone && l->forecast_zone) - zone = l->forecast_zone; - if (!radar && l->radar) - radar = l->radar; - if (!tz_hint && l->tz_hint) - tz_hint = l->tz_hint; - l = l->parent; - } - - wloc = weather_location_new (name, code, zone, radar, coords, - mateweather_location_get_country (gloc), - tz_hint); - g_free (coords); - return wloc; +mateweather_location_to_weather_location(MateWeatherLocation *gloc, + const char *name) { + const char *code = NULL, *zone = NULL, *radar = NULL, *tz_hint = NULL; + MateWeatherLocation *l; + WeatherLocation *wloc; + char *coords; + + g_return_val_if_fail(gloc != NULL, NULL); + + if (!name) + name = mateweather_location_get_name(gloc); + + if (gloc->level == MATEWEATHER_LOCATION_CITY && gloc->children) + l = gloc->children[0]; + else + l = gloc; + + if (l->latlon_valid) + coords = unparse_coordinates(l->latitude, l->longitude); + else + coords = NULL; + + while (l && (!code || !zone || !radar || !tz_hint)) { + if (!code && l->station_code) + code = l->station_code; + if (!zone && l->forecast_zone) + zone = l->forecast_zone; + if (!radar && l->radar) + radar = l->radar; + if (!tz_hint && l->tz_hint) + tz_hint = l->tz_hint; + l = l->parent; + } + + wloc = weather_location_new(name, code, zone, radar, coords, + mateweather_location_get_country(gloc), tz_hint); + g_free(coords); + return wloc; } /** @@ -798,16 +755,14 @@ mateweather_location_to_weather_location (MateWeatherLocation *gloc, * Return value: (transfer full): a #WeatherInfo corresponding to * @loc. **/ -WeatherInfo * -mateweather_location_get_weather (MateWeatherLocation *loc) -{ - WeatherLocation *wloc; - WeatherInfo *info; - - g_return_val_if_fail (loc != NULL, NULL); - - wloc = mateweather_location_to_weather_location (loc, NULL); - info = weather_info_new (wloc, NULL, NULL, NULL); - weather_location_free (wloc); - return info; +WeatherInfo *mateweather_location_get_weather(MateWeatherLocation *loc) { + WeatherLocation *wloc; + WeatherInfo *info; + + g_return_val_if_fail(loc != NULL, NULL); + + wloc = mateweather_location_to_weather_location(loc, NULL); + info = weather_info_new(wloc, NULL, NULL, NULL); + weather_location_free(wloc); + return info; } diff --git a/libmateweather/mateweather-location.h b/libmateweather/mateweather-location.h index 7bb9fa9..eb0e498 100644 --- a/libmateweather/mateweather-location.h +++ b/libmateweather/mateweather-location.h @@ -22,7 +22,8 @@ #define __MATEWEATHER_LOCATIONS_H__ #ifndef MATEWEATHER_I_KNOW_THIS_IS_UNSTABLE -#error "libmateweather should only be used if you understand that it's subject to change, and is not supported as a fixed API/ABI or as part of the platform" +#error \ + "libmateweather should only be used if you understand that it's subject to change, and is not supported as a fixed API/ABI or as part of the platform" #endif #include <glib.h> @@ -36,51 +37,55 @@ extern "C" { typedef struct _MateWeatherLocation MateWeatherLocation; typedef enum { /*< underscore_name=mateweather_location_level >*/ - MATEWEATHER_LOCATION_WORLD, - MATEWEATHER_LOCATION_REGION, - MATEWEATHER_LOCATION_COUNTRY, - /* ADM1 = first-order administrative division = state/province, etc */ - MATEWEATHER_LOCATION_ADM1, - /* ADM2 = second-order division = county, etc */ - MATEWEATHER_LOCATION_ADM2, - MATEWEATHER_LOCATION_CITY, - MATEWEATHER_LOCATION_WEATHER_STATION + MATEWEATHER_LOCATION_WORLD, + MATEWEATHER_LOCATION_REGION, + MATEWEATHER_LOCATION_COUNTRY, + /* ADM1 = first-order administrative division = state/province, + etc */ + MATEWEATHER_LOCATION_ADM1, + /* ADM2 = second-order division = county, etc */ + MATEWEATHER_LOCATION_ADM2, + MATEWEATHER_LOCATION_CITY, + MATEWEATHER_LOCATION_WEATHER_STATION } MateWeatherLocationLevel; -GType mateweather_location_get_type (void); -#define MATEWEATHER_TYPE_LOCATION (mateweather_location_get_type ()) +GType mateweather_location_get_type(void); +#define MATEWEATHER_TYPE_LOCATION (mateweather_location_get_type()) -MateWeatherLocation *mateweather_location_new_world (gboolean use_regions); -MateWeatherLocation *mateweather_location_ref (MateWeatherLocation *loc); -void mateweather_location_unref (MateWeatherLocation *loc); +MateWeatherLocation *mateweather_location_new_world(gboolean use_regions); +MateWeatherLocation *mateweather_location_ref(MateWeatherLocation *loc); +void mateweather_location_unref(MateWeatherLocation *loc); -const char *mateweather_location_get_name (MateWeatherLocation *loc); -const char *mateweather_location_get_sort_name (MateWeatherLocation *loc); -MateWeatherLocationLevel mateweather_location_get_level (MateWeatherLocation *loc); -MateWeatherLocation *mateweather_location_get_parent (MateWeatherLocation *loc); +const char *mateweather_location_get_name(MateWeatherLocation *loc); +const char *mateweather_location_get_sort_name(MateWeatherLocation *loc); +MateWeatherLocationLevel +mateweather_location_get_level(MateWeatherLocation *loc); +MateWeatherLocation *mateweather_location_get_parent(MateWeatherLocation *loc); -MateWeatherLocation **mateweather_location_get_children (MateWeatherLocation *loc); -void mateweather_location_free_children (MateWeatherLocation *loc, - MateWeatherLocation **children); +MateWeatherLocation ** +mateweather_location_get_children(MateWeatherLocation *loc); +void mateweather_location_free_children(MateWeatherLocation *loc, + MateWeatherLocation **children); -gboolean mateweather_location_has_coords (MateWeatherLocation *loc); -void mateweather_location_get_coords (MateWeatherLocation *loc, - double *latitude, - double *longitude); -double mateweather_location_get_distance (MateWeatherLocation *loc, - MateWeatherLocation *loc2); +gboolean mateweather_location_has_coords(MateWeatherLocation *loc); +void mateweather_location_get_coords(MateWeatherLocation *loc, double *latitude, + double *longitude); +double mateweather_location_get_distance(MateWeatherLocation *loc, + MateWeatherLocation *loc2); -const char *mateweather_location_get_country (MateWeatherLocation *loc); +const char *mateweather_location_get_country(MateWeatherLocation *loc); -MateWeatherTimezone *mateweather_location_get_timezone (MateWeatherLocation *loc); -MateWeatherTimezone **mateweather_location_get_timezones (MateWeatherLocation *loc); -void mateweather_location_free_timezones (MateWeatherLocation *loc, - MateWeatherTimezone **zones); +MateWeatherTimezone * +mateweather_location_get_timezone(MateWeatherLocation *loc); +MateWeatherTimezone ** +mateweather_location_get_timezones(MateWeatherLocation *loc); +void mateweather_location_free_timezones(MateWeatherLocation *loc, + MateWeatherTimezone **zones); -const char *mateweather_location_get_code (MateWeatherLocation *loc); -char *mateweather_location_get_city_name (MateWeatherLocation *loc); +const char *mateweather_location_get_code(MateWeatherLocation *loc); +char *mateweather_location_get_city_name(MateWeatherLocation *loc); -WeatherInfo *mateweather_location_get_weather (MateWeatherLocation *loc); +WeatherInfo *mateweather_location_get_weather(MateWeatherLocation *loc); #ifdef __cplusplus } diff --git a/libmateweather/mateweather-prefs.c b/libmateweather/mateweather-prefs.c index 6daeed2..dd6025d 100644 --- a/libmateweather/mateweather-prefs.c +++ b/libmateweather/mateweather-prefs.c @@ -33,149 +33,136 @@ * @Title: mateweather-prefs */ -void -mateweather_prefs_load (MateWeatherPrefs *prefs, GSettings *settings) -{ - g_return_if_fail (prefs != NULL); - g_return_if_fail (settings != NULL); +void mateweather_prefs_load(MateWeatherPrefs *prefs, GSettings *settings) { + g_return_if_fail(prefs != NULL); + g_return_if_fail(settings != NULL); - if (prefs->location) { - weather_location_free (prefs->location); - } - gchar *name, *code, *zone, *radar, *coordinates; - name = g_settings_get_string (settings, "location4"); - code = g_settings_get_string (settings, "location1"); - zone = g_settings_get_string (settings, "location2"); - radar = g_settings_get_string (settings, "location3"); - coordinates = g_settings_get_string (settings, "coordinates"); - prefs->location = weather_location_new (name, code, zone, radar, coordinates, - NULL, NULL); + if (prefs->location) { + weather_location_free(prefs->location); + } + gchar *name, *code, *zone, *radar, *coordinates; + name = g_settings_get_string(settings, "location4"); + code = g_settings_get_string(settings, "location1"); + zone = g_settings_get_string(settings, "location2"); + radar = g_settings_get_string(settings, "location3"); + coordinates = g_settings_get_string(settings, "coordinates"); + prefs->location = + weather_location_new(name, code, zone, radar, coordinates, NULL, NULL); - g_free (name); - g_free (code); - g_free (zone); - g_free (radar); - g_free (coordinates); + g_free(name); + g_free(code); + g_free(zone); + g_free(radar); + g_free(coordinates); - prefs->show_notifications = - g_settings_get_boolean (settings, "show-notifications"); - prefs->update_interval = - g_settings_get_int (settings, "auto-update-interval"); - prefs->update_interval = MAX (prefs->update_interval, 60); - prefs->update_enabled = - g_settings_get_boolean (settings, "auto-update"); - prefs->detailed = - g_settings_get_boolean (settings, "enable-detailed-forecast"); - prefs->radar_enabled = - g_settings_get_boolean (settings, "enable-radar-map"); - prefs->use_custom_radar_url = - g_settings_get_boolean (settings, "use-custom-radar-url"); + prefs->show_notifications = + g_settings_get_boolean(settings, "show-notifications"); + prefs->update_interval = g_settings_get_int(settings, "auto-update-interval"); + prefs->update_interval = MAX(prefs->update_interval, 60); + prefs->update_enabled = g_settings_get_boolean(settings, "auto-update"); + prefs->detailed = + g_settings_get_boolean(settings, "enable-detailed-forecast"); + prefs->radar_enabled = g_settings_get_boolean(settings, "enable-radar-map"); + prefs->use_custom_radar_url = + g_settings_get_boolean(settings, "use-custom-radar-url"); - if (prefs->radar) { - g_free (prefs->radar); - prefs->radar = NULL; - } - prefs->radar = g_settings_get_string (settings, "radar"); + if (prefs->radar) { + g_free(prefs->radar); + prefs->radar = NULL; + } + prefs->radar = g_settings_get_string(settings, "radar"); - prefs->temperature_unit = g_settings_get_enum (settings, GSETTINGS_TEMP_UNIT); - prefs->speed_unit = g_settings_get_enum (settings, GSETTINGS_SPEED_UNIT); - prefs->pressure_unit = g_settings_get_enum (settings, GSETTINGS_PRESSURE_UNIT); - prefs->distance_unit = g_settings_get_enum (settings, GSETTINGS_DISTANCE_UNIT); + prefs->temperature_unit = g_settings_get_enum(settings, GSETTINGS_TEMP_UNIT); + prefs->speed_unit = g_settings_get_enum(settings, GSETTINGS_SPEED_UNIT); + prefs->pressure_unit = g_settings_get_enum(settings, GSETTINGS_PRESSURE_UNIT); + prefs->distance_unit = g_settings_get_enum(settings, GSETTINGS_DISTANCE_UNIT); - return; + return; } -const char * -mateweather_prefs_get_temp_display_name (TempUnit temp) -{ - switch (temp) { - case TEMP_UNIT_DEFAULT: - return N_("Default"); - case TEMP_UNIT_KELVIN: - /* Translators: Kelvin */ - return N_("K"); - case TEMP_UNIT_CENTIGRADE: - /* Translators: Celsius */ - return N_("C"); - case TEMP_UNIT_FAHRENHEIT: - /* Translators: Fahrenheit */ - return N_("F"); - default: - return N_("Invalid"); - } +const char *mateweather_prefs_get_temp_display_name(TempUnit temp) { + switch (temp) { + case TEMP_UNIT_DEFAULT: + return N_("Default"); + case TEMP_UNIT_KELVIN: + /* Translators: Kelvin */ + return N_("K"); + case TEMP_UNIT_CENTIGRADE: + /* Translators: Celsius */ + return N_("C"); + case TEMP_UNIT_FAHRENHEIT: + /* Translators: Fahrenheit */ + return N_("F"); + default: + return N_("Invalid"); + } } -const char * -mateweather_prefs_get_speed_display_name (SpeedUnit speed) -{ - switch (speed) { - case SPEED_UNIT_DEFAULT: - return N_("Default"); - case SPEED_UNIT_MS: - /* Translators: meters per second */ - return N_("m/s"); - case SPEED_UNIT_KPH: - /* Translators: kilometers per hour */ - return N_("km/h"); - case SPEED_UNIT_MPH: - /* Translators: miles per hour */ - return N_("mph"); - case SPEED_UNIT_KNOTS: - /* Translators: knots (speed unit) */ - return N_("knots"); - case SPEED_UNIT_BFT: - /* Translators: wind speed */ - return N_("Beaufort scale"); - default: - return N_("Invalid"); - } +const char *mateweather_prefs_get_speed_display_name(SpeedUnit speed) { + switch (speed) { + case SPEED_UNIT_DEFAULT: + return N_("Default"); + case SPEED_UNIT_MS: + /* Translators: meters per second */ + return N_("m/s"); + case SPEED_UNIT_KPH: + /* Translators: kilometers per hour */ + return N_("km/h"); + case SPEED_UNIT_MPH: + /* Translators: miles per hour */ + return N_("mph"); + case SPEED_UNIT_KNOTS: + /* Translators: knots (speed unit) */ + return N_("knots"); + case SPEED_UNIT_BFT: + /* Translators: wind speed */ + return N_("Beaufort scale"); + default: + return N_("Invalid"); + } } -const char * -mateweather_prefs_get_pressure_display_name (PressureUnit pressure) -{ - switch (pressure) { - case PRESSURE_UNIT_DEFAULT: - return N_("Default"); - case PRESSURE_UNIT_KPA: - /* Translators: kilopascals */ - return N_("kPa"); - case PRESSURE_UNIT_HPA: - /* Translators: hectopascals */ - return N_("hPa"); - case PRESSURE_UNIT_MB: - /* Translators: millibars */ - return N_("mb"); - case PRESSURE_UNIT_MM_HG: - /* Translators: millimeters of mercury */ - return N_("mmHg"); - case PRESSURE_UNIT_INCH_HG: - /* Translators: inches of mercury */ - return N_("inHg"); - case PRESSURE_UNIT_ATM: - /* Translators: atmosphere */ - return N_("atm"); - default: - return N_("Invalid"); - } +const char *mateweather_prefs_get_pressure_display_name(PressureUnit pressure) { + switch (pressure) { + case PRESSURE_UNIT_DEFAULT: + return N_("Default"); + case PRESSURE_UNIT_KPA: + /* Translators: kilopascals */ + return N_("kPa"); + case PRESSURE_UNIT_HPA: + /* Translators: hectopascals */ + return N_("hPa"); + case PRESSURE_UNIT_MB: + /* Translators: millibars */ + return N_("mb"); + case PRESSURE_UNIT_MM_HG: + /* Translators: millimeters of mercury */ + return N_("mmHg"); + case PRESSURE_UNIT_INCH_HG: + /* Translators: inches of mercury */ + return N_("inHg"); + case PRESSURE_UNIT_ATM: + /* Translators: atmosphere */ + return N_("atm"); + default: + return N_("Invalid"); + } } -const char * -mateweather_prefs_get_distance_display_name (DistanceUnit distance) -{ - switch (distance) { - case DISTANCE_UNIT_DEFAULT: - return N_("Default"); - case DISTANCE_UNIT_METERS: - /* Translators: meters */ - return N_("m"); - case DISTANCE_UNIT_KM: - /* Translators: kilometers */ - return N_("km"); - case DISTANCE_UNIT_MILES: - /* Translators: miles */ - return N_("mi"); - default: - return N_("Invalid"); - } +const char *mateweather_prefs_get_distance_display_name(DistanceUnit distance) { + switch (distance) { + case DISTANCE_UNIT_DEFAULT: + return N_("Default"); + case DISTANCE_UNIT_METERS: + /* Translators: meters */ + return N_("m"); + case DISTANCE_UNIT_KM: + /* Translators: kilometers */ + return N_("km"); + case DISTANCE_UNIT_MILES: + /* Translators: miles */ + return N_("mi"); + default: + return N_("Invalid"); + } } diff --git a/libmateweather/mateweather-prefs.h b/libmateweather/mateweather-prefs.h index 5bd55cb..f179408 100644 --- a/libmateweather/mateweather-prefs.h +++ b/libmateweather/mateweather-prefs.h @@ -20,42 +20,42 @@ #define __MATEWEATHER_PREFS_H_ #ifndef MATEWEATHER_I_KNOW_THIS_IS_UNSTABLE -#error "libmateweather should only be used if you understand that it's subject to change, and is not supported as a fixed API/ABI or as part of the platform" +#error \ + "libmateweather should only be used if you understand that it's subject to change, and is not supported as a fixed API/ABI or as part of the platform" #endif -#include <libmateweather/weather.h> #include <gio/gio.h> +#include <libmateweather/weather.h> /* gsettings keys */ -#define GSETTINGS_TEMP_UNIT "temperature-unit" -#define GSETTINGS_SPEED_UNIT "speed-unit" +#define GSETTINGS_TEMP_UNIT "temperature-unit" +#define GSETTINGS_SPEED_UNIT "speed-unit" #define GSETTINGS_PRESSURE_UNIT "pressure-unit" #define GSETTINGS_DISTANCE_UNIT "distance-unit" typedef struct _MateWeatherPrefs MateWeatherPrefs; struct _MateWeatherPrefs { - WeatherLocation *location; - gboolean show_notifications; - gint update_interval; /* in seconds */ - gboolean update_enabled; - gboolean detailed; - gboolean radar_enabled; - gboolean use_custom_radar_url; - gchar *radar; - - TempUnit temperature_unit; - SpeedUnit speed_unit; - PressureUnit pressure_unit; - DistanceUnit distance_unit; + WeatherLocation *location; + gboolean show_notifications; + gint update_interval; /* in seconds */ + gboolean update_enabled; + gboolean detailed; + gboolean radar_enabled; + gboolean use_custom_radar_url; + gchar *radar; + + TempUnit temperature_unit; + SpeedUnit speed_unit; + PressureUnit pressure_unit; + DistanceUnit distance_unit; }; -void mateweather_prefs_load (MateWeatherPrefs *prefs, - GSettings *settings); +void mateweather_prefs_load(MateWeatherPrefs *prefs, GSettings *settings); -const char * mateweather_prefs_get_temp_display_name (TempUnit temp); -const char * mateweather_prefs_get_speed_display_name (SpeedUnit speed); -const char * mateweather_prefs_get_pressure_display_name (PressureUnit pressure); -const char * mateweather_prefs_get_distance_display_name (DistanceUnit distance); +const char *mateweather_prefs_get_temp_display_name(TempUnit temp); +const char *mateweather_prefs_get_speed_display_name(SpeedUnit speed); +const char *mateweather_prefs_get_pressure_display_name(PressureUnit pressure); +const char *mateweather_prefs_get_distance_display_name(DistanceUnit distance); #endif /* __MATEWEATHER_PREFS_H_ */ diff --git a/libmateweather/mateweather-timezone.c b/libmateweather/mateweather-timezone.c index 3b4c790..818e0c8 100644 --- a/libmateweather/mateweather-timezone.c +++ b/libmateweather/mateweather-timezone.c @@ -41,11 +41,11 @@ * to extract relevant timezones from the location hierarchy. */ struct _MateWeatherTimezone { - char *id, *name; - int offset, dst_offset; - gboolean has_dst; + char *id, *name; + int offset, dst_offset; + gboolean has_dst; - int ref_count; + int ref_count; }; #define TZ_MAGIC "TZif" @@ -57,198 +57,189 @@ struct _MateWeatherTimezone { #define TZ_TTINFO_GMTOFF_OFFSET 0 #define TZ_TTINFO_ISDST_OFFSET 4 -static gboolean -parse_tzdata (const char *tzname, time_t start, time_t end, - int *offset, gboolean *has_dst, int *dst_offset) -{ - char *filename, *contents; - const char *tzdir; - gsize length; - int timecnt, transitions_size, ttinfo_map_size; - int initial_transition = -1, second_transition = -1; - gint32 *transitions; - char *ttinfo_map, *ttinfos; - gint32 initial_offset, second_offset; - char initial_isdst, second_isdst; - int i; - - tzdir = g_getenv ("TZDIR"); - if (tzdir == NULL) - tzdir = ZONEINFO_DIR; - filename = g_build_filename (tzdir, tzname, NULL); - if (!g_file_get_contents (filename, &contents, &length, NULL)) { - g_free (filename); - return FALSE; +static gboolean parse_tzdata(const char *tzname, time_t start, time_t end, + int *offset, gboolean *has_dst, int *dst_offset) { + char *filename, *contents; + const char *tzdir; + gsize length; + int timecnt, transitions_size, ttinfo_map_size; + int initial_transition = -1, second_transition = -1; + gint32 *transitions; + char *ttinfo_map, *ttinfos; + gint32 initial_offset, second_offset; + char initial_isdst, second_isdst; + int i; + + tzdir = g_getenv("TZDIR"); + if (tzdir == NULL) + tzdir = ZONEINFO_DIR; + filename = g_build_filename(tzdir, tzname, NULL); + if (!g_file_get_contents(filename, &contents, &length, NULL)) { + g_free(filename); + return FALSE; + } + g_free(filename); + + if (length < TZ_HEADER_SIZE || + strncmp(contents, TZ_MAGIC, strlen(TZ_MAGIC)) != 0) { + g_free(contents); + return FALSE; + } + + timecnt = GUINT32_FROM_BE(*(guint32 *)(contents + TZ_TIMECNT_OFFSET)); + transitions = (void *)(contents + TZ_TRANSITIONS_OFFSET); + transitions_size = timecnt * sizeof(*transitions); + ttinfo_map = (void *)(contents + TZ_TRANSITIONS_OFFSET + transitions_size); + ttinfo_map_size = timecnt; + ttinfos = (void *)(ttinfo_map + ttinfo_map_size); + + /* @transitions is an array of @timecnt time_t values. We need to + * find the transition into the current offset, which is the last + * transition before @start. If the following transition is before + * @end, then note that one too, since it presumably means we're + * doing DST. + */ + for (i = 1; i < timecnt && initial_transition == -1; i++) { + if (GINT32_FROM_BE(transitions[i]) > start) { + initial_transition = ttinfo_map[i - 1]; + if (GINT32_FROM_BE(transitions[i]) < end) + second_transition = ttinfo_map[i]; } - g_free (filename); - - if (length < TZ_HEADER_SIZE || - strncmp (contents, TZ_MAGIC, strlen (TZ_MAGIC)) != 0) { - g_free (contents); - return FALSE; - } - - timecnt = GUINT32_FROM_BE (*(guint32 *)(contents + TZ_TIMECNT_OFFSET)); - transitions = (void *)(contents + TZ_TRANSITIONS_OFFSET); - transitions_size = timecnt * sizeof (*transitions); - ttinfo_map = (void *)(contents + TZ_TRANSITIONS_OFFSET + transitions_size); - ttinfo_map_size = timecnt; - ttinfos = (void *)(ttinfo_map + ttinfo_map_size); - - /* @transitions is an array of @timecnt time_t values. We need to - * find the transition into the current offset, which is the last - * transition before @start. If the following transition is before - * @end, then note that one too, since it presumably means we're - * doing DST. - */ - for (i = 1; i < timecnt && initial_transition == -1; i++) { - if (GINT32_FROM_BE (transitions[i]) > start) { - initial_transition = ttinfo_map[i - 1]; - if (GINT32_FROM_BE (transitions[i]) < end) - second_transition = ttinfo_map[i]; - } - } - if (initial_transition == -1) { - if (timecnt) - initial_transition = ttinfo_map[timecnt - 1]; - else - initial_transition = 0; - } - - /* Copy the data out of the corresponding ttinfo structs */ - initial_offset = *(gint32 *)(ttinfos + - initial_transition * TZ_TTINFO_SIZE + - TZ_TTINFO_GMTOFF_OFFSET); - initial_offset = GINT32_FROM_BE (initial_offset); - initial_isdst = *(ttinfos + - initial_transition * TZ_TTINFO_SIZE + - TZ_TTINFO_ISDST_OFFSET); - - if (second_transition != -1) { - second_offset = *(gint32 *)(ttinfos + - second_transition * TZ_TTINFO_SIZE + - TZ_TTINFO_GMTOFF_OFFSET); - second_offset = GINT32_FROM_BE (second_offset); - second_isdst = *(ttinfos + - second_transition * TZ_TTINFO_SIZE + - TZ_TTINFO_ISDST_OFFSET); - - *has_dst = (initial_isdst != second_isdst); - } else - *has_dst = FALSE; - - if (!*has_dst) - *offset = initial_offset / 60; - else { - if (initial_isdst) { - *offset = second_offset / 60; - *dst_offset = initial_offset / 60; - } else { - *offset = initial_offset / 60; - *dst_offset = second_offset / 60; - } + } + if (initial_transition == -1) { + if (timecnt) + initial_transition = ttinfo_map[timecnt - 1]; + else + initial_transition = 0; + } + + /* Copy the data out of the corresponding ttinfo structs */ + initial_offset = *(gint32 *)(ttinfos + initial_transition * TZ_TTINFO_SIZE + + TZ_TTINFO_GMTOFF_OFFSET); + initial_offset = GINT32_FROM_BE(initial_offset); + initial_isdst = + *(ttinfos + initial_transition * TZ_TTINFO_SIZE + TZ_TTINFO_ISDST_OFFSET); + + if (second_transition != -1) { + second_offset = *(gint32 *)(ttinfos + second_transition * TZ_TTINFO_SIZE + + TZ_TTINFO_GMTOFF_OFFSET); + second_offset = GINT32_FROM_BE(second_offset); + second_isdst = *(ttinfos + second_transition * TZ_TTINFO_SIZE + + TZ_TTINFO_ISDST_OFFSET); + + *has_dst = (initial_isdst != second_isdst); + } else + *has_dst = FALSE; + + if (!*has_dst) + *offset = initial_offset / 60; + else { + if (initial_isdst) { + *offset = second_offset / 60; + *dst_offset = initial_offset / 60; + } else { + *offset = initial_offset / 60; + *dst_offset = second_offset / 60; } + } - g_free (contents); - return TRUE; + g_free(contents); + return TRUE; } -static MateWeatherTimezone * -parse_timezone (MateWeatherParser *parser) -{ - MateWeatherTimezone *zone = NULL; - char *id = NULL, *name = NULL; - int offset = 0, dst_offset = 0; - gboolean has_dst = FALSE; - - id = (char *) xmlTextReaderGetAttribute (parser->xml, (xmlChar *) "id"); - if (!id) { - xmlTextReaderNext (parser->xml); - return NULL; - } +static MateWeatherTimezone *parse_timezone(MateWeatherParser *parser) { + MateWeatherTimezone *zone = NULL; + char *id = NULL, *name = NULL; + int offset = 0, dst_offset = 0; + gboolean has_dst = FALSE; - if (!xmlTextReaderIsEmptyElement (parser->xml)) { - if (xmlTextReaderRead (parser->xml) != 1) { - xmlFree (id); - return NULL; - } - - while (xmlTextReaderNodeType (parser->xml) != XML_READER_TYPE_END_ELEMENT) { - if (xmlTextReaderNodeType (parser->xml) != XML_READER_TYPE_ELEMENT) { - if (xmlTextReaderRead (parser->xml) != 1) - break; - continue; - } - - if (!strcmp ((const char *) xmlTextReaderConstName (parser->xml), "name")) - name = mateweather_parser_get_localized_value (parser); - else { - if (xmlTextReaderNext (parser->xml) != 1) - break; - } - } - } + id = (char *)xmlTextReaderGetAttribute(parser->xml, (xmlChar *)"id"); + if (!id) { + xmlTextReaderNext(parser->xml); + return NULL; + } - if (parse_tzdata (id, parser->year_start, parser->year_end, - &offset, &has_dst, &dst_offset)) { - zone = g_slice_new0 (MateWeatherTimezone); - zone->ref_count = 1; - zone->id = g_strdup (id); - zone->name = g_strdup (name); - zone->offset = offset; - zone->has_dst = has_dst; - zone->dst_offset = dst_offset; + if (!xmlTextReaderIsEmptyElement(parser->xml)) { + if (xmlTextReaderRead(parser->xml) != 1) { + xmlFree(id); + return NULL; } - xmlFree (id); - if (name) - xmlFree (name); + while (xmlTextReaderNodeType(parser->xml) != XML_READER_TYPE_END_ELEMENT) { + if (xmlTextReaderNodeType(parser->xml) != XML_READER_TYPE_ELEMENT) { + if (xmlTextReaderRead(parser->xml) != 1) + break; + continue; + } + + if (!strcmp((const char *)xmlTextReaderConstName(parser->xml), "name")) + name = mateweather_parser_get_localized_value(parser); + else { + if (xmlTextReaderNext(parser->xml) != 1) + break; + } + } + } - return zone; + if (parse_tzdata(id, parser->year_start, parser->year_end, &offset, &has_dst, + &dst_offset)) { + zone = g_slice_new0(MateWeatherTimezone); + zone->ref_count = 1; + zone->id = g_strdup(id); + zone->name = g_strdup(name); + zone->offset = offset; + zone->has_dst = has_dst; + zone->dst_offset = dst_offset; + } + + xmlFree(id); + if (name) + xmlFree(name); + + return zone; } MateWeatherTimezone ** -mateweather_timezones_parse_xml (MateWeatherParser *parser) -{ - GPtrArray *zones; - MateWeatherTimezone *zone; - const char *tagname; - int tagtype, i; - - zones = g_ptr_array_new (); - - if (xmlTextReaderRead (parser->xml) != 1) - goto error_out; - while ((tagtype = xmlTextReaderNodeType (parser->xml)) != - XML_READER_TYPE_END_ELEMENT) { - if (tagtype != XML_READER_TYPE_ELEMENT) { - if (xmlTextReaderRead (parser->xml) != 1) - goto error_out; - continue; - } - - tagname = (const char *) xmlTextReaderConstName (parser->xml); - - if (!strcmp (tagname, "timezone")) { - zone = parse_timezone (parser); - if (zone) - g_ptr_array_add (zones, zone); - } - - if (xmlTextReaderNext (parser->xml) != 1) - goto error_out; +mateweather_timezones_parse_xml(MateWeatherParser *parser) { + GPtrArray *zones; + MateWeatherTimezone *zone; + const char *tagname; + int tagtype, i; + + zones = g_ptr_array_new(); + + if (xmlTextReaderRead(parser->xml) != 1) + goto error_out; + while ((tagtype = xmlTextReaderNodeType(parser->xml)) != + XML_READER_TYPE_END_ELEMENT) { + if (tagtype != XML_READER_TYPE_ELEMENT) { + if (xmlTextReaderRead(parser->xml) != 1) + goto error_out; + continue; } - if (xmlTextReaderRead (parser->xml) != 1) - goto error_out; - g_ptr_array_add (zones, NULL); - return (MateWeatherTimezone **)g_ptr_array_free (zones, FALSE); + tagname = (const char *)xmlTextReaderConstName(parser->xml); + + if (!strcmp(tagname, "timezone")) { + zone = parse_timezone(parser); + if (zone) + g_ptr_array_add(zones, zone); + } + + if (xmlTextReaderNext(parser->xml) != 1) + goto error_out; + } + if (xmlTextReaderRead(parser->xml) != 1) + goto error_out; + + g_ptr_array_add(zones, NULL); + return (MateWeatherTimezone **)g_ptr_array_free(zones, FALSE); error_out: - for (i = 0; i < zones->len; i++) - mateweather_timezone_unref (zones->pdata[i]); - g_ptr_array_free (zones, TRUE); - return NULL; + for (i = 0; i < zones->len; i++) + mateweather_timezone_unref(zones->pdata[i]); + g_ptr_array_free(zones, TRUE); + return NULL; } /** @@ -259,13 +250,11 @@ error_out: * * Return value: @zone **/ -MateWeatherTimezone * -mateweather_timezone_ref (MateWeatherTimezone *zone) -{ - g_return_val_if_fail (zone != NULL, NULL); +MateWeatherTimezone *mateweather_timezone_ref(MateWeatherTimezone *zone) { + g_return_val_if_fail(zone != NULL, NULL); - zone->ref_count++; - return zone; + zone->ref_count++; + return zone; } /** @@ -274,31 +263,27 @@ mateweather_timezone_ref (MateWeatherTimezone *zone) * * Subtracts 1 from @zone's reference count and frees it if it reaches 0. **/ -void -mateweather_timezone_unref (MateWeatherTimezone *zone) -{ - g_return_if_fail (zone != NULL); - - if (!--zone->ref_count) { - g_free (zone->id); - g_free (zone->name); - g_slice_free (MateWeatherTimezone, zone); - } +void mateweather_timezone_unref(MateWeatherTimezone *zone) { + g_return_if_fail(zone != NULL); + + if (!--zone->ref_count) { + g_free(zone->id); + g_free(zone->name); + g_slice_free(MateWeatherTimezone, zone); + } } -GType -mateweather_timezone_get_type (void) -{ - static gsize initialization_value = 0; - - if (g_once_init_enter (&initialization_value)) { - GType type = g_boxed_type_register_static ( - g_intern_static_string ("MateWeatherTimezone"), - (GBoxedCopyFunc) mateweather_timezone_ref, - (GBoxedFreeFunc) mateweather_timezone_unref); - g_once_init_leave (&initialization_value, type); - } - return initialization_value; +GType mateweather_timezone_get_type(void) { + static gsize initialization_value = 0; + + if (g_once_init_enter(&initialization_value)) { + GType type = g_boxed_type_register_static( + g_intern_static_string("MateWeatherTimezone"), + (GBoxedCopyFunc)mateweather_timezone_ref, + (GBoxedFreeFunc)mateweather_timezone_unref); + g_once_init_leave(&initialization_value, type); + } + return initialization_value; } /** @@ -308,20 +293,18 @@ mateweather_timezone_get_type (void) * * Return value: a #MateWeatherTimezone for UTC, or %NULL on error. **/ -MateWeatherTimezone * -mateweather_timezone_get_utc (void) -{ - MateWeatherTimezone *zone = NULL; - - zone = g_slice_new0 (MateWeatherTimezone); - zone->ref_count = 1; - zone->id = g_strdup ("GMT"); - zone->name = g_strdup (_("Greenwich Mean Time")); - zone->offset = 0; - zone->has_dst = FALSE; - zone->dst_offset = 0; - - return zone; +MateWeatherTimezone *mateweather_timezone_get_utc(void) { + MateWeatherTimezone *zone = NULL; + + zone = g_slice_new0(MateWeatherTimezone); + zone->ref_count = 1; + zone->id = g_strdup("GMT"); + zone->name = g_strdup(_("Greenwich Mean Time")); + zone->offset = 0; + zone->has_dst = FALSE; + zone->dst_offset = 0; + + return zone; } /** @@ -337,11 +320,9 @@ mateweather_timezone_get_utc (void) * * Return value: @zone's name **/ -const char * -mateweather_timezone_get_name (MateWeatherTimezone *zone) -{ - g_return_val_if_fail (zone != NULL, NULL); - return zone->name; +const char *mateweather_timezone_get_name(MateWeatherTimezone *zone) { + g_return_val_if_fail(zone != NULL, NULL); + return zone->name; } /** @@ -352,11 +333,9 @@ mateweather_timezone_get_name (MateWeatherTimezone *zone) * * Return value: @zone's tzid **/ -const char * -mateweather_timezone_get_tzid (MateWeatherTimezone *zone) -{ - g_return_val_if_fail (zone != NULL, NULL); - return zone->id; +const char *mateweather_timezone_get_tzid(MateWeatherTimezone *zone) { + g_return_val_if_fail(zone != NULL, NULL); + return zone->id; } /** @@ -368,11 +347,9 @@ mateweather_timezone_get_tzid (MateWeatherTimezone *zone) * * Return value: @zone's standard offset, in minutes **/ -int -mateweather_timezone_get_offset (MateWeatherTimezone *zone) -{ - g_return_val_if_fail (zone != NULL, 0); - return zone->offset; +int mateweather_timezone_get_offset(MateWeatherTimezone *zone) { + g_return_val_if_fail(zone != NULL, 0); + return zone->offset; } /** @@ -383,11 +360,9 @@ mateweather_timezone_get_offset (MateWeatherTimezone *zone) * * Return value: %TRUE if @zone observes daylight/summer time. **/ -gboolean -mateweather_timezone_has_dst (MateWeatherTimezone *zone) -{ - g_return_val_if_fail (zone != NULL, FALSE); - return zone->has_dst; +gboolean mateweather_timezone_has_dst(MateWeatherTimezone *zone) { + g_return_val_if_fail(zone != NULL, FALSE); + return zone->has_dst; } /** @@ -400,10 +375,8 @@ mateweather_timezone_has_dst (MateWeatherTimezone *zone) * * Return value: @zone's daylight/summer time offset, in minutes **/ -int -mateweather_timezone_get_dst_offset (MateWeatherTimezone *zone) -{ - g_return_val_if_fail (zone != NULL, 0); - g_return_val_if_fail (zone->has_dst, 0); - return zone->dst_offset; +int mateweather_timezone_get_dst_offset(MateWeatherTimezone *zone) { + g_return_val_if_fail(zone != NULL, 0); + g_return_val_if_fail(zone->has_dst, 0); + return zone->dst_offset; } diff --git a/libmateweather/mateweather-timezone.h b/libmateweather/mateweather-timezone.h index 58c5d2b..87cf394 100644 --- a/libmateweather/mateweather-timezone.h +++ b/libmateweather/mateweather-timezone.h @@ -22,7 +22,8 @@ #define __MATEWEATHER_TIMEZONE_H__ #ifndef MATEWEATHER_I_KNOW_THIS_IS_UNSTABLE -#error "libmateweather should only be used if you understand that it's subject to change, and is not supported as a fixed API/ABI or as part of the platform" +#error \ + "libmateweather should only be used if you understand that it's subject to change, and is not supported as a fixed API/ABI or as part of the platform" #endif #include <glib-object.h> @@ -33,19 +34,19 @@ extern "C" { typedef struct _MateWeatherTimezone MateWeatherTimezone; -GType mateweather_timezone_get_type (void); -#define MATEWEATHER_TYPE_TIMEZONE (mateweather_timezone_get_type ()) +GType mateweather_timezone_get_type(void); +#define MATEWEATHER_TYPE_TIMEZONE (mateweather_timezone_get_type()) -const char *mateweather_timezone_get_name (MateWeatherTimezone *zone); -const char *mateweather_timezone_get_tzid (MateWeatherTimezone *zone); -int mateweather_timezone_get_offset (MateWeatherTimezone *zone); -gboolean mateweather_timezone_has_dst (MateWeatherTimezone *zone); -int mateweather_timezone_get_dst_offset (MateWeatherTimezone *zone); +const char *mateweather_timezone_get_name(MateWeatherTimezone *zone); +const char *mateweather_timezone_get_tzid(MateWeatherTimezone *zone); +int mateweather_timezone_get_offset(MateWeatherTimezone *zone); +gboolean mateweather_timezone_has_dst(MateWeatherTimezone *zone); +int mateweather_timezone_get_dst_offset(MateWeatherTimezone *zone); -MateWeatherTimezone *mateweather_timezone_ref (MateWeatherTimezone *zone); -void mateweather_timezone_unref (MateWeatherTimezone *zone); +MateWeatherTimezone *mateweather_timezone_ref(MateWeatherTimezone *zone); +void mateweather_timezone_unref(MateWeatherTimezone *zone); -MateWeatherTimezone *mateweather_timezone_get_utc (void); +MateWeatherTimezone *mateweather_timezone_get_utc(void); #ifdef __cplusplus } diff --git a/libmateweather/mateweather-xml.c b/libmateweather/mateweather-xml.c index c736370..2ce9a0f 100644 --- a/libmateweather/mateweather-xml.c +++ b/libmateweather/mateweather-xml.c @@ -22,11 +22,11 @@ #include <config.h> #endif -#include <string.h> -#include <math.h> -#include <locale.h> #include <gtk/gtk.h> #include <libxml/xmlreader.h> +#include <locale.h> +#include <math.h> +#include <string.h> #define MATEWEATHER_I_KNOW_THIS_IS_UNSTABLE #include "mateweather-xml.h" @@ -37,134 +37,117 @@ * @Title: mateweather-xml */ -static gboolean -mateweather_xml_parse_node (MateWeatherLocation *gloc, - GtkTreeStore *store, GtkTreeIter *parent) -{ - GtkTreeIter iter, *self = &iter; - MateWeatherLocation **children, *parent_loc; - MateWeatherLocationLevel level; - WeatherLocation *wloc; - const char *name; - int i; - - name = mateweather_location_get_name (gloc); - children = mateweather_location_get_children (gloc); - level = mateweather_location_get_level (gloc); - - if (!children[0] && level < MATEWEATHER_LOCATION_WEATHER_STATION) { - mateweather_location_free_children (gloc, children); - return TRUE; - } - - switch (mateweather_location_get_level (gloc)) { - case MATEWEATHER_LOCATION_WORLD: - case MATEWEATHER_LOCATION_ADM2: - self = parent; - break; - - case MATEWEATHER_LOCATION_REGION: - case MATEWEATHER_LOCATION_COUNTRY: - case MATEWEATHER_LOCATION_ADM1: - /* Create a row with a name but no WeatherLocation */ - gtk_tree_store_append (store, &iter, parent); - gtk_tree_store_set (store, &iter, - MATEWEATHER_XML_COL_LOC, name, - -1); - break; - - case MATEWEATHER_LOCATION_CITY: - /* If multiple children, treat this like a - * region/country/adm1. If a single child, merge with that - * location. - */ - gtk_tree_store_append (store, &iter, parent); - gtk_tree_store_set (store, &iter, - MATEWEATHER_XML_COL_LOC, name, - -1); - if (children[0] && !children[1]) { - wloc = mateweather_location_to_weather_location (children[0], name); - gtk_tree_store_set (store, &iter, - MATEWEATHER_XML_COL_POINTER, wloc, - -1); - } - break; - - case MATEWEATHER_LOCATION_WEATHER_STATION: - gtk_tree_store_append (store, &iter, parent); - gtk_tree_store_set (store, &iter, - MATEWEATHER_XML_COL_LOC, name, - -1); - - parent_loc = mateweather_location_get_parent (gloc); - if (parent_loc && mateweather_location_get_level (parent_loc) == MATEWEATHER_LOCATION_CITY) - name = mateweather_location_get_name (parent_loc); - wloc = mateweather_location_to_weather_location (gloc, name); - gtk_tree_store_set (store, &iter, - MATEWEATHER_XML_COL_POINTER, wloc, - -1); - break; +static gboolean mateweather_xml_parse_node(MateWeatherLocation *gloc, + GtkTreeStore *store, + GtkTreeIter *parent) { + GtkTreeIter iter, *self = &iter; + MateWeatherLocation **children, *parent_loc; + MateWeatherLocationLevel level; + WeatherLocation *wloc; + const char *name; + int i; + + name = mateweather_location_get_name(gloc); + children = mateweather_location_get_children(gloc); + level = mateweather_location_get_level(gloc); + + if (!children[0] && level < MATEWEATHER_LOCATION_WEATHER_STATION) { + mateweather_location_free_children(gloc, children); + return TRUE; + } + + switch (mateweather_location_get_level(gloc)) { + case MATEWEATHER_LOCATION_WORLD: + case MATEWEATHER_LOCATION_ADM2: + self = parent; + break; + + case MATEWEATHER_LOCATION_REGION: + case MATEWEATHER_LOCATION_COUNTRY: + case MATEWEATHER_LOCATION_ADM1: + /* Create a row with a name but no WeatherLocation */ + gtk_tree_store_append(store, &iter, parent); + gtk_tree_store_set(store, &iter, MATEWEATHER_XML_COL_LOC, name, -1); + break; + + case MATEWEATHER_LOCATION_CITY: + /* If multiple children, treat this like a + * region/country/adm1. If a single child, merge with that + * location. + */ + gtk_tree_store_append(store, &iter, parent); + gtk_tree_store_set(store, &iter, MATEWEATHER_XML_COL_LOC, name, -1); + if (children[0] && !children[1]) { + wloc = mateweather_location_to_weather_location(children[0], name); + gtk_tree_store_set(store, &iter, MATEWEATHER_XML_COL_POINTER, wloc, -1); } - - for (i = 0; children[i]; i++) { - if (!mateweather_xml_parse_node (children[i], store, self)) { - mateweather_location_free_children (gloc, children); - return FALSE; - } + break; + + case MATEWEATHER_LOCATION_WEATHER_STATION: + gtk_tree_store_append(store, &iter, parent); + gtk_tree_store_set(store, &iter, MATEWEATHER_XML_COL_LOC, name, -1); + + parent_loc = mateweather_location_get_parent(gloc); + if (parent_loc && + mateweather_location_get_level(parent_loc) == MATEWEATHER_LOCATION_CITY) + name = mateweather_location_get_name(parent_loc); + wloc = mateweather_location_to_weather_location(gloc, name); + gtk_tree_store_set(store, &iter, MATEWEATHER_XML_COL_POINTER, wloc, -1); + break; + } + + for (i = 0; children[i]; i++) { + if (!mateweather_xml_parse_node(children[i], store, self)) { + mateweather_location_free_children(gloc, children); + return FALSE; } + } - mateweather_location_free_children (gloc, children); - return TRUE; + mateweather_location_free_children(gloc, children); + return TRUE; } -GtkTreeModel * -mateweather_xml_load_locations (void) -{ - MateWeatherLocation *world; - GtkTreeStore *store; +GtkTreeModel *mateweather_xml_load_locations(void) { + MateWeatherLocation *world; + GtkTreeStore *store; - world = mateweather_location_new_world (TRUE); - if (!world) - return NULL; + world = mateweather_location_new_world(TRUE); + if (!world) + return NULL; - store = gtk_tree_store_new (2, G_TYPE_STRING, G_TYPE_POINTER); + store = gtk_tree_store_new(2, G_TYPE_STRING, G_TYPE_POINTER); - if (!mateweather_xml_parse_node (world, store, NULL)) { - mateweather_xml_free_locations ((GtkTreeModel *)store); - store = NULL; - } + if (!mateweather_xml_parse_node(world, store, NULL)) { + mateweather_xml_free_locations((GtkTreeModel *)store); + store = NULL; + } - mateweather_location_unref (world); + mateweather_location_unref(world); - return (GtkTreeModel *)store; + return (GtkTreeModel *)store; } -static gboolean -free_locations (GtkTreeModel *model, GtkTreePath *path, GtkTreeIter *iter, gpointer data) -{ - WeatherLocation *loc = NULL; +static gboolean free_locations(GtkTreeModel *model, GtkTreePath *path, + GtkTreeIter *iter, gpointer data) { + WeatherLocation *loc = NULL; - gtk_tree_model_get (model, iter, - MATEWEATHER_XML_COL_POINTER, &loc, - -1); + gtk_tree_model_get(model, iter, MATEWEATHER_XML_COL_POINTER, &loc, -1); - if (loc) { - weather_location_free (loc); - gtk_tree_store_set ((GtkTreeStore *)model, iter, - MATEWEATHER_XML_COL_POINTER, NULL, - -1); - } + if (loc) { + weather_location_free(loc); + gtk_tree_store_set((GtkTreeStore *)model, iter, MATEWEATHER_XML_COL_POINTER, + NULL, -1); + } - return FALSE; + return FALSE; } -/* Frees model returned from @mateweather_xml_load_locations. It contains allocated - WeatherLocation-s, thus this takes care of the freeing of that memory. */ -void -mateweather_xml_free_locations (GtkTreeModel *locations) -{ - if (locations && GTK_IS_TREE_STORE (locations)) { - gtk_tree_model_foreach (locations, free_locations, NULL); - g_object_unref (locations); - } +/* Frees model returned from @mateweather_xml_load_locations. It contains + allocated WeatherLocation-s, thus this takes care of the freeing of that + memory. */ +void mateweather_xml_free_locations(GtkTreeModel *locations) { + if (locations && GTK_IS_TREE_STORE(locations)) { + gtk_tree_model_foreach(locations, free_locations, NULL); + g_object_unref(locations); + } } diff --git a/libmateweather/mateweather-xml.h b/libmateweather/mateweather-xml.h index da53aab..32271d5 100644 --- a/libmateweather/mateweather-xml.h +++ b/libmateweather/mateweather-xml.h @@ -24,14 +24,13 @@ #include <gtk/gtk.h> #include <libmateweather/weather.h> -enum -{ - MATEWEATHER_XML_COL_LOC = 0, - MATEWEATHER_XML_COL_POINTER, - MATEWEATHER_XML_NUM_COLUMNS +enum { + MATEWEATHER_XML_COL_LOC = 0, + MATEWEATHER_XML_COL_POINTER, + MATEWEATHER_XML_NUM_COLUMNS }; -GtkTreeModel *mateweather_xml_load_locations (void); -void mateweather_xml_free_locations (GtkTreeModel *locations); +GtkTreeModel *mateweather_xml_load_locations(void); +void mateweather_xml_free_locations(GtkTreeModel *locations); #endif /* __MATEWEATHER_XML_H__ */ diff --git a/libmateweather/parser.c b/libmateweather/parser.c index 9e4bb63..faf8e79 100644 --- a/libmateweather/parser.c +++ b/libmateweather/parser.c @@ -27,9 +27,9 @@ #include "parser.h" -#include <string.h> #include <glib.h> #include <libxml/xmlreader.h> +#include <string.h> /** * mateweather_parser_get_value: @@ -41,36 +41,34 @@ * Return value: the text of the current node, as a libxml-allocated * string, or %NULL if the node is empty. **/ -char * -mateweather_parser_get_value (MateWeatherParser *parser) -{ - char *value; - - /* check for null node */ - if (xmlTextReaderIsEmptyElement (parser->xml)) - return NULL; - - /* the next "node" is the text node containing the value we want to get */ - if (xmlTextReaderRead (parser->xml) != 1) - return NULL; - - value = (char *) xmlTextReaderValue (parser->xml); - - /* move on to the end of this node */ - while (xmlTextReaderNodeType (parser->xml) != XML_READER_TYPE_END_ELEMENT) { - if (xmlTextReaderRead (parser->xml) != 1) { - xmlFree (value); - return NULL; - } - } +char *mateweather_parser_get_value(MateWeatherParser *parser) { + char *value; + + /* check for null node */ + if (xmlTextReaderIsEmptyElement(parser->xml)) + return NULL; + + /* the next "node" is the text node containing the value we want to get */ + if (xmlTextReaderRead(parser->xml) != 1) + return NULL; - /* consume the end element too */ - if (xmlTextReaderRead (parser->xml) != 1) { - xmlFree (value); - return NULL; + value = (char *)xmlTextReaderValue(parser->xml); + + /* move on to the end of this node */ + while (xmlTextReaderNodeType(parser->xml) != XML_READER_TYPE_END_ELEMENT) { + if (xmlTextReaderRead(parser->xml) != 1) { + xmlFree(value); + return NULL; } + } + + /* consume the end element too */ + if (xmlTextReaderRead(parser->xml) != 1) { + xmlFree(value); + return NULL; + } - return value; + return value; } /** @@ -86,178 +84,174 @@ mateweather_parser_get_value (MateWeatherParser *parser) * Return value: the localized (or unlocalized) text, as a * libxml-allocated string, or %NULL if the node is empty. **/ -char * -mateweather_parser_get_localized_value (MateWeatherParser *parser) -{ - const char *this_language; - int best_match = INT_MAX; - const char *lang, *tagname, *next_tagname; - gboolean keep_going; - char *name = NULL; - int i; - - tagname = (const char *) xmlTextReaderConstName (parser->xml); +char *mateweather_parser_get_localized_value(MateWeatherParser *parser) { + const char *this_language; + int best_match = INT_MAX; + const char *lang, *tagname, *next_tagname; + gboolean keep_going; + char *name = NULL; + int i; + + tagname = (const char *)xmlTextReaderConstName(parser->xml); + + do { + /* First let's get the language */ + lang = (const char *)xmlTextReaderConstXmlLang(parser->xml); + + if (lang == NULL) + this_language = "C"; + else + this_language = lang; + + /* the next "node" is text node containing the actual name */ + if (xmlTextReaderRead(parser->xml) != 1) { + if (name) + xmlFree(name); + return NULL; + } - do { - /* First let's get the language */ - lang = (const char *) xmlTextReaderConstXmlLang (parser->xml); - - if (lang == NULL) - this_language = "C"; - else - this_language = lang; - - /* the next "node" is text node containing the actual name */ - if (xmlTextReaderRead (parser->xml) != 1) { - if (name) - xmlFree (name); - return NULL; - } - - for (i = 0; parser->locales[i] && i < best_match; i++) { - if (!strcmp (parser->locales[i], this_language)) { - /* if we've already encounted a less accurate - translation, then free it */ - g_free (name); - - name = (char *) xmlTextReaderValue (parser->xml); - best_match = i; - - break; - } - } - - /* Skip to close tag */ - while (xmlTextReaderNodeType (parser->xml) != XML_READER_TYPE_END_ELEMENT) { - if (xmlTextReaderRead (parser->xml) != 1) { - xmlFree (name); - return NULL; - } - } - - /* Skip junk */ - do { - if (xmlTextReaderRead (parser->xml) != 1) { - xmlFree (name); - return NULL; - } - } while (xmlTextReaderNodeType (parser->xml) != XML_READER_TYPE_ELEMENT && - xmlTextReaderNodeType (parser->xml) != XML_READER_TYPE_END_ELEMENT); - - /* if the next tag has the same name then keep going */ - next_tagname = (const char *) xmlTextReaderConstName (parser->xml); - keep_going = !strcmp (next_tagname, tagname); - - } while (keep_going); - - return name; -} + for (i = 0; parser->locales[i] && i < best_match; i++) { + if (!strcmp(parser->locales[i], this_language)) { + /* if we've already encounted a less accurate + translation, then free it */ + g_free(name); -MateWeatherParser * -mateweather_parser_new (gboolean use_regions) -{ - MateWeatherParser *parser; - int zlib_support; - int i, keep_going; - char *filename; - char *tagname, *format; - time_t now; - struct tm tm; + name = (char *)xmlTextReaderValue(parser->xml); + best_match = i; - parser = g_slice_new0 (MateWeatherParser); - parser->use_regions = use_regions; - parser->locales = g_get_language_names (); + break; + } + } - zlib_support = xmlHasFeature (XML_WITH_ZLIB); + /* Skip to close tag */ + while (xmlTextReaderNodeType(parser->xml) != XML_READER_TYPE_END_ELEMENT) { + if (xmlTextReaderRead(parser->xml) != 1) { + xmlFree(name); + return NULL; + } + } - /* First try to load a locale-specific XML. It's much faster. */ - filename = NULL; - for (i = 0; parser->locales[i] != NULL; i++) { - filename = g_strdup_printf ("%s/Locations.%s.xml", - MATEWEATHER_XML_LOCATION_DIR, - parser->locales[i]); + /* Skip junk */ + do { + if (xmlTextReaderRead(parser->xml) != 1) { + xmlFree(name); + return NULL; + } + } while (xmlTextReaderNodeType(parser->xml) != XML_READER_TYPE_ELEMENT && + xmlTextReaderNodeType(parser->xml) != XML_READER_TYPE_END_ELEMENT); - if (g_file_test (filename, G_FILE_TEST_IS_REGULAR)) - break; + /* if the next tag has the same name then keep going */ + next_tagname = (const char *)xmlTextReaderConstName(parser->xml); + keep_going = !strcmp(next_tagname, tagname); - g_free (filename); - filename = NULL; + } while (keep_going); - if (!zlib_support) - continue; + return name; +} - filename = g_strdup_printf ("%s/Locations.%s.xml.gz", - MATEWEATHER_XML_LOCATION_DIR, - parser->locales[i]); +MateWeatherParser *mateweather_parser_new(gboolean use_regions) { + MateWeatherParser *parser; + int zlib_support; + int i, keep_going; + char *filename; + char *tagname, *format; + time_t now; + struct tm tm; - if (g_file_test (filename, G_FILE_TEST_IS_REGULAR)) - break; + parser = g_slice_new0(MateWeatherParser); + parser->use_regions = use_regions; + parser->locales = g_get_language_names(); - g_free (filename); - filename = NULL; - } + zlib_support = xmlHasFeature(XML_WITH_ZLIB); - /* Fall back on the file containing either all translations, or only - * the english names (depending on the configure flags). - */ - if (!filename) - filename = g_build_filename (MATEWEATHER_XML_LOCATION_DIR, "Locations.xml", NULL); + /* First try to load a locale-specific XML. It's much faster. */ + filename = NULL; + for (i = 0; parser->locales[i] != NULL; i++) { + filename = + g_strdup_printf("%s/Locations.%s.xml", MATEWEATHER_XML_LOCATION_DIR, + parser->locales[i]); - if (!g_file_test (filename, G_FILE_TEST_IS_REGULAR) && zlib_support) { - g_free (filename); - filename = g_build_filename (MATEWEATHER_XML_LOCATION_DIR, "Locations.xml.gz", NULL); - } + if (g_file_test(filename, G_FILE_TEST_IS_REGULAR)) + break; - /* Open the xml file containing the different locations */ - parser->xml = xmlNewTextReaderFilename (filename); - g_free (filename); + g_free(filename); + filename = NULL; - if (parser->xml == NULL) - goto error_out; + if (!zlib_support) + continue; - /* fast forward to the first element */ - do { - /* if we encounter a problem here, exit right away */ - if (xmlTextReaderRead (parser->xml) != 1) - goto error_out; - } while (xmlTextReaderNodeType (parser->xml) != XML_READER_TYPE_ELEMENT); - - /* check the name and format */ - tagname = (char *) xmlTextReaderName (parser->xml); - keep_going = tagname && !strcmp (tagname, "mateweather"); - xmlFree (tagname); - - if (!keep_going) - goto error_out; - - format = (char *) xmlTextReaderGetAttribute (parser->xml, (xmlChar *) "format"); - keep_going = format && !strcmp (format, "1.0"); - xmlFree (format); - - if (!keep_going) - goto error_out; - - /* Get timestamps for the start and end of this year */ - now = time (NULL); - tm = *gmtime (&now); - tm.tm_mon = 0; - tm.tm_mday = 1; - tm.tm_hour = tm.tm_min = tm.tm_sec = 0; - parser->year_start = mktime (&tm); - tm.tm_year++; - parser->year_end = mktime (&tm); - - return parser; + filename = + g_strdup_printf("%s/Locations.%s.xml.gz", MATEWEATHER_XML_LOCATION_DIR, + parser->locales[i]); + + if (g_file_test(filename, G_FILE_TEST_IS_REGULAR)) + break; + + g_free(filename); + filename = NULL; + } + + /* Fall back on the file containing either all translations, or only + * the english names (depending on the configure flags). + */ + if (!filename) + filename = + g_build_filename(MATEWEATHER_XML_LOCATION_DIR, "Locations.xml", NULL); + + if (!g_file_test(filename, G_FILE_TEST_IS_REGULAR) && zlib_support) { + g_free(filename); + filename = g_build_filename(MATEWEATHER_XML_LOCATION_DIR, + "Locations.xml.gz", NULL); + } + + /* Open the xml file containing the different locations */ + parser->xml = xmlNewTextReaderFilename(filename); + g_free(filename); + + if (parser->xml == NULL) + goto error_out; + + /* fast forward to the first element */ + do { + /* if we encounter a problem here, exit right away */ + if (xmlTextReaderRead(parser->xml) != 1) + goto error_out; + } while (xmlTextReaderNodeType(parser->xml) != XML_READER_TYPE_ELEMENT); + + /* check the name and format */ + tagname = (char *)xmlTextReaderName(parser->xml); + keep_going = tagname && !strcmp(tagname, "mateweather"); + xmlFree(tagname); + + if (!keep_going) + goto error_out; + + format = (char *)xmlTextReaderGetAttribute(parser->xml, (xmlChar *)"format"); + keep_going = format && !strcmp(format, "1.0"); + xmlFree(format); + + if (!keep_going) + goto error_out; + + /* Get timestamps for the start and end of this year */ + now = time(NULL); + tm = *gmtime(&now); + tm.tm_mon = 0; + tm.tm_mday = 1; + tm.tm_hour = tm.tm_min = tm.tm_sec = 0; + parser->year_start = mktime(&tm); + tm.tm_year++; + parser->year_end = mktime(&tm); + + return parser; error_out: - mateweather_parser_free (parser); - return NULL; + mateweather_parser_free(parser); + return NULL; } -void -mateweather_parser_free (MateWeatherParser *parser) -{ - if (parser->xml) - xmlFreeTextReader (parser->xml); - g_slice_free (MateWeatherParser, parser); +void mateweather_parser_free(MateWeatherParser *parser) { + if (parser->xml) + xmlFreeTextReader(parser->xml); + g_slice_free(MateWeatherParser, parser); } diff --git a/libmateweather/parser.h b/libmateweather/parser.h index 6547490..d3ecd06 100644 --- a/libmateweather/parser.h +++ b/libmateweather/parser.h @@ -21,23 +21,24 @@ #ifndef MATEWEATHER_PARSER_H #define MATEWEATHER_PARSER_H 1 -#include <libxml/xmlreader.h> #include "mateweather-timezone.h" +#include <libxml/xmlreader.h> typedef struct { - xmlTextReaderPtr xml; - const char * const *locales; - gboolean use_regions; - time_t year_start, year_end; + xmlTextReaderPtr xml; + const char *const *locales; + gboolean use_regions; + time_t year_start, year_end; } MateWeatherParser; -MateWeatherParser *mateweather_parser_new (gboolean use_regions); -void mateweather_parser_free (MateWeatherParser *parser); +MateWeatherParser *mateweather_parser_new(gboolean use_regions); +void mateweather_parser_free(MateWeatherParser *parser); -char *mateweather_parser_get_value (MateWeatherParser *parser); -char *mateweather_parser_get_localized_value (MateWeatherParser *parser); +char *mateweather_parser_get_value(MateWeatherParser *parser); +char *mateweather_parser_get_localized_value(MateWeatherParser *parser); /* from mateweather-timezone.c */ -MateWeatherTimezone **mateweather_timezones_parse_xml (MateWeatherParser *parser); +MateWeatherTimezone ** +mateweather_timezones_parse_xml(MateWeatherParser *parser); #endif diff --git a/libmateweather/test_locations.c b/libmateweather/test_locations.c index af1ad90..972df10 100644 --- a/libmateweather/test_locations.c +++ b/libmateweather/test_locations.c @@ -1,66 +1,61 @@ #define MATEWEATHER_I_KNOW_THIS_IS_UNSTABLE -#include <gtk/gtk.h> #include "location-entry.h" #include "timezone-menu.h" +#include <gtk/gtk.h> -static void -deleted (GtkWidget *widget, GdkEvent *event, gpointer data) -{ - gtk_main_quit (); +static void deleted(GtkWidget *widget, GdkEvent *event, gpointer data) { + gtk_main_quit(); } -static void -location_changed (GObject *object, GParamSpec *param, gpointer tzmenu) -{ - MateWeatherLocationEntry *entry = MATEWEATHER_LOCATION_ENTRY (object); - MateWeatherLocation *loc; - MateWeatherTimezone *zone; - - loc = mateweather_location_entry_get_location (entry); - g_return_if_fail (loc != NULL); - zone = mateweather_location_get_timezone (loc); - if (zone) - mateweather_timezone_menu_set_tzid (tzmenu, mateweather_timezone_get_tzid (zone)); - else - mateweather_timezone_menu_set_tzid (tzmenu, NULL); - if (zone) - mateweather_timezone_unref (zone); - mateweather_location_unref (loc); +static void location_changed(GObject *object, GParamSpec *param, + gpointer tzmenu) { + MateWeatherLocationEntry *entry = MATEWEATHER_LOCATION_ENTRY(object); + MateWeatherLocation *loc; + MateWeatherTimezone *zone; + + loc = mateweather_location_entry_get_location(entry); + g_return_if_fail(loc != NULL); + zone = mateweather_location_get_timezone(loc); + if (zone) + mateweather_timezone_menu_set_tzid(tzmenu, + mateweather_timezone_get_tzid(zone)); + else + mateweather_timezone_menu_set_tzid(tzmenu, NULL); + if (zone) + mateweather_timezone_unref(zone); + mateweather_location_unref(loc); } -int -main (int argc, char **argv) -{ - MateWeatherLocation *loc; - GtkWidget *window, *vbox, *entry; - GtkWidget *combo; - gtk_init (&argc, &argv); +int main(int argc, char **argv) { + MateWeatherLocation *loc; + GtkWidget *window, *vbox, *entry; + GtkWidget *combo; + gtk_init(&argc, &argv); - window = gtk_window_new (GTK_WINDOW_TOPLEVEL); - gtk_window_set_title (GTK_WINDOW (window), "location"); - gtk_container_set_border_width (GTK_CONTAINER (window), 8); - g_signal_connect (window, "delete-event", - G_CALLBACK (deleted), NULL); + window = gtk_window_new(GTK_WINDOW_TOPLEVEL); + gtk_window_set_title(GTK_WINDOW(window), "location"); + gtk_container_set_border_width(GTK_CONTAINER(window), 8); + g_signal_connect(window, "delete-event", G_CALLBACK(deleted), NULL); - vbox = gtk_box_new (GTK_ORIENTATION_VERTICAL, 8); - gtk_container_add (GTK_CONTAINER (window), vbox); + vbox = gtk_box_new(GTK_ORIENTATION_VERTICAL, 8); + gtk_container_add(GTK_CONTAINER(window), vbox); - loc = mateweather_location_new_world (FALSE); - entry = mateweather_location_entry_new (loc); - gtk_widget_set_size_request (entry, 400, -1); - gtk_box_pack_start (GTK_BOX (vbox), entry, FALSE, TRUE, 0); + loc = mateweather_location_new_world(FALSE); + entry = mateweather_location_entry_new(loc); + gtk_widget_set_size_request(entry, 400, -1); + gtk_box_pack_start(GTK_BOX(vbox), entry, FALSE, TRUE, 0); - combo = mateweather_timezone_menu_new (loc); - mateweather_location_unref (loc); - gtk_box_pack_start (GTK_BOX (vbox), combo, FALSE, TRUE, 0); + combo = mateweather_timezone_menu_new(loc); + mateweather_location_unref(loc); + gtk_box_pack_start(GTK_BOX(vbox), combo, FALSE, TRUE, 0); - g_signal_connect (entry, "notify::location", - G_CALLBACK (location_changed), combo); + g_signal_connect(entry, "notify::location", G_CALLBACK(location_changed), + combo); - gtk_widget_show_all (window); + gtk_widget_show_all(window); - gtk_main (); + gtk_main(); - return 0; + return 0; } diff --git a/libmateweather/test_metar.c b/libmateweather/test_metar.c index cbde991..4ba8bb7 100644 --- a/libmateweather/test_metar.c +++ b/libmateweather/test_metar.c @@ -4,8 +4,8 @@ */ #include <glib.h> -#include <string.h> #include <stdio.h> +#include <string.h> #define MATEWEATHER_I_KNOW_THIS_IS_UNSTABLE #include "weather-priv.h" @@ -13,62 +13,58 @@ #define BUFLEN 4096 #endif /* BUFLEN */ -int -main (int argc, char **argv) -{ - FILE* stream = stdin; - gchar* filename = NULL; - GOptionEntry entries[] = { - { "file", 'f', 0, G_OPTION_ARG_FILENAME, &filename, - "file constaining metar observations", NULL }, - { NULL, 0, 0, G_OPTION_ARG_NONE, NULL, NULL, NULL } - }; - GOptionContext* context; - GError* error = NULL; - char buf[BUFLEN]; - int len; - WeatherInfo info; +int main(int argc, char **argv) { + FILE *stream = stdin; + gchar *filename = NULL; + GOptionEntry entries[] = {{"file", 'f', 0, G_OPTION_ARG_FILENAME, &filename, + "file constaining metar observations", NULL}, + {NULL, 0, 0, G_OPTION_ARG_NONE, NULL, NULL, NULL}}; + GOptionContext *context; + GError *error = NULL; + char buf[BUFLEN]; + int len; + WeatherInfo info; - context = g_option_context_new ("- test libmateweather metar parser"); - g_option_context_add_main_entries (context, entries, NULL); - g_option_context_parse (context, &argc, &argv, &error); + context = g_option_context_new("- test libmateweather metar parser"); + g_option_context_add_main_entries(context, entries, NULL); + g_option_context_parse(context, &argc, &argv, &error); - if (error) { - perror (error->message); - return error->code; - } - if (filename) { - stream = fopen (filename, "r"); - if (!stream) { - perror ("fopen"); - return -1; - } - } else { - fprintf (stderr, "Enter a METAR string...\n"); + if (error) { + perror(error->message); + return error->code; + } + if (filename) { + stream = fopen(filename, "r"); + if (!stream) { + perror("fopen"); + return -1; } + } else { + fprintf(stderr, "Enter a METAR string...\n"); + } - while (fgets (buf, sizeof (buf), stream)) { - len = strlen (buf); - if (buf[len - 1] == '\n') { - buf[--len] = '\0'; - } - printf ("\n%s\n", buf); + while (fgets(buf, sizeof(buf), stream)) { + len = strlen(buf); + if (buf[len - 1] == '\n') { + buf[--len] = '\0'; + } + printf("\n%s\n", buf); - memset (&info, 0, sizeof (info)); - info.valid = 1; - metar_parse (buf, &info); - weather_info_to_metric (&info); - printf ("Returned info:\n"); - printf (" update: %s", ctime (&info.update)); - printf (" sky: %s\n", weather_info_get_sky (&info)); - printf (" cond: %s\n", weather_info_get_conditions (&info)); - printf (" temp: %s\n", weather_info_get_temp (&info)); - printf (" dewp: %s\n", weather_info_get_dew (&info)); - printf (" wind: %s\n", weather_info_get_wind (&info)); - printf (" pressure: %s\n", weather_info_get_pressure (&info)); - printf (" vis: %s\n", weather_info_get_visibility (&info)); + memset(&info, 0, sizeof(info)); + info.valid = 1; + metar_parse(buf, &info); + weather_info_to_metric(&info); + printf("Returned info:\n"); + printf(" update: %s", ctime(&info.update)); + printf(" sky: %s\n", weather_info_get_sky(&info)); + printf(" cond: %s\n", weather_info_get_conditions(&info)); + printf(" temp: %s\n", weather_info_get_temp(&info)); + printf(" dewp: %s\n", weather_info_get_dew(&info)); + printf(" wind: %s\n", weather_info_get_wind(&info)); + printf(" pressure: %s\n", weather_info_get_pressure(&info)); + printf(" vis: %s\n", weather_info_get_visibility(&info)); - // TODO: retrieve location's lat/lon to display sunrise/set times - } - return 0; + // TODO: retrieve location's lat/lon to display sunrise/set times + } + return 0; } diff --git a/libmateweather/test_sun_moon.c b/libmateweather/test_sun_moon.c index 9107b5f..5b9ad91 100644 --- a/libmateweather/test_sun_moon.c +++ b/libmateweather/test_sun_moon.c @@ -7,84 +7,79 @@ #define MATEWEATHER_I_KNOW_THIS_IS_UNSTABLE #include "weather-priv.h" -int -main (int argc, char **argv) -{ - WeatherInfo info; - GOptionContext* context; - GError* error = NULL; - gdouble latitude, longitude; - WeatherLocation location; - gchar* gtime = NULL; - GDate gdate; - struct tm tm; - gboolean bmoon; - time_t phases[4]; - const GOptionEntry entries[] = { - { "latitude", 0, 0, G_OPTION_ARG_DOUBLE, &latitude, - "observer's latitude in degrees north", NULL }, - { "longitude", 0, 0, G_OPTION_ARG_DOUBLE, &longitude, - "observer's longitude in degrees east", NULL }, - { "time", 0, 0, G_OPTION_ARG_STRING, >ime, - "time in seconds from Unix epoch", NULL }, - { NULL, 0, 0, G_OPTION_ARG_NONE, NULL, NULL, NULL } - }; +int main(int argc, char **argv) { + WeatherInfo info; + GOptionContext *context; + GError *error = NULL; + gdouble latitude, longitude; + WeatherLocation location; + gchar *gtime = NULL; + GDate gdate; + struct tm tm; + gboolean bmoon; + time_t phases[4]; + const GOptionEntry entries[] = { + {"latitude", 0, 0, G_OPTION_ARG_DOUBLE, &latitude, + "observer's latitude in degrees north", NULL}, + {"longitude", 0, 0, G_OPTION_ARG_DOUBLE, &longitude, + "observer's longitude in degrees east", NULL}, + {"time", 0, 0, G_OPTION_ARG_STRING, >ime, + "time in seconds from Unix epoch", NULL}, + {NULL, 0, 0, G_OPTION_ARG_NONE, NULL, NULL, NULL}}; - memset(&location, 0, sizeof(WeatherLocation)); - memset(&info, 0, sizeof(WeatherInfo)); + memset(&location, 0, sizeof(WeatherLocation)); + memset(&info, 0, sizeof(WeatherInfo)); - context = g_option_context_new ("- test libmateweather sun/moon calculations"); - g_option_context_add_main_entries (context, entries, NULL); - g_option_context_parse (context, &argc, &argv, &error); + context = g_option_context_new("- test libmateweather sun/moon calculations"); + g_option_context_add_main_entries(context, entries, NULL); + g_option_context_parse(context, &argc, &argv, &error); - if (error) { - perror (error->message); - return error->code; - } - else if (latitude < -90. || latitude > 90.) { - perror ("invalid latitude: should be [-90 .. 90]"); - return -1; - } else if (longitude < -180. || longitude > 180.) { - perror ("invalid longitude: should be [-180 .. 180]"); - return -1; - } + if (error) { + perror(error->message); + return error->code; + } else if (latitude < -90. || latitude > 90.) { + perror("invalid latitude: should be [-90 .. 90]"); + return -1; + } else if (longitude < -180. || longitude > 180.) { + perror("invalid longitude: should be [-180 .. 180]"); + return -1; + } - location.latitude = DEGREES_TO_RADIANS(latitude); - location.longitude = DEGREES_TO_RADIANS(longitude); - location.latlon_valid = TRUE; - info.location = &location; - info.valid = TRUE; + location.latitude = DEGREES_TO_RADIANS(latitude); + location.longitude = DEGREES_TO_RADIANS(longitude); + location.latlon_valid = TRUE; + info.location = &location; + info.valid = TRUE; - if (gtime != NULL) { - // printf(" gtime=%s\n", gtime); - g_date_set_parse(&gdate, gtime); - g_date_to_struct_tm(&gdate, &tm); - info.update = mktime(&tm); - } else { - info.update = time(NULL); - } + if (gtime != NULL) { + // printf(" gtime=%s\n", gtime); + g_date_set_parse(&gdate, gtime); + g_date_to_struct_tm(&gdate, &tm); + info.update = mktime(&tm); + } else { + info.update = time(NULL); + } - calc_sun_time(&info, info.update); - bmoon = calc_moon(&info); + calc_sun_time(&info, info.update); + bmoon = calc_moon(&info); - printf (" Latitude %7.3f %c Longitude %7.3f %c for %s All times UTC\n", - fabs(latitude), (latitude >= 0. ? 'N' : 'S'), - fabs(longitude), (longitude >= 0. ? 'E' : 'W'), - asctime(gmtime(&info.update))); - printf("sunrise: %s", - (info.sunriseValid ? ctime(&info.sunrise) : "(invalid)\n")); - printf("sunset: %s", - (info.sunsetValid ? ctime(&info.sunset) : "(invalid)\n")); - if (bmoon) { - printf("moonphase: %g\n", info.moonphase); - printf("moonlat: %g\n", info.moonlatitude); + printf(" Latitude %7.3f %c Longitude %7.3f %c for %s All times UTC\n", + fabs(latitude), (latitude >= 0. ? 'N' : 'S'), fabs(longitude), + (longitude >= 0. ? 'E' : 'W'), asctime(gmtime(&info.update))); + printf("sunrise: %s", + (info.sunriseValid ? ctime(&info.sunrise) : "(invalid)\n")); + printf("sunset: %s", + (info.sunsetValid ? ctime(&info.sunset) : "(invalid)\n")); + if (bmoon) { + printf("moonphase: %g\n", info.moonphase); + printf("moonlat: %g\n", info.moonlatitude); - if (calc_moon_phases(&info, phases)) { - printf(" New: %s", asctime(gmtime(&phases[0]))); - printf(" 1stQ: %s", asctime(gmtime(&phases[1]))); - printf(" Full: %s", asctime(gmtime(&phases[2]))); - printf(" 3rdQ: %s", asctime(gmtime(&phases[3]))); - } + if (calc_moon_phases(&info, phases)) { + printf(" New: %s", asctime(gmtime(&phases[0]))); + printf(" 1stQ: %s", asctime(gmtime(&phases[1]))); + printf(" Full: %s", asctime(gmtime(&phases[2]))); + printf(" 3rdQ: %s", asctime(gmtime(&phases[3]))); } - return 0; + } + return 0; } diff --git a/libmateweather/timezone-menu.c b/libmateweather/timezone-menu.c index 974afb2..bb4e59a 100644 --- a/libmateweather/timezone-menu.c +++ b/libmateweather/timezone-menu.c @@ -35,292 +35,259 @@ * A #GtkComboBox subclass for choosing a #MateWeatherTimezone */ -G_DEFINE_TYPE (MateWeatherTimezoneMenu, mateweather_timezone_menu, GTK_TYPE_COMBO_BOX) +G_DEFINE_TYPE(MateWeatherTimezoneMenu, mateweather_timezone_menu, + GTK_TYPE_COMBO_BOX) enum { - PROP_0, + PROP_0, - PROP_TOP, - PROP_TZID, + PROP_TOP, + PROP_TZID, - LAST_PROP + LAST_PROP }; -static void set_property (GObject *object, guint prop_id, - const GValue *value, GParamSpec *pspec); -static void get_property (GObject *object, guint prop_id, - GValue *value, GParamSpec *pspec); - -static void changed (GtkComboBox *combo); - -static GtkTreeModel *mateweather_timezone_model_new (MateWeatherLocation *top); -static gboolean row_separator_func (GtkTreeModel *model, GtkTreeIter *iter, - gpointer data); -static void is_sensitive (GtkCellLayout *cell_layout, GtkCellRenderer *cell, - GtkTreeModel *tree_model, GtkTreeIter *iter, gpointer data); - -static void -mateweather_timezone_menu_init (MateWeatherTimezoneMenu *menu) -{ - GtkCellRenderer *renderer; - - gtk_combo_box_set_row_separator_func (GTK_COMBO_BOX (menu), - row_separator_func, NULL, NULL); - - renderer = gtk_cell_renderer_text_new (); - gtk_cell_layout_pack_start (GTK_CELL_LAYOUT (menu), renderer, TRUE); - gtk_cell_layout_set_attributes (GTK_CELL_LAYOUT (menu), renderer, - "markup", 0, - NULL); - gtk_cell_layout_set_cell_data_func (GTK_CELL_LAYOUT (menu), - renderer, is_sensitive, NULL, NULL); +static void set_property(GObject *object, guint prop_id, const GValue *value, + GParamSpec *pspec); +static void get_property(GObject *object, guint prop_id, GValue *value, + GParamSpec *pspec); + +static void changed(GtkComboBox *combo); + +static GtkTreeModel *mateweather_timezone_model_new(MateWeatherLocation *top); +static gboolean row_separator_func(GtkTreeModel *model, GtkTreeIter *iter, + gpointer data); +static void is_sensitive(GtkCellLayout *cell_layout, GtkCellRenderer *cell, + GtkTreeModel *tree_model, GtkTreeIter *iter, + gpointer data); + +static void mateweather_timezone_menu_init(MateWeatherTimezoneMenu *menu) { + GtkCellRenderer *renderer; + + gtk_combo_box_set_row_separator_func(GTK_COMBO_BOX(menu), row_separator_func, + NULL, NULL); + + renderer = gtk_cell_renderer_text_new(); + gtk_cell_layout_pack_start(GTK_CELL_LAYOUT(menu), renderer, TRUE); + gtk_cell_layout_set_attributes(GTK_CELL_LAYOUT(menu), renderer, "markup", 0, + NULL); + gtk_cell_layout_set_cell_data_func(GTK_CELL_LAYOUT(menu), renderer, + is_sensitive, NULL, NULL); } -static void -finalize (GObject *object) -{ - MateWeatherTimezoneMenu *menu = MATEWEATHER_TIMEZONE_MENU (object); +static void finalize(GObject *object) { + MateWeatherTimezoneMenu *menu = MATEWEATHER_TIMEZONE_MENU(object); - if (menu->zone) - mateweather_timezone_unref (menu->zone); + if (menu->zone) + mateweather_timezone_unref(menu->zone); - G_OBJECT_CLASS (mateweather_timezone_menu_parent_class)->finalize (object); + G_OBJECT_CLASS(mateweather_timezone_menu_parent_class)->finalize(object); } -static void -mateweather_timezone_menu_class_init (MateWeatherTimezoneMenuClass *timezone_menu_class) -{ - GObjectClass *object_class = G_OBJECT_CLASS (timezone_menu_class); - GtkComboBoxClass *combo_class = GTK_COMBO_BOX_CLASS (timezone_menu_class); - - object_class->finalize = finalize; - object_class->set_property = set_property; - object_class->get_property = get_property; - - combo_class->changed = changed; - - /* properties */ - g_object_class_install_property ( - object_class, PROP_TOP, - g_param_spec_pointer ("top", - "Top Location", - "The MateWeatherLocation whose children will be used to fill in the menu", - G_PARAM_WRITABLE | G_PARAM_CONSTRUCT_ONLY)); - g_object_class_install_property ( - object_class, PROP_TZID, - g_param_spec_string ("tzid", - "TZID", - "The selected TZID", - NULL, - G_PARAM_READWRITE)); +static void mateweather_timezone_menu_class_init( + MateWeatherTimezoneMenuClass *timezone_menu_class) { + GObjectClass *object_class = G_OBJECT_CLASS(timezone_menu_class); + GtkComboBoxClass *combo_class = GTK_COMBO_BOX_CLASS(timezone_menu_class); + + object_class->finalize = finalize; + object_class->set_property = set_property; + object_class->get_property = get_property; + + combo_class->changed = changed; + + /* properties */ + g_object_class_install_property( + object_class, PROP_TOP, + g_param_spec_pointer("top", "Top Location", + "The MateWeatherLocation whose children will be " + "used to fill in the menu", + G_PARAM_WRITABLE | G_PARAM_CONSTRUCT_ONLY)); + g_object_class_install_property(object_class, PROP_TZID, + g_param_spec_string("tzid", "TZID", + "The selected TZID", NULL, + G_PARAM_READWRITE)); } -static void -set_property (GObject *object, guint prop_id, - const GValue *value, GParamSpec *pspec) -{ - GtkTreeModel *model; - - switch (prop_id) { - case PROP_TOP: - model = mateweather_timezone_model_new (g_value_get_pointer (value)); - gtk_combo_box_set_model (GTK_COMBO_BOX (object), model); - g_object_unref (model); - gtk_combo_box_set_active (GTK_COMBO_BOX (object), 0); - break; - - case PROP_TZID: - mateweather_timezone_menu_set_tzid (MATEWEATHER_TIMEZONE_MENU (object), - g_value_get_string (value)); - break; - default: - G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); - break; - } +static void set_property(GObject *object, guint prop_id, const GValue *value, + GParamSpec *pspec) { + GtkTreeModel *model; + + switch (prop_id) { + case PROP_TOP: + model = mateweather_timezone_model_new(g_value_get_pointer(value)); + gtk_combo_box_set_model(GTK_COMBO_BOX(object), model); + g_object_unref(model); + gtk_combo_box_set_active(GTK_COMBO_BOX(object), 0); + break; + + case PROP_TZID: + mateweather_timezone_menu_set_tzid(MATEWEATHER_TIMEZONE_MENU(object), + g_value_get_string(value)); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec); + break; + } } -static void -get_property (GObject *object, guint prop_id, - GValue *value, GParamSpec *pspec) -{ - MateWeatherTimezoneMenu *menu = MATEWEATHER_TIMEZONE_MENU (object); - - switch (prop_id) { - case PROP_TZID: - g_value_set_string (value, mateweather_timezone_menu_get_tzid (menu)); - break; - default: - G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); - break; - } +static void get_property(GObject *object, guint prop_id, GValue *value, + GParamSpec *pspec) { + MateWeatherTimezoneMenu *menu = MATEWEATHER_TIMEZONE_MENU(object); + + switch (prop_id) { + case PROP_TZID: + g_value_set_string(value, mateweather_timezone_menu_get_tzid(menu)); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec); + break; + } } -enum { - MATEWEATHER_TIMEZONE_MENU_NAME, - MATEWEATHER_TIMEZONE_MENU_ZONE -}; +enum { MATEWEATHER_TIMEZONE_MENU_NAME, MATEWEATHER_TIMEZONE_MENU_ZONE }; -static void -changed (GtkComboBox *combo) -{ - MateWeatherTimezoneMenu *menu = MATEWEATHER_TIMEZONE_MENU (combo); - GtkTreeIter iter; +static void changed(GtkComboBox *combo) { + MateWeatherTimezoneMenu *menu = MATEWEATHER_TIMEZONE_MENU(combo); + GtkTreeIter iter; - if (menu->zone) - mateweather_timezone_unref (menu->zone); + if (menu->zone) + mateweather_timezone_unref(menu->zone); - gtk_combo_box_get_active_iter (combo, &iter); - gtk_tree_model_get (gtk_combo_box_get_model (combo), &iter, - MATEWEATHER_TIMEZONE_MENU_ZONE, &menu->zone, - -1); + gtk_combo_box_get_active_iter(combo, &iter); + gtk_tree_model_get(gtk_combo_box_get_model(combo), &iter, + MATEWEATHER_TIMEZONE_MENU_ZONE, &menu->zone, -1); - if (menu->zone) - mateweather_timezone_ref (menu->zone); + if (menu->zone) + mateweather_timezone_ref(menu->zone); - g_object_notify (G_OBJECT (combo), "tzid"); + g_object_notify(G_OBJECT(combo), "tzid"); } -static void -append_offset (GString *desc, int offset) -{ - int hours, minutes; +static void append_offset(GString *desc, int offset) { + int hours, minutes; - hours = offset / 60; - minutes = (offset > 0) ? offset % 60 : -offset % 60; + hours = offset / 60; + minutes = (offset > 0) ? offset % 60 : -offset % 60; - if (minutes) - g_string_append_printf (desc, "GMT%+d:%02d", hours, minutes); - else if (hours) - g_string_append_printf (desc, "GMT%+d", hours); - else - g_string_append (desc, "GMT"); + if (minutes) + g_string_append_printf(desc, "GMT%+d:%02d", hours, minutes); + else if (hours) + g_string_append_printf(desc, "GMT%+d", hours); + else + g_string_append(desc, "GMT"); } -static char * -get_offset (MateWeatherTimezone *zone) -{ - GString *desc; +static char *get_offset(MateWeatherTimezone *zone) { + GString *desc; - desc = g_string_new (NULL); - append_offset (desc, mateweather_timezone_get_offset (zone)); - if (mateweather_timezone_has_dst (zone)) { - g_string_append (desc, " / "); - append_offset (desc, mateweather_timezone_get_dst_offset (zone)); - } - return g_string_free (desc, FALSE); + desc = g_string_new(NULL); + append_offset(desc, mateweather_timezone_get_offset(zone)); + if (mateweather_timezone_has_dst(zone)) { + g_string_append(desc, " / "); + append_offset(desc, mateweather_timezone_get_dst_offset(zone)); + } + return g_string_free(desc, FALSE); } -static void -insert_location (GtkTreeStore *store, MateWeatherTimezone *zone, const char *loc_name, GtkTreeIter *parent) -{ - GtkTreeIter iter; - char *name, *offset; - - offset = get_offset (zone); - name = g_strdup_printf ("%s <small>(%s)</small>", - loc_name ? loc_name : mateweather_timezone_get_name (zone), - offset); - gtk_tree_store_append (store, &iter, parent); - gtk_tree_store_set (store, &iter, - MATEWEATHER_TIMEZONE_MENU_NAME, name, - MATEWEATHER_TIMEZONE_MENU_ZONE, mateweather_timezone_ref (zone), - -1); - g_free (name); - g_free (offset); +static void insert_location(GtkTreeStore *store, MateWeatherTimezone *zone, + const char *loc_name, GtkTreeIter *parent) { + GtkTreeIter iter; + char *name, *offset; + + offset = get_offset(zone); + name = g_strdup_printf( + "%s <small>(%s)</small>", + loc_name ? loc_name : mateweather_timezone_get_name(zone), offset); + gtk_tree_store_append(store, &iter, parent); + gtk_tree_store_set(store, &iter, MATEWEATHER_TIMEZONE_MENU_NAME, name, + MATEWEATHER_TIMEZONE_MENU_ZONE, + mateweather_timezone_ref(zone), -1); + g_free(name); + g_free(offset); } -static void -insert_locations (GtkTreeStore *store, MateWeatherLocation *loc) -{ - int i; - - if (mateweather_location_get_level (loc) < MATEWEATHER_LOCATION_COUNTRY) { - MateWeatherLocation **children; - - children = mateweather_location_get_children (loc); - for (i = 0; children[i]; i++) - insert_locations (store, children[i]); - mateweather_location_free_children (loc, children); - } else { - MateWeatherTimezone **zones; - GtkTreeIter iter; - - zones = mateweather_location_get_timezones (loc); - if (zones[1]) { - gtk_tree_store_append (store, &iter, NULL); - gtk_tree_store_set (store, &iter, - MATEWEATHER_TIMEZONE_MENU_NAME, mateweather_location_get_name (loc), - -1); - - for (i = 0; zones[i]; i++) { - insert_location (store, zones[i], NULL, &iter); - } - } else if (zones[0]) { - insert_location (store, zones[0], mateweather_location_get_name (loc), NULL); - } - - mateweather_location_free_timezones (loc, zones); +static void insert_locations(GtkTreeStore *store, MateWeatherLocation *loc) { + int i; + + if (mateweather_location_get_level(loc) < MATEWEATHER_LOCATION_COUNTRY) { + MateWeatherLocation **children; + + children = mateweather_location_get_children(loc); + for (i = 0; children[i]; i++) + insert_locations(store, children[i]); + mateweather_location_free_children(loc, children); + } else { + MateWeatherTimezone **zones; + GtkTreeIter iter; + + zones = mateweather_location_get_timezones(loc); + if (zones[1]) { + gtk_tree_store_append(store, &iter, NULL); + gtk_tree_store_set(store, &iter, MATEWEATHER_TIMEZONE_MENU_NAME, + mateweather_location_get_name(loc), -1); + + for (i = 0; zones[i]; i++) { + insert_location(store, zones[i], NULL, &iter); + } + } else if (zones[0]) { + insert_location(store, zones[0], mateweather_location_get_name(loc), + NULL); } + + mateweather_location_free_timezones(loc, zones); + } } -static GtkTreeModel * -mateweather_timezone_model_new (MateWeatherLocation *top) -{ - GtkTreeStore *store; - GtkTreeModel *model; - GtkTreeIter iter; - char *unknown; - MateWeatherTimezone *utc; +static GtkTreeModel *mateweather_timezone_model_new(MateWeatherLocation *top) { + GtkTreeStore *store; + GtkTreeModel *model; + GtkTreeIter iter; + char *unknown; + MateWeatherTimezone *utc; - store = gtk_tree_store_new (2, G_TYPE_STRING, G_TYPE_POINTER); - model = GTK_TREE_MODEL (store); + store = gtk_tree_store_new(2, G_TYPE_STRING, G_TYPE_POINTER); + model = GTK_TREE_MODEL(store); - unknown = g_markup_printf_escaped ("<i>%s</i>", C_("timezone", "Unknown")); + unknown = g_markup_printf_escaped("<i>%s</i>", C_("timezone", "Unknown")); - gtk_tree_store_append (store, &iter, NULL); - gtk_tree_store_set (store, &iter, - MATEWEATHER_TIMEZONE_MENU_NAME, unknown, - MATEWEATHER_TIMEZONE_MENU_ZONE, NULL, - -1); + gtk_tree_store_append(store, &iter, NULL); + gtk_tree_store_set(store, &iter, MATEWEATHER_TIMEZONE_MENU_NAME, unknown, + MATEWEATHER_TIMEZONE_MENU_ZONE, NULL, -1); - utc = mateweather_timezone_get_utc (); - if (utc) { - insert_location (store, utc, NULL, NULL); - mateweather_timezone_unref (utc); - } + utc = mateweather_timezone_get_utc(); + if (utc) { + insert_location(store, utc, NULL, NULL); + mateweather_timezone_unref(utc); + } - gtk_tree_store_append (store, &iter, NULL); + gtk_tree_store_append(store, &iter, NULL); - g_free (unknown); + g_free(unknown); - insert_locations (store, top); + insert_locations(store, top); - return model; + return model; } -static gboolean -row_separator_func (GtkTreeModel *model, GtkTreeIter *iter, gpointer data) -{ - char *name; - - gtk_tree_model_get (model, iter, - MATEWEATHER_TIMEZONE_MENU_NAME, &name, - -1); - if (name) { - g_free (name); - return FALSE; - } else - return TRUE; +static gboolean row_separator_func(GtkTreeModel *model, GtkTreeIter *iter, + gpointer data) { + char *name; + + gtk_tree_model_get(model, iter, MATEWEATHER_TIMEZONE_MENU_NAME, &name, -1); + if (name) { + g_free(name); + return FALSE; + } else + return TRUE; } -static void -is_sensitive (GtkCellLayout *cell_layout, GtkCellRenderer *cell, - GtkTreeModel *tree_model, GtkTreeIter *iter, gpointer data) -{ - gboolean sensitive; +static void is_sensitive(GtkCellLayout *cell_layout, GtkCellRenderer *cell, + GtkTreeModel *tree_model, GtkTreeIter *iter, + gpointer data) { + gboolean sensitive; - sensitive = !gtk_tree_model_iter_has_child (tree_model, iter); - g_object_set (cell, "sensitive", sensitive, NULL); + sensitive = !gtk_tree_model_iter_has_child(tree_model, iter); + g_object_set(cell, "sensitive", sensitive, NULL); } /** @@ -335,37 +302,29 @@ is_sensitive (GtkCellLayout *cell_layout, GtkCellRenderer *cell, * * Return value: the new #MateWeatherTimezoneMenu **/ -GtkWidget * -mateweather_timezone_menu_new (MateWeatherLocation *top) -{ - return g_object_new (MATEWEATHER_TYPE_TIMEZONE_MENU, - "top", top, - NULL); +GtkWidget *mateweather_timezone_menu_new(MateWeatherLocation *top) { + return g_object_new(MATEWEATHER_TYPE_TIMEZONE_MENU, "top", top, NULL); } typedef struct { - GtkComboBox *combo; - const char *tzid; + GtkComboBox *combo; + const char *tzid; } SetTimezoneData; -static gboolean -check_tzid (GtkTreeModel *model, GtkTreePath *path, - GtkTreeIter *iter, gpointer data) -{ - SetTimezoneData *tzd = data; - MateWeatherTimezone *zone; - - gtk_tree_model_get (model, iter, - MATEWEATHER_TIMEZONE_MENU_ZONE, &zone, - -1); - if (!zone) - return FALSE; - - if (!strcmp (mateweather_timezone_get_tzid (zone), tzd->tzid)) { - gtk_combo_box_set_active_iter (tzd->combo, iter); - return TRUE; - } else - return FALSE; +static gboolean check_tzid(GtkTreeModel *model, GtkTreePath *path, + GtkTreeIter *iter, gpointer data) { + SetTimezoneData *tzd = data; + MateWeatherTimezone *zone; + + gtk_tree_model_get(model, iter, MATEWEATHER_TIMEZONE_MENU_ZONE, &zone, -1); + if (!zone) + return FALSE; + + if (!strcmp(mateweather_timezone_get_tzid(zone), tzd->tzid)) { + gtk_combo_box_set_active_iter(tzd->combo, iter); + return TRUE; + } else + return FALSE; } /** @@ -376,23 +335,20 @@ check_tzid (GtkTreeModel *model, GtkTreePath *path, * Sets @menu to the given @tzid. If @tzid is %NULL, sets @menu to * "Unknown". **/ -void -mateweather_timezone_menu_set_tzid (MateWeatherTimezoneMenu *menu, - const char *tzid) -{ - SetTimezoneData tzd; +void mateweather_timezone_menu_set_tzid(MateWeatherTimezoneMenu *menu, + const char *tzid) { + SetTimezoneData tzd; - g_return_if_fail (MATEWEATHER_IS_TIMEZONE_MENU (menu)); + g_return_if_fail(MATEWEATHER_IS_TIMEZONE_MENU(menu)); - if (!tzid) { - gtk_combo_box_set_active (GTK_COMBO_BOX (menu), 0); - return; - } + if (!tzid) { + gtk_combo_box_set_active(GTK_COMBO_BOX(menu), 0); + return; + } - tzd.combo = GTK_COMBO_BOX (menu); - tzd.tzid = tzid; - gtk_tree_model_foreach (gtk_combo_box_get_model (tzd.combo), - check_tzid, &tzd); + tzd.combo = GTK_COMBO_BOX(menu); + tzd.tzid = tzid; + gtk_tree_model_foreach(gtk_combo_box_get_model(tzd.combo), check_tzid, &tzd); } /** @@ -404,13 +360,10 @@ mateweather_timezone_menu_set_tzid (MateWeatherTimezoneMenu *menu, * Return value: (allow-none): @menu's tzid, or %NULL if no timezone * is selected. **/ -const char * -mateweather_timezone_menu_get_tzid (MateWeatherTimezoneMenu *menu) -{ - g_return_val_if_fail (MATEWEATHER_IS_TIMEZONE_MENU (menu), NULL); - - if (!menu->zone) - return NULL; - return mateweather_timezone_get_tzid (menu->zone); -} +const char *mateweather_timezone_menu_get_tzid(MateWeatherTimezoneMenu *menu) { + g_return_val_if_fail(MATEWEATHER_IS_TIMEZONE_MENU(menu), NULL); + if (!menu->zone) + return NULL; + return mateweather_timezone_get_tzid(menu->zone); +} diff --git a/libmateweather/timezone-menu.h b/libmateweather/timezone-menu.h index 00d4b4b..d664d00 100644 --- a/libmateweather/timezone-menu.h +++ b/libmateweather/timezone-menu.h @@ -24,31 +24,39 @@ #include <gtk/gtk.h> #include <libmateweather/mateweather-location.h> -#define MATEWEATHER_TYPE_TIMEZONE_MENU (mateweather_timezone_menu_get_type ()) -#define MATEWEATHER_TIMEZONE_MENU(object) (G_TYPE_CHECK_INSTANCE_CAST ((object), MATEWEATHER_TYPE_TIMEZONE_MENU, MateWeatherTimezoneMenu)) -#define MATEWEATHER_TIMEZONE_MENU_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), MATEWEATHER_TYPE_TIMEZONE_MENU, MateWeatherTimezoneMenuClass)) -#define MATEWEATHER_IS_TIMEZONE_MENU(object) (G_TYPE_CHECK_INSTANCE_TYPE ((object), MATEWEATHER_TYPE_TIMEZONE_MENU)) -#define MATEWEATHER_IS_TIMEZONE_MENU_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), MATEWEATHER_TYPE_TIMEZONE_MENU)) -#define MATEWEATHER_TIMEZONE_MENU_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), MATEWEATHER_TYPE_TIMEZONE_MENU, MateWeatherTimezoneMenuClass)) +#define MATEWEATHER_TYPE_TIMEZONE_MENU (mateweather_timezone_menu_get_type()) +#define MATEWEATHER_TIMEZONE_MENU(object) \ + (G_TYPE_CHECK_INSTANCE_CAST((object), MATEWEATHER_TYPE_TIMEZONE_MENU, \ + MateWeatherTimezoneMenu)) +#define MATEWEATHER_TIMEZONE_MENU_CLASS(klass) \ + (G_TYPE_CHECK_CLASS_CAST((klass), MATEWEATHER_TYPE_TIMEZONE_MENU, \ + MateWeatherTimezoneMenuClass)) +#define MATEWEATHER_IS_TIMEZONE_MENU(object) \ + (G_TYPE_CHECK_INSTANCE_TYPE((object), MATEWEATHER_TYPE_TIMEZONE_MENU)) +#define MATEWEATHER_IS_TIMEZONE_MENU_CLASS(klass) \ + (G_TYPE_CHECK_CLASS_TYPE((klass), MATEWEATHER_TYPE_TIMEZONE_MENU)) +#define MATEWEATHER_TIMEZONE_MENU_GET_CLASS(obj) \ + (G_TYPE_INSTANCE_GET_CLASS((obj), MATEWEATHER_TYPE_TIMEZONE_MENU, \ + MateWeatherTimezoneMenuClass)) typedef struct { - GtkComboBox parent; + GtkComboBox parent; - /*< private >*/ - MateWeatherTimezone *zone; + /*< private >*/ + MateWeatherTimezone *zone; } MateWeatherTimezoneMenu; typedef struct { - GtkComboBoxClass parent_class; + GtkComboBoxClass parent_class; } MateWeatherTimezoneMenuClass; -GType mateweather_timezone_menu_get_type (void); +GType mateweather_timezone_menu_get_type(void); -GtkWidget *mateweather_timezone_menu_new (MateWeatherLocation *top); +GtkWidget *mateweather_timezone_menu_new(MateWeatherLocation *top); -void mateweather_timezone_menu_set_tzid (MateWeatherTimezoneMenu *menu, - const char *tzid); -const char *mateweather_timezone_menu_get_tzid (MateWeatherTimezoneMenu *menu); +void mateweather_timezone_menu_set_tzid(MateWeatherTimezoneMenu *menu, + const char *tzid); +const char *mateweather_timezone_menu_get_tzid(MateWeatherTimezoneMenu *menu); #endif diff --git a/libmateweather/weather-bom.c b/libmateweather/weather-bom.c index f5c7a87..bce49e9 100644 --- a/libmateweather/weather-bom.c +++ b/libmateweather/weather-bom.c @@ -23,67 +23,62 @@ #include <string.h> #define MATEWEATHER_I_KNOW_THIS_IS_UNSTABLE -#include "weather.h" #include "weather-priv.h" +#include "weather.h" -static void -bom_finish (GObject *source, GAsyncResult *result, gpointer data) -{ - char *p, *rp; - WeatherInfo *info = (WeatherInfo *)data; - GError *error = NULL; - GBytes *bytes; - const char *response_body = NULL; - gsize len = 0; - - g_return_if_fail (info != NULL); - - bytes = soup_session_send_and_read_finish (SOUP_SESSION(source), - result, &error); - - if (error != NULL) { - g_warning ("Failed to get BOM forecast data: %s.\n", error->message); - request_done (info, error); - g_error_free (error); - return; - } - - response_body = g_bytes_get_data (bytes, &len); - - p = xstrnstr (response_body, len, "Forecast for the rest"); - if (p != NULL) { - rp = xstrnstr (p, len - (p - response_body), - "The next routine forecast will be issued"); - if (rp == NULL) - info->forecast = g_strndup (p, len - (p - response_body)); - else - info->forecast = g_strndup (p, rp - p); - } - - if (info->forecast == NULL) - info->forecast = g_strndup (response_body, len); - - g_bytes_unref (bytes); - g_print ("%s\n", info->forecast); - request_done (info, NULL); +static void bom_finish(GObject *source, GAsyncResult *result, gpointer data) { + char *p, *rp; + WeatherInfo *info = (WeatherInfo *)data; + GError *error = NULL; + GBytes *bytes; + const char *response_body = NULL; + gsize len = 0; + + g_return_if_fail(info != NULL); + + bytes = + soup_session_send_and_read_finish(SOUP_SESSION(source), result, &error); + + if (error != NULL) { + g_warning("Failed to get BOM forecast data: %s.\n", error->message); + request_done(info, error); + g_error_free(error); + return; + } + + response_body = g_bytes_get_data(bytes, &len); + + p = xstrnstr(response_body, len, "Forecast for the rest"); + if (p != NULL) { + rp = xstrnstr(p, len - (p - response_body), + "The next routine forecast will be issued"); + if (rp == NULL) + info->forecast = g_strndup(p, len - (p - response_body)); + else + info->forecast = g_strndup(p, rp - p); + } + + if (info->forecast == NULL) + info->forecast = g_strndup(response_body, len); + + g_bytes_unref(bytes); + g_print("%s\n", info->forecast); + request_done(info, NULL); } -void -bom_start_open (WeatherInfo *info) -{ - gchar *url; - SoupMessage *msg; - WeatherLocation *loc; +void bom_start_open(WeatherInfo *info) { + gchar *url; + SoupMessage *msg; + WeatherLocation *loc; - loc = info->location; + loc = info->location; - url = g_strdup_printf ("http://www.bom.gov.au/fwo/%s.txt", - loc->zone + 1); + url = g_strdup_printf("http://www.bom.gov.au/fwo/%s.txt", loc->zone + 1); - msg = soup_message_new ("GET", url); - soup_session_send_and_read_async (info->session, msg, G_PRIORITY_DEFAULT, - NULL, bom_finish, info); - g_free (url); + msg = soup_message_new("GET", url); + soup_session_send_and_read_async(info->session, msg, G_PRIORITY_DEFAULT, NULL, + bom_finish, info); + g_free(url); - info->requests_pending++; + info->requests_pending++; } diff --git a/libmateweather/weather-iwin.c b/libmateweather/weather-iwin.c index b1dc1ff..4a95481 100644 --- a/libmateweather/weather-iwin.c +++ b/libmateweather/weather-iwin.c @@ -27,463 +27,468 @@ #include <libxml/parser.h> #define MATEWEATHER_I_KNOW_THIS_IS_UNSTABLE -#include "weather.h" #include "weather-priv.h" +#include "weather.h" /** - * Humans don't deal well with .MONDAY...SUNNY AND BLAH BLAH.TUESDAY...THEN THIS AND THAT.WEDNESDAY...RAINY BLAH BLAH. - * This function makes it easier to read. + * Humans don't deal well with .MONDAY...SUNNY AND BLAH BLAH.TUESDAY...THEN + * THIS AND THAT.WEDNESDAY...RAINY BLAH BLAH. This function makes it easier to + * read. */ -static gchar * -formatWeatherMsg (gchar *forecast) -{ - gchar *ptr = forecast; - gchar *startLine = NULL; - - while (0 != *ptr) { - if (ptr[0] == '\n' && ptr[1] == '.') { - /* This removes the preamble by shifting the relevant data - * down to the start of the buffer. */ - if (NULL == startLine) { - memmove (forecast, ptr, strlen (ptr) + 1); - ptr = forecast; - ptr[0] = ' '; - } - ptr[1] = '\n'; - ptr += 2; - startLine = ptr; - } else if (ptr[0] == '.' && ptr[1] == '.' && ptr[2] == '.' && NULL != startLine) { - memmove (startLine + 2, startLine, (ptr - startLine) * sizeof (gchar)); - startLine[0] = ' '; - startLine[1] = '\n'; - ptr[2] = '\n'; - - ptr += 3; - - } else if (ptr[0] == '$' && ptr[1] == '$') { - ptr[0] = ptr[1] = ' '; - - } else { - ptr++; - } +static gchar *formatWeatherMsg(gchar *forecast) { + gchar *ptr = forecast; + gchar *startLine = NULL; + + while (0 != *ptr) { + if (ptr[0] == '\n' && ptr[1] == '.') { + /* This removes the preamble by shifting the relevant data + * down to the start of the buffer. */ + if (NULL == startLine) { + memmove(forecast, ptr, strlen(ptr) + 1); + ptr = forecast; + ptr[0] = ' '; + } + ptr[1] = '\n'; + ptr += 2; + startLine = ptr; + } else if (ptr[0] == '.' && ptr[1] == '.' && ptr[2] == '.' && + NULL != startLine) { + memmove(startLine + 2, startLine, (ptr - startLine) * sizeof(gchar)); + startLine[0] = ' '; + startLine[1] = '\n'; + ptr[2] = '\n'; + + ptr += 3; + + } else if (ptr[0] == '$' && ptr[1] == '$') { + ptr[0] = ptr[1] = ' '; + + } else { + ptr++; } + } - return forecast; + return forecast; } -static gboolean -hasAttr (xmlNode *node, const char *attr_name, const char *attr_value) -{ - xmlChar *attr; - gboolean res = FALSE; +static gboolean hasAttr(xmlNode *node, const char *attr_name, + const char *attr_value) { + xmlChar *attr; + gboolean res = FALSE; - if (!node) - return res; + if (!node) + return res; - attr = xmlGetProp (node, (const xmlChar *) attr_name); + attr = xmlGetProp(node, (const xmlChar *)attr_name); - if (!attr) - return res; + if (!attr) + return res; - res = g_str_equal ((const char *)attr, attr_value); + res = g_str_equal((const char *)attr, attr_value); - xmlFree (attr); + xmlFree(attr); - return res; + return res; } -static GSList * -parseForecastXml (const char *buff, gsize len, WeatherInfo *master_info) -{ - GSList *res = NULL; - xmlDocPtr doc; - xmlNode *root, *node; - - g_return_val_if_fail (master_info != NULL, NULL); - - if (!buff || !*buff) - return NULL; - - #define XC (const xmlChar *) - #define isElem(_node,_name) g_str_equal ((const char *)_node->name, _name) - - doc = xmlParseMemory (buff, len); - if (!doc) - return NULL; - - /* Description at http://www.weather.gov/mdl/XML/Design/MDL_XML_Design.pdf */ - root = xmlDocGetRootElement (doc); - for (node = root->xmlChildrenNode; node; node = node->next) { - if (node->name == NULL || node->type != XML_ELEMENT_NODE) - continue; - - if (isElem (node, "data")) { - xmlNode *n; - char *time_layout = NULL; - time_t update_times[7] = {0}; - - for (n = node->children; n; n = n->next) { - if (!n->name) - continue; - - if (isElem (n, "time-layout")) { - if (!time_layout && hasAttr (n, "summarization", "24hourly")) { - xmlNode *c; - int count = 0; - - for (c = n->children; c && (count < 7 || !time_layout); c = c->next) { - if (c->name && !time_layout && isElem (c, "layout-key")) { - xmlChar *val = xmlNodeGetContent (c); - - if (val) { - time_layout = g_strdup ((const char *)val); - xmlFree (val); - } - } else if (c->name && isElem (c, "start-valid-time")) { - xmlChar *val = xmlNodeGetContent (c); - - if (val) { - GDateTime *dt = g_date_time_new_from_iso8601 ((const char *)val, NULL); - if (dt != NULL) { - update_times[count] = g_date_time_to_unix (dt); - g_date_time_unref (dt); - } else { - update_times[count] = 0; - } - - count++; - - xmlFree (val); - } - } - } - - if (count != 7) { - /* There can be more than one time-layout element, the other - with only few children, which is not the one to use. */ - g_free (time_layout); - time_layout = NULL; - } - } - } else if (isElem (n, "parameters")) { - xmlNode *p; +static GSList *parseForecastXml(const char *buff, gsize len, + WeatherInfo *master_info) { + GSList *res = NULL; + xmlDocPtr doc; + xmlNode *root, *node; - /* time-layout should be always before parameters */ - if (!time_layout) - break; + g_return_val_if_fail(master_info != NULL, NULL); - if (!res) { - int i; - - for (i = 0; i < 7; i++) { - WeatherInfo *nfo = weather_info_clone (master_info); - - if (nfo) { - nfo->valid = FALSE; - nfo->forecast_type = FORECAST_ZONE; - nfo->update = update_times [i]; - nfo->sky = -1; - nfo->temperature_unit = TEMP_UNIT_FAHRENHEIT; - nfo->temp = -1000.0; - nfo->temp_min = -1000.0; - nfo->temp_max = -1000.0; - nfo->tempMinMaxValid = FALSE; - nfo->cond.significant = FALSE; - nfo->cond.phenomenon = PHENOMENON_NONE; - nfo->cond.qualifier = QUALIFIER_NONE; - nfo->dew = -1000.0; - nfo->wind = -1; - nfo->windspeed = -1; - nfo->pressure = -1.0; - nfo->visibility = -1.0; - nfo->sunriseValid = FALSE; - nfo->sunsetValid = FALSE; - nfo->sunrise = 0; - nfo->sunset = 0; - g_free (nfo->forecast); - nfo->forecast = NULL; - nfo->session = NULL; - nfo->requests_pending = 0; - nfo->finish_cb = NULL; - nfo->cb_data = NULL; - res = g_slist_append (res, nfo); - } - } - } + if (!buff || !*buff) + return NULL; - for (p = n->children; p; p = p->next) { - if (p->name && isElem (p, "temperature") && hasAttr (p, "time-layout", time_layout)) { - xmlNode *c; - GSList *at = res; - gboolean is_max = hasAttr (p, "type", "maximum"); - - if (!is_max && !hasAttr (p, "type", "minimum")) - break; - - for (c = p->children; c && at; c = c->next) { - if (isElem (c, "value")) { - WeatherInfo *nfo = (WeatherInfo *)at->data; - xmlChar *val = xmlNodeGetContent (c); - - /* can pass some values as <value xsi:nil="true"/> */ - if (!val || !*val) { - if (is_max) - nfo->temp_max = nfo->temp_min; - else - nfo->temp_min = nfo->temp_max; - } else { - if (is_max) - nfo->temp_max = atof ((const char *)val); - else - nfo->temp_min = atof ((const char *)val); - } - - if (val) - xmlFree (val); - - nfo->tempMinMaxValid = nfo->tempMinMaxValid || (nfo->temp_max > -999.0 && nfo->temp_min > -999.0); - nfo->valid = nfo->tempMinMaxValid; - - at = at->next; - } - } - } else if (p->name && isElem (p, "weather") && hasAttr (p, "time-layout", time_layout)) { - xmlNode *c; - GSList *at = res; - - for (c = p->children; c && at; c = c->next) { - if (c->name && isElem (c, "weather-conditions")) { - WeatherInfo *nfo = at->data; - xmlChar *val = xmlGetProp (c, XC "weather-summary"); - - if (val && nfo) { - /* Checking from top to bottom, if 'value' contains 'name', then that win, - thus put longer (more precise) values to the top. */ - int i; - struct _ph_list { - const char *name; - WeatherConditionPhenomenon ph; - } ph_list[] = { - { "Ice Crystals", PHENOMENON_ICE_CRYSTALS } , - { "Volcanic Ash", PHENOMENON_VOLCANIC_ASH } , - { "Blowing Sand", PHENOMENON_SANDSTORM } , - { "Blowing Dust", PHENOMENON_DUSTSTORM } , - { "Blowing Snow", PHENOMENON_FUNNEL_CLOUD } , - { "Drizzle", PHENOMENON_DRIZZLE } , - { "Rain", PHENOMENON_RAIN } , - { "Snow", PHENOMENON_SNOW } , - { "Fog", PHENOMENON_FOG } , - { "Smoke", PHENOMENON_SMOKE } , - { "Sand", PHENOMENON_SAND } , - { "Haze", PHENOMENON_HAZE } , - { "Dust", PHENOMENON_DUST } /*, - { "", PHENOMENON_SNOW_GRAINS } , - { "", PHENOMENON_ICE_PELLETS } , - { "", PHENOMENON_HAIL } , - { "", PHENOMENON_SMALL_HAIL } , - { "", PHENOMENON_UNKNOWN_PRECIPITATION } , - { "", PHENOMENON_MIST } , - { "", PHENOMENON_SPRAY } , - { "", PHENOMENON_SQUALL } , - { "", PHENOMENON_TORNADO } , - { "", PHENOMENON_DUST_WHIRLS } */ - }; - struct _sky_list { - const char *name; - WeatherSky sky; - } sky_list[] = { - { "Mostly Sunny", SKY_BROKEN } , - { "Mostly Clear", SKY_BROKEN } , - { "Partly Cloudy", SKY_SCATTERED } , - { "Mostly Cloudy", SKY_FEW } , - { "Sunny", SKY_CLEAR } , - { "Clear", SKY_CLEAR } , - { "Cloudy", SKY_OVERCAST } , - { "Clouds", SKY_SCATTERED } , - { "Rain", SKY_SCATTERED } , - { "Snow", SKY_SCATTERED } - }; - - nfo->valid = TRUE; - g_free (nfo->forecast); - nfo->forecast = g_strdup ((const char *)val); - - for (i = 0; i < G_N_ELEMENTS (ph_list); i++) { - if (strstr ((const char *)val, ph_list [i].name)) { - nfo->cond.phenomenon = ph_list [i].ph; - break; - } - } - - for (i = 0; i < G_N_ELEMENTS (sky_list); i++) { - if (strstr ((const char *)val, sky_list [i].name)) { - nfo->sky = sky_list [i].sky; - break; - } - } - } - - if (val) - xmlFree (val); - - at = at->next; - } - } - } - } +#define XC (const xmlChar *) +#define isElem(_node, _name) g_str_equal((const char *)_node->name, _name) - if (res) { - gboolean have_any = FALSE; - GSList *r; - - /* Remove invalid forecast data from the list. - They should be all valid or all invalid. */ - for (r = res; r; r = r->next) { - WeatherInfo *nfo = r->data; - - if (!nfo || !nfo->valid) { - if (r->data) - weather_info_free (r->data); - - r->data = NULL; - } else { - have_any = TRUE; - - if (nfo->tempMinMaxValid) - nfo->temp = (nfo->temp_min + nfo->temp_max) / 2.0; - } - } - - if (!have_any) { - /* data members are freed already */ - g_slist_free (res); - res = NULL; - } - } + doc = xmlParseMemory(buff, len); + if (!doc) + return NULL; - break; + /* Description at http://www.weather.gov/mdl/XML/Design/MDL_XML_Design.pdf */ + root = xmlDocGetRootElement(doc); + for (node = root->xmlChildrenNode; node; node = node->next) { + if (node->name == NULL || node->type != XML_ELEMENT_NODE) + continue; + + if (isElem(node, "data")) { + xmlNode *n; + char *time_layout = NULL; + time_t update_times[7] = {0}; + + for (n = node->children; n; n = n->next) { + if (!n->name) + continue; + + if (isElem(n, "time-layout")) { + if (!time_layout && hasAttr(n, "summarization", "24hourly")) { + xmlNode *c; + int count = 0; + + for (c = n->children; c && (count < 7 || !time_layout); + c = c->next) { + if (c->name && !time_layout && isElem(c, "layout-key")) { + xmlChar *val = xmlNodeGetContent(c); + + if (val) { + time_layout = g_strdup((const char *)val); + xmlFree(val); + } + } else if (c->name && isElem(c, "start-valid-time")) { + xmlChar *val = xmlNodeGetContent(c); + + if (val) { + GDateTime *dt = + g_date_time_new_from_iso8601((const char *)val, NULL); + if (dt != NULL) { + update_times[count] = g_date_time_to_unix(dt); + g_date_time_unref(dt); + } else { + update_times[count] = 0; + } + + count++; + + xmlFree(val); } + } } - g_free (time_layout); + if (count != 7) { + /* There can be more than one time-layout element, the other + with only few children, which is not the one to use. */ + g_free(time_layout); + time_layout = NULL; + } + } + } else if (isElem(n, "parameters")) { + xmlNode *p; - /* stop seeking XML */ + /* time-layout should be always before parameters */ + if (!time_layout) break; - } - } - xmlFreeDoc (doc); - #undef XC - #undef isElem - - return res; -} + if (!res) { + int i; + + for (i = 0; i < 7; i++) { + WeatherInfo *nfo = weather_info_clone(master_info); + + if (nfo) { + nfo->valid = FALSE; + nfo->forecast_type = FORECAST_ZONE; + nfo->update = update_times[i]; + nfo->sky = -1; + nfo->temperature_unit = TEMP_UNIT_FAHRENHEIT; + nfo->temp = -1000.0; + nfo->temp_min = -1000.0; + nfo->temp_max = -1000.0; + nfo->tempMinMaxValid = FALSE; + nfo->cond.significant = FALSE; + nfo->cond.phenomenon = PHENOMENON_NONE; + nfo->cond.qualifier = QUALIFIER_NONE; + nfo->dew = -1000.0; + nfo->wind = -1; + nfo->windspeed = -1; + nfo->pressure = -1.0; + nfo->visibility = -1.0; + nfo->sunriseValid = FALSE; + nfo->sunsetValid = FALSE; + nfo->sunrise = 0; + nfo->sunset = 0; + g_free(nfo->forecast); + nfo->forecast = NULL; + nfo->session = NULL; + nfo->requests_pending = 0; + nfo->finish_cb = NULL; + nfo->cb_data = NULL; + res = g_slist_append(res, nfo); + } + } + } + + for (p = n->children; p; p = p->next) { + if (p->name && isElem(p, "temperature") && + hasAttr(p, "time-layout", time_layout)) { + xmlNode *c; + GSList *at = res; + gboolean is_max = hasAttr(p, "type", "maximum"); + + if (!is_max && !hasAttr(p, "type", "minimum")) + break; + + for (c = p->children; c && at; c = c->next) { + if (isElem(c, "value")) { + WeatherInfo *nfo = (WeatherInfo *)at->data; + xmlChar *val = xmlNodeGetContent(c); + + /* can pass some values as <value xsi:nil="true"/> */ + if (!val || !*val) { + if (is_max) + nfo->temp_max = nfo->temp_min; + else + nfo->temp_min = nfo->temp_max; + } else { + if (is_max) + nfo->temp_max = atof((const char *)val); + else + nfo->temp_min = atof((const char *)val); + } + + if (val) + xmlFree(val); + + nfo->tempMinMaxValid = + nfo->tempMinMaxValid || + (nfo->temp_max > -999.0 && nfo->temp_min > -999.0); + nfo->valid = nfo->tempMinMaxValid; + + at = at->next; + } + } + } else if (p->name && isElem(p, "weather") && + hasAttr(p, "time-layout", time_layout)) { + xmlNode *c; + GSList *at = res; + + for (c = p->children; c && at; c = c->next) { + if (c->name && isElem(c, "weather-conditions")) { + WeatherInfo *nfo = at->data; + xmlChar *val = xmlGetProp(c, XC "weather-summary"); + + if (val && nfo) { + /* Checking from top to bottom, if 'value' contains 'name', + then that win, thus put longer (more precise) values to + the top. */ + int i; + struct _ph_list { + const char *name; + WeatherConditionPhenomenon ph; + } ph_list[] = { + {"Ice Crystals", PHENOMENON_ICE_CRYSTALS}, + {"Volcanic Ash", PHENOMENON_VOLCANIC_ASH}, + {"Blowing Sand", PHENOMENON_SANDSTORM}, + {"Blowing Dust", PHENOMENON_DUSTSTORM}, + {"Blowing Snow", PHENOMENON_FUNNEL_CLOUD}, + {"Drizzle", PHENOMENON_DRIZZLE}, + {"Rain", PHENOMENON_RAIN}, + {"Snow", PHENOMENON_SNOW}, + {"Fog", PHENOMENON_FOG}, + {"Smoke", PHENOMENON_SMOKE}, + {"Sand", PHENOMENON_SAND}, + {"Haze", PHENOMENON_HAZE}, + {"Dust", PHENOMENON_DUST} /*, + { "", PHENOMENON_SNOW_GRAINS } , + { "", PHENOMENON_ICE_PELLETS } , + { "", PHENOMENON_HAIL } , + { "", PHENOMENON_SMALL_HAIL } , + { "", PHENOMENON_UNKNOWN_PRECIPITATION } , + { "", PHENOMENON_MIST } , + { "", PHENOMENON_SPRAY } , + { "", PHENOMENON_SQUALL } , + { "", PHENOMENON_TORNADO } , + { "", PHENOMENON_DUST_WHIRLS } */ + }; + struct _sky_list { + const char *name; + WeatherSky sky; + } sky_list[] = {{"Mostly Sunny", SKY_BROKEN}, + {"Mostly Clear", SKY_BROKEN}, + {"Partly Cloudy", SKY_SCATTERED}, + {"Mostly Cloudy", SKY_FEW}, + {"Sunny", SKY_CLEAR}, + {"Clear", SKY_CLEAR}, + {"Cloudy", SKY_OVERCAST}, + {"Clouds", SKY_SCATTERED}, + {"Rain", SKY_SCATTERED}, + {"Snow", SKY_SCATTERED}}; + + nfo->valid = TRUE; + g_free(nfo->forecast); + nfo->forecast = g_strdup((const char *)val); + + for (i = 0; i < G_N_ELEMENTS(ph_list); i++) { + if (strstr((const char *)val, ph_list[i].name)) { + nfo->cond.phenomenon = ph_list[i].ph; + break; + } + } -static void -iwin_finish (GObject *source, GAsyncResult *result, gpointer data) -{ - WeatherInfo *info = (WeatherInfo *)data; - GError *error = NULL; - GBytes *bytes; - const char *response_body = NULL; - gsize len = 0; - - g_return_if_fail (info != NULL); - - bytes = soup_session_send_and_read_finish (SOUP_SESSION(source), - result, &error); - - if (error != NULL) { - /* forecast data is not really interesting anyway ;) */ - g_warning ("Failed to get IWIN forecast data: %s\n", - error->message); - request_done (info, error); - g_error_free (error); - return; - } + for (i = 0; i < G_N_ELEMENTS(sky_list); i++) { + if (strstr((const char *)val, sky_list[i].name)) { + nfo->sky = sky_list[i].sky; + break; + } + } + } - response_body = g_bytes_get_data (bytes, &len); - if (info->forecast_type == FORECAST_LIST) - info->forecast_list = parseForecastXml (response_body, len, info); - else - info->forecast = formatWeatherMsg (g_strndup (response_body, len)); + if (val) + xmlFree(val); - g_bytes_unref (bytes); - request_done (info, NULL); -} + at = at->next; + } + } + } + } -/* Get forecast into newly alloc'ed string */ -void -iwin_start_open (WeatherInfo *info) -{ - gchar *url, *state, *zone; - WeatherLocation *loc; - SoupMessage *msg; - - g_return_if_fail (info != NULL); - loc = info->location; - g_return_if_fail (loc != NULL); - - if (loc->zone[0] == '-' && (info->forecast_type != FORECAST_LIST || !loc->latlon_valid)) - return; - - if (info->forecast) { - g_free (info->forecast); - info->forecast = NULL; - } + if (res) { + gboolean have_any = FALSE; + GSList *r; - free_forecast_list (info); + /* Remove invalid forecast data from the list. + They should be all valid or all invalid. */ + for (r = res; r; r = r->next) { + WeatherInfo *nfo = r->data; - if (info->forecast_type == FORECAST_LIST) { - /* see the description here: http://www.weather.gov/forecasts/xml/ */ - if (loc->latlon_valid) { - GDateTime *dt; - gint year, month, day; + if (!nfo || !nfo->valid) { + if (r->data) + weather_info_free(r->data); - dt = g_date_time_new_now_local (); - g_date_time_get_ymd (dt, &year, &month, &day); - g_date_time_unref (dt); + r->data = NULL; + } else { + have_any = TRUE; - url = g_strdup_printf ("http://www.weather.gov/forecasts/xml/sample_products/browser_interface/ndfdBrowserClientByDay.php?&lat=%.02f&lon=%.02f&format=24+hourly&startDate=%04d-%02d-%02d&numDays=7", - RADIANS_TO_DEGREES (loc->latitude), RADIANS_TO_DEGREES (loc->longitude), year, month, day); + if (nfo->tempMinMaxValid) + nfo->temp = (nfo->temp_min + nfo->temp_max) / 2.0; + } + } - msg = soup_message_new ("GET", url); - g_free (url); - soup_session_send_and_read_async (info->session, msg, - G_PRIORITY_DEFAULT, - NULL, iwin_finish, info); + if (!have_any) { + /* data members are freed already */ + g_slist_free(res); + res = NULL; + } + } - info->requests_pending++; + break; } - return; - } + } - if (loc->zone[0] == ':') { - /* Met Office Region Names */ - metoffice_start_open (info); - return; - } else if (loc->zone[0] == '@') { - /* Australian BOM forecasts */ - bom_start_open (info); - return; - } + g_free(time_layout); - /* The zone for Pittsburgh (for example) is given as PAZ021 in the locations - ** file (the PA stands for the state pennsylvania). The url used wants the state - ** as pa, and the zone as lower case paz021. - */ - zone = g_ascii_strdown (loc->zone, -1); - state = g_strndup (zone, 2); + /* stop seeking XML */ + break; + } + } + xmlFreeDoc(doc); - url = g_strdup_printf ("http://tgftp.nws.noaa.gov/data/forecasts/zone/%s/%s.txt", state, zone); +#undef XC +#undef isElem - g_free (zone); - g_free (state); + return res; +} - msg = soup_message_new ("GET", url); - g_free (url); - soup_session_send_and_read_async (info->session, msg, G_PRIORITY_DEFAULT, - NULL, iwin_finish, info); +static void iwin_finish(GObject *source, GAsyncResult *result, gpointer data) { + WeatherInfo *info = (WeatherInfo *)data; + GError *error = NULL; + GBytes *bytes; + const char *response_body = NULL; + gsize len = 0; + + g_return_if_fail(info != NULL); + + bytes = + soup_session_send_and_read_finish(SOUP_SESSION(source), result, &error); + + if (error != NULL) { + /* forecast data is not really interesting anyway ;) */ + g_warning("Failed to get IWIN forecast data: %s\n", error->message); + request_done(info, error); + g_error_free(error); + return; + } + + response_body = g_bytes_get_data(bytes, &len); + if (info->forecast_type == FORECAST_LIST) + info->forecast_list = parseForecastXml(response_body, len, info); + else + info->forecast = formatWeatherMsg(g_strndup(response_body, len)); + + g_bytes_unref(bytes); + request_done(info, NULL); +} - info->requests_pending++; +/* Get forecast into newly alloc'ed string */ +void iwin_start_open(WeatherInfo *info) { + gchar *url, *state, *zone; + WeatherLocation *loc; + SoupMessage *msg; + + g_return_if_fail(info != NULL); + loc = info->location; + g_return_if_fail(loc != NULL); + + if (loc->zone[0] == '-' && + (info->forecast_type != FORECAST_LIST || !loc->latlon_valid)) + return; + + if (info->forecast) { + g_free(info->forecast); + info->forecast = NULL; + } + + free_forecast_list(info); + + if (info->forecast_type == FORECAST_LIST) { + /* see the description here: http://www.weather.gov/forecasts/xml/ */ + if (loc->latlon_valid) { + GDateTime *dt; + gint year, month, day; + + dt = g_date_time_new_now_local(); + g_date_time_get_ymd(dt, &year, &month, &day); + g_date_time_unref(dt); + + url = + g_strdup_printf("http://www.weather.gov/forecasts/xml/" + "sample_products/browser_interface/" + "ndfdBrowserClientByDay.php?&lat=%.02f&lon=%.02f&" + "format=24+hourly&startDate=%04d-%02d-%02d&numDays=7", + RADIANS_TO_DEGREES(loc->latitude), + RADIANS_TO_DEGREES(loc->longitude), year, month, day); + + msg = soup_message_new("GET", url); + g_free(url); + soup_session_send_and_read_async(info->session, msg, G_PRIORITY_DEFAULT, + NULL, iwin_finish, info); + + info->requests_pending++; + } + return; + } + + if (loc->zone[0] == ':') { + /* Met Office Region Names */ + metoffice_start_open(info); + return; + } else if (loc->zone[0] == '@') { + /* Australian BOM forecasts */ + bom_start_open(info); + return; + } + + /* The zone for Pittsburgh (for example) is given as PAZ021 in the locations + ** file (the PA stands for the state pennsylvania). The url used wants the + *state + ** as pa, and the zone as lower case paz021. + */ + zone = g_ascii_strdown(loc->zone, -1); + state = g_strndup(zone, 2); + + url = g_strdup_printf( + "http://tgftp.nws.noaa.gov/data/forecasts/zone/%s/%s.txt", state, zone); + + g_free(zone); + g_free(state); + + msg = soup_message_new("GET", url); + g_free(url); + soup_session_send_and_read_async(info->session, msg, G_PRIORITY_DEFAULT, NULL, + iwin_finish, info); + + info->requests_pending++; } diff --git a/libmateweather/weather-met.c b/libmateweather/weather-met.c index 7022abb..ac74ceb 100644 --- a/libmateweather/weather-met.c +++ b/libmateweather/weather-met.c @@ -25,91 +25,88 @@ #include <string.h> #define MATEWEATHER_I_KNOW_THIS_IS_UNSTABLE -#include "weather.h" #include "weather-priv.h" +#include "weather.h" -static char * -met_reprocess (char *x, int len) -{ - char *p = x; - char *o; - int spacing = 0; - static gchar *buf; - static gint buflen = 0; - gchar *lastspace = NULL; - int count = 0; - - if (buflen < len) - { - if (buf) - g_free (buf); - buf = g_malloc (len + 1); - buflen = len; +static char *met_reprocess(char *x, int len) { + char *p = x; + char *o; + int spacing = 0; + static gchar *buf; + static gint buflen = 0; + gchar *lastspace = NULL; + int count = 0; + + if (buflen < len) { + if (buf) + g_free(buf); + buf = g_malloc(len + 1); + buflen = len; + } + + o = buf; + x += len; /* End mark */ + + while (*p && p < x) { + if (g_ascii_isspace(*p)) { + if (!spacing) { + spacing = 1; + lastspace = o; + count++; + *o++ = ' '; + } + p++; + continue; + } + spacing = 0; + if (count > 75 && lastspace) { + count = o - lastspace - 1; + *lastspace = '\n'; + lastspace = NULL; } - o = buf; - x += len; /* End mark */ - - while (*p && p < x) { - if (g_ascii_isspace (*p)) { - if (!spacing) { - spacing = 1; - lastspace = o; - count++; - *o++ = ' '; - } - p++; - continue; - } - spacing = 0; - if (count > 75 && lastspace) { - count = o - lastspace - 1; - *lastspace = '\n'; - lastspace = NULL; - } - - if (*p == '&') { - if (g_ascii_strncasecmp (p, "&", 5) == 0) { - *o++ = '&'; - count++; - p += 5; - continue; - } - if (g_ascii_strncasecmp (p, "<", 4) == 0) { - *o++ = '<'; - count++; - p += 4; - continue; - } - if (g_ascii_strncasecmp (p, ">", 4) == 0) { - *o++ = '>'; - count++; - p += 4; - continue; - } - } - if (*p == '<') { - if (g_ascii_strncasecmp (p, "<BR>", 4) == 0) { - *o++ = '\n'; - count = 0; - } - if (g_ascii_strncasecmp (p, "<B>", 3) == 0) { - *o++ = '\n'; - *o++ = '\n'; - count = 0; - } - p++; - while (*p && *p != '>') - p++; - if (*p) - p++; - continue; - } - *o++ = *p++; - count++; + if (*p == '&') { + if (g_ascii_strncasecmp(p, "&", 5) == 0) { + *o++ = '&'; + count++; + p += 5; + continue; + } + if (g_ascii_strncasecmp(p, "<", 4) == 0) { + *o++ = '<'; + count++; + p += 4; + continue; + } + if (g_ascii_strncasecmp(p, ">", 4) == 0) { + *o++ = '>'; + count++; + p += 4; + continue; + } } - *o = 0; - return buf; + if (*p == '<') { + if (g_ascii_strncasecmp(p, "<BR>", 4) == 0) { + *o++ = '\n'; + count = 0; + } + if (g_ascii_strncasecmp(p, "<B>", 3) == 0) { + *o++ = '\n'; + *o++ = '\n'; + count = 0; + } + p++; + while (*p && *p != '>') + p++; + if (*p) + p++; + continue; + } + *o++ = *p++; + count++; + } + *o = 0; + return buf; } /* @@ -118,73 +115,67 @@ met_reprocess (char *x, int len) * be done with this ;) */ -static gchar * -met_parse (const gchar *meto, gsize len) -{ - gchar *p; - gchar *rp; - gchar *r = g_strdup ("Met Office Forecast\n"); - gchar *t; - const gchar *end = meto + len; +static gchar *met_parse(const gchar *meto, gsize len) { + gchar *p; + gchar *rp; + gchar *r = g_strdup("Met Office Forecast\n"); + gchar *t; + const gchar *end = meto + len; - g_return_val_if_fail (meto != NULL, r); + g_return_val_if_fail(meto != NULL, r); - p = xstrnstr (meto, len, "Summary: </b>"); - g_return_val_if_fail (p != NULL, r); + p = xstrnstr(meto, len, "Summary: </b>"); + g_return_val_if_fail(p != NULL, r); - rp = xstrnstr (p, end - p, "Text issued at:"); - g_return_val_if_fail (rp != NULL, r); + rp = xstrnstr(p, end - p, "Text issued at:"); + g_return_val_if_fail(rp != NULL, r); - p += 13; - /* p to rp is the text block we want but in HTML malformat */ - t = g_strconcat (r, met_reprocess (p, rp - p), NULL); - g_free (r); + p += 13; + /* p to rp is the text block we want but in HTML malformat */ + t = g_strconcat(r, met_reprocess(p, rp - p), NULL); + g_free(r); - return t; + return t; } -static void -met_finish (GObject *source, GAsyncResult *result, gpointer data) -{ - WeatherInfo *info = (WeatherInfo *)data; - GError *error = NULL; - GBytes *bytes; - const char *response_body = NULL; - gsize len = 0; - - g_return_if_fail (info != NULL); - - bytes = soup_session_send_and_read_finish (SOUP_SESSION(source), - result, &error); - - if (error != NULL) { - g_warning ("Failed to get Met Office forecast data: %s.\n", - error->message); - request_done (info, error); - g_error_free (error); - return; - } - - response_body = g_bytes_get_data (bytes, &len); - info->forecast = met_parse (response_body, len); - g_bytes_unref (bytes); - request_done (info, NULL); +static void met_finish(GObject *source, GAsyncResult *result, gpointer data) { + WeatherInfo *info = (WeatherInfo *)data; + GError *error = NULL; + GBytes *bytes; + const char *response_body = NULL; + gsize len = 0; + + g_return_if_fail(info != NULL); + + bytes = + soup_session_send_and_read_finish(SOUP_SESSION(source), result, &error); + + if (error != NULL) { + g_warning("Failed to get Met Office forecast data: %s.\n", error->message); + request_done(info, error); + g_error_free(error); + return; + } + + response_body = g_bytes_get_data(bytes, &len); + info->forecast = met_parse(response_body, len); + g_bytes_unref(bytes); + request_done(info, NULL); } -void -metoffice_start_open (WeatherInfo *info) -{ - gchar *url; - SoupMessage *msg; - WeatherLocation *loc; +void metoffice_start_open(WeatherInfo *info) { + gchar *url; + SoupMessage *msg; + WeatherLocation *loc; - loc = info->location; - url = g_strdup_printf ("http://www.metoffice.gov.uk/weather/europe/uk/%s.html", loc->zone + 1); + loc = info->location; + url = g_strdup_printf("http://www.metoffice.gov.uk/weather/europe/uk/%s.html", + loc->zone + 1); - msg = soup_message_new ("GET", url); - soup_session_send_and_read_async (info->session, msg, G_PRIORITY_DEFAULT, - NULL, met_finish, info); - g_free (url); + msg = soup_message_new("GET", url); + soup_session_send_and_read_async(info->session, msg, G_PRIORITY_DEFAULT, NULL, + met_finish, info); + g_free(url); - info->requests_pending++; + info->requests_pending++; } diff --git a/libmateweather/weather-metar.c b/libmateweather/weather-metar.c index d25a432..d1e67d8 100644 --- a/libmateweather/weather-metar.c +++ b/libmateweather/weather-metar.c @@ -20,376 +20,364 @@ #include <config.h> #endif +#include <regex.h> #include <stdlib.h> #include <string.h> #include <sys/types.h> -#include <regex.h> #define MATEWEATHER_I_KNOW_THIS_IS_UNSTABLE -#include "weather.h" #include "weather-priv.h" +#include "weather.h" enum { - TIME_RE, - WIND_RE, - VIS_RE, - COND_RE, - CLOUD_RE, - TEMP_RE, - PRES_RE, - - RE_NUM + TIME_RE, + WIND_RE, + VIS_RE, + COND_RE, + CLOUD_RE, + TEMP_RE, + PRES_RE, + + RE_NUM }; /* Return time of weather report as secs since epoch UTC */ -static time_t -make_time (gint utcDate, gint utcHour, gint utcMin) -{ - const time_t now = time (NULL); - struct tm tm; - - localtime_r (&now, &tm); - - /* If last reading took place just before midnight UTC on the - * first, adjust the date downward to allow for the month - * change-over. This ASSUMES that the reading won't be more than - * 24 hrs old! */ - if ((utcDate > tm.tm_mday) && (tm.tm_mday == 1)) { - tm.tm_mday = 0; /* mktime knows this is the last day of the previous - * month. */ - } else { - tm.tm_mday = utcDate; - } - tm.tm_hour = utcHour; - tm.tm_min = utcMin; - tm.tm_sec = 0; - - /* mktime() assumes value is local, not UTC. Use tm_gmtoff to compensate */ +static time_t make_time(gint utcDate, gint utcHour, gint utcMin) { + const time_t now = time(NULL); + struct tm tm; + + localtime_r(&now, &tm); + + /* If last reading took place just before midnight UTC on the + * first, adjust the date downward to allow for the month + * change-over. This ASSUMES that the reading won't be more than + * 24 hrs old! */ + if ((utcDate > tm.tm_mday) && (tm.tm_mday == 1)) { + tm.tm_mday = 0; /* mktime knows this is the last day of the previous + * month. */ + } else { + tm.tm_mday = utcDate; + } + tm.tm_hour = utcHour; + tm.tm_min = utcMin; + tm.tm_sec = 0; + + /* mktime() assumes value is local, not UTC. Use tm_gmtoff to compensate */ #ifdef HAVE_TM_TM_GMOFF - return tm.tm_gmtoff + mktime (&tm); + return tm.tm_gmtoff + mktime(&tm); #elif defined HAVE_TIMEZONE - return timezone + mktime (&tm); + return timezone + mktime(&tm); #endif } -static void -metar_tok_time (gchar *tokp, WeatherInfo *info) -{ - gint day, hr, min; +static void metar_tok_time(gchar *tokp, WeatherInfo *info) { + gint day, hr, min; - sscanf (tokp, "%2u%2u%2u", &day, &hr, &min); - info->update = make_time (day, hr, min); + sscanf(tokp, "%2u%2u%2u", &day, &hr, &min); + info->update = make_time(day, hr, min); } -static void -metar_tok_wind (gchar *tokp, WeatherInfo *info) -{ - gchar sdir[4], sspd[4], sgust[4]; - gint dir, spd = -1; - gchar *gustp; - size_t glen; - - strncpy (sdir, tokp, 3); - sdir[3] = 0; - dir = (!strcmp (sdir, "VRB")) ? -1 : atoi (sdir); - - memset (sspd, 0, sizeof (sspd)); - glen = strspn (tokp + 3, CONST_DIGITS); - strncpy (sspd, tokp + 3, glen); - spd = atoi (sspd); - tokp += glen + 3; - - gustp = strchr (tokp, 'G'); - if (gustp) { - memset (sgust, 0, sizeof (sgust)); - glen = strspn (gustp + 1, CONST_DIGITS); - strncpy (sgust, gustp + 1, glen); - tokp = gustp + 1 + glen; - } - - if (!strcmp (tokp, "MPS")) - info->windspeed = WINDSPEED_MS_TO_KNOTS ((WeatherWindSpeed)spd); - else - info->windspeed = (WeatherWindSpeed)spd; - - if ((349 <= dir) || (dir <= 11)) - info->wind = WIND_N; - else if ((12 <= dir) && (dir <= 33)) - info->wind = WIND_NNE; - else if ((34 <= dir) && (dir <= 56)) - info->wind = WIND_NE; - else if ((57 <= dir) && (dir <= 78)) - info->wind = WIND_ENE; - else if ((79 <= dir) && (dir <= 101)) - info->wind = WIND_E; - else if ((102 <= dir) && (dir <= 123)) - info->wind = WIND_ESE; - else if ((124 <= dir) && (dir <= 146)) - info->wind = WIND_SE; - else if ((147 <= dir) && (dir <= 168)) - info->wind = WIND_SSE; - else if ((169 <= dir) && (dir <= 191)) - info->wind = WIND_S; - else if ((192 <= dir) && (dir <= 213)) - info->wind = WIND_SSW; - else if ((214 <= dir) && (dir <= 236)) - info->wind = WIND_SW; - else if ((237 <= dir) && (dir <= 258)) - info->wind = WIND_WSW; - else if ((259 <= dir) && (dir <= 281)) - info->wind = WIND_W; - else if ((282 <= dir) && (dir <= 303)) - info->wind = WIND_WNW; - else if ((304 <= dir) && (dir <= 326)) - info->wind = WIND_NW; - else if ((327 <= dir) && (dir <= 348)) - info->wind = WIND_NNW; +static void metar_tok_wind(gchar *tokp, WeatherInfo *info) { + gchar sdir[4], sspd[4], sgust[4]; + gint dir, spd = -1; + gchar *gustp; + size_t glen; + + strncpy(sdir, tokp, 3); + sdir[3] = 0; + dir = (!strcmp(sdir, "VRB")) ? -1 : atoi(sdir); + + memset(sspd, 0, sizeof(sspd)); + glen = strspn(tokp + 3, CONST_DIGITS); + strncpy(sspd, tokp + 3, glen); + spd = atoi(sspd); + tokp += glen + 3; + + gustp = strchr(tokp, 'G'); + if (gustp) { + memset(sgust, 0, sizeof(sgust)); + glen = strspn(gustp + 1, CONST_DIGITS); + strncpy(sgust, gustp + 1, glen); + tokp = gustp + 1 + glen; + } + + if (!strcmp(tokp, "MPS")) + info->windspeed = WINDSPEED_MS_TO_KNOTS((WeatherWindSpeed)spd); + else + info->windspeed = (WeatherWindSpeed)spd; + + if ((349 <= dir) || (dir <= 11)) + info->wind = WIND_N; + else if ((12 <= dir) && (dir <= 33)) + info->wind = WIND_NNE; + else if ((34 <= dir) && (dir <= 56)) + info->wind = WIND_NE; + else if ((57 <= dir) && (dir <= 78)) + info->wind = WIND_ENE; + else if ((79 <= dir) && (dir <= 101)) + info->wind = WIND_E; + else if ((102 <= dir) && (dir <= 123)) + info->wind = WIND_ESE; + else if ((124 <= dir) && (dir <= 146)) + info->wind = WIND_SE; + else if ((147 <= dir) && (dir <= 168)) + info->wind = WIND_SSE; + else if ((169 <= dir) && (dir <= 191)) + info->wind = WIND_S; + else if ((192 <= dir) && (dir <= 213)) + info->wind = WIND_SSW; + else if ((214 <= dir) && (dir <= 236)) + info->wind = WIND_SW; + else if ((237 <= dir) && (dir <= 258)) + info->wind = WIND_WSW; + else if ((259 <= dir) && (dir <= 281)) + info->wind = WIND_W; + else if ((282 <= dir) && (dir <= 303)) + info->wind = WIND_WNW; + else if ((304 <= dir) && (dir <= 326)) + info->wind = WIND_NW; + else if ((327 <= dir) && (dir <= 348)) + info->wind = WIND_NNW; } -static void -metar_tok_vis (gchar *tokp, WeatherInfo *info) -{ - gchar *pfrac, *pend, *psp; - gchar sval[6]; - gint num, den, val; - - memset (sval, 0, sizeof (sval)); - - if (!strcmp (tokp,"CAVOK")) { - // "Ceiling And Visibility OK": visibility >= 10 KM - info->visibility=10000. / VISIBILITY_SM_TO_M (1.); - info->sky = SKY_CLEAR; - } else if (0 != (pend = strstr (tokp, "SM"))) { - // US observation: field ends with "SM" - pfrac = strchr (tokp, '/'); - if (pfrac) { - if (*tokp == 'M') { - info->visibility = 0.001; - } else { - num = (*(pfrac - 1) - '0'); - strncpy (sval, pfrac + 1, pend - pfrac - 1); - den = atoi (sval); - info->visibility = - ((WeatherVisibility)num / ((WeatherVisibility)den)); - - psp = strchr (tokp, ' '); - if (psp) { - *psp = '\0'; - val = atoi (tokp); - info->visibility += (WeatherVisibility)val; - } - } - } else { - strncpy (sval, tokp, pend - tokp); - val = atoi (sval); - info->visibility = (WeatherVisibility)val; +static void metar_tok_vis(gchar *tokp, WeatherInfo *info) { + gchar *pfrac, *pend, *psp; + gchar sval[6]; + gint num, den, val; + + memset(sval, 0, sizeof(sval)); + + if (!strcmp(tokp, "CAVOK")) { + // "Ceiling And Visibility OK": visibility >= 10 KM + info->visibility = 10000. / VISIBILITY_SM_TO_M(1.); + info->sky = SKY_CLEAR; + } else if (0 != (pend = strstr(tokp, "SM"))) { + // US observation: field ends with "SM" + pfrac = strchr(tokp, '/'); + if (pfrac) { + if (*tokp == 'M') { + info->visibility = 0.001; + } else { + num = (*(pfrac - 1) - '0'); + strncpy(sval, pfrac + 1, pend - pfrac - 1); + den = atoi(sval); + info->visibility = ((WeatherVisibility)num / ((WeatherVisibility)den)); + + psp = strchr(tokp, ' '); + if (psp) { + *psp = '\0'; + val = atoi(tokp); + info->visibility += (WeatherVisibility)val; } + } } else { - // International observation: NNNN(DD NNNNDD)? - // For now: use only the minimum visibility and ignore its direction - strncpy (sval, tokp, strspn (tokp, CONST_DIGITS)); - val = atoi (sval); - info->visibility = (WeatherVisibility)val / VISIBILITY_SM_TO_M (1.); + strncpy(sval, tokp, pend - tokp); + val = atoi(sval); + info->visibility = (WeatherVisibility)val; } + } else { + // International observation: NNNN(DD NNNNDD)? + // For now: use only the minimum visibility and ignore its direction + strncpy(sval, tokp, strspn(tokp, CONST_DIGITS)); + val = atoi(sval); + info->visibility = (WeatherVisibility)val / VISIBILITY_SM_TO_M(1.); + } } -static void -metar_tok_cloud (gchar *tokp, WeatherInfo *info) -{ - gchar stype[4], salt[4]; - - strncpy (stype, tokp, 3); - stype[3] = 0; - if (strlen (tokp) == 6) { - strncpy (salt, tokp + 3, 3); - salt[3] = 0; - } - - if (!strcmp (stype, "CLR")) { - info->sky = SKY_CLEAR; - } else if (!strcmp (stype, "SKC")) { - info->sky = SKY_CLEAR; - } else if (!strcmp (stype, "NSC")) { - info->sky = SKY_CLEAR; - } else if (!strcmp (stype, "BKN")) { - info->sky = SKY_BROKEN; - } else if (!strcmp (stype, "SCT")) { - info->sky = SKY_SCATTERED; - } else if (!strcmp (stype, "FEW")) { - info->sky = SKY_FEW; - } else if (!strcmp (stype, "OVC")) { - info->sky = SKY_OVERCAST; - } +static void metar_tok_cloud(gchar *tokp, WeatherInfo *info) { + gchar stype[4], salt[4]; + + strncpy(stype, tokp, 3); + stype[3] = 0; + if (strlen(tokp) == 6) { + strncpy(salt, tokp + 3, 3); + salt[3] = 0; + } + + if (!strcmp(stype, "CLR")) { + info->sky = SKY_CLEAR; + } else if (!strcmp(stype, "SKC")) { + info->sky = SKY_CLEAR; + } else if (!strcmp(stype, "NSC")) { + info->sky = SKY_CLEAR; + } else if (!strcmp(stype, "BKN")) { + info->sky = SKY_BROKEN; + } else if (!strcmp(stype, "SCT")) { + info->sky = SKY_SCATTERED; + } else if (!strcmp(stype, "FEW")) { + info->sky = SKY_FEW; + } else if (!strcmp(stype, "OVC")) { + info->sky = SKY_OVERCAST; + } } -static void -metar_tok_pres (gchar *tokp, WeatherInfo *info) -{ - if (*tokp == 'A') { - gchar sintg[3], sfract[3]; - gint intg, fract; +static void metar_tok_pres(gchar *tokp, WeatherInfo *info) { + if (*tokp == 'A') { + gchar sintg[3], sfract[3]; + gint intg, fract; - strncpy (sintg, tokp + 1, 2); - sintg[2] = 0; - intg = atoi (sintg); + strncpy(sintg, tokp + 1, 2); + sintg[2] = 0; + intg = atoi(sintg); - strncpy (sfract, tokp + 3, 2); - sfract[2] = 0; - fract = atoi (sfract); + strncpy(sfract, tokp + 3, 2); + sfract[2] = 0; + fract = atoi(sfract); - info->pressure = (WeatherPressure)intg + (((WeatherPressure)fract)/100.0); - } else { /* *tokp == 'Q' */ - gchar spres[5]; - gint pres; + info->pressure = (WeatherPressure)intg + (((WeatherPressure)fract) / 100.0); + } else { /* *tokp == 'Q' */ + gchar spres[5]; + gint pres; - strncpy (spres, tokp + 1, 4); - spres[4] = 0; - pres = atoi (spres); + strncpy(spres, tokp + 1, 4); + spres[4] = 0; + pres = atoi(spres); - info->pressure = PRESSURE_MBAR_TO_INCH ((WeatherPressure)pres); - } + info->pressure = PRESSURE_MBAR_TO_INCH((WeatherPressure)pres); + } } -static void -metar_tok_temp (gchar *tokp, WeatherInfo *info) -{ - gchar *ptemp, *pdew, *psep; - - psep = strchr (tokp, '/'); - *psep = 0; - ptemp = tokp; - pdew = psep + 1; - - info->temp = (*ptemp == 'M') ? TEMP_C_TO_F (-atoi (ptemp + 1)) - : TEMP_C_TO_F (atoi (ptemp)); - if (*pdew) { - info->dew = (*pdew == 'M') ? TEMP_C_TO_F (-atoi (pdew + 1)) - : TEMP_C_TO_F (atoi (pdew)); - } else { - info->dew = -1000.0; - } +static void metar_tok_temp(gchar *tokp, WeatherInfo *info) { + gchar *ptemp, *pdew, *psep; + + psep = strchr(tokp, '/'); + *psep = 0; + ptemp = tokp; + pdew = psep + 1; + + info->temp = (*ptemp == 'M') ? TEMP_C_TO_F(-atoi(ptemp + 1)) + : TEMP_C_TO_F(atoi(ptemp)); + if (*pdew) { + info->dew = + (*pdew == 'M') ? TEMP_C_TO_F(-atoi(pdew + 1)) : TEMP_C_TO_F(atoi(pdew)); + } else { + info->dew = -1000.0; + } } -static void -metar_tok_cond (gchar *tokp, WeatherInfo *info) -{ - gchar squal[3], sphen[4]; - gchar *pphen; - - if ((strlen (tokp) > 3) && ((*tokp == '+') || (*tokp == '-'))) - ++tokp; /* FIX */ - - if ((*tokp == '+') || (*tokp == '-')) - pphen = tokp + 1; - else if (strlen (tokp) < 4) - pphen = tokp; - else - pphen = tokp + 2; - - memset (squal, 0, sizeof (squal)); - strncpy (squal, tokp, pphen - tokp); - squal[pphen - tokp] = 0; - - memset (sphen, 0, sizeof (sphen)); - strncpy (sphen, pphen, sizeof (sphen)); - sphen[sizeof (sphen)-1] = '\0'; - - /* Defaults */ - info->cond.qualifier = QUALIFIER_NONE; - info->cond.phenomenon = PHENOMENON_NONE; - info->cond.significant = FALSE; - - if (!strcmp (squal, "")) { - info->cond.qualifier = QUALIFIER_MODERATE; - } else if (!strcmp (squal, "-")) { - info->cond.qualifier = QUALIFIER_LIGHT; - } else if (!strcmp (squal, "+")) { - info->cond.qualifier = QUALIFIER_HEAVY; - } else if (!strcmp (squal, "VC")) { - info->cond.qualifier = QUALIFIER_VICINITY; - } else if (!strcmp (squal, "MI")) { - info->cond.qualifier = QUALIFIER_SHALLOW; - } else if (!strcmp (squal, "BC")) { - info->cond.qualifier = QUALIFIER_PATCHES; - } else if (!strcmp (squal, "PR")) { - info->cond.qualifier = QUALIFIER_PARTIAL; - } else if (!strcmp (squal, "TS")) { - info->cond.qualifier = QUALIFIER_THUNDERSTORM; - } else if (!strcmp (squal, "BL")) { - info->cond.qualifier = QUALIFIER_BLOWING; - } else if (!strcmp (squal, "SH")) { - info->cond.qualifier = QUALIFIER_SHOWERS; - } else if (!strcmp (squal, "DR")) { - info->cond.qualifier = QUALIFIER_DRIFTING; - } else if (!strcmp (squal, "FZ")) { - info->cond.qualifier = QUALIFIER_FREEZING; - } else { - return; - } - - if (!strcmp (sphen, "DZ")) { - info->cond.phenomenon = PHENOMENON_DRIZZLE; - } else if (!strcmp (sphen, "RA")) { - info->cond.phenomenon = PHENOMENON_RAIN; - } else if (!strcmp (sphen, "SN")) { - info->cond.phenomenon = PHENOMENON_SNOW; - } else if (!strcmp (sphen, "SG")) { - info->cond.phenomenon = PHENOMENON_SNOW_GRAINS; - } else if (!strcmp (sphen, "IC")) { - info->cond.phenomenon = PHENOMENON_ICE_CRYSTALS; - } else if (!strcmp (sphen, "PE")) { - info->cond.phenomenon = PHENOMENON_ICE_PELLETS; - } else if (!strcmp (sphen, "GR")) { - info->cond.phenomenon = PHENOMENON_HAIL; - } else if (!strcmp (sphen, "GS")) { - info->cond.phenomenon = PHENOMENON_SMALL_HAIL; - } else if (!strcmp (sphen, "UP")) { - info->cond.phenomenon = PHENOMENON_UNKNOWN_PRECIPITATION; - } else if (!strcmp (sphen, "BR")) { - info->cond.phenomenon = PHENOMENON_MIST; - } else if (!strcmp (sphen, "FG")) { - info->cond.phenomenon = PHENOMENON_FOG; - } else if (!strcmp (sphen, "FU")) { - info->cond.phenomenon = PHENOMENON_SMOKE; - } else if (!strcmp (sphen, "VA")) { - info->cond.phenomenon = PHENOMENON_VOLCANIC_ASH; - } else if (!strcmp (sphen, "SA")) { - info->cond.phenomenon = PHENOMENON_SAND; - } else if (!strcmp (sphen, "HZ")) { - info->cond.phenomenon = PHENOMENON_HAZE; - } else if (!strcmp (sphen, "PY")) { - info->cond.phenomenon = PHENOMENON_SPRAY; - } else if (!strcmp (sphen, "DU")) { - info->cond.phenomenon = PHENOMENON_DUST; - } else if (!strcmp (sphen, "SQ")) { - info->cond.phenomenon = PHENOMENON_SQUALL; - } else if (!strcmp (sphen, "SS")) { - info->cond.phenomenon = PHENOMENON_SANDSTORM; - } else if (!strcmp (sphen, "DS")) { - info->cond.phenomenon = PHENOMENON_DUSTSTORM; - } else if (!strcmp (sphen, "PO")) { - info->cond.phenomenon = PHENOMENON_DUST_WHIRLS; - } else if (!strcmp (sphen, "+FC")) { - info->cond.phenomenon = PHENOMENON_TORNADO; - } else if (!strcmp (sphen, "FC")) { - info->cond.phenomenon = PHENOMENON_FUNNEL_CLOUD; - } else { - return; - } - - if ((info->cond.qualifier != QUALIFIER_NONE) || (info->cond.phenomenon != PHENOMENON_NONE)) - info->cond.significant = TRUE; +static void metar_tok_cond(gchar *tokp, WeatherInfo *info) { + gchar squal[3], sphen[4]; + gchar *pphen; + + if ((strlen(tokp) > 3) && ((*tokp == '+') || (*tokp == '-'))) + ++tokp; /* FIX */ + + if ((*tokp == '+') || (*tokp == '-')) + pphen = tokp + 1; + else if (strlen(tokp) < 4) + pphen = tokp; + else + pphen = tokp + 2; + + memset(squal, 0, sizeof(squal)); + strncpy(squal, tokp, pphen - tokp); + squal[pphen - tokp] = 0; + + memset(sphen, 0, sizeof(sphen)); + strncpy(sphen, pphen, sizeof(sphen)); + sphen[sizeof(sphen) - 1] = '\0'; + + /* Defaults */ + info->cond.qualifier = QUALIFIER_NONE; + info->cond.phenomenon = PHENOMENON_NONE; + info->cond.significant = FALSE; + + if (!strcmp(squal, "")) { + info->cond.qualifier = QUALIFIER_MODERATE; + } else if (!strcmp(squal, "-")) { + info->cond.qualifier = QUALIFIER_LIGHT; + } else if (!strcmp(squal, "+")) { + info->cond.qualifier = QUALIFIER_HEAVY; + } else if (!strcmp(squal, "VC")) { + info->cond.qualifier = QUALIFIER_VICINITY; + } else if (!strcmp(squal, "MI")) { + info->cond.qualifier = QUALIFIER_SHALLOW; + } else if (!strcmp(squal, "BC")) { + info->cond.qualifier = QUALIFIER_PATCHES; + } else if (!strcmp(squal, "PR")) { + info->cond.qualifier = QUALIFIER_PARTIAL; + } else if (!strcmp(squal, "TS")) { + info->cond.qualifier = QUALIFIER_THUNDERSTORM; + } else if (!strcmp(squal, "BL")) { + info->cond.qualifier = QUALIFIER_BLOWING; + } else if (!strcmp(squal, "SH")) { + info->cond.qualifier = QUALIFIER_SHOWERS; + } else if (!strcmp(squal, "DR")) { + info->cond.qualifier = QUALIFIER_DRIFTING; + } else if (!strcmp(squal, "FZ")) { + info->cond.qualifier = QUALIFIER_FREEZING; + } else { + return; + } + + if (!strcmp(sphen, "DZ")) { + info->cond.phenomenon = PHENOMENON_DRIZZLE; + } else if (!strcmp(sphen, "RA")) { + info->cond.phenomenon = PHENOMENON_RAIN; + } else if (!strcmp(sphen, "SN")) { + info->cond.phenomenon = PHENOMENON_SNOW; + } else if (!strcmp(sphen, "SG")) { + info->cond.phenomenon = PHENOMENON_SNOW_GRAINS; + } else if (!strcmp(sphen, "IC")) { + info->cond.phenomenon = PHENOMENON_ICE_CRYSTALS; + } else if (!strcmp(sphen, "PE")) { + info->cond.phenomenon = PHENOMENON_ICE_PELLETS; + } else if (!strcmp(sphen, "GR")) { + info->cond.phenomenon = PHENOMENON_HAIL; + } else if (!strcmp(sphen, "GS")) { + info->cond.phenomenon = PHENOMENON_SMALL_HAIL; + } else if (!strcmp(sphen, "UP")) { + info->cond.phenomenon = PHENOMENON_UNKNOWN_PRECIPITATION; + } else if (!strcmp(sphen, "BR")) { + info->cond.phenomenon = PHENOMENON_MIST; + } else if (!strcmp(sphen, "FG")) { + info->cond.phenomenon = PHENOMENON_FOG; + } else if (!strcmp(sphen, "FU")) { + info->cond.phenomenon = PHENOMENON_SMOKE; + } else if (!strcmp(sphen, "VA")) { + info->cond.phenomenon = PHENOMENON_VOLCANIC_ASH; + } else if (!strcmp(sphen, "SA")) { + info->cond.phenomenon = PHENOMENON_SAND; + } else if (!strcmp(sphen, "HZ")) { + info->cond.phenomenon = PHENOMENON_HAZE; + } else if (!strcmp(sphen, "PY")) { + info->cond.phenomenon = PHENOMENON_SPRAY; + } else if (!strcmp(sphen, "DU")) { + info->cond.phenomenon = PHENOMENON_DUST; + } else if (!strcmp(sphen, "SQ")) { + info->cond.phenomenon = PHENOMENON_SQUALL; + } else if (!strcmp(sphen, "SS")) { + info->cond.phenomenon = PHENOMENON_SANDSTORM; + } else if (!strcmp(sphen, "DS")) { + info->cond.phenomenon = PHENOMENON_DUSTSTORM; + } else if (!strcmp(sphen, "PO")) { + info->cond.phenomenon = PHENOMENON_DUST_WHIRLS; + } else if (!strcmp(sphen, "+FC")) { + info->cond.phenomenon = PHENOMENON_TORNADO; + } else if (!strcmp(sphen, "FC")) { + info->cond.phenomenon = PHENOMENON_FUNNEL_CLOUD; + } else { + return; + } + + if ((info->cond.qualifier != QUALIFIER_NONE) || + (info->cond.phenomenon != PHENOMENON_NONE)) + info->cond.significant = TRUE; } -#define TIME_RE_STR "([0-9]{6})Z" -#define WIND_RE_STR "(([0-9]{3})|VRB)([0-9]?[0-9]{2})(G[0-9]?[0-9]{2})?(KT|MPS)" -#define VIS_RE_STR "((([0-9]?[0-9])|(M?([12] )?([1357]/1?[0-9])))SM)|" \ - "([0-9]{4}(N|NE|E|SE|S|SW|W|NW( [0-9]{4}(N|NE|E|SE|S|SW|W|NW))?)?)|" \ - "CAVOK" -#define COND_RE_STR "(-|\\+)?(VC|MI|BC|PR|TS|BL|SH|DR|FZ)?(DZ|RA|SN|SG|IC|PE|GR|GS|UP|BR|FG|FU|VA|SA|HZ|PY|DU|SQ|SS|DS|PO|\\+?FC)" -#define CLOUD_RE_STR "((CLR|BKN|SCT|FEW|OVC|SKC|NSC)([0-9]{3}|///)?(CB|TCU|///)?)" -#define TEMP_RE_STR "(M?[0-9][0-9])/(M?(//|[0-9][0-9])?)" -#define PRES_RE_STR "(A|Q)([0-9]{4})" +#define TIME_RE_STR "([0-9]{6})Z" +#define WIND_RE_STR "(([0-9]{3})|VRB)([0-9]?[0-9]{2})(G[0-9]?[0-9]{2})?(KT|MPS)" +#define VIS_RE_STR \ + "((([0-9]?[0-9])|(M?([12] )?([1357]/1?[0-9])))SM)|" \ + "([0-9]{4}(N|NE|E|SE|S|SW|W|NW( [0-9]{4}(N|NE|E|SE|S|SW|W|NW))?)?)|" \ + "CAVOK" +#define COND_RE_STR \ + "(-|\\+)?(VC|MI|BC|PR|TS|BL|SH|DR|FZ)?(DZ|RA|SN|SG|IC|PE|GR|GS|UP|BR|FG|FU|" \ + "VA|SA|HZ|PY|DU|SQ|SS|DS|PO|\\+?FC)" +#define CLOUD_RE_STR \ + "((CLR|BKN|SCT|FEW|OVC|SKC|NSC)([0-9]{3}|///)?(CB|TCU|///)?)" +#define TEMP_RE_STR "(M?[0-9][0-9])/(M?(//|[0-9][0-9])?)" +#define PRES_RE_STR "(A|Q)([0-9]{4})" /* POSIX regular expressions do not allow us to express "match whole words * only" in a simple way, so we have to wrap them all into @@ -399,197 +387,183 @@ metar_tok_cond (gchar *tokp, WeatherInfo *info) #define RE_SUFFIX ")( |$)" static regex_t metar_re[RE_NUM]; -static void (*metar_f[RE_NUM]) (gchar *tokp, WeatherInfo *info); - -static void -metar_init_re (void) -{ - static gboolean initialized = FALSE; - if (initialized) - return; - initialized = TRUE; - - regcomp (&metar_re[TIME_RE], RE_PREFIX TIME_RE_STR RE_SUFFIX, REG_EXTENDED); - regcomp (&metar_re[WIND_RE], RE_PREFIX WIND_RE_STR RE_SUFFIX, REG_EXTENDED); - regcomp (&metar_re[VIS_RE], RE_PREFIX VIS_RE_STR RE_SUFFIX, REG_EXTENDED); - regcomp (&metar_re[COND_RE], RE_PREFIX COND_RE_STR RE_SUFFIX, REG_EXTENDED); - regcomp (&metar_re[CLOUD_RE], RE_PREFIX CLOUD_RE_STR RE_SUFFIX, REG_EXTENDED); - regcomp (&metar_re[TEMP_RE], RE_PREFIX TEMP_RE_STR RE_SUFFIX, REG_EXTENDED); - regcomp (&metar_re[PRES_RE], RE_PREFIX PRES_RE_STR RE_SUFFIX, REG_EXTENDED); - - metar_f[TIME_RE] = metar_tok_time; - metar_f[WIND_RE] = metar_tok_wind; - metar_f[VIS_RE] = metar_tok_vis; - metar_f[COND_RE] = metar_tok_cond; - metar_f[CLOUD_RE] = metar_tok_cloud; - metar_f[TEMP_RE] = metar_tok_temp; - metar_f[PRES_RE] = metar_tok_pres; +static void (*metar_f[RE_NUM])(gchar *tokp, WeatherInfo *info); + +static void metar_init_re(void) { + static gboolean initialized = FALSE; + if (initialized) + return; + initialized = TRUE; + + regcomp(&metar_re[TIME_RE], RE_PREFIX TIME_RE_STR RE_SUFFIX, REG_EXTENDED); + regcomp(&metar_re[WIND_RE], RE_PREFIX WIND_RE_STR RE_SUFFIX, REG_EXTENDED); + regcomp(&metar_re[VIS_RE], RE_PREFIX VIS_RE_STR RE_SUFFIX, REG_EXTENDED); + regcomp(&metar_re[COND_RE], RE_PREFIX COND_RE_STR RE_SUFFIX, REG_EXTENDED); + regcomp(&metar_re[CLOUD_RE], RE_PREFIX CLOUD_RE_STR RE_SUFFIX, REG_EXTENDED); + regcomp(&metar_re[TEMP_RE], RE_PREFIX TEMP_RE_STR RE_SUFFIX, REG_EXTENDED); + regcomp(&metar_re[PRES_RE], RE_PREFIX PRES_RE_STR RE_SUFFIX, REG_EXTENDED); + + metar_f[TIME_RE] = metar_tok_time; + metar_f[WIND_RE] = metar_tok_wind; + metar_f[VIS_RE] = metar_tok_vis; + metar_f[COND_RE] = metar_tok_cond; + metar_f[CLOUD_RE] = metar_tok_cloud; + metar_f[TEMP_RE] = metar_tok_temp; + metar_f[PRES_RE] = metar_tok_pres; } -gboolean -metar_parse (gchar *metar, WeatherInfo *info) -{ - gchar *p; - //gchar *rmk; - gint i, i2; - regmatch_t rm, rm2; - gchar *tokp; - - g_return_val_if_fail (info != NULL, FALSE); - g_return_val_if_fail (metar != NULL, FALSE); - - metar_init_re (); - - /* - * Force parsing to end at "RMK" field. This prevents a subtle - * problem when info within the remark happens to match an earlier state - * and, as a result, throws off all the remaining expression - */ - if (0 != (p = strstr (metar, " RMK "))) { - *p = '\0'; - //rmk = p + 5; // uncomment this if RMK data becomes useful +gboolean metar_parse(gchar *metar, WeatherInfo *info) { + gchar *p; + // gchar *rmk; + gint i, i2; + regmatch_t rm, rm2; + gchar *tokp; + + g_return_val_if_fail(info != NULL, FALSE); + g_return_val_if_fail(metar != NULL, FALSE); + + metar_init_re(); + + /* + * Force parsing to end at "RMK" field. This prevents a subtle + * problem when info within the remark happens to match an earlier state + * and, as a result, throws off all the remaining expression + */ + if (0 != (p = strstr(metar, " RMK "))) { + *p = '\0'; + // rmk = p + 5; // uncomment this if RMK data becomes useful + } + + p = metar; + i = TIME_RE; + while (*p) { + + i2 = RE_NUM; + rm2.rm_so = strlen(p); + rm2.rm_eo = rm2.rm_so; + + for (i = 0; i < RE_NUM && rm2.rm_so > 0; i++) { + if (0 == regexec(&metar_re[i], p, 1, &rm, 0) && rm.rm_so < rm2.rm_so) { + i2 = i; + /* Skip leading and trailing space characters, if present. + (the regular expressions include those characters to + only get matches limited to whole words). */ + if (p[rm.rm_so] == ' ') + rm.rm_so++; + if (p[rm.rm_eo - 1] == ' ') + rm.rm_eo--; + rm2.rm_so = rm.rm_so; + rm2.rm_eo = rm.rm_eo; + } } - p = metar; - i = TIME_RE; - while (*p) { - - i2 = RE_NUM; - rm2.rm_so = strlen (p); - rm2.rm_eo = rm2.rm_so; - - for (i = 0; i < RE_NUM && rm2.rm_so > 0; i++) { - if (0 == regexec (&metar_re[i], p, 1, &rm, 0) - && rm.rm_so < rm2.rm_so) - { - i2 = i; - /* Skip leading and trailing space characters, if present. - (the regular expressions include those characters to - only get matches limited to whole words). */ - if (p[rm.rm_so] == ' ') rm.rm_so++; - if (p[rm.rm_eo - 1] == ' ') rm.rm_eo--; - rm2.rm_so = rm.rm_so; - rm2.rm_eo = rm.rm_eo; - } - } - - if (i2 != RE_NUM) { - tokp = g_strndup (p + rm2.rm_so, rm2.rm_eo - rm2.rm_so); - metar_f[i2] (tokp, info); - g_free (tokp); - } - - p += rm2.rm_eo; - p += strspn (p, " "); + if (i2 != RE_NUM) { + tokp = g_strndup(p + rm2.rm_so, rm2.rm_eo - rm2.rm_so); + metar_f[i2](tokp, info); + g_free(tokp); } - return TRUE; -} -static void -metar_finish (GObject *source, GAsyncResult *result, gpointer data) -{ - WeatherInfo *info = (WeatherInfo *)data; - WeatherLocation *loc; - const gchar *p, *end, *endtag; - gchar *searchkey, *metar; - gboolean success = FALSE; - GError *error = NULL; - GBytes *bytes; - const char *response_body = NULL; - gsize len = 0; - - g_return_if_fail (info != NULL); - - bytes = soup_session_send_and_read_finish (SOUP_SESSION(source), - result, &error); - - if (error != NULL) { - /* https://libsoup.org/libsoup-3.0/migrating-from-libsoup-2.html#status-codes-no-longer-used-for-internal-errors */ - switch (error->code) { - case SOUP_SESSION_ERROR_PARSING: - case SOUP_SESSION_ERROR_ENCODING: - case SOUP_SESSION_ERROR_TOO_MANY_REDIRECTS: - info->network_error = TRUE; - break; - default: - break; - } - g_warning (_("Failed to get METAR data: %s.\n"), - error->message); - request_done (info, error); - g_error_free (error); - return; - } + p += rm2.rm_eo; + p += strspn(p, " "); + } + return TRUE; +} - loc = info->location; +static void metar_finish(GObject *source, GAsyncResult *result, gpointer data) { + WeatherInfo *info = (WeatherInfo *)data; + WeatherLocation *loc; + const gchar *p, *end, *endtag; + gchar *searchkey, *metar; + gboolean success = FALSE; + GError *error = NULL; + GBytes *bytes; + const char *response_body = NULL; + gsize len = 0; - response_body = g_bytes_get_data (bytes, &len); - end = response_body + len; + g_return_if_fail(info != NULL); - /* Try METAR first, then SPECI */ - searchkey = g_strdup_printf ("<raw_text>METAR %s", loc->code); - p = xstrnstr (response_body, len, searchkey); - if (!p) { - g_free (searchkey); - searchkey = g_strdup_printf ("<raw_text>SPECI %s", loc->code); - p = xstrnstr (response_body, len, searchkey); - } + bytes = + soup_session_send_and_read_finish(SOUP_SESSION(source), result, &error); - if (p) { - p += WEATHER_LOCATION_CODE_LEN + 11; - endtag = xstrnstr (p, end - p, "</raw_text>"); - if (endtag) - metar = g_strndup (p, endtag - p); - else - metar = g_strndup (p, end - p); - success = metar_parse (metar, info); - g_free (metar); - } - g_free (searchkey); - - if (!success && !xstrnstr (response_body, len, "aviationweather.gov")) { - /* The response doesn't even seem to have come from NOAA... - * most likely it is a wifi hotspot login page. Call that a - * network error. - */ - info->network_error = TRUE; + if (error != NULL) { + /* https://libsoup.org/libsoup-3.0/migrating-from-libsoup-2.html#status-codes-no-longer-used-for-internal-errors + */ + switch (error->code) { + case SOUP_SESSION_ERROR_PARSING: + case SOUP_SESSION_ERROR_ENCODING: + case SOUP_SESSION_ERROR_TOO_MANY_REDIRECTS: + info->network_error = TRUE; + break; + default: + break; } + g_warning(_("Failed to get METAR data: %s.\n"), error->message); + request_done(info, error); + g_error_free(error); + return; + } + + loc = info->location; + + response_body = g_bytes_get_data(bytes, &len); + end = response_body + len; + + /* Try METAR first, then SPECI */ + searchkey = g_strdup_printf("<raw_text>METAR %s", loc->code); + p = xstrnstr(response_body, len, searchkey); + if (!p) { + g_free(searchkey); + searchkey = g_strdup_printf("<raw_text>SPECI %s", loc->code); + p = xstrnstr(response_body, len, searchkey); + } + + if (p) { + p += WEATHER_LOCATION_CODE_LEN + 11; + endtag = xstrnstr(p, end - p, "</raw_text>"); + if (endtag) + metar = g_strndup(p, endtag - p); + else + metar = g_strndup(p, end - p); + success = metar_parse(metar, info); + g_free(metar); + } + g_free(searchkey); + + if (!success && !xstrnstr(response_body, len, "aviationweather.gov")) { + /* The response doesn't even seem to have come from NOAA... + * most likely it is a wifi hotspot login page. Call that a + * network error. + */ + info->network_error = TRUE; + } - info->valid = success; - request_done (info, NULL); - g_bytes_unref(bytes); + info->valid = success; + request_done(info, NULL); + g_bytes_unref(bytes); } /* Read current conditions and fill in info structure */ -void -metar_start_open (WeatherInfo *info) -{ - WeatherLocation *loc; - SoupMessage *msg; - char *query; - - g_return_if_fail (info != NULL); - info->valid = info->network_error = FALSE; - loc = info->location; - if (loc == NULL) { - g_warning (_("WeatherInfo missing location")); - return; - } - - query = soup_form_encode ( - "dataSource", "metars", - "requestType", "retrieve", - "format", "xml", - "hoursBeforeNow", "3", - "mostRecent", "true", - "fields", "raw_text", - "stationString", loc->code, - NULL); - msg = soup_message_new_from_encoded_form ( - "GET", "https://aviationweather.gov/api/data/dataserver", - query); - soup_session_send_and_read_async (info->session, msg, G_PRIORITY_DEFAULT, - NULL, metar_finish, info); - - info->requests_pending++; +void metar_start_open(WeatherInfo *info) { + WeatherLocation *loc; + SoupMessage *msg; + char *query; + + g_return_if_fail(info != NULL); + info->valid = info->network_error = FALSE; + loc = info->location; + if (loc == NULL) { + g_warning(_("WeatherInfo missing location")); + return; + } + + query = soup_form_encode("dataSource", "metars", "requestType", "retrieve", + "format", "xml", "hoursBeforeNow", "3", "mostRecent", + "true", "fields", "raw_text", "stationString", + loc->code, NULL); + msg = soup_message_new_from_encoded_form( + "GET", "https://aviationweather.gov/api/data/dataserver", query); + soup_session_send_and_read_async(info->session, msg, G_PRIORITY_DEFAULT, NULL, + metar_finish, info); + + info->requests_pending++; } diff --git a/libmateweather/weather-moon.c b/libmateweather/weather-moon.c index feb98ba..0c64084 100644 --- a/libmateweather/weather-moon.c +++ b/libmateweather/weather-moon.c @@ -23,17 +23,17 @@ */ #ifdef HAVE_CONFIG_H -# include <config.h> +#include <config.h> #endif #ifdef __FreeBSD__ #include <sys/types.h> #endif +#include <glib.h> #include <math.h> -#include <time.h> #include <string.h> -#include <glib.h> +#include <time.h> #define MATEWEATHER_I_KNOW_THIS_IS_UNSTABLE #include "weather-priv.h" @@ -44,11 +44,11 @@ * The page only lists most values to 2 decimal places */ -#define LUNAR_MEAN_LONGITUDE 218.316 -#define LUNAR_PERIGEE_MEAN_LONG 318.15 -#define LUNAR_NODE_MEAN_LONG 125.08 -#define LUNAR_PROGRESSION 13.176358 -#define LUNAR_INCLINATION DEGREES_TO_RADIANS(5.145396) +#define LUNAR_MEAN_LONGITUDE 218.316 +#define LUNAR_PERIGEE_MEAN_LONG 318.15 +#define LUNAR_NODE_MEAN_LONG 125.08 +#define LUNAR_PROGRESSION 13.176358 +#define LUNAR_INCLINATION DEGREES_TO_RADIANS(5.145396) /** * calc_moon: @@ -61,80 +61,76 @@ * '90' is first quarter, etc. */ -gboolean -calc_moon (WeatherInfo *info) -{ - time_t t; - gdouble ra_h; - gdouble decl_r; - gdouble ndays, sunMeanAnom_d; - gdouble moonLong_d; - gdouble moonMeanAnom_d, moonMeanAnom_r; - gdouble sunEclipLong_r; - gdouble ascNodeMeanLong_d; - gdouble corrLong_d, eviction_d; - gdouble sinSunMeanAnom; - gdouble Ae, A3, Ec, A4, lN_r; - gdouble lambda_r, beta_r; - - /* - * The comments refer to the enumerated steps to calculate the - * position of the moon (section 65 of above reference) - */ - t = info->update; - ndays = EPOCH_TO_J2000(t) / 86400.; - sunMeanAnom_d = fmod (MEAN_ECLIPTIC_LONGITUDE (ndays) - PERIGEE_LONGITUDE (ndays), - 360.); - sunEclipLong_r = sunEclipLongitude (t); - moonLong_d = fmod (LUNAR_MEAN_LONGITUDE + (ndays * LUNAR_PROGRESSION), - 360.); - /* 5: moon's mean anomaly */ - moonMeanAnom_d = fmod ((moonLong_d - (0.1114041 * ndays) - - (LUNAR_PERIGEE_MEAN_LONG + LUNAR_NODE_MEAN_LONG)), - 360.); - /* 6: ascending node mean longitude */ - ascNodeMeanLong_d = fmod (LUNAR_NODE_MEAN_LONG - (0.0529539 * ndays), - 360.); - eviction_d = 1.2739 /* 7: eviction */ - * sin (DEGREES_TO_RADIANS (2.0 * (moonLong_d - RADIANS_TO_DEGREES (sunEclipLong_r)) - - moonMeanAnom_d)); - sinSunMeanAnom = sin (DEGREES_TO_RADIANS (sunMeanAnom_d)); - Ae = 0.1858 * sinSunMeanAnom; - A3 = 0.37 * sinSunMeanAnom; /* 8: annual equation */ - moonMeanAnom_d += eviction_d - Ae - A3; /* 9: "third correction" */ - moonMeanAnom_r = DEGREES_TO_RADIANS (moonMeanAnom_d); - Ec = 6.2886 * sin (moonMeanAnom_r); /* 10: equation of center */ - A4 = 0.214 * sin (2.0 * moonMeanAnom_r); /* 11: "yet another correction" */ - - /* Steps 12-14 give the true longitude after correcting for variation */ - moonLong_d += eviction_d + Ec - Ae + A4 - + (0.6583 * sin (2.0 * (moonMeanAnom_r - sunEclipLong_r))); - - /* 15: corrected longitude of node */ - corrLong_d = ascNodeMeanLong_d - 0.16 * sinSunMeanAnom; - - /* - * Calculate ecliptic latitude (16-19) and longitude (20) of the moon, - * then convert to right ascension and declination. - */ - lN_r = DEGREES_TO_RADIANS (moonLong_d - corrLong_d); /* l''-N' */ - lambda_r = DEGREES_TO_RADIANS(corrLong_d) - + atan2 (sin (lN_r) * cos (LUNAR_INCLINATION), cos (lN_r)); - beta_r = asin (sin (lN_r) * sin (LUNAR_INCLINATION)); - ecl2equ (t, lambda_r, beta_r, &ra_h, &decl_r); - - /* - * The phase is the angle from the sun's longitude to the moon's - */ - info->moonphase = - fmod (15.*ra_h - RADIANS_TO_DEGREES (sunEclipLongitude (info->update)), - 360.); - if (info->moonphase < 0) - info->moonphase += 360; - info->moonlatitude = RADIANS_TO_DEGREES (decl_r); - info->moonValid = TRUE; - - return TRUE; +gboolean calc_moon(WeatherInfo *info) { + time_t t; + gdouble ra_h; + gdouble decl_r; + gdouble ndays, sunMeanAnom_d; + gdouble moonLong_d; + gdouble moonMeanAnom_d, moonMeanAnom_r; + gdouble sunEclipLong_r; + gdouble ascNodeMeanLong_d; + gdouble corrLong_d, eviction_d; + gdouble sinSunMeanAnom; + gdouble Ae, A3, Ec, A4, lN_r; + gdouble lambda_r, beta_r; + + /* + * The comments refer to the enumerated steps to calculate the + * position of the moon (section 65 of above reference) + */ + t = info->update; + ndays = EPOCH_TO_J2000(t) / 86400.; + sunMeanAnom_d = + fmod(MEAN_ECLIPTIC_LONGITUDE(ndays) - PERIGEE_LONGITUDE(ndays), 360.); + sunEclipLong_r = sunEclipLongitude(t); + moonLong_d = fmod(LUNAR_MEAN_LONGITUDE + (ndays * LUNAR_PROGRESSION), 360.); + /* 5: moon's mean anomaly */ + moonMeanAnom_d = fmod((moonLong_d - (0.1114041 * ndays) - + (LUNAR_PERIGEE_MEAN_LONG + LUNAR_NODE_MEAN_LONG)), + 360.); + /* 6: ascending node mean longitude */ + ascNodeMeanLong_d = fmod(LUNAR_NODE_MEAN_LONG - (0.0529539 * ndays), 360.); + eviction_d = 1.2739 /* 7: eviction */ + * sin(DEGREES_TO_RADIANS( + 2.0 * (moonLong_d - RADIANS_TO_DEGREES(sunEclipLong_r)) - + moonMeanAnom_d)); + sinSunMeanAnom = sin(DEGREES_TO_RADIANS(sunMeanAnom_d)); + Ae = 0.1858 * sinSunMeanAnom; + A3 = 0.37 * sinSunMeanAnom; /* 8: annual equation */ + moonMeanAnom_d += eviction_d - Ae - A3; /* 9: "third correction" */ + moonMeanAnom_r = DEGREES_TO_RADIANS(moonMeanAnom_d); + Ec = 6.2886 * sin(moonMeanAnom_r); /* 10: equation of center */ + A4 = 0.214 * sin(2.0 * moonMeanAnom_r); /* 11: "yet another correction" */ + + /* Steps 12-14 give the true longitude after correcting for variation */ + moonLong_d += eviction_d + Ec - Ae + A4 + + (0.6583 * sin(2.0 * (moonMeanAnom_r - sunEclipLong_r))); + + /* 15: corrected longitude of node */ + corrLong_d = ascNodeMeanLong_d - 0.16 * sinSunMeanAnom; + + /* + * Calculate ecliptic latitude (16-19) and longitude (20) of the moon, + * then convert to right ascension and declination. + */ + lN_r = DEGREES_TO_RADIANS(moonLong_d - corrLong_d); /* l''-N' */ + lambda_r = DEGREES_TO_RADIANS(corrLong_d) + + atan2(sin(lN_r) * cos(LUNAR_INCLINATION), cos(lN_r)); + beta_r = asin(sin(lN_r) * sin(LUNAR_INCLINATION)); + ecl2equ(t, lambda_r, beta_r, &ra_h, &decl_r); + + /* + * The phase is the angle from the sun's longitude to the moon's + */ + info->moonphase = fmod( + 15. * ra_h - RADIANS_TO_DEGREES(sunEclipLongitude(info->update)), 360.); + if (info->moonphase < 0) + info->moonphase += 360; + info->moonlatitude = RADIANS_TO_DEGREES(decl_r); + info->moonValid = TRUE; + + return TRUE; } /** @@ -147,51 +143,48 @@ calc_moon (WeatherInfo *info) * Returns: gboolean indicating success or failure */ -gboolean -calc_moon_phases (WeatherInfo *info, time_t *phases) -{ - WeatherInfo temp; - time_t *ptime; - int idx; - gdouble advance; - int iter; - time_t dtime; - - g_return_val_if_fail (info != NULL && - (info->moonValid || calc_moon (info)), - FALSE); - - ptime = phases; - memset(&temp, 0, sizeof(WeatherInfo)); - - for (idx = 0; idx < 4; idx++) { - temp.update = info->update; - temp.moonphase = info->moonphase; - - /* - * First estimate on how far the moon needs to advance - * to get to the required phase - */ - advance = (idx * 90.) - info->moonphase; - if (advance < 0.) - advance += 360.; - - for (iter = 0; iter < 10; iter++) { - /* Convert angle change (degrees) to dtime (seconds) */ - dtime = advance / LUNAR_PROGRESSION * 86400.; - if ((dtime > -10) && (dtime < 10)) - break; - temp.update += dtime; - (void)calc_moon (&temp); - - if (idx == 0 && temp.moonphase > 180.) { - advance = 360. - temp.moonphase; - } else { - advance = (idx * 90.) - temp.moonphase; - } - } - *ptime++ = temp.update; +gboolean calc_moon_phases(WeatherInfo *info, time_t *phases) { + WeatherInfo temp; + time_t *ptime; + int idx; + gdouble advance; + int iter; + time_t dtime; + + g_return_val_if_fail(info != NULL && (info->moonValid || calc_moon(info)), + FALSE); + + ptime = phases; + memset(&temp, 0, sizeof(WeatherInfo)); + + for (idx = 0; idx < 4; idx++) { + temp.update = info->update; + temp.moonphase = info->moonphase; + + /* + * First estimate on how far the moon needs to advance + * to get to the required phase + */ + advance = (idx * 90.) - info->moonphase; + if (advance < 0.) + advance += 360.; + + for (iter = 0; iter < 10; iter++) { + /* Convert angle change (degrees) to dtime (seconds) */ + dtime = advance / LUNAR_PROGRESSION * 86400.; + if ((dtime > -10) && (dtime < 10)) + break; + temp.update += dtime; + (void)calc_moon(&temp); + + if (idx == 0 && temp.moonphase > 180.) { + advance = 360. - temp.moonphase; + } else { + advance = (idx * 90.) - temp.moonphase; + } } + *ptime++ = temp.update; + } - return TRUE; + return TRUE; } diff --git a/libmateweather/weather-priv.h b/libmateweather/weather-priv.h index 03cdcbd..990ea6e 100644 --- a/libmateweather/weather-priv.h +++ b/libmateweather/weather-priv.h @@ -21,36 +21,38 @@ #include "config.h" -#include <string.h> -#include <time.h> #include <libintl.h> -#include <math.h> #include <libsoup/soup.h> +#include <math.h> +#include <string.h> +#include <time.h> -#include "weather.h" #include "mateweather-location.h" +#include "weather.h" -const char *mateweather_gettext (const char *str) G_GNUC_FORMAT (1); -const char *mateweather_dpgettext (const char *context, const char *str) G_GNUC_FORMAT (2); -#define _(str) (mateweather_gettext (str)) -#define C_(context, str) (mateweather_dpgettext (context, str)) +const char *mateweather_gettext(const char *str) G_GNUC_FORMAT(1); +const char *mateweather_dpgettext(const char *context, const char *str) + G_GNUC_FORMAT(2); +#define _(str) (mateweather_gettext(str)) +#define C_(context, str) (mateweather_dpgettext(context, str)) #define N_(str) (str) -#define xstrnstr(haystack, hlen, needle) \ - memmem(haystack, hlen, needle, strlen(needle)) +#define xstrnstr(haystack, hlen, needle) \ + memmem(haystack, hlen, needle, strlen(needle)) #define WEATHER_LOCATION_CODE_LEN 4 -WeatherLocation *mateweather_location_to_weather_location (MateWeatherLocation *gloc, - const char *name); +WeatherLocation * +mateweather_location_to_weather_location(MateWeatherLocation *gloc, + const char *name); /* * Weather information. */ struct _WeatherConditions { - gboolean significant; - WeatherConditionPhenomenon phenomenon; - WeatherConditionQualifier qualifier; + gboolean significant; + WeatherConditionPhenomenon phenomenon; + WeatherConditionQualifier qualifier; }; typedef struct _WeatherConditions WeatherConditions; @@ -63,126 +65,122 @@ typedef gdouble WeatherVisibility; typedef time_t WeatherUpdate; struct _WeatherInfo { - WeatherForecastType forecast_type; - - TempUnit temperature_unit; - SpeedUnit speed_unit; - PressureUnit pressure_unit; - DistanceUnit distance_unit; - - gboolean valid; - gboolean network_error; - gboolean sunriseValid; - gboolean sunsetValid; - gboolean midnightSun; - gboolean polarNight; - gboolean moonValid; - gboolean tempMinMaxValid; - WeatherLocation *location; - WeatherUpdate update; - WeatherSky sky; - WeatherConditions cond; - WeatherTemperature temp; - WeatherTemperature temp_min; - WeatherTemperature temp_max; - WeatherTemperature dew; - WeatherWindDirection wind; - WeatherWindSpeed windspeed; - WeatherPressure pressure; - WeatherVisibility visibility; - WeatherUpdate sunrise; - WeatherUpdate sunset; - WeatherMoonPhase moonphase; - WeatherMoonLatitude moonlatitude; - gchar *forecast; - GSList *forecast_list; /* list of WeatherInfo* for the forecast, NULL if not available */ - gchar *radar_buffer; - gchar *radar_url; - GdkPixbufAnimation *radar; - SoupSession *session; - gint requests_pending; - - WeatherInfoFunc finish_cb; - gpointer cb_data; + WeatherForecastType forecast_type; + + TempUnit temperature_unit; + SpeedUnit speed_unit; + PressureUnit pressure_unit; + DistanceUnit distance_unit; + + gboolean valid; + gboolean network_error; + gboolean sunriseValid; + gboolean sunsetValid; + gboolean midnightSun; + gboolean polarNight; + gboolean moonValid; + gboolean tempMinMaxValid; + WeatherLocation *location; + WeatherUpdate update; + WeatherSky sky; + WeatherConditions cond; + WeatherTemperature temp; + WeatherTemperature temp_min; + WeatherTemperature temp_max; + WeatherTemperature dew; + WeatherWindDirection wind; + WeatherWindSpeed windspeed; + WeatherPressure pressure; + WeatherVisibility visibility; + WeatherUpdate sunrise; + WeatherUpdate sunset; + WeatherMoonPhase moonphase; + WeatherMoonLatitude moonlatitude; + gchar *forecast; + GSList *forecast_list; /* list of WeatherInfo* for the forecast, NULL if not + available */ + gchar *radar_buffer; + gchar *radar_url; + GdkPixbufAnimation *radar; + SoupSession *session; + gint requests_pending; + + WeatherInfoFunc finish_cb; + gpointer cb_data; }; /* * Enum -> string conversions. */ -const gchar * weather_wind_direction_string (WeatherWindDirection wind); -const gchar * weather_sky_string (WeatherSky sky); -const gchar * weather_conditions_string (WeatherConditions cond); +const gchar *weather_wind_direction_string(WeatherWindDirection wind); +const gchar *weather_sky_string(WeatherSky sky); +const gchar *weather_conditions_string(WeatherConditions cond); /* Values common to the parsing source files */ -#define DATA_SIZE 5000 +#define DATA_SIZE 5000 -#define CONST_DIGITS "0123456789" -#define CONST_ALPHABET "ABCDEFGHIJKLMNOPQRSTUVWXYZ" +#define CONST_DIGITS "0123456789" +#define CONST_ALPHABET "ABCDEFGHIJKLMNOPQRSTUVWXYZ" /* Units conversions and names */ -#define TEMP_F_TO_C(f) (((f) - 32.0) * (5.0/9.0)) -#define TEMP_F_TO_K(f) ((f + 459.67) * (5.0/9.0)) -#define TEMP_C_TO_F(c) (((c) * (9.0/5.0)) + 32.0) +#define TEMP_F_TO_C(f) (((f) - 32.0) * (5.0 / 9.0)) +#define TEMP_F_TO_K(f) ((f + 459.67) * (5.0 / 9.0)) +#define TEMP_C_TO_F(c) (((c) * (9.0 / 5.0)) + 32.0) -#define WINDSPEED_KNOTS_TO_KPH(knots) ((knots) * 1.851965) -#define WINDSPEED_KNOTS_TO_MPH(knots) ((knots) * 1.150779) -#define WINDSPEED_KNOTS_TO_MS(knots) ((knots) * 0.514444) -#define WINDSPEED_MS_TO_KNOTS(ms) ((ms) / 0.514444) +#define WINDSPEED_KNOTS_TO_KPH(knots) ((knots) * 1.851965) +#define WINDSPEED_KNOTS_TO_MPH(knots) ((knots) * 1.150779) +#define WINDSPEED_KNOTS_TO_MS(knots) ((knots) * 0.514444) +#define WINDSPEED_MS_TO_KNOTS(ms) ((ms) / 0.514444) /* 1 bft ~= (1 m/s / 0.836) ^ (2/3) */ -#define WINDSPEED_KNOTS_TO_BFT(knots) (pow ((knots) * 0.615363, 0.666666)) +#define WINDSPEED_KNOTS_TO_BFT(knots) (pow((knots) * 0.615363, 0.666666)) -#define PRESSURE_INCH_TO_KPA(inch) ((inch) * 3.386) -#define PRESSURE_INCH_TO_HPA(inch) ((inch) * 33.86) -#define PRESSURE_INCH_TO_MM(inch) ((inch) * 25.40005) -#define PRESSURE_INCH_TO_MB(inch) (PRESSURE_INCH_TO_HPA (inch)) -#define PRESSURE_INCH_TO_ATM(inch) ((inch) * 0.033421052) -#define PRESSURE_MBAR_TO_INCH(mbar) ((mbar) * 0.029533373) +#define PRESSURE_INCH_TO_KPA(inch) ((inch) * 3.386) +#define PRESSURE_INCH_TO_HPA(inch) ((inch) * 33.86) +#define PRESSURE_INCH_TO_MM(inch) ((inch) * 25.40005) +#define PRESSURE_INCH_TO_MB(inch) (PRESSURE_INCH_TO_HPA(inch)) +#define PRESSURE_INCH_TO_ATM(inch) ((inch) * 0.033421052) +#define PRESSURE_MBAR_TO_INCH(mbar) ((mbar) * 0.029533373) -#define VISIBILITY_SM_TO_KM(sm) ((sm) * 1.609344) -#define VISIBILITY_SM_TO_M(sm) (VISIBILITY_SM_TO_KM (sm) * 1000) +#define VISIBILITY_SM_TO_KM(sm) ((sm) * 1.609344) +#define VISIBILITY_SM_TO_M(sm) (VISIBILITY_SM_TO_KM(sm) * 1000) -#define DEGREES_TO_RADIANS(deg) ((fmod ((deg),360.) / 180.) * M_PI) -#define RADIANS_TO_DEGREES(rad) ((rad) * 180. / M_PI) -#define RADIANS_TO_HOURS(rad) ((rad) * 12. / M_PI) +#define DEGREES_TO_RADIANS(deg) ((fmod((deg), 360.) / 180.) * M_PI) +#define RADIANS_TO_DEGREES(rad) ((rad) * 180. / M_PI) +#define RADIANS_TO_HOURS(rad) ((rad) * 12. / M_PI) /* * Planetary Mean Orbit and their progressions from J2000 are based on the * values in http://ssd.jpl.nasa.gov/txt/aprx_pos_planets.pdf * converting longitudes from heliocentric to geocentric coordinates (+180) */ -#define EPOCH_TO_J2000(t) ((gdouble)(t)-946727935.816) -#define MEAN_ECLIPTIC_LONGITUDE(d) (280.46457166 + (d)/36525.*35999.37244981) -#define SOL_PROGRESSION (360./365.242191) -#define PERIGEE_LONGITUDE(d) (282.93768193 + (d)/36525.*0.32327364) - -void metar_start_open (WeatherInfo *info); -void iwin_start_open (WeatherInfo *info); -void metoffice_start_open (WeatherInfo *info); -void bom_start_open (WeatherInfo *info); -void wx_start_open (WeatherInfo *info); - -gboolean metar_parse (gchar *metar, - WeatherInfo *info); - -gboolean requests_init (WeatherInfo *info); -void request_done (WeatherInfo *info, - GError *error); - -void ecl2equ (gdouble t, - gdouble eclipLon, - gdouble eclipLat, - gdouble *ra, - gdouble *decl); -gdouble sunEclipLongitude (time_t t); -gboolean calc_sun (WeatherInfo *info); -gboolean calc_sun_time (WeatherInfo *info, time_t t); -gboolean calc_moon (WeatherInfo *info); -gboolean calc_moon_phases (WeatherInfo *info, time_t *phases); - -void free_forecast_list (WeatherInfo *info); +#define EPOCH_TO_J2000(t) ((gdouble)(t) - 946727935.816) +#define MEAN_ECLIPTIC_LONGITUDE(d) \ + (280.46457166 + (d) / 36525. * 35999.37244981) +#define SOL_PROGRESSION (360. / 365.242191) +#define PERIGEE_LONGITUDE(d) (282.93768193 + (d) / 36525. * 0.32327364) -#endif /* __WEATHER_PRIV_H_ */ +void metar_start_open(WeatherInfo *info); +void iwin_start_open(WeatherInfo *info); +void metoffice_start_open(WeatherInfo *info); +void bom_start_open(WeatherInfo *info); +void wx_start_open(WeatherInfo *info); + +gboolean metar_parse(gchar *metar, WeatherInfo *info); + +gboolean requests_init(WeatherInfo *info); +void request_done(WeatherInfo *info, GError *error); +void ecl2equ(gdouble t, gdouble eclipLon, gdouble eclipLat, gdouble *ra, + gdouble *decl); +gdouble sunEclipLongitude(time_t t); +gboolean calc_sun(WeatherInfo *info); +gboolean calc_sun_time(WeatherInfo *info, time_t t); +gboolean calc_moon(WeatherInfo *info); +gboolean calc_moon_phases(WeatherInfo *info, time_t *phases); + +void free_forecast_list(WeatherInfo *info); + +#endif /* __WEATHER_PRIV_H_ */ diff --git a/libmateweather/weather-sun.c b/libmateweather/weather-sun.c index 3db5526..e7ff1fd 100644 --- a/libmateweather/weather-sun.c +++ b/libmateweather/weather-sun.c @@ -28,66 +28,59 @@ #include <config.h> #endif +#include <glib.h> #include <math.h> #include <time.h> -#include <glib.h> #define MATEWEATHER_I_KNOW_THIS_IS_UNSTABLE #include "weather-priv.h" -#define ECCENTRICITY(d) (0.01671123 - (d)/36525.*0.00004392) +#define ECCENTRICITY(d) (0.01671123 - (d) / 36525. * 0.00004392) /* * Ecliptic longitude of the sun at specified time (UT) * The algoithm is described in section 47 of Duffett-Smith * Return value is in radians */ -gdouble -sunEclipLongitude(time_t t) -{ - gdouble ndays, meanAnom, eccenAnom, delta, e, longitude; - - /* - * Start with an estimate based on a fixed daily rate - */ - ndays = EPOCH_TO_J2000(t) / 86400.; - meanAnom = DEGREES_TO_RADIANS(MEAN_ECLIPTIC_LONGITUDE(ndays) - - PERIGEE_LONGITUDE(ndays)); - - /* - * Approximate solution of Kepler's equation: - * Find E which satisfies E - e sin(E) = M (mean anomaly) - */ - eccenAnom = meanAnom; - e = ECCENTRICITY(ndays); - - while (1e-12 < fabs( delta = eccenAnom - e * sin(eccenAnom) - meanAnom)) - { - eccenAnom -= delta / (1.- e * cos(eccenAnom)); - } - - /* - * Earth's longitude on the ecliptic - */ - longitude = fmod( DEGREES_TO_RADIANS (PERIGEE_LONGITUDE(ndays)) - + 2. * atan (sqrt ((1.+e)/(1.-e)) - * tan (eccenAnom / 2.)), - 2. * M_PI); - if (longitude < 0.) { - longitude += 2 * M_PI; - } - return longitude; +gdouble sunEclipLongitude(time_t t) { + gdouble ndays, meanAnom, eccenAnom, delta, e, longitude; + + /* + * Start with an estimate based on a fixed daily rate + */ + ndays = EPOCH_TO_J2000(t) / 86400.; + meanAnom = DEGREES_TO_RADIANS(MEAN_ECLIPTIC_LONGITUDE(ndays) - + PERIGEE_LONGITUDE(ndays)); + + /* + * Approximate solution of Kepler's equation: + * Find E which satisfies E - e sin(E) = M (mean anomaly) + */ + eccenAnom = meanAnom; + e = ECCENTRICITY(ndays); + + while (1e-12 < fabs(delta = eccenAnom - e * sin(eccenAnom) - meanAnom)) { + eccenAnom -= delta / (1. - e * cos(eccenAnom)); + } + + /* + * Earth's longitude on the ecliptic + */ + longitude = + fmod(DEGREES_TO_RADIANS(PERIGEE_LONGITUDE(ndays)) + + 2. * atan(sqrt((1. + e) / (1. - e)) * tan(eccenAnom / 2.)), + 2. * M_PI); + if (longitude < 0.) { + longitude += 2 * M_PI; + } + return longitude; } -static gdouble -ecliptic_obliquity (gdouble time) -{ - gdouble jc = EPOCH_TO_J2000 (time) / (36525. * 86400.); - gdouble eclip_secs = (84381.448 - - (46.84024 * jc) - - (59.e-5 * jc * jc) - + (1.813e-3 * jc * jc * jc)); - return DEGREES_TO_RADIANS(eclip_secs / 3600.); +static gdouble ecliptic_obliquity(gdouble time) { + gdouble jc = EPOCH_TO_J2000(time) / (36525. * 86400.); + gdouble eclip_secs = (84381.448 - (46.84024 * jc) - (59.e-5 * jc * jc) + + (1.813e-3 * jc * jc * jc)); + return DEGREES_TO_RADIANS(eclip_secs / 3600.); } /* @@ -95,24 +88,21 @@ ecliptic_obliquity (gdouble time) * coordinates, expressed as right ascension (hours) and * declination (radians) */ -void -ecl2equ (gdouble time, - gdouble eclipLon, gdouble eclipLat, - gdouble *ra, gdouble *decl) -{ - gdouble mEclipObliq = ecliptic_obliquity(time); - - if (ra) { - *ra = RADIANS_TO_HOURS (atan2 ((sin (eclipLon) * cos (mEclipObliq) - - tan (eclipLat) * sin(mEclipObliq)), - cos (eclipLon))); - if (*ra < 0.) - *ra += 24.; - } - if (decl) { - *decl = asin (( sin (eclipLat) * cos (mEclipObliq)) - + cos (eclipLat) * sin (mEclipObliq) * sin(eclipLon)); - } +void ecl2equ(gdouble time, gdouble eclipLon, gdouble eclipLat, gdouble *ra, + gdouble *decl) { + gdouble mEclipObliq = ecliptic_obliquity(time); + + if (ra) { + *ra = RADIANS_TO_HOURS(atan2( + (sin(eclipLon) * cos(mEclipObliq) - tan(eclipLat) * sin(mEclipObliq)), + cos(eclipLon))); + if (*ra < 0.) + *ra += 24.; + } + if (decl) { + *decl = asin((sin(eclipLat) * cos(mEclipObliq)) + + cos(eclipLat) * sin(mEclipObliq) * sin(eclipLon)); + } } /* @@ -120,167 +110,159 @@ ecl2equ (gdouble time, * based on it equitorial coordinates (section 33 & 15) * Returned "rise" and "set" values are sideral times in hours */ -static void -gstObsv (gdouble ra, gdouble decl, - gdouble obsLat, gdouble obsLon, - gdouble *rise, gdouble *set) -{ - double a = acos (-tan (obsLat) * tan (decl)); - double b; - - if (isnan (a) != 0) { - *set = *rise = a; - return; - } - a = RADIANS_TO_HOURS (a); - b = 24. - a + ra; - a += ra; - a -= RADIANS_TO_HOURS (obsLon); - b -= RADIANS_TO_HOURS (obsLon); - if ((a = fmod (a, 24.)) < 0) - a += 24.; - if ((b = fmod (b, 24.)) < 0) - b += 24.; - - *set = a; - *rise = b; +static void gstObsv(gdouble ra, gdouble decl, gdouble obsLat, gdouble obsLon, + gdouble *rise, gdouble *set) { + double a = acos(-tan(obsLat) * tan(decl)); + double b; + + if (isnan(a) != 0) { + *set = *rise = a; + return; + } + a = RADIANS_TO_HOURS(a); + b = 24. - a + ra; + a += ra; + a -= RADIANS_TO_HOURS(obsLon); + b -= RADIANS_TO_HOURS(obsLon); + if ((a = fmod(a, 24.)) < 0) + a += 24.; + if ((b = fmod(b, 24.)) < 0) + b += 24.; + + *set = a; + *rise = b; } -static gdouble -t0 (time_t date) -{ - gdouble t = ((gdouble)(EPOCH_TO_J2000 (date) / 86400)) / 36525.0; - gdouble t0 = fmod (6.697374558 + 2400.051366 * t + 2.5862e-5 * t * t, 24.); - if (t0 < 0.) - t0 += 24.; - return t0; +static gdouble t0(time_t date) { + gdouble t = ((gdouble)(EPOCH_TO_J2000(date) / 86400)) / 36525.0; + gdouble t0 = fmod(6.697374558 + 2400.051366 * t + 2.5862e-5 * t * t, 24.); + if (t0 < 0.) + t0 += 24.; + return t0; } -static gboolean -calc_sun2 (WeatherInfo *info, time_t t) -{ - gdouble obsLat = info->location->latitude; - gdouble obsLon = info->location->longitude; - time_t gm_midn; - time_t lcl_midn; - gdouble gm_hoff, lambda; - gdouble ra1, ra2; - gdouble decl1, decl2; - gdouble decl_midn, decl_noon; - gdouble rise1, rise2; - gdouble set1, set2; - gdouble tt, t00; - gdouble x, u, dt; - - /* Approximate preceding local midnight at observer's longitude */ - obsLat = info->location->latitude; - obsLon = info->location->longitude; - gm_midn = t - (t % 86400); - gm_hoff = floor ((RADIANS_TO_DEGREES (obsLon) + 7.5) / 15.); - lcl_midn = gm_midn - 3600. * gm_hoff; - if (t - lcl_midn >= 86400) - lcl_midn += 86400; - else if (lcl_midn > t) - lcl_midn -= 86400; - - lambda = sunEclipLongitude (lcl_midn); - - /* - * Calculate equitorial coordinates of sun at previous - * and next local midnights - */ - ecl2equ (lcl_midn, lambda, 0., &ra1, &decl1); - ecl2equ (lcl_midn + 86400., - lambda + DEGREES_TO_RADIANS(SOL_PROGRESSION), 0., - &ra2, &decl2); - - /* - * If the observer is within the Arctic or Antarctic Circles then - * the sun may be above or below the horizon for the full day. - */ - decl_midn = MIN(decl1,decl2); - decl_noon = (decl1+decl2)/2.; - info->midnightSun = - (obsLat > (M_PI/2.-decl_midn)) || (obsLat < (-M_PI/2.-decl_midn)); - info->polarNight = - (obsLat > (M_PI/2.+decl_noon)) || (obsLat < (-M_PI/2.+decl_noon)); - if (info->midnightSun || info->polarNight) { - info->sunriseValid = info->sunsetValid = FALSE; - return FALSE; - } - - /* - * Convert to rise and set times based positions for the preceding - * and following local midnights. - */ - gstObsv (ra1, decl1, obsLat, obsLon - (gm_hoff * M_PI / 12.), &rise1, &set1); - gstObsv (ra2, decl2, obsLat, obsLon - (gm_hoff * M_PI / 12.), &rise2, &set2); - - /* TODO: include calculations for regions near the poles. */ - if (isnan(rise1) || isnan(rise2)) { - info->sunriseValid = info->sunsetValid = FALSE; - return FALSE; - } - - if (rise2 < rise1) { - rise2 += 24.; - } - if (set2 < set1) { - set2 += 24.; - } - - tt = t0(lcl_midn); - t00 = tt - (gm_hoff + RADIANS_TO_HOURS(obsLon)) * 1.002737909; - - if (t00 < 0.) - t00 += 24.; - - if (rise1 < t00) { - rise1 += 24.; - rise2 += 24.; - } - if (set1 < t00) { - set1 += 24.; - set2 += 24.; - } - - /* - * Interpolate between the two to get a rise and set time - * based on the sun's position at local noon (step 8) - */ - rise1 = (24.07 * rise1 - t00 * (rise2 - rise1)) / (24.07 + rise1 - rise2); - set1 = (24.07 * set1 - t00 * (set2 - set1)) / (24.07 + set1 - set2); - - /* - * Calculate an adjustment value to account for parallax, - * refraction and the Sun's finite diameter (steps 9,10) - */ - decl2 = (decl1 + decl2) / 2.; - x = DEGREES_TO_RADIANS(0.830725); - u = acos ( sin(obsLat) / cos(decl2) ); - dt = RADIANS_TO_HOURS ( asin ( sin(x) / sin(u) ) / cos(decl2) ); - - /* - * Subtract the correction value from sunrise and add to sunset, - * then (step 11) convert sideral times to UT - */ - rise1 = (rise1 - dt - tt) * 0.9972695661; - if (rise1 < 0.) - rise1 += 24; - else if (rise1 >= 24.) - rise1 -= 24.; - info->sunriseValid = ((rise1 >= 0.) && (rise1 < 24.)); - info->sunrise = (rise1 * 3600.) + lcl_midn; - - set1 = (set1 + dt - tt) * 0.9972695661; - if (set1 < 0.) - set1 += 24; - else if (set1 >= 24.) - set1 -= 24.; - info->sunsetValid = ((set1 >= 0.) && (set1 < 24.)); - info->sunset = (set1 * 3600.) + lcl_midn; - - return (info->sunriseValid || info->sunsetValid); +static gboolean calc_sun2(WeatherInfo *info, time_t t) { + gdouble obsLat = info->location->latitude; + gdouble obsLon = info->location->longitude; + time_t gm_midn; + time_t lcl_midn; + gdouble gm_hoff, lambda; + gdouble ra1, ra2; + gdouble decl1, decl2; + gdouble decl_midn, decl_noon; + gdouble rise1, rise2; + gdouble set1, set2; + gdouble tt, t00; + gdouble x, u, dt; + + /* Approximate preceding local midnight at observer's longitude */ + obsLat = info->location->latitude; + obsLon = info->location->longitude; + gm_midn = t - (t % 86400); + gm_hoff = floor((RADIANS_TO_DEGREES(obsLon) + 7.5) / 15.); + lcl_midn = gm_midn - 3600. * gm_hoff; + if (t - lcl_midn >= 86400) + lcl_midn += 86400; + else if (lcl_midn > t) + lcl_midn -= 86400; + + lambda = sunEclipLongitude(lcl_midn); + + /* + * Calculate equitorial coordinates of sun at previous + * and next local midnights + */ + ecl2equ(lcl_midn, lambda, 0., &ra1, &decl1); + ecl2equ(lcl_midn + 86400., lambda + DEGREES_TO_RADIANS(SOL_PROGRESSION), 0., + &ra2, &decl2); + + /* + * If the observer is within the Arctic or Antarctic Circles then + * the sun may be above or below the horizon for the full day. + */ + decl_midn = MIN(decl1, decl2); + decl_noon = (decl1 + decl2) / 2.; + info->midnightSun = + (obsLat > (M_PI / 2. - decl_midn)) || (obsLat < (-M_PI / 2. - decl_midn)); + info->polarNight = + (obsLat > (M_PI / 2. + decl_noon)) || (obsLat < (-M_PI / 2. + decl_noon)); + if (info->midnightSun || info->polarNight) { + info->sunriseValid = info->sunsetValid = FALSE; + return FALSE; + } + + /* + * Convert to rise and set times based positions for the preceding + * and following local midnights. + */ + gstObsv(ra1, decl1, obsLat, obsLon - (gm_hoff * M_PI / 12.), &rise1, &set1); + gstObsv(ra2, decl2, obsLat, obsLon - (gm_hoff * M_PI / 12.), &rise2, &set2); + + /* TODO: include calculations for regions near the poles. */ + if (isnan(rise1) || isnan(rise2)) { + info->sunriseValid = info->sunsetValid = FALSE; + return FALSE; + } + + if (rise2 < rise1) { + rise2 += 24.; + } + if (set2 < set1) { + set2 += 24.; + } + + tt = t0(lcl_midn); + t00 = tt - (gm_hoff + RADIANS_TO_HOURS(obsLon)) * 1.002737909; + + if (t00 < 0.) + t00 += 24.; + + if (rise1 < t00) { + rise1 += 24.; + rise2 += 24.; + } + if (set1 < t00) { + set1 += 24.; + set2 += 24.; + } + + /* + * Interpolate between the two to get a rise and set time + * based on the sun's position at local noon (step 8) + */ + rise1 = (24.07 * rise1 - t00 * (rise2 - rise1)) / (24.07 + rise1 - rise2); + set1 = (24.07 * set1 - t00 * (set2 - set1)) / (24.07 + set1 - set2); + + /* + * Calculate an adjustment value to account for parallax, + * refraction and the Sun's finite diameter (steps 9,10) + */ + decl2 = (decl1 + decl2) / 2.; + x = DEGREES_TO_RADIANS(0.830725); + u = acos(sin(obsLat) / cos(decl2)); + dt = RADIANS_TO_HOURS(asin(sin(x) / sin(u)) / cos(decl2)); + + /* + * Subtract the correction value from sunrise and add to sunset, + * then (step 11) convert sideral times to UT + */ + rise1 = (rise1 - dt - tt) * 0.9972695661; + if (rise1 < 0.) + rise1 += 24; + else if (rise1 >= 24.) + rise1 -= 24.; + info->sunriseValid = ((rise1 >= 0.) && (rise1 < 24.)); + info->sunrise = (rise1 * 3600.) + lcl_midn; + + set1 = (set1 + dt - tt) * 0.9972695661; + if (set1 < 0.) + set1 += 24; + else if (set1 >= 24.) + set1 -= 24.; + info->sunsetValid = ((set1 >= 0.) && (set1 < 24.)); + info->sunset = (set1 * 3600.) + lcl_midn; + + return (info->sunriseValid || info->sunsetValid); } /** @@ -291,10 +273,8 @@ calc_sun2 (WeatherInfo *info, time_t t) * * Returns: gboolean indicating if the results are valid. */ -gboolean -calc_sun_time (WeatherInfo *info, time_t t) -{ - return info->location->latlon_valid && calc_sun2 (info, t); +gboolean calc_sun_time(WeatherInfo *info, time_t t) { + return info->location->latlon_valid && calc_sun2(info, t); } /** @@ -304,11 +284,7 @@ calc_sun_time (WeatherInfo *info, time_t t) * * Returns: gboolean indicating if the results are valid. */ -gboolean -calc_sun (WeatherInfo *info) -{ - return calc_sun_time(info, time(NULL)); -} +gboolean calc_sun(WeatherInfo *info) { return calc_sun_time(info, time(NULL)); } /** * weather_info_next_sun_event: @@ -319,31 +295,27 @@ calc_sun (WeatherInfo *info) * - next sunrise, when icon changes to daytime version * - next sunset, when icon changes to nighttime version */ -gint -weather_info_next_sun_event (WeatherInfo *info) -{ - time_t now = time (NULL); - struct tm ltm; - time_t nxtEvent; - - g_return_val_if_fail (info != NULL, -1); - - if (!calc_sun (info)) - return -1; - - /* Determine when the next local midnight occurs */ - (void) localtime_r (&now, <m); - ltm.tm_sec = 0; - ltm.tm_min = 0; - ltm.tm_hour = 0; - ltm.tm_mday++; - nxtEvent = mktime (<m); - - if (info->sunsetValid && - (info->sunset > now) && (info->sunset < nxtEvent)) - nxtEvent = info->sunset; - if (info->sunriseValid && - (info->sunrise > now) && (info->sunrise < nxtEvent)) - nxtEvent = info->sunrise; - return (gint)(nxtEvent - now); +gint weather_info_next_sun_event(WeatherInfo *info) { + time_t now = time(NULL); + struct tm ltm; + time_t nxtEvent; + + g_return_val_if_fail(info != NULL, -1); + + if (!calc_sun(info)) + return -1; + + /* Determine when the next local midnight occurs */ + (void)localtime_r(&now, <m); + ltm.tm_sec = 0; + ltm.tm_min = 0; + ltm.tm_hour = 0; + ltm.tm_mday++; + nxtEvent = mktime(<m); + + if (info->sunsetValid && (info->sunset > now) && (info->sunset < nxtEvent)) + nxtEvent = info->sunset; + if (info->sunriseValid && (info->sunrise > now) && (info->sunrise < nxtEvent)) + nxtEvent = info->sunrise; + return (gint)(nxtEvent - now); } diff --git a/libmateweather/weather-wx.c b/libmateweather/weather-wx.c index 11f7336..a987d6d 100644 --- a/libmateweather/weather-wx.c +++ b/libmateweather/weather-wx.c @@ -21,88 +21,84 @@ #endif #define MATEWEATHER_I_KNOW_THIS_IS_UNSTABLE -#include "weather.h" #include "weather-priv.h" +#include "weather.h" -static void -wx_finish (GObject *source, GAsyncResult *result, gpointer data) -{ - WeatherInfo *info = (WeatherInfo *)data; - GdkPixbufAnimation *animation; - GError *error = NULL; - - g_return_if_fail (info != NULL); - - animation = gdk_pixbuf_animation_new_from_stream_finish (result, &error); - - if (error != NULL) { - g_warning ("Failed to get radar map image: %s.\n", error->message); - request_done (info, error); - g_error_free (error); - return; - } - if (animation != NULL) { - if (info->radar) - g_object_unref (info->radar); - info->radar = animation; - g_object_ref (info->radar); - } - - request_done (info, NULL); +static void wx_finish(GObject *source, GAsyncResult *result, gpointer data) { + WeatherInfo *info = (WeatherInfo *)data; + GdkPixbufAnimation *animation; + GError *error = NULL; + + g_return_if_fail(info != NULL); + + animation = gdk_pixbuf_animation_new_from_stream_finish(result, &error); + + if (error != NULL) { + g_warning("Failed to get radar map image: %s.\n", error->message); + request_done(info, error); + g_error_free(error); + return; + } + if (animation != NULL) { + if (info->radar) + g_object_unref(info->radar); + info->radar = animation; + g_object_ref(info->radar); + } + + request_done(info, NULL); } -static void -wx_got_chunk (GObject *source, GAsyncResult *result, gpointer data) -{ - WeatherInfo *info = (WeatherInfo *)data; - GError *error = NULL; - GInputStream *istream; +static void wx_got_chunk(GObject *source, GAsyncResult *result, gpointer data) { + WeatherInfo *info = (WeatherInfo *)data; + GError *error = NULL; + GInputStream *istream; - g_return_if_fail (info != NULL); + g_return_if_fail(info != NULL); - istream = soup_session_send_finish (SOUP_SESSION (source), result, &error); + istream = soup_session_send_finish(SOUP_SESSION(source), result, &error); - if (error != NULL) { - g_warning ("Failed to get radar map image: %s.\n", error->message); - g_error_free (error); - request_done (info, error); - return; - } + if (error != NULL) { + g_warning("Failed to get radar map image: %s.\n", error->message); + g_error_free(error); + request_done(info, error); + return; + } - gdk_pixbuf_animation_new_from_stream_async (istream, NULL, wx_finish, data); + gdk_pixbuf_animation_new_from_stream_async(istream, NULL, wx_finish, data); } /* Get radar map and into newly allocated pixmap */ -void -wx_start_open (WeatherInfo *info) -{ - gchar *url; - SoupMessage *msg; - WeatherLocation *loc; - - g_return_if_fail (info != NULL); - info->radar = NULL; - loc = info->location; - g_return_if_fail (loc != NULL); - - if (info->radar_url) - url = g_strdup (info->radar_url); - else { - if (loc->radar[0] == '-') - return; - url = g_strdup_printf ("http://image.weather.com/web/radar/us_%s_closeradar_medium_usen.jpg", loc->radar); - } - - msg = soup_message_new ("GET", url); - if (!msg) { - g_warning ("Invalid radar URL: %s\n", url); - g_free (url); - return; - } - - soup_session_send_async (info->session, msg, G_PRIORITY_DEFAULT, NULL, - wx_got_chunk, info); - g_free (url); - - info->requests_pending++; +void wx_start_open(WeatherInfo *info) { + gchar *url; + SoupMessage *msg; + WeatherLocation *loc; + + g_return_if_fail(info != NULL); + info->radar = NULL; + loc = info->location; + g_return_if_fail(loc != NULL); + + if (info->radar_url) + url = g_strdup(info->radar_url); + else { + if (loc->radar[0] == '-') + return; + url = g_strdup_printf( + "http://image.weather.com/web/radar/us_%s_closeradar_medium_usen.jpg", + loc->radar); + } + + msg = soup_message_new("GET", url); + if (!msg) { + g_warning("Invalid radar URL: %s\n", url); + g_free(url); + return; + } + + soup_session_send_async(info->session, msg, G_PRIORITY_DEFAULT, NULL, + wx_got_chunk, info); + g_free(url); + + info->requests_pending++; } diff --git a/libmateweather/weather.c b/libmateweather/weather.c index 1d7533a..61a0313 100644 --- a/libmateweather/weather.c +++ b/libmateweather/weather.c @@ -20,13 +20,13 @@ #include <config.h> #endif -#include <stdio.h> -#include <stdlib.h> #include <assert.h> -#include <string.h> #include <ctype.h> -#include <math.h> #include <fenv.h> +#include <math.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> #ifdef HAVE_VALUES_H #include <values.h> @@ -38,8 +38,8 @@ #include <gdk-pixbuf/gdk-pixbuf.h> #define MATEWEATHER_I_KNOW_THIS_IS_UNSTABLE -#include "weather.h" #include "weather-priv.h" +#include "weather.h" #define MOON_PHASES 36 @@ -48,35 +48,28 @@ * @Title: weather */ -static void _weather_internal_check (void); +static void _weather_internal_check(void); -static inline void -mateweather_gettext_init (void) -{ - static gsize mateweather_gettext_initialized = FALSE; +static inline void mateweather_gettext_init(void) { + static gsize mateweather_gettext_initialized = FALSE; - if (G_UNLIKELY (g_once_init_enter (&mateweather_gettext_initialized))) { - bindtextdomain (GETTEXT_PACKAGE, MATELOCALEDIR); + if (G_UNLIKELY(g_once_init_enter(&mateweather_gettext_initialized))) { + bindtextdomain(GETTEXT_PACKAGE, MATELOCALEDIR); #ifdef HAVE_BIND_TEXTDOMAIN_CODESET - bind_textdomain_codeset (GETTEXT_PACKAGE, "UTF-8"); + bind_textdomain_codeset(GETTEXT_PACKAGE, "UTF-8"); #endif - g_once_init_leave (&mateweather_gettext_initialized, TRUE); - } + g_once_init_leave(&mateweather_gettext_initialized, TRUE); + } } -const char * -mateweather_gettext (const char *str) -{ - mateweather_gettext_init (); - return dgettext (GETTEXT_PACKAGE, str); +const char *mateweather_gettext(const char *str) { + mateweather_gettext_init(); + return dgettext(GETTEXT_PACKAGE, str); } -const char * -mateweather_dpgettext (const char *context, - const char *str) -{ - mateweather_gettext_init (); - return g_dpgettext2 (GETTEXT_PACKAGE, context, str); +const char *mateweather_dpgettext(const char *context, const char *str) { + mateweather_gettext_init(); + return g_dpgettext2(GETTEXT_PACKAGE, context, str); } /* @@ -84,186 +77,169 @@ mateweather_dpgettext (const char *context, * DD:degrees (to 3 digits), MM:minutes, SS:seconds H:hemisphere (NESW) * Return value is positive for N,E; negative for S,W. */ -static gdouble -dmsh2rad (const gchar *latlon) -{ - char *p1, *p2; - int deg, min, sec, dir; - gdouble value; - - if (latlon == NULL) - return DBL_MAX; - p1 = strchr (latlon, '-'); - p2 = strrchr (latlon, '-'); - if (p1 == NULL || p1 == latlon) { - return DBL_MAX; - } else if (p1 == p2) { - sscanf (latlon, "%d-%d", °, &min); - sec = 0; - } else if (p2 == 1 + p1) { - return DBL_MAX; - } else { - sscanf (latlon, "%d-%d-%d", °, &min, &sec); - } - if (deg > 180 || min >= 60 || sec >= 60) - return DBL_MAX; - value = (gdouble)((deg * 60 + min) * 60 + sec) * M_PI / 648000.; - - dir = g_ascii_toupper (latlon[strlen (latlon) - 1]); - if (dir == 'W' || dir == 'S') - value = -value; - else if (dir != 'E' && dir != 'N' && (value != 0.0 || dir != '0')) - value = DBL_MAX; - return value; -} - -WeatherLocation * -weather_location_new (const gchar *name, const gchar *code, - const gchar *zone, const gchar *radar, - const gchar *coordinates, - const gchar *country_code, - const gchar *tz_hint) -{ - WeatherLocation *location; - - _weather_internal_check (); - - location = g_new (WeatherLocation, 1); - - /* name and metar code must be set */ - location->name = g_strdup (name); - location->code = g_strdup (code); - - if (zone) { - location->zone = g_strdup (zone); - } else { - location->zone = g_strdup ("------"); - } - - if (radar) { - location->radar = g_strdup (radar); - } else { - location->radar = g_strdup ("---"); +static gdouble dmsh2rad(const gchar *latlon) { + char *p1, *p2; + int deg, min, sec, dir; + gdouble value; + + if (latlon == NULL) + return DBL_MAX; + p1 = strchr(latlon, '-'); + p2 = strrchr(latlon, '-'); + if (p1 == NULL || p1 == latlon) { + return DBL_MAX; + } else if (p1 == p2) { + sscanf(latlon, "%d-%d", °, &min); + sec = 0; + } else if (p2 == 1 + p1) { + return DBL_MAX; + } else { + sscanf(latlon, "%d-%d-%d", °, &min, &sec); + } + if (deg > 180 || min >= 60 || sec >= 60) + return DBL_MAX; + value = (gdouble)((deg * 60 + min) * 60 + sec) * M_PI / 648000.; + + dir = g_ascii_toupper(latlon[strlen(latlon) - 1]); + if (dir == 'W' || dir == 'S') + value = -value; + else if (dir != 'E' && dir != 'N' && (value != 0.0 || dir != '0')) + value = DBL_MAX; + return value; +} + +WeatherLocation *weather_location_new(const gchar *name, const gchar *code, + const gchar *zone, const gchar *radar, + const gchar *coordinates, + const gchar *country_code, + const gchar *tz_hint) { + WeatherLocation *location; + + _weather_internal_check(); + + location = g_new(WeatherLocation, 1); + + /* name and metar code must be set */ + location->name = g_strdup(name); + location->code = g_strdup(code); + + if (zone) { + location->zone = g_strdup(zone); + } else { + location->zone = g_strdup("------"); + } + + if (radar) { + location->radar = g_strdup(radar); + } else { + location->radar = g_strdup("---"); + } + + if (location->zone[0] == '-') { + location->zone_valid = FALSE; + } else { + location->zone_valid = TRUE; + } + + location->coordinates = NULL; + if (coordinates) { + char **pieces; + + pieces = g_strsplit(coordinates, " ", -1); + + if (g_strv_length(pieces) == 2) { + location->coordinates = g_strdup(coordinates); + location->latitude = dmsh2rad(pieces[0]); + location->longitude = dmsh2rad(pieces[1]); } - if (location->zone[0] == '-') { - location->zone_valid = FALSE; - } else { - location->zone_valid = TRUE; - } + g_strfreev(pieces); + } - location->coordinates = NULL; - if (coordinates) - { - char **pieces; + if (!location->coordinates) { + location->coordinates = g_strdup("---"); + location->latitude = DBL_MAX; + location->longitude = DBL_MAX; + } - pieces = g_strsplit (coordinates, " ", -1); + location->latlon_valid = + (location->latitude < DBL_MAX && location->longitude < DBL_MAX); - if (g_strv_length (pieces) == 2) - { - location->coordinates = g_strdup (coordinates); - location->latitude = dmsh2rad (pieces[0]); - location->longitude = dmsh2rad (pieces[1]); - } - - g_strfreev (pieces); - } + location->country_code = g_strdup(country_code); + location->tz_hint = g_strdup(tz_hint); - if (!location->coordinates) - { - location->coordinates = g_strdup ("---"); - location->latitude = DBL_MAX; - location->longitude = DBL_MAX; - } - - location->latlon_valid = (location->latitude < DBL_MAX && location->longitude < DBL_MAX); - - location->country_code = g_strdup (country_code); - location->tz_hint = g_strdup (tz_hint); - - return location; + return location; } -WeatherLocation * -weather_location_clone (const WeatherLocation *location) -{ - WeatherLocation *clone; +WeatherLocation *weather_location_clone(const WeatherLocation *location) { + WeatherLocation *clone; - g_return_val_if_fail (location != NULL, NULL); + g_return_val_if_fail(location != NULL, NULL); - clone = weather_location_new (location->name, - location->code, location->zone, - location->radar, location->coordinates, - location->country_code, location->tz_hint); - clone->latitude = location->latitude; - clone->longitude = location->longitude; - clone->latlon_valid = location->latlon_valid; - return clone; + clone = weather_location_new(location->name, location->code, location->zone, + location->radar, location->coordinates, + location->country_code, location->tz_hint); + clone->latitude = location->latitude; + clone->longitude = location->longitude; + clone->latlon_valid = location->latlon_valid; + return clone; } -void -weather_location_free (WeatherLocation *location) -{ - if (location) { - g_free (location->name); - g_free (location->code); - g_free (location->zone); - g_free (location->radar); - g_free (location->coordinates); - g_free (location->country_code); - g_free (location->tz_hint); +void weather_location_free(WeatherLocation *location) { + if (location) { + g_free(location->name); + g_free(location->code); + g_free(location->zone); + g_free(location->radar); + g_free(location->coordinates); + g_free(location->country_code); + g_free(location->tz_hint); - g_free (location); - } + g_free(location); + } } -gboolean -weather_location_equal (const WeatherLocation *location1, const WeatherLocation *location2) -{ - /* if something is NULL, then it's TRUE if and only if both are NULL) */ - if (location1 == NULL || location2 == NULL) - return (location1 == location2); - if (!location1->code || !location2->code) - return (location1->code == location2->code); - if (!location1->name || !location2->name) - return (location1->name == location2->name); +gboolean weather_location_equal(const WeatherLocation *location1, + const WeatherLocation *location2) { + /* if something is NULL, then it's TRUE if and only if both are NULL) */ + if (location1 == NULL || location2 == NULL) + return (location1 == location2); + if (!location1->code || !location2->code) + return (location1->code == location2->code); + if (!location1->name || !location2->name) + return (location1->name == location2->name); - return ((strcmp (location1->code, location2->code) == 0) && - (strcmp (location1->name, location2->name) == 0)); + return ((strcmp(location1->code, location2->code) == 0) && + (strcmp(location1->name, location2->name) == 0)); } static const gchar *wind_direction_str[] = { - N_("Variable"), - N_("North"), N_("North - NorthEast"), N_("Northeast"), N_("East - NorthEast"), - N_("East"), N_("East - Southeast"), N_("Southeast"), N_("South - Southeast"), - N_("South"), N_("South - Southwest"), N_("Southwest"), N_("West - Southwest"), - N_("West"), N_("West - Northwest"), N_("Northwest"), N_("North - Northwest") -}; + N_("Variable"), N_("North"), + N_("North - NorthEast"), N_("Northeast"), + N_("East - NorthEast"), N_("East"), + N_("East - Southeast"), N_("Southeast"), + N_("South - Southeast"), N_("South"), + N_("South - Southwest"), N_("Southwest"), + N_("West - Southwest"), N_("West"), + N_("West - Northwest"), N_("Northwest"), + N_("North - Northwest")}; -const gchar * -weather_wind_direction_string (WeatherWindDirection wind) -{ - if (wind <= WIND_INVALID || wind >= WIND_LAST) - return _("Invalid"); +const gchar *weather_wind_direction_string(WeatherWindDirection wind) { + if (wind <= WIND_INVALID || wind >= WIND_LAST) + return _("Invalid"); - return _(wind_direction_str[(int)wind]); + return _(wind_direction_str[(int)wind]); } -static const gchar *sky_str[] = { - N_("Clear Sky"), - N_("Broken clouds"), - N_("Scattered clouds"), - N_("Few clouds"), - N_("Overcast") -}; +static const gchar *sky_str[] = {N_("Clear Sky"), N_("Broken clouds"), + N_("Scattered clouds"), N_("Few clouds"), + N_("Overcast")}; -const gchar * -weather_sky_string (WeatherSky sky) -{ - if (sky <= SKY_INVALID || sky >= SKY_LAST) - return _("Invalid"); +const gchar *weather_sky_string(WeatherSky sky) { + if (sky <= SKY_INVALID || sky >= SKY_LAST) + return _("Invalid"); - return _(sky_str[(int)sky]); + return _(sky_str[(int)sky]); } /* @@ -286,816 +262,820 @@ weather_sky_string (WeatherSky sky) * Note, magic numbers, when you change the size here, make sure to change * the below function so that new values are recognized */ -/* NONE VICINITY LIGHT MODERATE HEAVY SHALLOW PATCHES PARTIAL THUNDERSTORM BLOWING SHOWERS DRIFTING FREEZING */ +/* NONE VICINITY LIGHT MODERATE HEAVY + * SHALLOW PATCHES PARTIAL + * THUNDERSTORM BLOWING SHOWERS DRIFTING + * FREEZING */ /* *******************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************/ static const gchar *conditions_str[24][13] = { -/* Translators: If you want to know what "blowing" "shallow" "partial" - * etc means, you can go to http://www.weather.com/glossary/ and - * http://www.crh.noaa.gov/arx/wx.tbl.php */ - /* NONE */ {"??", "??", "??", "??", "??", "??", "??", "??", N_("Thunderstorm"), "??", "??", "??", "??" }, - /* DRIZZLE */ {N_("Drizzle"), "??", N_("Light drizzle"), N_("Moderate drizzle"), N_("Heavy drizzle"), "??", "??", "??", "??", "??", "??", "??", N_("Freezing drizzle") }, - /* RAIN */ {N_("Rain"), "??", N_("Light rain"), N_("Moderate rain"), N_("Heavy rain"), "??", "??", "??", N_("Thunderstorm"), "??", N_("Rain showers"), "??", N_("Freezing rain") }, - /* SNOW */ {N_("Snow"), "??", N_("Light snow"), N_("Moderate snow"), N_("Heavy snow"), "??", "??", "??", N_("Snowstorm"), N_("Blowing snowfall"), N_("Snow showers"), N_("Drifting snow"), "??" }, - /* SNOW_GRAINS */ {N_("Snow grains"), "??", N_("Light snow grains"), N_("Moderate snow grains"), N_("Heavy snow grains"), "??", "??", "??", "??", "??", "??", "??", "??" }, - /* ICE_CRYSTALS */ {N_("Ice crystals"), "??", "??", N_("Ice crystals"), "??", "??", "??", "??", "??", "??", "??", "??", "??" }, - /* ICE_PELLETS */ {N_("Ice pellets"), "??", N_("Few ice pellets"), N_("Moderate ice pellets"), N_("Heavy ice pellets"), "??", "??", "??", N_("Ice pellet storm"), "??", N_("Showers of ice pellets"), "??", "??" }, - /* HAIL */ {N_("Hail"), "??", "??", N_("Hail"), "??", "??", "??", "??", N_("Hailstorm"), "??", N_("Hail showers"), "??", "??", }, - /* SMALL_HAIL */ {N_("Small hail"), "??", "??", N_("Small hail"), "??", "??", "??", "??", N_("Small hailstorm"), "??", N_("Showers of small hail"), "??", "??" }, - /* PRECIPITATION */ {N_("Unknown precipitation"), "??", "??", "??", "??", "??", "??", "??", "??", "??", "??", "??", "??" }, - /* MIST */ {N_("Mist"), "??", "??", N_("Mist"), "??", "??", "??", "??", "??", "??", "??", "??", "??" }, - /* FOG */ {N_("Fog"), N_("Fog in the vicinity") , "??", N_("Fog"), "??", N_("Shallow fog"), N_("Patches of fog"), N_("Partial fog"), "??", "??", "??", "??", N_("Freezing fog") }, - /* SMOKE */ {N_("Smoke"), "??", "??", N_("Smoke"), "??", "??", "??", "??", "??", "??", "??", "??", "??" }, - /* VOLCANIC_ASH */ {N_("Volcanic ash"), "??", "??", N_("Volcanic ash"), "??", "??", "??", "??", "??", "??", "??", "??", "??" }, - /* SAND */ {N_("Sand"), "??", "??", N_("Sand"), "??", "??", "??", "??", "??", N_("Blowing sand"), "", N_("Drifting sand"), "??" }, - /* HAZE */ {N_("Haze"), "??", "??", N_("Haze"), "??", "??", "??", "??", "??", "??", "??", "??", "??" }, - /* SPRAY */ {"??", "??", "??", "??", "??", "??", "??", "??", "??", N_("Blowing sprays"), "??", "??", "??" }, - /* DUST */ {N_("Dust"), "??", "??", N_("Dust"), "??", "??", "??", "??", "??", N_("Blowing dust"), "??", N_("Drifting dust"), "??" }, - /* SQUALL */ {N_("Squall"), "??", "??", N_("Squall"), "??", "??", "??", "??", "??", "??", "??", "??", "??" }, - /* SANDSTORM */ {N_("Sandstorm"), N_("Sandstorm in the vicinity") , "??", N_("Sandstorm"), N_("Heavy sandstorm"), "??", "??", "??", "??", "??", "??", "??", "??" }, - /* DUSTSTORM */ {N_("Duststorm"), N_("Duststorm in the vicinity") , "??", N_("Duststorm"), N_("Heavy duststorm"), "??", "??", "??", "??", "??", "??", "??", "??" }, - /* FUNNEL_CLOUD */ {N_("Funnel cloud"), "??", "??", "??", "??", "??", "??", "??", "??", "??", "??", "??", "??" }, - /* TORNADO */ {N_("Tornado"), "??", "??", "??", "??", "??", "??", "??", "??", "??", "??", "??", "??" }, - /* DUST_WHIRLS */ {N_("Dust whirls"), N_("Dust whirls in the vicinity") , "??", N_("Dust whirls"), "??", "??", "??", "??", "??", "??", "??", "??", "??" } -}; - -const gchar * -weather_conditions_string (WeatherConditions cond) -{ - const gchar *str; - - if (!cond.significant) { - return "-"; - } else { - if (cond.phenomenon > PHENOMENON_INVALID && - cond.phenomenon < PHENOMENON_LAST && - cond.qualifier > QUALIFIER_INVALID && - cond.qualifier < QUALIFIER_LAST) - str = _(conditions_str[(int)cond.phenomenon][(int)cond.qualifier]); - else - str = _("Invalid"); - return (strlen (str) > 0) ? str : "-"; - } + /* Translators: If you want to know what "blowing" "shallow" "partial" + * etc means, you can go to http://www.weather.com/glossary/ and + * http://www.crh.noaa.gov/arx/wx.tbl.php */ + /* NONE */ {"??", "??", "??", "??", "??", "??", "??", "??", + N_("Thunderstorm"), "??", "??", "??", "??"}, + /* DRIZZLE */ + {N_("Drizzle"), "??", N_("Light drizzle"), N_("Moderate drizzle"), + N_("Heavy drizzle"), "??", "??", "??", "??", "??", "??", "??", + N_("Freezing drizzle")}, + /* RAIN */ + {N_("Rain"), "??", N_("Light rain"), N_("Moderate rain"), N_("Heavy rain"), + "??", "??", "??", N_("Thunderstorm"), "??", N_("Rain showers"), "??", + N_("Freezing rain")}, + /* SNOW */ + {N_("Snow"), "??", N_("Light snow"), N_("Moderate snow"), N_("Heavy snow"), + "??", "??", "??", N_("Snowstorm"), N_("Blowing snowfall"), + N_("Snow showers"), N_("Drifting snow"), "??"}, + /* SNOW_GRAINS */ + {N_("Snow grains"), "??", N_("Light snow grains"), + N_("Moderate snow grains"), N_("Heavy snow grains"), "??", "??", "??", + "??", "??", "??", "??", "??"}, + /* ICE_CRYSTALS */ + {N_("Ice crystals"), "??", "??", N_("Ice crystals"), "??", "??", "??", "??", + "??", "??", "??", "??", "??"}, + /* ICE_PELLETS */ + {N_("Ice pellets"), "??", N_("Few ice pellets"), N_("Moderate ice pellets"), + N_("Heavy ice pellets"), "??", "??", "??", N_("Ice pellet storm"), "??", + N_("Showers of ice pellets"), "??", "??"}, + /* HAIL */ + { + N_("Hail"), + "??", + "??", + N_("Hail"), + "??", + "??", + "??", + "??", + N_("Hailstorm"), + "??", + N_("Hail showers"), + "??", + "??", + }, + /* SMALL_HAIL */ + {N_("Small hail"), "??", "??", N_("Small hail"), "??", "??", "??", "??", + N_("Small hailstorm"), "??", N_("Showers of small hail"), "??", "??"}, + /* PRECIPITATION */ + {N_("Unknown precipitation"), "??", "??", "??", "??", "??", "??", "??", + "??", "??", "??", "??", "??"}, + /* MIST */ + {N_("Mist"), "??", "??", N_("Mist"), "??", "??", "??", "??", "??", "??", + "??", "??", "??"}, + /* FOG */ + {N_("Fog"), N_("Fog in the vicinity"), "??", N_("Fog"), "??", + N_("Shallow fog"), N_("Patches of fog"), N_("Partial fog"), "??", "??", + "??", "??", N_("Freezing fog")}, + /* SMOKE */ + {N_("Smoke"), "??", "??", N_("Smoke"), "??", "??", "??", "??", "??", "??", + "??", "??", "??"}, + /* VOLCANIC_ASH */ + {N_("Volcanic ash"), "??", "??", N_("Volcanic ash"), "??", "??", "??", "??", + "??", "??", "??", "??", "??"}, + /* SAND */ + {N_("Sand"), "??", "??", N_("Sand"), "??", "??", "??", "??", "??", + N_("Blowing sand"), "", N_("Drifting sand"), "??"}, + /* HAZE */ + {N_("Haze"), "??", "??", N_("Haze"), "??", "??", "??", "??", "??", "??", + "??", "??", "??"}, + /* SPRAY */ + {"??", "??", "??", "??", "??", "??", "??", "??", "??", N_("Blowing sprays"), + "??", "??", "??"}, + /* DUST */ + {N_("Dust"), "??", "??", N_("Dust"), "??", "??", "??", "??", "??", + N_("Blowing dust"), "??", N_("Drifting dust"), "??"}, + /* SQUALL */ + {N_("Squall"), "??", "??", N_("Squall"), "??", "??", "??", "??", "??", "??", + "??", "??", "??"}, + /* SANDSTORM */ + {N_("Sandstorm"), N_("Sandstorm in the vicinity"), "??", N_("Sandstorm"), + N_("Heavy sandstorm"), "??", "??", "??", "??", "??", "??", "??", "??"}, + /* DUSTSTORM */ + {N_("Duststorm"), N_("Duststorm in the vicinity"), "??", N_("Duststorm"), + N_("Heavy duststorm"), "??", "??", "??", "??", "??", "??", "??", "??"}, + /* FUNNEL_CLOUD */ + {N_("Funnel cloud"), "??", "??", "??", "??", "??", "??", "??", "??", "??", + "??", "??", "??"}, + /* TORNADO */ + {N_("Tornado"), "??", "??", "??", "??", "??", "??", "??", "??", "??", "??", + "??", "??"}, + /* DUST_WHIRLS */ + {N_("Dust whirls"), N_("Dust whirls in the vicinity"), "??", + N_("Dust whirls"), "??", "??", "??", "??", "??", "??", "??", "??", "??"}}; + +const gchar *weather_conditions_string(WeatherConditions cond) { + const gchar *str; + + if (!cond.significant) { + return "-"; + } else { + if (cond.phenomenon > PHENOMENON_INVALID && + cond.phenomenon < PHENOMENON_LAST && + cond.qualifier > QUALIFIER_INVALID && cond.qualifier < QUALIFIER_LAST) + str = _(conditions_str[(int)cond.phenomenon][(int)cond.qualifier]); + else + str = _("Invalid"); + return (strlen(str) > 0) ? str : "-"; + } } /* Locals turned global to facilitate asynchronous HTTP requests */ -gboolean -requests_init (WeatherInfo *info) -{ - if (info->requests_pending) - return FALSE; +gboolean requests_init(WeatherInfo *info) { + if (info->requests_pending) + return FALSE; - return TRUE; + return TRUE; } -void request_done (WeatherInfo *info, GError *error) -{ - if (error == NULL) { - (void) calc_sun (info); - info->moonValid = info->valid && calc_moon (info); - } else if (error->code == G_IO_ERROR_CANCELLED) - return; /* Caused by soup_session_abort */ - if (!--info->requests_pending) - info->finish_cb (info, info->cb_data); +void request_done(WeatherInfo *info, GError *error) { + if (error == NULL) { + (void)calc_sun(info); + info->moonValid = info->valid && calc_moon(info); + } else if (error->code == G_IO_ERROR_CANCELLED) + return; /* Caused by soup_session_abort */ + if (!--info->requests_pending) + info->finish_cb(info, info->cb_data); } /* it's OK to pass in NULL */ -void -free_forecast_list (WeatherInfo *info) -{ - GSList *p; - - if (!info) - return; - - for (p = info->forecast_list; p; p = p->next) - weather_info_free (p->data); +void free_forecast_list(WeatherInfo *info) { + GSList *p; - if (info->forecast_list) { - g_slist_free (info->forecast_list); - info->forecast_list = NULL; - } -} - -/* Relative humidity computation - thanks to <[email protected]> */ + if (!info) + return; -static inline gdouble -calc_humidity (gdouble temp, gdouble dewp) -{ - gdouble esat, esurf; + for (p = info->forecast_list; p; p = p->next) + weather_info_free(p->data); - if (temp > -500.0 && dewp > -500.0) { - temp = TEMP_F_TO_C (temp); - dewp = TEMP_F_TO_C (dewp); - - esat = 6.11 * pow (10.0, (7.5 * temp) / (237.7 + temp)); - esurf = 6.11 * pow (10.0, (7.5 * dewp) / (237.7 + dewp)); - } else { - esurf = -1.0; - esat = 1.0; - } - return ((esurf/esat) * 100.0); -} - -static inline gdouble -calc_apparent (WeatherInfo *info) -{ - gdouble temp = info->temp; - gdouble wind = WINDSPEED_KNOTS_TO_MPH (info->windspeed); - gdouble apparent = -1000.; - - /* - * Wind chill calculations as of 01-Nov-2001 - * http://www.nws.noaa.gov/om/windchill/index.shtml - * Some pages suggest that the formula will soon be adjusted - * to account for solar radiation (bright sun vs cloudy sky) - */ - if (temp <= 50.0) { - if (wind > 3.0) { - gdouble v = pow (wind, 0.16); - apparent = 35.74 + 0.6215 * temp - 35.75 * v + 0.4275 * temp * v; - } else if (wind >= 0.) { - apparent = temp; - } + if (info->forecast_list) { + g_slist_free(info->forecast_list); + info->forecast_list = NULL; + } +} + +/* Relative humidity computation - thanks to + * <[email protected]> */ + +static inline gdouble calc_humidity(gdouble temp, gdouble dewp) { + gdouble esat, esurf; + + if (temp > -500.0 && dewp > -500.0) { + temp = TEMP_F_TO_C(temp); + dewp = TEMP_F_TO_C(dewp); + + esat = 6.11 * pow(10.0, (7.5 * temp) / (237.7 + temp)); + esurf = 6.11 * pow(10.0, (7.5 * dewp) / (237.7 + dewp)); + } else { + esurf = -1.0; + esat = 1.0; + } + return ((esurf / esat) * 100.0); +} + +static inline gdouble calc_apparent(WeatherInfo *info) { + gdouble temp = info->temp; + gdouble wind = WINDSPEED_KNOTS_TO_MPH(info->windspeed); + gdouble apparent = -1000.; + + /* + * Wind chill calculations as of 01-Nov-2001 + * http://www.nws.noaa.gov/om/windchill/index.shtml + * Some pages suggest that the formula will soon be adjusted + * to account for solar radiation (bright sun vs cloudy sky) + */ + if (temp <= 50.0) { + if (wind > 3.0) { + gdouble v = pow(wind, 0.16); + apparent = 35.74 + 0.6215 * temp - 35.75 * v + 0.4275 * temp * v; + } else if (wind >= 0.) { + apparent = temp; } - /* - * Heat index calculations: - * http://www.srh.noaa.gov/fwd/heatindex/heat5.html - */ - else if (temp >= 80.0) { - if (info->temp >= -500. && info->dew >= -500.) { - gdouble humidity = calc_humidity (info->temp, info->dew); - gdouble t2 = temp * temp; - gdouble h2 = humidity * humidity; + } + /* + * Heat index calculations: + * http://www.srh.noaa.gov/fwd/heatindex/heat5.html + */ + else if (temp >= 80.0) { + if (info->temp >= -500. && info->dew >= -500.) { + gdouble humidity = calc_humidity(info->temp, info->dew); + gdouble t2 = temp * temp; + gdouble h2 = humidity * humidity; #if 1 - /* - * A really precise formula. Note that overall precision is - * constrained by the accuracy of the instruments and that the - * we receive the temperature and dewpoints as integers. - */ - gdouble t3 = t2 * temp; - gdouble h3 = h2 * temp; - - apparent = 16.923 - + 0.185212 * temp - + 5.37941 * humidity - - 0.100254 * temp * humidity - + 9.41695e-3 * t2 - + 7.28898e-3 * h2 - + 3.45372e-4 * t2 * humidity - - 8.14971e-4 * temp * h2 - + 1.02102e-5 * t2 * h2 - - 3.8646e-5 * t3 - + 2.91583e-5 * h3 - + 1.42721e-6 * t3 * humidity - + 1.97483e-7 * temp * h3 - - 2.18429e-8 * t3 * h2 - + 8.43296e-10 * t2 * h3 - - 4.81975e-11 * t3 * h3; + /* + * A really precise formula. Note that overall precision is + * constrained by the accuracy of the instruments and that the + * we receive the temperature and dewpoints as integers. + */ + gdouble t3 = t2 * temp; + gdouble h3 = h2 * temp; + + apparent = 16.923 + 0.185212 * temp + 5.37941 * humidity - + 0.100254 * temp * humidity + 9.41695e-3 * t2 + + 7.28898e-3 * h2 + 3.45372e-4 * t2 * humidity - + 8.14971e-4 * temp * h2 + 1.02102e-5 * t2 * h2 - + 3.8646e-5 * t3 + 2.91583e-5 * h3 + 1.42721e-6 * t3 * humidity + + 1.97483e-7 * temp * h3 - 2.18429e-8 * t3 * h2 + + 8.43296e-10 * t2 * h3 - 4.81975e-11 * t3 * h3; #else - /* - * An often cited alternative: values are within 5 degrees for - * most ranges between 10% and 70% humidity and to 110 degrees. - */ - apparent = - 42.379 - + 2.04901523 * temp - + 10.14333127 * humidity - - 0.22475541 * temp * humidity - - 6.83783e-3 * t2 - - 5.481717e-2 * h2 - + 1.22874e-3 * t2 * humidity - + 8.5282e-4 * temp * h2 - - 1.99e-6 * t2 * h2; + /* + * An often cited alternative: values are within 5 degrees for + * most ranges between 10% and 70% humidity and to 110 degrees. + */ + apparent = -42.379 + 2.04901523 * temp + 10.14333127 * humidity - + 0.22475541 * temp * humidity - 6.83783e-3 * t2 - + 5.481717e-2 * h2 + 1.22874e-3 * t2 * humidity + + 8.5282e-4 * temp * h2 - 1.99e-6 * t2 * h2; #endif - } - } else { - apparent = temp; - } - - return apparent; -} - -WeatherInfo * -_weather_info_fill (WeatherInfo *info, - WeatherLocation *location, - const WeatherPrefs *prefs, - WeatherInfoFunc cb, - gpointer data) -{ - g_return_val_if_fail (((info == NULL) && (location != NULL)) || \ - ((info != NULL) && (location == NULL)), NULL); - g_return_val_if_fail (prefs != NULL, NULL); - - /* FIXME: i'm not sure this works as intended anymore */ - if (!info) { - info = g_new0 (WeatherInfo, 1); - info->requests_pending = 0; - info->location = weather_location_clone (location); - } else { - location = info->location; - if (info->forecast) - g_free (info->forecast); - info->forecast = NULL; - - free_forecast_list (info); - - if (info->radar != NULL) { - g_object_unref (info->radar); - info->radar = NULL; - } - } - - /* Update in progress */ - if (!requests_init (info)) { - return NULL; } - - /* Defaults (just in case...) */ - /* Well, no just in case anymore. We may actually fail to fetch some - * fields. */ - info->forecast_type = prefs->type; - - info->temperature_unit = prefs->temperature_unit; - info->speed_unit = prefs->speed_unit; - info->pressure_unit = prefs->pressure_unit; - info->distance_unit = prefs->distance_unit; - - info->update = 0; - info->sky = -1; - info->cond.significant = FALSE; - info->cond.phenomenon = PHENOMENON_NONE; - info->cond.qualifier = QUALIFIER_NONE; - info->temp = -1000.0; - info->tempMinMaxValid = FALSE; - info->temp_min = -1000.0; - info->temp_max = -1000.0; - info->dew = -1000.0; - info->wind = -1; - info->windspeed = -1; - info->pressure = -1.0; - info->visibility = -1.0; - info->sunriseValid = FALSE; - info->sunsetValid = FALSE; - info->moonValid = FALSE; - info->sunrise = 0; - info->sunset = 0; - info->moonphase = 0; - info->moonlatitude = 0; + } else { + apparent = temp; + } + + return apparent; +} + +WeatherInfo *_weather_info_fill(WeatherInfo *info, WeatherLocation *location, + const WeatherPrefs *prefs, WeatherInfoFunc cb, + gpointer data) { + g_return_val_if_fail(((info == NULL) && (location != NULL)) || + ((info != NULL) && (location == NULL)), + NULL); + g_return_val_if_fail(prefs != NULL, NULL); + + /* FIXME: i'm not sure this works as intended anymore */ + if (!info) { + info = g_new0(WeatherInfo, 1); + info->requests_pending = 0; + info->location = weather_location_clone(location); + } else { + location = info->location; + if (info->forecast) + g_free(info->forecast); info->forecast = NULL; - info->forecast_list = NULL; - info->radar = NULL; - info->radar_url = prefs->radar && prefs->radar_custom_url ? - g_strdup (prefs->radar_custom_url) : NULL; - info->finish_cb = cb; - info->cb_data = data; - - if (!info->session) { - info->session = soup_session_new (); - } - metar_start_open (info); - iwin_start_open (info); + free_forecast_list(info); - if (prefs->radar) { - wx_start_open (info); + if (info->radar != NULL) { + g_object_unref(info->radar); + info->radar = NULL; } + } + + /* Update in progress */ + if (!requests_init(info)) { + return NULL; + } + + /* Defaults (just in case...) */ + /* Well, no just in case anymore. We may actually fail to fetch some + * fields. */ + info->forecast_type = prefs->type; + + info->temperature_unit = prefs->temperature_unit; + info->speed_unit = prefs->speed_unit; + info->pressure_unit = prefs->pressure_unit; + info->distance_unit = prefs->distance_unit; + + info->update = 0; + info->sky = -1; + info->cond.significant = FALSE; + info->cond.phenomenon = PHENOMENON_NONE; + info->cond.qualifier = QUALIFIER_NONE; + info->temp = -1000.0; + info->tempMinMaxValid = FALSE; + info->temp_min = -1000.0; + info->temp_max = -1000.0; + info->dew = -1000.0; + info->wind = -1; + info->windspeed = -1; + info->pressure = -1.0; + info->visibility = -1.0; + info->sunriseValid = FALSE; + info->sunsetValid = FALSE; + info->moonValid = FALSE; + info->sunrise = 0; + info->sunset = 0; + info->moonphase = 0; + info->moonlatitude = 0; + info->forecast = NULL; + info->forecast_list = NULL; + info->radar = NULL; + info->radar_url = prefs->radar && prefs->radar_custom_url + ? g_strdup(prefs->radar_custom_url) + : NULL; + info->finish_cb = cb; + info->cb_data = data; + + if (!info->session) { + info->session = soup_session_new(); + } + + metar_start_open(info); + iwin_start_open(info); + + if (prefs->radar) { + wx_start_open(info); + } + + return info; +} + +void weather_info_abort(WeatherInfo *info) { + g_return_if_fail(info != NULL); + + if (info->session) { + soup_session_abort(info->session); + info->requests_pending = 0; + } +} + +WeatherInfo *weather_info_clone(const WeatherInfo *info) { + WeatherInfo *clone; + + g_return_val_if_fail(info != NULL, NULL); + + clone = g_new(WeatherInfo, 1); + + /* move everything */ + memmove(clone, info, sizeof(WeatherInfo)); + + /* special moves */ + clone->location = weather_location_clone(info->location); + /* This handles null correctly */ + clone->forecast = g_strdup(info->forecast); + clone->radar_url = g_strdup(info->radar_url); + + if (info->forecast_list) { + GSList *p; - return info; -} - -void -weather_info_abort (WeatherInfo *info) -{ - g_return_if_fail (info != NULL); - - if (info->session) { - soup_session_abort (info->session); - info->requests_pending = 0; + clone->forecast_list = NULL; + for (p = info->forecast_list; p; p = p->next) { + clone->forecast_list = + g_slist_prepend(clone->forecast_list, weather_info_clone(p->data)); } -} -WeatherInfo * -weather_info_clone (const WeatherInfo *info) -{ - WeatherInfo *clone; + clone->forecast_list = g_slist_reverse(clone->forecast_list); + } - g_return_val_if_fail (info != NULL, NULL); + clone->radar = info->radar; + if (clone->radar != NULL) + g_object_ref(clone->radar); - clone = g_new (WeatherInfo, 1); - - /* move everything */ - memmove (clone, info, sizeof (WeatherInfo)); - - /* special moves */ - clone->location = weather_location_clone (info->location); - /* This handles null correctly */ - clone->forecast = g_strdup (info->forecast); - clone->radar_url = g_strdup (info->radar_url); - - if (info->forecast_list) { - GSList *p; - - clone->forecast_list = NULL; - for (p = info->forecast_list; p; p = p->next) { - clone->forecast_list = g_slist_prepend (clone->forecast_list, weather_info_clone (p->data)); - } - - clone->forecast_list = g_slist_reverse (clone->forecast_list); - } - - clone->radar = info->radar; - if (clone->radar != NULL) - g_object_ref (clone->radar); - - return clone; + return clone; } -void -weather_info_free (WeatherInfo *info) -{ - if (!info) - return; +void weather_info_free(WeatherInfo *info) { + if (!info) + return; - weather_info_abort (info); - if (info->session) - g_object_unref (info->session); + weather_info_abort(info); + if (info->session) + g_object_unref(info->session); - weather_location_free (info->location); - info->location = NULL; + weather_location_free(info->location); + info->location = NULL; - g_free (info->forecast); - info->forecast = NULL; + g_free(info->forecast); + info->forecast = NULL; - free_forecast_list (info); + free_forecast_list(info); - if (info->radar != NULL) { - g_object_unref (info->radar); - info->radar = NULL; - } + if (info->radar != NULL) { + g_object_unref(info->radar); + info->radar = NULL; + } - g_free (info); + g_free(info); } -gboolean -weather_info_is_valid (WeatherInfo *info) -{ - g_return_val_if_fail (info != NULL, FALSE); - return info->valid; +gboolean weather_info_is_valid(WeatherInfo *info) { + g_return_val_if_fail(info != NULL, FALSE); + return info->valid; } -gboolean -weather_info_network_error (WeatherInfo *info) -{ - g_return_val_if_fail (info != NULL, FALSE); - return info->network_error; -} - -void -weather_info_to_metric (WeatherInfo *info) -{ - g_return_if_fail (info != NULL); - - info->temperature_unit = TEMP_UNIT_CENTIGRADE; - info->speed_unit = SPEED_UNIT_MS; - info->pressure_unit = PRESSURE_UNIT_HPA; - info->distance_unit = DISTANCE_UNIT_METERS; -} - -void -weather_info_to_imperial (WeatherInfo *info) -{ - g_return_if_fail (info != NULL); - - info->temperature_unit = TEMP_UNIT_FAHRENHEIT; - info->speed_unit = SPEED_UNIT_MPH; - info->pressure_unit = PRESSURE_UNIT_INCH_HG; - info->distance_unit = DISTANCE_UNIT_MILES; -} - -const WeatherLocation * -weather_info_get_location (WeatherInfo *info) -{ - g_return_val_if_fail (info != NULL, NULL); - return info->location; -} - -const gchar * -weather_info_get_location_name (WeatherInfo *info) -{ - g_return_val_if_fail (info != NULL, NULL); - g_return_val_if_fail (info->location != NULL, NULL); - return info->location->name; -} - -const gchar * -weather_info_get_update (WeatherInfo *info) -{ - static gchar buf[200]; - char *utf8, *timeformat; - - g_return_val_if_fail (info != NULL, NULL); - - if (!info->valid) - return "-"; - - if (info->update != 0) { - struct tm tm; - localtime_r (&info->update, &tm); - /* Translators: this is a format string for strftime - * see `man 3 strftime` for more details - */ - timeformat = g_locale_from_utf8 (_("%a, %b %d / %H:%M"), -1, - NULL, NULL, NULL); - if (!timeformat) { - strcpy (buf, "???"); - } - else if (strftime (buf, sizeof (buf), timeformat, &tm) <= 0) { - strcpy (buf, "???"); - } - g_free (timeformat); - - /* Convert to UTF-8 */ - utf8 = g_locale_to_utf8 (buf, -1, NULL, NULL, NULL); - strcpy (buf, utf8); - g_free (utf8); - } else { - strncpy (buf, _("Unknown observation time"), sizeof (buf)); - buf[sizeof (buf)-1] = '\0'; - } +gboolean weather_info_network_error(WeatherInfo *info) { + g_return_val_if_fail(info != NULL, FALSE); + return info->network_error; +} - return buf; -} - -const gchar * -weather_info_get_sky (WeatherInfo *info) -{ - g_return_val_if_fail (info != NULL, NULL); - if (!info->valid) - return "-"; - if (info->sky < 0) - return _("Unknown"); - return weather_sky_string (info->sky); -} - -const gchar * -weather_info_get_conditions (WeatherInfo *info) -{ - g_return_val_if_fail (info != NULL, NULL); - if (!info->valid) - return "-"; - return weather_conditions_string (info->cond); -} - -static const gchar * -temperature_string (gdouble temp, TempUnit to_unit, gboolean want_round) -{ - static gchar buf[100]; - - switch (to_unit) { - case TEMP_UNIT_FAHRENHEIT: - if (!want_round) { - /* Translators: This is the temperature in degrees Fahrenheit (\302\260 is U+00B0 DEGREE SIGN) */ - g_snprintf (buf, sizeof (buf), _("%.1f \302\260F"), temp); - } else { - const int range_problem = FE_INVALID | FE_DIVBYZERO | FE_OVERFLOW | FE_UNDERFLOW; - gdouble temp_r; - - feclearexcept(range_problem); - temp_r = round (temp); - if (fetestexcept(range_problem)) - g_snprintf (buf, sizeof (buf), _("n/a")); - else - /* Translators: This is the temperature in degrees Fahrenheit (\302\260 is U+00B0 DEGREE SIGN) */ - g_snprintf (buf, sizeof (buf), _("%d \302\260F"), (int)temp_r); - } - break; - case TEMP_UNIT_CENTIGRADE: - if (!want_round) { - /* Translators: This is the temperature in degrees Celsius (\302\260 is U+00B0 DEGREE SIGN) */ - g_snprintf (buf, sizeof (buf), _("%.1f \302\260C"), TEMP_F_TO_C (temp)); - } else { - const int range_problem = FE_INVALID | FE_DIVBYZERO | FE_OVERFLOW | FE_UNDERFLOW; - gdouble temp_r; - - feclearexcept(range_problem); - temp_r = round (TEMP_F_TO_C (temp)); - if (fetestexcept(range_problem)) - g_snprintf (buf, sizeof (buf), _("n/a")); - else - /* Translators: This is the temperature in degrees Celsius (\302\260 is U+00B0 DEGREE SIGN) */ - g_snprintf (buf, sizeof (buf), _("%d \302\260C"), (int)temp_r); - } - break; - case TEMP_UNIT_KELVIN: - if (!want_round) { - /* Translators: This is the temperature in kelvin */ - g_snprintf (buf, sizeof (buf), _("%.1f K"), TEMP_F_TO_K (temp)); - } else { - const int range_problem = FE_INVALID | FE_DIVBYZERO | FE_OVERFLOW | FE_UNDERFLOW; - gdouble temp_r; - - feclearexcept(range_problem); - temp_r = round (TEMP_F_TO_K (temp)); - if (fetestexcept(range_problem)) - g_snprintf (buf, sizeof (buf), _("n/a")); - else - /* Translators: This is the temperature in kelvin */ - g_snprintf (buf, sizeof (buf), _("%d K"), (int)temp_r); - } - break; - - case TEMP_UNIT_INVALID: - case TEMP_UNIT_DEFAULT: - default: - g_warning ("Conversion to illegal temperature unit: %d", to_unit); - return _("Unknown"); - } +void weather_info_to_metric(WeatherInfo *info) { + g_return_if_fail(info != NULL); - return buf; + info->temperature_unit = TEMP_UNIT_CENTIGRADE; + info->speed_unit = SPEED_UNIT_MS; + info->pressure_unit = PRESSURE_UNIT_HPA; + info->distance_unit = DISTANCE_UNIT_METERS; } -const gchar * -weather_info_get_temp (WeatherInfo *info) -{ - g_return_val_if_fail (info != NULL, NULL); - - if (!info->valid) - return "-"; - if (info->temp < -500.0) - return _("Unknown"); +void weather_info_to_imperial(WeatherInfo *info) { + g_return_if_fail(info != NULL); - return temperature_string (info->temp, info->temperature_unit, FALSE); + info->temperature_unit = TEMP_UNIT_FAHRENHEIT; + info->speed_unit = SPEED_UNIT_MPH; + info->pressure_unit = PRESSURE_UNIT_INCH_HG; + info->distance_unit = DISTANCE_UNIT_MILES; } -const gchar * -weather_info_get_temp_min (WeatherInfo *info) -{ - g_return_val_if_fail (info != NULL, NULL); - - if (!info->valid || !info->tempMinMaxValid) - return "-"; - if (info->temp_min < -500.0) - return _("Unknown"); +const WeatherLocation *weather_info_get_location(WeatherInfo *info) { + g_return_val_if_fail(info != NULL, NULL); + return info->location; +} - return temperature_string (info->temp_min, info->temperature_unit, FALSE); +const gchar *weather_info_get_location_name(WeatherInfo *info) { + g_return_val_if_fail(info != NULL, NULL); + g_return_val_if_fail(info->location != NULL, NULL); + return info->location->name; } -const gchar * -weather_info_get_temp_max (WeatherInfo *info) -{ - g_return_val_if_fail (info != NULL, NULL); +const gchar *weather_info_get_update(WeatherInfo *info) { + static gchar buf[200]; + char *utf8, *timeformat; - if (!info->valid || !info->tempMinMaxValid) - return "-"; - if (info->temp_max < -500.0) - return _("Unknown"); + g_return_val_if_fail(info != NULL, NULL); - return temperature_string (info->temp_max, info->temperature_unit, FALSE); -} + if (!info->valid) + return "-"; -const gchar * -weather_info_get_dew (WeatherInfo *info) -{ - g_return_val_if_fail (info != NULL, NULL); + if (info->update != 0) { + struct tm tm; + localtime_r(&info->update, &tm); + /* Translators: this is a format string for strftime + * see `man 3 strftime` for more details + */ + timeformat = + g_locale_from_utf8(_("%a, %b %d / %H:%M"), -1, NULL, NULL, NULL); + if (!timeformat) { + strcpy(buf, "???"); + } else if (strftime(buf, sizeof(buf), timeformat, &tm) <= 0) { + strcpy(buf, "???"); + } + g_free(timeformat); + + /* Convert to UTF-8 */ + utf8 = g_locale_to_utf8(buf, -1, NULL, NULL, NULL); + strcpy(buf, utf8); + g_free(utf8); + } else { + strncpy(buf, _("Unknown observation time"), sizeof(buf)); + buf[sizeof(buf) - 1] = '\0'; + } + + return buf; +} + +const gchar *weather_info_get_sky(WeatherInfo *info) { + g_return_val_if_fail(info != NULL, NULL); + if (!info->valid) + return "-"; + if (info->sky < 0) + return _("Unknown"); + return weather_sky_string(info->sky); +} + +const gchar *weather_info_get_conditions(WeatherInfo *info) { + g_return_val_if_fail(info != NULL, NULL); + if (!info->valid) + return "-"; + return weather_conditions_string(info->cond); +} + +static const gchar *temperature_string(gdouble temp, TempUnit to_unit, + gboolean want_round) { + static gchar buf[100]; + + switch (to_unit) { + case TEMP_UNIT_FAHRENHEIT: + if (!want_round) { + /* Translators: This is the temperature in degrees Fahrenheit (\302\260 is + * U+00B0 DEGREE SIGN) */ + g_snprintf(buf, sizeof(buf), _("%.1f \302\260F"), temp); + } else { + const int range_problem = + FE_INVALID | FE_DIVBYZERO | FE_OVERFLOW | FE_UNDERFLOW; + gdouble temp_r; + + feclearexcept(range_problem); + temp_r = round(temp); + if (fetestexcept(range_problem)) + g_snprintf(buf, sizeof(buf), _("n/a")); + else + /* Translators: This is the temperature in degrees Fahrenheit (\302\260 + * is U+00B0 DEGREE SIGN) */ + g_snprintf(buf, sizeof(buf), _("%d \302\260F"), (int)temp_r); + } + break; + case TEMP_UNIT_CENTIGRADE: + if (!want_round) { + /* Translators: This is the temperature in degrees Celsius (\302\260 is + * U+00B0 DEGREE SIGN) */ + g_snprintf(buf, sizeof(buf), _("%.1f \302\260C"), TEMP_F_TO_C(temp)); + } else { + const int range_problem = + FE_INVALID | FE_DIVBYZERO | FE_OVERFLOW | FE_UNDERFLOW; + gdouble temp_r; + + feclearexcept(range_problem); + temp_r = round(TEMP_F_TO_C(temp)); + if (fetestexcept(range_problem)) + g_snprintf(buf, sizeof(buf), _("n/a")); + else + /* Translators: This is the temperature in degrees Celsius (\302\260 is + * U+00B0 DEGREE SIGN) */ + g_snprintf(buf, sizeof(buf), _("%d \302\260C"), (int)temp_r); + } + break; + case TEMP_UNIT_KELVIN: + if (!want_round) { + /* Translators: This is the temperature in kelvin */ + g_snprintf(buf, sizeof(buf), _("%.1f K"), TEMP_F_TO_K(temp)); + } else { + const int range_problem = + FE_INVALID | FE_DIVBYZERO | FE_OVERFLOW | FE_UNDERFLOW; + gdouble temp_r; + + feclearexcept(range_problem); + temp_r = round(TEMP_F_TO_K(temp)); + if (fetestexcept(range_problem)) + g_snprintf(buf, sizeof(buf), _("n/a")); + else + /* Translators: This is the temperature in kelvin */ + g_snprintf(buf, sizeof(buf), _("%d K"), (int)temp_r); + } + break; - if (!info->valid) - return "-"; - if (info->dew < -500.0) - return _("Unknown"); + case TEMP_UNIT_INVALID: + case TEMP_UNIT_DEFAULT: + default: + g_warning("Conversion to illegal temperature unit: %d", to_unit); + return _("Unknown"); + } - return temperature_string (info->dew, info->temperature_unit, FALSE); + return buf; } -const gchar * -weather_info_get_humidity (WeatherInfo *info) -{ - static gchar buf[20]; - gdouble humidity; - - g_return_val_if_fail (info != NULL, NULL); +const gchar *weather_info_get_temp(WeatherInfo *info) { + g_return_val_if_fail(info != NULL, NULL); - if (!info->valid) - return "-"; + if (!info->valid) + return "-"; + if (info->temp < -500.0) + return _("Unknown"); - humidity = calc_humidity (info->temp, info->dew); - if (humidity < 0.0) - return _("Unknown"); - - /* Translators: This is the humidity in percent */ - g_snprintf (buf, sizeof (buf), _("%.f%%"), humidity); - return buf; + return temperature_string(info->temp, info->temperature_unit, FALSE); } -const gchar * -weather_info_get_apparent (WeatherInfo *info) -{ - gdouble apparent; - - g_return_val_if_fail (info != NULL, NULL); - if (!info->valid) - return "-"; +const gchar *weather_info_get_temp_min(WeatherInfo *info) { + g_return_val_if_fail(info != NULL, NULL); - apparent = calc_apparent (info); - if (apparent < -500.0) - return _("Unknown"); + if (!info->valid || !info->tempMinMaxValid) + return "-"; + if (info->temp_min < -500.0) + return _("Unknown"); - return temperature_string (apparent, info->temperature_unit, FALSE); + return temperature_string(info->temp_min, info->temperature_unit, FALSE); } -static const gchar * -windspeed_string (gfloat knots, SpeedUnit to_unit) -{ - static gchar buf[100]; +const gchar *weather_info_get_temp_max(WeatherInfo *info) { + g_return_val_if_fail(info != NULL, NULL); - switch (to_unit) { - case SPEED_UNIT_KNOTS: - /* Translators: This is the wind speed in knots */ - g_snprintf (buf, sizeof (buf), _("%0.1f knots"), knots); - break; - case SPEED_UNIT_MPH: - /* Translators: This is the wind speed in miles per hour */ - g_snprintf (buf, sizeof (buf), _("%.1f mph"), WINDSPEED_KNOTS_TO_MPH (knots)); - break; - case SPEED_UNIT_KPH: - /* Translators: This is the wind speed in kilometers per hour */ - g_snprintf (buf, sizeof (buf), _("%.1f km/h"), WINDSPEED_KNOTS_TO_KPH (knots)); - break; - case SPEED_UNIT_MS: - /* Translators: This is the wind speed in meters per second */ - g_snprintf (buf, sizeof (buf), _("%.1f m/s"), WINDSPEED_KNOTS_TO_MS (knots)); - break; - case SPEED_UNIT_BFT: - /* Translators: This is the wind speed as a Beaufort force factor - * (commonly used in nautical wind estimation). - */ - g_snprintf (buf, sizeof (buf), _("Beaufort force %.1f"), - WINDSPEED_KNOTS_TO_BFT (knots)); - break; - case SPEED_UNIT_INVALID: - case SPEED_UNIT_DEFAULT: - default: - g_warning ("Conversion to illegal speed unit: %d", to_unit); - return _("Unknown"); - } + if (!info->valid || !info->tempMinMaxValid) + return "-"; + if (info->temp_max < -500.0) + return _("Unknown"); - return buf; + return temperature_string(info->temp_max, info->temperature_unit, FALSE); } -const gchar * -weather_info_get_wind (WeatherInfo *info) -{ - static gchar buf[200]; - - g_return_val_if_fail (info != NULL, NULL); - - if (!info->valid) - return "-"; - if (info->windspeed < 0.0 || info->wind < 0) - return _("Unknown"); - if (info->windspeed == 0.00) { - strncpy (buf, _("Calm"), sizeof (buf)); - buf[sizeof (buf)-1] = '\0'; - } else { - /* Translators: This is 'wind direction' / 'wind speed' */ - g_snprintf (buf, sizeof (buf), _("%s / %s"), - weather_wind_direction_string (info->wind), - windspeed_string (info->windspeed, info->speed_unit)); - } - return buf; -} - -const gchar * -weather_info_get_pressure (WeatherInfo *info) -{ - static gchar buf[100]; - - g_return_val_if_fail (info != NULL, NULL); - - if (!info->valid) - return "-"; - if (info->pressure < 0.0) - return _("Unknown"); - - switch (info->pressure_unit) { - case PRESSURE_UNIT_INCH_HG: - /* Translators: This is pressure in inches of mercury */ - g_snprintf (buf, sizeof (buf), _("%.2f inHg"), info->pressure); - break; - case PRESSURE_UNIT_MM_HG: - /* Translators: This is pressure in millimeters of mercury */ - g_snprintf (buf, sizeof (buf), _("%.1f mmHg"), PRESSURE_INCH_TO_MM (info->pressure)); - break; - case PRESSURE_UNIT_KPA: - /* Translators: This is pressure in kiloPascals */ - g_snprintf (buf, sizeof (buf), _("%.2f kPa"), PRESSURE_INCH_TO_KPA (info->pressure)); - break; - case PRESSURE_UNIT_HPA: - /* Translators: This is pressure in hectoPascals */ - g_snprintf (buf, sizeof (buf), _("%.2f hPa"), PRESSURE_INCH_TO_HPA (info->pressure)); - break; - case PRESSURE_UNIT_MB: - /* Translators: This is pressure in millibars */ - g_snprintf (buf, sizeof (buf), _("%.2f mb"), PRESSURE_INCH_TO_MB (info->pressure)); - break; - case PRESSURE_UNIT_ATM: - /* Translators: This is pressure in atmospheres */ - g_snprintf (buf, sizeof (buf), _("%.3f atm"), PRESSURE_INCH_TO_ATM (info->pressure)); - break; - - case PRESSURE_UNIT_INVALID: - case PRESSURE_UNIT_DEFAULT: - default: - g_warning ("Conversion to illegal pressure unit: %d", info->pressure_unit); - return _("Unknown"); - } +const gchar *weather_info_get_dew(WeatherInfo *info) { + g_return_val_if_fail(info != NULL, NULL); - return buf; -} - -const gchar * -weather_info_get_visibility (WeatherInfo *info) -{ - static gchar buf[100]; - - g_return_val_if_fail (info != NULL, NULL); - - if (!info->valid) - return "-"; - if (info->visibility < 0.0) - return _("Unknown"); - - switch (info->distance_unit) { - case DISTANCE_UNIT_MILES: - /* Translators: This is the visibility in miles */ - g_snprintf (buf, sizeof (buf), _("%.1f miles"), info->visibility); - break; - case DISTANCE_UNIT_KM: - /* Translators: This is the visibility in kilometers */ - g_snprintf (buf, sizeof (buf), _("%.1f km"), VISIBILITY_SM_TO_KM (info->visibility)); - break; - case DISTANCE_UNIT_METERS: - /* Translators: This is the visibility in meters */ - g_snprintf (buf, sizeof (buf), _("%.0fm"), VISIBILITY_SM_TO_M (info->visibility)); - break; - - case DISTANCE_UNIT_INVALID: - case DISTANCE_UNIT_DEFAULT: - default: - g_warning ("Conversion to illegal visibility unit: %d", info->pressure_unit); - return _("Unknown"); - } + if (!info->valid) + return "-"; + if (info->dew < -500.0) + return _("Unknown"); - return buf; + return temperature_string(info->dew, info->temperature_unit, FALSE); } -const gchar * -weather_info_get_sunrise (WeatherInfo *info) -{ - static gchar buf[200]; - struct tm tm; +const gchar *weather_info_get_humidity(WeatherInfo *info) { + static gchar buf[20]; + gdouble humidity; + + g_return_val_if_fail(info != NULL, NULL); - g_return_val_if_fail (info && info->location, NULL); + if (!info->valid) + return "-"; - if (!info->location->latlon_valid) - return "-"; - if (!info->valid) - return "-"; - if (!calc_sun (info)) - return "-"; + humidity = calc_humidity(info->temp, info->dew); + if (humidity < 0.0) + return _("Unknown"); - localtime_r (&info->sunrise, &tm); - if (strftime (buf, sizeof (buf), _("%H:%M"), &tm) <= 0) - return "-"; - return buf; + /* Translators: This is the humidity in percent */ + g_snprintf(buf, sizeof(buf), _("%.f%%"), humidity); + return buf; } -const gchar * -weather_info_get_sunset (WeatherInfo *info) -{ - static gchar buf[200]; - struct tm tm; +const gchar *weather_info_get_apparent(WeatherInfo *info) { + gdouble apparent; - g_return_val_if_fail (info && info->location, NULL); + g_return_val_if_fail(info != NULL, NULL); + if (!info->valid) + return "-"; - if (!info->location->latlon_valid) - return "-"; - if (!info->valid) - return "-"; - if (!calc_sun (info)) - return "-"; + apparent = calc_apparent(info); + if (apparent < -500.0) + return _("Unknown"); - localtime_r (&info->sunset, &tm); - if (strftime (buf, sizeof (buf), _("%H:%M"), &tm) <= 0) - return "-"; - return buf; + return temperature_string(apparent, info->temperature_unit, FALSE); } -const gchar * -weather_info_get_forecast (WeatherInfo *info) -{ - g_return_val_if_fail (info != NULL, NULL); - return info->forecast; +static const gchar *windspeed_string(gfloat knots, SpeedUnit to_unit) { + static gchar buf[100]; + + switch (to_unit) { + case SPEED_UNIT_KNOTS: + /* Translators: This is the wind speed in knots */ + g_snprintf(buf, sizeof(buf), _("%0.1f knots"), knots); + break; + case SPEED_UNIT_MPH: + /* Translators: This is the wind speed in miles per hour */ + g_snprintf(buf, sizeof(buf), _("%.1f mph"), WINDSPEED_KNOTS_TO_MPH(knots)); + break; + case SPEED_UNIT_KPH: + /* Translators: This is the wind speed in kilometers per hour */ + g_snprintf(buf, sizeof(buf), _("%.1f km/h"), WINDSPEED_KNOTS_TO_KPH(knots)); + break; + case SPEED_UNIT_MS: + /* Translators: This is the wind speed in meters per second */ + g_snprintf(buf, sizeof(buf), _("%.1f m/s"), WINDSPEED_KNOTS_TO_MS(knots)); + break; + case SPEED_UNIT_BFT: + /* Translators: This is the wind speed as a Beaufort force factor + * (commonly used in nautical wind estimation). + */ + g_snprintf(buf, sizeof(buf), _("Beaufort force %.1f"), + WINDSPEED_KNOTS_TO_BFT(knots)); + break; + case SPEED_UNIT_INVALID: + case SPEED_UNIT_DEFAULT: + default: + g_warning("Conversion to illegal speed unit: %d", to_unit); + return _("Unknown"); + } + + return buf; +} + +const gchar *weather_info_get_wind(WeatherInfo *info) { + static gchar buf[200]; + + g_return_val_if_fail(info != NULL, NULL); + + if (!info->valid) + return "-"; + if (info->windspeed < 0.0 || info->wind < 0) + return _("Unknown"); + if (info->windspeed == 0.00) { + strncpy(buf, _("Calm"), sizeof(buf)); + buf[sizeof(buf) - 1] = '\0'; + } else { + /* Translators: This is 'wind direction' / 'wind speed' */ + g_snprintf(buf, sizeof(buf), _("%s / %s"), + weather_wind_direction_string(info->wind), + windspeed_string(info->windspeed, info->speed_unit)); + } + return buf; +} + +const gchar *weather_info_get_pressure(WeatherInfo *info) { + static gchar buf[100]; + + g_return_val_if_fail(info != NULL, NULL); + + if (!info->valid) + return "-"; + if (info->pressure < 0.0) + return _("Unknown"); + + switch (info->pressure_unit) { + case PRESSURE_UNIT_INCH_HG: + /* Translators: This is pressure in inches of mercury */ + g_snprintf(buf, sizeof(buf), _("%.2f inHg"), info->pressure); + break; + case PRESSURE_UNIT_MM_HG: + /* Translators: This is pressure in millimeters of mercury */ + g_snprintf(buf, sizeof(buf), _("%.1f mmHg"), + PRESSURE_INCH_TO_MM(info->pressure)); + break; + case PRESSURE_UNIT_KPA: + /* Translators: This is pressure in kiloPascals */ + g_snprintf(buf, sizeof(buf), _("%.2f kPa"), + PRESSURE_INCH_TO_KPA(info->pressure)); + break; + case PRESSURE_UNIT_HPA: + /* Translators: This is pressure in hectoPascals */ + g_snprintf(buf, sizeof(buf), _("%.2f hPa"), + PRESSURE_INCH_TO_HPA(info->pressure)); + break; + case PRESSURE_UNIT_MB: + /* Translators: This is pressure in millibars */ + g_snprintf(buf, sizeof(buf), _("%.2f mb"), + PRESSURE_INCH_TO_MB(info->pressure)); + break; + case PRESSURE_UNIT_ATM: + /* Translators: This is pressure in atmospheres */ + g_snprintf(buf, sizeof(buf), _("%.3f atm"), + PRESSURE_INCH_TO_ATM(info->pressure)); + break; + + case PRESSURE_UNIT_INVALID: + case PRESSURE_UNIT_DEFAULT: + default: + g_warning("Conversion to illegal pressure unit: %d", info->pressure_unit); + return _("Unknown"); + } + + return buf; +} + +const gchar *weather_info_get_visibility(WeatherInfo *info) { + static gchar buf[100]; + + g_return_val_if_fail(info != NULL, NULL); + + if (!info->valid) + return "-"; + if (info->visibility < 0.0) + return _("Unknown"); + + switch (info->distance_unit) { + case DISTANCE_UNIT_MILES: + /* Translators: This is the visibility in miles */ + g_snprintf(buf, sizeof(buf), _("%.1f miles"), info->visibility); + break; + case DISTANCE_UNIT_KM: + /* Translators: This is the visibility in kilometers */ + g_snprintf(buf, sizeof(buf), _("%.1f km"), + VISIBILITY_SM_TO_KM(info->visibility)); + break; + case DISTANCE_UNIT_METERS: + /* Translators: This is the visibility in meters */ + g_snprintf(buf, sizeof(buf), _("%.0fm"), + VISIBILITY_SM_TO_M(info->visibility)); + break; + + case DISTANCE_UNIT_INVALID: + case DISTANCE_UNIT_DEFAULT: + default: + g_warning("Conversion to illegal visibility unit: %d", info->pressure_unit); + return _("Unknown"); + } + + return buf; +} + +const gchar *weather_info_get_sunrise(WeatherInfo *info) { + static gchar buf[200]; + struct tm tm; + + g_return_val_if_fail(info && info->location, NULL); + + if (!info->location->latlon_valid) + return "-"; + if (!info->valid) + return "-"; + if (!calc_sun(info)) + return "-"; + + localtime_r(&info->sunrise, &tm); + if (strftime(buf, sizeof(buf), _("%H:%M"), &tm) <= 0) + return "-"; + return buf; +} + +const gchar *weather_info_get_sunset(WeatherInfo *info) { + static gchar buf[200]; + struct tm tm; + + g_return_val_if_fail(info && info->location, NULL); + + if (!info->location->latlon_valid) + return "-"; + if (!info->valid) + return "-"; + if (!calc_sun(info)) + return "-"; + + localtime_r(&info->sunset, &tm); + if (strftime(buf, sizeof(buf), _("%H:%M"), &tm) <= 0) + return "-"; + return buf; +} + +const gchar *weather_info_get_forecast(WeatherInfo *info) { + g_return_val_if_fail(info != NULL, NULL); + return info->forecast; } /** @@ -1107,542 +1087,509 @@ weather_info_get_forecast (WeatherInfo *info) * The 'update' property is the date/time when the forecast info * is used for. **/ -GSList * -weather_info_get_forecast_list (WeatherInfo *info) -{ - g_return_val_if_fail (info != NULL, NULL); - - if (!info->valid) - return NULL; - - return info->forecast_list; -} - -GdkPixbufAnimation * -weather_info_get_radar (WeatherInfo *info) -{ - g_return_val_if_fail (info != NULL, NULL); - return info->radar; -} - -const gchar * -weather_info_get_temp_summary (WeatherInfo *info) -{ - g_return_val_if_fail (info != NULL, NULL); - - if (!info->valid || info->temp < -500.0) - return "--"; - - return temperature_string (info->temp, info->temperature_unit, TRUE); - -} - -gchar * -weather_info_get_weather_summary (WeatherInfo *info) -{ - const gchar *buf; - - g_return_val_if_fail (info != NULL, NULL); - - if (!info->valid) - return g_strdup (_("Retrieval failed")); - buf = weather_info_get_conditions (info); - if (!strcmp (buf, "-")) - buf = weather_info_get_sky (info); - return g_strdup_printf ("%s: %s", weather_info_get_location_name (info), buf); -} - -const gchar * -weather_info_get_icon_name (WeatherInfo *info) -{ - WeatherConditions cond; - WeatherSky sky; - time_t current_time; - gboolean daytime; - gchar* icon; - static gchar icon_buffer[32]; - WeatherMoonPhase moonPhase; - WeatherMoonLatitude moonLat; - gint phase; - - g_return_val_if_fail (info != NULL, NULL); - - if (!info->valid) - return NULL; - - cond = info->cond; - sky = info->sky; - - if (cond.significant) { - if (cond.phenomenon != PHENOMENON_NONE && - cond.qualifier == QUALIFIER_THUNDERSTORM) - return "weather-storm"; - - switch (cond.phenomenon) { - case PHENOMENON_INVALID: - case PHENOMENON_LAST: - case PHENOMENON_NONE: - break; - - case PHENOMENON_DRIZZLE: - case PHENOMENON_RAIN: - case PHENOMENON_UNKNOWN_PRECIPITATION: - case PHENOMENON_HAIL: - case PHENOMENON_SMALL_HAIL: - return "weather-showers"; - - case PHENOMENON_SNOW: - case PHENOMENON_SNOW_GRAINS: - case PHENOMENON_ICE_PELLETS: - case PHENOMENON_ICE_CRYSTALS: - return "weather-snow"; - - case PHENOMENON_TORNADO: - case PHENOMENON_SQUALL: - return "weather-storm"; - - case PHENOMENON_MIST: - case PHENOMENON_FOG: - case PHENOMENON_SMOKE: - case PHENOMENON_VOLCANIC_ASH: - case PHENOMENON_SAND: - case PHENOMENON_HAZE: - case PHENOMENON_SPRAY: - case PHENOMENON_DUST: - case PHENOMENON_SANDSTORM: - case PHENOMENON_DUSTSTORM: - case PHENOMENON_FUNNEL_CLOUD: - case PHENOMENON_DUST_WHIRLS: - return "weather-fog"; - } +GSList *weather_info_get_forecast_list(WeatherInfo *info) { + g_return_val_if_fail(info != NULL, NULL); + + if (!info->valid) + return NULL; + + return info->forecast_list; +} + +GdkPixbufAnimation *weather_info_get_radar(WeatherInfo *info) { + g_return_val_if_fail(info != NULL, NULL); + return info->radar; +} + +const gchar *weather_info_get_temp_summary(WeatherInfo *info) { + g_return_val_if_fail(info != NULL, NULL); + + if (!info->valid || info->temp < -500.0) + return "--"; + + return temperature_string(info->temp, info->temperature_unit, TRUE); +} + +gchar *weather_info_get_weather_summary(WeatherInfo *info) { + const gchar *buf; + + g_return_val_if_fail(info != NULL, NULL); + + if (!info->valid) + return g_strdup(_("Retrieval failed")); + buf = weather_info_get_conditions(info); + if (!strcmp(buf, "-")) + buf = weather_info_get_sky(info); + return g_strdup_printf("%s: %s", weather_info_get_location_name(info), buf); +} + +const gchar *weather_info_get_icon_name(WeatherInfo *info) { + WeatherConditions cond; + WeatherSky sky; + time_t current_time; + gboolean daytime; + gchar *icon; + static gchar icon_buffer[32]; + WeatherMoonPhase moonPhase; + WeatherMoonLatitude moonLat; + gint phase; + + g_return_val_if_fail(info != NULL, NULL); + + if (!info->valid) + return NULL; + + cond = info->cond; + sky = info->sky; + + if (cond.significant) { + if (cond.phenomenon != PHENOMENON_NONE && + cond.qualifier == QUALIFIER_THUNDERSTORM) + return "weather-storm"; + + switch (cond.phenomenon) { + case PHENOMENON_INVALID: + case PHENOMENON_LAST: + case PHENOMENON_NONE: + break; + + case PHENOMENON_DRIZZLE: + case PHENOMENON_RAIN: + case PHENOMENON_UNKNOWN_PRECIPITATION: + case PHENOMENON_HAIL: + case PHENOMENON_SMALL_HAIL: + return "weather-showers"; + + case PHENOMENON_SNOW: + case PHENOMENON_SNOW_GRAINS: + case PHENOMENON_ICE_PELLETS: + case PHENOMENON_ICE_CRYSTALS: + return "weather-snow"; + + case PHENOMENON_TORNADO: + case PHENOMENON_SQUALL: + return "weather-storm"; + + case PHENOMENON_MIST: + case PHENOMENON_FOG: + case PHENOMENON_SMOKE: + case PHENOMENON_VOLCANIC_ASH: + case PHENOMENON_SAND: + case PHENOMENON_HAZE: + case PHENOMENON_SPRAY: + case PHENOMENON_DUST: + case PHENOMENON_SANDSTORM: + case PHENOMENON_DUSTSTORM: + case PHENOMENON_FUNNEL_CLOUD: + case PHENOMENON_DUST_WHIRLS: + return "weather-fog"; + } + } + + if (info->midnightSun || (!info->sunriseValid && !info->sunsetValid)) + daytime = TRUE; + else if (info->polarNight) + daytime = FALSE; + else { + current_time = time(NULL); + daytime = (!info->sunriseValid || (current_time >= info->sunrise)) && + (!info->sunsetValid || (current_time < info->sunset)); + } + + switch (sky) { + case SKY_INVALID: + case SKY_LAST: + case SKY_CLEAR: + if (daytime) + return "weather-clear"; + else { + icon = g_stpcpy(icon_buffer, "weather-clear-night"); + break; } - if (info->midnightSun || - (!info->sunriseValid && !info->sunsetValid)) - daytime = TRUE; - else if (info->polarNight) - daytime = FALSE; + case SKY_BROKEN: + case SKY_SCATTERED: + case SKY_FEW: + if (daytime) + return "weather-few-clouds"; else { - current_time = time (NULL); - daytime = - ( !info->sunriseValid || (current_time >= info->sunrise) ) && - ( !info->sunsetValid || (current_time < info->sunset) ); + icon = g_stpcpy(icon_buffer, "weather-few-clouds-night"); + break; } - switch (sky) { - case SKY_INVALID: - case SKY_LAST: - case SKY_CLEAR: - if (daytime) - return "weather-clear"; - else { - icon = g_stpcpy(icon_buffer, "weather-clear-night"); - break; - } - - case SKY_BROKEN: - case SKY_SCATTERED: - case SKY_FEW: - if (daytime) - return "weather-few-clouds"; - else { - icon = g_stpcpy(icon_buffer, "weather-few-clouds-night"); - break; - } - - case SKY_OVERCAST: - return "weather-overcast"; - - default: /* unrecognized */ - return NULL; + case SKY_OVERCAST: + return "weather-overcast"; + + default: /* unrecognized */ + return NULL; + } + + /* + * A phase-of-moon icon is to be returned. + * Determine which one based on the moon's location + */ + if (info->moonValid && + weather_info_get_value_moonphase(info, &moonPhase, &moonLat)) { + phase = (gint)((moonPhase * MOON_PHASES / 360.) + 0.5); + if (phase == MOON_PHASES) { + phase = 0; + } else if (phase > 0 && + (RADIANS_TO_DEGREES(weather_info_get_location(info)->latitude) < + moonLat)) { + /* + * Locations south of the moon's latitude will see the moon in the + * northern sky. The moon waxes and wanes from left to right + * so we reference an icon running in the opposite direction. + */ + phase = MOON_PHASES - phase; } /* - * A phase-of-moon icon is to be returned. - * Determine which one based on the moon's location + * If the moon is not full then append the angle to the icon string. + * Note that an icon by this name is not required to exist: + * the caller can use GTK_ICON_LOOKUP_GENERIC_FALLBACK to fall back to + * the full moon image. */ - if (info->moonValid && weather_info_get_value_moonphase(info, &moonPhase, &moonLat)) { - phase = (gint)((moonPhase * MOON_PHASES / 360.) + 0.5); - if (phase == MOON_PHASES) { - phase = 0; - } else if (phase > 0 && - (RADIANS_TO_DEGREES(weather_info_get_location(info)->latitude) - < moonLat)) { - /* - * Locations south of the moon's latitude will see the moon in the - * northern sky. The moon waxes and wanes from left to right - * so we reference an icon running in the opposite direction. - */ - phase = MOON_PHASES - phase; - } - - /* - * If the moon is not full then append the angle to the icon string. - * Note that an icon by this name is not required to exist: - * the caller can use GTK_ICON_LOOKUP_GENERIC_FALLBACK to fall back to - * the full moon image. - */ - if ((0 == (MOON_PHASES & 0x1)) && (MOON_PHASES/2 != phase)) { - g_snprintf(icon, sizeof(icon_buffer) - strlen(icon_buffer), - "-%03d", phase * 360 / MOON_PHASES); - } + if ((0 == (MOON_PHASES & 0x1)) && (MOON_PHASES / 2 != phase)) { + g_snprintf(icon, sizeof(icon_buffer) - strlen(icon_buffer), "-%03d", + phase * 360 / MOON_PHASES); } - return icon_buffer; -} - -static gboolean -temperature_value (gdouble temp_f, - TempUnit to_unit, - gdouble *value, - TempUnit def_unit) -{ - gboolean ok = TRUE; - - *value = 0.0; - if (temp_f < -500.0) - return FALSE; - - if (to_unit == TEMP_UNIT_DEFAULT) - to_unit = def_unit; - - switch (to_unit) { - case TEMP_UNIT_FAHRENHEIT: - *value = temp_f; - break; - case TEMP_UNIT_CENTIGRADE: - *value = TEMP_F_TO_C (temp_f); - break; - case TEMP_UNIT_KELVIN: - *value = TEMP_F_TO_K (temp_f); - break; - case TEMP_UNIT_INVALID: - case TEMP_UNIT_DEFAULT: - default: - ok = FALSE; - break; - } - - return ok; -} - -static gboolean -speed_value (gdouble knots, SpeedUnit to_unit, gdouble *value, SpeedUnit def_unit) -{ - gboolean ok = TRUE; - - *value = -1.0; - - if (knots < 0.0) - return FALSE; - - if (to_unit == SPEED_UNIT_DEFAULT) - to_unit = def_unit; - - switch (to_unit) { - case SPEED_UNIT_KNOTS: - *value = knots; - break; - case SPEED_UNIT_MPH: - *value = WINDSPEED_KNOTS_TO_MPH (knots); - break; - case SPEED_UNIT_KPH: - *value = WINDSPEED_KNOTS_TO_KPH (knots); - break; - case SPEED_UNIT_MS: - *value = WINDSPEED_KNOTS_TO_MS (knots); - break; - case SPEED_UNIT_BFT: - *value = WINDSPEED_KNOTS_TO_BFT (knots); - break; - case SPEED_UNIT_INVALID: - case SPEED_UNIT_DEFAULT: - default: - ok = FALSE; - break; - } - - return ok; -} - -static gboolean -pressure_value (gdouble inHg, PressureUnit to_unit, gdouble *value, PressureUnit def_unit) -{ - gboolean ok = TRUE; - - *value = -1.0; - - if (inHg < 0.0) - return FALSE; - - if (to_unit == PRESSURE_UNIT_DEFAULT) - to_unit = def_unit; - - switch (to_unit) { - case PRESSURE_UNIT_INCH_HG: - *value = inHg; - break; - case PRESSURE_UNIT_MM_HG: - *value = PRESSURE_INCH_TO_MM (inHg); - break; - case PRESSURE_UNIT_KPA: - *value = PRESSURE_INCH_TO_KPA (inHg); - break; - case PRESSURE_UNIT_HPA: - *value = PRESSURE_INCH_TO_HPA (inHg); - break; - case PRESSURE_UNIT_MB: - *value = PRESSURE_INCH_TO_MB (inHg); - break; - case PRESSURE_UNIT_ATM: - *value = PRESSURE_INCH_TO_ATM (inHg); - break; - case PRESSURE_UNIT_INVALID: - case PRESSURE_UNIT_DEFAULT: - default: - ok = FALSE; - break; - } - - return ok; -} - -static gboolean -distance_value (gdouble miles, DistanceUnit to_unit, gdouble *value, DistanceUnit def_unit) -{ - gboolean ok = TRUE; - - *value = -1.0; - - if (miles < 0.0) - return FALSE; - - if (to_unit == DISTANCE_UNIT_DEFAULT) - to_unit = def_unit; - - switch (to_unit) { - case DISTANCE_UNIT_MILES: - *value = miles; - break; - case DISTANCE_UNIT_KM: - *value = VISIBILITY_SM_TO_KM (miles); - break; - case DISTANCE_UNIT_METERS: - *value = VISIBILITY_SM_TO_M (miles); - break; - case DISTANCE_UNIT_INVALID: - case DISTANCE_UNIT_DEFAULT: - default: - ok = FALSE; - break; - } - - return ok; -} - -gboolean -weather_info_get_value_sky (WeatherInfo *info, WeatherSky *sky) -{ - g_return_val_if_fail (info != NULL, FALSE); - g_return_val_if_fail (sky != NULL, FALSE); - - if (!info->valid) - return FALSE; - - if (info->sky <= SKY_INVALID || info->sky >= SKY_LAST) - return FALSE; - - *sky = info->sky; - - return TRUE; + } + return icon_buffer; +} + +static gboolean temperature_value(gdouble temp_f, TempUnit to_unit, + gdouble *value, TempUnit def_unit) { + gboolean ok = TRUE; + + *value = 0.0; + if (temp_f < -500.0) + return FALSE; + + if (to_unit == TEMP_UNIT_DEFAULT) + to_unit = def_unit; + + switch (to_unit) { + case TEMP_UNIT_FAHRENHEIT: + *value = temp_f; + break; + case TEMP_UNIT_CENTIGRADE: + *value = TEMP_F_TO_C(temp_f); + break; + case TEMP_UNIT_KELVIN: + *value = TEMP_F_TO_K(temp_f); + break; + case TEMP_UNIT_INVALID: + case TEMP_UNIT_DEFAULT: + default: + ok = FALSE; + break; + } + + return ok; +} + +static gboolean speed_value(gdouble knots, SpeedUnit to_unit, gdouble *value, + SpeedUnit def_unit) { + gboolean ok = TRUE; + + *value = -1.0; + + if (knots < 0.0) + return FALSE; + + if (to_unit == SPEED_UNIT_DEFAULT) + to_unit = def_unit; + + switch (to_unit) { + case SPEED_UNIT_KNOTS: + *value = knots; + break; + case SPEED_UNIT_MPH: + *value = WINDSPEED_KNOTS_TO_MPH(knots); + break; + case SPEED_UNIT_KPH: + *value = WINDSPEED_KNOTS_TO_KPH(knots); + break; + case SPEED_UNIT_MS: + *value = WINDSPEED_KNOTS_TO_MS(knots); + break; + case SPEED_UNIT_BFT: + *value = WINDSPEED_KNOTS_TO_BFT(knots); + break; + case SPEED_UNIT_INVALID: + case SPEED_UNIT_DEFAULT: + default: + ok = FALSE; + break; + } + + return ok; +} + +static gboolean pressure_value(gdouble inHg, PressureUnit to_unit, + gdouble *value, PressureUnit def_unit) { + gboolean ok = TRUE; + + *value = -1.0; + + if (inHg < 0.0) + return FALSE; + + if (to_unit == PRESSURE_UNIT_DEFAULT) + to_unit = def_unit; + + switch (to_unit) { + case PRESSURE_UNIT_INCH_HG: + *value = inHg; + break; + case PRESSURE_UNIT_MM_HG: + *value = PRESSURE_INCH_TO_MM(inHg); + break; + case PRESSURE_UNIT_KPA: + *value = PRESSURE_INCH_TO_KPA(inHg); + break; + case PRESSURE_UNIT_HPA: + *value = PRESSURE_INCH_TO_HPA(inHg); + break; + case PRESSURE_UNIT_MB: + *value = PRESSURE_INCH_TO_MB(inHg); + break; + case PRESSURE_UNIT_ATM: + *value = PRESSURE_INCH_TO_ATM(inHg); + break; + case PRESSURE_UNIT_INVALID: + case PRESSURE_UNIT_DEFAULT: + default: + ok = FALSE; + break; + } + + return ok; +} + +static gboolean distance_value(gdouble miles, DistanceUnit to_unit, + gdouble *value, DistanceUnit def_unit) { + gboolean ok = TRUE; + + *value = -1.0; + + if (miles < 0.0) + return FALSE; + + if (to_unit == DISTANCE_UNIT_DEFAULT) + to_unit = def_unit; + + switch (to_unit) { + case DISTANCE_UNIT_MILES: + *value = miles; + break; + case DISTANCE_UNIT_KM: + *value = VISIBILITY_SM_TO_KM(miles); + break; + case DISTANCE_UNIT_METERS: + *value = VISIBILITY_SM_TO_M(miles); + break; + case DISTANCE_UNIT_INVALID: + case DISTANCE_UNIT_DEFAULT: + default: + ok = FALSE; + break; + } + + return ok; +} + +gboolean weather_info_get_value_sky(WeatherInfo *info, WeatherSky *sky) { + g_return_val_if_fail(info != NULL, FALSE); + g_return_val_if_fail(sky != NULL, FALSE); + + if (!info->valid) + return FALSE; + + if (info->sky <= SKY_INVALID || info->sky >= SKY_LAST) + return FALSE; + + *sky = info->sky; + + return TRUE; } gboolean -weather_info_get_value_conditions (WeatherInfo *info, WeatherConditionPhenomenon *phenomenon, WeatherConditionQualifier *qualifier) -{ - g_return_val_if_fail (info != NULL, FALSE); - g_return_val_if_fail (phenomenon != NULL, FALSE); - g_return_val_if_fail (qualifier != NULL, FALSE); +weather_info_get_value_conditions(WeatherInfo *info, + WeatherConditionPhenomenon *phenomenon, + WeatherConditionQualifier *qualifier) { + g_return_val_if_fail(info != NULL, FALSE); + g_return_val_if_fail(phenomenon != NULL, FALSE); + g_return_val_if_fail(qualifier != NULL, FALSE); - if (!info->valid) - return FALSE; + if (!info->valid) + return FALSE; - if (!info->cond.significant) - return FALSE; + if (!info->cond.significant) + return FALSE; - if (!(info->cond.phenomenon > PHENOMENON_INVALID && - info->cond.phenomenon < PHENOMENON_LAST && - info->cond.qualifier > QUALIFIER_INVALID && - info->cond.qualifier < QUALIFIER_LAST)) - return FALSE; + if (!(info->cond.phenomenon > PHENOMENON_INVALID && + info->cond.phenomenon < PHENOMENON_LAST && + info->cond.qualifier > QUALIFIER_INVALID && + info->cond.qualifier < QUALIFIER_LAST)) + return FALSE; - *phenomenon = info->cond.phenomenon; - *qualifier = info->cond.qualifier; + *phenomenon = info->cond.phenomenon; + *qualifier = info->cond.qualifier; - return TRUE; + return TRUE; } -gboolean -weather_info_get_value_temp (WeatherInfo *info, TempUnit unit, gdouble *value) -{ - g_return_val_if_fail (info != NULL, FALSE); - g_return_val_if_fail (value != NULL, FALSE); +gboolean weather_info_get_value_temp(WeatherInfo *info, TempUnit unit, + gdouble *value) { + g_return_val_if_fail(info != NULL, FALSE); + g_return_val_if_fail(value != NULL, FALSE); - if (!info->valid) - return FALSE; + if (!info->valid) + return FALSE; - return temperature_value (info->temp, unit, value, info->temperature_unit); + return temperature_value(info->temp, unit, value, info->temperature_unit); } -gboolean -weather_info_get_value_temp_min (WeatherInfo *info, TempUnit unit, gdouble *value) -{ - g_return_val_if_fail (info != NULL, FALSE); - g_return_val_if_fail (value != NULL, FALSE); +gboolean weather_info_get_value_temp_min(WeatherInfo *info, TempUnit unit, + gdouble *value) { + g_return_val_if_fail(info != NULL, FALSE); + g_return_val_if_fail(value != NULL, FALSE); - if (!info->valid || !info->tempMinMaxValid) - return FALSE; + if (!info->valid || !info->tempMinMaxValid) + return FALSE; - return temperature_value (info->temp_min, unit, value, info->temperature_unit); + return temperature_value(info->temp_min, unit, value, info->temperature_unit); } -gboolean -weather_info_get_value_temp_max (WeatherInfo *info, TempUnit unit, gdouble *value) -{ - g_return_val_if_fail (info != NULL, FALSE); - g_return_val_if_fail (value != NULL, FALSE); +gboolean weather_info_get_value_temp_max(WeatherInfo *info, TempUnit unit, + gdouble *value) { + g_return_val_if_fail(info != NULL, FALSE); + g_return_val_if_fail(value != NULL, FALSE); - if (!info->valid || !info->tempMinMaxValid) - return FALSE; + if (!info->valid || !info->tempMinMaxValid) + return FALSE; - return temperature_value (info->temp_max, unit, value, info->temperature_unit); + return temperature_value(info->temp_max, unit, value, info->temperature_unit); } -gboolean -weather_info_get_value_dew (WeatherInfo *info, TempUnit unit, gdouble *value) -{ - g_return_val_if_fail (info != NULL, FALSE); - g_return_val_if_fail (value != NULL, FALSE); +gboolean weather_info_get_value_dew(WeatherInfo *info, TempUnit unit, + gdouble *value) { + g_return_val_if_fail(info != NULL, FALSE); + g_return_val_if_fail(value != NULL, FALSE); - if (!info->valid) - return FALSE; + if (!info->valid) + return FALSE; - return temperature_value (info->dew, unit, value, info->temperature_unit); + return temperature_value(info->dew, unit, value, info->temperature_unit); } -gboolean -weather_info_get_value_apparent (WeatherInfo *info, TempUnit unit, gdouble *value) -{ - g_return_val_if_fail (info != NULL, FALSE); - g_return_val_if_fail (value != NULL, FALSE); +gboolean weather_info_get_value_apparent(WeatherInfo *info, TempUnit unit, + gdouble *value) { + g_return_val_if_fail(info != NULL, FALSE); + g_return_val_if_fail(value != NULL, FALSE); - if (!info->valid) - return FALSE; + if (!info->valid) + return FALSE; - return temperature_value (calc_apparent (info), unit, value, info->temperature_unit); + return temperature_value(calc_apparent(info), unit, value, + info->temperature_unit); } -gboolean -weather_info_get_value_update (WeatherInfo *info, time_t *value) -{ - g_return_val_if_fail (info != NULL, FALSE); - g_return_val_if_fail (value != NULL, FALSE); +gboolean weather_info_get_value_update(WeatherInfo *info, time_t *value) { + g_return_val_if_fail(info != NULL, FALSE); + g_return_val_if_fail(value != NULL, FALSE); - if (!info->valid) - return FALSE; + if (!info->valid) + return FALSE; - *value = info->update; + *value = info->update; - return TRUE; + return TRUE; } -gboolean -weather_info_get_value_sunrise (WeatherInfo *info, time_t *value) -{ - g_return_val_if_fail (info != NULL, FALSE); - g_return_val_if_fail (value != NULL, FALSE); +gboolean weather_info_get_value_sunrise(WeatherInfo *info, time_t *value) { + g_return_val_if_fail(info != NULL, FALSE); + g_return_val_if_fail(value != NULL, FALSE); - if (!info->valid || !info->sunriseValid) - return FALSE; + if (!info->valid || !info->sunriseValid) + return FALSE; - *value = info->sunrise; + *value = info->sunrise; - return TRUE; + return TRUE; } -gboolean -weather_info_get_value_sunset (WeatherInfo *info, time_t *value) -{ - g_return_val_if_fail (info != NULL, FALSE); - g_return_val_if_fail (value != NULL, FALSE); +gboolean weather_info_get_value_sunset(WeatherInfo *info, time_t *value) { + g_return_val_if_fail(info != NULL, FALSE); + g_return_val_if_fail(value != NULL, FALSE); - if (!info->valid || !info->sunsetValid) - return FALSE; + if (!info->valid || !info->sunsetValid) + return FALSE; - *value = info->sunset; + *value = info->sunset; - return TRUE; + return TRUE; } -gboolean -weather_info_get_value_moonphase (WeatherInfo *info, - WeatherMoonPhase *value, - WeatherMoonLatitude *lat) -{ - g_return_val_if_fail (info != NULL, FALSE); - g_return_val_if_fail (value != NULL, FALSE); +gboolean weather_info_get_value_moonphase(WeatherInfo *info, + WeatherMoonPhase *value, + WeatherMoonLatitude *lat) { + g_return_val_if_fail(info != NULL, FALSE); + g_return_val_if_fail(value != NULL, FALSE); - if (!info->valid || !info->moonValid) - return FALSE; + if (!info->valid || !info->moonValid) + return FALSE; - *value = info->moonphase; - *lat = info->moonlatitude; + *value = info->moonphase; + *lat = info->moonlatitude; - return TRUE; + return TRUE; } -gboolean -weather_info_get_value_wind (WeatherInfo *info, SpeedUnit unit, gdouble *speed, WeatherWindDirection *direction) -{ - gboolean res = FALSE; +gboolean weather_info_get_value_wind(WeatherInfo *info, SpeedUnit unit, + gdouble *speed, + WeatherWindDirection *direction) { + gboolean res = FALSE; - g_return_val_if_fail (info != NULL, FALSE); - g_return_val_if_fail (speed != NULL, FALSE); - g_return_val_if_fail (direction != NULL, FALSE); + g_return_val_if_fail(info != NULL, FALSE); + g_return_val_if_fail(speed != NULL, FALSE); + g_return_val_if_fail(direction != NULL, FALSE); - if (!info->valid) - return FALSE; + if (!info->valid) + return FALSE; - if (info->windspeed < 0.0 || info->wind <= WIND_INVALID || info->wind >= WIND_LAST) - return FALSE; + if (info->windspeed < 0.0 || info->wind <= WIND_INVALID || + info->wind >= WIND_LAST) + return FALSE; - res = speed_value (info->windspeed, unit, speed, info->speed_unit); - *direction = info->wind; + res = speed_value(info->windspeed, unit, speed, info->speed_unit); + *direction = info->wind; - return res; + return res; } -gboolean -weather_info_get_value_pressure (WeatherInfo *info, PressureUnit unit, gdouble *value) -{ - g_return_val_if_fail (info != NULL, FALSE); - g_return_val_if_fail (value != NULL, FALSE); +gboolean weather_info_get_value_pressure(WeatherInfo *info, PressureUnit unit, + gdouble *value) { + g_return_val_if_fail(info != NULL, FALSE); + g_return_val_if_fail(value != NULL, FALSE); - if (!info->valid) - return FALSE; + if (!info->valid) + return FALSE; - return pressure_value (info->pressure, unit, value, info->pressure_unit); + return pressure_value(info->pressure, unit, value, info->pressure_unit); } -gboolean -weather_info_get_value_visibility (WeatherInfo *info, DistanceUnit unit, gdouble *value) -{ - g_return_val_if_fail (info != NULL, FALSE); - g_return_val_if_fail (value != NULL, FALSE); +gboolean weather_info_get_value_visibility(WeatherInfo *info, DistanceUnit unit, + gdouble *value) { + g_return_val_if_fail(info != NULL, FALSE); + g_return_val_if_fail(value != NULL, FALSE); - if (!info->valid) - return FALSE; + if (!info->valid) + return FALSE; - return distance_value (info->visibility, unit, value, info->distance_unit); + return distance_value(info->visibility, unit, value, info->distance_unit); } /** @@ -1654,20 +1601,17 @@ weather_info_get_value_visibility (WeatherInfo *info, DistanceUnit unit, gdouble * * Returns: gboolean indicating success or failure */ -gboolean -weather_info_get_upcoming_moonphases (WeatherInfo *info, time_t *phases) -{ - g_return_val_if_fail (info != NULL, FALSE); - g_return_val_if_fail (phases != NULL, FALSE); +gboolean weather_info_get_upcoming_moonphases(WeatherInfo *info, + time_t *phases) { + g_return_val_if_fail(info != NULL, FALSE); + g_return_val_if_fail(phases != NULL, FALSE); - return calc_moon_phases(info, phases); + return calc_moon_phases(info, phases); } -static void -_weather_internal_check (void) -{ - g_assert (G_N_ELEMENTS (wind_direction_str) == WIND_LAST); - g_assert (G_N_ELEMENTS (sky_str) == SKY_LAST); - g_assert (G_N_ELEMENTS (conditions_str) == PHENOMENON_LAST); - g_assert (G_N_ELEMENTS (conditions_str[0]) == QUALIFIER_LAST); +static void _weather_internal_check(void) { + g_assert(G_N_ELEMENTS(wind_direction_str) == WIND_LAST); + g_assert(G_N_ELEMENTS(sky_str) == SKY_LAST); + g_assert(G_N_ELEMENTS(conditions_str) == PHENOMENON_LAST); + g_assert(G_N_ELEMENTS(conditions_str[0]) == QUALIFIER_LAST); } diff --git a/libmateweather/weather.h b/libmateweather/weather.h index 842975d..7e58c00 100644 --- a/libmateweather/weather.h +++ b/libmateweather/weather.h @@ -20,7 +20,8 @@ #define __WEATHER_H_ #ifndef MATEWEATHER_I_KNOW_THIS_IS_UNSTABLE -#error "libmateweather should only be used if you understand that it's subject to change, and is not supported as a fixed API/ABI or as part of the platform" +#error \ + "libmateweather should only be used if you understand that it's subject to change, and is not supported as a fixed API/ABI or as part of the platform" #endif #include <gdk-pixbuf/gdk-pixbuf.h> @@ -34,90 +35,89 @@ extern "C" { */ struct _WeatherLocation { - gchar *name; - gchar *code; - gchar *zone; - gchar *radar; - gboolean zone_valid; - gchar *coordinates; - gdouble latitude; - gdouble longitude; - gboolean latlon_valid; - gchar *country_code; - gchar *tz_hint; + gchar *name; + gchar *code; + gchar *zone; + gchar *radar; + gboolean zone_valid; + gchar *coordinates; + gdouble latitude; + gdouble longitude; + gboolean latlon_valid; + gchar *country_code; + gchar *tz_hint; }; typedef struct _WeatherLocation WeatherLocation; -WeatherLocation * weather_location_new (const gchar *trans_name, - const gchar *code, - const gchar *zone, - const gchar *radar, - const gchar *coordinates, - const gchar *country_code, - const gchar *tz_hint); -WeatherLocation * weather_location_clone (const WeatherLocation *location); -void weather_location_free (WeatherLocation *location); -gboolean weather_location_equal (const WeatherLocation *location1, - const WeatherLocation *location2); +WeatherLocation *weather_location_new(const gchar *trans_name, + const gchar *code, const gchar *zone, + const gchar *radar, + const gchar *coordinates, + const gchar *country_code, + const gchar *tz_hint); +WeatherLocation *weather_location_clone(const WeatherLocation *location); +void weather_location_free(WeatherLocation *location); +gboolean weather_location_equal(const WeatherLocation *location1, + const WeatherLocation *location2); /* * Weather prefs */ typedef enum _WeatherForecastType { - FORECAST_STATE, - FORECAST_ZONE, - FORECAST_LIST + FORECAST_STATE, + FORECAST_ZONE, + FORECAST_LIST } WeatherForecastType; typedef enum { - TEMP_UNIT_INVALID = 0, - TEMP_UNIT_DEFAULT, - TEMP_UNIT_KELVIN, - TEMP_UNIT_CENTIGRADE, - TEMP_UNIT_FAHRENHEIT + TEMP_UNIT_INVALID = 0, + TEMP_UNIT_DEFAULT, + TEMP_UNIT_KELVIN, + TEMP_UNIT_CENTIGRADE, + TEMP_UNIT_FAHRENHEIT } TempUnit; typedef enum { - SPEED_UNIT_INVALID = 0, - SPEED_UNIT_DEFAULT, - SPEED_UNIT_MS, /* metres per second */ - SPEED_UNIT_KPH, /* kilometres per hour */ - SPEED_UNIT_MPH, /* miles per hour */ - SPEED_UNIT_KNOTS, /* Knots */ - SPEED_UNIT_BFT /* Beaufort scale */ + SPEED_UNIT_INVALID = 0, + SPEED_UNIT_DEFAULT, + SPEED_UNIT_MS, /* metres per second */ + SPEED_UNIT_KPH, /* kilometres per hour */ + SPEED_UNIT_MPH, /* miles per hour */ + SPEED_UNIT_KNOTS, /* Knots */ + SPEED_UNIT_BFT /* Beaufort scale */ } SpeedUnit; typedef enum { - PRESSURE_UNIT_INVALID = 0, - PRESSURE_UNIT_DEFAULT, - PRESSURE_UNIT_KPA, /* kiloPascal */ - PRESSURE_UNIT_HPA, /* hectoPascal */ - PRESSURE_UNIT_MB, /* 1 millibars = 1 hectoPascal */ - PRESSURE_UNIT_MM_HG, /* millimeters of mecury */ - PRESSURE_UNIT_INCH_HG, /* inches of mercury */ - PRESSURE_UNIT_ATM /* atmosphere */ + PRESSURE_UNIT_INVALID = 0, + PRESSURE_UNIT_DEFAULT, + PRESSURE_UNIT_KPA, /* kiloPascal */ + PRESSURE_UNIT_HPA, /* hectoPascal */ + PRESSURE_UNIT_MB, /* 1 millibars = 1 hectoPascal */ + PRESSURE_UNIT_MM_HG, /* millimeters of mecury */ + PRESSURE_UNIT_INCH_HG, /* inches of mercury */ + PRESSURE_UNIT_ATM /* atmosphere */ } PressureUnit; typedef enum { - DISTANCE_UNIT_INVALID = 0, - DISTANCE_UNIT_DEFAULT, - DISTANCE_UNIT_METERS, - DISTANCE_UNIT_KM, - DISTANCE_UNIT_MILES + DISTANCE_UNIT_INVALID = 0, + DISTANCE_UNIT_DEFAULT, + DISTANCE_UNIT_METERS, + DISTANCE_UNIT_KM, + DISTANCE_UNIT_MILES } DistanceUnit; struct _WeatherPrefs { - WeatherForecastType type; + WeatherForecastType type; - gboolean radar; - const char *radar_custom_url; + gboolean radar; + const char *radar_custom_url; - TempUnit temperature_unit; - SpeedUnit speed_unit; - PressureUnit pressure_unit; - DistanceUnit distance_unit; + TempUnit temperature_unit; + SpeedUnit speed_unit; + PressureUnit pressure_unit; + DistanceUnit distance_unit; }; typedef struct _WeatherPrefs WeatherPrefs; @@ -128,155 +128,182 @@ typedef struct _WeatherPrefs WeatherPrefs; typedef struct _WeatherInfo WeatherInfo; -typedef void (*WeatherInfoFunc) (WeatherInfo *info, gpointer data); - -WeatherInfo * _weather_info_fill (WeatherInfo *info, - WeatherLocation *location, - const WeatherPrefs *prefs, - WeatherInfoFunc cb, - gpointer data); -#define weather_info_new(location, prefs, cb, data) _weather_info_fill (NULL, (location), (prefs), (cb), (data)) -#define weather_info_update(info, prefs, cb, data) _weather_info_fill ((info), NULL, (prefs), (cb), (data)) - -void weather_info_abort (WeatherInfo *info); -WeatherInfo * weather_info_clone (const WeatherInfo *info); -void weather_info_free (WeatherInfo *info); - -gboolean weather_info_is_valid (WeatherInfo *info); -gboolean weather_info_network_error (WeatherInfo *info); - -void weather_info_to_metric (WeatherInfo *info); -void weather_info_to_imperial (WeatherInfo *info); - -const WeatherLocation * weather_info_get_location (WeatherInfo *info); -const gchar * weather_info_get_location_name (WeatherInfo *info); -const gchar * weather_info_get_update (WeatherInfo *info); -const gchar * weather_info_get_sky (WeatherInfo *info); -const gchar * weather_info_get_conditions (WeatherInfo *info); -const gchar * weather_info_get_temp (WeatherInfo *info); -const gchar * weather_info_get_temp_min (WeatherInfo *info); -const gchar * weather_info_get_temp_max (WeatherInfo *info); -const gchar * weather_info_get_dew (WeatherInfo *info); -const gchar * weather_info_get_humidity (WeatherInfo *info); -const gchar * weather_info_get_wind (WeatherInfo *info); -const gchar * weather_info_get_pressure (WeatherInfo *info); -const gchar * weather_info_get_visibility (WeatherInfo *info); -const gchar * weather_info_get_apparent (WeatherInfo *info); -const gchar * weather_info_get_sunrise (WeatherInfo *info); -const gchar * weather_info_get_sunset (WeatherInfo *info); -const gchar * weather_info_get_forecast (WeatherInfo *info); -GSList * weather_info_get_forecast_list (WeatherInfo *info); -GdkPixbufAnimation * weather_info_get_radar (WeatherInfo *info); - -const gchar * weather_info_get_temp_summary (WeatherInfo *info); -gchar * weather_info_get_weather_summary(WeatherInfo *info); - -const gchar * weather_info_get_icon_name (WeatherInfo *info); -gint weather_info_next_sun_event (WeatherInfo *info); +typedef void (*WeatherInfoFunc)(WeatherInfo *info, gpointer data); + +WeatherInfo *_weather_info_fill(WeatherInfo *info, WeatherLocation *location, + const WeatherPrefs *prefs, WeatherInfoFunc cb, + gpointer data); +#define weather_info_new(location, prefs, cb, data) \ + _weather_info_fill(NULL, (location), (prefs), (cb), (data)) +#define weather_info_update(info, prefs, cb, data) \ + _weather_info_fill((info), NULL, (prefs), (cb), (data)) + +void weather_info_abort(WeatherInfo *info); +WeatherInfo *weather_info_clone(const WeatherInfo *info); +void weather_info_free(WeatherInfo *info); + +gboolean weather_info_is_valid(WeatherInfo *info); +gboolean weather_info_network_error(WeatherInfo *info); + +void weather_info_to_metric(WeatherInfo *info); +void weather_info_to_imperial(WeatherInfo *info); + +const WeatherLocation *weather_info_get_location(WeatherInfo *info); +const gchar *weather_info_get_location_name(WeatherInfo *info); +const gchar *weather_info_get_update(WeatherInfo *info); +const gchar *weather_info_get_sky(WeatherInfo *info); +const gchar *weather_info_get_conditions(WeatherInfo *info); +const gchar *weather_info_get_temp(WeatherInfo *info); +const gchar *weather_info_get_temp_min(WeatherInfo *info); +const gchar *weather_info_get_temp_max(WeatherInfo *info); +const gchar *weather_info_get_dew(WeatherInfo *info); +const gchar *weather_info_get_humidity(WeatherInfo *info); +const gchar *weather_info_get_wind(WeatherInfo *info); +const gchar *weather_info_get_pressure(WeatherInfo *info); +const gchar *weather_info_get_visibility(WeatherInfo *info); +const gchar *weather_info_get_apparent(WeatherInfo *info); +const gchar *weather_info_get_sunrise(WeatherInfo *info); +const gchar *weather_info_get_sunset(WeatherInfo *info); +const gchar *weather_info_get_forecast(WeatherInfo *info); +GSList *weather_info_get_forecast_list(WeatherInfo *info); +GdkPixbufAnimation *weather_info_get_radar(WeatherInfo *info); + +const gchar *weather_info_get_temp_summary(WeatherInfo *info); +gchar *weather_info_get_weather_summary(WeatherInfo *info); + +const gchar *weather_info_get_icon_name(WeatherInfo *info); +gint weather_info_next_sun_event(WeatherInfo *info); /* values retrieving functions */ enum _WeatherWindDirection { - WIND_INVALID = -1, - WIND_VARIABLE, - WIND_N, WIND_NNE, WIND_NE, WIND_ENE, - WIND_E, WIND_ESE, WIND_SE, WIND_SSE, - WIND_S, WIND_SSW, WIND_SW, WIND_WSW, - WIND_W, WIND_WNW, WIND_NW, WIND_NNW, - WIND_LAST + WIND_INVALID = -1, + WIND_VARIABLE, + WIND_N, + WIND_NNE, + WIND_NE, + WIND_ENE, + WIND_E, + WIND_ESE, + WIND_SE, + WIND_SSE, + WIND_S, + WIND_SSW, + WIND_SW, + WIND_WSW, + WIND_W, + WIND_WNW, + WIND_NW, + WIND_NNW, + WIND_LAST }; typedef enum _WeatherWindDirection WeatherWindDirection; enum _WeatherSky { - SKY_INVALID = -1, - SKY_CLEAR, - SKY_BROKEN, - SKY_SCATTERED, - SKY_FEW, - SKY_OVERCAST, - SKY_LAST + SKY_INVALID = -1, + SKY_CLEAR, + SKY_BROKEN, + SKY_SCATTERED, + SKY_FEW, + SKY_OVERCAST, + SKY_LAST }; typedef enum _WeatherSky WeatherSky; enum _WeatherConditionPhenomenon { - PHENOMENON_INVALID = -1, - - PHENOMENON_NONE, - - PHENOMENON_DRIZZLE, - PHENOMENON_RAIN, - PHENOMENON_SNOW, - PHENOMENON_SNOW_GRAINS, - PHENOMENON_ICE_CRYSTALS, - PHENOMENON_ICE_PELLETS, - PHENOMENON_HAIL, - PHENOMENON_SMALL_HAIL, - PHENOMENON_UNKNOWN_PRECIPITATION, - - PHENOMENON_MIST, - PHENOMENON_FOG, - PHENOMENON_SMOKE, - PHENOMENON_VOLCANIC_ASH, - PHENOMENON_SAND, - PHENOMENON_HAZE, - PHENOMENON_SPRAY, - PHENOMENON_DUST, - - PHENOMENON_SQUALL, - PHENOMENON_SANDSTORM, - PHENOMENON_DUSTSTORM, - PHENOMENON_FUNNEL_CLOUD, - PHENOMENON_TORNADO, - PHENOMENON_DUST_WHIRLS, - - PHENOMENON_LAST + PHENOMENON_INVALID = -1, + + PHENOMENON_NONE, + + PHENOMENON_DRIZZLE, + PHENOMENON_RAIN, + PHENOMENON_SNOW, + PHENOMENON_SNOW_GRAINS, + PHENOMENON_ICE_CRYSTALS, + PHENOMENON_ICE_PELLETS, + PHENOMENON_HAIL, + PHENOMENON_SMALL_HAIL, + PHENOMENON_UNKNOWN_PRECIPITATION, + + PHENOMENON_MIST, + PHENOMENON_FOG, + PHENOMENON_SMOKE, + PHENOMENON_VOLCANIC_ASH, + PHENOMENON_SAND, + PHENOMENON_HAZE, + PHENOMENON_SPRAY, + PHENOMENON_DUST, + + PHENOMENON_SQUALL, + PHENOMENON_SANDSTORM, + PHENOMENON_DUSTSTORM, + PHENOMENON_FUNNEL_CLOUD, + PHENOMENON_TORNADO, + PHENOMENON_DUST_WHIRLS, + + PHENOMENON_LAST }; typedef enum _WeatherConditionPhenomenon WeatherConditionPhenomenon; enum _WeatherConditionQualifier { - QUALIFIER_INVALID = -1, + QUALIFIER_INVALID = -1, - QUALIFIER_NONE, + QUALIFIER_NONE, - QUALIFIER_VICINITY, + QUALIFIER_VICINITY, - QUALIFIER_LIGHT, - QUALIFIER_MODERATE, - QUALIFIER_HEAVY, - QUALIFIER_SHALLOW, - QUALIFIER_PATCHES, - QUALIFIER_PARTIAL, - QUALIFIER_THUNDERSTORM, - QUALIFIER_BLOWING, - QUALIFIER_SHOWERS, - QUALIFIER_DRIFTING, - QUALIFIER_FREEZING, + QUALIFIER_LIGHT, + QUALIFIER_MODERATE, + QUALIFIER_HEAVY, + QUALIFIER_SHALLOW, + QUALIFIER_PATCHES, + QUALIFIER_PARTIAL, + QUALIFIER_THUNDERSTORM, + QUALIFIER_BLOWING, + QUALIFIER_SHOWERS, + QUALIFIER_DRIFTING, + QUALIFIER_FREEZING, - QUALIFIER_LAST + QUALIFIER_LAST }; typedef enum _WeatherConditionQualifier WeatherConditionQualifier; typedef gdouble WeatherMoonPhase; typedef gdouble WeatherMoonLatitude; -gboolean weather_info_get_value_update (WeatherInfo *info, time_t *value); -gboolean weather_info_get_value_sky (WeatherInfo *info, WeatherSky *sky); -gboolean weather_info_get_value_conditions (WeatherInfo *info, WeatherConditionPhenomenon *phenomenon, WeatherConditionQualifier *qualifier); -gboolean weather_info_get_value_temp (WeatherInfo *info, TempUnit unit, gdouble *value); -gboolean weather_info_get_value_temp_min (WeatherInfo *info, TempUnit unit, gdouble *value); -gboolean weather_info_get_value_temp_max (WeatherInfo *info, TempUnit unit, gdouble *value); -gboolean weather_info_get_value_dew (WeatherInfo *info, TempUnit unit, gdouble *value); -gboolean weather_info_get_value_apparent (WeatherInfo *info, TempUnit unit, gdouble *value); -gboolean weather_info_get_value_wind (WeatherInfo *info, SpeedUnit unit, gdouble *speed, WeatherWindDirection *direction); -gboolean weather_info_get_value_pressure (WeatherInfo *info, PressureUnit unit, gdouble *value); -gboolean weather_info_get_value_visibility (WeatherInfo *info, DistanceUnit unit, gdouble *value); -gboolean weather_info_get_value_sunrise (WeatherInfo *info, time_t *value); -gboolean weather_info_get_value_sunset (WeatherInfo *info, time_t *value); -gboolean weather_info_get_value_moonphase (WeatherInfo *info, WeatherMoonPhase *value, WeatherMoonLatitude *lat); -gboolean weather_info_get_upcoming_moonphases (WeatherInfo *info, time_t *phases); +gboolean weather_info_get_value_update(WeatherInfo *info, time_t *value); +gboolean weather_info_get_value_sky(WeatherInfo *info, WeatherSky *sky); +gboolean +weather_info_get_value_conditions(WeatherInfo *info, + WeatherConditionPhenomenon *phenomenon, + WeatherConditionQualifier *qualifier); +gboolean weather_info_get_value_temp(WeatherInfo *info, TempUnit unit, + gdouble *value); +gboolean weather_info_get_value_temp_min(WeatherInfo *info, TempUnit unit, + gdouble *value); +gboolean weather_info_get_value_temp_max(WeatherInfo *info, TempUnit unit, + gdouble *value); +gboolean weather_info_get_value_dew(WeatherInfo *info, TempUnit unit, + gdouble *value); +gboolean weather_info_get_value_apparent(WeatherInfo *info, TempUnit unit, + gdouble *value); +gboolean weather_info_get_value_wind(WeatherInfo *info, SpeedUnit unit, + gdouble *speed, + WeatherWindDirection *direction); +gboolean weather_info_get_value_pressure(WeatherInfo *info, PressureUnit unit, + gdouble *value); +gboolean weather_info_get_value_visibility(WeatherInfo *info, DistanceUnit unit, + gdouble *value); +gboolean weather_info_get_value_sunrise(WeatherInfo *info, time_t *value); +gboolean weather_info_get_value_sunset(WeatherInfo *info, time_t *value); +gboolean weather_info_get_value_moonphase(WeatherInfo *info, + WeatherMoonPhase *value, + WeatherMoonLatitude *lat); +gboolean weather_info_get_upcoming_moonphases(WeatherInfo *info, + time_t *phases); #ifdef __cplusplus } |
