emacs-elpa-diffs
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[elpa] master 6417d2c 49/76: Correctly merged old branch.


From: Ian Dunn
Subject: [elpa] master 6417d2c 49/76: Correctly merged old branch.
Date: Thu, 23 Feb 2017 19:42:52 -0500 (EST)

branch: master
commit 6417d2cef160f18c3e0e70f88dc41ea8b65cf941
Merge: 5c63470 d9cbdb9
Author: Ian Dunn <address@hidden>
Commit: Ian Dunn <address@hidden>

    Correctly merged old branch.
---
 .bzrignore         |    1 +
 Makefile           |    2 +-
 doc/connman.txt    |   29 +-
 doc/enwc.texi      |    2 +-
 doc/nm-dbus.txt    |   34 ++
 lisp/enwc-cm.el    |  388 +++++++++++---
 lisp/enwc-nm.el    | 1249 ++++++++++++++++++-------------------------
 lisp/enwc-setup.el |  146 ++---
 lisp/enwc-wicd.el  |  492 ++++++++++-------
 lisp/enwc.el       | 1497 ++++++++++++++++++++++++++++------------------------
 10 files changed, 2038 insertions(+), 1802 deletions(-)

diff --git a/.bzrignore b/.bzrignore
new file mode 100644
index 0000000..c531d98
--- /dev/null
+++ b/.bzrignore
@@ -0,0 +1 @@
+*.elc
diff --git a/Makefile b/Makefile
index 9c7fa1b..a99c195 100644
--- a/Makefile
+++ b/Makefile
@@ -1,6 +1,6 @@
 # This is part of ENWC
 #
-#  Copyright (C) 2012 Ian Dunn.
+#  Copyright (C) 2012-2016 Ian Dunn.
 #
 #  This program is free software: you can redistribute it and/or modify
 #  it under the terms of the GNU General Public License as published by
diff --git a/doc/connman.txt b/doc/connman.txt
index dafbe38..0084365 100644
--- a/doc/connman.txt
+++ b/doc/connman.txt
@@ -4,4 +4,31 @@ net.connman.Manager.GetTechnologies():
 
 net.connman.Manager.GetServices():
 
