Use TAILQ to make life easy.
authorRoy Marples <roy@marples.name>
Sat, 27 Sep 2014 19:20:52 +0000 (19:20 +0000)
committerRoy Marples <roy@marples.name>
Sat, 27 Sep 2014 19:20:52 +0000 (19:20 +0000)
Fix the menu refreshing while receiving new scans.

src/dhcpcd-gtk/dhcpcd-gtk.h
src/dhcpcd-gtk/main.c
src/dhcpcd-gtk/menu.c
src/dhcpcd-gtk/prefs.c
src/dhcpcd-gtk/queue.h [new file with mode: 0644]
src/dhcpcd-gtk/wpa.c

index 616c41a564ae5ca034cc3e3057246edde7e34a79..309c81401a6974e5ce5c65d3d0c14f20d6eb16b0 100644 (file)
@@ -35,6 +35,7 @@
 #include <libintl.h>
 
 #include "dhcpcd.h"
+#include "queue.h"
 
 #define PACKAGE "dhcpcd-gtk"
 
 #  define _unused
 #endif
 
+typedef struct wi_menu {
+       TAILQ_ENTRY(wi_menu) next;
+       DHCPCD_WI_SCAN *scan;
+       GtkWidget *menu;
+       GtkWidget *ssid;
+       GtkWidget *icon;
+       GtkWidget *bar;
+} WI_MENU;
+typedef TAILQ_HEAD(wi_menu_head, wi_menu) WI_MENUS;
+
 typedef struct wi_scan {
+       TAILQ_ENTRY(wi_scan) next;
        DHCPCD_IF *interface;
-       GtkWidget *menu;
        DHCPCD_WI_SCAN *scans;
-       struct wi_scan *next;
+
+       GtkWidget *ifmenu;
+       WI_MENUS menus;
 } WI_SCAN;
 
-extern WI_SCAN *wi_scans;
+typedef TAILQ_HEAD(wi_scan_head, wi_scan) WI_SCANS;
+extern WI_SCANS wi_scans;
 
 WI_SCAN * wi_scan_find(DHCPCD_WI_SCAN *);
 
@@ -62,9 +76,10 @@ void menu_update_scans(WI_SCAN *, DHCPCD_WI_SCAN *);
 
 void notify_close(void);
 
-void dhcpcd_prefs_show(DHCPCD_CONNECTION *con);
-void dhcpcd_prefs_abort(void);
-void dhcpcd_menu_abort(void);
+void prefs_show(DHCPCD_CONNECTION *con);
+void prefs_abort(void);
+void menu_abort(void);
+void wpa_abort(void);
 
 bool wpa_configure(DHCPCD_WPA *, DHCPCD_WI_SCAN *);
 
index d91bc424c67b3f74fefcce420a3f2c940e48c709..249881f14257f54a7deb09ff0a6cb06375fd7f25 100644 (file)
@@ -56,7 +56,7 @@ struct watch {
 };
 static struct watch *watches;
 
-WI_SCAN *wi_scans;
+WI_SCANwi_scans;
 
 static gboolean dhcpcd_try_open(gpointer data);
 static gboolean dhcpcd_wpa_try_open(gpointer data);
@@ -67,12 +67,10 @@ wi_scan_find(DHCPCD_WI_SCAN *scan)
        WI_SCAN *w;
        DHCPCD_WI_SCAN *dw;
 
-       for (w = wi_scans; w; w = w->next) {
+       TAILQ_FOREACH(w, &wi_scans, next) {
                for (dw = w->scans; dw; dw = dw->next)
                        if (dw == scan)
-                               break;
-               if (dw)
-                       return w;
+                               return w;
        }
        return NULL;
 }
@@ -341,13 +339,13 @@ dhcpcd_status_cb(DHCPCD_CONNECTION *con, const char *status,
                gtk_status_icon_set_from_icon_name(status_icon,
                    "network-offline");
                gtk_status_icon_set_tooltip_text(status_icon, msg);
-               dhcpcd_prefs_abort();
-               dhcpcd_menu_abort();
-               while (wi_scans) {
-                       w = wi_scans->next;
-                       dhcpcd_wi_scans_free(wi_scans->scans);
-                       g_free(wi_scans);
-                       wi_scans = w;
+               prefs_abort();
+               menu_abort();
+               wpa_abort();
+               while ((w = TAILQ_FIRST(&wi_scans))) {
+                       TAILQ_REMOVE(&wi_scans, w, next);
+                       dhcpcd_wi_scans_free(w->scans);
+                       g_free(w);
                }
                dhcpcd_unwatch(-1, con);
                g_timeout_add(DHCPCD_RETRYOPEN, dhcpcd_try_open, con);
@@ -530,15 +528,17 @@ dhcpcd_wpa_scan_cb(DHCPCD_WPA *wpa, _unused void *data)
        if (scans == NULL && errno)
                g_warning("%s: %s", i->ifname, strerror(errno));
        errno = lerrno;
-       for (w = wi_scans; w; w = w->next)
+       TAILQ_FOREACH(w, &wi_scans, next) {
                if (w->interface == i)
                        break;
+       }
        if (w == NULL) {
                w = g_malloc(sizeof(*w));
                w->interface = i;
-               w->menu = NULL;
-               w->next = wi_scans;
-               wi_scans = w;
+               w->scans = scans;
+               w->ifmenu = NULL;
+               TAILQ_INIT(&w->menus);
+               TAILQ_INSERT_TAIL(&wi_scans, w, next);
        } else {
                txt = NULL;
                msg = N_("New Access Point");
@@ -563,9 +563,7 @@ dhcpcd_wpa_scan_cb(DHCPCD_WPA *wpa, _unused void *data)
                        g_free(txt);
                }
                menu_update_scans(w, scans);
-               dhcpcd_wi_scans_free(w->scans);
        }
-       w->scans = scans;
 }
 
 static void
@@ -603,6 +601,7 @@ main(int argc, char *argv[])
        notify_init(PACKAGE);
 #endif
 
+       TAILQ_INIT(&wi_scans);
        g_message(_("Connecting ..."));
        con = dhcpcd_new();
        if (con ==  NULL) {
index fed6e7246ee9a1fa3030024c9c8e37bd9c8e6cc6..df7213ee18831dd9c356c0e0bd4609eceff505b7 100644 (file)
@@ -34,28 +34,18 @@ static GtkStatusIcon *sicon;
 static GtkWidget *menu;
 static bool ifmenu;
 
-typedef struct wi_menu {
-       DHCPCD_IF *interface;
-       DHCPCD_WI_SCAN *scan;
-
-       GtkWidget *menu;
-       GtkWidget *ssid;
-       GtkWidget *icon;
-       GtkWidget *bar;
-} WI_MENU;
-static GList *wi_menus;
-
 static void
 on_pref(_unused GObject *o, gpointer data)
 {
 
-       dhcpcd_prefs_show((DHCPCD_CONNECTION *)data);
+       prefs_show((DHCPCD_CONNECTION *)data);
 }
 
 static void
 on_quit(void)
 {
 
+       wpa_abort();
        gtk_main_quit();
 }
 
@@ -130,11 +120,18 @@ on_about(_unused GtkMenuItem *item)
 }
 
 static void
-update_item(WI_MENU *m, DHCPCD_WI_SCAN *scan)
+update_item(WI_SCAN *wi, WI_MENU *m, DHCPCD_WI_SCAN *scan)
 {
        const char *icon;
        double perc;
 
+       m->scan = scan;
+
+       g_object_set_data(G_OBJECT(m->menu), "dhcpcd_wi_scan", scan);
+       gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(m->menu),
+               (wi->interface->up &&
+               g_strcmp0(wi->interface->ssid, scan->ssid)));
+
        gtk_label_set_text(GTK_LABEL(m->ssid), scan->ssid);
        if (scan->flags[0] == '\0')
                icon = "network-wireless";
@@ -158,7 +155,7 @@ update_item(WI_MENU *m, DHCPCD_WI_SCAN *scan)
 }
 
 static WI_MENU *