-(("/net/connman/service/wifi_0026b6e6518e_7270695f3830322e3178_managed_wep" 
(("Type" ("wifi")) ("Security" (("wep"))) ("State" ("idle")) ("Strength" (79)) 
("Favorite" (nil)) ("Immutable" (nil)) ("AutoConnect" (nil)) ("Name" 
("rpi_802.1x")) ("Ethernet" ((("Method" ("auto")) ("Interface" ("wlan0")) 
("Address" ("00:26:B6:E6:51:8E")) ("MTU" (1500))))) ("IPv4" (nil)) 
("IPv4.Configuration" ((("Method" ("dhcp"))))) ("IPv6" (nil)) 
("IPv6.Configuration" ((("Method" ("auto")) ("Privacy" ("disabled [...]
+(("/net/connman/service/wifi_0026b6e6518e_7270695f3830322e3178_managed_wep"
+  (("Type" ("wifi"))
+   ("Security" (("wep")))
+   ("State" ("idle"))
+   ("Strength" (79))
+   ("Favorite" (nil))
+   ("Immutable" (nil))
+   ("AutoConnect" (nil))
+   ("Name" ("rpi_802.1x"))
+   ("Ethernet"
+     ((("Method" ("auto"))
+     ("Interface" ("wlan0"))
+     ("Address" ("00:26:B6:E6:51:8E"))
+     ("MTU" (1500)))))
+   ("IPv4" (nil))
+   ("IPv4.Configuration" ((("Method" ("dhcp")))))
+   ("IPv6" (nil))
+   ("IPv6.Configuration" ((("Method" ("auto")) ("Privacy" ("disabled")))))
+   ("Nameservers" (nil))
+   ("Nameservers.Configuration" (nil))
+   ("Timeservers" (nil))
+   ("Timeservers.Configuration" (nil))
+   ("Domains" (nil))
+   ("Domains.Configuration" (nil))
+   ("Proxy" (nil))
+   ("Proxy.Configuration" (nil))
+   ("Provider" (nil))
+   )) ("/net/connman/service/wifi_0026b6e6518e_hidden_managed_none" (("Type" 
("wifi")) ("Security" (("none"))) ("State" ("idle")) ("Strength" (79)) 
("Favorite" (nil)) ("Immutable" (nil)) ("AutoConnect" (nil)) ("Ethernet" 
((("Method" ("auto")) ("Interface" ("wlan0")) ("Address" ("00:26:B6:E6:51:8E")) 
("MTU" (1500))))) ("IPv4" (nil)) ("IPv4.Configuration" ((("Method" ("dhcp"))))) 
("IPv6" (nil)) ("IPv6.Configuration" ((("Method" ("auto")) ("Privacy" 
("disabled"))))) ("Nameservers" (nil)) (" [...]
diff --git a/doc/enwc.texi b/doc/enwc.texi
index cc1a40f..dddb66d 100644
--- a/doc/enwc.texi
+++ b/doc/enwc.texi
@@ -15,7 +15,7 @@
 @copying
 This manual is for ENWC, the Emacs Network Client.
 
-Copyright (C) 2012 Ian Dunn
+Copyright (C) 2012,2013,2014 Ian Dunn
 
 @quotation
 Permission is granted to copy, distribute and/or modify this document
diff --git a/doc/nm-dbus.txt b/doc/nm-dbus.txt
index 89aa5a9..2d49ab0 100644
--- a/doc/nm-dbus.txt
+++ b/doc/nm-dbus.txt
@@ -354,3 +354,37 @@ Settings/0:
   </interface>
 </node>
 "
+
+GetSettings: (a{sa{sv}})
+(("connection"
+  (("id"
+    ("Wired connection 1"))
+   ("uuid"
+    ("68ef4936-b67f-4973-bd31-84ce745f3150"))
+   ("timestamp"
+    (1414346232))
+   ("type"
+    ("802-3-ethernet"))))
+ ("ipv4"
+  (("addresses"
+    (nil))
+   ("dns"
+    (nil))
+   ("method"
+    ("auto"))
+   ("routes"
+    (nil))))
+ ("802-3-ethernet"
+  (("s390-options"
+    (nil))
+   ("mac-address"
+    ((92 249 221 62 23 118)))))
+ ("ipv6"
+  (("addresses"
+    (nil))
+   ("dns"
+    (nil))
+   ("method"
+    ("auto"))
+   ("routes"
+    (nil)))))
diff --git a/lisp/enwc-cm.el b/lisp/enwc-cm.el
index 965992c..cce89d7 100644
--- a/lisp/enwc-cm.el
+++ b/lisp/enwc-cm.el
@@ -1,42 +1,40 @@
-;; enwc-cm.el
+;; enwc-cm.el --- The ConnMan back-end to ENWC.
 
-;; Copyright (C) 2012,2013 Free Software Foundation
+;; Copyright (C) 2012,2013,2014 Free Software Foundation, Inc.
 
-;; Author: Ian Dunn
-;; Keywords: enwc, network, wicd, manager, nm
+;; Author: Ian Dunn <address@hidden>
+;; Keywords: network, wicd, manager, nm
+;; Version: 2.0
+;; Homepage: https://savannah.nongnu.org/p/enwc
 
-;; This file is part of ENWC
+;; This file is part of GNU Emacs
 
-;; ENWC is free software; you can redistribute it and/or modify it
+;; GNU Emacs is free software; you can redistribute it and/or modify it
 ;; under the terms of the GNU General Public License as published by
 ;; the Free Software Foundation; either version 3, or (at your option)
 ;; any later version.
 
-;; ENWC is distributed in the hope that it will be useful, but WITHOUT
+;; GNU Emacs is distributed in the hope that it will be useful, but WITHOUT
 ;; ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
 ;; or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public
 ;; License for more details.
 
 ;; You should have received a copy of the GNU General Public License
-;; along with ENWC; see the file COPYING.  If not, write to the Free
+;; along with GNU Emacs; see the file COPYING.  If not, write to the Free
 ;; Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
 ;; 02110-1301, USA.
 
-;; connect
-;; disconnect
-;; scan
-;; get-prop
-;; save-profile
-;; get-networks
-;; check-connecting
-;; get-current-nw-id
+;;; Commentary:
 
+;; ConnMan support is still experimental.
+
+;;; Code:
 
 (require 'enwc)
 
 (defgroup enwc-cm nil
   "*ConnMan variables for ENWC"
-  :prefix "ewnc-cm-"
+  :prefix "enwc-cm-"
   :group 'enwc)
 
 (defcustom enwc-cm-dbus-service "net.connman"
@@ -54,97 +52,317 @@
   :group 'enwc-cm
   :type 'string)
 
+(defcustom enwc-cm-dbus-technology-interface "net.connman.Technology"
+  "ConnMan D-Bus Technology Interface"
+  :group 'enwc-cm
+  :type 'string)
+
+(defcustom enwc-cm-dbus-technology-path "/net/connman/technology/"
+  "ConnMan D-Bus Technology Path"
+  :group 'enwc-cm
+  :type 'string)
+
+(defcustom enwc-cm-dbus-service-path "/net/connman/service"
+  "ConnMan D-Bus Service Path"
+  :group 'enwc-cm
+  :type 'string)
+
+(defcustom enwc-cm-dbus-agent-service "org.gnu.enwc.agent"
+  "The service for the ConnMan Agent for ENWC to use."
+  :group 'enwc-cm
+  :type 'string)
+
+(defcustom enwc-cm-dbus-agent-path "/org/gnu/enwc/agent"
+  "The path to the Agent for ENWC to use for ConnMan security."
+  :group 'enwc-cm
+  :type 'string)
+
+(defcustom enwc-cm-dbus-agent-interface "org.gnu.enwc.agent"
+  "The interface for the ConnMan Agent for ENWC to use."
+  :group 'enwc-cm
+  :type 'string)
+
 (defvar enwc-cm-details-list
-  '("Name" "bssid" "Strength" "Security" "mode" "channel"))
+  '("Name" "Ethernet/Address" "Strength" "Security" "mode" "channel"))
 
-(defun enwc-cm-get-services ()
-  (dbus-call-method :system
-                   enwc-cm-dbus-service
-                   "/"
-                   enwc-cm-dbus-manager-interface
-                   "GetServices"))
+(defun enwc-cm-get-wifi-tech-path ()
+  "Return the ConnMan Wifi Technology path."
+  (concat enwc-cm-dbus-technology-path "wifi"))
 
-(defun enwc-cm-get-networks ()
-  (let ((services (enwc-cm-get-services)))
-    (mapcar 'car services)))
+(defun enwc-cm-get-wired-tech-path ()
+  "Return the ConnMan Ethernet Technology path."
+  (concat enwc-cm-dbus-technology-path "ethernet"))
 
 (defun enwc-cm-get-network (id)
   (nth id (enwc-cm-get-services)))
 
-;; scan
-(defun enwc-cm-scan (wired)
-  (dbus-call-method :system
-                   enwc-cm-dbus-service
-                   "/net/connman/technology/(ethernet|wifi)"
-                   "net.connman.Technology"
-                   "Scan"))
-
 ;; connect
 (defun enwc-cm-connect (wired id)
-  (dbus-call-method :system
-                   enwc-cm-dbus-service
-                   "/net/connman/service/serviceID"
-                   enwc-cm-dbus-service-interface
-                   "Connect"))
-
+  (let ((path (concat enwc-cm-dbus-service-path (number-to-string id))))
+    (dbus-call-method :system
+                      enwc-cm-dbus-service
+                      path
+                      enwc-cm-dbus-service-interface
+                      "Connect")))
 
+;; disconnect
 (defun enwc-cm-disconnect (wired)
   (dbus-call-method :system
-                   enwc-cm-dbus-service
-                   "/net/connman/service/CONNECTED-SERVICE"
-                   enwc-cm-dbus-service-interface
-                   "Disconnect"))
+                    enwc-cm-dbus-service
+                    "/net/connman/service/CONNECTED-SERVICE"
+                    enwc-cm-dbus-service-interface
+                    "Disconnect"))
+
+;; scan
+(defun enwc-cm-scan (wired)
+  (let ((path (if wired
+                  (enwc-cm-get-wired-tech-path)
+                (enwc-cm-get-wifi-tech-path))))
+    (dbus-call-method-asynchronously :system
+                                     path
+                                     enwc-cm-dbus-technology-interface
+                                     "Scan"
+                                     'enwc-process-scan
+                                     :timeout 6000)))
+
+;; (defun enwc-cm-scan (wired)
+;;   (dbus-call-method :system
+;;                  enwc-cm-dbus-service
+;;                  "/net/connman/technology/(ethernet|wifi)"
+;;                  "net.connman.Technology"
+;;                  "Scan"))
+
+;; get-network-props
+;; Might combine this with enwc-nm-get-dbus-dict-entry
+(defun enwc-cm-dict-assoc (dict prop)
+  (let ((path-list (split-string prop "/"))
+        (cur-list dict))
+    (while (and path-list cur-list)
+      (let ((cur-path (pop path-list)))
+        (setq cur-list
+              (when (assoc cur-path cur-list)
+                (caadr (assoc cur-path cur-list))))))
+    (if (and cur-list (consp cur-list)) (car cur-list) cur-list)))
 
 (defun enwc-cm-get-nw-prop (id prop)
   (let ((network (enwc-cm-get-network id)))
     (car (cadr (assoc prop (cadr network))))))
 
+(defun enwc-cm-get-network-props (id wired)
+  (let ((network (enwc-cm-get-network id))
+        props)
+    ;; network should be a pair, (path . props)
+    (unless network
+      (error "Invalid Network Id %d" id))
+    (setq props (cadr network))
+    (mapcar
+     (lambda (det)
+       (enwc-cm-dict-assoc props det))
+     enwc-cm-details-list)))
+
 (defun enwc-cm-get-wireless-network-property (id prop)
   (enwc-cm-get-nw-prop id prop))
 
-(defun enwc-cm-get-encryption-type (id)
-  (enwc-cm-get-nw-prop id "Security"))
+;; get-profile-props
+(defun enwc-cm-get-profile-props (prof wired)
+  (let ((network (enwc-cm-get-network prof))
+        props
+        ipv4-settings
+        dns-settings)
+    (unless network
+      (error "Invalid Network Id %d" id))
+    (setq props (cadr network))
+    (setq ipv4-settings (enwc-cm-dict-assoc "IPv4/Configuration" props)
+          dns-settings  (enwc-cm-dict-assoc "Domains/Configuration" props))
+    `((addr    . ,(cadr (assoc "Address" ipv4-settings)))
+      (netmask . ,(cadr (assoc "Netmask" ipv4-settings)))
+      (gateway . ,(cadr (assoc "Gateway" ipv4-settings)))
+      (dns1    . ,(nth 0 dns-settings))
+      (dns2    . ,(nth 1 dns-settings)))))
+
+;; get-current-nw-id
+(defun enwc-cm-is-disconnected-p (service)
+  (member (enwc-cm-dict-assoc (cadr service) "State")
+          '("idle" "disconnect")))
 
-(defun enwc-cm-get-ip-addr (wired id)
-  (let ((ipv4-config (enwc-cm-get-nw-prop id "IPv4.Configuration")))
-    (car (cadr (assoc "Address" ipv4-config)))))
+(defun enwc-cm-is-connecting-p (service)
+  (member (enwc-cm-dict-assoc (cadr service) "State")
+          '("association" "configuration")))
 
-(defun enwc-cm-get-netmask (wired id)
-  (let ((ipv4-config (enwc-cm-get-nw-prop id "IPv4.Configuration")))
-    (car (cadr (assoc "Netmask" ipv4-config)))))
+(defun enwc-cm-is-connected-p (service)
+  (member (enwc-cm-dict-assoc (cadr service) "State")
+          '("ready" "online")))
 
-(defun enwc-cm-get-gateway (wired id)
-  (let ((ipv4-config (enwc-cm-get-nw-prop id "IPv4.Configuration")))
-    (car (cadr (assoc "Gateway" ipv4-config)))))
+(defun enwc-cm--find-connected-service (services num)
+  (if services
+      (if (enwc-cm-is-connected-p (car services))
+          num
+        (enwc-cm--find-connected-service (cdr services) (1+ num)))
+    -1))
 
-(defun enwc-cm-get-dns (wired id)
-  (enwc-cm-get-nw-prop id "Nameservers.Configuration"))
+(defun enwc-cm-get-current-nw-id ()
+  "Get the current network id."
+  (let* ((services (enwc-cm-get-services)))
+    (enwc-cm--find-connected-service services 0)))
 
-(defun enwc-cm-set-nw-prop (wired id prop val)
+;; save-profile
+(defun enwc-cm-set-nw-prop (nw prop val &optional wired)
   (dbus-call-method :system
-                   enwc-cm-dbus-service
-                   (car (enwc-cm-get-network id))
-                   enwc-cm-dbus-service-interface
-                   "SetProperty"
-                   prop
-                   val))
-
-(defun enwc-cm-save-nw-settings (wired id settings)
-  (let* ((ipv4 (enwc-cm-get-nw-prop id "IPv4.Configuration"))
-        (method (car (cadr (assoc "Method" ipv4))))
-        (ip-addr (cdr (assoc "addr" settings)))
-        (netmask (cdr (assoc "netmask" settings)))
-        (gateway (cdr (assoc "gateway" settings)))
-        new-ipv4-config new-dns-config)
-    (setq new-ipv4-config
-         (list (list (cons "Method" (cons (cons method nil) nil))
-                     (cons "Address" (cons (cons ip-addr nil) nil))
-                     (cons "Netmask" (cons (cons netmask nil) nil))
-                     (cons "Gateway" (cons (cons gateway nil) nil)))))
-    (setq new-dns-config
-         (list (list (cdr (assoc "dns1" settings))
-                     (cdr (assoc "dns2" settings)))))
-    (enwc-cm-set-nw-prop wired id "IPv4.Configuration"
-                        new-ipv4-config)
-    (enwc-cm-set-nw-prop wired id "Nameservers.Configuration"
-                        new-dns-config)))
+                    enwc-cm-dbus-service
+                    (car nw)
+                    enwc-cm-dbus-service-interface
+                    "SetProperty"
+                    :string prop
+                    val))
+
+(defun enwc-cm-save-profile (prof settings wired)
+  (let ((network (enwc-cm-get-network prof))
+        props
+        ipv4-settings
+        dns-settings)
+    (unless network
+      (error "Invalid Network Id %d" id))
+    (setq props (cadr network))
+    (setq ipv4-settings
+          `((("Method" ("manual"))
+             ("Address" (,(alist-get 'addr settings "")))
+             ("Netmask" (,(alist-get 'netmask settings "")))
+             ("Gateway" (,(alist-get 'gateway settings ""))))))
+    (setq dns-settings
+          `((,(alist-get 'dns1 settings ""))
+            (,(alist-get 'dns2 settings ""))))
+    (enwc-cm-set-nw-prop prof "IPv4.Configuration" ipv4-settings wired)
+    (enwc-cm-set-nw-prop prof "Domains.Configuration" dns-settings wired)))
+
+;; check-connecting-p
+(defun enwc-cm--find-connecting-service (services)
+  (when services
+    (or (enwc-cm-is-connecting-p (car services))
+        (enwc-cm--find-connecting-service (cdr services)))))
+
+(defun enwc-cm-check-connecting-p ()
+  (let ((services (enwc-cm-get-services)))
+    (enwc-cm--find-connecting-service services)))
+
+;; get-networks
+(defun enwc-cm-get-services ()
+  (dbus-call-method :system
+                    enwc-cm-dbus-service
+                    "/"
+                    enwc-cm-dbus-manager-interface
+                    "GetServices"))
+
+(defun enwc-cm-get-networks ()
+  (let ((services (enwc-cm-get-services)))
+    (mapcar 'car services)))
+
+;; Agent
+;; ConnMan requires that an agent is registered, so we create one here.
+
+(defun enwc-cm-agent-release (&rest args)
+  )
+
+(defun enwc-cm-agent-report-error (service err)
+  )
+
+(defun enwc-cm-agent-report-peer-error (peer err))
+
+(defun enwc-cm-agent-request-browser (service url)
+  (browse-url url))
+
+(defun enwc-cm-agent-request-input (service fields)
+  "Called when a user requests input.
+SERVICE is the current service.
+FIELDS is an associative list of requested fields."
+  ;; Obtain the information from somewhere.
+  )
+
+(defun enwc-cm-agent-request-peer-authorization (peer fields))
+
+(defun enwc-cm-agent-cancel ())
+
+(defun enwc-cm-method-to-defun (method)
+  (let ((case-fold-search nil))
+    (combine-and-quote-strings
+     (mapcar 'downcase
+             (cdr (split-string
+                   (replace-regexp-in-string "\\([[:upper:]]\\)" " \\1" method)
+                   " ")))
+     "-")))
+
+(defmacro enwc-cm-agent-register-method (method)
+  "Register a method METHOD with D-Bus.
+METHOD is assumed to be the camel-case D-Bus method."
+  `((dbus-register-method :session
+                          enwc-cm-dbus-agent-service
+                          enwc-cm-dbus-agent-path
+                          enwc-cm-dbus-agent-interface
+                          ,method
+                          (quote ,(car (read-from-string
+                                        (concat
+                                         "enwc-cm-agent-"
+                                         (enwc-cm-method-to-defun 
method))))))))
+
+;; Run during setup.
+(defun enwc-cm-setup ()
+
+  ;; Setup the agent.
+  (dbus-register-service :session enwc-cm-dbus-agent-service)
+
+  (enwc-cm-agent-register-method "Release")
+  (enwc-cm-agent-register-method "ReportError")
+  (enwc-cm-agent-register-method "ReportPeerError")
+  (enwc-cm-agent-register-method "RequestBrowser")
+  (enwc-cm-agent-register-method "RequestInput")
+  (enwc-cm-agent-register-method "RequestPeerAuthorization")
+  (enwc-cm-agent-register-method "Cancel")
+
+  (dbus-call-method :system
+                    enwc-cm-dbus-manager-service
+                    enwc-cm-dbus-manager-path
+                    enwc-cm-dbus-manager-interface
+                    "RegisterAgent"
+                    :string enwc-cm-dbus-agent-path))
+
+
+;; (defun enwc-cm-get-encryption-type (id)
+;;   (enwc-cm-get-nw-prop id "Security"))
+
+;; (defun enwc-cm-get-ip-addr (wired id)
+;;   (let ((ipv4-config (enwc-cm-get-nw-prop id "IPv4.Configuration")))
+;;     (car (cadr (assoc "Address" ipv4-config)))))
+
+;; (defun enwc-cm-get-netmask (wired id)
+;;   (let ((ipv4-config (enwc-cm-get-nw-prop id "IPv4.Configuration")))
+;;     (car (cadr (assoc "Netmask" ipv4-config)))))
+
+;; (defun enwc-cm-get-gateway (wired id)
+;;   (let ((ipv4-config (enwc-cm-get-nw-prop id "IPv4.Configuration")))
+;;     (car (cadr (assoc "Gateway" ipv4-config)))))
+
+;; (defun enwc-cm-get-dns (wired id)
+;;   (enwc-cm-get-nw-prop id "Nameservers.Configuration"))
+
+;; (defun enwc-cm-save-nw-settings (wired id settings)
+;;   (let* ((ipv4 (enwc-cm-get-nw-prop id "IPv4.Configuration"))
+;;          (method (car (cadr (assoc "Method" ipv4))))
+;;          (ip-addr (cdr (assoc "addr" settings)))
+;;          (netmask (cdr (assoc "netmask" settings)))
+;;          (gateway (cdr (assoc "gateway" settings)))
+;;          new-ipv4-config new-dns-config)
+;;     (setq new-ipv4-config
+;;           (list (list (cons "Method" (cons (cons method nil) nil))
+;;                       (cons "Address" (cons (cons ip-addr nil) nil))
+;;                       (cons "Netmask" (cons (cons netmask nil) nil))
+;;                       (cons "Gateway" (cons (cons gateway nil) nil)))))
+;;     (setq new-dns-config
+;;           (list (list (cdr (assoc "dns1" settings))
+;;                       (cdr (assoc "dns2" settings)))))
+;;     (enwc-cm-set-nw-prop wired id "IPv4.Configuration"
+;;                          new-ipv4-config)
+;;     (enwc-cm-set-nw-prop wired id "Nameservers.Configuration"
+;;                          new-dns-config)))
+
+(provide 'enwc-cm)
+
+;;; enwc-cm.el ends here
diff --git a/lisp/enwc-nm.el b/lisp/enwc-nm.el
index e7dc5a3..b6499ce 100644
--- a/lisp/enwc-nm.el
+++ b/lisp/enwc-nm.el
@@ -1,28 +1,29 @@
 ;;; enwc-nm.el - The NetworkManager backend to ENWC
 
-;; Copyright (C) 2012,2013 Free Software Foundation
+;; Copyright (C) 2012-2014 Free Software Foundation, Inc.
 
-;; Author: Ian Dunn
-;; Keywords: enwc, network, wicd, manager, nm
+;; Author: Ian Dunn <address@hidden>
+;; Keywords: network, wicd, manager, nm
+;; Version: 2.0
+;; Homepage: https://savannah.nongnu.org/p/enwc
 
-;; This file is part of ENWC
+;; This file is part of GNU Emacs.
 
-;; ENWC is free software; you can redistribute it and/or modify it
+;; GNU Emacs is free software; you can redistribute it and/or modify it
 ;; under the terms of the GNU General Public License as published by
 ;; the Free Software Foundation; either version 3, or (at your option)
 ;; any later version.
 
-;; ENWC is distributed in the hope that it will be useful, but WITHOUT
+;; GNU Emacs is distributed in the hope that it will be useful, but WITHOUT
 ;; ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
 ;; or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public
 ;; License for more details.
 
 ;; You should have received a copy of the GNU General Public License
-;; along with ENWC; see the file COPYING.  If not, write to the Free
+;; along with GNU Emacs; see the file COPYING.  If not, write to the Free
 ;; Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
 ;; 02110-1301, USA.
 
-
 ;;; Commentary:
 ;;
 ;;   This requires NetworkManager >= 0.9.6
@@ -90,45 +91,25 @@
   :group 'enwc-nm
   :type 'string)
 
-(defvar enwc-nm-details-list
-  '("Ssid" "HwAddress" "Strength" "Flags" "Mode" "Frequency")
-  "The list of the desired details to be obtained from each network.")
-
-(defvar enwc-nm-sec-types
-  '(("eap-leap" . (("Name" . "eap-leap")
-                  ("reqs" . ((("identity" . "Username")
-                              ("password" . "Password"))))))
-    ("eap-peap" . (("Name" . "eap-peap")
-                  ("reqs" . ((("anonymous-identity" . "Anonymous Identity")
-                              ("ca-cert" . "CA Certificate")
-                              ("phase2-auth" . "Inner Authentication")
-                              ("phase1-peapver" . "PEAP Version")
-                              ("identity" . "Username")
-                              ("password" . "Password"))))))
-    ("eap-tls" . (("Name" . "eap-tls")
-                 ("reqs" . ((("identity" . "Identity")
-                             ("client-cert" . "User Certificate")
-                             ("ca-cert" . "CA Certificate")
-                             ("private-key" . "Private Key")
-                             ("private-key-password" . "Private Key 
Password"))))))
-    ("eap-ttls" . (("Name" . "eap-ttls")
-                  ("reqs" . ((("anonymous-identity" . "Anonymous Identity")
-                              ("ca-cert" . "CA Certificate")
-                              ("phase2-auth" . "Inner Authentication")
-                              ("identity" . "Username")
-                              ("password" . "Password"))))))
-    ("wpa-psk" . (("Name" . "wpa2")
-                 ("reqs" . ((("psk" . "PSK"))))))
-    ("wep" . (("Name" . "wep")
-             ("reqs" . ((("wep-key0" . "WEP Key")
-                         ("wep-key-type" . "WEP Key Type"))))))
-    ("leap" . (("Name" . "leap")
-              ("reqs" . ((("leap-username" . "Username")
-                         ("leap-password" . "Password"))))))
-    )
-  "The security types for NetworkManager.
-This is still in the process of being worked on."
-  )
+;;TODO: Make this customizable.
+(defconst enwc-nm-dbus-settings-groups
+  '(("802-11-wireless-security" . ("name"
+                                   "key-mgmt"
+                                   "wep-tx-keyidx"
+                                   "auth-alg"
+                                   "proto"
+                                   "pairwise"
+                                   "group"
+                                   "leap-username"
+                                   "wep-key0"
+                                   "wep-key1"
+                                   "wep-key2"
+                                   "wep-key3"
+                                   "wep-key-type"
+                                   "psk"
+                                   "leap-password"))
+    ("ipv4" . ("addresses"
+               "dns"))))
 
 (defvar enwc-nm-wired-dev nil
   "The wired device object path.")
@@ -148,764 +129,562 @@ This is still in the process of being worked on."
 (defvar enwc-nm-edit-info nil
   "The information for the network connection being edited.")
 
-(defun enwc-nm-get-settings (conn)
-  "Gets the connection settings.
-CONN is an object path to the connection."
-  (dbus-call-method :system
-                   enwc-nm-dbus-service
-                   conn
-                   enwc-nm-dbus-connections-interface
-                   "GetSettings"
-                   :timeout 25000))
+;; D-Bus Signals:
+
+(defvar enwc-nm-access-point-added-signal nil
+  "D-Bus signal object for the \"AccessPointAdded\" signal.")
+
+(defvar enwc-nm-access-point-removed-signal nil
+  "D-Bus signal object for the \"AccessPointRemoved\" signal.")
+
+(defvar enwc-nm-properties-changed-signal nil
+  "D-Bus signal object for the \"PropertiesChanged\" signal.")
+
+(defvar enwc-nm-wired-state-changed-signal nil
+  "D-Bus signal object for the \"StateChanged\" signal for the wired device.")
+
+(defvar enwc-nm-state-changed-signal nil
+  "D-Bus signal object for the \"StateChanged\" signal for the default path.")
+
+(defun enwc-nm-dbus-call-method (method &optional path interface &rest args)
+  (unless path (setq path enwc-nm-dbus-path))
+  (unless interface (setq interface enwc-nm-dbus-interface))
+  (apply 'dbus-call-method :system
+         enwc-nm-dbus-service
+         path
+         interface
+         method
+         :timeout 25000
+         args))
+
+(defun enwc-nm-dbus-default-call-method (method &rest args)
+  (apply 'enwc-nm-dbus-call-method method nil nil args))
+
+(defun enwc-nm-dbus-settings-call-method (method &rest args)
+  (apply 'enwc-nm-dbus-call-method
+         method
+         enwc-nm-dbus-settings-path
+         enwc-nm-dbus-settings-interface
+         args))
+
+(defun enwc-nm-dbus-wireless-call-method (method &rest args)
+  (apply 'enwc-nm-dbus-call-method
+         method
+         enwc-nm-wireless-dev
+         enwc-nm-dbus-wireless-interface
+         args))
+
+(defun enwc-nm-dbus-wired-call-method (method &rest args)
+  (apply 'enwc-nm-dbus-call-method
+         method
+         enwc-nm-wired-dev
+         enwc-nm-dbus-wired-interface
+         args))
 
+(defun enwc-nm-get-settings (conn)
+  "Get the connection settings from CONN."
+  (enwc-nm-dbus-call-method "GetSettings" conn
+                            enwc-nm-dbus-connections-interface))
 
 (defun enwc-nm-list-connections ()
   "List the connections."
-  (dbus-call-method :system
-                   enwc-nm-dbus-service
-                   enwc-nm-dbus-settings-path
-                   enwc-nm-dbus-settings-interface
-                   "ListConnections"
-                   :timeout 25000))
+  (enwc-nm-dbus-settings-call-method "ListConnections"))
 
 ;; Default
 (defun enwc-nm-get-device-by-name (name)
-  (dbus-call-method :system
-                   enwc-nm-dbus-service
-                   enwc-nm-dbus-path
-                   enwc-nm-dbus-interface
-                   "GetDeviceByIpIface"
-                   :timeout 25000
-                   :string name))
-
-;; Settings, Connections
-(defun enwc-nm-get-uuid-by-ssid (ssid)
-  "Gets the uuid of the network with ssid SSID."
-  (let ((conns (enwc-nm-list-connections))
-       cur-conn cur-ssid uuid)
-    (while (and conns (not uuid))
-      (setq cur-conn (pop conns))
-      (let ((settings (enwc-nm-get-settings cur-conn)))
-       (if (not (assoc "802-11-wireless" settings))
-           nil
-         (setq cur-ssid
-               (dbus-byte-array-to-string (car (cadr (assoc "ssid"
-                                                            (cadr (assoc 
"802-11-wireless"
-                                                                         
settings)))))))
-         (if (string= cur-ssid ssid)
-             (setq uuid
-                   (car (cadr (assoc "uuid"
-                                     (cadr (assoc "connection"
-                                                  settings))))))))))
-    uuid))
-
-(defun enwc-nm-get-uuid-by-id (id)
-  "Gets a network connection's uuid by the network's id.
-ID is a string that NetworkManager uses to identify this network."
-  (let ((conns (enwc-nm-list-connections))
-       cur-conn cur-id uuid)
-    (while (and conns (not uuid))
-      (setq cur-conn (pop conns))
-      (let ((settings (enwc-nm-get-settings cur-conn))
-           conn-set)
-       (if (not (assoc "connection" settings))
-           nil
-         (setq conn-set (assoc "connection" settings))
-         (setq cur-id (car (cadr (assoc "id" (cadr conn-set)))))
-         (if (string= cur-id id)
-             (setq uuid (car (cadr (assoc "uuid" (cadr conn-set)))))))))))
-
-(defun enwc-nm-get-conn-by-uuid (uuid)
-  (dbus-call-method :system
-                   enwc-nm-dbus-service
-                   enwc-nm-dbus-settings-path
-                   enwc-nm-dbus-settings-interface
-                   "GetConnectionByUuid"
-                   :timeout 25000
-                   uuid))
-
-;; Settings
-(defun enwc-nm-get-conn-by-ssid (ssid)
-  "Gets the connection path for the access point with ssid SSID."
-  (let ((uuid (enwc-nm-get-uuid-by-ssid ssid)))
-    (if uuid
-       (enwc-nm-get-conn-by-uuid uuid)
-      nil)))
-
-(defun enwc-nm-get-conn-by-id (id)
-  "Gets a connection object with the id ID.
-ID is the identifier used by Network Manager."
-  (let ((uuid (enwc-nm-get-uuid-by-id id)))
-    (enwc-nm-get-conn-by-uuid uuid)))
-
-;; Wireless
-(defun enwc-nm-scan ()
-  "The NetworkManager scan function."
-  (dbus-call-method :system
-                   enwc-nm-dbus-service
-                   enwc-nm-wireless-dev
-                   enwc-nm-dbus-wireless-interface
-                   "RequestScan"
-                   :timeout 25000
-                   '(:array :signature "{sv}")))
-
-;; Wireless
-(defun enwc-nm-get-networks ()
+  (enwc-nm-dbus-default-call-method "GetDeviceByIpIface" :string name))
+
+(defun enwc-nm--ap-to-conn (ap)
+  "Get the connection that corresponds to AP."
+  (let ((ssid (dbus-byte-array-to-string (enwc-nm-get-wireless-network-property
+                                          ap "Ssid")))
+        (conns (enwc-nm-list-connections))
+        conn)
+    (while (and conns (not conn))
+      (setq conn (pop conns))
+      (let ((settings (enwc-nm-get-settings conn)))
+        (if settings
+            (let ((this-ssid (enwc-nm-get-dbus-dict-entry 
"802-11-wireless/ssid"
+                                                          settings)))
+              (unless (and this-ssid
+                           (string-equal (dbus-byte-array-to-string this-ssid)
+                                         ssid))
+                (setq conn nil)))
+          (setq conn nil))))
+    conn))
+
+(defun enwc-nm-connection-p (conn)
+  "Return non-nil if CONN is a connection object."
+  (and conn
+       (stringp conn)
+       (string-match "^/org/freedesktop/NetworkManager/Settings/[0-9]+$" 
conn)))
+
+;;;;;;;;;;;;;;;;;;
+;; Get networks ;;
+;;;;;;;;;;;;;;;;;;
+
+(defun enwc-nm-get-networks (&optional wired)
+  (if wired
+      (enwc-nm-get-wired-profiles)
+    (enwc-nm-get-wireless-networks)))
+
+(defun enwc-nm-get-wireless-networks ()
   "The NetworkManager get networks function.
 This returns a list of D-Bus paths to the access points."
-  (dbus-call-method :system
-                   enwc-nm-dbus-service
-                   enwc-nm-wireless-dev
-                   enwc-nm-dbus-wireless-interface
+  (enwc-nm-dbus-wireless-call-method "GetAccessPoints"))
 
-                   "GetAccessPoints"))
+(defun enwc-nm-get-wired-profiles ()
+  (let ((profs-list (enwc-nm-list-connections)))
+    (mapcar
+     (lambda (x)
+       (let ((props (enwc-nm-get-settings x)))
+         (when (string= (enwc-nm-get-dbus-dict-entry "connection/type" props)
+                        "802-3-ethernet")
+           (enwc-nm-get-dbus-dict-entry "connection/id" props))))
+     profs-list)))
+
+;;;;;;;;;;;;;
+;; Connect ;;
+;;;;;;;;;;;;;
 
-;; Accesspoint
-(defun enwc-nm-get-wireless-network-property (id prop)
+;; Default
+(defun enwc-nm-connect (nw &optional wired)
+  "The NetworkManager connect function.
+This gets the connection path from NW, and connects to it."
+  (if wired
+      (enwc-nm-wired-connect nw)
+    (enwc-nm-wireless-connect nw)))
+
+(defun enwc-nm-wireless-connect (nw)
+  (enwc-nm-dbus-default-call-method "ActivateConnection"
+                                    :object-path nw
+                                    :object-path enwc-nm-wireless-dev
+                                    :object-path nw))
+
+(defun enwc-nm-wired-connect (nw)
+  (enwc-nm-dbus-default-call-method "ActivateConnection"
+                                    :object-path nw
+                                    :object-path enwc-nm-wired-dev
+                                    :object-path nw))
+
+;;;;;;;;;;;;;;;;
+;; Disconnect ;;
+;;;;;;;;;;;;;;;;
+
+(defun enwc-nm-disconnect (&optional wired)
+  (if wired
+      (enwc-nm-wired-disconnect)
+    (enwc-nm-disconnect-wireless)))
+
+;; Device
+(defun enwc-nm-disconnect-wireless ()
+  (enwc-nm-dbus-call-method "Disconnect"
+                            enwc-nm-wireless-dev
+                            enwc-nm-dbus-device-interface))
+
+(defun enwc-nm-wired-disconnect ()
+  (enwc-nm-dbus-call-method "Disconnect"
+                            enwc-nm-wired-dev
+                            enwc-nm-dbus-device-interface))
+
+;;;;;;;;;;
+;; Scan ;;
+;;;;;;;;;;
+
+(defun enwc-nm-scan (&optional wired)
+  "The NetworkManager scan function."
+  (let ((dev (if wired
+                 enwc-nm-wired-dev
+               enwc-nm-wireless-dev))
+        (interface (if wired
+                       enwc-nm-dbus-wired-interface
+                     enwc-nm-dbus-wireless-interface)))
+    (enwc-nm-dbus-call-method "RequestScan"
+                              dev interface
+                              '(:array :signature "{sv}"))))
+
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;; Get network properties ;;
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+
+(defun enwc-nm-get-wireless-network-property (nw prop)
   "The NetworkManager get wireless network property function.
 This runs like normal, using element ID of `enwc-access-points'
  to determine the access point path, then obtains the property
 PROP from that access point.  It also sets the channel from the
  frequency if necessary."
-  (let ((ap (nth id enwc-access-points))
-       (mod-prop prop)
-       ret)
-    (if (string= mod-prop "essid")
-       (setq mod-prop "Ssid"))
-    (setq ret (dbus-get-property :system
-                                enwc-nm-dbus-service
-                                ap
-                                enwc-nm-dbus-accesspoint-interface
-                                mod-prop))
-    (if (not ret)
-       (progn
-         (if (not enwc-nm-edit-info)
-             (setq ret ""))
-         (progn
-           (setq ret (assoc mod-prop
-                            (cadr (assoc "802-1x"
-                                         enwc-nm-edit-info))))
-           (if (not ret)
-               (setq ret (assoc mod-prop
-                                (cadr (assoc "802-11-wireless-security"
-                                             enwc-nm-edit-info)))))
-           (setq ret (car (cadr ret))))))
-    (if (string= mod-prop "Frequency")
-       (setq ret (number-to-string (1+ (/ (- ret 2412) 5)))))
-    (if (string= mod-prop "Ssid")
-       (setq ret (dbus-byte-array-to-string ret)))
-    (if (string= mod-prop "Mode")
-       (setq ret (cond ((= ret 0) "Unknown")
-                       ((= ret 1) "Ad-Hoc")
-                       ((= ret 2) "Infrastructure"))))
-    ret))
-
-(defun enwc-nm-get-wireless-nw-props (id)
-  (let ((ap (nth id enwc-access-points))
-       tmp-val
-       ret)
-    (setq ret (dbus-get-all-properties :system
-                                      enwc-nm-dbus-service
-                                      ap
-                                      enwc-nm-dbus-accesspoint-interface))
-    (setq tmp-val (cdr (assoc "Mode" ret)))
-    (setcdr (assoc "Frequency" ret)
-           (number-to-string (1+ (/ (- (cdr (assoc "Frequency" ret))
-                                       2412) 5))))
-    (setcdr (assoc "Ssid" ret)
-           (dbus-byte-array-to-string (cdr (assoc "Ssid" ret))))
-    (setcdr (assoc "Mode" ret)
-           (cond ((= tmp-val 0) "Unkown")
-                 ((= tmp-val 1) "Ad-Hoc")
-                 ((= tmp-val 2) "Infrastructure")))
-    ret))
-
-(defun enwc-nm-get-conn-by-nid (nid)
-  "Gets a connection object with the network id NID."
-  (let* ((ssid (enwc-nm-get-wireless-network-property nid
-                                                     "Ssid"))
-        (uuid (enwc-nm-get-uuid-by-ssid ssid)))
-    (if uuid
-       (enwc-nm-get-conn-by-uuid uuid)
-      nil)))
-
-(defun enwc-nm-get-encryption-type (id)
+  (dbus-get-property :system
+                     enwc-nm-dbus-service
+                     nw
+                     enwc-nm-dbus-accesspoint-interface
+                     prop))
+
+(defun enwc-nm--freq-to-channel (freq)
+  "Convert a frequency FREQ into a channel."
+  (1+ (/ (- freq 2412) 5)))
+
+(defun enwc-nm-get-wireless-nw-props (nw)
+  "Get the network properties for the network NW."
+  (let ((props (dbus-get-all-properties :system
+                                        enwc-nm-dbus-service
+                                        nw
+                                        enwc-nm-dbus-accesspoint-interface)))
+
+    `((essid    . ,(dbus-byte-array-to-string (cdr (assoc "Ssid" props))))
+      (bssid    . ,(cdr (assoc "HwAddress" props)))
+      (strength . ,(cdr (assoc "Strength" props)))
+      (encrypt  . ,(or (enwc-nm-get-encryption-type nw) "Unsecured"))
+      (channel  . ,(number-to-string (enwc-nm--freq-to-channel
+                                      (cdr (assoc "Frequency" props))))))))
+
+(defun enwc-nm-get-encryption-type (nw)
   "The NetworkManager get encryption type function.
-This gets the WPA flags and RSN flags from access point in ID.
+This gets the WPA flags and RSN flags from access point in NW.
 If both are 0, then it returns WEP, otherwise WPA."
-  (let ((wpa-flags (enwc-nm-get-wireless-network-property id "WpaFlags"))
-       (rsn-flags (enwc-nm-get-wireless-network-property id "RsnFlags")))
+  (let ((wpa-flags (enwc-nm-get-wireless-network-property nw "WpaFlags"))
+        (rsn-flags (enwc-nm-get-wireless-network-property nw "RsnFlags")))
     (if (and (= wpa-flags 0) (= rsn-flags 0))
-       "WEP"
+        "WEP"
       "WPA")))
 
-;; Default
-(defun enwc-nm-connect (id)
-  "The NetworkManager connect function.
-This gets the connection path from ID, and connects to it."
-  (let ((ssid (enwc-nm-get-wireless-network-property id "Ssid")))
-    (dbus-call-method :system
-                     enwc-nm-dbus-service
-                     enwc-nm-dbus-path
-                     enwc-nm-dbus-interface
-                     "ActivateConnection"
-                     :timeout 25000
-                     :object-path (enwc-nm-get-conn-by-ssid ssid)
-                     :object-path enwc-nm-wireless-dev
-                     :object-path (nth id enwc-access-points))))
-
-
-(defun enwc-nm-string-idx (obj list)
-  (let ((tmp-list list)
-       (cur-pos -1)
-       cur-obj)
-    (while (and (not cur-obj) tmp-list)
-      (setq cur-obj (pop tmp-list))
-      (setq cur-pos (1+ cur-pos))
-      (if (not (string= obj cur-obj))
-         (setq cur-obj nil)))
-    cur-pos))
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;; Get Current network id ;;
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;
 
 (defun enwc-nm-wireless-prop-changed (props)
-  (if (assoc "ActiveAccessPoint" props)
-      (setq enwc-nm-active-ap (car (cadr (assoc "ActiveAccessPoint"
-                                               props))))))
+  "Called when network properties are changed.
+PROPS is a list of updated properties."
+  (let ((ap (assoc "ActiveAccessPoint" props)))
+    (when ap
+      (setq enwc-nm-active-ap (car (cadr ap))))))
 
-;; Wireless
 (defun enwc-nm-get-current-nw-id (wired)
   "The NetworkManager get current network id function.
 This simply checks for the active access point."
-  (if (or wired (string= enwc-nm-active-ap "/"))
-      -1
-    (enwc-nm-string-idx enwc-nm-active-ap enwc-access-points)))
+  (cond
+   (wired 'wired)
+   ((string= enwc-nm-active-ap "/") nil)
+   (t enwc-nm-active-ap)))
 
 (defun enwc-nm-prop-changed (state)
+  "Called when NetworkManager's state is changed.
+STATE is the new state
+
+If STATE is 40, then NetworkManager is connecting to a new AP."
   (setq enwc-nm-connecting-p (eq state 40)))
 
-;; Default
+;;;;;;;;;;;;;;;;;;;;;;
+;; Check Connecting ;;
+;;;;;;;;;;;;;;;;;;;;;;
+
 (defun enwc-nm-check-connecting ()
   "The NetworkManager check connecting function."
   enwc-nm-connecting-p)
 
-;; Device
-(defun enwc-nm-disconnect-wireless ()
-  (dbus-call-method :system
-                   enwc-nm-dbus-service
-                   enwc-nm-wireless-dev
-                   enwc-nm-dbus-device-interface
-                   "Disconnect"))
-
-;; Settings, Connections
-(defun enwc-nm-get-wired-profiles ()
-  (let ((profs-list (enwc-nm-list-connections)))
-    (mapcar (lambda (x)
-             (let ((props (enwc-nm-get-settings x)))
-               (if (string= (caar props) "connection")
-                   (car (cadr (car (cadr (car props))))))))
-           profs-list)))
-
-(defun enwc-nm-wired-connect (id)
-  (let ((nid (nth id enwc-access-points)))
-    (dbus-call-method :system
-                     enwc-nm-dbus-service
-                     enwc-nm-dbus-path
-                     enwc-nm-dbus-interface
-                     :timeout 25000
-                     :object-path (enwc-nm-get-conn-by-id nid)
-                     :object-path enwc-nm-wired-dev
-                     :objec-path "/")))
-
-;; Device
-(defun enwc-nm-wired-disconnect ()
-  (dbus-call-method :system
-                   enwc-nm-dbus-service
-                   enwc-nm-wired-dev
-                   enwc-nm-dbus-device-interface
-                   "Disconnect"))
-
 (defun enwc-nm-dev-prop-changed (new-state old-state reason)
   (setq enwc-nm-wired-p (eq new-state 100)))
 
-;; Default
 (defun enwc-nm-is-wired ()
   enwc-nm-wired-p)
 
-;; Each entry in sec-types should be:
-;; ("IDENT" (("Name" . "NAME") ("reqs" . (("key1" . "Entry1") ("key2" . 
"Entry2") ... ))))
-;; Where:
-;;  "IDENT" => String that identifies this to the backend.
-;;  "NAME" => String that ENWC displays
-;;  "reqs" => Constant string, but the association list holds entries
-;;              required by the security type, i.e. user, passphrase, etc.
-;;  "keyXX" => String that the backend uses for this security entry.
-;;  "EntryXX" => String that ENWC displays for this security entry.
-
-(defun enwc-nm-get-sec-types (wired)
-  "Get security types."
-  (if wired
-      nil
-    enwc-nm-sec-types)
-  )
+;;;;;;;;;;;;;;;;;;;;;;
+;; Profile Handling ;;
+;;;;;;;;;;;;;;;;;;;;;;
 
 (defun enwc-nm-gen-uuid ()
+  "Generate a UUID."
   (random t)
-  (let ((hex-nums
-        (mapcar (lambda (x)
-                  (random 65535))
-                (number-sequence 0 7)))
-       fin-str)
-    (setq fin-str (format "%04x%04x-%04x-%04x-%04x-%04x%04x%04x"
-                         (nth 0 hex-nums)
-                         (nth 1 hex-nums)
-                         (nth 2 hex-nums)
-                         (nth 3 hex-nums)
-                         (nth 4 hex-nums)
-                         (nth 5 hex-nums)
-                         (nth 6 hex-nums)
-                         (nth 7 hex-nums)))))
+  (apply 'format
+         "%04x%04x-%04x-%04x-%04x-%04x%04x%04x"
+         (mapcar (lambda (x)
+                   (random 65535))
+                 (number-sequence 0 7))))
+
+(defmacro enwc-nm--hex-substring (str st ed)
+  "Get a standard integer from hex string STR starting at ST and ending st ED"
+  `(string-to-number (substring ,str ,st ,ed) 16))
 
 (defun enwc-nm-convert-addr (addr)
-  (if addr
+  "Convert an address ADDR from an integer in network byte order to a string."
+  (if (and addr (integerp addr))
       (let* ((hex-addr (format "%08x" addr))
-            (ret-addr (format "%i.%i.%i.%i"
-                              (string-to-number (substring hex-addr
-                                                           6 8)
-                                                16)
-                              (string-to-number (substring hex-addr
-                                                           4 6)
-                                                16)
-                              (string-to-number (substring hex-addr
-                                                           2 4)
-                                                16)
-                              (string-to-number (substring hex-addr
-                                                           0 2)
-                                                16))))
-       ret-addr)
+             (subs (mapcar
+                    (lambda (n)
+                      (enwc-nm--hex-substring hex-addr n (+ n 2)))
+                    (number-sequence 6 0 -2))))
+        (apply 'format "%i.%i.%i.%i" subs))
     ""))
 
 (defun enwc-nm-addr-back (addr)
-  (let ((bytes (split-string addr "."))
-        ret-val)
-    (setq ret-val (logior (lsh (string-to-number (nth 3 bytes))
-                              0)
-                         (lsh (string-to-number (nth 2 bytes))
-                              1)
-                         (lsh (string-to-number (nth 1 bytes))
-                              2)
-                         (lsh (string-to-number (nth 0 bytes))
-                              3)))))
+  "Convert an IP address ADDR in dots notation to an integer."
+  (cl-check-type addr string)
+  (let* ((bytes (split-string addr "\\."))
+         (byte-string (mapcar
+                       (lambda (n) (lsh (string-to-number (nth n bytes))
+                                        (* 8 n)))
+                       (number-sequence 0 3))))
+    (apply 'logior byte-string)))
 
 ;; These next two come from libnm-util/nm-utils.c in NM's source.
 
 (defun enwc-nm-netmask-to-prefix (netmask)
-  "Converts a netmask to a prefix.
+  "Convert a netmask to a CIDR prefix.
 NETMASK is an ip address in network byte order."
-  (if netmask
-      (let* ((mask netmask)
-            (cur-pos 3)
-            (cur-mark (logand (lsh mask (* -8 cur-pos)) 255))
-            (pf 0))
-       (while (and (eq cur-mark 255) (>= cur-pos 0))
-         (setq pf (+ pf 8))
-         (setq cur-pos (1- cur-pos))
-         (setq cur-mark (logand (lsh mask (* -8 cur-pos)) 255))
-         )
-
-       (if (>= cur-pos 0)
-           (let ((v (logand (lsh mask (* -8 cur-pos)) 255)))
-             (while (not (eq v 0))
-               (setq pf (1+ pf))
-               (setq v (lsh v 1)))))
-       pf)
+  (if (and netmask (integerp netmask))
+      (progn
+        (setq netmask (enwc--htonl netmask))
+        (while (cl-evenp netmask)
+          (setq netmask (lsh netmask -1)))
+        (floor (log (1+ netmask) 2)))
     0))
 
 (defun enwc-nm-prefix-to-netmask (prefix)
-  "Converts a prefix to a netmask.
+  "Convert a CIDR prefix to a netmask.
 PREFIX is an integer <= 32."
-  (let ((pf prefix)
-       (netmask 0)
-       (msk #x80000000))
-  (while (> pf 0)
-    (setq netmask (logior netmask msk))
-    (setq msk (lsh msk -1))
-    (setq pf (1- pf)))
-  netmask))
-
-(defun enwc-nm-get-nw-info (wired id)
-  (let ((conn (enwc-nm-get-conn-by-nid id)))
-    (if conn
-       (setq enwc-nm-edit-info
-             (enwc-nm-get-settings conn))))
-
-  (let (ip-addr netmask gateway dns-list nw-info)
-    (if enwc-nm-edit-info
-       (progn
-         (setq ip-addr (nth 0 (caar (cadr (assoc "addresses"
-                                                 (cadr (assoc "ipv4"
-                                                              
enwc-nm-edit-info))))))
-               netmask (nth 3 (caar (cadr (assoc "addresses"
-                                                 (cadr (assoc "ipv4"
-                                                              
enwc-nm-edit-info))))))
-               gateway (nth 2 (caar (cadr (assoc "address"
-                                                 (cadr (assoc "ipv4"
-                                                              
enwc-nm-edit-info))))))
-               dns-list (car (cadr (assoc "dns" (cadr (assoc "ipv4"
-                                                             
enwc-nm-edit-info))))))
-         (setq ip-addr (enwc-nm-convert-addr ip-addr)
-               netmask (enwc-nm-convert-addr netmask)
-               gateway (enwc-nm-convert-addr gateway)
-               dns-list (mapcar 'enwc-nm-convert-addr
-                                dns-list))
-         (setq nw-info (list (cons (cons "addr"
-                                         ip-addr) nil)
-                             (cons (cons "netmask"
-                                         netmask) nil)
-                             (cons (cons "gateway"
-                                         gateway) nil)
-                             (cons (cons "dns1"
-                                         (nth 0
-                                              dns-list))
-                                   nil)
-                             (cons (cons "dns2"
-                                         (nth 1
-                                              dns-list))
-                                   nil)
-                             (cons (cons "enctype"
-                                         "None") nil)
-                             )))
-      nil)))
-
-(defun enwc-nm-get-ip-addr (wired id)
-  "Gets the IP Address of a connection profile."
-  (let ((props (enwc-nm-get-settings (enwc-nm-get-conn-by-nid id)))
-       ipaddr ret-addr)
-    (if (not props)
-       (setq ret-addr "")
-      (setq ipaddr (nth 0 (caar (cadr (assoc "addresses"
-                                            (cadr (assoc "ipv4"
-                                                         props)))))))
-      (setq ret-addr (enwc-nm-convert-addr ipaddr)))))
-
-(defun enwc-nm-get-netmask (wired id)
-  "Gets the Netmask of a connection profile."
-  (let ((props (enwc-nm-get-settings (enwc-nm-get-conn-by-nid id)))
-       ipaddr hex-addr ret-addr)
-    (if (not props)
-       (setq ret-addr "")
-      (setq ipaddr (nth 3 (caar (cadr (assoc "addresses"
-                                            (cadr (assoc "ipv4"
-                                                         props)))))))
-      (setq hex-addr (enwc-nm-prefix-to-netmask ipaddr))
-      (setq ret-addr (format "%i.%i.%i.%i"
-                            (logand hex-addr 255)
-                            (logand (lsh hex-addr -8) 255)
-                            (logand (lsh hex-addr -16) 255)
-                            (logand (lsh hex-addr -24) 255))))))
-
-
-(defun enwc-nm-get-gateway (wired id)
-  "Gets the Gateway of a connection profile."
-  (let ((props (enwc-nm-get-settings (enwc-nm-get-conn-by-nid id)))
-       ipaddr ret-addr)
-    (if (not props)
-       (setq ret-addr "")
-      (setq ipaddr (nth 2 (caar (cadr (assoc "addresses"
-                                            (cadr (assoc "ipv4"
-                                                         props)))))))
-      (setq ret-addr (enwc-nm-convert-addr ipaddr)))))
-
-(defun enwc-nm-get-dns (wired id)
-  "Gets the DNS settings of a connection profile."
-  (let ((props (enwc-nm-get-settings (enwc-nm-get-conn-by-nid id)))
-       dns-list)
-    (setq dns-list (car (cadr (assoc "dns" (cadr (assoc "ipv4"
-                                                       props))))))
-    (mapcar 'enwc-nm-convert-addr
-           dns-list)))
-
-(defun enwc-nm-process-enctype (settings nw-settings)
-  "Process the encryption type.
-Sets up the encryption type passed in through SETTINGS."
-  (let* ((ret-list nw-settings)
-        (req-list (nthcdr 6 settings))
-        (enctype (cdr (assoc "enctype" settings)))
-        key-mgmt
-        new-list name-list
-        ;;(name-list (cdr (assoc "reqs" (cdr (assoc enctype 
enwc-nm-sec-types)))))
-        key-name)
-
-    ;; There is a possibility that any of these don't exist in
-    ;; nw-settings.
-
-    (setq new-list `("802-11-wireless-security" (("pairwise" (("wep40" 
"wep104")))
-                                                ("group" (("wep40" "wep104")))
-                                                ("auth-alg" (nil))
-                                                ("key-mgmt" (nil)))))
-
-    (if (not (assoc "802-11-wireless-security" ret-list))
-       (setq ret-list (append ret-list (list new-list))))
-
-    (if (or (string= enctype "eap-leap")
-           (string= enctype "eap-peap")
-           (string= enctype "eap-tls")
-           (string= enctype "eap-ttls"))
-       (progn
-         (setq key-name "802-1x")
-         (setq key-mgmt "ieee8021x")
-         (setq req-list (push (cons "eap" (substring enctype 4)) req-list))
-         (print req-list)
-         ;;(setcdr (assoc "eap" (cadr (assoc "802-1x" ret-list))) (list (list 
(list (substring enctype 4)))))
-         )
-      (setq key-name "802-11-wireless-security")
-      (setq key-mgmt
-           (cond ((string= enctype "wep") "none")
-                 ((string= enctype "wpa-psk") "wpa-psk")
-                 ((string= enctype "leap") "iee8021x"))))
-    (setcdr (assoc "key-mgmt" (cadr (assoc "802-11-wireless-security" 
ret-list)))
-           (list (list key-mgmt)))
-
-    (if (string= enctype "leap")
-       (setcdr (assoc "auth-alg" (cadr (assoc "802-11-wireless-security" 
ret-list)))
-               (list (list "leap"))))
-
-    (setq name-list (cons key-name
-                         (list (mapcar (lambda (x)
-                                         (cons (car x)
-                                               (cons (cons (cdr x) nil)
-                                                     nil)))
-                                       req-list))))
-
-    (if (not (assoc key-name ret-list))
-       (setq ret-list (append ret-list (list name-list)))
-      (setcdr (assoc key-name ret-list) (list name-list)))
-
-
-    (if (or (string= enctype "eap-leap")
-           (string= enctype "eap-peap")
-           (string= enctype "eap-tls")
-           (string= enctype "eap-ttls"))
-       (setcdr (assoc "eap" (cadr (assoc "802-1x" ret-list)))
-               (cons (cons (cons (substring enctype 4) nil) nil) nil)))
-
-    ret-list))
+  (if (and prefix (integerp prefix))
+      (progn
+        (setq prefix (min prefix 32))
+        (enwc--htonl (lsh (1- (expt 2 prefix)) (- 32 prefix))))
+    0))
+
+;;;;;;;;;;;;;;;;;;;;;;
+;; D-Bus Conversion ;;
+;;;;;;;;;;;;;;;;;;;;;;
+
+(defun enwc-nm-get-dbus-dict-entry (entry dict)
+  "Get an entry ENTRY from D-Bus dictionary DICT.
+
+ENTRY is in the form LVL1/LVL2/.../LVLN, where each LVLi is a string
+representing another layer in the dictionary."
+  (cl-check-type entry string)
+  (cl-check-type dict list)
+  (let ((ent-strs (split-string entry "/"))
+        (cur-ent dict)
+        cur-str)
+    (while ent-strs
+      (setq cur-str (pop ent-strs))
+      (setq cur-ent (assoc cur-str cur-ent))
+      (when cur-ent
+        (setq cur-ent (cadr cur-ent))))
+    cur-ent))
+
+(defun enwc-nm--recurse-dbus-entry (dict value entries)
+  "Look in DICT for ENTRIES, and set the final one to VALUE."
+  (if (not entries)
+      (setcar dict value)
+    (let* ((cur-str (car entries))
+           (cur-ent (assoc cur-str dict)))
+      (unless cur-ent
+        (if (equal dict '(nil))
+            (setcar dict `(,cur-str (nil)))
+          (nconc dict `((,cur-str (nil)))))
+        (setq cur-ent (assoc cur-str dict)))
+      (enwc-nm--recurse-dbus-entry (cadr cur-ent) value (cdr entries)))))
+
+(defun enwc-nm-set-dbus-dict-entry (entry dict value)
+  "Set entry ENTRY in D-Bus dictionary DICT to VALUE."
+  (cl-check-type entry string)
+  (cl-check-type dict list)
+  (enwc-nm--recurse-dbus-entry dict value (split-string entry "/")))
+
+(defun enwc-nm-convert-dict-list (dict-ent settings)
+  "Convert a D-Bus dictionary entry DICT-ENT from SETTINGS to an alist."
+  (mapcar
+   (lambda (ent)
+     (cons
+      (intern (car ent))
+      (cl-caadr ent)))
+   (cadr (assoc dict-ent settings))))
+
+(defun enwc-nm-get-sec-info (settings)
+  "Get security information from SETTINGS."
+  (append
+   (enwc-nm-convert-dict-list "802-11-wireless-security" settings)
+   (enwc-nm-convert-dict-list "802-1x" settings)))
+
+(defun enwc-nm-pair-to-dbus-dict-ent (pair)
+  "Convert PAIR into a D-Bus dictionary entry."
+  (let ((str (car pair))
+        (var (cdr pair)))
+    `(:dict-entry (:string ,str :variant ,var))))
+
+(defun enwc-nm-alist-to-dbus-dict (alist)
+  "Convert ALIST into a D-Bus dictionary."
+  (let (dict)
+    (append
+     '(:array)
+     (dolist (pr alist dict)
+       (setq dict (apply 'list dict (enwc-nm-pair-to-dbus-dict-ent pr)))))))
+
+(defun enwc-nm-process-profile-info (settings prof-info)
+  (dolist (ent prof-info settings)
+    ;; Find the corresponding entry in settings, and set it to the new value.
+    ;; Check 802-11-wireless-security, then 802-1x, then ipv4.
+    (let ((ent-list '("802-11-wireless-security"
+                      "ipv4"))
+          cur-ent)
+      (while ent-list
+        (setq cur-ent (pop ent-list))
+        (when (enwc-nm-set-dbus-dict-entry (concat cur-ent "/"
+                                                   (symbol-name (car ent)))
+                                           settings
+                                           (cdr ent))
+          (setq ent-list nil))))))
+
+(defun enwc-nm-alist-to-dbus-str-str-var-map-map (alist)
+  (let (ret)
+    (dolist (ent alist ret)
+      (push `(:string (car ent) ,(enwc-nm-alist-to-dbus-dict (cadr ent))) ret)
+      (push :dict-entry ret))))
+
+(defun enwc-nm-get-profile-info (ap &optional wired)
+  "Get the profile info for access point AP."
+  (let ((conn (enwc-nm--ap-to-conn ap))
+        settings)
+    (when conn
+      (setq settings (enwc-nm-get-settings conn)))
+    (when settings
+      (let* ((adr-info (caar (enwc-nm-get-dbus-dict-entry "ipv4/addresses" 
settings)))
+             (ip-addr (enwc-nm-convert-addr (nth 0 adr-info)))
+             (netmask (enwc-nm-convert-addr (enwc-nm-prefix-to-netmask (nth 1 
adr-info))))
+             (gateway (enwc-nm-convert-addr (nth 2 adr-info)))
+             (dns-list (mapcar 'enwc-nm-convert-addr
+                               (car (enwc-nm-get-dbus-dict-entry "ipv4/dns"
+                                                                 settings))))
+             (sec-info (enwc-nm-get-sec-info settings)))
+        `((addr . ,ip-addr)
+          (netmask . ,netmask)
+          (gateway . ,gateway)
+          (dns1    . ,(nth 0 dns-list))
+          (dns2    . ,(nth 1 dns-list))
+          ,@sec-info)))))
 
 (defun enwc-nm-finalize-settings (settings)
-  "Sets up all of the D-BUS types of a settings list.
-SETTINGS is the list of settings list to setup.
-This will place all of the necessary markers in the list,
-such as :array, :dict-entry, etc."
-  (cons :array
-       (let (first-one)
-         (mapc (lambda (x)
-                 (setq first-one (cons :dict-entry first-one))
-                 (setq first-one
-                       (cons (cons :string
-                                   (cons (car x)
-                                         (cons (cons :array
-                                                     (let (this-one)
-                                                       (mapc (lambda (y)
-                                                               (setq this-one
-                                                                     (cons 
:dict-entry this-one))
-                                                               (setq this-one
-                                                                     (cons 
(list :string (car y)
-                                                                               
  :variant
-                                                                               
  (if (string= (car y) "ssid")
-                                                                               
      (cons (dbus-string-to-byte-array
-                                                                               
             (dbus-byte-array-to-string (car (cadr y))))
-                                                                               
            nil)
-                                                                               
    (cadr y)))
-                                                                           
this-one)))
-                                                             (cadr x))
-                                                       (nreverse this-one))) 
nil)))
-                             first-one)))
-               settings)
-         (nreverse first-one))))
-
-(defun enwc-nm-create-settings (wired ssid)
-  (let ((uuid (enwc-nm-gen-uuid))
-       (id (concat ssid " settings"))
-       type
-       ret-list
-       conn-list
-       ipv4-list ipv6-list
-       mod-list
-       new-ssid
-       80211-list)
-
-    (if (not wired)
-       (setq new-ssid (dbus-string-to-byte-array ssid))
-       (progn
-         (setq 80211-list `("802-11-wireless" (("security" (nil))
-                                               ("ssid" (,new-ssid))
-                                               ("mode" ("infrastructure")))))
-
-         (setq ret-list (append ret-list (list 80211-list))
-               type "802-11-wireless"))
-      (setq type "802-3-ethernet"))
-    (setq conn-list `("connection" (("id" (,id))
-                                   ("uuid" (,uuid))
-                                   ("autoconnect" (nil))
-                                   ("type" (,type)))))
-
-    (setq ipv4-list '("ipv4" (("addresses" (nil))
-                             ("dns" (nil))
-                             ("method" ("auto"))
-                             ("routes" (nil)))))
-
-    (setq ipv6-list '("ipv4" (("addresses" (nil))
-                             ("dns" (nil))
-                             ("method" ("auto"))
-                             ("routes" (nil)))))
-
-    (setq ret-list (append ret-list (list conn-list)))
-    (setq ret-list (append ret-list (list ipv4-list)))
-    (setq ret-list (append ret-list (list ipv6-list)))
-    ))
-
-(defun enwc-nm-setup-settings (wired id settings)
-  "Sets up NetworkManager settings.
-Gets the current network properties of network ID
+  "Set up all of the D-BUS types of a settings list SETTINGS.
+This will place all of the necessary markers in the list, such as :array,
+:dict-entry, etc."
+  `(:array ,@(enwc-nm-alist-to-dbus-str-str-var-map-map settings)))
+
+(defun enwc-nm-setup-settings (conn settings wired)
+  "Set up NetworkManager settings.
+Get the current network properties of network CONN
 and uses the information in the association list SETTINGS
 to put it in the form that NetworkManager will recognize."
-  (print settings)
-  (let (ssid uuid conn props)
-
-    (if (not enwc-nm-edit-info)
-       (progn
-         (setq ssid
-               (enwc-nm-get-wireless-network-property (nth id
-                                                           enwc-access-points)
-                                                      "Ssid"))
-         (setq props (enwc-nm-create-settings wired ssid)))
-      (setq props enwc-nm-edit-info))
-
-    (print enwc-nm-edit-info)
-         ;; (setq uuid (enwc-nm-get-uuid-by-ssid ssid))
-         ;; (if uuid
-         ;;     (setq conn (enwc-nm-get-conn-by-uuid uuid)))))
-
-    ;; (setq props
-    ;;           (if conn
-    ;;               (enwc-nm-get-settings (enwc-nm-get-conn-by-nid id))
-    ;;             (enwc-nm-create-settings wired ssid)))
-
-    (setcdr (assoc "type" (cadr (assoc "connection" props)))
-           (list (list (cond (wired "802-3-ethernet")
-                             ((not wired) "802-11-wireless")))))
-
-    (if (= (length (cdr (assoc "addr" settings))) 0)
-       (setcdr (assoc "addresses" (cadr (assoc "ipv4" props)))
-               (cons (cons nil nil) nil))
-
-      (setcdr (assoc "addresses" (cadr (assoc "ipv4" props)))
-             (list (list (list (list (enwc-nm-addr-back
-                                      (cdr (assoc "addr" settings)))
-                                     (enwc-nm-netmask-to-prefix 
(enwc-nm-addr-back
-                                                                 (cdr (assoc 
"netmask"
-                                                                             
settings))))
-                                     (enwc-nm-addr-back
-                                      (cdr (assoc "gateway" settings)))))))))
-
-    (if (= (length (cdr (assoc "dns1" settings))) 0)
-       (setcdr (assoc "dns" (cadr (assoc "ipv4" props)))
-               (cons (cons nil nil) nil))
-      (setcdr (assoc "dns" (cadr (assoc "ipv4" props)))
-             (list (list (list (enwc-nm-addr-back
-                                (cdr (assoc "dns1" settings)))
-                               (enwc-nm-addr-back
-                                (cdr (assoc "dns2" settings))))))))
-
-    (setq props (enwc-nm-process-enctype settings props))
-    (print props)
-
-    (enwc-nm-finalize-settings props)))
-
-(defun enwc-nm-save-nw-settings (wired id settings)
-  "Saves network settings.
-ID is the network id of the profile to save,
-WIRED denotes whether or not this is a wired profile,
-and SETTINGS is the list of settings."
-  (let ((mod-sets (enwc-nm-setup-settings wired id settings)))
-    (print mod-sets)
-    (print id)
-    (dbus-call-method :system
-                     enwc-nm-dbus-service
-                     ;;(nth id enwc-access-points)
-                     (enwc-nm-get-conn-by-nid id)
-                     enwc-nm-dbus-connections-interface
-                     (if (not enwc-nm-edit-info)
-                         "AddConnection"
-                       "Update")
-                     :timeout 25000
-                     :array mod-sets)
-    ))
-
-(defun enwc-nm-setup ()
+  (let (conn-settings)
+    (if (enwc-nm-connection-p conn)
+        (setq conn-settings (enwc-nm-get-settings conn))
+      (message "Not a connection")
+      (print conn)
+      ;;TODO: ssid will be invalid for wired connections.
+      ;; This would actually throw an error in that case.
+      (let ((ssid (dbus-byte-array-to-string 
(enwc-nm-get-wireless-network-property
+                                              conn "Ssid")))
+            (type (if wired "802-3-ethernet" "802-11-wireless")))
+        (setq conn-settings `(("connection"
+                               (("id" (,(concat ssid " settings")))
+                                ("uuid" (,(enwc-nm-gen-uuid)))
+                                ("autoconnect" (nil))
+                                ("type" (,type))))))))
+    (setq conn-settings (enwc-nm-process-profile-info conn-settings settings))
+    (pp conn-settings)
+    (print conn-settings)
+    (enwc-nm-finalize-settings conn-settings)))
+
+(defun enwc-nm-save-nw-settings (ap settings wired)
+  "Save network AP with settings SETTINGS."
+  (let ((conn (enwc-nm--ap-to-conn ap)))
+    (print conn)
+    (if conn
+        (enwc-nm-dbus-call-method "Update"
+                                  conn
+                                  enwc-nm-dbus-connections-interface
+                                  (enwc-nm-setup-settings conn settings wired))
+      (enwc-nm-dbus-call-method "AddConnection"
+                                enwc-nm-dbus-settings-path
+                                enwc-nm-dbus-settings-interface
+                                (enwc-nm-setup-settings ap settings wired)))))
+
+(defun enwc-nm-load ()
+  "Setup the NetworkManager back-end."
+  ;;TODO: Add way of changing these two after load.
   (setq enwc-nm-wired-dev (enwc-nm-get-device-by-name enwc-wired-device)
-       enwc-nm-wireless-dev (enwc-nm-get-device-by-name enwc-wireless-device))
-
-  (dbus-register-signal :system
-                       enwc-nm-dbus-service
-                       enwc-nm-wireless-dev
-                       enwc-nm-dbus-wireless-interface
-                       "AccessPointAdded"
-                       'enwc-process-scan)
-
-  (dbus-register-signal :system
-                       enwc-nm-dbus-service
-                       enwc-nm-wireless-dev
-                       enwc-nm-dbus-wireless-interface
-                       "AccessPointRemoved"
-                       'enwc-process-scan)
+        enwc-nm-wireless-dev (enwc-nm-get-device-by-name enwc-wireless-device))
+
+  (setq enwc-nm-access-point-added-signal
+        (dbus-register-signal :system
+                              enwc-nm-dbus-service
+                              enwc-nm-wireless-dev
+                              enwc-nm-dbus-wireless-interface
+                              "AccessPointAdded"
+                              'enwc-process-scan))
+
+  (setq enwc-nm-access-point-removed-signal
+        (dbus-register-signal :system
+                              enwc-nm-dbus-service
+                              enwc-nm-wireless-dev
+                              enwc-nm-dbus-wireless-interface
+                              "AccessPointRemoved"
+                              'enwc-process-scan))
 
   (setq enwc-nm-active-ap
-       (let ((cur-net (dbus-get-property :system
-                                         enwc-nm-dbus-service
-                                         enwc-nm-wireless-dev
-                                         enwc-nm-dbus-wireless-interface
-                                         "ActiveAccessPoint")))
-         (if (string= cur-net "/")
-             "/"
-           cur-net)))
-
-  (dbus-register-signal :system
-                       enwc-nm-dbus-service
-                       enwc-nm-wireless-dev
-                       enwc-nm-dbus-wireless-interface
-                       "PropertiesChanged"
-                       'enwc-nm-wireless-prop-changed)
+        (let ((cur-net (dbus-get-property :system
+                                          enwc-nm-dbus-service
+                                          enwc-nm-wireless-dev
+                                          enwc-nm-dbus-wireless-interface
+                                          "ActiveAccessPoint")))
+          (if (string= cur-net "/")
+              "/"
+            cur-net)))
+
+  (setq enwc-nm-properties-changed-signal
+        (dbus-register-signal :system
+                              enwc-nm-dbus-service
+                              enwc-nm-wireless-dev
+                              enwc-nm-dbus-wireless-interface
+                              "PropertiesChanged"
+                              'enwc-nm-wireless-prop-changed))
 
   (setq enwc-nm-connecting-p
-       (let ((state (dbus-get-property :system
-                                       enwc-nm-dbus-service
-                                       enwc-nm-dbus-path
-                                       enwc-nm-dbus-interface
-                                       "State")))
-         (eq state 40)))
-
-  (dbus-register-signal :system
-                       enwc-nm-dbus-service
-                       enwc-nm-wired-dev
-                       enwc-nm-dbus-device-interface
-                       "StateChanged"
-                       'enwc-nm-dev-prop-changed)
+        (let ((state (dbus-get-property :system
+                                        enwc-nm-dbus-service
+                                        enwc-nm-dbus-path
+                                        enwc-nm-dbus-interface
+                                        "State")))
+          (eq state 40)))
+
+  (setq enwc-nm-wired-state-changed-signal
+        (dbus-register-signal :system
+                              enwc-nm-dbus-service
+                              enwc-nm-wired-dev
+                              enwc-nm-dbus-device-interface
+                              "StateChanged"
+                              'enwc-nm-dev-prop-changed))
 
   (setq enwc-nm-wired-p
-       (let ((state (dbus-get-property :system
-                                       enwc-nm-dbus-service
-                                       enwc-nm-wired-dev
-                                       enwc-nm-dbus-device-interface
-                                       "State")))
-         (eq state 100)))
-  (dbus-register-signal :system
-                       enwc-nm-dbus-service
-                       enwc-nm-dbus-path
-                       enwc-nm-dbus-interface
-                       "StateChanged"
-                       'enwc-nm-prop-changed)
-  )
-
+        (let ((state (dbus-get-property :system
+                                        enwc-nm-dbus-service
+                                        enwc-nm-wired-dev
+                                        enwc-nm-dbus-device-interface
+                                        "State")))
+          (eq state 100)))
+  (setq enwc-nm-state-changed-signal
+        (dbus-register-signal :system
+                              enwc-nm-dbus-service
+                              enwc-nm-dbus-path
+                              enwc-nm-dbus-interface
+                              "StateChanged"
+                              'enwc-nm-prop-changed)))
+
+(defun enwc-nm-unload ()
+  "Unload the NetworkManager back-end.
+
+Unregister all of the D-Bus signals set up during load."
+  (dbus-unregister-object enwc-nm-access-point-added-signal)
+  (dbus-unregister-object enwc-nm-access-point-removed-signal)
+  (dbus-unregister-object enwc-nm-properties-changed-signal)
+  (dbus-unregister-object enwc-nm-wired-state-changed-signal)
+  (dbus-unregister-object enwc-nm-state-changed-signal))
 
 (provide 'enwc-nm)
 
-;;; End of File.
+;;; enwc-nm.el ends here
diff --git a/lisp/enwc-setup.el b/lisp/enwc-setup.el
index 053b941..1e11100 100644
--- a/lisp/enwc-setup.el
+++ b/lisp/enwc-setup.el
@@ -1,118 +1,84 @@
 ;; enwc-setup.el - Setup routines for ENWC
 
-;; Copyright (C) 2012,2013 Free Software Foundation
+;; Copyright (C) 2012-2014 Free Software Foundation, Inc.
 
-;; Author: Ian Dunn
-;; Keywords: enwc, network, wicd, manager, nm
+;; Author: Ian Dunn <address@hidden>
+;; Keywords: network, wicd, manager, nm
+;; Version: 2.0
+;; Homepage: https://savannah.nongnu.org/p/enwc
 
-;; This file is part of ENWC
+;; This file is part of GNU Emacs.
 
-;; ENWC is free software; you can redistribute it and/or modify it
+;; GNU Emacs is free software; you can redistribute it and/or modify it
 ;; under the terms of the GNU General Public License as published by
 ;; the Free Software Foundation; either version 3, or (at your option)
 ;; any later version.
 
-;; ENWC is distributed in the hope that it will be useful, but WITHOUT
+;; GNU Emacs is distributed in the hope that it will be useful, but WITHOUT
 ;; ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
 ;; or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public
 ;; License for more details.
 
 ;; You should have received a copy of the GNU General Public License
-;; along with ENWC; see the file COPYING.  If not, write to the Free
+;; along with GNU Emacs; see the file COPYING.  If not, write to the Free
 ;; Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
 ;; 02110-1301, USA.
 
+;;; Commentary:
+
+;;; Code:
+
 (require 'enwc)
 (require 'enwc-wicd)
 (require 'enwc-nm)
 
-(defun enwc-setup-backend (cur-back)
-  "Sets up ENWC to use the correct function for the backend CUR-BACK."
-  (let ((sym-name (symbol-name cur-back)))
-    (setq enwc-scan-func (intern (concat "enwc-"
-                                        sym-name
-                                        "-scan"))
-         enwc-get-nw-func (intern (concat "enwc-"
-                                          sym-name
-                                          "-get-networks"))
-         enwc-get-wireless-nw-prop-func (intern (concat "enwc-"
-                                                        sym-name
-                                                        
"-get-wireless-network-property"))
-         enwc-get-wireless-nw-props-func (intern (concat "enwc-"
-                                                         sym-name
-                                                         
"-get-wireless-nw-props"))
-         enwc-details-list (symbol-value (intern (concat "enwc-"
-                                                         sym-name
-                                                         "-details-list")))
-         enwc-get-encryption-type-func (intern (concat "enwc-"
-                                                       sym-name
-                                                       "-get-encryption-type"))
-         enwc-wireless-connect-func (intern (concat "enwc-"
-                                                    sym-name
-                                                    "-connect"))
-         enwc-get-current-nw-id-func (intern (concat "enwc-"
-                                                     sym-name
-                                                     "-get-current-nw-id"))
-         enwc-check-connecting-func (intern (concat "enwc-"
-                                                    sym-name
-                                                    "-check-connecting"))
-         enwc-get-wired-profiles-func (intern (concat "enwc-"
-                                                      sym-name
-                                                      "-get-wired-profiles"))
-         enwc-is-wired-func (intern (concat "enwc-"
-                                            sym-name
-                                            "-is-wired"))
-         enwc-wired-connect-func (intern (concat "enwc-"
-                                                 sym-name
-                                                 "-wired-connect"))
-         enwc-wired-disconnect-func (intern (concat "enwc-"
-                                                    sym-name
-                                                    "-wired-disconnect"))
-         enwc-get-sec-types-func (intern (concat "enwc-"
-                                                 sym-name
-                                                 "-get-sec-types"))
-         enwc-get-ip-addr-func (intern (concat "enwc-"
-                                               sym-name
-                                               "-get-ip-addr"))
-         enwc-get-netmask-func (intern (concat "enwc-"
-                                               sym-name
-                                               "-get-netmask"))
-         enwc-get-gateway-func (intern (concat "enwc-"
-                                               sym-name
-                                               "-get-gateway"))
-         enwc-get-dns-func (intern (concat "enwc-"
-                                           sym-name
-                                           "-get-dns"))
-         enwc-get-nw-info-func (intern (concat "enwc-"
-                                               sym-name
-                                               "-get-nw-info"))
-         enwc-save-nw-settings-func (intern (concat "enwc-"
-                                                    sym-name
-                                                    "-save-nw-settings"))
-         )
-    (funcall (intern (concat "enwc-" sym-name "-setup")))))
+(defun enwc-load-backend (&optional backend)
+  "Load the backend BACKEND."
+  (interactive)
+  (unless backend
+    (setq backend
+          (intern (completing-read "Backend: " enwc-backends nil t))))
+  (when (and enwc-current-backend
+             (not (eq enwc-current-backend backend)))
+    (enwc-unload-backend))
+  (let ((service (symbol-value (intern (concat "enwc-"
+                                               (symbol-name backend)
+                                               "-dbus-service")))))
+    ;;TODO: Might need a better way of doing this.
+    ;; NM doesn't seem to want to ping.
+    (unless (dbus-ping :system service)
+      (error "Backend %s is not usable." backend))
+
+    (enwc-call-backend-function "load" backend)
+    (setq enwc-current-backend backend)))
+
+(defun enwc-unload-backend ()
+  "Unload the current backend."
+  (when enwc-current-backend
+    (enwc-call-backend-function "unload")
+    (setq enwc-current-backend nil)))
 
 ;;;###autoload
 (defun enwc-setup ()
-  "Sets up ENWC.
-This setups ENWC and confirms that one of the backends can be found
-on D-Bus."
-  (add-to-list 'global-mode-string 'enwc-display-string t #'equal)
-  (unless enwc-mode-line-timer
-    (setq enwc-mode-line-timer (run-at-time t 1 'enwc-update-mode-line)))
-  (let ((cur-back nil)
-       (back-list enwc-backends))
-    (while (and back-list (not cur-back))
+  "Set up ENWC.
+This sets up ENWC and confirms that one of the backends can be found on D-Bus."
+  (when enwc-display-mode-line
+    (enwc-enable-display-mode-line))
+
+  (when (and enwc-auto-scan
+             (> enwc-auto-scan-interval 0)
+             (not enwc-scan-timer))
+    (setq enwc-scan-timer
+          (run-at-time t enwc-auto-scan-interval 'enwc-scan t)))
+
+  (let ((back-list enwc-backends)
+        cur-back pass)
+    (while (and back-list (not pass))
       (setq cur-back (pop back-list))
-      (if (not (dbus-ping :system
-                         (symbol-value (intern (concat "enwc-"
-                                                       (symbol-name cur-back)
-                                                       "-dbus-service")))))
-         (setq cur-back nil)))
-    (if cur-back
-       (enwc-setup-backend cur-back)
-      (error "No usable backend found."))))
+      (setq pass (ignore-errors (enwc-load-backend cur-back))))
+    (unless pass
+      (error "No usable backend was found."))))
 
 (provide 'enwc-setup)
 
-;;; End of File.
+;;; enwc-setup.el ends here
diff --git a/lisp/enwc-wicd.el b/lisp/enwc-wicd.el
index f02f4b6..3438ee2 100644
--- a/lisp/enwc-wicd.el
+++ b/lisp/enwc-wicd.el
@@ -1,30 +1,34 @@
 ;;; enwc-wicd.el --- The Wicd backend to ENWC
 
-;; Copyright (C) 2012,2013,2014 Free Software Foundation
+;; Copyright (C) 2012-2014 Free Software Foundation, Inc.
 
-;; Author: Ian Dunn
-;; Keywords: enwc, network, wicd, manager, nm
+;; Author: Ian Dunn <address@hidden>
+;; Keywords: network, wicd, manager, nm
+;; Version: 2.0
+;; Homepage: https://savannah.nongnu.org/p/enwc
 
-;; This file is part of ENWC
+;; This file is part of GNU Emacs
 
-;; ENWC is free software; you can redistribute it and/or modify it
+;; GNU Emacs is free software; you can redistribute it and/or modify it
 ;; under the terms of the GNU General Public License as published by
 ;; the Free Software Foundation; either version 3, or (at your option)
 ;; any later version.
 
-;; ENWC is distributed in the hope that it will be useful, but WITHOUT
+;; GNU Emacs is distributed in the hope that it will be useful, but WITHOUT
 ;; ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
 ;; or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public
 ;; License for more details.
 
 ;; You should have received a copy of the GNU General Public License
-;; along with ENWC; see the file COPYING.  If not, write to the Free
+;; along with GNU Emacs; see the file COPYING.  If not, write to the Free
 ;; Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
 ;; 02110-1301, USA.
 
-
 ;;; Commentary:
-;; TODO
+
+;; Wicd is one of the default supported back-ends for ENWC.
+
+;;; Code:
 
 (require 'enwc)
 
@@ -59,43 +63,75 @@
   :type 'string)
 
 (defvar enwc-wicd-details-list
-  '("essid" "bssid" "quality" "encryption" "mode" "channel")
+  '("essid" "bssid" "quality" "encryption" "channel")
   "The list of the desired details to be obtained from each network.")
 
-(defvar enwc-wicd-current-ap "")
+(defvar enwc-wicd-current-ap ""
+  "Current access point.
+UNUSED")
+
+(defvar enwc-wicd-current-nw-id -1
+  "Id of the current network.
+UNUSED")
 
-(defvar enwc-wicd-current-nw-id -1)
+(defvar enwc-wicd-end-scan-signal nil
+  "D-Bus signal object for the \"SendEndScanSignal\" signal.")
+
+(defvar enwc-wicd-status-changed-signal nil
+  "D-Bus signal objects for the \"StatusChanged\" signal.")
 
 (defun enwc-wicd-dbus-wireless-call-method (method &rest args)
   "Calls D-Bus method METHOD with arguments ARGS within
 the wicd wireless interface."
   (apply 'dbus-call-method :system
-        enwc-wicd-dbus-service
-        enwc-wicd-dbus-wireless-path
-        enwc-wicd-dbus-wireless-interface
-        method
-        :timeout 25000
-        args))
+         enwc-wicd-dbus-service
+         enwc-wicd-dbus-wireless-path
+         enwc-wicd-dbus-wireless-interface
+         method
+         :timeout 25000
+         args))
 
 (defun enwc-wicd-dbus-wired-call-method (method &rest args)
   "Calls D-Bus method METHOD with arguments ARGS within
 the wicd wired interface."
   (apply 'dbus-call-method :system
-        enwc-wicd-dbus-service
-        enwc-wicd-dbus-wired-path
-        enwc-wicd-dbus-wired-interface
-        method
-        :timeout 25000
-        args))
+         enwc-wicd-dbus-service
+         enwc-wicd-dbus-wired-path
+         enwc-wicd-dbus-wired-interface
+         method
+         :timeout 25000
+         args))
+
+;;;;;;;;;;
+;; Scan ;;
+;;;;;;;;;;
 
 (defun enwc-wicd-scan ()
   "Wicd scan function."
   (enwc-wicd-dbus-wireless-call-method "Scan"))
 
-(defun enwc-wicd-get-networks ()
-  "Wicd get networks function.  Just returns a number sequence."
+;;;;;;;;;;;;;;;;;;
+;; Get networks ;;
+;;;;;;;;;;;;;;;;;;
+
+(defun enwc-wicd-get-networks (&optional wired)
+  (if wired
+      (enwc-wicd-get-wired-profiles)
+    (enwc-wicd-get-wireless-networks)))
+
+(defun enwc-wicd-get-wireless-networks ()
+  "Wicd get networks function.
+Just returns a number sequence."
   (number-sequence 0 (1- (enwc-wicd-dbus-wireless-call-method 
"GetNumberOfNetworks"))))
 
+(defun enwc-wicd-get-wired-profiles ()
+  "Get the list of wired network profiles."
+  (enwc-wicd-dbus-wired-call-method "GetWiredProfileList"))
+
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;; Get network properties ;;
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+
 (defvar enwc-wicd-prop-values nil)
 (defvar enwc-wicd-prop-num 0)
 (defvar enwc-wicd-prop-timeout 3)
@@ -104,35 +140,41 @@ the wicd wired interface."
   "The handler for `enwc-wicd-get-wireless-network-property'.
 This receives the value of network property PROP,
 and appends the value to `enwc-wicd-prop-values'."
-  (setq enwc-wicd-prop-values (cons (cons prop (car args)) 
enwc-wicd-prop-values))
+  (push `(,prop . ,(car args)) enwc-wicd-prop-values)
   (setq enwc-wicd-prop-num (1+ enwc-wicd-prop-num)))
 
+(defun enwc-wicd-prop-to-prop (prop)
+  "Convert a Wicd network property to an ENWC network property."
+  (cond
+   ((equal prop "essid") 'essid)
+   ((equal prop "bssid") 'bssid)
+   ((equal prop "quality") 'strength)
+   ((equal prop "encryption") 'encrypt)
+   ((equal prop "mode") 'mode)
+   ((equal prop "channel") 'channel)))
+
 (defun enwc-wicd-get-wireless-network-property (id prop)
   "Wicd get wireless network property function.
 This calls the D-Bus method on Wicd to get the property PROP
 from wireless network with id ID."
   (dbus-call-method-asynchronously :system
-                                  enwc-wicd-dbus-service
-                                  enwc-wicd-dbus-wireless-path
-                                  enwc-wicd-dbus-wireless-interface
-                                  "GetWirelessProperty"
-                                  `(lambda (x) (enwc-wicd-nw-prop-handler 
,prop x))
+                                   enwc-wicd-dbus-service
+                                   enwc-wicd-dbus-wireless-path
+                                   enwc-wicd-dbus-wireless-interface
+                                   "GetWirelessProperty"
+                                   `(lambda (x) (enwc-wicd-nw-prop-handler 
,prop x))
                                    :timeout 1000
-                                  :int32 id
-                                  :string prop))
+                                   :int32 id
+                                   :string prop))
 
 (defun enwc-wicd-build-prop-list (prop-list det-list)
-  (let (ret
-       (act-det-list (reverse det-list)))
-    (while act-det-list
-      (let* ((cur-det (pop act-det-list))
-            (cur-prop (assoc cur-det prop-list)))
-        (setq ret
-              (if cur-prop
-                  (cons cur-prop ret)
-                (cons (cons cur-det nil) nil)))
-       ))
-    ret))
+  (mapcar
+   (lambda (det)
+     (let* ((cur-prop (assoc det prop-list))
+            (act-det (enwc-wicd-prop-to-prop det))
+            (act-prop (when cur-prop (cdr cur-prop))))
+       `(,act-det . ,act-prop)))
+   det-list))
 
 (defun enwc-wicd-get-wireless-nw-props (id)
   "Get the network properties of a network.
@@ -141,114 +183,114 @@ for the network with id ID.
 For a list of properties, see `enwc-wicd-details-list'."
   (setq enwc-wicd-prop-values nil)
   (setq enwc-wicd-prop-num 0)
-  (mapc (lambda (x)
-           (enwc-wicd-get-wireless-network-property id x))
-         enwc-wicd-details-list)
-  ;; Wait for less than a second.
+  (dolist (x enwc-wicd-details-list)
+    (enwc-wicd-get-wireless-network-property id x))
+
   (with-timeout (enwc-wicd-prop-timeout)
-      (while (< enwc-wicd-prop-num 6)
-       (read-event nil nil 0.001)))
+    (while (< enwc-wicd-prop-num (length enwc-wicd-details-list))
+      (read-event nil nil 0.001)))
+
+  (if (assoc "encryption" enwc-wicd-prop-values)
+      (let ((enc-type (enwc-wicd-get-encryption-type id)))
+        (setcdr (assoc "encryption" enwc-wicd-prop-values)
+                (or enc-type "Unsecured")))
+    (setq enwc-wicd-prop-values
+          (cons (cons "encryption" "Unsecured")
+                enwc-wicd-prop-values)))
 
   (enwc-wicd-build-prop-list enwc-wicd-prop-values enwc-wicd-details-list))
 
+(defalias 'enwc-wicd-get-wireless-network-props 
'enwc-wicd-get-wireless-nw-props)
+
 (defun enwc-wicd-get-encryption-type (id)
   "Wicd get encryption type function.
 This calls the D-Bus method on Wicd to get the encryption_method
 property from wireless network with id ID."
   (enwc-wicd-dbus-wireless-call-method "GetWirelessProperty"
-                                      id "encryption_method"))
+                                       id "encryption_method"))
 
-(defun enwc-wicd-connect (id)
-  "Wicd connect function.
-This calls the D-Bus method on Wicd to connect to wireless
-network with id ID."
-  (enwc-wicd-dbus-wireless-call-method "ConnectWireless" id))
-
-(defun enwc-wicd-get-current-nw-id (wired)
-  "Wicd get current network id function.
-This calls the D-Bus method on Wicd to get the current
-wireless network id."
-  (if wired
-      -1
-    enwc-wicd-current-nw-id))
+(defun enwc-wicd-get-wired-nw-prop (id det)
+  "Get property DET from the wired network with id ID."
+  (enwc-wicd-dbus-wired-call-method "GetWiredProperty" id det))
 
-(defun enwc-wicd-check-connecting ()
-  "The Wicd check connecting function."
-  (enwc-wicd-dbus-wireless-call-method "CheckIfWirelessConnecting"))
+;;;;;;;;;;;;;;;;;;;;;;;
+;; Connect Functions ;;
+;;;;;;;;;;;;;;;;;;;;;;;
 
-(defun enwc-wicd-disconnect ()
-  "Wicd disconnect function."
-  (enwc-wicd-dbus-wireless-call-method "DisconnectWireless"))
+(defun enwc-wicd-connect (id &optional wired)
+  "Wicd connect function.
+This calls the D-Bus method on Wicd to connect to a
+wired or wireless network with id ID."
+  (if wired
+      (enwc-wicd-wired-connect id)
+    (enwc-wicd-dbus-wireless-call-method "ConnectWireless" id)))
 
-(defun enwc-wicd-get-wired-profiles ()
-  "Gets the list of wired network profiles."
-  (enwc-wicd-dbus-wired-call-method "GetWiredProfileList"))
+(defun enwc-wicd-wireless-connect (id)
+  "Wicd connect function.
+This calls the D-Bus method on Wicd to connect to a
+wireless network with id ID."
+  (enwc-wicd-dbus-wireless-call-method "ConnectWireless" id))
 
 (defun enwc-wicd-wired-connect (id)
-  "Connects to the wired network with profile id ID."
-  (let* ((profs (enwc-get-wired-profiles))
-        (prf (nth id profs)))
+  "Connect to the wired network with profile id ID."
+  (let* ((profs (enwc-wicd-get-wired-profiles))
+         (prf (nth id profs)))
     (enwc-wicd-dbus-wired-call-method "ReadWiredNetworkProfile" prf)
     (enwc-wicd-dbus-wired-call-method "ConnectWired")))
 
+;;;;;;;;;;;;;;;;;;;;;;;;;;
+;; Disconnect functions ;;
+;;;;;;;;;;;;;;;;;;;;;;;;;;
+
+(defun enwc-wicd-disconnect (&optional wired)
+  (if wired
+      (enwc-wicd-wired-disconnect)
+    (enwc-wicd-wireless-disconnect)))
+
+(defun enwc-wicd-wireless-disconnect ()
+  "Wicd disconnect function."
+  (enwc-wicd-dbus-wireless-call-method "DisconnectWireless"))
+
 (defun enwc-wicd-wired-disconnect ()
-  "Disconnects from the wired connection."
+  "Disconnect from the wired connection."
   (enwc-wicd-dbus-wired-call-method "DisconnectWired"))
 
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;; Get current network id ;;
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+
+(defun enwc-wicd-get-current-nw-id (wired-p)
+  "Wicd get current network id function.
+The current network id is updated upon connect,
+so this jut returns the tracked network id."
+  (let ((ap (enwc-wicd-dbus-wireless-call-method "GetCurrentNetworkID")))
+    (cond
+     (wired-p 'wired)
+     ((< ap 0) nil)
+     (t ap))))
+
+;;;;;;;;;;;;;;;;;;;;;;
+;; Check Connecting ;;
+;;;;;;;;;;;;;;;;;;;;;;
+
+(defun enwc-wicd-check-connecting ()
+  "Return non-nil if currently connecting to a network."
+  (enwc-wicd-dbus-wireless-call-method "CheckIfWirelessConnecting"))
+
+;;;;;;;;;;;;;
+;; Is Wired
+;;;;;;;;;;;;;
+
 (defun enwc-wicd-is-wired ()
-  "Checks to see if wired is connected."
+  "Return non-nil if connected to a wired network."
   (not (not (enwc-wicd-dbus-wired-call-method "GetWiredIP"))))
 
-(defun enwc-wicd-get-wired-nw-prop (id det)
-  "Gets property DET from the wired network with id ID."
-  (enwc-wicd-dbus-wired-call-method "GetWiredProperty" id det))
+;;;;;;;;;;;;;;;;;;;;;;
+;; Get Profile Info ;;
+;;;;;;;;;;;;;;;;;;;;;;
 
-;; Each entry in sec-types should be:
-;; ("IDENT" (("Name" . "NAME") ("reqs" . (("key1" . "Entry1") ("key2" . 
"Entry2") ... ))))
-;; Where:
-;;  "IDENT" => String that identifies this to the backend.
-;;  "NAME" => String that ENWC displays
-;;  "reqs" => Constant string, but the association list holds entries
-;;              required by the security type, i.e. user, passphrase, etc.
-;;  "keyXX" => String that the backend uses for this security entry.
-;;  "EntryXX" => String that ENWC displays for this security entry.
-
-(defun enwc-wicd-get-sec-types (wired)
-  "Gets the list of security types.
-WIRED indicates whether this is a wired connection.
-The returned list will be in the format:
- (name . ((\"Name\" . \"DISPLAY-NAME\")
-          (\"reqs\" . ((\"Display\" . \"id\") ...))))"
-  (let (sec-types
-       ret-list)
-    (with-temp-buffer
-      (insert-file-contents (concat "/etc/wicd/encryption/templates/active"
-                                   (if wired
-                                       "_wired")))
-      (setq sec-types (split-string (buffer-string) "\n")))
-    (setq ret-list
-         (mapcar (lambda (x)
-                   (if (not (eq (length x) 0))
-                       (let (name reqs)
-                         (with-temp-buffer
-                           (insert-file-contents (concat 
"/etc/wicd/encryption/templates/"
-                                                         x))
-                           (re-search-forward "name[ \t]*=[ 
\t]*\\([^\n]*\\)[\n]")
-                           (setq name (match-string 1))
-                           (re-search-forward "require[ \t]*\\([^\n]*\\)[\n]")
-                           (let ((str-reqs (split-string (match-string 1) " 
")))
-                             (while str-reqs
-                               (setq reqs
-                                     (append reqs
-                                             (cons (cons (pop str-reqs)
-                                                         (pop str-reqs))
-                                                   nil)))))
-                           (cons x (cons (cons "Name" name) (cons (cons "reqs" 
(cons reqs nil)) nil)))
-                           ))))
-                 sec-types))))
-
-(defun enwc-wicd-get-profile-ent (wired id ent)
-  "Gets profile entry ENT from the network with id ID.
+(defun enwc-wicd-get-profile-ent (id ent wired)
+  "Get profile entry ENT from the network with id ID.
 WIRED is set to indicate whether this is a wired network.
 This function is a wrapper around the *-get-(wired|wireless)-nw-prop
 functions, allowing for a single function that checks for wired."
@@ -256,45 +298,65 @@ functions, allowing for a single function that checks for 
wired."
       (enwc-wicd-get-wired-nw-prop id ent)
     (enwc-wicd-dbus-wireless-call-method "GetWirelessProperty" id ent)))
 
-(defun enwc-wicd-get-nw-info (wired id)
-  (let ((dns-list (enwc-wicd-get-dns wired id)))
-    (list (cons (cons "addr" (enwc-wicd-get-ip-addr wired id)) nil)
-         (cons (cons "netmask" (enwc-wicd-get-netmask wired id)) nil)
-         (cons (cons "gateway" (enwc-wicd-get-gateway wired id)) nil)
-         (cons (cons "dns1" (nth 0 dns-list)) nil)
-         (cons (cons "dns2" (nth 1 dns-list)) nil))))
-
-(defun enwc-wicd-get-ip-addr (wired id)
-  "Gets the IP Address from the network with id ID.
+(defun enwc-wicd-get-profile-info (id &optional wired)
+  "Get the profile for profile ID.
+WIRED is set to indicate whether this is a wired network."
+  (let ((dns-list (enwc-wicd-get-dns id wired))
+        (sec-info (enwc-wicd-get-profile-sec-info id wired)))
+    `((addr . ,(enwc-wicd-get-ip-addr id wired))
+      (netmask . ,(enwc-wicd-get-netmask id wired))
+      (gateway . ,(enwc-wicd-get-gateway id wired))
+      (dns1 . ,(nth 0 dns-list))
+      (dns2 . ,(nth 1 dns-list))
+      ,@sec-info)))
+
+(defun enwc-wicd-get-profile-sec-info (id &optional wired)
+  "Get the security info for profile with id ID.
+WIRED is set to indicate whether this is a wired network."
+  (remq nil
+   (mapcar
+    (lambda (ent)
+      (let ((info (enwc-wicd-get-profile-ent wired id (symbol-name (car 
ent)))))
+        (if info
+            (cons (car ent) info)
+          nil)))
+    enwc-supplicant-alist)))
+
+(defun enwc-wicd-get-ip-addr (id wired)
+  "Get the IP Address from the network with id ID.
 Wired is set to indicate whether this is a wired network."
-  (or (enwc-wicd-get-profile-ent wired id "ip") ""))
+  (or (enwc-wicd-get-profile-ent id "ip" wired) ""))
 
-(defun enwc-wicd-get-netmask (wired id)
-  "Gets the Netmask from the network with id ID.
+(defun enwc-wicd-get-netmask (id wired)
+  "Get the Netmask from the network with id ID.
 WIRED is set to indicate whether this is a wired network."
-  (or (enwc-wicd-get-profile-ent wired id "netmask") ""))
+  (or (enwc-wicd-get-profile-ent id "netmask" wired) ""))
 
-(defun enwc-wicd-get-gateway (wired id)
-    "Gets the Gateway from the network with id ID.
+(defun enwc-wicd-get-gateway (id wired)
+  "Get the Gateway from the network with id ID.
 WIRED is set to indicate whether this is a wired network."
-  (or (enwc-wicd-get-profile-ent wired id "gateway") ""))
+  (or (enwc-wicd-get-profile-ent id "gateway" wired) ""))
 
-(defun enwc-wicd-get-dns (wired id)
-    "Gets the list of DNS servers from the network with id ID.
+(defun enwc-wicd-get-dns (id wired)
+  "Get the list of DNS servers from the network with id ID.
 WIRED is set to indicate whether this is a wired network."
-  (list (or (enwc-wicd-get-profile-ent wired id "dns1") "")
-       (or (enwc-wicd-get-profile-ent wired id "dns2") "")
-       (or (enwc-wicd-get-profile-ent wired id "dns3") "")))
+  (list (or (enwc-wicd-get-profile-ent id "dns1" wired) "")
+        (or (enwc-wicd-get-profile-ent id "dns2" wired) "")
+        (or (enwc-wicd-get-profile-ent id "dns3" wired) "")))
+
+;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;; Save Network Settings ;;
+;;;;;;;;;;;;;;;;;;;;;;;;;;;
 
 (defun enwc-wicd-set-nw-prop (wired id prop val)
-  "Sets the network property PROP of the network with id ID
+  "Set the network property PROP of the network with id ID
 to VAL.
 WIRED indicates whether this is a wired network."
   (if wired
       (enwc-wicd-dbus-wired-call-method "SetWiredProperty"
-                                       id prop val)
+                                        id prop val)
     (enwc-wicd-dbus-wireless-call-method "SetWirelessProperty"
-                                        id prop val)))
+                                         id prop val)))
 
 (defun enwc-wicd-save-nw-profile (wired id)
   "Save the network profile with for the network with id ID.
@@ -303,61 +365,81 @@ WIRED indicates whether this is a wired network."
       (enwc-wicd-dbus-wired-call-method "SaveWiredNetworkProfile" id)
     (enwc-wicd-dbus-wireless-call-method "SaveWirelessNetworkProfile" id)))
 
-(defun enwc-wicd-save-nw-settings (wired id settings)
-  "Saves the settings indicated by the association list SETTINGS for
-the network with id ID."
-  (let ((enctype (cdr (assoc "enctype" settings))))
-
-    (enwc-wicd-set-nw-prop wired id "ip"
-                          (cdr (assoc "addr" settings)))
-    (enwc-wicd-set-nw-prop wired id "netmask"
-                          (cdr (assoc "netmask" settings)))
-    (enwc-wicd-set-nw-prop wired id "gateway"
-                          (cdr (assoc "gateway" settings)))
-
-    (enwc-wicd-set-nw-prop wired id "dns1"
-                          (cdr (assoc "dns1" settings)))
-    (enwc-wicd-set-nw-prop wired id "dns2"
-                          (cdr (assoc "dns2" settings)))
-
-    (enwc-wicd-set-nw-prop wired id "enctype" enctype)
-    (if (not (string= enctype "None"))
-       (dolist (x (cadr (assoc "reqs"
-                               (cdr (assoc enctype
-                                           (enwc-wicd-get-sec-types wired))))))
-         (enwc-wicd-set-nw-prop wired id (car x)
-                                (cdr (assoc (car x) settings)))))
-    (enwc-wicd-save-nw-profile wired id))
-  )
+(defun enwc-wicd--phase-to-string (phase)
+  "Convert a list of phase settings PHASE into a string.
+
+The format of this string is \"ENT0=VAL0 ENT1=VAL1 ... ENTN=VALN\",
+for each entry in PHASE."
+  (mapconcat
+   (lambda (ent)
+     (format "%s=%s" (car ent) (cdr ent)))
+   phase " "))
+
+(defun enwc-wicd-save-nw-settings (id settings &optional wired)
+  "Set the settings for network ID to SETTINGS and save the profile.
+The association list SETTINGS contains the settings for the network.
+WIRED indicates whether or not ID is a wired connection."
+  (dolist (setting settings)
+    (let (key ent)
+      ;; There are four special cases in here:
+      ;;  1. IP Address, which has a different key.
+      ;;  2. Encryption type, which has a different key and value.
+      ;;  3,4. Phases, both of which need to have their results concatenated.
+      (pcase (car setting)
+        ('addr (setq key "ip"
+                     ent (cdr setting)))
+        ('sec-type (setq key "enctype"
+                         ent (if (cdr setting)
+                                 (symbol-name (cdr setting))
+                               "None")))
+        ('phase1 (setq key "phase1"
+                       ent (enwc-wicd--phase-to-string (cdr setting))))
+        ('phase2 (setq key "phase2"
+                       ent (enwc-wicd--phase-to-string (cdr setting))))
+        (_ (setq key (symbol-name (car setting))
+                 ent (or (cdr setting) ""))))
+      (enwc-wicd-set-nw-prop wired id key ent)))
+
+  (enwc-wicd-save-nw-profile wired id))
 
 (defun enwc-wicd-wireless-prop-changed (state info)
-  (if state
-      (if (eq state 0)
-         (setq enwc-wicd-current-ap ""
-               enwc-wicd-current-nw-id -1)
-       (setq enwc-wicd-current-ap (car (cadr info))
-             enwc-wicd-current-nw-id (or (and info
-                                              (nthcdr 3 info)
-                                              (caar (nthcdr 3 info))
-                                              (string-to-number (caar (nthcdr 
3 info))))
-                                         -1)))))
-
-(defun enwc-wicd-setup ()
+  "Callback for when the network status changes."
+  (when state
+    (if (eq state 0)
+        (setq enwc-wicd-current-ap ""
+              enwc-wicd-current-nw-id nil)
+      (setq enwc-wicd-current-ap (car (cadr info))
+            enwc-wicd-current-nw-id (and info
+                                         (nthcdr 3 info)
+                                         (caar (nthcdr 3 info))
+                                         (string-to-number (caar (nthcdr 3 
info))))))))
+
+(defun enwc-wicd-load ()
+  "Load the Wicd backend."
   ;; Thanks to Michael Albinus for pointing out this signal.
-  (dbus-register-signal :system
-                       enwc-wicd-dbus-service
-                       enwc-wicd-dbus-wireless-path
-                       enwc-wicd-dbus-wireless-interface
-                       "SendEndScanSignal"
-                       'enwc-process-scan)
-
-  (dbus-register-signal :system
-                       enwc-wicd-dbus-service
-                       "/org/wicd/daemon"
-                       enwc-wicd-dbus-service
-                       "StatusChanged"
-                       'enwc-wicd-wireless-prop-changed))
+  (setq enwc-wicd-end-scan-signal
+        (dbus-register-signal :system
+                              enwc-wicd-dbus-service
+                              enwc-wicd-dbus-wireless-path
+                              enwc-wicd-dbus-wireless-interface
+                              "SendEndScanSignal"
+                              'enwc-process-scan))
+
+  (setq enwc-wicd-status-changed-signal
+        (dbus-register-signal :system
+                              enwc-wicd-dbus-service
+                              "/org/wicd/daemon"
+                              enwc-wicd-dbus-service
+                              "StatusChanged"
+                              'enwc-wicd-wireless-prop-changed)))
+
+(defun enwc-wicd-unload ()
+  "Unload the Wicd back-end.
+
+Unregister all of the D-Bus signals set up during load."
+  (dbus-unregister-object enwc-wicd-end-scan-signal)
+  (dbus-unregister-object enwc-wicd-status-changed-signal))
 
 (provide 'enwc-wicd)
 
-;;; End of File
+;;; enwc-wicd.el ends here.
diff --git a/lisp/enwc.el b/lisp/enwc.el
index 69c81d0..540bc90 100644
--- a/lisp/enwc.el
+++ b/lisp/enwc.el
@@ -1,55 +1,60 @@
 ;;; enwc.el --- The Emacs Network Client
 
-;; Copyright (C) 2012,2013 Free Software Foundation
+;; Copyright (C) 2012-2014 Free Software Foundation, Inc.
 
-;; Author: Ian Dunn
+;; Author: Ian Dunn <address@hidden>
 ;; Keywords: external, network, wicd, manager, nm
+;; Version: 2.0
+;; Homepage: https://savannah.nongnu.org/p/enwc
 
-;; This file is part of ENWC
+;; This file is part of GNU Emacs.
 
-;; ENWC is free software; you can redistribute it and/or modify it
+;; GNU Emacs is free software; you can redistribute it and/or modify it
 ;; under the terms of the GNU General Public License as published by
 ;; the Free Software Foundation; either version 3, or (at your option)
 ;; any later version.
 
-;; ENWC is distributed in the hope that it will be useful, but WITHOUT
+;; GNU Emacs is distributed in the hope that it will be useful, but WITHOUT
 ;; ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
 ;; or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public
 ;; License for more details.
 
 ;; You should have received a copy of the GNU General Public License
-;; along with ENWC; see the file COPYING.  If not, write to the Free
+;; along with GNU Emacs; see the file COPYING.  If not, write to the Free
 ;; Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
 ;; 02110-1301, USA.
 
-;; connect
-;; disconnect
-;; scan
-;; get-prop
-;; save-profile
-;; get-networks
-;; check-connecting
-;; get-current-nw-id
-
 ;;; Commentary:
-;; In order to use this, add
+;;
+;; ENWC is the Emacs Network Client.  It is designed to provide a front-end to
+;; various network managers, such as NetworkManager and Wicd.
+;;
+;; Currently, only NetworkManager and Wicd are supported, although experimental
+;; support exists for Connman.
+;;
+;; In order to use this package, add
 ;;
 ;; (require 'enwc-setup)
 ;; (enwc-setup)
 ;;
-;; to your .emacs file.
+;; to your .emacs file (or other init file).
 
-(require 'dbus)
-(require 'wid-edit)
-(require 'tabulated-list)
+;;; TODO:
+;;
+;; - Add hooks for scan completion, and possibly upon network connection.
 
 ;;; Code:
 
+(require 'dbus)
+(require 'wid-edit)
+(require 'tabulated-list)
 (require 'cl-lib)
+(require 'cl-macs)
+(require 'format-spec)
 
 (defgroup enwc nil
   "*The Emacs Network Client"
-  :prefix "ewnc-"
+  :prefix "enwc-"
   :group 'external)
 
 (defcustom enwc-wireless-device "wlan0"
@@ -69,173 +74,126 @@ and the first active backend found will be used."
   :group 'enwc
   :type 'list)
 
+(defcustom enwc-display-mode-line 't
+  "Non-nil means display network information in the mode line.
+The specific information can be set using `enwc-mode-line-format'."
+  :group 'enwc
+  :type 'boolean)
+
+(defcustom enwc-auto-scan 't
+  "Whether or not to have ENWC automatically scan.
+If non-nil, then ENWC will automatically scan for
+networks every `enwc-auto-scan-interval' seconds."
+  :group 'enwc
+  :type 'boolean)
+
+(defcustom enwc-auto-scan-interval 20
+  "The interval between automatic scans."
+  :group 'enwc
+  :type 'integer)
+
+(defcustom enwc-mode-line-format "[%s%%]"
+  "The format for displaying the mode line.
+
+%s = The current signal strength.  If wired, then this is set to 100.
+
+%e = The essid of the current network.  If wired, then this set to 'Wired'
+
+%b = The bssid of the current network.  If using a wired connection, then this
+is set to 'Wired'.
+
+%n = The encryption type of the current network, or 'Wired' if using a wired
+connection.
+
+%c = The channel of the current network, or 'Wired' if using a wired 
connection.
+
+%% = A Normal '%'"
+  :group 'enwc
+  :type 'string)
+
 ;;; The function variables for the abstract layer.
 
-(defvar enwc-scan-func nil
-  "The function variable for the scan function.
-This variable is set during setup.")
-
-(defvar enwc-get-nw-func nil
-  "A function variable to be used in `enwc-get-nw'.
-This is redefined during setup to be the function to get the network
- list.")
-
-(defvar enwc-get-wireless-nw-prop-func nil
-  "A function variable to be used in `enwc-get-wireless-nw-prop'.
-This is redefined during setup to be the function to get
-a wireless network property.")
-
-(defvar enwc-get-wireless-nw-props-func nil)
-
-(defvar enwc-get-encryption-type-func nil
-  "A function variable to be used in `enwc-get-encryption-type'.
-This is redefined during setup to be the function to get the encryption
-type for the selected backend.")
-
-(defvar enwc-wireless-connect-func nil
-  "The function variable for the wireless connect function.
-This is redefined during setup to be the function to connect
-for the selected backend.")
-
-(defvar enwc-get-current-nw-id-func nil
-  "The function variable to be used in `enwc-get-current-nw-id'.
-This is redefined during setup to be the function to get
-the current network id.")
-
-(defvar enwc-check-connecting-func nil
-  "The function variable to be used in `enwc-check-connecting'.
-This is redefined during setup to be the function to
-check whether or not ENWC is connecting.")
-
-(defvar enwc-wireless-disconnect-func nil
-  "The function variable for the wireless disconnect function.
-This is redefined during setup to be the function to
-disconnect from the wireless network.")
-
-(defvar enwc-get-wired-profiles-func nil
-  "The function variable to be used in `enwc-get-wired-profiles'.
-This is redefined during setup to be the function to
-get the list of wired network profiles.")
-
-(defvar enwc-wired-connect-func nil
-  "The function variable for the wired connect function.
-This is redefined during setup to be the function
-to connect to a wired network.")
-
-(defvar enwc-wired-disconnect-func nil
-  "The function variable for the wired disconnect function.
-This is redefined during setup to be the function
-to disconnect from a wired network.")
-
-(defvar enwc-is-wired-func nil
-  "The function variable to be used in `enwc-is-wired'.
-This is redefined during setup to be the function to
-check whether or not a wired connection is active.")
-
-(defvar enwc-get-wired-nw-prop-func nil
-  "The function variable to be used in `enwc-get-wired-nw-prop'.
-This is redefined during setup to be the function to get
-a network property from a wired network.")
-
-(defvar enwc-get-sec-types-func nil
-  "The function variable to be used in `enwc-get-sec-types'.
-This is redefined during setup to be the function to get
-the security types for a given network.")
-
-(defvar enwc-get-ip-addr-func nil
-  "The function variable to be used in `enwc-get-ip-addr'.
-This is redefined during setup to be the function to get
-the IP Address of a given network.")
-
-(defvar enwc-get-netmask-func nil
-  "The function variable to be used in `enwc-get-netmask'.
-This is redefined during setup to be the function to get
-the Netmask of a given network.")
-
-(defvar enwc-get-gateway-func nil
-  "The function variable to be used in `enwc-get-gateway'.
-This is redefined during setup to be the function to get
-the Gateway of a given network.")
-
-(defvar enwc-get-dns-func nil
-  "The function variable to be used in `enwc-get-dns'.
-This is redefined during setup to be the function to get
-the DNS Server Addresses for a given network.")
-
-(defvar enwc-get-nw-info-func nil)
-
-(defvar enwc-save-nw-settings-func nil
-  "The function variable to be used in `enwc-save-nw-settings'.
-This is redefined during setup to be the function to save
-the network settings of a given network.")
-
-(defvar enwc-details-list nil
-  "The network details list.
-
-This is redefined during setup to be the details list
-for the selected backend.
-
-This usually includes signal strength, essid, encryption type,
-bssid, mode, and channel.")
+(defvar enwc-current-backend nil
+  "The backend that ENWC is currently using.
+
+Do not set this directly.  Instead, use `enwc-load-backend'.")
 
 (defvar enwc-display-string " [0%] "
   "The mode line display string.
 This is altered every second to display the current network strength
 in `enwc-update-mode-line'.")
 
-;; (setq tabulated-list-format (vector `("ID" ,enwc-id-width sort) ...))
-;; (setq tabulated-list-entries `((,id [id str essid encrypt ...]) ...))
-;; (tabulated-list-init-header)
-;; (tabulated-list-print)
-
-(defvar enwc-wireless-headers '("ID" "STR" "ESSID"
-                               "ENCRYPT" "BSSID" "MODE" "CHNL")
-  "The list of headers to be displayed in the ENWC buffer.
-These correspond to the details in `enwc-details-list'.")
-
-(defvar enwc-id-width 3
-  "The width of the id column.")
-(defvar enwc-str-width 5
-  "The width of the strength column.")
-(defvar enwc-essid-width 5
-  "The initial width of the essid column.
-This is reset in wicd-scan-internal.")
-(defvar enwc-encrypt-width 10
-  "The width of the encryption column.")
-(defvar enwc-bssid-width 18
-  "The width of the bssid column.")
-(defvar enwc-mode-width 16
-  "The width of the mode column.")
-(defvar enwc-chnl-width 3
-  "The width of the channel column.")
+(defun enwc-print-strength (s)
+  "Convert signal strength S to a string to dispay."
+  (concat (number-to-string s) "%"))
+
+(defvar enwc-details-alist
+  `((strength . ((display . "Str")
+                 (width   . 0)
+                 (conv    . enwc-print-strength)))
+    (essid    . ((display . "Essid")
+                 (width   . 0)
+                 (conv    . identity)))
+    (encrypt  . ((display . "Encrypt")
+                 (width   . 0)
+                 (conv    . identity)))
+    (bssid    . ((display . "Bssid")
+                 (width   . 0)
+                 (conv    . identity)))
+    (channel  . ((display . "Chnl")
+                 (width   . 0)
+                 (conv    . identity))))
+  "Alist of the details to their information.
+
+The information entries themselves are an alist, with the following keys:
+
+DISPLAY is the display name.
+WIDTH is used during display to keep track of the width of each one.
+CONV is the conversion function used during display.")
 
 (defvar enwc-last-scan nil
-  "The most recent scan results.")
+  "The most recent scan results.
+
+This will be an association list of the form:
+
+((ID . ((strength . STRENGTH) (essid . ESSID) ...)) ...)
+
+Each ID is a backend-specific network ID.
+
+Each key in the children association lists corresponds to an entry in
+`enwc-details-alist'.")
 
 (defvar enwc-access-points nil
   "The most recent access point list.")
 
 (defvar enwc-using-wired nil
-  "Whether or not wired mode is active.
+  "Non-nil means ENWC is using wired connections.
 
-This is `non-NIL' if ENWC is using wired connections.
 Note that this is NOT the same as `enwc-is-wired'.  This checks
 whether or not ENWC is in wired mode.")
 
-(defvar enwc-scan-done nil
-  "Whether or not a scan is finished.")
-
 (defvar enwc-edit-id nil
   "This is the network id of the network being edited.")
 
-(defvar enwc-scan-requested nil)
+(defvar enwc-scan-requested nil
+  "This is non-nil when a scan has been requested.
+This is used so as to avoid multiple updates of the scan data.")
+
+(defvar enwc-scan-interactive nil
+  "This is non-nil that a scan was interactively requested.
+This is only used internally.")
 
-(defvar enwc-scan-interactive nil)
+(defvar enwc-display-mode-line-timer nil
+  "The timer that updates the mode line display.")
+
+(defvar enwc-scan-timer nil
+  "The timer for automatic scanning.")
 
 (defvar enwc-mode-line-timer nil)
 
 (make-local-variable 'enwc-edit-id)
-;; The Fonts
+
+;; The Faces
 
 (defface enwc-header-face
   '((((class color) (background light))
@@ -255,359 +213,403 @@ whether or not ENWC is in wired mode.")
   "The face for the connected network."
   :group 'enwc)
 
-
-;; Small helper function.
-
-(defun enwc-detail-to-ident (detail)
-  "Converts detail DETAIL to a constant identifier."
-  (case (intern detail)
-        ((essid Ssid) "essid")
-        ((bssid HwAddress) "bssid")
-        ((quality Strength) "quality")
-        ((encryption Flags) "encryption")
-        ((mode Mode) "mode")
-        ((channel Frequency) "channel")))
+(eval-when-compile
+  (defun enwc--break-by-words (str)
+    "Break up string STR into a list of words."
+    (cl-check-type str string)
+    (split-string str "-\\|_\\| "))
+
+  (defun enwc--sym-to-str (sym &optional seps)
+    "Create a string from symbol SYM.
+SEPS is a string specifying the separator to use to combine the words,
+or \" \" if not specified."
+    (cl-check-type sym symbol)
+    (unless seps
+      (setq seps " "))
+    (cl-check-type seps string)
+    (combine-and-quote-strings (enwc--break-by-words (symbol-name sym)) seps))
+
+  (defun enwc--str-to-sym (str &optional seps)
+    "Create a symbol from the string STR.
+This will break STR into words, and then put it back together separating
+each word by SEPS, which defaults to \"-\"."
+    (cl-check-type str string)
+    (unless seps
+      (setq seps "-"))
+    (cl-check-type seps string)
+    (intern (combine-and-quote-strings (enwc--break-by-words str) seps))))
+
+(defun enwc--int-to-byte-list (n)
+  "Convert 32-bit integer N into a byte list."
+  (cl-check-type n integer)
+  (let (ret)
+    (dotimes (x 4 ret)
+      (push (logand n 255) ret)
+      (setq n (lsh n -8)))))
+
+(defun enwc--byte-list-to-int (bl)
+  "Convert byte list BL into a 32-bit integer."
+  (cl-check-type bl list)
+  (let ((ret 0))
+    (dolist (x bl ret)
+      (setq ret (logior (lsh ret 8) x)))))
+
+(defun enwc--htonl (n)
+  "Convert 32-bit integer N from hardware to network byte order."
+  (cl-check-type n integer)
+  (enwc--byte-list-to-int (nreverse (enwc--int-to-byte-list n))))
+
+(defun enwc-call-backend-function (function &optional backend &rest args)
+  "Call FUNCTION on backend BACKEND.
+FUNCTION is an ENWC function suffix string.
+If the symbol BACKEND is not specified, then it defaults to
+`enwc-current-backend'.
+ARGS are passed in to the function."
+  (unless backend
+    (setq backend enwc-current-backend))
+  (apply (intern (format "enwc-%s-%s" backend function)) args))
 
 ;;;;;;;;;;;;;;;;;;;;
-;; ENWC functions
+;; ENWC functions ;;
 ;;;;;;;;;;;;;;;;;;;;
 
-(defun enwc-do-scan ()
-  "Runs a backend scan."
-  (funcall enwc-scan-func))
-
-(defun enwc-get-nw ()
-  "Gets the identifiers for the access points
+(defun enwc-get-networks ()
+  "Get the identifiers for the access points
 from a previous scan."
-  (funcall enwc-get-nw-func))
-
-(defun enwc-get-current-nw-id ()
-  "Gets the id of the current network id,
-or `nil' if there isn't one."
-  (funcall enwc-get-current-nw-id-func enwc-using-wired))
+  (enwc-call-backend-function "get-networks" nil enwc-using-wired))
 
-(defun enwc-check-connecting-p ()
-  "Checks to see if there is a connection
-in progress.  Returns `non-NIL' if there is one,
-`NIL' otherwise."
-  (funcall enwc-check-connecting-func))
+(defun enwc-request-scan ()
+  "Request a backend scan."
+  (setq enwc-scan-requested t)
+  (enwc-call-backend-function "scan"))
 
-(defun enwc-get-wireless-nw-prop (id prop)
-  "Gets property PROP from wireless network with id
-ID and returns it."
-  (funcall enwc-get-wireless-nw-prop-func id prop))
+(defun enwc-connect (id)
+  "Connect to network with id ID.
 
-(defun enwc-get-wireless-nw-props (id)
-  (funcall enwc-get-wireless-nw-props-func id))
+ID is specific to the backend."
+  (enwc-call-backend-function "connect" nil id enwc-using-wired))
 
-(defun enwc-get-encryption-type (id)
-  "Gets the encryption type used by the wireless
-network with id ID."
-  (funcall enwc-get-encryption-type-func id))
+(defun enwc-disconnect ()
+  "Disconnect from the current network."
+  (enwc-call-backend-function "disconnect" nil enwc-using-wired))
 
-(defun enwc-get-wired-profiles ()
-  "Gets the list of wired profiles."
-  (funcall enwc-get-wired-profiles-func))
+(defun enwc-get-current-nw-id ()
+  "Get the id of the current network id,
+or nil if there isn't one.
 
-;;TODO: Add hooks to run after connecting.
-(defun enwc-wireless-connect (id)
-  "Begins a connection to wireless network with
-id ID."
-  (funcall enwc-wireless-connect-func id)
-  ;; (run-hooks 'enwc-on-connected-hook)
-  )
+The returned id is specific to the backend."
+  (enwc-call-backend-function "get-current-nw-id" nil enwc-using-wired))
 
-(defun enwc-wireless-disconnect ()
-  "Disconnects the wireless."
-  (funcall enwc-wireless-disconnect-func))
+(defun enwc-check-connecting-p ()
+  "Check to see if there is a connection in progress.
+Returns `non-nil' if there is one, nil otherwise."
+  (enwc-call-backend-function "check-connecting"))
 
-(defun enwc-wired-connect (id)
-  "Connects to the wired profile with id ID."
-  (funcall enwc-wired-connect-func id))
+(defun enwc-get-wireless-nw-props (id)
+  "Get the network properties of the wireless network with id ID.
+This will return an associative list with the keys
+corresponding to `enwc-details-alist'.
 
-(defun enwc-wired-disconnect ()
-  "Disconnects from the current network."
-  (funcall enwc-wired-disconnect-func))
+ID is specific to the backend."
+  (enwc-call-backend-function "get-wireless-nw-props" nil id))
 
 (defun enwc-is-wired-p ()
-  "Checks whether or not ENWC is connected to
-a wired network.
+  "Check whether or not ENWC is connected to a wired network.
 Note that this is NOT the same as `enwc-using-wired'.
 This checks for an active wired connection."
-  (funcall enwc-is-wired-func))
-
-(defun enwc-get-sec-types (wired)
-  "Gets the security types for network.
-WIRED is set to indicate whether or not this is
-a wired network."
-  (funcall enwc-get-sec-types-func wired))
-
-(defun enwc-get-network-ent (wired id ent)
-  "Gets network entry ENT from the network with network id ID.
-WIRED is set to indicate whether or not this is
-a wired network."
-  (if wired
-      nil
-    (enwc-get-wireless-nw-prop id ent)))
-
-(defun enwc-get-wired-nw-prop (id prop)
-  "Gets network property PROP from
- the wired network with network id ID."
-  (funcall enwc-get-wired-nw-prop-func id prop))
-
-(defun enwc-get-ip-addr (wired id)
-  "Gets the IP Address from the network with network id ID.
-WIRED is set to indicate whether or not this is
-a wired network."
-  (funcall enwc-get-ip-addr-func wired id))
-
-(defun enwc-get-netmask (wired id)
-  "Gets the Netmask from the network with network id ID.
-WIRED is set to indicate whether or not this is
-a wired network."
-  (funcall enwc-get-netmask-func wired id))
-
-(defun enwc-get-gateway (wired id)
-  "Gets the Gateway from the network with network id ID.
-WIRED is set to indicate whether or not this is
-a wired network."
-  (funcall enwc-get-gateway-func wired id))
-
-(defun enwc-get-dns (wired id)
-  "Gets the DNS Servers from the network with network id ID.
-WIRED is set to indicate whether or not this is
-a wired network."
-  (funcall enwc-get-dns-func wired id))
-
-(defun enwc-get-nw-info (wired id)
-  (funcall enwc-get-nw-info-func wired id))
-
-(defun enwc-save-nw-settings (wired id settings)
-  "Saves network settings SETTINGS to the network profile with
-network id ID.
-SETTINGS is an association list with entries for the IP Address,
-Netmask, Gateway, DNS Servers, and Security.
-WIRED is set to indicate whether or not this is
-a wired network."
-  (funcall enwc-save-nw-settings-func wired id settings))
+  (enwc-call-backend-function "is-wired"))
+
+(defun enwc-get-profile-info (id)
+  "Get the profile information for network ID.
+
+ID is specific to the backend."
+  (enwc-call-backend-function "get-profile-info" nil id enwc-using-wired))
+
+(defun enwc-save-nw-settings (id settings)
+  "Save network settings SETTINGS to the network profile with network id ID.
+SETTINGS is an association list with entries for the IP Address, Netmask,
+Gateway, DNS Servers, and Security.  WIRED is set to indicate whether or not
+this is a wired network.
+
+ID is specific to the backend."
+  (enwc-call-backend-function "save-nw-settings" nil
+                              id settings
+                              enwc-using-wired))
+
+;;;;;;;;;;;;;;;;;;;;;;
+;; Actual Functions ;;
+;;;;;;;;;;;;;;;;;;;;;;
+
+(defun enwc-is-valid-nw-id-p (id)
+  "Confirm that ID is a valid network id."
+  (and id (not (eq id 'wired))))
+
+(defun enwc-value-from-scan (detail &optional id)
+  "Retrieve a value for DETAIL from `enwc-last-scan'.
+If ID is specified, then it will get the entry for ID.
+Otherwise, ID is set to the current network ID.
+
+If DETAIL is not found in `enwc-last-scan', then return nil."
+  (unless id
+    (setq id (enwc-get-current-nw-id)))
+  (when enwc-last-scan
+    (alist-get detail (alist-get id enwc-last-scan))))
+
+(defun enwc-make-format-spec ()
+  "Create a format specification for the mode line string."
+  ;; Variables here are cached to avoid latencies when communicating with 
D-Bus.
+  (let* ((cur-id (enwc-get-current-nw-id))
+         (wiredp (enwc-is-wired-p))
+         (no-last (not enwc-last-scan))
+         (invalid-id (not (enwc-is-valid-nw-id-p cur-id)))
+         (connectingp (enwc-check-connecting-p)))
+    (format-spec-make ?s (cond
+                          (wiredp "100")
+                          ((or invalid-id no-last) "0")
+                          (connectingp "*")
+                          (t (enwc-value-from-scan 'strength cur-id)))
+                      ?e (cond
+                          (wiredp "Wired")
+                          ((or invalid-id connectingp no-last) "None")
+                          (t (enwc-value-from-scan 'essid cur-id)))
+                      ?b (cond
+                          (wiredp "Wired")
+                          ((or invalid-id connectingp no-last) "none")
+                          (t (enwc-value-from-scan 'bssid cur-id)))
+                      ?n (cond
+                          (wiredp "None")
+                          ((or invalid-id connectingp no-last) "None")
+                          (t (enwc-value-from-scan 'encrypt cur-id)))
+                      ?c (cond
+                          (wiredp "None")
+                          ((or invalid-id connectingp no-last) "None")
+                          (t (enwc-value-from-scan 'channel cur-id)))
+                      ?% "%")))
+
+(defun enwc-format-mode-line-string ()
+  "Format the mode line string.
+This is derived from `enwc-mode-line-format'.
+See the documentation for it for more details."
+  (format-spec enwc-mode-line-format (enwc-make-format-spec)))
 
-;;;;;;;;;;;;;;;;;;;;;
-;; Actual Functions
-;;;;;;;;;;;;;;;;;;;;;
+(defun enwc-update-mode-line ()
+  "Update the mode line display.
+This uses the format specified by `enwc-mode-line-format'.
+This is initiated during setup, and runs once every second."
+  (setq enwc-display-string (enwc-format-mode-line-string))
+  (force-mode-line-update))
 
-(defun enwc-is-valid-nw-id (id)
-  "Confirms that ID is a valid network id."
-  (<= 0 id))
+(defun enwc-enable-display-mode-line ()
+  "Enable the mode line display."
+  (interactive)
+  (or global-mode-string (setq global-mode-string '("")))
+  (setq enwc-display-mode-line t)
+  (unless (member 'enwc-display-string global-mode-string)
+    (setq global-mode-string (append global-mode-string 
'(enwc-display-string))))
+  (unless enwc-display-mode-line-timer
+    (setq enwc-display-mode-line-timer
+          (run-at-time t 1 'enwc-update-mode-line)))
+  (message "ENWC mode line enabled"))
+
+(defun enwc-disable-display-mode-line ()
+  "Disable the mode line display."
+  (interactive)
+  (or global-mode-string (setq global-mode-string '("")))
+  (setq enwc-display-mode-line nil)
+  (setq global-mode-string (remove 'enwc-display-string global-mode-string))
+  (when enwc-display-mode-line-timer
+    (cancel-timer enwc-display-mode-line-timer))
+  (setq enwc-display-mode-line-timer nil)
+  (message "ENWC mode line disabled"))
+
+(defun enwc-toggle-display-mode-line ()
+  "Toggles the mode line display."
+  (interactive)
+  (if (not enwc-display-mode-line)
+      (enwc-enable-display-mode-line)
+    (enwc-disable-display-mode-line)))
 
-(defun enwc-get-nw-prop (wired id prop)
-  "Small function to get network property PROP from the network
-with network id ID.
-WIRED indicates whether or not this is a wired connection."
-  (if wired
-      (enwc-get-wired-nw-prop id prop)
-    (enwc-get-wireless-nw-prop id prop)))
+(defun enwc-enable-auto-scan ()
+  "Enable auto scanning."
+  (interactive)
+  (unless enwc-scan-timer
+    (setq enwc-scan-timer
+          (run-at-time t enwc-auto-scan-interval 'enwc-scan t)))
+  (setq enwc-auto-scan t)
+  (message "Auto-scan enabled"))
+
+(defun enwc-disable-auto-scan ()
+  "Disable auto scanning."
+  (interactive)
+  (when enwc-scan-timer (cancel-timer enwc-scan-timer))
+  (setq enwc-auto-scan nil)
+  (message "Auto scan disabled"))
 
-(defun enwc-update-mode-line ()
-  "Updates the mode line with the current network strength.
-If no network is connected, then prints 0%.
-If wired is active, then prints 100%.
-If ENWC is in the process of connecting, then prints *%.
-This is initiated during setup, and runs once every second."
-  (let ((cur-id (enwc-get-current-nw-id))
-       (conn (enwc-check-connecting-p))
-       str)
-    (setq str
-         (if (enwc-is-wired-p)
-             100
-           (if (and
-                (enwc-is-valid-nw-id cur-id)
-                enwc-last-scan)
-               (cdr (assoc "quality" (nth cur-id enwc-last-scan)))
-             0)))
-    (setq enwc-display-string (concat " ["
-                                     (if conn
-                                         "*"
-                                       (number-to-string str))
-                                     "%] "))))
-
-;;;;;;;;;;;;;;;;;;
-;; Scan internal
-;;;;;;;;;;;;;;;;;;
+(defun enwc-toggle-auto-scan ()
+  "Toggles automatic scanning.
+This will use the current value of `enwc-auto-scan-interval'."
+  (interactive)
+  (if enwc-auto-scan
+      (enwc-disable-auto-scan)
+    (enwc-enable-auto-scan)))
+
+;;;;;;;;;;;;;;;;;;;
+;; Scan internal ;;
+;;;;;;;;;;;;;;;;;;;
+
+(defun enwc-scan (&optional nodisp)
+  "The frontend of the scanning routine.
+Set up and move to the ENWC buffer if necessary, and scan and display the
+ networks.  If NODISP is `non-nil', then do not display the results in the ENWC
+buffer."
+  (interactive)
+  (unless nodisp
+    (setq enwc-scan-interactive t))
+  (when (get-buffer "*ENWC*")
+    (with-current-buffer "*ENWC*"
+      (enwc-scan-internal))))
 
 (defun enwc-scan-internal-wireless ()
-  "The initial scan routine.
-This initiates a scan using D-Bus, then exits,
-waiting for the callback."
-  (message "Scanning...")
-  (setq enwc-scan-requested t)
-  (setq enwc-scan-done nil)
-  (enwc-do-scan))
+  "The initial scan routine for wireless networks.
+This initiates a scan using D-Bus, then exits, waiting for the callback.
 
-(defun enwc-process-scan (&rest args)
-  "The scanning callback.
-After a scan has been performed, this processes and displays
-the scan results."
-  (if (or enwc-using-wired (not enwc-scan-requested))
-      nil
-    (setq enwc-scan-requested nil)
-    (let ((cur-id 0)
-         (nw-prop-list nil))
-      (message "Scanning... Done")
-      (setq enwc-access-points (enwc-get-nw)
-           enwc-essid-width 5)
-      (setq nw-prop-list
-           (mapcar 'enwc-get-wireless-nw-props
-                   (number-sequence 0 (1- (length enwc-access-points)))))
-      (setq enwc-last-scan
-           (mapcar (lambda (x)
-                     (let ((ret-itm (cons (cons "id" cur-id) nil))
-                           (prop-list (pop nw-prop-list)))
-                       (setq cur-id (1+ cur-id))
-                       (dolist (det enwc-details-list)
-                         (let ((cur-item (cdr (assoc det prop-list)))
-                               (ident (enwc-detail-to-ident det))
-                               pos-len)
-                           (if (string= ident "essid")
-                               (progn
-                                 (setq pos-len (length cur-item))
-                                 (setq enwc-essid-width
-                                       (max enwc-essid-width
-                                            pos-len))))
-                           (if (string= ident "encryption")
-                               (setq cur-item
-                                     (if cur-item
-                                         (enwc-get-encryption-type x)
-                                       "Unsecured")))
-                           (setq ret-itm (append ret-itm
-                                                 (cons (cons ident
-                                                             cur-item)
-                                                       nil)))))
-                       ret-itm))
-                   (number-sequence 0 (1- (length enwc-access-points))))))
-    (setq enwc-essid-width (1+ enwc-essid-width))
-    (setq enwc-scan-done t)
-    (if enwc-scan-interactive
-        (enwc-display-wireless-networks enwc-last-scan))))
+All back-ends must call `enwc-process-scan' in some way upon completion of a
+ scan."
+  (when enwc-scan-interactive
+    (message "Scanning..."))
+  (enwc-request-scan))
 
 (defun enwc-scan-internal-wired ()
   "The scanning routine for a wired connection.
 This gets the list of wired network profiles."
   (message "Updating Profiles...")
-  (let ((profs (enwc-get-wired-profiles))
-       cur-prof fin-profs)
-    (while profs
-      (setq cur-prof (pop profs))
-      (if cur-prof
-         (setq fin-profs (cons cur-prof
-                               fin-profs))))
+  (let ((profs (enwc-get-networks)))
     (message "Updating Profiles... Done")
-    (setq enwc-access-points fin-profs)
-    (setq enwc-last-scan fin-profs)
-    fin-profs))
+    (setq enwc-access-points profs
+          enwc-last-scan     profs)
+    (enwc-display-wired-networks profs)))
 
 (defun enwc-scan-internal ()
   "The entry point for the internal scan routines.
-This checks whether or not wired is being used,
- and runs the appropriate function."
+This checks whether or not wired is being used, and runs the appropriate
+ function."
   (if enwc-using-wired
       (enwc-scan-internal-wired)
     (enwc-scan-internal-wireless)))
 
-;;;;;;;;;;;;;;;;;;;;;
-;; Display Networks
-;;;;;;;;;;;;;;;;;;;;;
+(defun enwc-process-scan (&rest args)
+  "The scanning callback.
+After a scan has been performed, this processes and displays the scan results.
+
+ARGS is only for compatibility with the calling function."
+  (unless (or enwc-using-wired (not enwc-scan-requested))
+    (setq enwc-scan-requested nil
+          enwc-access-points  (enwc-get-networks))
+    (when enwc-scan-interactive
+      (message "Scanning... Done"))
+    (setq enwc-last-scan (mapcar
+                          (lambda (ap)
+                            `(,ap . ,(enwc-get-wireless-nw-props ap)))
+                          enwc-access-points))
+    (enwc-display-wireless-networks enwc-last-scan)
+    (setq enwc-scan-interactive nil)))
+
+;;;;;;;;;;;;;;;;;;;;;;
+;; Display Networks ;;
+;;;;;;;;;;;;;;;;;;;;;;
+
+(defun enwc-update-width (detail &optional val)
+  "Update the width for column DETAIL to VAL.
+This modifies the width entry in `enwc-details-alist' that corresponds to
+DETAIL.
+
+If VAL is not specified, then use the width of the display name for DETAIL."
+  (let ((det (alist-get detail enwc-details-alist)))
+    (unless val
+      (setq val (1+ (length (alist-get 'display det)))))
+    (setq val (max val (alist-get 'width det)))
+    (setcdr (assq 'width det) val)))
+
+(defun enwc-reset-widths ()
+  "Reset the column widths for display."
+  (dolist (det enwc-details-alist)
+    (enwc-update-width (car det))))
+
+(defun enwc-refresh-widths (&optional networks)
+  "Refresh the column widths for display."
+  (unless networks
+    (setq networks enwc-last-scan))
+  (enwc-reset-widths)
+  (dolist (nw networks)
+    (dolist (props (cdr nw))
+      (enwc-update-width (car props) (length (prin1-to-string (cdr props)))))))
 
 (defun enwc-display-wired-networks (networks)
-  "Displays the wired networks specified in the list NETWORKS.
+  "Display the wired networks specified in the list NETWORKS.
 NETWORKS must be in the form returned from
 `enwc-scan-internal-wired'."
-  (if (not (listp networks))
-      (error "NETWORKS must be a list of networks."))
+  (unless (listp networks)
+    (error "NETWORKS must be a list of networks."))
   (let ((inhibit-read-only t))
-    (erase-buffer)
-    (insert (propertize "Profile" 'face 'enwc-header-face))
-    (insert "\n")
-    (dolist (pr networks)
-      (insert pr)
-      (insert "\n"))))
-
-(defun enwc-insert-ent (ent width)
-  "Small function to insert a network property entry.
-ENT is the entry, and WIDTH is the column width."
-  (insert ent)
-  (insert-char 32 (- width (length ent))))
+    (setq tabulated-list-format (vector '("Profile" . 1)))
+    ;;TODO: actually get names of profiles, if possible.
+    (setq tabulated-list-entries (mapcar (lambda (prop) (cons prop prop)) 
networks))
+    (tabulated-list-init-header)
+    (tabulated-list-print)))
 
-(defun enwc-display-wireless-networks (networks)
-  "Displays the networks in the list NETWORKS in the current buffer.
-NETWORKS must be in the format returned by
-`enwc-scan-internal-wireless'."
-  (if (not (eq major-mode 'enwc-mode))
-      (enwc-setup-buffer))
-  (if (not (listp networks))
-      (error "NETWORKS must be a list of association lists."))
-  (let ((cur-id (enwc-get-current-nw-id))
-       entries)
-    (let ((header enwc-wireless-headers)
-         (pos 0))
+(defmacro enwc--propertize-entry (network-entry)
+  "Propertize network entry NETWORK-ENTRY."
+  `(mapcar
+    (lambda (det)
+      (let* ((conv     (alist-get 'conv (cdr det)))
+             (ent      (alist-get (car det) (cdr ,network-entry)))
+             (conv-ent (funcall conv ent)))
+        (if (equal cur-id (car nw))
+            (propertize conv-ent
+                        'font-lock-face
+                        'enwc-connected-face)
+          conv-ent)))
+    enwc-details-alist))
 
+(defun enwc-display-wireless-networks (networks)
+  "Display the networks in the list NETWORKS in the current buffer."
+  (unless (get-buffer "*ENWC*")
+    (enwc-setup-buffer t))
+  (cl-check-type networks list)
+  ;; Update the display widths.
+  (enwc-refresh-widths)
+  (with-current-buffer (get-buffer "*ENWC*")
+    (let ((cur-id (enwc-get-current-nw-id)))
       (setq tabulated-list-format
-           (vector '("ID" 2)
-                   '("STR" 4)
-                   `("ESSID" ,enwc-essid-width)
-                   '("ENCRYPT" 9)
-                   '("BSSID" 17)
-                   '("MODE" 15)
-                   '("CHNL" 2))))
-
-    ;;TODO: Setup faces.
-    (dolist (nw networks)
-      (let ((id (cdr (assoc "id" nw)))
-           entry)
-       (setq entry (list nil
-                         (vector
-                          (number-to-string (cdr (assoc "id" nw)))
-                           (concat (number-to-string (cdr (assoc "quality" 
nw)))
-                                  "%")
-                           (cdr (assoc "essid" nw))
-                          (cdr (assoc "encryption" nw))
-                          (cdr (assoc "bssid" nw))
-                          (cdr (assoc "mode" nw))
-                          (cdr (assoc "channel" nw)))))
-       (setq entries (cons entry entries))))
-
-    (setq tabulated-list-entries (nreverse entries))
+            (apply 'vector
+                   (mapcar
+                    (lambda (det)
+                      `(,(alist-get 'display (cdr det))
+                        ,(alist-get 'width   (cdr det))
+                        t))
+                    enwc-details-alist)))
+
+      (setq tabulated-list-entries
+            (mapcar
+             (lambda (nw)
+               `(,(car nw)
+                 ,(apply 'vector (enwc--propertize-entry nw))))
+             networks)))
     (tabulated-list-init-header)
 
     (tabulated-list-print)))
 
 (defun enwc-display-networks (networks)
-  "Displays the network in NETWORKS.  This is an entry to the display
-functions, and checks whether or not ENWC is using wired."
-  (if (not (eq major-mode 'enwc-mode))
-      (enwc-setup-buffer))
-  (if (not (listp networks))
-      (error "NETWORKS must be a list."))
+  "Displays the network in NETWORKS.
+This is an entry to the display functions, and checks whether or not ENWC is
+ using wired."
+  (unless (eq major-mode 'enwc-mode)
+    (enwc-setup-buffer))
+  (cl-check-type networks list)
   (if enwc-using-wired
       (enwc-display-wired-networks networks)
     (enwc-display-wireless-networks networks)))
 
-;;;###autoload
-(defun enwc-scan ()
-  "The frontend of the scanning routine.  Sets up and moves to
-the ENWC buffer if necessary, and scans and displays the networks."
-  (interactive)
-  (setq enwc-scan-interactive t)
-  (if (get-buffer "*ENWC*")
-      (with-current-buffer "*ENWC*"
-       (if enwc-using-wired
-           (progn
-             (enwc-scan-internal)
-             ;;(enwc-display-networks enwc-last-scan)
-             (goto-char 0)
-             (forward-line))
-         (enwc-scan-internal)))))
-
-;;;###autoload
 (defun enwc-find-network (essid &optional networks)
   "Checks through NETWORKS for the network with essid ESSID,
 and returns the network identifier.  Uses `enwc-last-scan' if
@@ -616,94 +618,78 @@ NETWORKS is nil.  If the network is not found, then it 
returns nil.
    When called interactively, this only prints out what it finds.
 Otherwise, it actually returns it."
   (interactive "sNetwork ESSID: ")
-  (if (not (or networks enwc-last-scan))
-      (progn
-       (setq enwc-scan-interactive nil)
-       (enwc-scan-internal)))
+  (unless (or networks enwc-last-scan)
+    (setq enwc-scan-interactive nil)
+    (enwc-scan-internal))
   (let ((nets (or networks enwc-last-scan))
-       need-break cur-net)
-    (if (not nets)
-       (setq nets enwc-last-scan))
-    (while (and nets (not need-break))
-      (let (cur-essid)
-       (setq cur-net (pop nets))
-       (setq cur-essid (cdr (assoc "essid" cur-net)))
-       (if (string= cur-essid essid)
-           (setq need-break t))))
-    (if need-break
-       (if (called-interactively-p 'any)
-           (message (number-to-string (cdr (assoc "id" cur-net))))
-         (cdr (assoc "id" cur-net)))
-      (if (called-interactively-p 'any)
-         (message "Network not found.")
-       nil))))
+        need-break cur-net)
+    (while (and nets (not cur-net))
+      (setq cur-net (pop nets))
+      (unless (string-equal (alist-get 'essid (cdr-safe cur-net))
+                            essid)
+        (setq cur-net nil)))
+    (if cur-net
+        (if (called-interactively-p 'any)
+            (message "Network %d has essid %s" (number-to-string (car 
cur-net)) essid)
+          (car cur-net))
+      (when (called-interactively-p 'any)
+        (message "Network not found.")))))
 
-;;;;;;;;;;;;;;;;;;;;
-;; Connect Network
-;;;;;;;;;;;;;;;;;;;;
+;;;;;;;;;;;;;;;;;;;;;
+;; Connect Network ;;
+;;;;;;;;;;;;;;;;;;;;;
 
 (defun enwc-connect-network (id)
   "Connect to network with id ID.
 This is an entry point for the internal connection functions,
 and checks whether or not ENWC is using wired."
-  (let (cur-net)
-    (if enwc-using-wired
-       (progn
-         (enwc-wired-connect id)
-         (setq cur-net (nth id (enwc-get-wired-profiles))))
-      (enwc-wireless-connect id)
-      (if enwc-last-scan
-         (setq cur-net (cdr (assoc "essid" (nth id enwc-last-scan)))))
-      cur-net)))
+  (enwc-connect id)
+  (if enwc-using-wired
+      id
+    (when enwc-last-scan
+      (enwc-value-from-scan 'essid id))))
 
-;;;###autoload
 (defun enwc-connect-to-network (net-id)
-  "Connects the the network with network id NET-ID.
+  "Connect the the network with network id NET-ID.
 Confirms that NET-ID is a valid network id.
 This calls `enwc-connect-network' as a subroutine."
-  (interactive "nNetwork ID: ")
-  (if (not (numberp net-id))
-      (error "NET-ID must be a number"))
-  (let ((num-ids (length enwc-last-scan))
-       cur-net)
-    (if (or (< net-id 0) (>= net-id num-ids))
-       (error "Invalid network id."))
+  (interactive "sNetwork ID: ")
+  (let (cur-net)
+    (unless (enwc-is-valid-nw-id-p net-id)
+      (error "Invalid network id."))
     (setq cur-net (enwc-connect-network net-id))
-    (message (concat "Connecting to " cur-net))))
+    (message "Connecting to %s" cur-net)))
 
-;;;###autoload
 (defun enwc-connect-to-network-essid (essid)
-  "Connects to the network with essid ESSID."
+  "Connect to the network with essid ESSID."
   (interactive "sNetwork ESSID: ")
   (let ((net-id (enwc-find-network essid)))
     (if net-id
-       (enwc-connect-to-network net-id)
+        (enwc-connect-to-network net-id)
       (message "Network not found."))))
 
 (defun enwc-connect-to-network-at-point ()
-  "Connects to the network at the current line number.
+  "Connect to the network at the current line number.
 Moves to the enwc buffer if necessary."
   (interactive)
-  (if (not (eq major-mode 'enwc-mode))
-      (enwc-setup-buffer))
-  (let ((id (- (line-number-at-pos) 1)))
-    (enwc-connect-to-network id)))
+  (unless (eq major-mode 'enwc-mode)
+    (enwc-setup-buffer))
+  ;;TODO: Fix this for wired (which doesn't have tabulated list)
+  (enwc-connect-to-network (tabulated-list-get-id)))
 
-(defun enwc-disconnect ()
-  "Disconnects from the network, if any."
+(defun enwc-disconnect-network ()
+  "Disconnect from the network, if any."
   (interactive)
-  (if (not (eq major-mode 'enwc-mode))
-      (enwc-setup-buffer))
-  (if enwc-using-wired
-      (enwc-wired-disconnect)
-    (enwc-wireless-disconnect)))
+  (message "Disconnecting")
+  (enwc-disconnect))
 
 (defun enwc-toggle-wired ()
   "Toggle the display and mode between wireless and wired.
-This function also sets the variable `enwc-using-wired'."
+This has the side-effect of setting the variable `enwc-using-wired', and 
calling
+a scan."
   (interactive)
-  (if (not (eq major-mode 'enwc-mode))
-      (enwc-setup-buffer))
+  (unless (eq major-mode 'enwc-mode)
+    (enwc-setup-buffer))
   (let ((inhibit-read-only t))
     (erase-buffer)
     (setq enwc-using-wired (not enwc-using-wired))
@@ -721,6 +707,10 @@ In order to use this, one must have already run
   (enwc-setup-buffer)
   (enwc-scan))
 
+;;;;;;;;;;;;;;;;;;;;;;;;
+;; Profile Properties ;;
+;;;;;;;;;;;;;;;;;;;;;;;;
+
 ;; Settings for access point AP
 ;;
 ;; IPv4 Settings:
@@ -739,188 +729,323 @@ In order to use this, one must have already run
   "View the text of the entry at point.
 This is mostly useful to view the text of the hidden entries."
   (interactive)
-  (if (not (get-buffer "*ENWC Edit*"))
-      (error "Not editing a network entry."))
-  (if (not (eq (current-buffer) (get-buffer "*ENWC Edit*")))
-      (switch-to-buffer "*ENWC Edit*"))
-  (if (not (widget-at))
-      (error "No widget at point"))
+  (unless (get-buffer "*ENWC Edit*")
+    (error "Not editing a network entry."))
+  (unless (eq (current-buffer) (get-buffer "*ENWC Edit*"))
+    (switch-to-buffer "*ENWC Edit*"))
+  (unless (widget-at)
+    (error "No widget at point"))
   (message (widget-field-value-get (widget-at))))
 
-(defun enwc-display-sec-reqs (widget &rest stuff)
-  "Display the security requirements.
-This is a callback to the security selection widget.
-WIDGET is always the menu drop-down of security types."
-  (let (reqs
-       (inhibit-read-only t)
-       type-wid-list)
-    ;; First, erase any of the old ones.
-    (goto-char (1+ (widget-get widget :to)))
-    (widget-forward 1)
-    (while (>= (point) (widget-get widget :to))
-      (widget-delete (widget-at))
-      (widget-forward 1))
-    (goto-char (point-max))
-    ;; Then check to see if widget-value is None
-    (if (string= (widget-value widget) "None")
-       nil
-      (setq type-wid-list
-           (cadr (assoc "reqs"
-                        (cdr (assoc (widget-value widget)
-                                    (enwc-get-sec-types enwc-using-wired))))))
-      (setq reqs
-           (mapcar (lambda (x)
-                     (if (not (eq (length (cdr x)) 0))
-                         (widget-create 'editable-field
-                                        :format (concat "  "
-                                                        (cdr x)
-                                                        ": %v")
-                                        :secret ?*
-                                        :keymap 'enwc-edit-field-map
-                                        :value (or (enwc-get-nw-prop 
enwc-using-wired
-                                                                     
enwc-edit-id
-                                                                     (car x))
-                                                   ""))))
-                   type-wid-list))
-      (widget-setup)
-      reqs)))
+(define-widget 'enwc-profile-props-widget 'group
+  "ENWC edit widget."
+  :convert-widget 'identity
+  :format "IPv4 Settings:\n %v"
+  :value-to-internal 'enwc-profile-props-to-widget
+  :value-to-external 'enwc-widget-to-profile-props
+  :match #'(lambda nil t)
+  :indent 1
+  :args '((string :tag "Address")
+          (string :tag "Netmask")
+          (string :tag "Gateway")
+          (string :tag "DNS1")
+          (string :tag "DNS2")))
+
+(defun enwc-profile-props-to-widget (widget props)
+  "Create a profile props widget."
+  (list
+   (alist-get 'addr props "")
+   (alist-get 'netmask props "")
+   (alist-get 'gateway props "")
+   (alist-get 'dns1 props "")
+   (alist-get 'dns2 props "")))
+
+(defun enwc-widget-to-profile-props (widget vals)
+  "Convert widget values to a profile properties alist.
+WIDGET is unused.
+VALS is the list of widget values."
+  (let ((addr (nth 0 vals))
+        (netmask (nth 1 vals))
+        (gateway (nth 2 vals))
+        (dns1 (nth 3 vals))
+        (dns2 (nth 4 vals)))
+    `((addr . ,addr)
+      (netmask . ,netmask)
+      (gateway . ,gateway)
+      (dns1 . ,dns1)
+      (dns2 . ,dns2))))
+
+;;;;;;;;;;;;;;
+;; Security ;;
+;;;;;;;;;;;;;;
+
+(eval-when-compile
+  (defmacro enwc--make-supplicant-multi (key &rest args)
+    `(cons (quote ,key)
+           (quote (checklist :tag ,(capitalize (enwc--sym-to-str key))
+                             :format "%{%t%}: %v"
+                             :sample-face bold
+                             :indent ,(+ 4 (length (enwc--sym-to-str key)))
+                             :args ,(mapcar
+                                     (lambda (arg)
+                                       `(item :tag ,(upcase arg) :value 
,(downcase arg)))
+                                     args)))))
+
+  (defmacro enwc--make-supplicant-choice (key &rest args)
+    `(cons (quote ,key)
+           (quote (menu-choice :tag ,(capitalize (enwc--sym-to-str key))
+                               :format "%[%t%]: %v"
+                               :sample-face bold
+                               :args
+                               ,(mapcar
+                                 (lambda (arg)
+                                   `(item :tag ,(upcase arg) :value (downcase 
,arg)))
+                                 args)))))
+
+  (defmacro enwc--make-supplicant-secret (key)
+    `(cons (quote ,key)
+           (quote (editable-field :tag ,(capitalize (enwc--sym-to-str key))
+                                  :format "%{%t%}: %v"
+                                  :sample-face bold
+                                  :keymap enwc-edit-field-map
+                                  :secret ?*))))
+
+  (defmacro enwc--make-supplicant-entry (key)
+    `(cons (quote ,key)
+           (quote (editable-field :tag ,(capitalize (enwc--sym-to-str key))
+                                  :sample-face bold
+                                  :format "%{%t%}: %v"))))
+
+  (defmacro enwc--make-supplicant-file (key)
+    `(cons (quote ,key)
+           (quote (file :tag ,(capitalize (enwc--sym-to-str key))
+                        :format "%{%t%}: %v"
+                        :sample-face bold
+                        :must-match t))))
+
+  (defmacro enwc--make-supplicant-list (key &rest args)
+    `(cons (quote ,key)
+           (quote (list :tag ,(capitalize (enwc--sym-to-str key))
+                        :format "%{%t%}: %v"
+                        :sample-face bold
+                        :indent ,(length (enwc--sym-to-str key))
+                        :args ,(mapcar (lambda (x) (cdr (eval x))) args))))))
+
+(defconst enwc-supplicant-alist
+  (list
+   (enwc--make-supplicant-multi proto "WPA" "RSN")
+   (enwc--make-supplicant-multi key-mgmt "None" "WPA-PSK" "WPA-EAP" 
"IEEE8021X")
+   (enwc--make-supplicant-choice auth-alg "OPEN" "SHARED" "LEAP")
+   (enwc--make-supplicant-multi pairwise "CCMP" "TKIP" "NONE")
+   (enwc--make-supplicant-multi group "CCMP" "TKIP" "WEP104" "WEP40")
+   (enwc--make-supplicant-secret psk)
+   (enwc--make-supplicant-secret wep-key0)
+   (enwc--make-supplicant-secret wep-key1)
+   (enwc--make-supplicant-secret wep-key2)
+   (enwc--make-supplicant-secret wep-key3)
+   (enwc--make-supplicant-choice wep-tx-keyidx "0" "1" "2" "3")
+   (enwc--make-supplicant-choice eap "TLS" "PEAP" "TTLS" "LEAP" "FAST")
+   (enwc--make-supplicant-entry identity)
+   (enwc--make-supplicant-entry anonymous-identity)
+   (enwc--make-supplicant-secret password)
+   (enwc--make-supplicant-file ca-cert)
+   (enwc--make-supplicant-file client-cert)
+   (enwc--make-supplicant-file private-key)
+   (enwc--make-supplicant-secret private-key-passwd)
+   (enwc--make-supplicant-file pac-file)
+   (enwc--make-supplicant-list phase1
+                               (enwc--make-supplicant-choice peapver "" "0" 
"1")
+                               (enwc--make-supplicant-choice peaplabel "" "0" 
"1")
+                               (enwc--make-supplicant-choice fast-provisioning 
"" "0" "1" "2" "3"))
+   (enwc--make-supplicant-list phase2
+                               (enwc--make-supplicant-choice auth "" "MD5" 
"MSCHAPV2" "OTP" "GTC" "TLS")
+                               (enwc--make-supplicant-choice autheap "" "MD5" 
"MSCHAPV2" "OTP" "GTC" "TLS")
+                               (enwc--make-supplicant-file ca-cert)
+                               (enwc--make-supplicant-file client-cert)
+                               (enwc--make-supplicant-file private-key)
+                               (enwc--make-supplicant-secret 
private-key-passwd)))
+  "An alist that maps supplicant entries to a widget type.
+
+For more information, see the documentation for wpa_supplicant.")
+
+(defcustom enwc-supplicant-template-alist
+  `((wep . ((key-mgmt . ("none"))
+            (wep-key0 . req)
+            (wep-tx-keyidx . "0")))
+    (wpa2 . ((proto . ("wpa" "rsn"))
+             (key-mgmt . ("wpa-psk"))
+             (pairwise . ("ccmp" "tkip"))
+             (group . ("ccmp" "tkip"))
+             (psk . req)))
+    (leap . ((eap . "leap")
+             (key-mgmt . ("ieee8021x"))
+             (auth-alg . "leap")
+             (identity . req)
+             (password . req)))
+    (eap-fast . ((proto . ("rsn" "wpa"))
+                 (pairwise . ("ccmp" "tkip"))
+                 (group . ("ccmp" "tkip"))
+                 (key-mgmt . ("wpa-eap"))
+                 (eap . "fast")
+                 (identity . req)
+                 (password . req)
+                 (phase1 . ((fast-provisioning . "1")))
+                 (pac-file . opt)))
+    (eap-tls . ((key-mgmt . ("wpa-eap"))
+                (pairwise . ("tkip"))
+                (group . ("tkip"))
+                (eap . "tls")
+                (identity . req)
+                (ca-cert . opt)
+                (client-cert . opt)
+                (private-key . req)
+                (private-key-passwd . req)))
+    (peap . ((proto . ("rsn"))
+             (key-mgmt . ("wpa-eap"))
+             (pairwise . ("ccmp"))
+             (eap . "peap")
+             (identity . req)
+             (password . req)))
+    (peap-tkip . ((proto . ("wpa"))
+                  (key-mgmt . ("wpa-eap"))
+                  (pairwise . ("tkip"))
+                  (group . ("tkip"))
+                  (eap . "peap")
+                  (identity . req)
+                  (password . req)
+                  (ca-cert . opt)
+                  (phase1 . ((peaplabel . "0")))
+                  (phase2 . ((auth . "mschapv2"))))))
+  "The alist of templates for security.
+This should be an alist of the form (KEY . ((SUPPLICANT-KEY . INITIAL-INPUT) 
...))
+Each SUPPLICANT-KEY should be a key from `enwc-supplicant-alist', and 
INITIAL-INPUT
+should be an acceptable value for SUPPLICANT-KEY.
+
+If INITIAL-INPUT is the symbol req, then this option is required.
+The value opt means that the option is optional."
+  :group 'enwc
+  :type '(alist :key-type symbol :value-type (alist :key-type symbol)))
+
+(defun enwc--get-supplicant-entry (ent &optional sec-info)
+  "Create a widget definition from ENT.
+
+If optional parameter SEC-INFO is non-nil, then use it
+for security information."
+  (let ((init (cdr ent))
+        (wid (assq (car ent) enwc-supplicant-alist))
+        fin)
+    (unless wid
+      (error "Unknown supplicant type %s" (car ent)))
+    ;; Set the initial value for the widget.
+    (when (eq (cadr wid) 'list)
+      (let (act-init)
+        (dolist (arg (widget-get (cdr wid) :args))
+          (push (alist-get (enwc--str-to-sym (downcase (widget-get arg :tag))) 
init "")
+                act-init))
+        (setq init (nreverse act-init))))
+    (cons (cadr wid)
+          (append (pcase init
+                  (`req `(:required t :value ,(alist-get (car ent) sec-info 
"")))
+                  (`opt `(:value ,(alist-get (car ent) sec-info "")))
+                  (_ `(:value ,init)))
+                (cddr wid)))))
+
+(defun enwc-create-template-menu (&optional sec-info)
+  "Create the widget declaration for the menu of templates.
+
+If specified, SEC-INFO is passed to the templates to initialize them."
+  `(menu-choice
+    :tag "Security"
+    :indent 2
+    ,@(mapcar
+       (lambda (tm)
+         `(list
+           :tag ,(symbol-name (car tm))
+           :menu-tag ,(symbol-name (car tm))
+           ,@(mapcar
+              (lambda (ent)
+                (enwc--get-supplicant-entry ent sec-info))
+              (cdr tm))))
+       enwc-supplicant-template-alist)))
+
+(defun enwc-display-sec-widget (&optional sec-info)
+  "Create the menu of security templates.
+If specified, SEC-INFO is passed to the templates to initialize them."
+  (widget-create (enwc-create-template-menu sec-info)))
+
+(defun enwc-sec-widget-data (widget)
+  "Get the data from a security widget WIDGET."
+  (let* ((type (widget-get (widget-get widget :choice) :tag))
+         (values (widget-value widget))
+         (template (assq (intern type) enwc-supplicant-template-alist)))
+    (unless template
+      (error "Unrecognized security template \"%s\"." type))
+    (setq template (cdr template))
+    (cons
+     `(sec-type . ,(intern type))
+     (cl-mapcar
+      (lambda (val v)
+        (let ((vl v))
+          (when (or (eq (car val) 'phase1)
+                    (eq (car val) 'phase2))
+            (let ((subs
+                   (mapcar
+                    (lambda (arg)
+                      (enwc--str-to-sym (downcase (widget-get arg :tag))))
+                    (widget-get (alist-get (car val) enwc-supplicant-alist) 
:args))))
+              (setq vl (cl-mapcar 'cons subs v))))
+          (print vl)
+          (cons (car val) vl)))
+      template values))))
+
+(defvar enwc-network-edit-widget nil
+  "The network information widget used in the edit buffer.")
+
+(defvar enwc-security-edit-widget nil
+  "The security widget used in the edit buffer.")
 
 (defun enwc-setup-edit-buffer ()
   "Setup the edit buffer.  This removes the old one if neccessary,
 and redisplays the settings from the network profile
  with id `enwc-edit-id', which is set in `enwc-edit-entry-at-point'."
-  (if (get-buffer "*ENWC Edit*")
-      (kill-buffer "*ENWC Edit*"))
+  (when (get-buffer "*ENWC Edit*")
+    (kill-buffer "*ENWC Edit*"))
   (with-current-buffer (get-buffer-create "*ENWC Edit*")
-    (let ((sec-types (enwc-get-sec-types enwc-using-wired))
-         (nw-info (enwc-get-nw-info enwc-using-wired enwc-edit-id))
-         ip-addr netmask gateway dns-1 dns-2
-         addr-wid net-wid gate-wid
-         dns-1-wid dns-2-wid dns-list
-         type-wid type-wid-list)
+    (let ((nw-info (enwc-get-profile-info enwc-edit-id)))
 
       (widget-insert (concat "Settings for access point "
-                            (cdr (assoc "essid"
-                                        (nth enwc-edit-id
-                                             enwc-last-scan)))
-                            "\n"))
-      (widget-insert "\n")
-      ;; ip
-      (widget-insert "IPv4 Settings:\n")
-      (setq addr-wid (widget-create 'editable-field
-                                   :format "  Address: %v"
-                                   :value (or (assoc "addr" nw-info) "")))
-      ;; netmask
-      (setq net-wid (widget-create 'editable-field
-                                  :format "  Netmask: %v"
-                                  :value (or (assoc "netmask" nw-info) "")))
-
-      ;; gateway
-      (setq gate-wid (widget-create 'editable-field
-                                   :format "  Gateway: %v"
-                                   :value (or (assoc "gateway" nw-info) "")))
-      ;; dns1
+                             (enwc-value-from-scan 'essid enwc-edit-id)
+                             "\n"))
       (widget-insert "\n")
-      ;;(setq dns-list (enwc-get-dns enwc-using-wired enwc-edit-id))
-      (setq dns-1-wid (widget-create 'editable-field
-                                    :format "    DNS 1: %v"
-                                    :value (or (assoc "dns1" nw-info) "")))
-
-      ;; dns2
-      (setq dns-2-wid (widget-create 'editable-field
-                                    :format "    DNS 2: %v"
-                                    :value (or (assoc "dns2" nw-info) "")))
+      (setq enwc-network-edit-widget
+            (widget-create 'enwc-profile-props-widget :value nw-info))
 
       (widget-insert "\n")
-      (widget-insert "Security:\n")
-      (setq type-wid (apply 'widget-create
-                           'menu-choice
-                                   :tag "Type "
-                           :value (or (assoc "enctype" nw-info) "None")
-                           :notify 'enwc-display-sec-reqs
-                                   '(item :tag "No Encryption"
-                                  :value "None")
-                           (mapcar (lambda (x)
-                                     `(item :format "%t\n"
-                                            :value ,(car x)
-                                            :tag ,(cdr (assoc "Name" (cdr 
x)))))
-                                           sec-types)))
-      (enwc-display-sec-reqs type-wid)
+      (setq enwc-security-edit-widget (enwc-display-sec-widget nw-info))
+
       (use-local-map enwc-edit-map)
       (widget-setup)))
 
   (switch-to-buffer "*ENWC Edit*"))
 
 (defun enwc-edit-save ()
-  "Save the network settings."
-  ;; Basically, just iterate through the widgets,
-  ;; retrieving values from each.
+  "Save the network settings from the edit buffer."
   (interactive)
-  (if (not (get-buffer "*ENWC Edit*"))
-      (error "Not editing a network entry."))
-  (if (not (eq (current-buffer) (get-buffer "*ENWC Edit*")))
-      (switch-to-buffer "*ENWC Edit*"))
-  (goto-char 0)
-  (let (settings start-pos type-wid-list)
-
-    (widget-forward 1)
-    (setq settings
-         (append settings
-                 (cons (cons "addr"
-                             (widget-field-value-get (widget-at)))
-                       nil)))
-    (widget-forward 1)
-    (setq settings
-         (append settings
-                 (cons (cons "netmask"
-                             (widget-field-value-get (widget-at)))
-                       nil)))
-    (widget-forward 1)
-    (setq settings
-         (append settings
-                 (cons (cons "gateway"
-                             (widget-field-value-get (widget-at)))
-                       nil)))
-    (widget-forward 1)
-    (setq settings
-         (append settings
-                 (cons (cons "dns1"
-                             (widget-field-value-get (widget-at)))
-                       nil)))
-    (widget-forward 1)
-    (setq settings
-         (append settings
-                 (cons (cons "dns2"
-                             (widget-field-value-get (widget-at)))
-                       nil)))
-    (widget-forward 1)
-    (setq settings
-         (append settings
-                 (cons (cons "enctype"
-                             (widget-value (widget-at)))
-                       nil)))
-    (setq start-pos (widget-get (widget-at) :to))
-    (if (not (string= (widget-value (widget-at)) "None"))
-       (setq type-wid-list
-             (cadr (assoc "reqs"
-                          (cdr (assoc (widget-value (widget-at))
-                                      (enwc-get-sec-types 
enwc-using-wired)))))))
-    (dolist (x type-wid-list)
-      (widget-forward 1)
-      (if (not (string= (widget-field-value-get (widget-at)) ""))
-         (setq settings
-               (append settings
-                       (cons (cons (car x)
-                                   (widget-field-value-get (widget-at)))
-                             nil)))))
-    (print settings)
-
-    (enwc-save-nw-settings enwc-using-wired enwc-edit-id settings)))
+  (unless (get-buffer "*ENWC Edit*")
+    (error "Not editing a network entry"))
+  (unless (eq (current-buffer) (get-buffer "*ENWC Edit*"))
+    (switch-to-buffer "*ENWC Edit*"))
+
+  (enwc-save-nw-settings
+   enwc-edit-id
+   (append (widget-value enwc-network-edit-widget)
+           (enwc-sec-widget-data enwc-security-edit-widget))))
 
 (defun enwc-edit-entry-at-point ()
   "Edit the current network entry."
   (interactive)
-  (setq enwc-edit-id (- (line-number-at-pos) 1))
+  (setq enwc-edit-id (tabulated-list-get-id))
+  ;;TODO: This is really annoying.
   (select-window (split-window))
   (enwc-setup-edit-buffer))
 
@@ -928,7 +1053,7 @@ and redisplays the settings from the network profile
   (let ((map (make-sparse-keymap)))
     (define-key map (kbd "R") 'enwc-scan)
     (define-key map (kbd "C") 'enwc-connect-to-network-essid)
-    (define-key map (kbd "D") 'enwc-disconnect)
+    (define-key map (kbd "D") 'enwc-disconnect-network)
     (define-key map (kbd "W") 'enwc-toggle-wired)
     (define-key map (kbd "E") 'enwc-edit-entry-at-point)
     (define-key map (kbd "RET") 'enwc-connect-to-network-at-point)
@@ -952,14 +1077,18 @@ and redisplays the settings from the network profile
 \\{enwc-mode-map}"
   (add-hook 'tabulated-list-revert-hook 'enwc-scan nil t))
 
-(defun enwc-setup-buffer ()
+(defun enwc-setup-buffer (&optional nomove)
   "Sets up the ENWC buffer.
 This first checks to see that it exists,
-and if it doesn't, then create it."
-  (if (not (get-buffer "*ENWC*"))
-      (with-current-buffer (get-buffer-create "*ENWC*")
-       (enwc-mode)))
-  (switch-to-buffer "*ENWC*"))
+and if it doesn't, then create it.
+
+If NOMOVE is non-nil, then do not move to the
+newly created buffer."
+  (unless (get-buffer "*ENWC*")
+    (with-current-buffer (get-buffer-create "*ENWC*")
+      (enwc-mode)))
+  (unless nomove
+    (switch-to-buffer "*ENWC*")))
 
 (provide 'enwc)
 



reply via email to

[Prev in Thread] Current Thread [Next in Thread]