-create_menu(GtkWidget *m, WI_SCAN *scan, DHCPCD_WI_SCAN *wis)
+create_menu(GtkWidget *m, WI_SCAN *wis, DHCPCD_WI_SCAN *scan)
 {
        WI_MENU *wim;
        GtkWidget *box;
@@ -167,20 +164,20 @@ create_menu(GtkWidget *m, WI_SCAN *scan, DHCPCD_WI_SCAN *wis)
        char *tip;
 
        wim = g_malloc(sizeof(*wim));
-       wim->interface = scan->interface;
-       wim->scan = wis;
+       wim->scan = scan;
        wim->menu = gtk_check_menu_item_new();
        gtk_check_menu_item_set_draw_as_radio(
            GTK_CHECK_MENU_ITEM(wim->menu), true);
        box = gtk_box_new(GTK_ORIENTATION_HORIZONTAL, 4);
        gtk_container_add(GTK_CONTAINER(wim->menu), box);
-       wim->ssid = gtk_label_new(wis->ssid);
+       wim->ssid = gtk_label_new(scan->ssid);
        gtk_box_pack_start(GTK_BOX(box), wim->ssid, TRUE, TRUE, 0);
 
-       if (g_strcmp0(wis->ssid, scan->interface->ssid) == 0)
+       if (wis->interface->up &&
+           g_strcmp0(scan->ssid, wis->interface->ssid) == 0)
                gtk_check_menu_item_set_active(
                    GTK_CHECK_MENU_ITEM(wim->menu), true);
-       if (wis->flags[0] == '\0')
+       if (scan->flags[0] == '\0')
                icon = "network-wireless";
        else
                icon = "network-wireless-encrypted";
@@ -191,20 +188,20 @@ create_menu(GtkWidget *m, WI_SCAN *scan, DHCPCD_WI_SCAN *wis)
        wim->bar = gtk_progress_bar_new();
        gtk_widget_set_size_request(wim->bar, 100, -1);
        gtk_box_pack_end(GTK_BOX(box), wim->bar, FALSE, TRUE, 0);
-       perc = wis->strength.value / 100.0;
+       perc = scan->strength.value / 100.0;
        gtk_progress_bar_set_fraction(GTK_PROGRESS_BAR(wim->bar), perc);
 
-       if (wis->flags[0] == '\0')
-               gtk_widget_set_tooltip_text(wim->menu, wis->bssid);
+       if (scan->flags[0] == '\0')
+               gtk_widget_set_tooltip_text(wim->menu, scan->bssid);
        else {
-               tip = g_strconcat(wis->bssid, " ", wis->flags, NULL);
+               tip = g_strconcat(scan->bssid, " ", scan->flags, NULL);
                gtk_widget_set_tooltip_text(wim->menu, tip);
                g_free(tip);
        }
 
-       g_signal_connect(G_OBJECT(wim->menu), "activate",
+       g_signal_connect(G_OBJECT(wim->menu), "toggled",
            G_CALLBACK(ssid_hook), NULL);
-       g_object_set_data(G_OBJECT(wim->menu), "dhcpcd_wi_scan", wis);
+       g_object_set_data(G_OBJECT(wim->menu), "dhcpcd_wi_scan", scan);
        gtk_menu_shell_append(GTK_MENU_SHELL(m), wim->menu);
 
        return wim;
@@ -213,41 +210,39 @@ create_menu(GtkWidget *m, WI_SCAN *scan, DHCPCD_WI_SCAN *wis)
 void
 menu_update_scans(WI_SCAN *wi, DHCPCD_WI_SCAN *scans)
 {
-       GList *item, *next;
-       WI_MENU *wim;
+       WI_MENU *wim, *win;
        DHCPCD_WI_SCAN *s;
        bool found, added;
 
-       item = wi_menus;
-       while (item) {
-               next = item->next;
-               wim = (WI_MENU *)item->data;
-               if (wim->interface != wi->interface)
-                       goto cont;
+       if (menu == NULL) {
+               dhcpcd_wi_scans_free(wi->scans);
+               wi->scans = scans;
+               return;
+       }
+
+       TAILQ_FOREACH_SAFE(wim, &wi->menus, next, win) {
                found = false;
                for (s = scans; s; s = s->next) {
                        if (memcmp(wim->scan->bssid, s->bssid,
                            sizeof(s->bssid)) == 0)
                        {
                                found = true;
-                               update_item(wim, s);
+                               update_item(wi, wim, s);
                        }
                }
                if (!found) {
+                       TAILQ_REMOVE(&wi->menus, wim, next);
                        g_message("removed %s", wim->scan->ssid);
                        gtk_widget_destroy(wim->menu);
+                       g_free(wim->scan);
                        g_free(wim);
-                       wi_menus = g_list_delete_link(wi_menus, item);
                }
-cont:
-               item = next;
        }
 
        added = false;
        for (s = scans; s; s = s->next) {
                found = false;
-               for (item = wi_menus; item; item = item->next) {
-                       wim = (WI_MENU *)item->data;
+               TAILQ_FOREACH(wim, &wi->menus, next) {
                        if (memcmp(wim->scan->bssid, s->bssid,
                            sizeof(s->bssid)) == 0)
                        {
@@ -257,47 +252,57 @@ cont:
                }
                if (!found) {
                        added = true;
-                       wim = create_menu(wi->menu, wi, s);
+                       wim = create_menu(wi->ifmenu, wi, s);
+                       TAILQ_INSERT_TAIL(&wi->menus, wim, next);
                        gtk_widget_show_all(wim->menu);
                        g_message("added %s", wim->scan->ssid);
-                       wi_menus = g_list_append(wi_menus, wim);
                }
        }
-       if (added) {
-               gtk_widget_hide(wi->menu);
-               gtk_menu_popup(GTK_MENU(wi->menu), NULL, NULL,
-                   gtk_status_icon_position_menu, sicon,
-                   1, gtk_get_current_event_time());
-               gtk_widget_show(wi->menu);
+
+       dhcpcd_wi_scans_free(wi->scans);
+       wi->scans = scans;
+
+       if (added && gtk_widget_get_visible(wi->ifmenu)) {
+//             gtk_widget_hide(wi->ifmenu);
+//             gtk_menu_popup(GTK_MENU(wi->ifmenu), NULL, NULL,
+//                 gtk_status_icon_position_menu, sicon,
+//                 1, gtk_get_current_event_time());
+//             gtk_widget_show(wi->ifmenu);
        }
 }
 
 
 static GtkWidget *
-add_scans(WI_SCAN *scan)
+add_scans(WI_SCAN *wi)
 {
        GtkWidget *m;
        DHCPCD_WI_SCAN *wis;
        WI_MENU *wim;
 
-       if (scan->scans == NULL)
+       if (wi->scans == NULL)
                return NULL;
 
        m = gtk_menu_new();
-       for (wis = scan->scans; wis; wis = wis->next) {
-               wim = create_menu(m, scan, wis);
-               wi_menus = g_list_append(wi_menus, wim);
+       for (wis = wi->scans; wis; wis = wis->next) {
+               wim = create_menu(m, wi, wis);
+               TAILQ_INSERT_TAIL(&wi->menus, wim, next);
        }
+
        return m;
 }
 
 void
-dhcpcd_menu_abort(void)
+menu_abort(void)
 {
+       WI_SCAN *wis;
+       WI_MENU *wim;
 
-       while (wi_menus) {
-               g_free(wi_menus->data);
-               wi_menus = g_list_delete_link(wi_menus, wi_menus);
+       TAILQ_FOREACH(wis, &wi_scans, next) {
+               wis->ifmenu = NULL;
+               while ((wim = TAILQ_FIRST(&wis->menus))) {
+                       TAILQ_REMOVE(&wis->menus, wim, next);
+                       g_free(wim);
+               }
        }
 
        if (menu != NULL) {
@@ -311,18 +316,21 @@ dhcpcd_menu_abort(void)
 static void
 on_activate(GtkStatusIcon *icon)
 {
-       WI_SCAN *w;
+       WI_SCAN *w, *l;
        GtkWidget *item, *image;
 
        sicon = icon;
        notify_close();
-       dhcpcd_menu_abort();
-       if (wi_scans == NULL)
+       prefs_abort();
+       menu_abort();
+
+       if ((w = TAILQ_FIRST(&wi_scans)) == NULL)
                return;
-       if (wi_scans->next) {
+
+       if ((l = TAILQ_LAST(&wi_scans, wi_scan_head)) && l != w) {
                menu = gtk_menu_new();
                ifmenu = true;
-               for (w = wi_scans; w; w = w->next) {
+               TAILQ_FOREACH(w, &wi_scans, next) {
                        item = gtk_image_menu_item_new_with_label(
                                w->interface->ifname);
                        image = gtk_image_new_from_icon_name(
@@ -330,22 +338,19 @@ on_activate(GtkStatusIcon *icon)
                        gtk_image_menu_item_set_image(
                                GTK_IMAGE_MENU_ITEM(item), image);
                        gtk_menu_shell_append(GTK_MENU_SHELL(menu), item);
-                       w->menu = add_scans(w);
+                       w->ifmenu = add_scans(w);
                        gtk_menu_item_set_submenu(GTK_MENU_ITEM(item),
-                           w->menu);
+                           w->ifmenu);
                }
-       } else if (wi_scans->scans) {
+       } else {
                ifmenu = false;
-               wi_scans->menu = menu = add_scans(wi_scans);
-       } else
-               menu = NULL;
-
-       if (menu) {
-               gtk_widget_show_all(GTK_WIDGET(menu));
-               gtk_menu_popup(GTK_MENU(menu), NULL, NULL,
-                   gtk_status_icon_position_menu, icon,
-                   1, gtk_get_current_event_time());
+               w->ifmenu = menu = add_scans(w);
        }
+
+       gtk_widget_show_all(GTK_WIDGET(menu));
+       gtk_menu_popup(GTK_MENU(menu), NULL, NULL,
+           gtk_status_icon_position_menu, icon,
+           1, gtk_get_current_event_time());
 }
 
 static void
index 9427772e8ba0e76789ccbcbfc8b93bd7be5083e4..81752acf2a0487fb4f8b9ae1cc1efdaffcd4baee 100644 (file)
@@ -220,14 +220,14 @@ list_interfaces(DHCPCD_CONNECTION *con)
 }
 
 static GSList *
-list_ssids(WI_SCAN *scans)
+list_ssids(WI_SCANS *scans)
 {
        GSList *list, *l;
        WI_SCAN *w;
        DHCPCD_WI_SCAN *wis;
 
        list = NULL;
-       for (w = scans; w; w = w->next) {
+       TAILQ_FOREACH(w, scans, next) {
                for (wis = w->scans; wis; wis = wis->next) {
                        for (l = list; l; l = l->next)
                                if (g_strcmp0((const char *)l->data,
@@ -270,7 +270,7 @@ blocks_on_change(GtkWidget *widget, gpointer data)
        if (g_strcmp0(block, "interface") == 0)
                new_names = list_interfaces(con);
        else
-               new_names = list_ssids(wi_scans);
+               new_names = list_ssids(&wi_scans);
 
        n = 0;
        for (l = new_names; l; l = l->next) {
@@ -470,7 +470,7 @@ on_destroy(_unused GObject *o, gpointer data)
 }
 
 static void
-dhcpcd_prefs_close(void)
+prefs_close(void)
 {
        if (dialog != NULL) {
                gtk_widget_destroy(dialog);
@@ -479,11 +479,11 @@ dhcpcd_prefs_close(void)
 }
 
 void
-dhcpcd_prefs_abort(void)
+prefs_abort(void)
 {
        g_free(name);
        name = NULL;
-       dhcpcd_prefs_close();
+       prefs_close();
 }
 
 #if GTK_MAJOR_VERSION == 2
@@ -499,7 +499,7 @@ gtk_separator_new(GtkOrientation o)
 #endif
 
 void
-dhcpcd_prefs_show(DHCPCD_CONNECTION *con)
+prefs_show(DHCPCD_CONNECTION *con)
 {
        GtkWidget *dialog_vbox, *hbox, *vbox, *table, *w;
        GtkListStore *store;
@@ -640,7 +640,7 @@ dhcpcd_prefs_show(DHCPCD_CONNECTION *con)
        w = gtk_button_new_from_stock(GTK_STOCK_CLOSE);
        gtk_box_pack_end(GTK_BOX(hbox), w, false, false, 0);
        g_signal_connect(G_OBJECT(w), "clicked",
-           G_CALLBACK(dhcpcd_prefs_close), NULL);
+           G_CALLBACK(prefs_close), NULL);
 
        blocks_on_change(blocks, con);
        show_config(NULL);
diff --git a/src/dhcpcd-gtk/queue.h b/src/dhcpcd-gtk/queue.h
new file mode 100644 (file)
index 0000000..ef6a3b8
--- /dev/null
@@ -0,0 +1,176 @@
+/*     $NetBSD: queue.h,v 1.65 2013/12/25 17:19:34 christos Exp $      */
+
+/*
+ * Copyright (c) 1991, 1993
+ *     The Regents of the University of California.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ *     @(#)queue.h     8.5 (Berkeley) 8/20/94
+ */
+
+#ifndef COMPAT_QUEUE_H
+#define COMPAT_QUEUE_H
+
+#include <sys/queue.h>
+/*
+ * Tail queue definitions.
+ */
+#ifndef TAILQ_END
+#define        TAILQ_END(head)                 (NULL)
+#endif
+
+#ifndef TAILQ_HEAD
+#define        _TAILQ_HEAD(name, type, qual)                                   \
+struct name {                                                          \
+       qual type *tqh_first;           /* first element */             \
+       qual type *qual *tqh_last;      /* addr of last next element */ \
+}
+#define TAILQ_HEAD(name, type) _TAILQ_HEAD(name, struct type,)
+
+#define        TAILQ_HEAD_INITIALIZER(head)                                    \
+       { TAILQ_END(head), &(head).tqh_first }
+
+#define        _TAILQ_ENTRY(type, qual)                                        \
+struct {                                                               \
+       qual type *tqe_next;            /* next element */              \
+       qual type *qual *tqe_prev;      /* address of previous next element */\
+}
+#define TAILQ_ENTRY(type)      _TAILQ_ENTRY(struct type,)
+#endif /* !TAILQ_HEAD */
+
+/*
+ * Tail queue access methods.
+ */
+#ifndef TAILQ_FIRST
+#define        TAILQ_FIRST(head)               ((head)->tqh_first)
+#define        TAILQ_NEXT(elm, field)          ((elm)->field.tqe_next)
+#define        TAILQ_LAST(head, headname) \
+       (*(((struct headname *)((head)->tqh_last))->tqh_last))
+#define        TAILQ_PREV(elm, headname, field) \
+       (*(((struct headname *)((elm)->field.tqe_prev))->tqh_last))
+#define        TAILQ_EMPTY(head)               (TAILQ_FIRST(head) == TAILQ_END(head))
+#endif /* !TAILQ_FIRST */
+
+#ifndef TAILQ_FOREACH
+#define        TAILQ_FOREACH(var, head, field)                                 \
+       for ((var) = ((head)->tqh_first);                               \
+           (var) != TAILQ_END(head);                                   \
+           (var) = ((var)->field.tqe_next))
+
+#define        TAILQ_FOREACH_REVERSE(var, head, headname, field)               \
+       for ((var) = (*(((struct headname *)((head)->tqh_last))->tqh_last));\
+           (var) != TAILQ_END(head);                                   \
+           (var) = (*(((struct headname *)((var)->field.tqe_prev))->tqh_last)))
+#endif /* !TAILQ_FOREACH */
+
+#ifndef TAILQ_INIT
+#define        TAILQ_INIT(head) do {                                           \
+       (head)->tqh_first = TAILQ_END(head);                            \
+       (head)->tqh_last = &(head)->tqh_first;                          \
+} while (/*CONSTCOND*/0)
+
+#define        TAILQ_INSERT_HEAD(head, elm, field) do {                        \
+       if (((elm)->field.tqe_next = (head)->tqh_first) != TAILQ_END(head))\
+               (head)->tqh_first->field.tqe_prev =                     \
+                   &(elm)->field.tqe_next;                             \
+       else                                                            \
+               (head)->tqh_last = &(elm)->field.tqe_next;              \
+       (head)->tqh_first = (elm);                                      \
+       (elm)->field.tqe_prev = &(head)->tqh_first;                     \
+} while (/*CONSTCOND*/0)
+
+#define        TAILQ_INSERT_TAIL(head, elm, field) do {                        \
+       (elm)->field.tqe_next = TAILQ_END(head);                        \
+       (elm)->field.tqe_prev = (head)->tqh_last;                       \
+       *(head)->tqh_last = (elm);                                      \
+       (head)->tqh_last = &(elm)->field.tqe_next;                      \
+} while (/*CONSTCOND*/0)
+
+#define        TAILQ_INSERT_AFTER(head, listelm, elm, field) do {              \
+       if (((elm)->field.tqe_next = (listelm)->field.tqe_next) !=      \
+           TAILQ_END(head))                                            \
+               (elm)->field.tqe_next->field.tqe_prev =                 \
+                   &(elm)->field.tqe_next;                             \
+       else                                                            \
+               (head)->tqh_last = &(elm)->field.tqe_next;              \
+       (listelm)->field.tqe_next = (elm);                              \
+       (elm)->field.tqe_prev = &(listelm)->field.tqe_next;             \
+} while (/*CONSTCOND*/0)
+
+#define        TAILQ_INSERT_BEFORE(listelm, elm, field) do {                   \
+       (elm)->field.tqe_prev = (listelm)->field.tqe_prev;              \
+       (elm)->field.tqe_next = (listelm);                              \
+       *(listelm)->field.tqe_prev = (elm);                             \
+       (listelm)->field.tqe_prev = &(elm)->field.tqe_next;             \
+} while (/*CONSTCOND*/0)
+
+#define        TAILQ_REMOVE(head, elm, field) do {                             \
+       if (((elm)->field.tqe_next) != TAILQ_END(head))                 \
+               (elm)->field.tqe_next->field.tqe_prev =                 \
+                   (elm)->field.tqe_prev;                              \
+       else                                                            \
+               (head)->tqh_last = (elm)->field.tqe_prev;               \
+       *(elm)->field.tqe_prev = (elm)->field.tqe_next;                 \
+} while (/*CONSTCOND*/0)
+#endif /* !TAILQ_INIT */
+
+#ifndef TAILQ_REPLACE
+#define TAILQ_REPLACE(head, elm, elm2, field) do {                      \
+        if (((elm2)->field.tqe_next = (elm)->field.tqe_next) !=                \
+           TAILQ_END(head))                                            \
+                (elm2)->field.tqe_next->field.tqe_prev =                \
+                    &(elm2)->field.tqe_next;                            \
+        else                                                            \
+                (head)->tqh_last = &(elm2)->field.tqe_next;             \
+        (elm2)->field.tqe_prev = (elm)->field.tqe_prev;                 \
+        *(elm2)->field.tqe_prev = (elm2);                               \
+} while (/*CONSTCOND*/0)
+#endif /* !TAILQ_REPLACE */
+
+#ifndef TAILQ_FOREACH_SAFE
+#define        TAILQ_FOREACH_SAFE(var, head, field, next)                      \
+       for ((var) = TAILQ_FIRST(head);                                 \
+           (var) != TAILQ_END(head) &&                                 \
+           ((next) = TAILQ_NEXT(var, field), 1); (var) = (next))
+
+#define        TAILQ_FOREACH_REVERSE_SAFE(var, head, headname, field, prev)    \
+       for ((var) = TAILQ_LAST((head), headname);                      \
+           (var) != TAILQ_END(head) &&                                 \
+           ((prev) = TAILQ_PREV((var), headname, field), 1); (var) = (prev))
+#endif /* !TAILQ_FOREACH_SAFE */
+
+#ifndef TAILQ_CONCAT
+#define        TAILQ_CONCAT(head1, head2, field) do {                          \
+       if (!TAILQ_EMPTY(head2)) {                                      \
+               *(head1)->tqh_last = (head2)->tqh_first;                \
+               (head2)->tqh_first->field.tqe_prev = (head1)->tqh_last; \
+               (head1)->tqh_last = (head2)->tqh_last;                  \
+               TAILQ_INIT((head2));                                    \
+       }                                                               \
+} while (/*CONSTCOND*/0)
+#endif /* !TAILQ_CONCAT */
+
+#endif /* !COMAPT_QUEUE_H */
index 58feda10b3e4b38a85c7d1dde7a5a4798a0e34ba..31fcdc53de53745998bc6742750f917d7ff35b49 100644 (file)
 
 #include "dhcpcd-gtk.h"
 
+static GtkWidget *wpa_dialog, *wpa_err;
+
 static void
-wpa_dialog(const char *title, const char *txt)
+wpa_show_err(const char *title, const char *txt)
 {
-       GtkWidget *dialog;
 
-       dialog = gtk_message_dialog_new(NULL, GTK_DIALOG_MODAL,
+       if (wpa_err)
+               gtk_widget_destroy(wpa_err);
+       wpa_err = gtk_message_dialog_new(NULL, GTK_DIALOG_MODAL,
            GTK_MESSAGE_ERROR, GTK_BUTTONS_OK, "%s", txt);
-       gtk_window_set_title(GTK_WINDOW(dialog), title);
-       gtk_dialog_run(GTK_DIALOG(dialog));
-       gtk_widget_destroy(dialog);
+       gtk_window_set_title(GTK_WINDOW(wpa_err), title);
+       gtk_dialog_run(GTK_DIALOG(wpa_err));
+       gtk_widget_destroy(wpa_err);
 }
 
 static void
 onEnter(_unused GtkWidget *widget, gpointer *data)
 {
+
        gtk_dialog_response(GTK_DIALOG(data), GTK_RESPONSE_ACCEPT);
 }
 
+void
+wpa_abort(void)
+{
+
+       if (wpa_err) {
+               gtk_widget_destroy(wpa_err);
+               wpa_err = NULL;
+       }
+       if (wpa_dialog) {
+               gtk_widget_destroy(wpa_dialog);
+               wpa_dialog = NULL;
+       }
+}
+
 bool
 wpa_configure(DHCPCD_WPA *wpa, DHCPCD_WI_SCAN *scan)
 {
        DHCPCD_WI_SCAN s;
-       GtkWidget *dialog, *label, *psk, *vbox, *hbox;
+       GtkWidget *label, *psk, *vbox, *hbox;
        const char *var, *errt;
        int result;
        bool retval;
@@ -59,18 +77,21 @@ wpa_configure(DHCPCD_WPA *wpa, DHCPCD_WI_SCAN *scan)
        memcpy(&s, scan, sizeof(s));
        s.next = NULL;
 
-       dialog = gtk_dialog_new_with_buttons(s.ssid,
+       if (wpa_dialog)
+               gtk_widget_destroy(wpa_dialog);
+
+       wpa_dialog = gtk_dialog_new_with_buttons(s.ssid,
            NULL,
            GTK_DIALOG_MODAL,
            GTK_STOCK_OK, GTK_RESPONSE_ACCEPT,
            GTK_STOCK_CANCEL, GTK_RESPONSE_REJECT,
            NULL);
-       gtk_window_set_resizable(GTK_WINDOW(dialog), false);
-       gtk_window_set_icon_name(GTK_WINDOW(dialog),
+       gtk_window_set_resizable(GTK_WINDOW(wpa_dialog), false);
+       gtk_window_set_icon_name(GTK_WINDOW(wpa_dialog),
            "network-wireless-encrypted");
-       gtk_dialog_set_default_response(GTK_DIALOG(dialog),
+       gtk_dialog_set_default_response(GTK_DIALOG(wpa_dialog),
            GTK_RESPONSE_ACCEPT);
-       vbox = gtk_dialog_get_content_area(GTK_DIALOG(dialog));
+       vbox = gtk_dialog_get_content_area(GTK_DIALOG(wpa_dialog));
 
        hbox = gtk_box_new(GTK_ORIENTATION_HORIZONTAL, 2);
        label = gtk_label_new(_("Pre Shared Key:"));
@@ -78,13 +99,13 @@ wpa_configure(DHCPCD_WPA *wpa, DHCPCD_WI_SCAN *scan)
        psk = gtk_entry_new();
        gtk_entry_set_max_length(GTK_ENTRY(psk), 130);
        g_signal_connect(G_OBJECT(psk), "activate",
-           G_CALLBACK(onEnter), dialog);
+           G_CALLBACK(onEnter), wpa_dialog);
        gtk_box_pack_start(GTK_BOX(hbox), psk, true, true, 0);
        gtk_container_add(GTK_CONTAINER(vbox), hbox);
 
-       gtk_widget_show_all(dialog);
+       gtk_widget_show_all(wpa_dialog);
 again:
-       result = gtk_dialog_run(GTK_DIALOG(dialog));
+       result = gtk_dialog_run(GTK_DIALOG(wpa_dialog));
 
        retval = false;
        if (result == GTK_RESPONSE_ACCEPT) {
@@ -113,10 +134,13 @@ again:
                        break;
                }
                if (!retval) {
-                       wpa_dialog(_("Error enabling network"), errt);
+                       wpa_show_err(_("Error enabling network"), errt);
                        goto again;
                }
        }
-       gtk_widget_destroy(dialog);
+       if (wpa_dialog) {
+               gtk_widget_destroy(wpa_dialog);
+               wpa_dialog = NULL;
+       }
        return retval;
 }