Index: /trunk/contrib/README
===================================================================
--- /trunk/contrib/README	(revision 13946)
+++ /trunk/contrib/README	(revision 13946)
@@ -0,0 +1,7 @@
+This directory contains source code contributed by users.  It
+is on the module search path, so files here can be loaded using
+REQUIRE.
+
+If you are interested in contributing source code here and don't
+have write access to the CCL repository, send a note to
+ccl-devel@clozure.com.
Index: /trunk/contrib/baylis/ca-demo.lisp
===================================================================
--- /trunk/contrib/baylis/ca-demo.lisp	(revision 13946)
+++ /trunk/contrib/baylis/ca-demo.lisp	(revision 13946)
@@ -0,0 +1,136 @@
+;;
+;; Core Animation Demo
+;;
+;; Author: Neil Baylis
+;;
+;; neil.baylis@gmail.com
+;;
+;; usage:
+;;   1. start a 64 bit version of ccl
+;;   2. (load "path to ca-demo.lisp on your system")
+;;   3. (run-demo "absolute path to small image file on your system")
+;;
+;; Click in the window, and the image will move smoothly to the mouse point.
+;; Pressing any key will toggle full-screen mode
+;;
+;; This demo is meant purely to illustrate various objc bridge constructs
+;; as well as minimal steps to make Core Animation do something.
+;;
+(in-package "CL-USER")
+
+(require :cocoa)
+
+(eval-when (:compile-toplevel :load-toplevel :execute)
+  (objc:load-framework "Quartz" :quartz))
+
+(defun nsstr (s) (make-instance 'gui::ns-lisp-string :string s))
+
+(defparameter +standard-window-style-mask+
+  (logior #$NSTitledWindowMask
+          #$NSClosableWindowMask
+          #$NSMiniaturizableWindowMask
+          #$NSResizableWindowMask))
+
+(defun make-ns-window (x y &optional (title "Untitled"))
+  (let ((nsw (make-instance 'ns:ns-window
+               :with-content-rect (ns:make-ns-rect 0 0 x y)
+               :style-mask +standard-window-style-mask+
+               :backing #$NSBackingStoreBuffered
+               :defer t)))
+    (#/setTitle: nsw (nsstr title))
+    (#/setBackgroundColor:
+     nsw
+     (#/colorWithDeviceRed:green:blue:alpha: ns:ns-color 0.95 1.0 0.95 1.0 ))
+    (#/center nsw)
+    (#/makeKeyAndOrderFront: nsw nil)
+    nsw))
+
+(defmacro with-focused-view (view &body forms)
+  `(when (#/lockFocusIfCanDraw ,view)
+     (unwind-protect (progn ,@forms)
+       (#/unlockFocus ,view)
+       (#/flushGraphics (#/currentContext ns:ns-graphics-context))
+       (#/flushWindow (#/window ,view)))))
+
+(defclass ca-demo-view (ns:ns-view)
+  ((path :initform (make-instance ns:ns-bezier-path)))
+  (:metaclass ns:+ns-object))
+
+(defvar sprite)
+
+(defun set-layer-position (layer point)
+  (let* ((pos
+	  (make-record
+	   :<CGP>oint x (ns:ns-point-x point) y (ns:ns-point-y point))))
+    (#/removeAllAnimations layer)
+    (#/setPosition: layer pos)
+    (free pos)))
+
+(ccl::define-objc-method ((:void :mouse-down (:id event)) ca-demo-view)
+    (let* ((event-location (#/locationInWindow event))
+	   (view-location (#/convertPoint:fromView: self event-location nil)))
+      (set-layer-position sprite view-location)))
+
+(ccl::define-objc-method ((:void :mouse-dragged (:id event)) ca-demo-view)
+    (let* ((event-location (#/locationInWindow event))
+	   (view-location (#/convertPoint:fromView: self event-location nil)))
+      (set-layer-position sprite view-location)))
+
+(ccl::define-objc-method ((:void :key-down (:id event)) ca-demo-view)
+    (declare (ignore event))
+    (if (#/isInFullScreenMode self)
+	(#/exitFullScreenModeWithOptions: self #$nil)
+	(#/enterFullScreenMode:withOptions: self (#/mainScreen ns:ns-screen) #$nil)))
+
+(ccl::define-objc-method ((:<BOOL> accepts-first-responder) ca-demo-view) #$YES)
+
+(defun set-layer-bounds (layer rect)
+  (let* ((o (make-record :<CGP>oint
+			 x (ns:ns-rect-x rect)
+			 y (ns:ns-rect-y rect)))
+	 (s (make-record :<CGS>ize
+			 width (ns:ns-rect-width rect)
+			 height (ns:ns-rect-height rect)))
+	 (bounds (make-record :<CGR>ect origin o size s)))
+    (#/setBounds: layer bounds)
+    (free bounds)
+    (free s)
+    (free o)))
+
+(defun make-ca-layer (filename)
+  (let* ((layer (#/init (make-instance 'ns:ca-layer)))
+	 (ns-img (make-instance ns:ns-image :init-with-contents-of-file (nsstr filename)))
+	 (s (#/size ns-img))
+	 (repr (#/TIFFRepresentation ns-img))
+	 (sr (#_CGImageSourceCreateWithData repr CCL:+NULL-PTR+))
+	 (ir (#_CGImageSourceCreateImageAtIndex sr 0 CCL:+NULL-PTR+))
+	 )
+    (#/setName: layer (nsstr "sprite"))
+    (#/setContents: layer ir)
+    (set-layer-bounds layer (ns:make-ns-rect 0 0 (pref s :ns-size.width) (pref s :ns-size.height)))
+    (#/release ns-img)
+    (#_CFRelease sr)
+    (#_CGImageRelease ir)
+    layer))
+
+(defun add-layer-to-view (view layer)
+  (#/setDelegate: layer view)
+  (#/addSublayer: (#/layer view) sprite))
+
+;
+; e.g. (run-demo "/foo/bar/my-image.jpg")
+;
+; Make a window.
+; Make a view
+; Tell the view that it needs a CA Backing layer
+; Make a CALayer using the content of the supplied image 
+; Add the newly created layer to the view
+; Add the newly created view to the window
+;
+(defun run-demo (filename)
+  (let ((w (make-ns-window 900 600 "CA Demo"))
+        (v (make-instance 'ca-demo-view)))
+    (#/setWantsLayer: v #$YES)
+    (setf sprite (make-ca-layer filename))
+    (add-layer-to-view v sprite)
+    (#/setContentView: w v)))
Index: /trunk/contrib/cater/extended-demo.lisp
===================================================================
--- /trunk/contrib/cater/extended-demo.lisp	(revision 13946)
+++ /trunk/contrib/cater/extended-demo.lisp	(revision 13946)
@@ -0,0 +1,316 @@
+(in-package :easygui-demo)
+
+; ---------------
+; Demo for the new control types for EasyGui within Clozure CL
+; Contributed March 2009 by AWSC (arthur.cater@ucd.ie)
+; based upon earlier work by an unknown author.
+; Permission is given to disseminate, use, and modify.
+; No warranty is expressed or implied.
+;
+; Tested in cclv1.2 on 32-bitPPC, in cclv1.3 on 32-bitPPC and 64-bitIntel Macs.
+; Tested only in images constructed using (require :cocoa-application).
+
+(setf easygui::*debug-cocoa-calls* nil)
+
+(defclass view-hierarchy-demo-window (window)
+     ((with :initarg :with :initform :button)
+      (textbox :initarg :textbox :initform nil :accessor demo-textbox))
+  (:default-initargs :size (point 480 270)
+    :position (point 125 513)
+    :resizable-p nil
+    :minimizable-p t
+    :title "View tree demo")
+  (:documentation "Shows a window with a simple view hierarchy and one or more controls
+ that manipulate this hierarchy."))
+
+(defclass brown-drawing-view (drawing-view) ())
+
+(defmethod draw-view-rectangle ((drawing brown-drawing-view) rectangle)
+  (declare (ignore rectangle))
+  (let* ((cocoa-view (cocoa-ref drawing))
+         (rect (dcc (#/bounds cocoa-view)))
+         (brown (dcc (#/brownColor ns:ns-color))))
+    (with-focused-view cocoa-view
+      (dcc (#/setFill brown))
+      (dcc (#_NSRectFill rect)))))
+         
+(defmethod initialize-view :after ((w view-hierarchy-demo-window))
+  (let (left-box right-box button left-button right-button checkbox popup pulldown slider
+        drawing text (leftp t)
+        (normalfont (gui::default-font :name "Monaco" :size 10.0 :attributes nil))
+        (shoutfont (gui::default-font :name "Courier" :size 36.0 :attributes '(:bold :italic))))
+    (labels ((to-left ()
+               (retaining-objects (text)
+                 (cond ((not leftp)
+                        (remove-subviews right-box text)
+                        (add-subviews left-box text))))
+               (setf leftp t))
+            (to-right ()
+             (retaining-objects (text)
+                (cond (leftp
+                       (remove-subviews left-box text)
+                       (add-subviews right-box text))))
+             (setf leftp nil))
+            (to-other ()
+             (retaining-objects (text)
+                (cond ((not leftp)
+                       (remove-subviews right-box text)
+                       (add-subviews left-box text))
+                      (leftp
+                       (remove-subviews left-box text)
+                       (add-subviews right-box text))))
+             (setf leftp (not leftp)))
+            (generate-menu-items ()
+              (list (make-instance 'menu-item-view :title "Left" :action #'to-left)
+                    (make-instance 'menu-item-view :title "Right" :action #'to-right)
+                    (make-instance 'menu-item-view :title "Other" :action #'to-other)
+                    (make-instance 'pop-up-menu :title "Text Options"
+                      :menu-items
+                      (list (make-instance 'menu-item-view :title "Oink"
+                              :action #'(lambda () (setf (view-font text) normalfont)
+                                                   (setf (view-text text) "Oink!")
+                                                   (setf (view-size text) (point 60 20))
+                                                   (setf (view-position text) (point 37 112))))
+                            (make-instance 'menu-item-view :title "SHOUT!"
+                              :action #'(lambda () (setf (view-font text) shoutfont)
+                                                   (setf (view-text text) "HEY!")
+                                                   (setf (view-size text) (point 160 60))
+                                                   (setf (view-position text) (point 17 10))))
+                            (make-instance 'pop-up-menu :title "Whisper"
+                              :menu-items
+                              (list (make-instance 'menu-item-view :title "sh!"
+                                      :action #'(lambda () (setf (view-font text) normalfont)
+                                                           (setf (view-text text) "sh!")))
+                                    (make-instance 'menu-item-view :title "psst!"
+                                      :action #'(lambda () (setf (view-font text) normalfont)
+                                                           (setf (view-text text) "psst!"))))))))))
+      (setf left-box (make-instance 'box-view
+                       :position (point 17 51)
+                       :size (point 208 199)
+                       :title "Left"
+                       :tip #'(lambda nil (unless leftp "The occupied box has no tooltip"))
+                       :view-nick-name :leftbox)
+            right-box (make-instance 'box-view
+                        :position (point 255 51)
+                        :size (point 208 199)
+                        :tip #'(lambda nil (if leftp "The occupied box has no tooltip"))
+                        :title "Right"
+                        :view-nick-name :rightbox)
+            button (make-instance 'push-button-view
+                       :position (point 173 12)
+                       :text "Change side"
+                       :tip #'(lambda nil "Button tip does not work!")
+                       :view-nick-name :push-button
+                       :action #'to-other)
+            left-button (make-instance 'radio-button-view
+                          :position (point 103 12)
+                          :text "Left side"
+                          :selected t
+                          :view-nick-name :leftbutton
+                          :tip #'(lambda nil (format nil
+                                                       "Where's the amazing tooltip?~%The text is in the box on the ~:[right~;left~]"
+                                                       leftp))
+                          :action #'to-left)
+            right-button (make-instance 'radio-button-view
+                           :position (point 243 12)
+                           :text "Right side"
+                           :view-nick-name :rightbutton
+                           :tip #'(lambda nil (format nil
+                                                        "Where's the amazing tooltip?~%The text is in the box on the ~:[right~;left~]"
+                                                        leftp))
+                   
+                           :action #'to-right)
+            checkbox (make-instance 'check-box-view
+                       :position (point 173 12)
+                       :text "Right side"
+                       :view-nick-name :checkbox
+                       :tip #'(lambda nil (format nil
+                                                    "Where's the amazing tooltip?~%The text is in the box on the ~:[right~;left~]"
+                                                    leftp))
+                       :action #'to-other)
+            popup (make-instance 'pop-up-menu
+                   :position (point 173 12)
+                   :size (point 120 24)
+                   :title "Command?"
+                   :tip #'(lambda nil (format nil "Pop up menus can have tooltips,~%however their menu items cannot."))
+                   :view-nick-name :pop-up-menu
+                   :menu-items (generate-menu-items))
+            pulldown (make-instance 'pull-down-menu
+                   :position (point 173 12)
+                   :size (point 120 24)
+                   :title "Command?"
+                   :tip #'(lambda nil (format nil "Pull down menus can have tooltips,~%however their menu items cannot."))
+                   :view-nick-name :pull-down-menu
+                   :menu-items (generate-menu-items))
+            drawing (make-instance 'brown-drawing-view
+                   :position (point 173 12)
+                   :size (point 120 24)
+                   :view-nick-name :drawing
+                   :tip #'(lambda nil (format nil
+                                                "See the amazing tooltip!~%The text is in the box on the ~:[right~;left~]"
+                                                leftp))
+                   :mouse-down #'(lambda (view &key &allow-other-keys)
+                                   (declare (ignore view))
+                                   (if (shift-key-p) (to-left) (to-other))))
+            text (make-instance 'static-text-view
+                   :text "Oink!"
+                   :view-font normalfont
+                   :tip :identify
+                   :position (point 37 112)
+                   :size (point 60 20)
+                   :fore-color (make-rgb :red 0 :green 0 :blue 255)
+                   :back-color (make-rgb :red 255 :green 220 :blue 200))
+            slider (make-instance 'slider-view :min-value 0 :max-value 1
+                     ;            :text "How right"   ;; No provision for title or text?
+                     :position (point 173 12) :size (point 136 24)
+                     :view-nick-name :slider
+                     :tip #'(lambda nil (format nil
+                                                "See the amazing tooltip!~%The text is in the box on the ~:[right~;left~]"
+                                                leftp))
+                     :action #'(lambda ()
+                                 (if (> (dcc (#/floatValue (cocoa-ref slider))) 0.5)
+                                   (to-right)
+                                   (to-left)))))
+      (add-subviews w left-box right-box)
+      (case (slot-value w 'with)
+        (:button (add-subviews w button))
+        (:radio (add-subviews w left-button right-button))
+        (:check (add-subviews w checkbox))
+        (:popup  (add-subviews w popup))
+        (:pulldown (add-subviews w pulldown))
+        (:slider (add-subviews w slider))
+        (:drawing (add-subviews w drawing))
+        (otherwise (format t "~&** The WITH slot is ~s, it must be either :BUTTON :RADIO :CHECK :POPUP ~
+                           :PULLDOWN :DRAWING or :SLIDER~%"
+                           (slot-value w 'with))))
+      (add-subviews left-box text)
+      (setf (demo-textbox w) text)
+      (add-contextual-menu w
+                           (make-instance 'contextual-menu
+                             :menu-items (generate-menu-items))
+                           t)
+      (window-show w))))
+
+(defparameter *w nil)
+
+(defparameter *run-file-chooser-anyway* nil)
+
+(defvar *closing-under-program-control* nil
+"Used in demonstrating tailored window-closing behaviour.")
+ 
+(defmethod window-may-close ((w view-hierarchy-demo-window))
+  (or *closing-under-program-control*
+      (when (y-or-n-dialog "Do you really want to close the window like this?")
+        (setf *w nil)
+        t)))
+
+(defun run-demo ()
+  (flet ((example (with)
+           (when *w (let ((*closing-under-program-control* t)) (perform-close *w)))
+           (setf *w (make-instance 'view-hierarchy-demo-window :with with))))
+    (dolist (spec `(("Did you know?" "Contextual Menus"        ,#'(lambda nil (y-or-n-dialog
+                                                                               (format nil
+                                                                                       "Did you know there are contextual menus ~
+                                                                                       available - in many but not all places - ~
+                                                                                       when you press control-click?"))))
+                    ("Did you know?" "New TOOLS item"          ,#'(lambda nil (y-or-n-dialog
+                                                                               (format nil
+                                                                                       "Did you know there is a \"Choose Color\" ~
+                                                                                       item added to the TOOLS menu?~%
+                                                                                       (Sadly however there is no keyboard ~
+                                                                                       shortcut for it and it simply prints the ~
+                                                                                       chosen color in the console window.)"))))
+                    ("Did you know?" "Tooltips"                ,#'(lambda nil (y-or-n-dialog
+                                                                               (format nil
+                                                                                       "Did you know that some sorts of view ~
+                                                                                       have tooltips attached?~%~
+                                                                                       (Sadly however some do not work as intended.)~%~
+                                                                                       These may be fixed strings, dynamically ~
+                                                                                       generated strings, or cocoa descriptions."))))
+                    ("Did you know?" "Choose File menu items (not working)"
+                                                               ,#'(lambda nil (y-or-n-dialog
+                                                                               (format nil
+                                                                                       "Did you know that there are items in the File menu ~
+                                                                                       and in the Easygui Demo menu that let you use a ~
+                                                                                       Choose-File-Dialog? Sadly however they do not work properly ~
+                                                                                       right now and will probably crash your CCL session. ~
+                                                                                       If you want to go ahead anyway, first select the ~
+                                                                                       \"Run File Chooser Anyway\" item."))))
+                    ("Did you know?" "Flipped screen mode"     ,#'(lambda nil (y-or-n-dialog
+                                                                               (format nil
+                                                                                       "Did you know that it is possible to position windows ~
+                                                                                       and items within them as if screen coordinates had their ~
+                                                                                       origin at screen top-left, as in Digitool's MCL?"))))
+                    ("Did you know?" "Cocoa tracing"           ,#'(lambda nil (y-or-n-dialog
+                                                                               (format nil
+                                                                                       "Did you know that debugging messages can be ~
+                                                                                       produced when Cocoa calls are made? ~
+                                                                                       This relies on the DCC macro being used conscientiously, ~
+                                                                                       it is not automatic."))))
+                    ("Did you know?" "Font and Color support"  ,#'(lambda nil (y-or-n-dialog
+                                                                               (format nil
+                                                                                       "Did you know that there is some limited support for ~
+                                                                                       handling text fonts and colors and backgrounds? ~
+                                                                                       Try out the \"SHOUT!\" options in a demo window menu."))))
+                    ("Did you know?" "Window Close behaviour"  ,#'(lambda nil (y-or-n-dialog
+                                                                               (format nil
+                                                                                       "Did you know that windows can be made to invoke Lisp ~
+                                                                                       code when they are told to close? The primary method ~
+                                                                                       for Window-Should-Close decides whether the window ~
+                                                                                       should close or not, before- and after-methods could ~
+                                                                                       be used for other purposes. The Demo Window behaves ~
+                                                                                       differently when you close the window as part of ~
+                                                                                       creating a new one, and when you press its close button."))))
+                    ("Give Example" "With Button"              ,#'(lambda nil (example :button)))
+                    ("Give Example" "With Radio Buttons"       ,#'(lambda nil (example :radio)))
+                    ("Give Example" "With Checkbox"            ,#'(lambda nil (example :check)))
+                    ("Give Example" "With Popup Menu"          ,#'(lambda nil (example :popup)))
+                    ("Give Example" "With Pulldown Menu"       ,#'(lambda nil (example :pulldown)))
+                    ("Give Example" "With Drawing"             ,#'(lambda nil (example :drawing)))
+                    ("Give Example" "With Slider"              ,#'(lambda nil (example :slider)))
+                    ("Flipping" "New windows are flipped"      ,#'(lambda nil (setf *screen-flipped* t)))
+                    ("Flipping" "New windows are not flipped"  ,#'(lambda nil (setf *screen-flipped* nil)))
+                    ("Tracing" "Cocoa Calls are traced"        ,#'(lambda nil (setf easygui::*debug-cocoa-calls* t)))
+                    ("Tracing" "Cocoa Calls are not traced"    ,#'(lambda nil (setf easygui::*debug-cocoa-calls* nil)))
+                    ("Color Picker" "Text"                     ,#'(lambda nil
+                                                                    (cl-user::process-run-function "Pick color for text in box"
+                                                                     #'(lambda nil
+                                                                         (gui::with-autorelease-pool
+                                                                             (let* ((textbox (if *w (demo-textbox *w)))
+                                                                                    (color (if textbox
+                                                                                             (get-fore-color textbox)
+                                                                                             (make-rgb :red 0 :green 0 :blue 255))))
+                                                                               (setf color (user-pick-color :color color
+                                                                                              :prompt "Pick a text color"))
+                                                                               (when textbox
+                                                                                 (set-fore-color textbox color)
+                                                                                 (invalidate-view textbox))))))))
+                    ("Color Picker" "Background"               ,#'(lambda nil
+                                                                    (cl-user::process-run-function "Pick color for text in box"
+                                                                     #'(lambda nil
+                                                                         (gui::with-autorelease-pool
+                                                                             (let* ((textbox (if *w (demo-textbox *w)))
+                                                                                    (color (if textbox
+                                                                                             (get-back-color textbox)
+                                                                                             (make-rgb :red 255 :green 220 :blue 200))))
+                                                                               (setf color (user-pick-color :color color
+                                                                                              :prompt "Pick a background color"))
+                                                                               (when textbox
+                                                                                 (set-back-color textbox color t))))))))
+                    ("Destroy this menu"                       ,#'(lambda nil (remove-topbar-item (list "Easygui Demo"))))
+                    ("Run File Chooser Anyway"                 ,#'(lambda nil (setf *run-file-chooser-anyway* t)))
+                    ("File" "Get a pathname"                   ,#'(lambda nil
+                                                                    (when *run-file-chooser-anyway*
+                                                                      (print "Getting a pathname(Easygui Demo Menu)...doomed to failure!")
+                                                                      (choose-file-dialog :button-string "Get a pathname(EG)"))))))
+      (add-topbar-item (cons "Easygui Demo" (butlast spec)) (first (last spec))))
+    (add-topbar-item '("Tools" "Choose Color")                 #'(lambda nil
+                                                                   (print (user-pick-color))))
+    (add-topbar-item '("File" "Get a pathname")                #'(lambda nil
+                                                                   (when *run-file-chooser-anyway*
+                                                                     (running-on-main-thread ()
+                                                                       (print "Getting a pathname(File Menu)...doomed to failure")
+                                                                       (print (choose-file-dialog :button-string "Get a pathname(FILE)"))))))
+    (y-or-n-dialog "Have you spotted the new \"Easygui Demo\" item in the menubar?")))
+
+; (easygui-demo::run-extended-demo)
Index: /trunk/contrib/foy/cl-documentation-cm/cl-documentation-2.lisp
===================================================================
--- /trunk/contrib/foy/cl-documentation-cm/cl-documentation-2.lisp	(revision 13946)
+++ /trunk/contrib/foy/cl-documentation-cm/cl-documentation-2.lisp	(revision 13946)
@@ -0,0 +1,107 @@
+;;;-*-Mode: LISP; Package: HEMLOCK-COMMANDS -*-
+
+;;; ----------------------------------------------------------------------------
+;;;
+;;;      cl-documentation-2.lisp
+;;;
+;;;      copyright (c) 2009 Glen Foy
+;;;      (Permission is granted to Clozure Associates to distribute this file.)
+;;;
+;;;      This code adds an alphabetical index of :CL commands to the Context-Menu 
+;;;      mechanism.  Command-Right-Click displays a list of letter submenus.
+;;;      Popping the submenu displays entries for all Hemlock Commands starting with
+;;;      that letter.  Selecting an entry opens a documentation dialog.
+;;;
+;;;      This software is offered "as is", without warranty of any kind.
+;;;
+;;;      Mod History, most recent first:
+;;;      9/2/9  version 0.1b1
+;;;              First cut.
+;;;
+;;; ----------------------------------------------------------------------------
+
+(in-package "CL-DOCUMENTATION") 
+
+
+;;; ----------------------------------------------------------------------------
+;;;
+(defclass CL-ALPHABETICAL-MENU-ITEM (ns:ns-menu-item)
+  ((symbol :initarg :symbol :accessor item-symbol))
+  (:documentation "Support for the CL alphabetical menu.")
+  (:metaclass ns:+ns-object))
+
+(defun populate-submenu (menu symbol-list)
+  "Make menu-items for all symbols in SYMBOL-LIST, and add them to MENU"
+  (dolist (symbol (reverse symbol-list))
+    (let* ((menu-item (make-instance 'cl-alphabetical-menu-item :symbol symbol))
+           (attributed-string (#/initWithString:attributes:
+                               (#/alloc ns:ns-attributed-string) 
+                               (ccl::%make-nsstring (string-downcase (string symbol)))
+                               cmenu:*hemlock-menu-dictionary*)))
+;      (setf (item-symbol menu-item) symbol)
+      (#/setAttributedTitle: menu-item attributed-string)
+      (#/setAction: menu-item (ccl::@selector "clAlphabeticalDocAction:"))
+      (#/setTarget: menu-item  *cl-alphabetical-menu*)
+      (#/addItem: menu menu-item))))
+
+(defun make-submenu-item (title symbol-list)
+  "Create a menu-item with a submenu, and populate the submenu with the symbols in SYMBOL-LIST."
+  (let ((menu-item (make-instance ns:ns-menu-item))
+        (attributed-string (#/initWithString:attributes:
+                            (#/alloc ns:ns-attributed-string) 
+                            (ccl::%make-nsstring title)
+                            cmenu:*hemlock-menu-dictionary*))
+        (submenu (make-instance ns:ns-menu)))
+    (#/setAttributedTitle: menu-item attributed-string)
+    (#/setSubmenu: menu-item submenu)
+    (populate-submenu submenu symbol-list)
+    menu-item))
+
+(defparameter *ABCs* "ABCDEFGHIJKLMNOPQRSTUVWXYZ")
+
+;;; ----------------------------------------------------------------------------
+;;;
+(defclass CL-ALPHABETICAL-MENU (ns:ns-menu)
+  ((tool-menu :initform nil :accessor tool-menu)
+   (text-view :initform nil :accessor text-view)
+   (sub-title :initform "alphabetical" :reader sub-title))
+  (:documentation "A popup menu with alphabetically ordered letter submenus.")
+  (:metaclass ns:+ns-object))
+
+(objc:defmethod (#/clAlphabeticalDocAction: :void) ((m cl-alphabetical-menu) (sender :id))
+  (display-cl-doc (item-symbol sender) (text-view m)))
+
+(defmethod initialize-instance :after ((menu cl-alphabetical-menu) &key)
+  (setf (tool-menu menu) (cmenu:add-default-tool-menu menu)))
+
+(defmethod add-submenus ((menu cl-alphabetical-menu))
+  (let* ((letter-array-length (length *ABCs*))
+         (letter-array (make-array letter-array-length :initial-element nil))
+         miscellaneous first-letter index)
+    (dolist (sym (remove-duplicates (apply #'append *cl-symbol-lists*) :test #'eq))
+      (setq first-letter (elt (string sym) 0))
+      (setq index (position first-letter *ABCs* :test #'char-equal))
+      (if index
+        (push sym (aref letter-array index))
+        (push sym miscellaneous)))
+    (dotimes (idx letter-array-length)
+      (let ((submenu-item (make-submenu-item (elt *ABCs* idx) 
+                                             (sort (coerce (aref letter-array idx) 'list)
+                                                   #'string> :key #'string))))
+        (#/addItem: menu submenu-item)))
+    (when miscellaneous
+      (#/addItem: menu (#/separatorItem ns:ns-menu-item))    
+      (let ((submenu-item (make-submenu-item "Other:" miscellaneous)))
+        (#/addItem: menu submenu-item)))))
+
+(objc:defmethod (#/update :void) ((self cl-alphabetical-menu))
+  (cmenu:update-tool-menu self (tool-menu self) :sub-title (sub-title self))
+  (call-next-method))
+
+(setq *cl-alphabetical-menu* (make-instance 'cl-alphabetical-menu))
+
+(add-submenus *cl-alphabetical-menu*)
+
+
+
+
Index: /trunk/contrib/foy/cl-documentation-cm/cl-documentation-cm.lisp
===================================================================
--- /trunk/contrib/foy/cl-documentation-cm/cl-documentation-cm.lisp	(revision 13946)
+++ /trunk/contrib/foy/cl-documentation-cm/cl-documentation-cm.lisp	(revision 13946)
@@ -0,0 +1,22 @@
+
+;;; cl-documentation.lisp 
+
+(in-package :common-lisp-user)
+
+(unless (member "CL-DOCUMENTATION-CM" *modules* :test #'string-equal)
+  
+(eval-when (:load-toplevel :execute)
+  (defParameter *cl-documentation-directory*
+    (make-pathname :name nil :type nil :defaults (if *load-pathname* 
+                                                     *load-pathname*
+                                                     *loading-file-source-file*)))
+  (defParameter *cl-documentation-files* 
+    (list (merge-pathnames ";cl-documentation.lisp" *cl-documentation-directory*)
+          (merge-pathnames ";cl-documentation-2.lisp" *cl-documentation-directory*))))
+ 
+(dolist (file *cl-documentation-files*)
+  (load file))
+
+(provide :cl-documentation-cm)
+
+)
Index: /trunk/contrib/foy/cl-documentation-cm/cl-documentation.lisp
===================================================================
--- /trunk/contrib/foy/cl-documentation-cm/cl-documentation.lisp	(revision 13946)
+++ /trunk/contrib/foy/cl-documentation-cm/cl-documentation.lisp	(revision 13946)
@@ -0,0 +1,472 @@
+;;;-*-Mode: LISP; Package: CL-DOCUMENTATION -*-
+
+;;; ----------------------------------------------------------------------------
+;;;
+;;;      cl-documentation.lisp
+;;;
+;;;      copyright (c) 2009 Glen Foy
+;;;      (Permission is granted to Clozure Associates to distribute this file.)
+;;;
+;;;      This code is moronically simple, but surprisingly useful.
+;;;      It adds a documentation tool for CL functions to the Context-Menu mechanism.
+;;;      Right-Click displays a list of submenus.  The submenus are functional groups.
+;;;      Popping the submenu displays entries for all CL functions belonging to that
+;;;      functional group.  Selecting a function open a documentation dialog.
+;;;
+;;;      This software is offered "as is", without warranty of any kind.
+;;;
+;;;      Mod History, most recent first:
+;;;      9/2/9   Added a second menu, providing an alphabetical index.
+;;;      8/31/9  version 0.1b1
+;;;              First cut.
+;;;
+;;; ----------------------------------------------------------------------------
+
+(defpackage "CL-DOCUMENTATION" (:nicknames "CLDOC") (:use :cl :ccl))
+(in-package "CL-DOCUMENTATION")
+
+(require :context-menu-cm)
+(cmenu:check-hyperspec-availability "CL-Documentation-CM")
+
+(defparameter *cl-documentation-menu* nil "The cl-documentation-menu instance.")
+(defparameter *cl-alphabetical-menu* nil "The cl-alphabetical-menu instance.")
+
+
+;;; ----------------------------------------------------------------------------
+;;;
+(defClass CL-DOCUMENTATION-MENU (ns:ns-menu) 
+  ((tool-menu :initform nil :accessor tool-menu)
+   (sub-title :initform "functional groups" :reader sub-title)
+   (doc-path :initform (merge-pathnames ";ReadMe.rtf" cl-user::*cl-documentation-directory*) :reader doc-path)
+   (text-view :initform nil :accessor text-view))
+  (:documentation "A menu containing CL functions sorted into functional groups.")
+  (:metaclass ns:+ns-object))
+
+(objc:defmethod (#/clDocumentationAction: :void) ((m cl-documentation-menu) (sender :id))
+  (display-cl-doc (item-symbol sender) (text-view m)))
+
+(objc:defmethod (#/update :void) ((m cl-documentation-menu))
+  (cmenu:update-tool-menu m (tool-menu m) :sub-title (sub-title m))
+  (call-next-method))
+
+(defmethod initialize-instance :after ((m cl-documentation-menu) &key)
+  (setf (tool-menu m) (cmenu:add-default-tool-menu m :doc-file (doc-path m))))
+
+(defun display-cl-doc (symbol text-view)
+  "Display the documentation for SYMBOL."
+  ;; If Hemlock-Commands is loaded, this will be
+  ;; redefined there to use the documentation dialog.
+  (gui::lookup-hyperspec-symbol symbol text-view))
+
+(setq *cl-documentation-menu* (make-instance 'cl-documentation-menu))
+
+;;; ----------------------------------------------------------------------------
+;;;
+(defClass CL-CATEGORY-MENU-ITEM (ns:ns-menu-item) 
+  ((symbol :initform nil :accessor item-symbol))
+  (:documentation "Support for the documentation menu.")
+  (:metaclass ns:+ns-object))
+
+(defun populate-submenu (menu symbol-list)
+  "Create and add menu-items for each functional group in SYMBOL-LIST."
+  (dolist (sym symbol-list)
+    (let ((menu-item (make-instance 'cl-category-menu-item))
+          (attributed-string (#/initWithString:attributes:
+                              (#/alloc ns:ns-attributed-string) 
+                              (ccl::%make-nsstring (string-downcase (string sym)))
+                              cmenu:*hemlock-menu-dictionary*)))
+      (#/setAttributedTitle: menu-item attributed-string)
+      (#/setAction: menu-item (ccl::@selector "clDocumentationAction:"))
+      (#/setTarget: menu-item  *cl-documentation-menu*)
+      (setf (item-symbol menu-item) sym)
+      (#/addItem: menu menu-item))))
+
+(defun make-submenu-item (title symbol-list)
+  "Create a menu-item with a submenu and populate the submenu based on SYMBOL-LIST."
+  (let ((menu-item (make-instance ns:ns-menu-item))
+        (attributed-string (#/initWithString:attributes:
+                            (#/alloc ns:ns-attributed-string) 
+                            (ccl::%make-nsstring title)
+                            cmenu:*hemlock-menu-dictionary*))
+        (submenu (make-instance ns:ns-menu)))
+    (#/setAttributedTitle: menu-item attributed-string)
+    (#/setSubmenu: menu-item submenu)
+    (populate-submenu submenu symbol-list)
+    menu-item))
+
+;;; ----------------------------------------------------------------------------
+;;;
+(defParameter *evaluation-and-compilation-symbol-list*
+  (list 'compile 'compiler-macro-function 'constantp 'declaim 'declare 'define-compiler-macro 
+        'define-symbol-macro 'defmacro 'eval 'eval-when 'lambda 'load-time-value 'locally 
+        'macroexpand 'macroexpand-1 'macro-function 'proclaim 'special-operator-p 'symbol-macrolet
+        'the 'quote))
+
+(defParameter *evaluation-and-compilation*
+  (make-submenu-item "evaluation and compilation" *evaluation-and-compilation-symbol-list*))
+
+;;; ----------------------------------------------------------------------------
+;;;
+(defParameter *types-and-classes-symbol-list*
+  (list 'coerce 'deftype 'subtypep 'type-error-datum 'type-error-expected-type 'type-of 'typep))
+
+(defParameter *types-and-classes*
+  (make-submenu-item "types and classes" *types-and-classes-symbol-list*))
+
+;;; ----------------------------------------------------------------------------
+;;;
+(defParameter *control-and-data-flow-symbol-list*
+  (list 'and 'apply 'block 'case 'catch 'ccase 'compiled-function-p 'complement 'cond 
+        'constantly 'ctypecase 'defconstant 'define-modify-macro 'define-setf-expander 
+        'defparameter 'defsetf 'defun 'defvar 'destructuring-bind 'ecase 'eq 'eql 'equal 'equalp 
+        'etypecase 'every 'fboundp 'fdefinition 'flet 'fmakunbound 'funcall 'function 
+        'function-lambda-expression 'functionp 'labels 'get-setf-expansion 'go 'identity 'if 
+        'let 'let* 'macrolet 'multiple-value-bind 'multiple-value-call 'multiple-value-list 
+        'multiple-value-prog1 'multiple-value-setq 'not 'notany 'notevery 'nth-value 'or 'prog 
+        'prog* 'prog1 'prog2 'progn 'progv 'psetf 'psetq 'return 'return-from 'rotatef 'setf 
+        'setq 'shiftf 'some 'tagbody 'throw 'typecase 'unless 'unwind-protect 'values 
+        'values-list 'when))
+
+(defParameter *control-and-data-flow*
+  (make-submenu-item "control and data flow" *control-and-data-flow-symbol-list*))
+
+;;; ----------------------------------------------------------------------------
+;;;
+(defParameter *iteration-symbol-list*
+  (list 'do 'do* 'dolist 'dotimes 'loop))
+
+(defParameter *iteration*
+  (make-submenu-item "iteration" *iteration-symbol-list*))
+
+;;; ----------------------------------------------------------------------------
+;;;
+(defParameter *objects-symbol-list*
+  (list 'add-method 'allocate-instance 'call-method 'call-next-method 'change-class 'class-name 
+        'class-of 'compute-applicable-methods 'defclass 'defgeneric 'define-method-combination 
+        'defmethod 'ensure-generic-function 'find-class 'find-method 'function-keywords 
+        'initialize-instance 'make-instance 'make-instances-obsolete 'make-load-form 
+        'make-load-form-saving-slots 'method-qualifiers 'next-method-p 'no-applicable-method 
+        'no-next-method 'reinitialize-instance 'remove-method 'shared-initialize 'slot-boundp 
+        'slot-exists-p 'slot-makunbound 'slot-missing 'slot-unbound 'slot-value 'with-accessors 
+        'with-slots 'unbound-slot-instance 'update-instance-for-different-class 
+        'update-instance-for-redefined-class))
+
+(defParameter *objects*
+  (make-submenu-item "objects" *objects-symbol-list*))
+
+;;; ----------------------------------------------------------------------------
+;;;
+(defParameter *structures-symbol-list*
+  (list 'copy-structure 'defstruct))
+
+(defParameter *structures*
+  (make-submenu-item "structures" *structures-symbol-list*))
+
+;;; ----------------------------------------------------------------------------
+;;;
+(defParameter *conditions-symbol-list*
+  (list 'abort 'assert 'break 'cell-error-name 'cerror 'check-type 'compute-restarts 'continue 
+        'define-condition 'error 'find-restart 'handler-bind 'handler-case 'ignore-errors 
+        'invalid-method-error 'invoke-debugger 'invoke-restart 'invoke-restart-interactively 
+        'make-condition 'method-combination-error 'muffle-warning 'restart-bind 'restart-case 
+        'restart-name 'signal 'simple-condition-format-arguments 'simple-condition-format-control 
+        'store-value 'use-value 'warn 'with-condition-restarts 'with-simple-restart))
+
+(defParameter *conditions*
+  (make-submenu-item "conditions" *conditions-symbol-list*))
+
+;;; ----------------------------------------------------------------------------
+;;;
+(defParameter *symbols-symbol-list*
+  (list 'boundp 'copy-symbol 'gensym 'gentemp 'get 'keywordp 'make-symbol 'makunbound 'set 
+        'symbol-function 'symbol-name 'symbolp 'symbol-package 'symbol-plist 'symbol-value 
+        'remprop))
+
+(defParameter *symbols*
+  (make-submenu-item "symbols" *symbols-symbol-list*))
+
+;;; ----------------------------------------------------------------------------
+;;;
+(defParameter *packages-symbol-list*
+  (list 'defpackage 'delete-package 'do-all-symbols 'do-external-symbols 'do-symbols 'export 
+        'find-all-symbols 'find-package 'find-symbol 'import 'in-package 'intern 
+        'list-all-packages 'make-package 'package-error-package 'package-name 'package-nicknames 
+        'packagep 'package-shadowing-symbols 'package-used-by-list 'package-use-list 
+        'rename-package 'shadow 'shadowing-import 'unexport 'unintern 'unuse-package 
+        'with-package-iterator))
+
+(defParameter *packages*
+  (make-submenu-item "packages" *packages-symbol-list*))
+
+;;; ----------------------------------------------------------------------------
+;;;
+(defParameter *numbers-symbol-list*
+  (list 'abs 'acos 'acosh 'arithmetic-error-operands 'arithmetic-error-operation 'ash 'asin 
+        'asinh 'atan 'atanh 'boole 'byte 'byte-position 'byte-size 'ceiling 'cis 'complex 
+        'complexp 'conjugate 'cos 'cosh 'decf 'decode-float 'denominator 'deposit-field 'dpb 
+        'evenp 'exp 'expt 'fceiling 'ffloor 'float 'float-digits 'floatp 'float-precision 
+        'float-radix 'float-sign 'floor 'fround 'ftruncate 'gcd 'imagpart 'incf 
+        'integer-decode-float 'integer-length 'integerp 'isqrt 'lcm 'ldb 'ldb-test 'log 'logand 
+        'logandc1 'logandc2 'logbitp 'logcount 'logeqv 'logior 'lognand 'lognor 'lognot 'logorc1 
+        'logorc2 'logtest 'logxor 'make-random-state 'mask-field 'max 'min 'minusp 'mod 'numberp 
+        'numerator 'oddp 'parse-integer 'phase 'plusp 'random 'random-state-p 'rational 
+        'rationalize 'rationalp 'realp 'realpart 'rem 'round 'scale-float 'signum 'sin 'sinh 
+        'sqrt 'tan 'tanh 'truncate 'upgraded-complex-part-type 'zerop '= '/= '> '< '<= '>= '* 
+        '+ '- '/ '1+ '1- ))
+
+(defParameter *numbers*
+  (make-submenu-item "numbers" *numbers-symbol-list*))
+
+;;; ----------------------------------------------------------------------------
+;;;
+(defParameter *characters-symbol-list*
+  (list 'alpha-char-p 'both-case-p 'alphanumericp 'character 'characterp 'char-code 
+        'char-downcase 'char-greaterp 'char-equal 'char-int 'char-lessp 'char-name 
+        'char-not-greaterp 'char-not-equal 'char-not-lessp 'char-upcase 'char= 'char/= 
+        'char> 'char< 'char<= 'char>= 'code-char 'digit-char 'digit-char-p 'graphic-char-p 
+        'lower-case-p 'name-char 'standard-char-p 'upper-case-p))
+
+(defParameter *characters*
+  (make-submenu-item "characters" *characters-symbol-list*))
+
+;;; ----------------------------------------------------------------------------
+;;;
+(defParameter *conses-symbol-list*
+  (list 'acons 'adjoin 'append 'assoc 'assoc-if 'assoc-if-not 'atom 'butlast 'nbutlast 'car 'cdr 
+        'cons 'consp 'copy-alist 'copy-list 'copy-tree 'endp 'first 'getf 'get-properties 
+        'intersection 'nintersection 'last 'ldiff 'list 'list-length 'listp 'make-list 'mapc 
+        'mapcan 'mapcar 'mapcon 'mapl 'maplist 'member 'member-if 'member-if-not 'nconc 'nth 
+        'nthcdr 'null 'pairlis 'pop 'push 'pushnew 'rassoc 'rassoc-if 'rassoc-if-not 'remf 'rest 
+        'revappend 'nreconc 'rplaca 'rplacd 'set-difference 'nset-difference 'set-exclusive-or 
+        'nset-exclusive-or 'sublis 'nsublis 'subsetp 'subst 'nsubst 'subst-if 'nsubst-if 
+        'subst-if-not 'nsubst-if-not 'tailp 'tree-equal 'union 'nunion))
+
+(defParameter *conses*
+  (make-submenu-item "conses" *conses-symbol-list*))
+
+;;; ----------------------------------------------------------------------------
+;;;
+(defParameter *arrays-symbol-list*
+  (list  'adjustable-array-p 'adjust-array 'aref 'array-dimension 'array-dimensions  
+         'array-displacement 'array-element-type 'array-has-fill-pointer-p 'array-in-bounds-p  
+         'arrayp 'array-rank 'array-row-major-index 'array-total-size 'bit 'bit-and 'bit-andc1  
+         'bit-andc2 'bit-eqv 'bit-ior 'bit-nand 'bit-nor 'bit-not 'bit-orc1 'bit-orc2 'bit-xor  
+         'bit-vector-p 'fill-pointer 'make-array 'row-major-aref 'sbit 'simple-bit-vector-p  
+         'simple-vector-p 'svref 'upgraded-array-element-type 'vector 'vectorp 'vector-pop  
+         'vector-push 'vector-push-extend))
+
+(defParameter *arrays*
+  (make-submenu-item "arrays" *arrays-symbol-list*))
+
+;;; ----------------------------------------------------------------------------
+;;;
+(defParameter *strings-symbol-list*
+  (list 'char 'make-string 'schar 'simple-string-p 'string 'string-capitalize 'nstring-capitalize 
+        'string-downcase 'nstring-downcase 'string-equal 'string-greaterp 'string-upcase 
+        'nstring-upcase 'string-left-trim 'string-lessp 'string-not-equal 'string-not-greaterp 
+        'string-not-lessp 'stringp 'string-right-trim 'string-trim 'string= 'string/= 'string< 
+        'string> 'string<= 'string>=))
+
+(defParameter *strings*
+  (make-submenu-item "strings" *strings-symbol-list*))
+
+;;; ----------------------------------------------------------------------------
+;;;
+(defParameter *sequences-symbol-list*
+  (list 'concatenate 'copy-seq 'count 'count-if 'elt 'fill 'find 'find-if 'find-if-not 'length 
+        'make-sequence 'map 'map-into 'merge 'mismatch 'position 'position-if 'position-if-not 
+        'reduce 'remove 'delete 'remove-duplicates 'delete-duplicates 'remove-if 'delete-if 
+        'remove-if-not 'delete-if-not 'replace 'reverse 'nreverse 'search 'sort 'stable-sort 
+        'subseq 'substitute 'nsubstitute 'substitute-if 'nsubstitute-if 'substitute-if-not 
+        'nsubstitute-if-not))
+
+(defParameter *sequences*
+  (make-submenu-item "sequences" *sequences-symbol-list*))
+
+;;; ----------------------------------------------------------------------------
+;;;
+(defParameter *hash-tables-symbol-list*
+  (list 'clrhash 'gethash 'hash-table-count 'hash-table-p 'hash-table-rehash-size 'hash-table-rehash-threshold 'hash-table-size 'hash-table-test 'make-hash-table 'maphash 'remhash 'sxhash 'with-hash-table-iterator))
+
+(defParameter *hash-tables*
+  (make-submenu-item "hash tables" *hash-tables-symbol-list*))
+
+;;; ----------------------------------------------------------------------------
+;;;
+(defParameter *filenames-symbol-list*
+  (list 'directory-namestring 'enough-namestring 'file-namestring 'host-namestring 
+        'load-logical-pathname-translations 'logical-pathname 'logical-pathname-translations 
+        'make-pathname 'merge-pathnames 'namestring 'parse-namestring 'pathname 'pathname-host 
+        'pathname-device 'pathname-directory 'pathname-match-p 'pathname-name 'pathnamep 
+        'pathname-type 'pathname-version 'translate-logical-pathname 'translate-pathname 
+        'wild-pathname-p))
+
+(defParameter *filenames*
+  (make-submenu-item "filenames" *filenames-symbol-list*))
+
+;;; ----------------------------------------------------------------------------
+;;;
+(defParameter *files-symbol-list*
+  (list 'delete-file 'directory 'ensure-directories-exist 'file-author 'file-error-pathname 
+        'file-write-date 'probe-file 'rename-file 'truename))
+
+(defParameter *files*
+  (make-submenu-item "files" *files-symbol-list*))
+
+;;; ----------------------------------------------------------------------------
+;;;
+(defParameter *streams-symbol-list*
+  (list 'broadcast-stream-streams 'clear-input 'clear-output 'close 'concatenated-stream-streams 
+        'echo-stream-input-stream 'echo-stream-output-stream 'file-length 'file-position 
+        'file-string-length 'finish-output 'force-output 'fresh-line 'get-output-stream-string 
+        'input-stream-p 'interactive-stream-p 'listen 'make-broadcast-stream 
+        'make-concatenated-stream 'make-echo-stream 'make-string-input-stream 
+        'make-string-output-stream 'make-synonym-stream 'make-two-way-stream 'open 
+        'open-stream-p 'output-stream-p 'peek-char 'read-byte 'read-char 'read-char-no-hang 
+        'read-line 'read-sequence 'stream-element-type 'stream-error-stream 
+        'stream-external-format 'streamp 'synonym-stream-symbol 'terpri 
+        'two-way-stream-input-stream 'two-way-stream-output-stream 'unread-char 
+        'with-input-from-string 'with-open-file 'with-open-stream 'with-output-to-string 
+        'write-byte 'write-char 'write-line 'write-sequence 'write-string 'yes-or-no-p 'y-or-n-p))
+
+(defParameter *streams*
+  (make-submenu-item "streams" *streams-symbol-list*))
+
+;;; ----------------------------------------------------------------------------
+;;;
+(defParameter *printer-symbol-list*
+  (list 'copy-pprint-dispatch 'format 'formatter 'pprint 'pprint-dispatch 
+        'pprint-exit-if-list-exhausted 'pprint-fill 'pprint-indent 'pprint-linear 
+        'pprint-logical-block 'pprint-newline 'pprint-pop 'pprint-tab 'pprint-tabular 'princ 
+        'princ-to-string 'print 'print-object 'print-not-readable-object 'print-unreadable-object 
+        'prin1 'prin1-to-string 'set-pprint-dispatch 'write 'write-to-string))
+
+(defParameter *printer*
+  (make-submenu-item "printer" *printer-symbol-list*))
+
+;;; ----------------------------------------------------------------------------
+;;;
+(defParameter *reader-symbol-list*
+  (list 'copy-readtable 'get-dispatch-macro-character 'get-macro-character 
+        'make-dispatch-macro-character 'read 'read-delimited-list 'read-from-string 
+        'read-preserving-whitespace 'readtable-case 'readtablep 'set-dispatch-macro-character 
+        'set-macro-character 'set-syntax-from-char 'with-standard-io-syntax))
+
+(defParameter *reader*
+  (make-submenu-item "reader" *reader-symbol-list*))
+
+;;; ----------------------------------------------------------------------------
+;;;
+(defParameter *system-construction-symbol-list*
+  (list 'copy-readtable 'get-dispatch-macro-character 'get-macro-character 
+        'make-dispatch-macro-character 'read 'read-delimited-list 'read-from-string 
+        'read-preserving-whitespace 'readtable-case 'readtablep 'set-dispatch-macro-character 
+        'set-macro-character 'set-syntax-from-char 'with-standard-io-syntax))
+
+(defParameter *system-construction*
+  (make-submenu-item "system construction" *system-construction-symbol-list*))
+
+;;; ----------------------------------------------------------------------------
+;;;
+(defParameter *environment-symbol-list*
+  (list 'apropos 'apropos-list 'decode-universal-time 'describe 'describe-object 'disassemble 
+        'documentation 'dribble 'ed 'encode-universal-time 'get-decoded-time 
+        'get-internal-real-time 'get-internal-run-time 'get-universal-time 'inspect 
+        'lisp-implementation-type 'lisp-implementation-version 'long-site-name 'machine-instance 
+        'machine-type 'machine-version 'room 'short-site-name 'sleep 'software-type 
+        'software-version 'step 'time 'trace 'untrace 'user-homedir-pathname))
+
+(defParameter *environment*
+  (make-submenu-item "environment" *environment-symbol-list*))
+
+;;; ----------------------------------------------------------------------------
+;;;
+(defParameter *constants-and-variables-symbol-list*
+  (list 'array-dimension-limit 'array-rank-limit 'array-total-size 'boole-1 '*break-on-signals* 
+        'call-arguments-limit 'char-code-limit '*compile-file-pathname* '*compile-file-truename* 
+        '*compile-print* '*compile-verbose* '*debug-io* '*debugger-hook* 
+        '*default-pathname-defaults* 'short-float-epsilon 'single-float-epsilon 
+        'double-float-epsilon 'long-float-epsilon 'short-float-negative-epsilon 
+        'single-float-negative-epsilon 'double-float-negative-epsilon 
+        'long-float-negative-epsilon '*error-output* '*features* '*gensym-counter* 
+        'internal-time-units-per-second 'lambda-list-keywords 'lambda-parameters-limit 
+        'least-negative-short-float 'least-negative-single-float 'least-negative-double-float 
+        'least-negative-long-float 'least-negative-normalized-short-float 
+        'least-negative-normalized-single-float 'least-negative-normalized-double-float 
+        'least-negative-normalized-long-float 'least-positive-short-float 
+        'least-positive-single-float 'least-positive-double-float 'least-positive-long-float
+        'least-positive-normalized-short-float 'least-positive-normalized-single-float 
+        'least-positive-normalized-double-float 'least-positive-normalized-long-float
+        '*load-pathname* '*load-print* '*load-truename* '*load-verbose* '*macroexpand-hook* 
+        '*modules* 'most-negative-fixnum 'most-negative-short-float 'most-negative-single-float 
+        'most-negative-double-float 'most-negative-long-float 'most-positive-fixnum
+        'most-positive-short-float 'most-positive-single-float 'most-positive-double-float 
+        'most-positive-long-float 'multiple-values-limit 'nil '*package* 'pi '*print-array* 
+        '*print-base* '*print-case* '*print-circle* '*print-escape* '*print-gensym* 
+        '*print-length* '*print-level* '*print-lines* '*print-miser-width* 
+        '*print-pprint-dispatch* '*print-pretty* '*print-radix* '*print-readably* 
+        '*print-right-margin* '*query-io* '*random-state* '*read-base* 
+        '*read-default-float-format* '*read-eval* '*read-suppress* '*readtable* 
+        '*standard-input* '*standard-output* 't '*terminal-io* '*trace-output* 
+        '* '** '*** '+ '++ '+++ '- '/ '// '///))
+
+(defParameter *constants-and-variables*
+  (make-submenu-item "constants and variables" *constants-and-variables-symbol-list*))
+
+;;; ----------------------------------------------------------------------------
+;;;
+(defParameter *type-specifiers-symbol-list*
+  (list 'and 'array 'simple-array 'base-string 'simple-base-string 'bit-vector 'simple-bit-vector 
+        'complex 'cons 'eql 'float 'short-float 'single-float 'double-float 'long-float 'function 
+        'integer 'member 'mod 'not 'or 'rational 'real 'satisfies 'signed-byte 'string 
+        'simple-string 'unsigned-byte 'values 'vector 'simple-vector))
+
+(defParameter *type-specifiers*
+  (make-submenu-item "type specifiers" *type-specifiers-symbol-list*))
+
+;;; ----------------------------------------------------------------------------
+;;;
+(defun add-cl-documentation-submenus (menu)
+  (let ((submenus '(*evaluation-and-compilation* *types-and-classes* 
+                                                 *control-and-data-flow* *iteration* *objects* *structures* 
+                                                 *conditions* *symbols* *packages* *numbers* *characters* 
+                                                 *conses* *arrays* *strings* *sequences* *hash-tables* 
+                                                 *filenames* *files* *streams* *printer* *reader* 
+                                                 *system-construction* *environment* *constants-and-variables* 
+                                                 *type-specifiers*)))
+    (dolist (submenu submenus)
+      (#/addItem: menu (symbol-value submenu)))))
+
+;;; ----------------------------------------------------------------------------
+;;;
+(defParameter *cl-symbol-lists*
+  (list 
+   *evaluation-and-compilation-symbol-list* *types-and-classes-symbol-list* 
+   *control-and-data-flow-symbol-list* *iteration-symbol-list* *objects-symbol-list* 
+   *structures-symbol-list* *conditions-symbol-list* *symbols-symbol-list* *packages-symbol-list* 
+   *numbers-symbol-list* *characters-symbol-list* *conses-symbol-list* *arrays-symbol-list* 
+   *strings-symbol-list* *sequences-symbol-list* *hash-tables-symbol-list* *filenames-symbol-list* 
+   *files-symbol-list* *streams-symbol-list* *printer-symbol-list* *reader-symbol-list* 
+   *system-construction-symbol-list* *environment-symbol-list* 
+   *constants-and-variables-symbol-list* *type-specifiers-symbol-list*))
+
+;;; ----------------------------------------------------------------------------
+;;;
+(defun test-symbol-list (sym-list &optional package)
+  (dolist (sym (rest sym-list))
+    (unless (find-symbol (string-upcase (format nil "~A" sym)) (or package :cl))
+      (format t "~%~A" sym))))
+
+;;; (dolist (list *cl-symbol-lists*) (test-symbol-list list)) 
+
+(add-cl-documentation-submenus *cl-documentation-menu*)
+
+(defun get-cl-documentation-menu (view event) 
+  (cond ((logtest #$NSCommandKeyMask (#/modifierFlags event))
+         (setf (text-view *cl-alphabetical-menu*) view)           
+         *cl-alphabetical-menu*)
+        (t
+         (setf (text-view *cl-documentation-menu*) view)           
+         *cl-documentation-menu*)))
+
+(cmenu:register-tool "CL-Documentation-CM" #'get-cl-documentation-menu)
Index: /trunk/contrib/foy/context-menu-cm/context-menu-cm.lisp
===================================================================
--- /trunk/contrib/foy/context-menu-cm/context-menu-cm.lisp	(revision 13946)
+++ /trunk/contrib/foy/context-menu-cm/context-menu-cm.lisp	(revision 13946)
@@ -0,0 +1,22 @@
+
+;;; context-menu-cm.lisp 
+
+(in-package :common-lisp-user)
+
+(unless (member "CONTEXT-MENU-CM" *modules* :test #'string-equal)
+  
+(eval-when (:load-toplevel :execute)
+  (defParameter *context-menu-directory*
+    (make-pathname :name nil :type nil :defaults (if *load-pathname* 
+                                                     *load-pathname*
+                                                     *loading-file-source-file*)))
+  (defParameter *context-menu-files* 
+    (list (merge-pathnames ";context-menu.lisp" *context-menu-directory*)
+          (merge-pathnames ";context-menu-dialogs.lisp" *context-menu-directory*))))
+ 
+(dolist (file *context-menu-files*)
+  (load file))
+
+(provide :context-menu-cm)
+
+)
Index: /trunk/contrib/foy/context-menu-cm/context-menu-dialogs.lisp
===================================================================
--- /trunk/contrib/foy/context-menu-cm/context-menu-dialogs.lisp	(revision 13946)
+++ /trunk/contrib/foy/context-menu-cm/context-menu-dialogs.lisp	(revision 13946)
@@ -0,0 +1,184 @@
+;;; ----------------------------------------------------------------------------
+;;;
+;;;      context-menu-dialogs.lisp
+;;;
+;;;      copyright (c) 2009 Glen Foy
+;;;      (Permission is granted to Clozure Associates to distribute this file.)
+;;;
+;;;      Utilities and dialogs for the Context-Menu tool set.
+;;;
+;;;      The API for writing new tools is described in the accompanying NewTools file.
+;;;
+;;;      This software is offered "as is", without warranty of any kind.
+;;;
+;;;      Mod History, most recent first:
+;;;      9/14/9  First cut
+;;;
+;;; ----------------------------------------------------------------------------
+
+(defpackage "CONTEXT-MENU" (:nicknames "CMENU") (:use :cl :ccl))
+(in-package "CONTEXT-MENU")
+
+(export '(notify window-with-path active-hemlock-window window-path echo-msg))
+
+(defparameter *clozure-jpg* (merge-pathnames ";Clozure.jpg" cl-user::*context-menu-directory*))
+(defparameter *graphic-p* t "To use, or not to use the Clozure graphic.")
+
+
+(defun active-hemlock-window ()
+  "Return the active hemlock-frame."
+  (gui::first-window-satisfying-predicate 
+   #'(lambda (w)
+       (and (typep w 'gui::hemlock-frame)
+            (not (typep w 'gui::hemlock-listener-frame))
+            (#/isKeyWindow w)))))
+
+(defun window-path (w)
+  "Return the window's path."
+  (let* ((pane (slot-value w 'gui::pane))
+         (hemlock-view (when pane (gui::text-pane-hemlock-view pane)))
+         (buffer (when hemlock-view (hi::hemlock-view-buffer hemlock-view))))
+    (when buffer (hi::buffer-pathname buffer))))
+
+;;; This includes a work-around for what appears to be a bug in the hemlock-frame
+;;; #/close method.  After a #/close, the window remains on the (#/orderedWindows *NSApp*)
+;;; list, but (hi::buffer-document buffer) in NIL.  Therefore the extra tests:
+(defun window-with-path (path)
+  "If a window with PATH is open, return it."
+  (gui::first-window-satisfying-predicate 
+   #'(lambda (w)
+       (when (and (typep w 'gui::hemlock-frame)
+                  (not (typep w 'gui::hemlock-listener-frame)))
+         (let* ((pane (slot-value w 'gui::pane))
+                (text-view (gui::text-pane-text-view pane))
+                (buffer (gui::hemlock-buffer text-view))
+                (document (when buffer (hi::buffer-document buffer)))
+                (p (hi::buffer-pathname buffer)))
+           (when (and document p) (string-equal path p)))))))
+
+(defun echo-msg (string &rest args)
+  (let* ((window (cmenu:active-hemlock-window))
+         (hemlock-view (when window (gui::hemlock-view window))))
+    (when hemlock-view
+      (let ((hi::*current-view* hemlock-view))
+        (hi::message string args)))))
+
+(defun notify (message &rest args)
+  "FYI"
+  (let ((message-string (apply #'format nil message args)))
+    (if *graphic-p*
+      (open-notification-dialog message-string)
+      (gui::alert-window :title "Notification" :message message-string))))
+
+(defparameter *notify-dialog* nil "The notification-dialog instance.")
+
+;;; ----------------------------------------------------------------------------
+;;;
+(defclass NOTIFICATION-DIALOG (ns:ns-window)
+  ((message-field :initform nil :accessor nd-message-field)
+   (okay-button :initform nil :accessor nd-okay-button))
+  (:documentation "A dialog for displaying messages.")
+  (:metaclass ns:+ns-object))
+
+(objc:defmethod (#/okayAction: :void) ((d notification-dialog) (sender :id))
+  (declare (ignore sender))
+  (#/stopModalWithCode: ccl::*nsapp* 0))
+
+(defun open-notification-dialog (message)
+  "Open the notification-dialog and display MESSAGE."
+  (let ((message-string (#/initWithString:attributes: (#/alloc ns:ns-attributed-string) 
+                                                      (ccl::%make-nsstring message)
+                                                      cmenu::*tool-doc-dictionary*)))
+    (cond (*notify-dialog*
+           (#/setStringValue: (nd-message-field *notify-dialog*) message-string)
+           (#/makeKeyAndOrderFront: *notify-dialog* nil)
+           (#/runModalForWindow: ccl::*nsapp* *notify-dialog*)
+           (#/close *notify-dialog*))
+          (t
+           (let ((dialog (#/alloc notification-dialog)))
+             (setq *notify-dialog* dialog)
+             (ns:with-ns-rect (r 10 300 400 127)
+               (#/initWithContentRect:styleMask:backing:defer: 
+                dialog
+                r
+                #$NSTitledWindowMask 
+                #$NSBackingStoreBuffered
+                #$NO))
+             (dolist (item (get-notify-items dialog))
+               (#/addSubview: (#/contentView dialog) item))
+             (#/setTitle: dialog #@"Notification")
+             (#/setReleasedWhenClosed: dialog nil)
+             (#/setDefaultButtonCell: dialog (nd-okay-button dialog))
+             (#/setStringValue: (nd-message-field dialog) message-string)
+             (#/center dialog)
+             (#/makeKeyAndOrderFront: dialog nil)
+             (#/runModalForWindow: ccl::*nsapp* dialog)
+             (#/close dialog))))))
+
+#|
+(open-notification-dialog "foobear")
+|#
+
+(defmethod get-notify-items ((d notification-dialog))
+  (append
+   (make-notify-graphic)
+   ;; (make-notify-prompt)
+   (make-notify-message d)
+   (make-notify-button d)))
+
+(defun make-notify-graphic ()
+  "Create the Clozure graphic."
+  (when (probe-file *clozure-jpg*)
+    (let ((image (#/alloc ns:ns-image))
+          (image-view (#/alloc ns:ns-image-view)))
+      (ns:with-ns-rect (frame 0 0 108 127)
+        (#/initWithFrame: image-view frame))
+      (#/setImageScaling: image-view #$NSScaleToFit)
+      (#/initWithContentsOfFile: image (ccl::%make-nsstring (namestring *clozure-jpg*)))
+      (#/setImage: image-view image)
+      (list image-view))))
+
+(defun make-notify-prompt ()
+  "Create the prompt text-field."
+  (list
+   (let* ((string (#/initWithString:attributes: 
+                   (#/alloc ns:ns-attributed-string) 
+                   #@"Notification"
+                   cmenu::*tool-label-dictionary*))
+          (title (#/alloc ns:ns-text-field)))
+     (ns:with-ns-rect (frame 120 90 150 32)
+       (#/initWithFrame: title frame))
+     (#/setEditable: title nil)
+     (#/setDrawsBackground: title nil)
+     (#/setBordered: title nil)
+     (#/setStringValue: title string)
+     title)))
+
+(defun make-notify-message (dialog)
+  "Create the documentation text-view."
+  (list
+   (let ((field (#/alloc ns:ns-text-field)))
+     (ns:with-ns-rect (frame 120 50 270 60)
+       (#/initWithFrame: field frame))
+     (#/setEditable: field nil)
+     (#/setDrawsBackground: field nil)
+     (#/setBordered: field nil)
+     (setf (nd-message-field dialog) field))))
+
+(defun make-notify-button (dialog)
+  "Construct the button."
+  (list
+   (let ((button (#/alloc ns:ns-button)))
+     (ns:with-ns-rect (frame 310 10 80 32)
+       (#/initWithFrame: button frame))
+     (#/setButtonType: button #$NSMomentaryPushInButton)
+     (#/setBezelStyle: button #$NSRoundedBezelStyle)
+     (#/setTitle: button #@"Okay")
+     (#/setTarget: button dialog)
+     (#/setAction: button (ccl::@selector "okayAction:"))
+     (setf (nd-okay-button dialog) button))))
+
+
+
+
+
Index: /trunk/contrib/foy/context-menu-cm/context-menu.lisp
===================================================================
--- /trunk/contrib/foy/context-menu-cm/context-menu.lisp	(revision 13946)
+++ /trunk/contrib/foy/context-menu-cm/context-menu.lisp	(revision 13946)
@@ -0,0 +1,204 @@
+;;;-*-Mode: LISP; Package: CONTEXT-MENU -*-
+
+;;; ----------------------------------------------------------------------------
+;;;
+;;;      context-menu.lisp
+;;;
+;;;      copyright (c) 2009 Glen Foy
+;;;      (Permission is granted to Clozure Associates to distribute this file.)
+;;;
+;;;      This code provides a mechanism for switching the tool that has access to 
+;;;      Hemlock's contextual popup menu.  This is an initial prototype, implementing
+;;;      what may be the simplest approach.
+;;;
+;;;      The API for writing new tools is described in the accompanying NewTools file.
+;;;
+;;;      This software is offered "as is", without warranty of any kind.
+;;;
+;;;      Mod History, most recent first:
+;;;      9/2/9   Changed the appearance of the Default Tool submenu.
+;;;      8/31/9  version 0.1b1
+;;;              First cut
+;;;              Numerous User Interface suggestions, Rainer Joswig
+;;;
+;;; ----------------------------------------------------------------------------
+
+(defpackage "CONTEXT-MENU" (:nicknames "CMENU") (:use :cl :ccl))
+(in-package "CONTEXT-MENU")
+
+(export '(register-tool add-default-tool-menu update-tool-menu set-default-tool
+          tool-menu *hemlock-menu-dictionary* *tool-label-dictionary* *tool-doc-dictionary*
+          *tool-key-dictionary* *dark-blue-color* *dark-turquoise-color* *light-gray-color* 
+          *wine-red-color* check-hyperspec-availability))
+
+(defparameter *menu-manager* nil "The context-menu-manager instance.")
+
+(defparameter *dark-blue-color* (#/colorWithCalibratedRed:green:blue:alpha: ns:ns-color 0.2 0.2 0.5 1.0))
+(defparameter *dark-turquoise-color* (#/colorWithCalibratedRed:green:blue:alpha: ns:ns-color 0.0 0.28 0.28 1.0))
+(defparameter *wine-red-color* (#/colorWithCalibratedRed:green:blue:alpha: ns:ns-color 0.4 0.1 0.2 1.0))
+(defparameter *light-gray-color* (#/colorWithCalibratedRed:green:blue:alpha: ns:ns-color 0.92 0.92 0.92 1.0))
+
+(defparameter *hemlock-menu-dictionary* (make-instance 'ns:ns-mutable-dictionary :with-capacity 2))
+(#/setObject:forKey: *hemlock-menu-dictionary* (#/systemFontOfSize: ns:ns-font (#/smallSystemFontSize ns:ns-font)) #&NSFontAttributeName)
+(#/setObject:forKey: *hemlock-menu-dictionary* *dark-blue-color* #&NSForegroundColorAttributeName)
+
+(defparameter *tool-label-dictionary* (make-instance 'ns:ns-mutable-dictionary :with-capacity 2))
+(#/setObject:forKey: *tool-label-dictionary* (#/systemFontOfSize: ns:ns-font (#/systemFontSize ns:ns-font)) #&NSFontAttributeName)
+(#/setObject:forKey: *tool-label-dictionary* *dark-turquoise-color* #&NSForegroundColorAttributeName)
+
+(defparameter *tool-doc-dictionary* (make-instance 'ns:ns-mutable-dictionary :with-capacity 2))
+(#/setObject:forKey: *tool-doc-dictionary* (#/systemFontOfSize: ns:ns-font (#/smallSystemFontSize ns:ns-font)) #&NSFontAttributeName)
+(#/setObject:forKey: *tool-doc-dictionary* *dark-turquoise-color* #&NSForegroundColorAttributeName)
+
+(defparameter *tool-key-dictionary* (make-instance 'ns:ns-mutable-dictionary :with-capacity 2))
+(#/setObject:forKey: *tool-key-dictionary* (#/systemFontOfSize: ns:ns-font (#/smallSystemFontSize ns:ns-font)) #&NSFontAttributeName)
+(#/setObject:forKey: *tool-key-dictionary* *wine-red-color* #&NSForegroundColorAttributeName)
+
+;;; ----------------------------------------------------------------------------
+;;;
+(defclass CONTEXT-MENU-MANAGER ()
+  ((tool-alist :initform nil :accessor tool-alist)
+   (default-tool :initform nil :accessor default-tool))
+  (:documentation "A class to manage Hemlock's contextual popup menu, supporting access by multiple tools."))
+
+(defmethod display-menu ((manager context-menu-manager) view event)
+  (when (default-tool manager)
+    (let ((entry (assoc (default-tool manager) (tool-alist manager) :test #'string-equal)))
+      (when entry 
+        (funcall (cdr entry) view event)))))
+
+(objc:defmethod #/menuForEvent: ((view gui::hemlock-text-view) (event :id))
+  (display-menu *menu-manager* view event))
+
+(defun register-tool (tool-name menu-function)
+  "Register the new tool with the menu-manager.  The last tool registered becomes the default tool."
+  (let ((entry (find tool-name (tool-alist *menu-manager*) :test #'string-equal :key #'car)))
+    (cond (entry
+           (gui::alert-window :title "Notification" :message (format nil "Re-registering ~S." tool-name))
+           (setf (tool-alist *menu-manager*) (delete tool-name (tool-alist *menu-manager*) :test #'string-equal :key #'car))
+           (setf (tool-alist *menu-manager*) (cons (cons tool-name menu-function) (tool-alist *menu-manager*))))           
+          (t
+           (setf (tool-alist *menu-manager*) (cons (cons tool-name menu-function) (tool-alist *menu-manager*)))
+           (setf (tool-alist *menu-manager*)
+                 (sort (tool-alist *menu-manager*) #'string< :key #'car))
+           (set-default-tool tool-name)))))
+
+(defun set-default-tool (tool-name)
+  "Set the menu-manager's default tool.  Right-Click will display this tool's menu."
+  (let ((registered-name (car (find tool-name (tool-alist *menu-manager*) :test #'string-equal :key #'car))))
+    (if registered-name
+      (setf (default-tool *menu-manager*) registered-name) ; keep the original capitalization
+      (gui::alert-window :title "Notification" :message (format nil "~S is not a registered tool.  It can't be set as default." tool-name)))))
+
+;;; ----------------------------------------------------------------------------
+;;;
+(defclass DEFAULT-TOOL-MENU-ITEM (ns:ns-menu-item)
+  ((name :accessor tool-name)) ; Lisp string
+  (:documentation "Support for the Tool submenu.")
+  (:metaclass ns:+ns-object))
+
+;;; ----------------------------------------------------------------------------
+;;;
+(defclass DEFAULT-TOOL-DOC-MENU-ITEM (ns:ns-menu-item)
+  ((filename :accessor tool-filename))
+  (:documentation "A menu-item to display the default tool's documentation.")
+  (:metaclass ns:+ns-object))
+
+;;; ----------------------------------------------------------------------------
+;;;
+(defclass DEFAULT-TOOL-MENU (ns:ns-menu)
+  ()
+  (:documentation "A submenu displaying all registered tools.")
+  (:metaclass ns:+ns-object))
+
+(objc:defmethod (#/hemlockDefaultToolAction: :void) ((m default-tool-menu) (sender :id))
+  (set-default-tool (tool-name sender)))
+
+(objc:defmethod (#/hemlockDefaultToolDocAction: :void) ((m default-tool-menu) (sender :id))
+  (display-doc (tool-filename sender)))
+
+(defun display-doc (path)
+  "Display the default tool's documentation."
+  (when (probe-file path)
+    (#/openFile:withApplication: (#/sharedWorkspace ns:ns-workspace) 
+                                 (ccl::%make-nsstring (namestring path))
+                                 (ccl::%make-nsstring "TextEdit"))))
+  
+(defmethod populate-menu ((menu default-tool-menu))
+  (dotimes (count (#/numberOfItems menu))
+    (#/removeItemAtIndex: menu 0))
+  (flet ((create-menu-item (name)
+           (let ((menu-item (make-instance 'default-tool-menu-item))
+                 (attributed-string (#/initWithString:attributes:
+                                     (#/alloc ns:ns-attributed-string) 
+                                     (ccl::%make-nsstring name)
+                                     *tool-label-dictionary*)))
+             (setf (tool-name menu-item) name) 
+             (#/setAttributedTitle: menu-item attributed-string)
+             (#/setAction: menu-item (ccl::@selector "hemlockDefaultToolAction:"))
+             (#/setTarget: menu-item  menu)
+             (if (string-equal name (default-tool *menu-manager*))
+               (#/setState: menu-item #$NSOnState)
+               (#/setState: menu-item #$NSOffState))
+             (#/addItem: menu menu-item))))
+    (dolist (entry (tool-alist *menu-manager*))
+      (create-menu-item (car entry)))))
+
+(defun add-default-tool-menu (menu &key doc-file)
+  "Add the default tool submenu and possibly a documentation menu-item to MENU."
+  (let ((default-item (make-instance ns:ns-menu-item))
+        (tool-menu (make-instance 'default-tool-menu)))
+    ;; Title is set by update method.
+    (#/setSubmenu: default-item tool-menu)
+    (#/insertItem:atIndex: menu default-item 0)
+    (cond (doc-file
+           (let ((doc-item (make-instance 'default-tool-doc-menu-item))
+                 (attributed-string (#/initWithString:attributes:
+                                     (#/alloc ns:ns-attributed-string) 
+                                     (ccl::%make-nsstring (format nil "~A     doc..." (default-tool *menu-manager*)))
+                                     *tool-doc-dictionary*)))
+             (#/setAttributedTitle: doc-item attributed-string)
+             (#/setAction: doc-item (ccl::@selector "hemlockDefaultToolDocAction:"))
+             (#/setTarget: doc-item  tool-menu)
+             (setf (tool-filename doc-item) doc-file)
+             (#/insertItem:atIndex: menu doc-item 1))
+          (#/insertItem:atIndex: menu (#/separatorItem ns:ns-menu-item) 2))
+          (t
+           (#/insertItem:atIndex: menu (#/separatorItem ns:ns-menu-item) 1)))
+    tool-menu))
+
+(defun update-tool-menu (menu default-menu &key sub-title)
+  "Update MENU's Tool submenu."
+  (let ((first-item (#/itemAtIndex: menu 0))
+        (attributed-string (#/initWithString:attributes:
+                            (#/alloc ns:ns-attributed-string) 
+                            (if sub-title
+                              (ccl::%make-nsstring (format nil "~S
+    (~A)" (default-tool *menu-manager*) sub-title))
+                              (ccl::%make-nsstring (format nil "~S" (default-tool *menu-manager*))))
+                            *tool-label-dictionary*)))
+    (#/setAttributedTitle: first-item attributed-string)
+    (populate-menu default-menu)))
+
+(let (checked-p)
+(defun check-hyperspec-availability (tool-name)
+  "Some tools require the HyperSpec."
+  (unless (or checked-p gui::*hyperspec-root-url*)
+    (rlet ((perror :id  +null-ptr+))
+      (let* ((map-url (make-instance 'ns:ns-url :with-string #@"Data/Map_Sym.txt" :relative-to-url (gui::hyperspec-root-url)))
+             ;; kludge alert:
+             (data (make-instance 'ns:ns-data
+                     :with-contents-of-url map-url
+                     :options 0
+                     :error perror)))
+        (declare (ignore data))
+        (setq checked-p t)
+        (unless (%null-ptr-p (pref perror :id))
+          (gui::alert-window 
+           :title "Notification" 
+           :message (format nil "~S needs the HyperSpec, and it does not appear to be available. Check the documentation in the Context-Menu-CM/ReadMe, and restart CCL." tool-name))))))))
+
+(setq *menu-manager* (make-instance 'context-menu-manager))
+
+
+
Index: /trunk/contrib/foy/hemlock-commands-cm/MCL-doc.lisp
===================================================================
--- /trunk/contrib/foy/hemlock-commands-cm/MCL-doc.lisp	(revision 13946)
+++ /trunk/contrib/foy/hemlock-commands-cm/MCL-doc.lisp	(revision 13946)
@@ -0,0 +1,4258 @@
+#|
+; Copyright 1987-1988 Coral Software Corp.
+; Copyright 1989-1994 Apple Computer, Inc.
+; Copyright 1995-2001 Digitool, Inc.
+
+; MCL has been released as an open source application, subject to the GLGPL License.
+|#
+
+* 
+"&rest numbers"
+"[Function / Variable]"
+"as a function, multiplies all the numbers, returning the product. As a variable, bound to the last
+value returned by the read loop."
+
+**  
+NIL "[Variable]"
+"bound to the second to last value returned by the read loop."
+
+***  
+NIL "[Variable]"
+"bound to the third to last value returned by the read loop."
+
+*COMPILE-PRINT* 
+NIL "[Variable]"
+"holds the default value for the :print keyword argument to compile. If the value of this variable is t,
+then compile prints the value of each expression compiled to *standard-output*. The default value is
+nil."
+
+*COMPILE-VERBOSE* 
+NIL "[Variable]"
+"holds the default value for the :verbose keyword argument to compile If true, then compile defaults to
+printing the name of each file compiled. If nil, then compile defaults to not printing the names of files
+compiled."
+
+*DEBUG-IO*  
+NIL "[Variable]"
+"the stream used for input and output when operating inside a break loop."
+
+*DEFAULT-PATHNAME-DEFAULTS* 
+NIL "[Variable]" 
+"the default pathname used to supply missing components when pathnames are merged."
+
+*ERROR-OUTPUT*  
+NIL "[Variable]"
+"the stream to which error messages are sent."
+
+*FEATURES*  
+NIL "[Variable]"
+"a list of features present in the current lisp environment. You can add features to this list as you
+bring tools into your environment. The features should be represented as keywords. This variable is
+used by the #+ and #- reader macros."
+
+*LOAD-PRINT*  
+NIL "[Variable]"
+"holds the default value for the :print keyword argument to load. If the value of this variable is t, then
+load prints the value of each expression loaded to *standard-output*. The default value is nil."
+
+*LOAD-TRUENAME*  
+NIL "[Variable]"
+"a variable bound to the true name of the file being loaded. Its initial value is nil."
+
+*LOAD-VERBOSE*  
+NIL "[Variable]"
+"holds the default value for the :verbose keyword argument to load. If true, then load defaults to
+printing the name of each file loaded. If nil, then load defaults to not printing the names of files loaded."
+
+*MACROEXPAND-HOOK*  
+NIL "[Variable]"
+"used by macroexpand-1. Its initial value is funcall."
+
+#|
+*MODULES*  
+NIL "[Variable]"
+"holds a list of the names of the modules that have been loaded into Macintosh Common Lisp. This list is
+used by the functions require and provide. This variable has been removed from Common Lisp and is
+provided in the CCL: package."
+|#
+
+*PACKAGE*  
+NIL "[Variable]"
+"at any point, this variable is bound to the current package. The functions load and compile-file rebind
+*package* to its current value. The forthcoming ANSI Common Lisp will use the package name
+common-lisp-user instead of user."
+
+*PRINT-ARRAY*  
+NIL "[Variable]"
+"controls whether arrays are printed readably. If the value of this variable is nil, the contents of
+arrays other than strings are never printed."
+
+*PRINT-BASE*  
+NIL "[Variable]"
+"specifies the radix to use for printing rational numbers. The default is base 10. Note that this is the
+radix for printing; it doesnÕt affect the radix for reading numbers."
+
+*PRINT-CASE*  
+NIL "[Variable]"
+"controls the case used for printing symbols. The value of *print-case* should be :upcase (the
+default), :downcase, or :capitalize."
+
+*PRINT-CIRCLE*  
+NIL "[Variable]"
+"Controls the printing of data objects which may be circular, such as arrays and lists. If
+*print-circle* is true, then the printer checks for circular structures (which makes printing
+slower). The default is nil."
+
+*PRINT-ESCAPE*  
+NIL "[Variable]"
+"controls the printing of escape characters. If *print-escape* is true (the default), then escape
+characters are printed (which increases the chances that objects will print readably)."
+
+*PRINT-GENSYM*  
+NIL "[Variable]"
+"controls the printing of uninterned symbols. If true, uninterned symbols are printed with the #:
+reader macro; they will not be interned when read into Lisp. If nil, they are not printed with the
+reader macro, and they will be interned when read back in."
+
+*PRINT-LENGTH*  
+NIL "[Variable]"
+"controls how many elements of a list or array are printed. If nil, then the entire data structure is
+printed."
+
+*PRINT-LEVEL*  
+NIL "[Variable]"
+"controls how many levels of a list or array are printed. If nil, then all levels are printed."
+
+*PRINT-LINES*  
+NIL "[Variable]"
+"When the value of this Common Lisp variable is other than nil, it is a limit on the number of output
+lines produced when an object is pretty printed."
+
+*PRINT-PRETTY*  
+NIL "[Variable]"
+"controls the look of printed expressions. If true, then extra whitespace is inserted to make the
+printed representation of forms more readable. For a description of user-controlled pretty-printing
+in Common Lisp, see Common Lisp: The Language, 2d edition, Chapter 27."
+
+*PRINT-RADIX*  
+NIL "[Variable]"
+"controls the printing of radix specifiers for rational numbers. If true, then rational numbers are
+printed with radix specifiers. This ensures that the numbers may be read back into Lisp. The default
+is nil."
+
+*PRINT-READABLY*  
+NIL "[Variable]"
+"If this Common Lisp variable true, objects are printed out such that the printed representation can
+be read back into Lisp to create a similar object. If false, objects may be printed more tersely."
+
+*PRINT-RIGHT-MARGIN*  
+NIL "[Variable]"
+"If non-nil, this Common Lisp variable specifies the right margin to use when the pretty printer is
+making layout decisions."
+
+*QUERY-IO*  
+NIL "[Variable]"
+"the stream used for asking questions of, and receiving answer from, the user."
+
+*RANDOM-STATE*  
+NIL "[Variable]"
+"the default random state object, used by random when it is not explicitly passed a random state."
+
+*READ-BASE*  
+NIL "[Variable]"
+"specifies the radix used when reading rational numbers. Note that this does not affect the radix used
+when printing numbers."
+
+*READ-DEFAULT-FLOAT-FORMAT*  
+NIL "[Constant]"
+"the default floating-point type in which to read floating-point numbers."
+
+*READ-SUPPRESS*  
+NIL "[Variable]"
+"if true, most read operations are suppressed, preventing the reading of Lisp data objects. This
+variable is most often used by the reader macros #+ and #-."
+
+*READTABLE*  
+NIL "[Variable]"
+"holds the default readtable used by read operations."
+
+*STANDARD-INPUT*  
+NIL "[Variable]"
+"the stream from which the top level read-eval-print loop gets its input. This is the default input
+stream used by functions such as read and read-char."
+
+*STANDARD-OUTPUT*  
+NIL "[Variable]"
+"the stream to which the top level read-eval-print loop sends its output. This is also the default
+output stream for functions such as print, write, etc."
+
+*TERMINAL-IO*  
+NIL "[Variable]"
+"the stream which is used for interacting with the user. *terminal-io* is bound to a stream that reads
+from the Listener and other Fred windows, and from forms which have been set up with
+eval-enqueue. It prints to the *standard-output* or one of the other system output streams (such as
+*error-output*)."
+
+*TRACE-OUTPUT*  
+NIL "[Variable]"
+"the stream to which the output of trace is sent. *trace-output* is initially bound to the same stream
+as *terminal-io*, but may be rebound to redirect the output of trace."
+
++ 
+"&rest numbers"
+"[Function / Variable]"
+"as a function, adds all the arguments and returns the sum. As a variable, bound to the last form read
+by the read loop."
+
+++  
+NIL "[Variable]"
+"bound to the second to last form read by the read loop."
+
++++  
+NIL "[Variable]"
+"bound to the third to last form read by the read loop."
+
+- 
+"number &rest more-numbers"
+"[Function / Variable]"
+"as a function subtracts each argument, from left to right, from the result of the previous
+subtraction, and returns the final difference. As a variable, bound to the form currently being
+executed by the read loop."
+
+/ 
+"number &rest more-numbers"
+"[Function / Variable]"
+"as a function divides each argument, from left to right, into the result of the previous division, and
+returns the final quotient. As a variable, bound to a list containing the multiple values last returned
+by the read loop."
+
+//  
+NIL "[Variable]"
+"bound to a list of the second to last set of multiple values returned by the read loop."
+
+///  
+NIL "[Variable]"
+"bound to a list of the third to last set of multiple values returned by the read loop."
+
+/= 
+"number &rest more-numbers"
+"[Function]"
+"returns true if none of the arguments are numerically equal; otherwise returns nil."
+
+1+ 
+"number"
+"[Function]"
+"returns the result of adding 1 to number."
+
+1- 
+"number"
+"[Function]"
+"returns the result of subtracting 1 from number."
+
+< 
+"number &rest more-numbers"
+"[Function]"
+"returns true if each argument is less than the one following it; otherwise returns nil."
+
+<= 
+"number &rest more-numbers"
+"[Function]"
+"returns true if each argument is less than or equal to the one following it; otherwise returns nil."
+
+= 
+"number &rest more-numbers"
+"[Function]"
+"returns true if all the arguments are numerically equal; otherwise returns nil."
+
+> 
+"number &rest more-numbers"
+"[Function]"
+"returns true if each argument is greater than the one following it; otherwise returns nil."
+
+>= 
+"number &rest more-numbers"
+"[Function]"
+"returns true if each argument is greater than or equal to the one following it; otherwise returns nil."
+
+ABORT 
+"&optional condition"
+"[Function]"
+"transfers control to the restart named abort. If no such restart exists, an error is signaled. If
+condition is not nil, only restarts associated with condition are considered."
+
+ABS 
+"number"
+"[Function]"
+"returns the absolute value of number."
+
+ACONS 
+"key datum alist"
+"[Function]"
+"creates a cons with key in the car and datum in the cdr, conses this onto the front of alist, and returns
+the resulting list. alist is not destructively modified."
+
+ACOS 
+"radians"
+"[Function]"
+"returns the arc cosine of radians, a number in radians."
+
+ACOSH 
+"radians"
+"[Function]"
+"returns the hyperbolic arc cosine of radians, a number in radians."
+
+ADJOIN 
+"item list &key :test :test-not :key"
+"[Function]"
+"adds item to list if it is not already a member of list, and returns the resulting list. list is not
+destructively modified."
+
+ADJUST-ARRAY 
+"array new-dimensions &key :element-type :initial-element :initial-contents
+:fill-pointer :displaced-to :displaced-index-offset"
+"[Function]"
+"returns an array of the same type and rank as array, with the specified new-dimensions. This
+function may either alter the given array or create and return a new one."
+
+ADJUSTABLE-ARRAY-P 
+"array"
+"[Function]"
+"returns true if array is adjustable, and nil if it is not."
+
+ALPHA-CHAR-P 
+"char"
+"[Function]"
+"returns true if char is an alphabetic character, otherwise false. char must be a character."
+
+ALPHANUMERICP 
+"char"
+"[Function]"
+"returns true if char is an alphabetic or numeric character, otherwise returns nil. char must be a
+character."
+
+AND 
+"{form}*"
+"[Macro]"
+"evaluates each form sequentially. If and reaches a form that returns nil, it returns nil without
+evaluating any more forms. If it reaches the last form, it returns that form's value."
+
+APPEND 
+"&rest lists"
+"[Function]"
+"concatenates the top-level elements of lists, in effect splicing them together. The lists are not
+modified. Returns the resulting concatenated list."
+
+APPLY 
+"function first-arg &rest more-args"
+"[Function]"
+"invokes function, giving it first-arg and more-args as arguments. The value returned by function is
+returned. The last argument to apply should be a list; the elements of this list are passed as
+individual arguments to function. The type of function can be only symbol or function."
+
+APROPOS 
+"string-or-symbol &optional package"
+"[Function]"
+"finds all interned symbols whose print names contain string-or-symbol as a substring and prints
+the name, function definition, and global value of each symbol. The printing is sent to
+*standard-output*. If package is specified, only the given package is searched. apropos returns no
+values."
+
+APROPOS-LIST 
+"string-or-symbol &optional package"
+"[Function]"
+"returns a list of all available symbols whose print names contain string-or-symbol as a substring.
+If package is specified, only the given package is searched."
+
+AREF 
+"array &rest subscripts"
+"[Function]"
+"returns the element of array specified by subscripts. aref can be used with setf to modify an array."
+
+ARRAY-DIMENSION 
+"array dimension"
+"[Function]"
+"returns the length of dimension of array. Vector fill-pointers are ignored (i.e. the total size,
+including inactive elements, is returned)."
+
+#|
+ARRAY-DIMENSION-LIMIT  
+NIL "[Constant]"
+"The maximum allowable number of elements in a single dimension of an array. This value must be a
+fixnum. Its value in Macintosh Common Lisp is 4194304."
+|#
+
+ARRAY-DIMENSIONS 
+"array"
+"[Function]"
+"returns a list whose elements are the dimensions of array."
+
+ARRAY-ELEMENT-TYPE 
+"array"
+"[Function]"
+"returns a type specifier which describes what data types an element of array may have."
+
+ARRAY-HAS-FILL-POINTER-P 
+"array"
+"[Function]"
+"returns t if array is a vector with a fill pointer. Returns nil if array is not a vector or if array does
+not have a fill pointer."
+
+ARRAY-IN-BOUNDS-P 
+"array &rest subscripts"
+"[Function]"
+"returns true if subscripts are all legal subscripts for array."
+
+ARRAY-RANK 
+"array"
+"[Function]"
+"returns the rank (number of dimensions) of array."
+
+#|
+ARRAY-RANK-LIMIT  
+NIL "[Constant]"
+"a positive integer that is the upper exclusive bound on the rank (number of dimensions) in an array.
+Its value in Macintosh Common Lisp is 8192."
+|#
+
+ARRAY-ROW-MAJOR-INDEX 
+"array &rest subscripts"
+"[Function]"
+"given an array and a valid set of subscripts, returns a single number indicating the position of the
+accessed element based on row-major ordering. This function ignores fill-pointers."
+
+ARRAY-TOTAL-SIZE 
+"array"
+"[Function]"
+"returns the total size of array. This is the product of the sizes of all the dimensions."
+
+#|
+ARRAY-TOTAL-SIZE-LIMIT  
+NIL "[Constant]"
+"a positive integer that is the upper exclusive bound on the total number of elements in an array. Its
+value in Macintosh Common Lisp is 4194304."
+|#
+
+ARRAYP 
+"object"
+"[Function]"
+"returns true if data-object is an array, false if it is not."
+
+ASH 
+"integer count"
+"[Function]"
+"Shifts integer arithmetically left or right by count bits, depending on the sign of count. Bits shifted
+off the right are lost."
+
+ASIN 
+"radians"
+"[Function]"
+"returns the arc sine of radians, a number in radians."
+
+ASINH 
+"radians"
+"[Function]"
+"returns the hyperbolic arc sine of radians, a number in radians."
+
+ASSERT 
+"test-form [({place}*) [string {arg}*]]"
+"[Macro]"
+"signals a continuable error if the value of test-form is nil. If the user continues, the values of some
+variables can be changed, and the assert will start over, evaluating the test-form again. assert
+returns nil."
+
+ASSOC 
+"indicator a-list &key :test :key :test-not"
+"[Function]"
+"searches a-list for the first pair whose car matches indicator. Returns the pair, or nil if the search
+fails."
+
+ASSOC-IF 
+"predicate a-list &key :key"
+"[Function]"
+"searches a-list for the first pair matching :key whose car satisfies predicate. Returns the pair, or
+nil if the search fails."
+
+ASSOC-IF-NOT 
+"predicate a-list &key :key"
+"[Function]"
+"searches a-list for the first pair matching :key whose car does not satisfy predicate. Returns the
+pair, or nil if the search fails."
+
+ATAN 
+"y &optional x"
+"[Function]"
+"returns the arc tangent of y, either the y-component of a number in radians or the complete number,
+encoded as a point."
+
+ATANH 
+"radians"
+"[Function]"
+"returns the hyperbolic arc tangent of radians, a number in radians."
+
+ATOM 
+"data-object"
+"[Function]"
+"returns true if object is not a cons; otherwise returns false. In general , atom is true of anything that
+is not a list. The one exception is the empty list, which is both a list and an atom."
+
+BIT 
+"bit-array &rest subscripts"
+"[Function]"
+"returns the value of the the bit in bit-array specified by the subscripts."
+
+BIT-AND 
+"bit-array-1 bit-array-2 &optional result-bit-array"
+"[Function]"
+"performs a logical AND of the bits in bit-array-1 and bit-array-2, storing the result into
+result-bit-array. If result-bit-array is not specified, a new bit-array is created to hold the result.
+If result-bit-array is t, the result is stored into bit-array-1. If result-bit-array is a bit array,
+the result is destructively placed into that array."
+
+BIT-ANDC1 
+"bit-array-1 bit-array-2 &optional result-bit-array"
+"[Function]"
+"performs a logical AND of the bits in the complement of bit-array-1 and the bits in bit-array-2,
+storing the result into result-bit-array. If result-bit-array is not specified, a new bit-array is
+created to hold the result. If result-bit-array is t, the result is stored into bit-array-1. If
+result-bit-array is a bit array, the result is destructively placed into that array."
+
+BIT-ANDC2 
+"bit-array-1 bit-array-2 &optional result-bit-array"
+"[Function]"
+"performs a logical AND of the bits in bit-array-1 and the bits in the complement of bit-array-2,
+storing the result into result-bit-array. If result-bit-array is not specified, a new bit-array is
+created to hold the result. If result-bit-array is t, the result is stored into bit-array-1. If
+result-bit-array is a bit array, the result is destructively placed into that array."
+
+BIT-EQV 
+"bit-array-1 bit-array-2 &optional result-bit-array"
+"[Function]"
+"compares the bits in bit-array-1 and bit-array-2; if both are 1s or both are 0s, a 1 is stored into
+result-bit-array (otherwise a 0 is stored into result-bit-array). If result-bit-array is not
+specified, a new bit-array is created to hold the result. If result-bit-array is t, the result is stored
+into bit-array-1. If result-bit-array is a bit array, the result is destructively placed into that
+array."
+
+BIT-IOR 
+"bit-array-1 bit-array-2 &optional result-bit-array"
+"[Function]"
+"performs a logical inclusive OR of the bits in bit-array-1 and bit-array-2, storing the result into
+result-bit-array. If result-bit-array is not specified, a new bit-array is created to hold the result.
+If result-bit-array is t, the result is stored into bit-array-1. If result-bit-array is a bit array,
+the result is destructively placed into that array."
+
+BIT-NAND 
+"bit-array-1 bit-array-2 &optional result-bit-array"
+"[Function]"
+"performs a logical NOT-AND of the bits in bit-array-1 and bit-array-2, storing the result into
+result-bit-array. If result-bit-array is not specified, a new bit-array is created to hold the result.
+If result-bit-array is t, the result is stored into bit-array-1. If result-bit-array is a bit array,
+the result is destructively placed into that array."
+
+BIT-NOR 
+"bit-array-1 bit-array-2 &optional result-bit-array"
+"[Function]"
+"performs a logical NOT-OR of the bits in bit-array-1 and bit-array-2, storing the result into
+result-bit-array. If result-bit-array is not specified, a new bit-array is created to hold the result.
+If result-bit-array is t, the result is stored into bit-array-1. If result-bit-array is a bit array,
+the result is destructively placed into that array."
+
+BIT-NOT 
+"source-bit-array &optional result-bit-array"
+"[Function]"
+"stores the contents of source-bit-array, with all the bits inverted, into result-bit-array. If
+result-bit-array is not specified, a new bit array is created. If result-bit-array is t, the result is
+stored in source-bit-array. If result-bit-array is a bit array, the result is destructively placed
+into that array."
+
+BIT-ORC1 
+"bit-array-1 bit-array-2 &optional result-bit-array"
+"[Function]"
+"performs a logical OR of the bits in the complement of bit-array-1 and the bits of bit-array-2,
+storing the result into result-bit-array. If result-bit-array is not specified, a new bit-array is
+created to hold the result. If result-bit-array is t, the result is stored into bit-array-1. If
+result-bit-array is a bit array, the result is destructively placed into that array."
+
+BIT-ORC2 
+"bit-array-1 bit-array-2 &optional result-bit-array"
+"[Function]"
+"performs a logical OR of the bits in bit-array-1 and the bits in the complement of bit-array-2,
+storing the result into result-bit-array. If result-bit-array is not specified, a new bit-array is
+created to hold the result. If result-bit-array is t, the result is stored into bit-array-1. If
+result-bit-array is a bit array, the result is destructively placed into that array."
+
+BIT-VECTOR-P 
+"thing"
+"[Function]"
+"returns true if thing is a bit-vector."
+
+BIT-XOR 
+"bit-array-1 bit-array-2 &optional result-bit-array"
+"[Function]"
+"performs a logical exclusive OR of the bits in bit-array-1 and bit-array-2, storing the result into
+result-bit-array. If result-bit-array is not specified, a new bit-array is created to hold the result.
+If result-bit-array is t, the result is stored into bit-array-1. If result-bit-array is a bit array,
+the result is destructively placed into that array."
+
+BLOCK 
+"name {form} *"
+"[Special Form]"
+"establishes a lexical construct named name in which the forms are evaluated sequentially. The block
+may be exited at any time by calling return-from with the argument name. Block returns the value
+of the last form, or the value passed to return-from."
+
+BOOLE 
+"op integer-1 integer-2"
+"[Function]"
+"applies the logical operation indicated by op to integer-1 and integer-2."
+
+BOOLE-1  
+NIL "[Constant]"
+"Constant used by the boole function. boole will return 1 for each bit in the first integer argument
+which is 1."
+
+BOOLE-2  
+NIL "[Constant]"
+"Constant used by the boole function. boole will return 1 for each bit in the second integer argument
+which is 1."
+
+BOOLE-AND  
+NIL "[Constant]"
+"Constant used by the boole function. boole will return the logical and of the two integer arguments."
+
+BOOLE-ANDC1  
+NIL "[Constant]"
+"Constant used by the boole function. boole will return the and complement of the first integer
+argument with the second integer argument."
+
+BOOLE-ANDC2  
+NIL "[Constant]"
+"Constant used by the boole function. boole will return the and complement of the second integer
+argument with the first integer argument."
+
+BOOLE-C1  
+NIL "[Constant]"
+"Constant used by the boole function. boole will return the complement of the first integer argument."
+
+BOOLE-C2  
+NIL "[Constant]"
+"Constant used by the boole function. boole will return the complement of the second integer argument."
+
+BOOLE-CLR  
+NIL "[Constant]"
+"Constant used by the boole function. boole will return 0."
+
+BOOLE-EQV  
+NIL "[Constant]"
+"Constant used by the boole function. boole will return the exclusive nor of the integer arguments."
+
+BOOLE-IOR  
+NIL "[Constant]"
+"Constant used by the boole function. boole will return the inclusive or of the integer arguments."
+
+BOOLE-NAND  
+NIL "[Constant]"
+"Constant used by the boole function. boole will return the not-and of the integer arguments."
+
+BOOLE-NOR  
+NIL "[Constant]"
+"Constant used by the boole function. boole will return the not-or of the integer arguments."
+
+BOOLE-ORC1  
+NIL "[Constant]"
+"Constant used by the boole function. boole will return the or complement of the first integer
+argument with the second integer argument."
+
+BOOLE-ORC2  
+NIL "[Constant]"
+"Constant used by the boole function. boole will return the or complement of the second integer
+argument with the first integer argument."
+
+BOOLE-SET  
+NIL "[Constant]"
+"Constant used by the boole function. boole will return 1."
+
+BOOLE-XOR  
+NIL "[Constant]"
+"Constant used by the boole function. boole will return exclusive or of the integer arguments."
+
+BOTH-CASE-P 
+"char"
+"[Function]"
+"returns true if char has both a lowercase and and uppercase version. char must be a character."
+
+BOUNDP 
+"symbol"
+"[Function]"
+"returns true if the dynamic (special) variable named by symbol has a value binding, otherwise
+returns nil. boundp does not check for lexical bindings."
+
+BREAK 
+"&optional format-string &rest arguments"
+"[Function]"
+"Prints the message specified by format-string and arguments, sets up a break catch, and enters a
+break loop. The program will resume when the expression (continue) is evaluated (at which point
+break will return nil)."
+
+BUTLAST 
+"list &optional num"
+"[Function]"
+"copies all of list except the last num elements, and returns the new list. num defaults to 1. If list is
+shorter than num, the empty list is returned. list is not modified."
+
+BYTE 
+"size position"
+"[Function]"
+"constructs and returns a byte specifier from size and position."
+
+BYTE-POSITION 
+"bytespec"
+"[Function]"
+"returns the position component of bytespec."
+
+BYTE-SIZE 
+"bytespec"
+"[Function]"
+"returns the size component of bytespec."
+
+CAAAAR 
+"list"
+"[Function]"
+"returns the fourth car of list."
+
+CAAADR 
+"list"
+"[Function]"
+"returns the car of the car of the car of the cdr of list."
+
+CAAAR 
+"list"
+"[Function]"
+"returns the third car of list."
+
+CAADAR 
+"list"
+"[Function]"
+"returns the car of the car of the cdr of the car of list."
+
+CAADDR 
+"list"
+"[Function]"
+"returns the car of the car of the cdr of the cdr of list."
+
+CAADR 
+"list"
+"[Function]"
+"returns the car of the car of the cdr of list."
+
+CAAR 
+"list"
+"[Function]"
+"returns the car of the car of list."
+
+CADAAR 
+"list"
+"[Function]"
+"returns the car of the cdr of the car of the car of list."
+
+CADADR 
+"list"
+"[Function]"
+"returns the car of the cdr of the car of the cdr of list."
+
+CADAR 
+"list"
+"[Function]"
+"returns the car of the cdr of the car of list."
+
+CADDAR 
+"list"
+"[Function]"
+"returns the car of the cdr of the cdr of the car of list."
+
+CADDDR 
+"list"
+"[Function]"
+"returns the car of the cdr of the cdr of the cdr of list."
+
+CADDR 
+"list"
+"[Function]"
+"returns the car of the cdr of the cdr of list."
+
+CADR 
+"list"
+"[Function]"
+"returns the car of the cdr of list. This is the second element of list."
+
+CALL-ARGUMENTS-LIMIT  
+NIL "[Constant]"
+"a positive integer that is the upper exclusive bound on the number of arguments that may be passed to
+a function."
+
+CALL-NEXT-METHOD 
+"&rest args"
+"[Function]"
+"can be used within the body of a method defined by a method-defining form to call the next method.
+The type of method combination used determines which methods can invoke this function and what
+behavior results."
+
+CAR 
+"list"
+"[Function]"
+"returns the first element of list."
+
+CASE 
+"keyform {({({key }*) | key } {form}* ) }*"
+"[Macro]"
+"evaluates keyform, then evaluates as an implicit progn the forms whose keys match the value of
+keyform. Returns the last form evaluated. keyform is evaluated, but the keys are not. case permits a
+final case, otherwise or t, that handles all keys not otherwise covered."
+
+CATCH 
+"tag {form}*"
+"[Special Form]"
+"sets up a catch called tag and executes forms sequentially. At any time during the execution of the
+forms a throw to tag will immediately cause catch to return the thrown value. If no throw occurs, the
+value of the last body-form is returned."
+
+CCASE 
+"keyform {({( {key }*) | key } {form}* ) }*"
+"[Macro]"
+"gets the value of keyform (which must be a place acceptable to setf), and then executes the first set of
+forms whose corresponding keys are eql to the keyform value. I A continuable error is signalled if
+there is no match, allowing the user to place a new value in the keyform place."
+
+CDAAAR 
+"list"
+"[Function]"
+"returns the cdr of the car of the car of the car of list."
+
+CDAADR 
+"list"
+"[Function]"
+"returns the cdr of the car of the car of the cdr of list."
+
+CDAAR 
+"list"
+"[Function]"
+"returns the cdr of the car of the car of list."
+
+CDADAR 
+"list"
+"[Function]"
+"returns the cdr of the car of the cdr of the car of list."
+
+CDADDR 
+"list"
+"[Function]"
+"returns the cdr of the car of the cdr of the cdr of list."
+
+CDADR 
+"list"
+"[Function]"
+"returns the cdr of the car of the cdr of list."
+
+CDAR 
+"list"
+"[Function]"
+"returns the cdr of the car of list."
+
+CDDAAR 
+"list"
+"[Function]"
+"returns the cdr of the cdr of the car of the car of list."
+
+CDDADR 
+"list"
+"[Function]"
+"returns the cdr of the cdr of the car of the cdr of list."
+
+CDDAR 
+"list"
+"[Function]"
+"returns the cdr of the cdr of the car of list."
+
+CDDDAR 
+"list"
+"[Function]"
+"returns the cdr of the cdr of the cdr of the car of list."
+
+CDDDDR 
+"list"
+"[Function]"
+"returns the fourth cdr of list."
+
+CDDDR 
+"list"
+"[Function]"
+"returns the third cdr of list."
+
+CDDR 
+"list"
+"[Function]"
+"returns the cdr of the cdr of list."
+
+CDR 
+"list"
+"[Function]"
+"returns all of list but the first element."
+
+CEILING 
+"number &optional divisor"
+"[Function]"
+"converts number to an integer by rounding up. That is, it returns the smallest integer which is not
+smaller than number. The remainder is returned as a second value. When divisor is specified, ceiling
+first divides divisor into number, and then applies ceiling to the result."
+
+CERROR 
+"continue-format-string datum &rest args"
+"[Function]"
+"invokes the signal facility on a condition. If the condition is not handled, (invoke-debugger condition)
+is executed. While signaling is going on, it is possible to return from cerrror by invoking continue.
+cerror returns nil."
+
+CHANGE-CLASS 
+"instance new-class"
+"[Generic function]"
+"changes the class of an instance to a new class. This function destructively modifies and returns the
+instance."
+
+CHAR 
+"string index"
+"[Function]"
+"returns as a character object the character in string in the position indicated by index. char may be
+used with setf."
+
+CHAR-CODE 
+"character"
+"[Function]"
+"returns the integer ASCII value of character, a character object."
+
+CHAR-CODE-LIMIT  
+NIL "[Constant]"
+"a non-negative integer that is the upper exclusive bound on values produced by the char-code
+function."
+
+CHAR-DOWNCASE 
+"char"
+"[Function]"
+"returns a character which is the lowercase equivalent of char."
+
+#|
+CHAR-EQUAL 
+"char &rest more-chars"
+"[Function]"
+"returns true if all the characters are equal, otherwise false. In Macintosh Common Lisp, case, font,
+and bits attributes are ignored; that is, Control-A is char-equal to a."
+
+CHAR-GREATERP 
+"char &rest more-chars"
+"[Function]"
+"returns true if each character is greater than the one to its right, otherwise false.In Macintosh
+Common Lisp, case, font, and bits attributes are ignored."
+
+CHAR-INT 
+"char"
+"[Function]"
+"returns an integer encoding char, including bit and font information. In Macintosh Common Lisp, this
+function is equal to char-code."
+
+CHAR-LESSP 
+"char &rest more-chars"
+"[Function]"
+"returns true if each character is less than the one to its right, otherwise false. In Macintosh Common
+Lisp, case, font, and bits attributes are ignored."
+
+CHAR-NAME 
+"character"
+"[Function]"
+"returns the standard name of character as a string, or nil if character has no standard name."
+
+CHAR-NOT-EQUAL 
+"char &rest more-chars"
+"[Function]"
+"returns true if none of the characters are equal, otherwise false. In Macintosh Common Lisp, case,
+font, and bits attributes are ignored; that is, (char-not-equal #\d #\Control-D) is false."
+
+CHAR-NOT-GREATERP 
+"char &rest more-chars"
+"[Function]"
+"returns true if no character is greater than the one to its right, otherwise false. In Macintosh
+Common Lisp, case, font, and bits attributes are ignored."
+
+CHAR-NOT-LESSP 
+"char &rest more-chars"
+"[Function]"
+"returns true if no character is less than the one to its right, otherwise false. In Macintosh Common
+Lisp, case, font, and bits attributes are ignored."
+|#
+
+CHAR-UPCASE 
+"char"
+"[Function]"
+"returns a character which is the uppercase equivalent of char."
+
+CHAR/= 
+"char &rest more-chars"
+"[Function]"
+"returns true if none of the characters are equal, otherwise false. The comparison is case sensitive."
+
+CHAR< 
+"character &rest characters"
+"[Function]"
+"returns true if the ASCII value of character is less than the ASCII value of any of the other
+characters, otherwise false. Because ASCII values are compared, case is significant."
+
+CHAR<= 
+"char &rest more-chars"
+"[Function]"
+"returns true if each character is less than or equal to the character to its right, otherwise false. The
+comparison is case sensitive."
+
+CHAR= 
+"character &rest characters"
+"[Function]"
+"returns true if all the characters are equal. Case is significant, so that characters of different cases
+will never be considered equal."
+
+CHAR> 
+"character &rest characters"
+"[Function]"
+"returns true if the ASCII value of character is greater than the ASCII value of any of the other
+characters, otherwise false. Because ASCII values are compared, case is significant."
+
+CHAR>= 
+"char &rest more-chars"
+"[Function]"
+"returns true if each character is greater than or equal to the one to its right, otherwise false. The
+comparison is case sensitive."
+
+CHARACTER 
+"thing"
+"[Function]"
+"coerces thing to a character if possible. thing must be a character, positive integer less than
+char-code-limit, a string of length one, or a symbol whose print-name is a string of length one."
+
+CHARACTERP 
+"object"
+"[Function]"
+"returns true if object is a character; otherwise returns false."
+
+CHECK-TYPE 
+"place typespec &optional string"
+"[Macro]"
+"signals an error if the value place is not of the type typespec. string, if present, provides a
+description of typespec that can appear in an error message."
+
+CLEAR-INPUT 
+"&optional input-stream"
+"[Function]"
+"clears any buffered input associated with input-stream. Returns nil."
+
+CLEAR-OUTPUT 
+"&optional output-stream"
+"[Function]"
+"flushes any pending output to output-stream and returns nil. The output is simply cleared, not sent."
+
+CLOSE 
+"stream &key :abort"
+"[Function]"
+"closes stream so that it can no longer be used for input or output. Returns nil."
+
+CLRHASH 
+"hash-table"
+"[Function]"
+"removes all the entries from the hash table and returns the hash table."
+
+CODE-CHAR 
+"code"
+"[Function]"
+"creates and returns a character object corresponding to the ASCII value code, a non-negative integer.
+Signals an error if code is outside the range of supported ASCII values."
+
+COERCE 
+"thing type-specifier"
+"[Function]"
+"converts thing to an \"equivalent\" object of type type-specifier. Coercions can take place between
+numeric types as long as these would not involve loss of accuracy, between sequence types, from some
+strings, symbols, and numbers to characters, and from a symbol or lambda-function to a function.
+Returns the new object. If the coercion cannot take place, an error is signaled."
+
+COMPILE 
+"name &optional definition"
+"[Function]"
+"compiles the function name, using the definition supplied by definition . If definition is supplied, it
+should be a lambda-expression or a function to be compiled; if not, the symbol-function of the
+symbol is extracted and compiled. The resulting compiled code becomes the function definition of
+name, and name is returned. name may be a symbol or a list whose car is setf."
+
+COMPILE-FILE 
+"filename &key :output-file :verbose :print :load :features :save-local-symbols
+:save-doc-strings :save-definitions"
+"[Function]"
+"produces a compiled version of the file filename. Compiled files (also called fasl files) can be loaded
+much more quickly than source code files. The default values of :verbose and :print are the values of
+*compile-verbose* and *compile-print*. The default value of :save-local-symbols is the value of
+*fasl-save-local-symbols*; of :save-doc-strings, the value of *fasl-save-doc-strings*;; and of
+save-definitions, the value of *fasl-save-definitions*. The default value of :output-file is the input
+file with the file type *.fasl-pathname*."
+
+COMPILED-FUNCTION-P 
+"thing"
+"[Function]"
+"returns true if thing is any compiled code object, otherwise false."
+
+COMPLEX 
+"realpart &optional imagpart"
+"[Function]"
+"creates a complex number from realpart and imagpart."
+
+COMPLEXP 
+"object"
+"[Function]"
+"returns true if object is a complex number; otherwise returns false."
+
+CONCATENATE 
+"result-type &rest sequences"
+"[Function]"
+"copies sequences in order into a new sequence of type result-type."
+
+COND 
+"{(test {form}* )}*"
+"[Macro]"
+"consists of a series of clauses which are tested sequentially. If a test is true, cond evaluates the
+corresponding forms and returns the last form's value. If the test returns nil, cond proceeds to the
+next test / form clause. If all tests fail, cond returns nil."
+
+CONJUGATE 
+"number"
+"[Function]"
+"returns the complex conjugate of number."
+
+CONS 
+"x list-or-thing"
+"[Function]"
+"allocates a new cons cell whose car is x and whose cdr is list-or-thing."
+
+CONSP 
+"object"
+"[Function]"
+"returns true if object is a cons, otherwise returns false. consp of the empty list returns false. (See
+also listp which returns true on the empty list.)"
+
+CONSTANTP 
+"object"
+"[Function]"
+"returns true if object is a constant. Constants include self-evaluating objects such as numbers,
+characters, bit-vectors, strings, and keywords, and all constant symbols defined with defconstant,
+such as nil and t. In addition, a list whose car is quote, such as (quote foo), is considered to be a
+constant."
+
+CONTINUE 
+"&optional condition"
+"[Function]"
+"resumes execution of the code suspended by the most recent call to break or cerror. If there have
+been no calls to break or cerror, continue simply returns to the top level. If condition is present, the
+restart for condition is invoked."
+
+COPY-ALIST 
+"a-list"
+"[Function]"
+"returns a copy of a-list. The top level of list structure is copied; in addition, any element of a-list
+that is a cons is also copied. Used for copying association lists."
+
+COPY-LIST 
+"list"
+"[Function]"
+"returns a list that is equal to but not eq to list."
+
+COPY-READTABLE 
+"&optional from-readtable to-readtable"
+"[Function]"
+"copies from-readtable to to-readtable. from-readtable defaults to the current readtable; if it is
+supplied as nil, the standard. Common Lisp readtable is used. If to-readtable is supplied, it is
+destructively modified to hold the result; otherwise a new readtable is created."
+
+COPY-SEQ 
+"sequence"
+"[Function]"
+"returns a copy of sequence. The result is equalp but not eq to the argument."
+
+COPY-SYMBOL 
+"symbol &optional copy-props"
+"[Function]"
+"returns a uninterned symbol whose print-name is string-=, but not eq, to that of symbol. If
+copy-props is non-nil, then the contents of the value, function, and property cells are copied to the
+new symbol (the property list is actually duplicated). If copy-props is nil (the default), they are
+not copied."
+
+COPY-TREE 
+"tree"
+"[Function]"
+"if tree is not a cons, it is returned directly. Otherwise, a copy of tree is returned, with all conses,
+stopping only when non-conses are encountered. Used for copying trees of conses. This function does
+not preserve circularities and sharing of substructures."
+
+COS 
+"radians"
+"[Function]"
+"returns the cosine of radians, a number in radians."
+
+COSH 
+"radians"
+"[Function]"
+"returns the hyperbolic cosine of radians, a number in radians."
+
+COUNT 
+"item sequence &key :start :end :from-end :key :test :test-not"
+"[Function]"
+"returns the number of elements of sequence that match item using the given test function; returns nil
+if no element matches."
+
+COUNT-IF 
+"test sequence &key :from-end :start :end :key"
+"[Function]"
+"returns the number of elements in the given range of sequence that satisfy test."
+
+COUNT-IF-NOT 
+"test sequence &key :from-end :start :end :key"
+"[Function]"
+"returns the number of elements in the given range of sequence which do not satisfy test."
+
+CTYPECASE 
+"keyform {(type {form}* )}*"
+"[Macro]"
+"evaluates keyform, then evaluates as an implicit progn the forms whose type matches the value of
+keyform. Returns the last form evaluated. keyform is evaluated, but the type is not. ctypecase does
+not permit an otherwise or t clause. If no clause is satisfied, ctypecase signals a continuable
+type-error."
+
+DECF 
+"place &optional delta"
+"[Function]"
+"decrements the value in place by delta (which defaults to 1)."
+
+DECLAIM 
+"{declaration-spec}*"
+"[Special Form]"
+"provides a declaration that is executable and may be used anywhere proclaim may be called, but each
+declaration-spec is not evaluated."
+
+DECLARE 
+"{declaration-spec}*"
+"[Special Form]"
+"provides a declaration within executable code. The declare form is not executed; it is limited to
+appearing within the bodies of lambda-expressions, certain generic functions, and some special
+forms, and must always appear at the beginning of the body."
+
+DECODE-FLOAT 
+"float"
+"[Function]"
+"returns three values describing the value of float: a new floating-point number representing the
+mantissa, an integer representing the exponent, and a floating-point number indicating the sign
+(+1.0 or -1.0)."
+
+DECODE-UNIVERSAL-TIME 
+"universal-time &optional time-zone"
+"[Function]"
+"returns nine values giving the decoded time equivalents of time-code. The values are: second, minute,
+hour, date, month, year, day of week, daylight-savings-time-p, and time-zone."
+
+DEFCONSTANT 
+"name value &optional documentation"
+"[Macro]"
+"proclaims name to be constant with the value that is the result of evaluatingvalue. Returns name.
+Documentation may be provided as a string."
+
+DEFINE-MODIFY-MACRO 
+"name lambda-list function [doc-string]"
+"[Macro]"
+"defines a read-modify-write macro named name. These macros set a location to a new value based on
+the old value. (incf and decf are examples of read-modify-write macros.)"
+
+DEFINE-SETF-METHOD 
+"access-function lambda-list [[{declaration}* | doc-string]] {form}*"
+"[Macro]"
+"defines how to setf a generalized variable that is accessed by access-function, which should be a
+function or macro."
+
+DEFMACRO 
+"symbol lambda-list {declaration | doc-string}* {form}*"
+"[Macro]"
+"constructs a global macro definition, binds it to symbol, marks symbol as a macro, and returns
+symbol. defmacro is the macro equivalent of defun."
+
+DEFMETHOD 
+"function-name {method-qualifier}* specialized-lambda-list [[{declaration}* |
+doc-string]] {form}*"
+"[Macro]"
+"defines a method on a generic function."
+
+DEFPACKAGE 
+"defined-package-name {option}*"
+"[Macro]"
+"Creates a new package, or modifies an existing one, whose name is defined-package-name (a string or
+symbol) and returns defined-package-name. The standard options are :size, :nicknames, :shadow,
+:shadowing-import-from, :use, :import-from, :intern, and :export."
+
+DEFPARAMETER 
+"variable-name initial-value &optional documentation"
+"[Macro]"
+"proclaims variable-name to be a special variable, sets it to the value of evaluating initial-value, a
+form, and returns variable-name. Documentation may be provided as a string."
+
+DEFSETF 
+"access-function {update-function [doc-string] | lambda-list (store-variable)
+[[{declaration}* | doc-string]] {form}*}"
+"[Macro]"
+"defines how to setf a generalized variable that is accessed by access-function, which should be a
+function or macro."
+
+DEFSTRUCT 
+"name-and-options [doc-string] {slot-description}*"
+"[Macro]"
+"defines a new structure, according to name-and-options, with slots described by the
+slot-descriptions."
+
+DEFTYPE 
+"symbol lambda-list [[{declaration }* | doc-string]] {form}*"
+"[Macro]"
+"defines the type symbol, to be expanded according to the lambda-list and forms, and returns symbol."
+
+DEFUN 
+"symbol lambda-list {declaration | doc-string}* {form}*"
+"[Macro]"
+"defines a function with the name symbol. Once a function is defined, it may be used just like the
+functions which are built into the system. defun returns symbol."
+
+DEFVAR 
+"variable-name &optional initial-value documentation"
+"[Macro]"
+"proclaims variable-name to be a special variable, optionally sets it to the value of initial-value, and
+returns variable-name. If initial-value is given, variable-name is initialized to the result of
+evaluating it unless variable-name already has a value. If initial-name is not used, it is not
+evaluated. The macro defvar only has an effect the first time it is called on a symbol. Documentation
+may be provided as a string."
+
+DELETE 
+"item sequence &key :count :start :end :from-end :test :test-not :key"
+"[Function]"
+"returns a sequence equivalent to sequence with occurrences of item removed. The original sequence
+may be modified. (This is the destructive counterpart of remove.)"
+
+DELETE-DUPLICATES 
+"sequence &key :start :end :from-end :test :test-not :key"
+"[Function]"
+"returns a sequence equivalent to sequence except that all duplicate elements have been removed. The
+original sequence may be modified. The non-destructive version of this function is
+remove-duplicates."
+
+#|
+DELETE-FILE 
+"file-or-dir &key :if-does-not-exist"
+"[Function]"
+"deletes file-or-dir. Returns the pathname of the file if it was successfully deleted, or nil if the file
+does not exist and the 0value of :if-does-not-exist is nil. If the file does not exist and the value of
+:if-does-not-exist is t, Macintosh Common Lisp signals an error."
+|#
+
+DELETE-IF 
+"test sequence &key :from-end :start :end :count :key"
+"[Function]"
+"returns a sequence equivalent to sequence except that elements that pass test are removed. The
+original sequence may be destroyed by the operation."
+
+DELETE-IF-NOT 
+"test sequence &key :from-end :start :end :count :key"
+"[Function]"
+"returns a sequence equivalent to sequence except that elements that fail to pass test are removed. The
+original sequence may be destroyed by the operation."
+
+DENOMINATOR 
+"rational"
+"[Function]"
+"returns the denominator of the canonical reduced form of rational."
+
+DEPOSIT-FIELD 
+"source-integer bytespec destination-integer"
+"[Function]"
+"returns a number that is the same as destination-integer, except that the byte specified by bytespec
+has been replaced by the corresponding byte from source-integer."
+
+DESCRIBE 
+"thing &optional stream"
+"[Function]"
+"prints information about thing to stream, which defaults to the value of *standard-output*. stream
+may also be nil (meaning *standard-output*) or t (meaning *terminal-io*)."
+
+DIGIT-CHAR 
+"weight &optional radix"
+"[Function]"
+"if possible, returns a character corresponding to weight in the given radix. If it is not possible to
+return such a character, returns nil. radix defaults to 10."
+
+DIGIT-CHAR-P 
+"char &optional radix"
+"[Function]"
+"if char is a legal digit in the base given by radix (default 10), then returns the numeric value of the
+digit. If it is not a legal digit, returns nil. char must be a character."
+
+DIRECTORY 
+"pathname &key :directories :files :directory-pathnames :test :resolve-aliases"
+"[Function]"
+"returns a list of the truenames of all files or folders that match pathname, using * as a wildcard
+character. directory must accept logical pathnames but does not return them."
+
+DIRECTORY-NAMESTRING 
+"pathname"
+"[Function]"
+"returns the directory component of pathname, as a string."
+
+DISASSEMBLE 
+"name-or-compiled-function"
+"[Function]"
+"prints out a disassembly of name-or-compiled-function, which should be a compiled function object,
+a symbol, a lambda expression, or a list whose car is setf."
+
+DO 
+"({var | (var [init [step]])}*) (end-test {result}*) {declaration}* {tag | statement}*"
+"[Macro]"
+"at the beginning of each iteration, evaluates all the init forms (before any var is bound), then binds
+each var to the value of its init . Then evaluates end-test; if the result is nil, execution proceeds with
+the body of the form. If the result is non-nil, the result forms are evaluated as an implicit progn and
+the value of the last result form is returned. At the beginning of the second and subsequent iterations,
+all step forms are evaluated, then all variables are updated."
+
+DO* 
+"({(var [init-val [update]])}*) (end-test {result}*) {decl}* {tag | body-form}*"
+"[Macro]"
+"sequentially evaluates each init form and binds each var to the value of its init , then evaluates
+end-test. If the result is nil, execution proceeds with the body of the form. If the result is non-nil,
+the result forms are evaluated as an implicit progn and the value of the last result form is returned.
+At the beginning of the second and subsequent iterations, the first step form is evaluated and its value
+assigned to the first var, then the second step form is evaluated and its value assigned, and so on."
+
+DO-ALL-SYMBOLS 
+"(var [result-form]) {declaration}* {tag | form}*"
+"[Macro]"
+"iterates over all the symbols accessible in any package, binding var to each of them in turn, and
+evaluating the forms. Some symbols may be processed more than once. When done, evaluates
+result-form and returns its value."
+
+DO-EXTERNAL-SYMBOLS 
+"(var [package [result-form]]) {declaration}* {tag | form}*"
+"[Macro]"
+"iterates over all the external symbols of package, binding var to each of them in turn, and evaluating
+the forms. When done, evaluates result-form and returns its value. package may be either a package
+object or a package name."
+
+DO-SYMBOLS 
+"(var [package [result-form]]) {declaration}* {tag | form}*"
+"[Macro]"
+"iterates over all the symbols accessible in package, binding var to each of them in turn, and
+evaluating the forms. When done, evaluates result-form and returns its value."
+
+DOCUMENTATION 
+"symbol &optional doc-type"
+"[Generic Function]"
+"returns the documentation string of doc-type for symbol. Documentation strings may be specified
+when functions, variables, macros, etc. are defined. The documentation strings are only retained if
+*save-doc-strings* is true when the definition occurs. doc-type may be function, variable,
+structure, type, or setf."
+
+DOLIST 
+"(var listform [resultform]) {declaration}* {tag | statement}*"
+"[Macro]"
+"evaluates listform, which produces a list, and executes the body once for every element in the list. On
+each iteration, var is bound to successive elements of the list. Upon completion, resultform is
+evaluated, and the value is returned. If resultform is omitted, the result is nil."
+
+DOTIMES 
+"(var countform [resultform]) {declaration}* {tag | statement}*"
+"[Macro]"
+"executes forms countform times. On successive executions, var is bound to the integers between zero
+and countform. Upon completion, resultform is evaluated, and the value is returned. If resultform is
+omitted, the result is nil."
+
+DOUBLE-FLOAT-EPSILON  
+NIL "[Constant]"
+"The smallest positive floating point number e such that (not (= (float 1 e) (+ (float 1 e) e)))."
+
+DOUBLE-FLOAT-NEGATIVE-EPSILON  
+NIL "[Constant]"
+"The smallest negative floating point number e such that (not (= (float 1 e) (- (float 1 e) e)))."
+
+DPB 
+"source-integer. bytespec destination-integer"
+"[Function]"
+"returns a number that is the same as destination-integer., except that the byte specified by bytespec
+is replaced with the appropriate number of low bits from source-integer."
+
+DRIBBLE 
+"&optional pathname"
+"[Function]"
+"sends input/output from an interactive session in the Listener to the file pathname, creating a
+readable record of the session."
+
+ECASE 
+"keyform {({( {key }*) | key } {form}* ) }*"
+"[Macro]"
+"evaluates keyform, and then executes the first set of forms whose corresponding keys ares eql to the
+keyform. An error is signalled if there is no match."
+
+ED 
+"&optional pathname"
+"[Function]"
+"opens an editor window to the file specified by pathname, or a new editor window if pathname is not
+specified. pathname may be a logical pathname."
+
+EIGHTH 
+"list"
+"[Function]"
+"returns the eighth element of list, using one-based addressing."
+
+ELT 
+"sequence index"
+"[Function]"
+"returns the element of sequence specified by index, a non-negative integer less than the length of
+sequence. Zero-based indexing is used."
+
+ENCODE-UNIVERSAL-TIME 
+"second minute hour date month year &optional time-zone"
+"[Function]"
+"returns the time indicated by the arguments in encoded format."
+
+ENDP 
+"list"
+"[Function]"
+"returns t if list is nil; returns nil if list is a cons; errors if list is not a list."
+
+ENOUGH-NAMESTRING 
+"pathname &optional defaults"
+"[Function]"
+"returns a string form of pathname containing just enough information to distinguish it uniquely from
+defaults (which defaults to the value of *default-pathname-defaults*)."
+
+EQ 
+"object1 object2"
+"[Function]"
+"returns true if and only if object1 and object2 are the same object. eq is the fastest and strictest test
+for equality. (eq works by testing whether object1 and object2 address the same location in
+memory.) Things that print the same are not necessarily eq, numbers with the same value need not
+be eq, and two similar lists are usually not eq."
+
+EQL 
+"object1 object2"
+"[Function]"
+"returns true if object1 and object2 are eq, or if they are numbers of the same type with the same
+value, or if they are character objects that represent the same character."
+
+EQUAL 
+"object1 object2"
+"[Function]"
+"returns true when object1 and object2 are structurally similar. A rough rule of thumb is that
+objects are equal when their printed representation is the same. equal is case sensitive when
+comparing strings and characters."
+
+EQUALP 
+"object1 object2"
+"[Function]"
+"returns true if object1 and object2 are equal; if they are characters and satisfy char-equal; if they
+are numbers with the same numeric value (even if they are of different types); or if they have
+components that are all equalp. Special rules apply to arrays, hash tables, and structures; see the
+full Common Lisp specification."
+
+ERROR 
+"datum &rest args"
+"[Function]"
+"invokes the signal facility on a condition. If the condition is not handled, (invoke-debugger condition)
+is executed."
+
+ETYPECASE 
+"keyform {(type {form}* )}*"
+"[Macro]"
+"evaluates keyform, then evaluates as an implicit progn the forms whose type matches the value of
+keyform. Returns the last form evaluated. keyform is evaluated, but the type is not. etypecase does
+not permit an otherwise or t clause. If no clause is satisfied, etypecase signals a non-continuable
+type-error."
+
+EVAL 
+"form"
+"[Function]"
+"evaluates form and returns the value returned by form. The evaluation is performed in the current
+dynamic environment and a null lexical environment."
+
+EVAL-WHEN 
+"({situation}*) {form}*"
+"[Special Form]"
+"specifies when form is to be executed; if it is executed, processes the body of its form as an implicit
+progn. situation must be one of :compile-toplevel, :load-toplevel, or :execute."
+
+EVENP 
+"integer"
+"[Function]"
+"returns true if integer is even (evenly divisible by two); otherwise returns nil."
+
+EVERY 
+"predicate sequence &rest more-sequences"
+"[Function]"
+"predicate is applied to the elements of sequence with index 0, then to those with index 1, and so on,
+until the end of the shortest sequence is reached. As soon as predicate returns a nil value, nil is
+returned; otherwise a non-nil value is returned. That is, every is true if every invocation of
+predicate on sequence returns true."
+
+EXP 
+"number"
+"[Function]"
+"returns e raised to the power number, where e is the base of the natural logarithms."
+
+EXPORT 
+"symbols &optional package"
+"[Function]"
+"makes symbols (which should be a symbol or list of symbols) accessible as external symbols in
+package (which defaults to *package*), and returns t."
+
+EXPT 
+"base-number power-number"
+"[Function]"
+"returns base-number raised to power-number."
+
+FBOUNDP 
+"symbol"
+"[Function]"
+"returns true if symbol has a global function binding, otherwise returns nil."
+
+FCEILING 
+"number &optional divisor"
+"[Function]"
+"rounds number upward to a floating-point number. The remainder is returned as a second value.
+When divisor is specified, fceiling first divides divisor into number, then rounds the result upward."
+
+FFLOOR 
+"number &optional divisor"
+"[Function]"
+"rounds number downward to a floating-point number. The remainder of the operation is returned as a
+second value. When divisor is specified, ffloor first divides divisor into number, then rounds the
+result downward."
+
+FIFTH 
+"list"
+"[Function]"
+"returns the fifth element of list, using one-based addressing."
+
+#|
+FILE-AUTHOR 
+"file"
+"[Function]"
+"attempts to determine and return the author of file. In Macintosh Common Lisp, this returns the
+empty string for all files."
+|#
+
+FILE-LENGTH 
+"file-stream &optional new-length"
+"[Function]"
+"returns the length of the file associated with file-stream. If new-length is supplied, the function sets
+the file size and returns new-pos. If new-length is set to less than the current file position the file is
+truncated and the position is set to the new length."
+
+FILE-NAMESTRING 
+"pathname"
+"[Function]"
+"returns the filename portion of pathname, in string format."
+
+FILE-POSITION 
+"file-stream &optional new-position"
+"[Function]"
+"returns or sets the current position within a random access file. If new-position is given, the
+position is set and the new position is returned. If new-position is not given, the current position is
+returned. Stream input or output operations will occur at this position in the file."
+
+FILE-STRING-LENGTH 
+"file-stream object"
+"[Function]"
+"returns a non-negative integer that is the difference between what the file-position of file-stream
+will be after and before writing object to file-stream. If this difference cannot be determined,
+returns nil."
+
+FILE-WRITE-DATE 
+"file"
+"[Function]"
+"returns the time when file was last modified as an integer in Universal Time format. If this cannot be
+determined, returns nil."
+
+FILL 
+"sequence item &key :start :end"
+"[Function]"
+"destructively replaces elements of sequence with item. Returns the destructively modified sequence."
+
+FILL-POINTER 
+"vector"
+"[Function]"
+"returns the fill pointer of vector. If vector does not have a fill pointer, an error is returned."
+
+FIND 
+"item sequence &key :from-end :test :test-not :start :end :key"
+"[Function]"
+"returns the first element in the specified portion of sequence that matches item according to test, or
+nil if no element matches."
+
+FIND-ALL-SYMBOLS 
+"string-or-symbol"
+"[Function]"
+"returns a list of all symbols in any package whose print-name is the same as string-or-symbol. The
+search is case-sensitive. If the argument is a symbol, its print name supplies the string to be
+searched for."
+
+FIND-CLASS 
+"symbol &optional errorp environment"
+"[Function]"
+"returns the class object named by the given signal in the given environment. If there is no such class
+and the errorp argument is nil, find-class returns nil. The default value of errorp is t, which means
+that if there is no such class, find-class returns an error."
+
+FIND-IF 
+"test sequence &key :key :start :end :from-end"
+"[Function]"
+"returns the first element in the specified portion of sequence that satisfies test."
+
+FIND-IF-NOT 
+"test sequence &key :from-end :start :end :key"
+"[Function]"
+"returns the first element in the specified portion of sequence that fails to satisfy test."
+
+FIND-PACKAGE 
+"package"
+"[Function]"
+"returns the package with package as its name or nickname, or nil if no such package exists. If package
+is a symbol, its print-name is used. If package is a package object, the package is returned."
+
+FIND-SYMBOL 
+"string &optional package"
+"[Function]"
+"searches for the symbol named by string in package (a package object or a package name). Returns
+the symbol if it is found, otherwise returns nil."
+
+FINISH-OUTPUT 
+"&optional output-stream"
+"[Function]"
+"attempts to ensure that any output to output-stream that has been buffered reaches its destination.
+When the output is complete, returns nil."
+
+FIRST 
+"list"
+"[Function]"
+"returns the car of list, using one-based addressing."
+
+FLET 
+"({(name lambda-list {declaration | doc-string}* {form}*)}*) {flet-body-form}*"
+"[Special Form]"
+"creates local function definitions which can be accessed by the flet-body-forms. Within the body of
+the flet, if there are global functions with the same names as the local function definitions, the local
+definitions are used instead of the global. The local definition can refer to the global definition."
+
+FLOAT 
+"number &optional other"
+"[Function]"
+"converts number, any non-complex number, to a floating-point number. If other is given, it should
+be a floating-point number. number is converted to a float of the same type."
+
+FLOAT-SIGN 
+"float1 &optional float2"
+"[Function]"
+"returns a floating-point number with the same sign as float1 and the same absolute value as float2
+(which defaults to 1.0)."
+
+FLOATP 
+"object"
+"[Function]"
+"returns true if object is a floating point number; otherwise returns false."
+
+FLOOR 
+"number &optional divisor"
+"[Function]"
+"converts number to an integer by rounding down. That is, it returns the largest integer which is not
+larger than number. A second value returned is the remainder of the operation. When divisor is
+specified, floor first divides divisor into number, and then applies floor to the result."
+
+FMAKUNBOUND 
+"symbol"
+"[Function]"
+"causes the global function definition of symbol to become unbound (have no value). symbol may be a
+symbol or a list whose car is setf. fmakunbound returns symbol."
+
+FORCE-OUTPUT 
+"&optional output-stream"
+"[Function]"
+"tells output-stream to immediately process all pending buffered output, and returns nil (without
+waiting for completion or acknowledgment)."
+
+FORMAT 
+"destination control-string &rest args"
+"[Function]"
+"generates output from control-string and args, and sends it to destination, which should be a stream,
+t, or nil. If destination is nil, format returns a stream of type string-stream holding the output.
+Otherwise it sends the output to destination (*standard-output* if destination is t) and returns nil."
+
+FOURTH 
+"list"
+"[Function]"
+"returns the fourth element (cadddr) of list, using one-based addressing."
+
+FRESH-LINE 
+"&optional output-stream"
+"[Function]"
+"writes a newline character to output-stream if and only if output-stream is not already at the start
+of a new line. Returns t if it wrote a newline or nil if it did not."
+
+FROUND 
+"number &optional divisor"
+"[Function]"
+"returns as a floating-point number the integer nearest to number. If number is halfway between two
+integers (for example 3.5), fround rounds up to the next integer and expresses it as a floating-point
+number. fround returns a second value, which is the remainder of the rounding operation. When
+divisor is present, fround first divides divisor into number, then rounds up the result."
+
+FTRUNCATE 
+"number &optional divisor"
+"[Function]"
+"returns two values: the integer part of number (i.e. number with the fractional part removed),
+expressed as a floating-point number, and the fractional part. When divisor is present, truncate
+divides divisor into number first and then truncates the result."
+
+FUNCALL 
+"function &rest arguments"
+"[Function]"
+"invokes function, passing it arguments as arguments. Because funcall is a function, function is
+evaluated. The type of function can be only symbol or function. The value returned by the function
+call is returned."
+
+FUNCTION 
+"function-indicator"
+"[Special Form]"
+"returns the function object associated with function-indicator. This function object is the piece of
+code that would be executed if function-indicator was in the car of a list. function is usually
+abbreviated by the reader macro #'."
+
+FUNCTIONP 
+"object"
+"[Function]"
+"returns true if object could be a function, otherwise returns false. However, functionp is always
+false of symbols and lists, including lambda-lists."
+
+GCD 
+"&rest integers"
+"[Function]"
+"returns the greatest common denominator of its arguments."
+
+GENSYM 
+"&optional string-or-number"
+"[Function]"
+"creates and returns a unique uninterned symbol. If string-or-number is given, it will be used in the
+name of the new symbol."
+
+GENTEMP 
+"&optional prefix package"
+"[Function]"
+"creates and returns a new symbol interned in package (which defaults to *package*), guaranteeing
+that the symbol will be a new one not already in package."
+
+GET 
+"symbol property &optional default"
+"[Function]"
+"searches the property list of symbol for property (using eq to test). Returns the property value if
+found; otherwise returns default-value if specified, or nil if no default-value is specified. get may be
+combined with setf to add or change a property."
+
+GET-DECODED-TIME  
+NIL
+"[Function]"
+"returns 9 values giving the current time in Decoded Time format. The 9 values are seconds, minutes,
+hours, date, month, year, day-of-week, daylight-saving-time-p, and time-zone."
+
+GET-DISPATCH-MACRO-CHARACTER 
+"disp-char sub-char &optional readtable"
+"[Function]"
+"returns the function associated with sub-char under disp-char in readtable (which defaults to
+*readtable*)."
+
+#|
+GET-INTERNAL-REAL-TIME  
+NIL
+"[Function]"
+"returns an integer representing, in Internal Time format, the amount of time since your Macintosh
+computer has been turned on."
+
+GET-INTERNAL-RUN-TIME  
+NIL
+"[Function]"
+"returns an integer representing, in Internal Time format, the amount of time since your Macintosh
+computer has been turned on during which Macintosh Common Lisp computation took place."
+|#
+
+GET-MACRO-CHARACTER 
+"char &optional readtable"
+"[Function]"
+"returns two values, the function associated with char in readtable (which defaults to *readtable*),
+and a second value that is the non-terminating-p flag."
+
+GET-OUTPUT-STREAM-STRING 
+"string-output-stream"
+"[Function]"
+"returns a string containing all characters written to string-output-stream and resets the stream."
+
+GET-PROPERTIES 
+"plist indicator-list"
+"[Function]"
+"searches plist for any one of the properties from indicator-list. Returns three values: the first found
+property, its value, and the portion of plist that has yet to be searched. If no property is found, all
+three values are nil."
+
+GET-SETF-METHOD 
+"form &optional environment"
+"[Function]"
+"returns five values constituting the setf method for form in environment."
+
+GET-SETF-METHOD-MULTIPLE-VALUE 
+"form &optional environment"
+"[Function]"
+"returns five values constituting the setf method for form in environment. Used (instead of
+get-setf-method) when multiple values may be stored into a generalized variable."
+
+GET-UNIVERSAL-TIME  
+NIL
+"[Function]"
+"returns the current time as a single integer in Universal Time format. This integer can be decoded
+with decode-universal-time."
+
+GETF 
+"place indicator &optional default"
+"[Function]"
+"searches the property list stored in place for an indicator eq to indicator. Returns the corresponding
+value if indicator matches; otherwise returns default, if specified, or nil. place may be computed
+from a generalized variable acceptable to setf."
+
+GETHASH 
+"key hash-table &optional default"
+"[Function]"
+"returns the value of key in hash-table, or default if key is not entered in hash-table. default is nil if
+not specified. This function can be used with setf to enter a value into a hash table."
+
+GO 
+"tag"
+"[Special Form]"
+"transfers control to the position in a tagbody referred to by tag."
+
+GRAPHIC-CHAR-P 
+"char"
+"[Function]"
+"returns true if char is a printing character (as opposed to formatting or control character),
+otherwise false. char must be a character."
+
+HANDLER-BIND 
+"({(typespec handler)}*) {form}*"
+"[Macro]"
+"executes body in a dynamic context where the given handler bindings are in effect. Each typespec may
+be any type specifier. Each handler should evaluate to a function to be used to handle conditions of the
+given type(s) during execution of form. The function should take a single argument, the condition
+being signaled."
+
+HASH-TABLE-COUNT 
+"hash-table"
+"[Function]"
+"returns the number of entries in hash-table."
+
+HASH-TABLE-P 
+"thing"
+"[Function]"
+"returns true if thing is a hash table, otherwise false."
+
+HOST-NAMESTRING 
+"pathname"
+"[Function]"
+"returns the host portion of pathname, in the form of a string."
+
+IDENTITY 
+"thing"
+"[Function]"
+"returns thing, unaltered."
+
+IF 
+"testform thenform [elseform]"
+"[Special Form]"
+"evaluates testform. If the result is true, evaluates thenform and returns the result; if the result is
+nil, evaluates elseform and returns the result."
+
+IMAGPART 
+"number"
+"[Function]"
+"returns the imaginary part of number."
+
+IMPORT 
+"symbols &optional package"
+"[Function]"
+"imports symbols (which should be a symbol or list of symbols) into package (which defaults to
+*package*), so that they can referenced without the qualifying colon syntax."
+
+IN-PACKAGE 
+"package-name"
+"[Macro]"
+"sets *package* to the package whose name is package-name. An error is signaled if the package does
+not exist. package-name must be a symbol or string; if it is a symbol, the symbol's print-name is
+used."
+
+INCF 
+"place &optional delta"
+"[Function]"
+"increases the value in place (which can be any setf-able location) by delta (which defaults to 1)."
+
+INITIALIZE-INSTANCE 
+"instance &rest initargs"
+"[Generic Function]"
+"called by make-instance to initialize a newly created instance."
+
+INPUT-STREAM-P 
+"thing"
+"[Function]"
+"returns true if stream is a stream which can handle input operations, otherwise returns nil."
+
+INSPECT 
+"thing"
+"[Function]"
+"inspects thing, any Lisp data object."
+
+INTEGER-DECODE-FLOAT 
+"float"
+"[Function]"
+"returns three values: the significand scaled to be an integer, the exponent, and the sign of float."
+
+INTEGERP 
+"object"
+"[Function]"
+"returns true if object is an integer; otherwise returns false."
+
+INTERN 
+"string &optional package"
+"[Function]"
+"searches package (a package object or package name, defaulting to the current package) and all
+inherited packages for the symbol named by string. If not found, it creates and interns such a symbol.
+Returns two values, the found or new symbol, and a Boolean value indicating whether the symbol
+already existed (t indicates that it existed, nil that it was created)."
+
+#|
+INTERNAL-TIME-UNITS-PER-SECOND  
+NIL "[Constant]"
+"an integer that is the number of Macintosh Common Lisp internal time units per second."
+|#
+
+INTERSECTION 
+"list1 list2 &key :test :test-not :key"
+"[Function]"
+"returns the intersection of list1 and list2, that is, a list of those elements which are in both list1 and
+list2. If either list has duplicate entries, the redundant entries may or may not appear in the result.
+list1 and list2 are not modified."
+
+ISQRT 
+"integer"
+"[Function]"
+"returns the integer square root of integer."
+
+KEYWORDP 
+"thing"
+"[Function]"
+"returns true if thing is a symbol in the keyword package. Every symbol that is a keyword is written
+with a leading colon and always evaluates to itself."
+
+LABELS 
+"({(name lambda-list {declaration | doc-string}* {function-body-form}*)}*)
+{labels-body-form}*"
+"[Special Form]"
+"creates local function definitions whose scope encompasses both the body and the function definitions
+themselves. If there are global functions with the same names, the local definitions take precedence
+within the body of the labels. That is, labels can be used to define mutually recursive functions, while
+flet cannot; but a local function definition with flet can refer to the global definition, while one with
+labels cannot."
+
+LAMBDA 
+"lambda-list {declarations}* {form}*"
+"[Special Form]"
+"indicates a function with parameters specified by lambda-list and body specified by forms."
+
+#|
+LAMBDA-LIST-KEYWORDS  
+NIL "[Constant]"
+"a list of all the lambda-list keywords used in Macintosh Common Lisp, including the additional ones
+used only by defmacro."
+|#
+
+LAMBDA-PARAMETERS-LIMIT  
+NIL "[Constant]"
+"a positive integer that is the upper exclusive bound on the number of distinct parameter names that
+may appear in a single lambda list."
+
+LAST 
+"list &optional count"
+"[Function]"
+"returns the last count conses of list."
+
+LCM 
+"&rest integers"
+"[Function]"
+"returns the least common multiple of its arguments."
+
+LDB 
+"bytespec integer"
+"[Function]"
+"returns the byte of integer specified by bytespec."
+
+LDB-TEST 
+"bytespec integer"
+"[Function]"
+"returns true if any of the bits in the specified bytespec of integer are 1's."
+
+LDIFF 
+"list sublist"
+"[Function]"
+"returns a new list containing the portion of list prior to sublist, which should be a cons appearing in
+list. If sublist does not appear in list, a copy of the entire list is returned."
+
+#|
+LEAST-NEGATIVE-DOUBLE-FLOAT  
+NIL "[Constant]"
+"the negative double-float floating-point number closest in value, but not equal to, zero in Macintosh
+Common Lisp."
+
+LEAST-NEGATIVE-LONG-FLOAT  
+NIL "[Constant]"
+"the negative long-format floating-point number closest in value, but not equal to, zero in Macintosh
+Common Lisp."
+
+LEAST-NEGATIVE-SHORT-FLOAT  
+NIL "[Constant]"
+"the negative short-format floating-point number closest in value, but not equal to, zero in Macintosh
+Common Lisp."
+
+LEAST-NEGATIVE-SINGLE-FLOAT  
+NIL "[Constant]"
+"The negative floating-point number closest in value, but not equal to, zero in Macintosh Common Lisp."
+
+LEAST-POSITIVE-DOUBLE-FLOAT  
+NIL "[Constant]"
+"the positive double-float floating-point number closest in value, but not equal to, zero in Macintosh
+Common Lisp."
+
+LEAST-POSITIVE-LONG-FLOAT  
+NIL "[Constant]"
+"the positive long-format floating-point number closest in value, but not equal to, zero in Macintosh
+Common Lisp."
+
+LEAST-POSITIVE-SHORT-FLOAT  
+NIL "[Constant]"
+"the positive short-format floating-point number closest in value, but not equal to, zero in Macintosh
+Common Lisp."
+
+LEAST-POSITIVE-SINGLE-FLOAT  
+NIL "[Constant]"
+"the negative floating-point number closest in value, but not equal to, zero in Macintosh Common Lisp."
+|#
+
+LENGTH 
+"sequence"
+"[Function]"
+"returns the number of elements in sequence."
+
+LET 
+"({variable | (variable value) }*) {declaration}* {form}*"
+"[Special Form]"
+"creates a binding for each variable (in parallel) and evaluates forms in the resulting environment.
+Returns the value of the last form."
+
+LET* 
+"({variable | (variable value) }*) {declaration}* {form}*"
+"[Special Form]"
+"creates a binding for each variable (sequentially) and evaluates forms in the resulting environment.
+This sequential binding allows the expression for the value of a variable to refer to variables bound
+earlier in the let* form. Returns the value of the last form."
+
+#|
+LISP-IMPLEMENTATION-TYPE  
+NIL
+"[Function]"
+"returns the string \"Macintosh Common Lisp\"."
+
+LISP-IMPLEMENTATION-VERSION  
+NIL
+"[Function]"
+"returns the version of Macintosh Common Lisp."
+|#
+
+LIST 
+"&rest arguments"
+"[Function]"
+"constructs and returns a list containing arguments as its elements."
+
+LIST* 
+"object &rest more-objects"
+"[Function]"
+"constructs and returns a list containing object and more-objects. Unlike list, list* places the last
+more-objects in the final cdr of the list. If the last argument to list* is an atom, this will result in a
+dotted list; if the last argument is a list, it will have the effect of appending the other arguments to
+this list."
+
+LIST-ALL-PACKAGES  
+NIL
+"[Function]"
+"returns a list of all packages that currently exist in the Lisp system."
+
+LIST-LENGTH 
+"list"
+"[Function]"
+"returns the length of list as an integer, or nil if list is a circular list."
+
+LISTEN 
+"&optional input-stream"
+"[Function]"
+"returns true if a character is immediately available from input-stream. Returns nil if a character is
+not available or the stream is at end-of-file."
+
+LISTP 
+"object"
+"[Function]"
+"returns true if object is a cons or the empty list; otherwise returns false. listp returns true on the
+empty list. This is the only difference between listp and consp. listp does not check whether the list is
+terminated by nil or is a dotted list."
+
+#|
+LOAD 
+"filename &key :verbose :print :if-does-not-exist :foreign-files :system-libraries
+:unreferenced-lib-names"
+"[Function]"
+"loads the file named by filename into the Macintosh Common Lisp environment. This is equivalent to
+opening an editor buffer to the file and evaluating all the forms in the buffer (which is equivalent to
+typing the forms into the Listener)."
+|#
+
+LOCALLY 
+"{declaration}* {form}*"
+"[Special form]"
+"executes forms with the declarations in effect. When a locally form appears at top level, the forms in
+its body are processed as top-level forms. This function may be used to wrap declarations around a
+defun or defmacro."
+
+LOG 
+"number &optional base"
+"[Function]"
+"returns the logarithm of number in base."
+
+LOGAND 
+"&rest integers"
+"[Function]"
+"returns the bit-wise logical ÒandÓ of its arguments. If no argument is given, then the result is -1."
+
+LOGANDC1 
+"integer1 integer2"
+"[Function]"
+"returns (logand (lognot integer1) integer2)."
+
+LOGANDC2 
+"integer1 integer2"
+"[Function]"
+"returns (logand integer1 (lognot integer2))."
+
+LOGBITP 
+"index integer"
+"[Function]"
+"returns true if the bit in integer whose index is index is a one-bit; return nil if it is a zero bit. The
+rightmost bit of integer is bit 0."
+
+LOGCOUNT 
+"integer"
+"[Function]"
+"returns the number of ÒonÓ bits in integer. If integer is positive, then the one bits in its binary
+representation are counted; if integer is negative, then the zero bits in the twoÕs-complement
+representation are counted."
+
+LOGEQV 
+"&rest integers"
+"[Function]"
+"returns the logical-exclusive-nor of the integers."
+
+LOGIOR 
+"&rest integers"
+"[Function]"
+"returns the bit-wise logical inclusive ÒorÓ of its arguments. If no argument is given, then the result
+is 0."
+
+LOGNAND 
+"integer1 integer2"
+"[Function]"
+"returns (lognot (logand integer1 integer2))."
+
+LOGNOR 
+"integer1 integer2"
+"[Function]"
+"returns the logical nor of integer1 and integer2. Each bit that is a 0 in both integer1 and integer2
+will be a 1 in the result."
+
+LOGNOT 
+"integer"
+"[Function]"
+"returns the bit-wise logical ÒnotÓ of its argument. Every bit of the result is the complement of the
+corresponding bit in the argument."
+
+LOGORC1 
+"integer1 integer2"
+"[Function]"
+"returns (logior (lognot integer1) integer2)."
+
+LOGORC2 
+"integer1 integer2"
+"[Function]"
+"returns (logior integer1 (lognot integer2))."
+
+LOGTEST 
+"integer1 integer2"
+"[Function]"
+"returns true if any of the 1 bits in integer1 are also 1 bits in integer2."
+
+LOGXOR 
+"&rest integers"
+"[Function]"
+"returns the bit-wise logical exclusive ÒorÓ of its arguments. If no argument is given, then the result
+is 0."
+
+LONG-FLOAT-EPSILON  
+NIL "[Constant]"
+"the smallest positive floating point number e such that (not (= (float 1 e) (+ (float 1 e) e)))."
+
+LONG-FLOAT-NEGATIVE-EPSILON  
+NIL "[Constant]"
+"The smallest negative floating point number e such that (not (= (float 1 e) (- (float 1 e) e)))."
+
+LONG-SITE-NAME  
+NIL
+"[Function]"
+"returns a string giving the full name of the site at which the Lisp is running. This function should be
+redefined by the user."
+
+LOOP 
+"{form}*"
+"[Macro]"
+"repeatedly evaluates+ forms. loop will continue until explicitly terminated by a throw, return, or
+go. A set of extensions to loop is documented in Common Lisp: The Language, chapter 26."
+
+
+LOOP-FINISH 
+"()"
+"[macro]"
+"Causes the iteration to terminate \"normally\", the same as implicit
+termination by an iteration driving clause, or by use of WHILE or
+UNTIL -- the epilogue code (if any) will be run, and any implicitly
+collected result will be returned as the value of the LOOP."
+
+LOWER-CASE-P 
+"char"
+"[Function]"
+"returns true if char is a lowercase character; otherwise returns false. char must be a character."
+
+#|
+MACHINE-INSTANCE  
+NIL
+"[Function]"
+"returns the name of the machine running Macintosh Common Lisp; this might be a local nickname or
+a serial number. This function should be redefined by the user."
+
+MACHINE-TYPE  
+NIL
+"[Function]"
+"returns the type of Macintosh computer running Macintosh Common Lisp."
+
+MACHINE-VERSION  
+NIL
+"[Function]"
+"returns a string that identifies the version of the current hardware running Macintosh Common Lisp."
+|#
+
+MACRO-FUNCTION 
+"symbol &optional environment"
+"[Function]"
+"returns the macro expansion function of the global macro definition associated with symbol. If
+symbol does not name a macro, returns nil."
+
+MACROEXPAND 
+"form &optional environment"
+"[Function]"
+"expands form repeatedly within environment until it is no longer a macro call, and returns the
+expansion and a second value, t if form was a macro call and nil if it was not."
+
+MACROEXPAND-1 
+"form &optional environment"
+"[Function]"
+"returns the result of expanding form oncewithin environment . Returns the expansion and a second
+value, t if the form was a macro call and nil if it was not."
+
+MACROLET 
+"({(name lambda-list {declaration | doc-string}* {form}*)}*) {form}*"
+"[Special Form]"
+"constructs one or more local macro definitions. macrolet is equivalent to flet except that it generates
+macro definitions rather than functions. the value of the last form is returned."
+
+MAKE-ARRAY 
+"dimensions &key :element-type :initial-element :initial-contents :adjustable
+:fill-pointer :displaced-to :displaced-index-offset"
+"[Function]"
+"constructs and returns an array. dimensions should be an integer or a list of integers."
+
+MAKE-BROADCAST-STREAM 
+"&rest stream"
+"[Function]"
+"returns an output stream which sends its output to all the given streams and returns the result of
+performing the operation on the last stream; all other values are discarded."
+
+MAKE-CONCATENATED-STREAM 
+"&rest streams"
+"[Function]"
+"returns an input stream that reads from streams in sequence; when one stream is at end-of-file, the
+function takes input from the next."
+
+MAKE-DISPATCH-MACRO-CHARACTER 
+"char &optional non-terminating-p readtable"
+"[Function]"
+"makes the character char a dispatching macro character in readtable (which defaults to *readtable*).
+If non-terminating-p is nil (the default), char is a terminating macro character; otherwise it is
+non-terminating and may be embedded within extended tokens."
+
+MAKE-ECHO-STREAM 
+"input-stream output-stream"
+"[Function]"
+"returns a stream that gets input from input-stream and sends output to output-stream. In addition,
+all input received is echoed to output-stream."
+
+MAKE-HASH-TABLE 
+"&key :test :size :rehash-size :rehash-threshold :weak :hash-function"
+"[Function]"
+"creates and returns a new hash table. :test should be one of the values #`eq, #`eql, #`equal, or
+#`equalp, or one of the symbols eq, eql, equal or equalp."
+
+MAKE-INSTANCE 
+"class &rest initargs"
+"[Generic Function]"
+"creates a new instance of the given class."
+
+MAKE-LIST 
+"size &key :initial-element"
+"[Function]"
+"returns a list containing size elements, each of which is intialized to :initial-element. size should be
+a non-negative integer; the default value of :initial-element is nil."
+
+MAKE-LOAD-FORM 
+"object"
+"[Generic Function]"
+"returns two values, a form that, when evaluated at load time, returns an object that is equivalent to
+object, and a form that, when evaluated at load time, performs further initialization of object. See
+Common Lisp: The Language, pages 659-662."
+
+MAKE-LOAD-FORM-SAVING-SLOTS 
+"object &optional slots"
+"[Generic Function]"
+"returns two values suitable for return from a make-load-form method. The first argument is the
+object; the optional second argument is a list of the names of slots to preserve. It defaults to all of the
+local slots."
+
+MAKE-PACKAGE 
+"package-name &key :nicknames :use :internal-size :external-size"
+"[Function]"
+"creates and returns a package named package-name, which may be either a string or symbol. If it is a
+symbol, the symbol's print-name is used. The list :nicknames contains strings that serve as
+alternative names; :use is a list of packages whose external symbols are inherited by the new
+package. The default value of :use is the value of the variable *make-package-use-defaults* which is
+initially (\"COMMON-LISP\" \"CCL\")."
+
+MAKE-PATHNAME 
+"&key :host :device :directory :name :type :version :defaults :case"
+"[Function]"
+"creates and returns a pathname with components based on the arguments."
+
+MAKE-RANDOM-STATE 
+"&optional state"
+"[Function]"
+"returns a new random state object, based on state (which defaults to *random-state*). If state is nil
+or omitted, the current random state object is copied; if it is t, a completely fresh random state is
+generated."
+
+MAKE-SEQUENCE 
+"type size &key :initial-element"
+"[Function]"
+"creates and returns a sequence of type with length size."
+
+MAKE-STRING 
+"size &key :initial-element :element-type"
+"[Function]"
+"returns a simple string of length size, each character of which is initialized to :initial-element. The
+:element-type argument names the type of the elements of the stream; its default is character."
+
+MAKE-STRING-INPUT-STREAM 
+"string &optional start end"
+"[Function]"
+"creates and returns an input stream of type string-stream that reads from string."
+
+MAKE-STRING-OUTPUT-STREAM 
+"&key :element-type"
+"[Function]"
+"creates and returns an output stream that accumulates all output given it in a string-stream for the
+benefit of get-output-stream-string. The :element-type argument specifies what characters must be
+accepted by the created stream; if the argument is omitted the stream must accept all characters."
+
+MAKE-SYMBOL 
+"print-name"
+"[Function]"
+"creates and returns an uninterned symbol with name print-name."
+
+MAKE-SYNONYM-STREAM 
+"symbol"
+"[Function]"
+"returns a synonym stream associated with symbol. Any operations performed on the stream will act
+on the stream that is (at that point) bound to symbol. symbol may be bound to a new stream, and the
+operations will act on the new stream."
+
+MAKE-TWO-WAY-STREAM 
+"input-stream output-stream"
+"[Function]"
+"returns a bidirectional stream that receives input from input-stream and sends output to
+output-stream."
+
+MAKUNBOUND 
+"symbol"
+"[Function]"
+"causes the dynamic (special) variable symbol to become unbound (have no value). makunbound
+returns symbol."
+
+MAP 
+"result-type function sequence &rest more-sequences"
+"[Function]"
+"applies function to the first element of each sequence, then the second element of each, and so on until
+the end of the shortest sequence is reached. The results of the function calls are collected in a
+sequence of type result-type. If the result-type is nil, the results are not collected and nil is
+returned."
+
+MAPC 
+"function list &rest more-lists"
+"[Function]"
+"applies function to the elements of list and more-lists. The results are not stored. list is returned. If
+the lists are not all the same length, the iteration terminates when the shortest list runs out.
+function can be only of type symbol or function."
+
+MAPCAN 
+"function list &rest more-lists"
+"[Function]"
+"applies function to the car of list and more-lists, then to the cadr, and so on. The results, which must
+be lists, are combined using nconc. If the lists are not all the same length, the iteration terminates
+when the shortest list runs out. function can be only of type symbol or function."
+
+MAPCAR 
+"function list &rest more-lists"
+"[Function]"
+"applies function to the car of list and more-lists, then to the cadr, and so on. The results are collected
+into a list, which is returned. If the lists are not all the same length, the iteration terminates when
+the shortest list runs out. function can be only of type symbol or function."
+
+MAPCON 
+"function list &rest more-lists"
+"[Function]"
+"applies function first to list and more-lists, and then to successive cdrs of list and more-lists. The
+results, which must be lists, are combined using nconc. If the lists are not all the same length, the
+iteration terminates when the shortest list runs out. function can be only of type symbol or function."
+
+MAPHASH 
+"function hash-table"
+"[Function]"
+"calls function for each entry in hash-table, passing as arguments both the key and the value. Entries
+should not be added or removed while maphash is in progress. maphash returns nil."
+
+MAPL 
+"function list &rest more-lists"
+"[Function]"
+"applies function first to list and more-lists, and then to successive cdrs of list and more-lists. The
+results are not stored (i.e. the operation is only for side-effect). list is returned. If the lists are not
+all the same length, the iteration terminates when the shortest list runs out. function can be only of
+type symbol or function."
+
+MAPLIST 
+"function list &rest more-lists"
+"[Function]"
+"applies function first to list and more-lists, and then to successive cdrs of list and more-lists. The
+results are collected into a list, which is returned. If the lists are not all the same length, the
+iteration terminates when the shortest list runs out. function can be only of type symbol or function."
+
+MASK-FIELD 
+"bytespec integer"
+"[Function]"
+"returns an integer all of whose bits are zero but the byte specified in bytespec; that byte is the same
+as the one at bytespec pin integer."
+
+MAX 
+"number &rest more-numbers"
+"[Function]"
+"returns the largest of numbers."
+
+MEMBER 
+"item list &key :test :test-not :key"
+"[Function]"
+"searches list for a top-level element that matches item. If a match is successful, member returns the
+rest of the list starting with the element that matched item; otherwise returns nil."
+
+MEMBER-IF 
+"test list &key :key"
+"[Function]"
+"searches list for the first top-level element satisfying test. If one is found, the rest of the list
+(beginning with that element) is returned. If none are found, nil is returned."
+
+MEMBER-IF-NOT 
+"test list &key :key"
+"[Function]"
+"searches list for the first top-level element that fails to satisfy test. If such an element is found, the
+rest of the list (beginning with that element) is returned, otherwise nil is returned."
+
+MERGE 
+"result-type sequence1 sequence2 predicate &key :key"
+"[Function]"
+"destructively merges sequence1 and sequence2 into a new sequence of type result-type. result-type
+must be a subtype of sequence."
+
+MERGE-PATHNAMES 
+"pathname &optional defaults default-version"
+"[Function]"
+"creates a new pathname resulting from merging pathname with defaults (which defaults to
+*default-pathname-defaults*). pathname may be a pathname, a string, or a stream that is or was
+open to a file; if defaults is a logical pathname, pathname may be a logical pathname namestring."
+
+MIN 
+"number &rest more-numbers"
+"[Function]"
+"returns the smallest of numbers."
+
+MINUSP 
+"number"
+"[Function]"
+"returns true if number is strictly less than zero; otherwise returns nil. number must be a
+non-complex number."
+
+MISMATCH 
+"sequence1 sequence2 &key :from-end :test :test-not :key :start1 :start2 :end1 :end2"
+"[Function]"
+"compares the elements of the specified portions of sequence1 and sequence2. If two elements do not
+match, the index within sequence1 of the leftmost position at which the elements fail to match is
+returned. If all elements match, nil is returned."
+
+MOD 
+"number divisor"
+"[Function]"
+"returns the root of number modulo divisor. The result will have the same sign as divisor."
+
+#|
+MOST-NEGATIVE-DOUBLE-FLOAT  
+NIL "[Constant]"
+"the double-float floating-point number closest in value, but not equal to, minus infinity in Macintosh
+Common Lisp."
+
+MOST-NEGATIVE-FIXNUM  
+NIL "[Constant]"
+"The fixnum closest to minus infinity in Macintosh Common Lisp."
+
+MOST-NEGATIVE-LONG-FLOAT  
+NIL "[Constant]"
+"the long-float floating-point number closest in value, but not equal to, minus infinity in Macintosh
+Common Lisp."
+
+MOST-NEGATIVE-SHORT-FLOAT  
+NIL "[Constant]"
+"the short-float floating-point number closest in value, but not equal to, minus infinity in Macintosh
+Common Lisp."
+
+MOST-NEGATIVE-SINGLE-FLOAT  
+NIL "[Constant]"
+"the floating-point number closest in value, but not equal to, minus infinity in Macintosh Common
+Lisp."
+
+MOST-POSITIVE-DOUBLE-FLOAT  
+NIL "[Constant]"
+"the double-float floating-point number closest in value, but not equal to, infinity in Macintosh
+Common Lisp."
+
+MOST-POSITIVE-FIXNUM  
+NIL "[Constant]"
+"the fixnum closest in value, but not equal to, infinity in Macintosh Common Lisp."
+
+MOST-POSITIVE-LONG-FLOAT  
+NIL "[Constant]"
+"the long-float floating-point number closest in value, but not equal to, infinity in Macintosh Common
+Lisp."
+
+MOST-POSITIVE-SHORT-FLOAT  
+NIL "[Constant]"
+"the short-float floating-point number closest in value, but not equal to, infinity in Macintosh
+Common Lisp."
+
+MOST-POSITIVE-SINGLE-FLOAT  
+NIL "[Constant]"
+"the floating-point number closest in value, but not equal to, infinity in Macintosh Common Lisp."
+|#
+
+MULTIPLE-VALUE-BIND 
+"({var}*) values-form {declaration}* {form}*"
+"[Macro]"
+"evaluates values-form, and binds the multiple values returned to the vars. The forms are evaluated
+in the resulting environment. The value of the last form is returned."
+
+MULTIPLE-VALUE-CALL 
+"function {form}*"
+"[Special Form]"
+"calls function, passing as arguments all the multiple values returned by forms. The first argument
+(function) is evaluated."
+
+MULTIPLE-VALUE-LIST 
+"form"
+"[Macro]"
+"collects the multiple values returned by form, and returns them in a list."
+
+MULTIPLE-VALUE-PROG1 
+"form {more-forms}*"
+"[Special Form]"
+"evaluates form, and saves the values it returns. Then evaluates more-forms, discarding their
+returned values. When done, returns the values returned by form."
+
+MULTIPLE-VALUE-SETQ 
+"({var}*) form"
+"[Macro]"
+"calls form, and uses the returned multiple values to set (not bind) the vars."
+
+MULTIPLE-VALUES-LIMIT  
+NIL "[Constant]"
+"a positive integer that is the upper exclusive bound on the number of values that may be returned
+from a function."
+
+NAME-CHAR 
+"name"
+"[Function]"
+"returns the character with name name, or nil if there is no such character."
+
+NAMESTRING 
+"pathname"
+"[Function]"
+"returns a string representation of pathname, which may be a pathname, a string, or a stream that is
+or was open to a file."
+
+NBUTLAST 
+"list &optional num"
+"[Function]"
+"destructively modifies list to remove the last num elements. num defaults to 1. If list is shorter than
+num, the empty list is returned and list is not modified. (Therefore one normally writes (setq a
+(nbutlast a)) rather than (nbutlast a).)"
+
+NCONC 
+"&rest lists-or-thing"
+"[Function]"
+"concatenates lists destructively and returns the resulting list. The lists are not copied, but are
+destructively altered in place. nconc is the destructive equivalent of append."
+
+#|
+NIL  
+NIL "[Constant]"
+"the false value in Common Lisp. nil is a symbol, a constant, the Boolean false, a data type, a logical
+operator, an object of type null, and the usual terminator of a list. It is also equivalent to the empty
+list. It is no longer equivalent to Pascal null, which in Macintosh Common Lisp is now equivalent to
+the macptr %null-ptr."
+|#
+
+NINTERSECTION 
+"list1 list2 &key :test :test-not :key"
+"[Function]"
+"returns the intersection of list1 and list2, that is, a list of those elements which are in both list1 and
+list2. If either list has duplicate entries, the redundant entries may or may not appear in the result.
+list1 and list2 may be modified by the process. (nintersection is the destructive form of
+intersection.)"
+
+NINTH 
+"list"
+"[Function]"
+"returns the ninth element of list, using one-based addressing."
+
+NOT 
+"object"
+"[Function]"
+"returns true if object is nil; otherwise returns false. It inverts its argument considered as a Boolean
+value."
+
+NOTANY 
+"predicate sequence &rest more-sequences"
+"[Function]"
+"applies predicate to succesive elements of sequence and more-sequences until a call returns non-nil.
+If a call returns non-nil, notany returns false. If no call returns true, notany returns non-nil.
+predicate must take as many arguments as there are sequences."
+
+NOTEVERY 
+"predicate sequence &rest more-sequences"
+"[Function]"
+"applies predicate to succesive elements of sequence and more-sequences until a call returns nil. If a
+call returns nil, notevery immediately returns a non-nil value. If all calls return true, notevery
+returns nil. predicate must take as many arguments as there are sequences."
+
+NRECONC 
+"list-1 list-2"
+"[Function]"
+"reverses list-1, and places its elements (reversed) at the head of list-2. list-1 is destructively
+modified. This function has exactly the same side-effect behavior as (nconc (nreverse x) y) but is
+potentially more efficient."
+
+NREVERSE 
+"sequence"
+"[Function]"
+"returns a sequence with the elements of sequence reversed. The original sequence may be modified."
+
+NSET-DIFFERENCE 
+"list1 list2 &key :test :test-not :key"
+"[Function]"
+"returns a list of elements in list1 that are not elements of list2. list1 and list2 may be modified by
+the process. (nset-difference is the destructive form of set-difference.)"
+
+NSET-EXCLUSIVE-OR 
+"list1 list2 &key :test :test-not :key"
+"[Function]"
+"returns a list containing those elements that are in list1 or in list2 but are not in both. list1 and
+list2 may be modified by the process. (nset-exclusive-or is the destructive form of
+set-exclusive-or.)"
+
+NSTRING-CAPITALIZE 
+"string &key :start :end"
+"[Function]"
+"destructively modifies the given portion of string, capitalizing all words."
+
+NSTRING-DOWNCASE 
+"string &key :start :end"
+"[Function]"
+"destructively modifies the given portion of string, converting all uppercase characters to lowercase."
+
+NSTRING-UPCASE 
+"string &key :start :end"
+"[Function]"
+"destructively modifies the given portion of string, converting all lowercase characters to uppercase."
+
+NSUBLIS 
+"a-list tree &key :test :test-not :key"
+"[Function]"
+"destructively modifies tree, replacing elements that appear as keys in a-list with the corresponding
+value from a-list. In effect, nsublis can perform several nsubst operations simultaneously."
+
+NSUBST 
+"new old tree &key :test :test-not :key"
+"[Function]"
+"destructively modifies tree, replacing occurrences of old with new."
+
+NSUBST-IF 
+"new test tree &key :key"
+"[Function]"
+"destructively modifies tree, replacing elements that satisfy test with new."
+
+NSUBST-IF-NOT 
+"new test tree &key :key"
+"[Function]"
+"destructively modifies tree, replacing elements that don't satisfy test with new."
+
+NSUBSTITUTE 
+"new-item old-item sequence &key :start :end :from-end :count :test :test-not :key"
+"[Function]"
+"returns a sequence equivalent to sequence except that occurrences of old-item within a given
+subsequence are replaced with new-item. The :count argument, if given, limits the number of
+substitutions which take place. The original sequence may be modified. This is the destructive
+equivalent of substitute."
+
+NSUBSTITUTE-IF 
+"new-item test sequence &key :start :end :from-end :count :key"
+"[Function]"
+"returns a sequence equivalent to sequence except that elements which satisfy test within the given
+subsequence are replaced with new-item. The :count argument, if given, limits the number of
+substitutions which take place. The original sequence may be modified. This is the destructive
+equivalent of substitute-if."
+
+NSUBSTITUTE-IF-NOT "new-item test sequence &key :start :end :from-end :count :key"
+"[Function]"
+"returns a sequence equivalent to sequence except that elements which do not satisfy test within the
+given subsequence are replaced with new-item. The :count argument, if given, limits the number of
+substitutions which take place. The original sequence may be modified. This is the destructive
+equivalent of substitute-if-not."
+
+NTH 
+"n list"
+"[Function]"
+"returns the nth element of list (where the car of list is the \"zeroth\" element )."
+
+NTHCDR 
+"n list"
+"[Function]"
+"performs the cdr operation n times on list and returns the result."
+
+NULL 
+"thing"
+"[Function]"
+"returns true if thing is the empty list (), otherwise returns nil. This is equivalent to the function
+not, except that null is normally used to check for the empty list and not to invert. The programmer
+can express intent by choice of function name."
+
+NUMBERP 
+"object"
+"[Function]"
+"returns true if object is a number; otherwise returns false. More specific numeric data type tests
+include integerp, rationalp, floatp, and complexp."
+
+NUMERATOR 
+"rational"
+"[Function]"
+"returns the numerator of the canonical reduced form of rational."
+
+NUNION 
+"list1 list2 &key :test :test-not :key"
+"[Function]"
+"returns a list containing the union of the elements list1 and list2. Any element that is contained in
+list1 or list2 will be contained in the result list. list1 and list2 may be modified by the process.
+(nunion is the destructive form of union.)"
+
+ODDP 
+"integer"
+"[Function]"
+"returns true if integer is odd (not evenly divisible by two); otherwise returns nil."
+
+OPEN 
+"filename &key :direction :element-type :if-exists :if-does-not-exist :external-format :fork
+:mac-file-creator"
+"[Function]"
+"opens a stream to the file specified by filename, which may be a string, a pathname, a logical
+pathname, or a stream."
+
+OR 
+"{form}*"
+"[Macro]"
+"evaluates each form sequentially. If or reaches a form that returns non-nil, it returns the value of
+that form without evaluating any more forms. If it reaches the last form, it returns that form's value."
+
+OUTPUT-STREAM-P 
+"thing"
+"[Function]"
+"returns true if thing is a stream which can handle output, otherwise returns nil."
+
+PACKAGE-NAME 
+"package"
+"[Function]"
+"returns the name of package as a string, or nil if applied to a deleted package."
+
+PACKAGE-NICKNAMES 
+"package"
+"[Function]"
+"returns a list of the nickname strings of package. This will not include the primary name."
+
+PACKAGE-SHADOWING-SYMBOLS 
+"package"
+"[Function]"
+"returns a list of symbols which have been declared (by shadow or shadowing-import) as shadowing
+symbols in package."
+
+PACKAGE-USE-LIST 
+"package"
+"[Function]"
+"returns a list of packages used by package."
+
+PACKAGE-USED-BY-LIST 
+"package"
+"[Function]"
+"returns a list of all the packages that use package."
+
+PACKAGEP 
+"thing"
+"[Function]"
+"returns true if thing is a package, otherwise false."
+
+PAIRLIS 
+"keys data &optional a-list"
+"[Function]"
+"creates an a-list associated matching elements from the lists keys and data. This a-list is appended to
+a-list. It is an error if the lists keys and data are not the same length."
+
+PARSE-INTEGER 
+"string &key :start :end :radix :junk-allowed"
+"[Function]"
+"reads and returns an integer from the indicated portion of string. Returns a second value that is the
+index into the string of the delimiter that terminated the parse, or the index beyond the substring if
+the parse terminated at the end of the substring. An error is signaled if the substring cannot be
+parsed as an integer."
+
+PARSE-NAMESTRING 
+"thing &optional host defaults &key :start :end :junk-allowed"
+"[Function]"
+"parses thing to a pathname. thing is usually a string, but may be a logical pathname, pathname, or
+stream. The host and defaults arguments are used only to determine pathname syntax, not for
+supplying default pathname components."
+
+PATHNAME 
+"thing"
+"[Function]"
+"coerces thing to a pathname, which it returns. thing should be a pathname, string, or stream."
+
+PATHNAME-DEVICE 
+"pathname &key :case"
+"[Function]"
+"returns the device component of pathname."
+
+PATHNAME-DIRECTORY 
+"pathname &key :case"
+"[Function]"
+"returns the directory component of pathname."
+
+PATHNAME-HOST 
+"pathname &key :case"
+"[Function]"
+"returns the host component of pathname."
+
+PATHNAME-NAME 
+"pathname &key :case"
+"[Function]"
+"returns the name component of pathname."
+
+PATHNAME-TYPE 
+"pathname &key :case"
+"[Function]"
+"returns the type component of pathname."
+
+PATHNAME-VERSION 
+"pathname"
+"[Function]"
+"returns the version component of pathname."
+
+PATHNAMEP 
+"thing"
+"[Function]"
+"returns true if thing is a pathname, otherwise false."
+
+PEEK-CHAR 
+"&optional peek-type input-stream eof-error-p eof-value recursive-p"
+"[Function]"
+"returns the next character of stream according to peek-type, and leaves the character in the input
+stream. peek-type may be nil (return next character), t (skip whitespace, then return next
+character) or a character (advance to first occurrence of the character)."
+
+PHASE 
+"number"
+"[Function]"
+"returns the angle part of the polar representation of number as a complex number. The return value
+is in radians."
+
+PI  
+NIL "[Constant]"
+"The best possible approximation of pi in floating-point format."
+
+PLUSP 
+"number"
+"[Function]"
+"returns true if number is strictly greater than zero; otherwise returns nil. number must be a
+non-complex number."
+
+POP 
+"place"
+"[Macro]"
+"returns the car of the contents of place , which can be any generalized variable containing a list and
+acceptable as a generalized variable to setf. Sets place to point to the cdr of its previous contents. "
+
+POSITION 
+"item sequence &key :start :end :from-end :key :test :test-not"
+"[Function]"
+"returns the index of the first element of sequence that match item using the given test function;
+returns nil if no element matches."
+
+POSITION-IF 
+"test sequence &key :from-end :start :end :key"
+"[Function]"
+"returns the position of the first element in the given range of sequence that satisfies test, or nil if no
+element satisfies the test."
+
+POSITION-IF-NOT 
+"test sequence &key :from-end :start :end :key"
+"[Function]"
+"returns the position of the first element in the given range of sequence that does not satisfy test, or
+nil if all the elements satisfy test."
+
+PPRINT 
+"object &optional output-stream"
+"[Function]"
+"outputs a newline character and the pretty-print representation of object to output-stream. pprint
+returns no value. Common Lisp user-controlled pretty-printing is described in Common Lisp: The
+Language, 2d edition, Chapter 27."
+
+PRIN1 
+"object &optional output-stream"
+"[Function]"
+"outputs the printed representation of data-object to output-stream, using escape characters as
+appropriate. Returns object."
+
+PRIN1-TO-STRING 
+"thing"
+"[Function]"
+"thing is printed, as if by prin1, but the output is collected in a string, which is returned."
+
+PRINC 
+"object &optional output-stream"
+"[Function]"
+"outputs the printed representation of object to output-stream, without any escape characters.
+Returns object."
+
+PRINC-TO-STRING 
+"thing"
+"[Function]"
+"thing is printed, as if by princ, but the output is collected in a string, which is returned."
+
+PRINT 
+"object &optional output-stream"
+"[Function]"
+"outputs the printed representation of data object to output-stream, preceded by a newline and
+followed by a space. Returns object."
+
+PROBE-FILE 
+"pathname"
+"[Function]"
+"if pathname corresponds to an existing file or folder, returns its true name. If pathname does not
+correspond to an existing file or folder, returns nil."
+
+PROCLAIM 
+"declaration-spec"
+"[Function]"
+"provides a global declaration (called a proclamation) or a declaration that is computed by a program.
+proclaim returns nil."
+
+PROG 
+"({var | (var [init])}*) {declaration}* {tag | statement}*"
+"[Macro]"
+"binds the vars to the values of the inits in parallel (or to nil for vars with no corresponding init),
+and then executes the statements. The entire prog form is implicitly surrounded by a block named nil
+(so that return may be used at any time to exit from the construct), and the body is a tagbody. prog
+returns nil."
+
+PROG* 
+"({var | (var [init])}*) {declaration}* {tag | statement}*"
+"[Macro]"
+"binds the vars to the values of the inits in sequence (or to nil for vars with no corresponding init),
+and then executes the statements. The entire prog* form is implicitly surrounded by a block named
+nil (so that return may be used at any time to exit from the construct), and the body is a tagbody.
+prog* returns nil."
+
+PROG1 
+"{form}*"
+"[Macro]"
+"evaluates each form in order, left to right. The first form is evaluated and its value is stored; the
+other forms are evaluated, usually for their side effects; the value of the first form is then returned."
+
+PROG2 
+"{form}*"
+"[Macro]"
+"evaluates each form in order, left to right. The value of the second form is stored and returned."
+
+PROGN 
+"{form}*"
+"[Special Form]"
+"evaluates each form in order, left to right. The values of all forms but the last are discarded; the
+value of the last form is returned."
+
+PROGV 
+"symbols values {form}*"
+"[Special Form]"
+"binds one or more dynamic variables in the list symbols to the values in the list values. With these
+bindings in effect, the forms are executed. Both symbols and values are computed quantities, rather
+than stated explicitly."
+
+PROVIDE 
+"module"
+"[Function]"
+"adds a new module name to the list of modules maintained in the variable *modules*, indicating that
+the module module has been provided. provide is no longer part of the Common Lisp standard."
+
+PSETF 
+"{place newvalue}*"
+"[Macro]"
+"sets the contents of places to the corresponding newvalues. The assignments are done in parallel."
+
+PSETQ 
+"{variable form}*"
+"[Macro]"
+"sets the value of the current binding of each variable to the result of evaluating the corresponding
+form. The assignmentes are performed in parallel Returns nil."
+
+PUSH 
+"item place"
+"[Macro]"
+"conses item onto the list contained in place , which can be any generalized variable containing a list
+and acceptable as a generalized variable to setf. Stores the resulting list in place and returns the new
+contents of place."
+
+PUSHNEW 
+"item place &key :test :test-not :key"
+"[Macro]"
+"pushes item onto the list in place, if the list does not already contain item (as determined by :test).
+The modified list is returned."
+
+QUOTE 
+"object"
+"[Special Form]"
+"returns object , which may be any object, without evaluating it."
+
+RANDOM 
+"number &optional state"
+"[Function]"
+"returns a pseudo random number between zero (inclusive) and number (exclusive). state is an
+object of type random-state and defaults to the value of the variable *random-state*."
+
+RANDOM-STATE-P 
+"thing"
+"[Function]"
+"returns true if thing is a random state, otherwise false."
+
+RASSOC 
+"value a-list &key :test :test-not :key"
+"[Function]"
+"searches a-list for the first pair whose cdr matches value. Returns the pair, or nil if the search fails."
+
+RASSOC-IF 
+"predicate a-list &key :key"
+"[Function]"
+"searches a-list for the first pair matching :key whose cdr satisfies predicate. Returns the pair, or
+nil if the search fails."
+
+RASSOC-IF-NOT 
+"predicate a-list &key :key"
+"[Function]"
+"searches a-list for the first pair matching :key whose cdr does not satisfy predicate. Returns the
+pair, or nil if the search fails."
+
+RATIONAL 
+"number"
+"[Function]"
+"returns the rational representation of number, any non-complex number. With floating-point
+numbers, rational assumes that number is completely accurate and returns a rational number
+mathematically equal to the precise value of the floating-point number. Compare rationalize, which
+returns the best available approximation of number that keeps numerator and denominator small."
+
+RATIONALIZE 
+"number"
+"[Function]"
+"returns the rational representation of number, any non-complex number. With floating-point
+numbers, rationalize assumes that number is accurate only to the precision of the floating-point
+representation and returns the best available approximation of number, keeping numerator and
+denominator small. Compare rational, which returns the precise value."
+
+RATIONALP 
+"object"
+"[Function]"
+"returns true if object is a rational number; otherwise returns false. A rational number is any
+number expressible as the ratio of two integers."
+
+READ 
+"&optional input-stream eof-error-p eof-value recursivep"
+"[Function]"
+"reads the printed representation of a single object from input-stream, builds a corresponding
+object, and returns the object."
+
+READ-BYTE 
+"binary-input-stream &optional eof-errorp eof-value"
+"[Function]"
+"reads one byte from binary-input-stream and returns it in the form of an integer."
+
+READ-CHAR 
+"&optional input-stream eof-error-p eof-value recursive-p"
+"[Function]"
+"reads one character from input-stream, and returns the corresponding character object."
+
+READ-CHAR-NO-HANG 
+"&optional input-stream eof-errorp eof-value recursive-p"
+"[Function]"
+"reads and returns a character from input-stream if one is immediately available, otherwise
+immediately returns nil."
+
+READ-DELIMITED-LIST 
+"char &optional stream recursive-p"
+"[Function]"
+"reads objects from stream, ignoring whitespace and comments, until an occurrence of the character
+char is reached, then returns a list of all the objects it has read so far. char should not be a
+whitespace character."
+
+READ-FROM-STRING 
+"string &optional eof-error-p eof-value &key :start :end :preserve-whitespace"
+"[Function]"
+"reads and returns an expression, taking input from string. A second value returned indicates the
+index of the first character in string not read."
+
+READ-LINE 
+"&optional input-stream eof-error-p eof-value recursive-p"
+"[Function]"
+"reads a line of text terminated by a newline or end of file from input-stream and returns two values,
+the line as a character string and a Boolean value, t if the line was terminated by an end-of-file and
+nil if it was terminated by a newline."
+
+READ-PRESERVING-WHITESPACE 
+"&optional input-stream eof-errorp eof-value recursive-p"
+"[Function]"
+"performs the same operation as read, except that if recursive-p is nil or omitted, delimiting
+whitespace following a token is not discarded, but is retained at the head of the stream, where it can
+be read."
+
+READTABLEP 
+"thing"
+"[Function]"
+"returns t if thing is a readtable, nil if not."
+
+REALP 
+"object"
+"[Function]"
+"returns true if object is a real number; otherwise returns false."
+
+REALPART 
+"number"
+"[Function]"
+"returns the real part of number."
+
+REDUCE 
+"function sequence &key :start :end :from-end :initial-value :key"
+"[Function]"
+"combines the elements of sequence according to function and returns the result. (For example, a list
+of numbers can be combined by adding all the numbers together.)"
+
+REM 
+"number divisor"
+"[Function]"
+"returns the remainder of number divided by divisor. The result will have the same sign as number."
+
+REMF 
+"place property-name"
+"[Macro]"
+"removes the property with an indicator eq to indicator from the property list stored in place. The
+property indicator and its value are removed by destructively splicing the property list. Returns
+true if the property is found; otherwise returns nil. place can be any form acceptable to setf."
+
+REMHASH 
+"key hash-table"
+"[Function]"
+"removes the entry for key from the hash-table hash-table. Returns t if there was such an entry,
+otherwise nil."
+
+REMOVE 
+"item sequence &key :count :start :end :from-end :test :test-not :key"
+"[Function]"
+"returns a new sequence equivalent to sequence with occurrences of item removed. The original
+sequence is not modified. (The destructive counterpart of remove is delete.)"
+
+REMOVE-DUPLICATES 
+"sequence &key :start :end :from-end :test :test-not :key"
+"[Function]"
+"returns a sequence equivalent to sequence except that all duplicate elements have been removed. The
+original sequence is not modified. The destructive version of this function is delete-duplicates."
+
+REMOVE-IF 
+"test sequence &key :from-end :start :end :count :key"
+"[Function]"
+"returns a sequence equivalent to sequence except that elements in the given range that pass test are
+removed. The original sequence is not modified."
+
+REMOVE-IF-NOT 
+"test sequence &key :from-end :start :end :count :key"
+"[Function]"
+"returns a sequence equivalent to sequence except that elements in the given range that fail test are
+removed. The original sequence is not modified."
+
+REMPROP 
+"symbol property-name"
+"[Function]"
+"removes property-name and its value from the property list of symbol. Returns true if the property
+was found and nil if the property was not found."
+
+RENAME-FILE 
+"old-pathname new-pathname &key :if-exists"
+"[Function]"
+"renames the last component of the specified old-pathname to the result of merging new-pathname
+with old-pathname. The :if-exists argument has the same meaning as for copy-file."
+
+RENAME-PACKAGE 
+"package new-name &optional new-nicknames"
+"[Function]"
+"the old name and nicknames of package are replaced by new-name and new-nicknames. new-name
+should be a string, a symbol (the symbol's print-name is used), or a package object. new-nicknames
+should be a string, a symbol, or a list of strings and symbols. package is returned."
+
+REPLACE 
+"destination-sequence source-sequence &key :start1 :end1 :start2 :end2"
+"[Function]"
+"destructively replaces elements in the specified portion of destination-sequence with the elements of
+the specified portion of source-sequence. Returns the modified destination-sequence."
+
+REQUIRE 
+"module &optional pathname"
+"[Function]"
+"attempts to load the files in module if they have not already been loaded. require is no longer part of
+the Common Lisp standard."
+
+REST 
+"list"
+"[Function]"
+"returns the cdr of list. rest can be used with setf to set the cdr of a list."
+
+RETURN 
+"[result-form]"
+"[Macro]"
+"used to return from a block or from constructs such as do and progn. Returns from a block named nil,
+and the block as a whole returns the value of result-form ). If result-form is not supplied, nil is
+returned."
+
+RETURN-FROM 
+"name [result-form]"
+"[Special Form]"
+"used to return from a block or from constructs such as do and progn. The function exits from the
+innermost block named name, and the block as a whole returns the value of result-form. If
+result-form is not supplied, nil is returned."
+
+REVAPPEND 
+"list thing"
+"[Function]"
+"appends the reverse of list to thing. This is equivalent to (append (reverse list) thing) but is
+potentially more efficient."
+
+REVERSE 
+"sequence"
+"[Function]"
+"returns a new sequence with the elements of sequence reversed. The original sequence is not modified."
+
+ROOM 
+"&optional detailedp"
+"[Function]"
+"prints information on the amount of space available in the Lisp operating system."
+
+ROTATEF 
+"&rest places"
+"[Function]"
+"rotates the contents of all the places to the left. The contents of the leftmost place is put into the
+rightmost place."
+
+ROUND 
+"number &optional divisor"
+"[Function]"
+"returns the integer nearest to number. If number is halfway between two integers (for example
+3.5), round converts number to the nearest integer divisible by 2. round returns a second value,
+which is the remainder of the rounding operation. When there is a second argument, round first
+divides divisor into number, and then applies round to the result."
+
+RPLACA 
+"cons object"
+"[Function]"
+"destructively alters cons so that its car points to object. Returns the modified cons."
+
+RPLACD 
+"cons object"
+"[Function]"
+"destructively alters cons so that its cdr points to object. Returns the modified cons."
+
+SBIT 
+"simple-bit-array &rest subscripts"
+"[Function]"
+"returns the bit in simple-bit-array indicated by the subscripts. This function can be used with setf
+to destructively replace a bit-array element."
+
+SCHAR 
+"string index"
+"[Function]"
+"returns the indexth character in string, which must be a simple string. This function can be used
+with setf to set a character in a simple string. Indexing is zero-origin."
+
+SEARCH 
+"sequence1 sequence2 &key :start1 :end1 :start2 :end2 :from-end :key :test :test-not"
+"[Function]"
+"searches sequence2 for a subsequence whose elements match those of sequence1. If successful,
+returns an index into sequence2 indicating the leftmost element of this subsequence. If not successful,
+returns nil."
+
+SECOND 
+"list"
+"[Function]"
+"returns the cadr of list, using one-based addressing."
+
+SET 
+"symbol value"
+"[Function]"
+"assigns value to the result of evaluating symbol, the name of a dynamic (special) variable. Returns
+symbol. The function set cannot alter a local (lexically bound) variable."
+
+SET-DIFFERENCE 
+"list1 list2 &key :test :test-not :key"
+"[Function]"
+"returns the as list of elements of list1 that are not elements of list2. list1 and list2 are not modified."
+
+SET-DISPATCH-MACRO-CHARACTER 
+"disp-char sub-char function &optional readtable"
+"[Function]"
+"causes function to be called when disp-char followed by sub-char is read. readtable is the current
+readtable."
+
+SET-EXCLUSIVE-OR 
+"list1 list2 &key :test :test-not :key"
+"[Function]"
+"returns a list containing those elements that are in list1 or in list2 but are not in both. list1 and
+list2 are not modified."
+
+SET-MACRO-CHARACTER 
+"char function &optional non-terminating-p readtable"
+"[Function]"
+"sets char to be a macro character in readtable (which defaults to *readtable*). When read
+encounters char, function is invoked."
+
+SET-SYNTAX-FROM-CHAR 
+"to-char from-char &optional to-readtable from-readtable"
+"[Function]"
+"sets the syntax of to-char in to-readtable (which defaults to *readtable*) to be equal to the syntax of
+from-char in from-readtable (which defaults to nil, meaning to use the syntax from the standard
+Common Lisp readtable)."
+
+SETF 
+"{place newvalue}*"
+"[Macro]"
+"stores the result of evaluating newvalue into the location that results from examining place. If
+multiple place-newvalue pairs are specified, they are processed sequentially. setf returns the last
+newvalue."
+
+SETQ 
+"{variable form}*"
+"[Special Form]"
+"sets the value of the current binding of each variable to the result of evaluating the corresponding
+form. The assignments are performed sequentially. Returns the value of the last variable."
+
+SEVENTH 
+"list"
+"[Function]"
+"returns the seventh element of list, using one-based addressing."
+
+SHADOW 
+"symbols &optional package"
+"[Function]"
+"searches package for a symbol with the print-name of symbol. If package does not own such a symbol
+(inherited symbols do not count), a new internal symbol is created in the package and placed on the
+shadowing symbols list. symbols should be a symbol, a string, or a list of symbols and/or strings.
+shadow returns t."
+
+SHADOWING-IMPORT 
+"symbols &optional package"
+"[Function]"
+"imports symbols (which should be a symbol or list of symbols) into package, a package object or
+package name. This function does not error if the importation causes a conflict with symbols already
+accessible in package. The symbols are placed in package's shadowing-symbols list."
+
+SHIFTF 
+"{place}+ newvalue"
+"[Macro]"
+"the contents of all the places are shifted to the place to the left. newvalue is shifted into the rightmost
+placo, and the original value of the leftmost place is returned."
+
+SHORT-FLOAT-EPSILON  
+NIL "[Constant]"
+"The smallest positive floating point number e such that (not (= (float 1 e) (+ (float 1 e) e)))."
+
+SHORT-FLOAT-NEGATIVE-EPSILON  
+NIL "[Constant]"
+"The smallest negative floating point number e such that (not (= (float 1 e) (- (float 1 e) e)))."
+
+SHORT-SITE-NAME  
+NIL
+"[Function]"
+"returns the short form of the name of the site in which the Lisp is running. This function should be
+redefined by the user to return an appropriate value."
+
+SIGNUM 
+"number"
+"[Function]"
+"returns an indication of the sign of number. This will be -1, 1, or 0 for rational numbers, -1.0,
+1.0, or 0.0 for floating point numbers. For a complex number z, (signum z) is a complex number of
+the same phase but with unit magnitude unless z is a complex zero, in which case the result is z."
+
+SIMPLE-BIT-VECTOR-P 
+"thing"
+"[Function]"
+"returns true if thing is a simple-bit-vector."
+
+SIMPLE-STRING-P 
+"thing"
+"[Function]"
+"returns true if thing is a simple-string."
+
+SIMPLE-VECTOR-P 
+"thing"
+"[Function]"
+"returns true if thing is a simple-vector."
+
+SIN 
+"radians"
+"[Function]"
+"returns the sine of radians, a number in radians."
+
+SINGLE-FLOAT-EPSILON  
+NIL "[Constant]"
+"The smallest positive floating point number e such that (not (= (float 1 e) (+ (float 1 e) e)))."
+
+SINGLE-FLOAT-NEGATIVE-EPSILON  
+NIL "[Constant]"
+"The smallest negative floating point number e such that (not (= (float 1 e) (- (float 1 e) e)))."
+
+SINH 
+"radians"
+"[Function]"
+"returns the hyperbolic sine of radians, a number in radians."
+
+SIXTH 
+"list"
+"[Function]"
+"returns the sixth element of list, using one-based addressing."
+
+SLEEP 
+"seconds"
+"[Function]"
+"pauses for seconds seconds."
+
+SLOT-VALUE 
+"object slot-name"
+"[Function]"
+"returns the value contained in the slot slot-name of the given object."
+
+#|
+SOFTWARE-TYPE  
+NIL
+"[Function]"
+"returns a string identifying the operating system software. In Macintosh Common Lisp, this is the
+type of Macintosh currently running."
+
+SOFTWARE-VERSION  
+NIL
+"[Function]"
+"returns a string identifying version information of the operating system software. In Macintosh
+Common Lisp, this includes the Macintosh ROM version and the operating system file version."
+|#
+
+SOME 
+"predicate sequence &rest more-sequences"
+"[Function]"
+"predicate is applied to the elements of sequence with index 0, then to those with index 1, and so on,
+until the end of the shortest sequence is reached. As soon as predicate returns a non-nil value, that
+value is returned. nil is returned if there is no true value. That is, some is true if some invocation of
+predicate on sequence returns true."
+
+SORT 
+"sequence predicate &key :key"
+"[Function]"
+"destructively sorts the elements of sequence into an order determined by predicate."
+
+SPECIAL-FORM-P 
+"symbol"
+"[Function]"
+"returns true if symbol names a special form; otherwise returns nil. This is the general mechanism
+for seeing if something is a special form."
+
+SQRT 
+"number"
+"[Function]"
+"returns the principal square root of number."
+
+STABLE-SORT 
+"sequence predicate &key :key"
+"[Function]"
+"destructively sorts the elements of sequence into an order determined by predicate. Elements
+considered equal by predicate stay in their original order. (This function is similar to sort, but is
+guaranteed to be stable.)"
+
+STANDARD-CHAR-P 
+"char"
+"[Function]"
+"returns true if char is a standard character, otherwise false. char must be a character."
+
+STEP 
+"form"
+"[Macro]"
+"Evaluates form expression by expression, under user control. Calls to compiled functions within
+form are treated as a single step if the definition was not saved. The stepping is performed in an
+empty lexical environment."
+
+STREAM 
+NIL
+"[Class name]"
+"the class from which all other streams inherit. This is an abstract class. It should not be directly
+instantiated, but instead used for the creation of new subclasses."
+
+STREAM-ELEMENT-TYPE 
+"stream"
+"[Function]"
+"returns a type indicator, describing what types of objects may be read from or written to stream."
+
+STREAMP 
+"thing"
+"[Function]"
+"returns true if thing is a stream, otherwise false."
+
+STRING 
+"object"
+"[Function]"
+"creates a string from object and returns it. Signals an error if object cannot be transformed into a
+string. string can only convert characters and symbols. (Use format to convert numbers.)"
+
+STRING-CAPITALIZE 
+"string &key :start :end"
+"[Function]"
+"returns a string equivalent to string except that all words in the given range have been capitalized."
+
+STRING-DOWNCASE 
+"string &key :start :end"
+"[Function]"
+"returns a string equivalent to string except that all uppercase characters in the given range have
+been converted to lowercase."
+
+STRING-EQUAL 
+"string1 string2 &key :start1 :end1 :start2 :end2"
+"[Function]"
+"returns true if the specified portions of string1 and string2 are equal, ignoring case. Returns nil if
+the strings are not equal. The keywords :start and :end allow comparison of substrings."
+
+STRING-GREATERP 
+"string1 string2 &key :start1 :end1 :start2 :end2"
+"[Function]"
+"compares the specified portions of string1 and string2, using ASCII alphabetical order and ignoring
+case. Returns true if the specified portion of string1 is greater than the specified portion of string2,
+otherwise returns nil. If the result is true, it will be an integer index into string1 indicating the
+first different character. The keywords :start and :end allow comparison of substrings."
+
+STRING-LEFT-TRIM 
+"char-bag string"
+"[Function]"
+"returns a substring of string with all characters in char-bag removed from the start."
+
+STRING-LESSP 
+"string1 string2 &key :start1 :end1 :start2 :end2"
+"[Function]"
+"compares the specified portions of string1 and string2, using ASCII alphabetical order and ignoring
+case. Returns true if the portion of string1 is less than the portion of string2, otherwise returns nil.
+If the result is true, it will be an integer index into string1 indicating the first different character.
+The keywords :start and :end allow comparison of substrings."
+
+STRING-NOT-EQUAL 
+"string1 string2 &key :start1 :end1 :start2 :end2"
+"[Function]"
+"returns true of the specified portions of string1 and string2 are not equal. Character case is ignored.
+If the strings are equal, nil is returned. If a true result is returned, it is the index into string1 of the
+first non-matching character."
+
+STRING-NOT-GREATERP 
+"string1 string2 &key :start1 :end1 :start2 :end2"
+"[Function]"
+"returns true of the specified portion of string1 is not greater than the specified portion of string2.
+Character case is ignored."
+
+STRING-NOT-LESSP 
+"string1 string2 &key :start1 :end1 :start2 :end2"
+"[Function]"
+"returns true of the specified portion of string1 is not less than the specified portion of string2.
+Character case is ignored."
+
+STRING-RIGHT-TRIM 
+"char-bag string"
+"[Function]"
+"returns a substring of string with all characters in char-bag removed from the end."
+
+STRING-TRIM 
+"char-bag string"
+"[Function]"
+"returns a substring of string with all characters in char-bag removed from the beginning and end."
+
+STRING-UPCASE 
+"string &key :start :end"
+"[Function]"
+"returns a string equivalent to string except that all lowercase characters in the given range have
+been converted to uppercase."
+
+STRING/= 
+"string1 string2 &key :start1 :end1 :start2 :end2"
+"[Function]"
+"returns true of the specified portions of string1 and string2 are not equal. Character case is
+significant. If the strings are equal, nil is returned. If a true result is returned, it is the index into
+string1 of the first non-matching character."
+
+STRING< 
+"string1 string2 &key :start1 :end1 :start2 :end2"
+"[Function]"
+"compares the specified portions of string1 and string2, using ASCII alphabetical order and treating
+case as significant. Returns true if the portion of string1 is less than the portion of string2,
+otherwise returns nil. If the result is true, it will be an integer index into string1 indicating the
+first different character. The keywords :start and :end allow comparison of substrings."
+
+STRING<= 
+"string1 string2 &key :start1 :end1 :start2 :end2"
+"[Function]"
+"returns true of the specified portion of string1 is less than or equal to the specified portion of
+string2. Character case is significant."
+
+STRING= 
+"string1 string2 &key :start1 :end1 :start2 :end2"
+"[Function]"
+"returns true if the specified portions of string1 and string2 are equal, treating case as significant.
+The keywords :start and :end allow comparison of substrings."
+
+STRING> 
+"string1 string2 &key :start1 :end1 :start2 :end2"
+"[Function]"
+"compares the specified portions of string1 and string2, using ASCII alphabetical order and treating
+case as significant. Returns true if the portion of string1 is greater than the portion of string2,
+otherwise returns nil. If the result is true it will be an integer index into string1 indicating the first
+different character. The keywords :start and :end allow comparison of substrings."
+
+STRING>= 
+"string1 string2 &key :start1 :end1 :start2 :end2"
+"[Function]"
+"returns true of the specified portion of string1 is greater than or equal to the specified portion of
+string2. Character case is significant."
+
+STRINGP 
+"object"
+"[Function]"
+"returns true if object is a string; otherwise, returns false."
+
+SUBLIS 
+"a-list tree &key :test :test-not :key"
+"[Function]"
+"creates a new tree based on tree, except that elements that appear as keys in a-list are replaced with
+the corresponding value from a-list. The original tree is not modified, but the new tree may share
+list structure with it. In effect, sublis can perform several subst operations simultaneously."
+
+SUBSEQ 
+"sequence start &optional end"
+"[Function]"
+"returns a new sequence which contains the elements of the portion of sequence specified by start and
+end. subseq may be used with setf to destructively replace a portion of a sequence."
+
+SUBSETP 
+"list1 list2 &key :test :test-not :key"
+"[Function]"
+"returns true if every element of list1 matches some element of list2."
+
+SUBST 
+"new old tree &key :test :test-not :key"
+"[Function]"
+"creates a new tree based on tree, except that occurrences of old have been replaced with new. The
+original tree is not modified, but the new tree may share list structure with it."
+
+SUBST-IF 
+"new test tree &key :key"
+"[Function]"
+"creates a new tree based on tree, except that elements that satisfy test have been replaced with new.
+The original tree is not modified, but the new tree may share list structure with it."
+
+SUBST-IF-NOT 
+"new test tree &key :key"
+"[Function]"
+"creates a new tree based on tree, except that elements that don't satisfy test have been replaced with
+new. The original tree is not modified, but the new tree may share list structure with it."
+
+SUBSTITUTE 
+"new-item old-item sequence &key :start :end :from-end :count :test :test-not :key"
+"[Function]"
+"returns a new sequence equivalent to sequence except that occurrences of old-item within a given
+subsequence are replaced with new-item. The :count argument, if given, limits the number of
+substitutions which take place. The original sequence is not modified."
+
+SUBSTITUTE-IF 
+"new-item test sequence &key :start :end :from-end :count :key"
+"[Function]"
+"returns a sequence equivalent to sequence except that elements that satisfy test within the given
+subsequence are replaced with new-item. The :count argument, if given, limits the number of
+substitutions that take place. The original sequence is not modified."
+
+SUBSTITUTE-IF-NOT 
+"new-item test sequence &key :start :end :from-end :count :key"
+"[Function]"
+"returns a sequence equivalent to sequence except that elements that do not satisfy test within the
+given subsequence are replaced with new-item. The :count argument, if given, limits the number of
+substitutions that take place. The original sequence is not modified."
+
+SUBTYPEP 
+"type-1 type-2"
+"[Function]"
+"returns true if type-1 is definitely a subtype of type-2. If the result is nil, however, type1 may or
+may not be a subtype of type2. A second value is returned indicating the certainty of the result (t
+indicates that type1 definitely is or is not a subtype of type2; nil indicates that the result is
+uncertain). subtypep is not permitted to return a second value of nil unless one or both of its
+arguments involve satisfies, and, or, not, or member. When one or both of its arguments involve
+values or the list form of the function type specifier, subtypep returns an error."
+
+SVREF 
+"simple-vector index"
+"[Function]"
+"returns the element of simple-vector indicated by index."
+
+SXHASH 
+"thing"
+"[Function]"
+"computes a hash code for thing and returns it as a non-negative fixnum."
+
+SYMBOL-FUNCTION 
+"symbol"
+"[Function]"
+"returns the current global function definition named bysymbol. If the symbol has no function
+binding, symbol-function signals an error."
+
+SYMBOL-NAME 
+"symbol"
+"[Function]"
+"returns the print name of symbol as a string."
+
+SYMBOL-PACKAGE 
+"symbol"
+"[Function]"
+"returns the home package of symbol."
+
+SYMBOL-PLIST 
+"symbol"
+"[Function]"
+"returns the property list of symbol."
+
+SYMBOL-VALUE 
+"symbol"
+"[Function]"
+"returns the current value of the special variable named by symbol. An error is signalled if symbol is
+unbound."
+
+SYMBOLP 
+"object"
+"[Function]"
+"returns true if object is a symbol; otherwise returns false."
+
+T  
+NIL "[Constant]"
+"the general truth value in Common Lisp. t is a constant, a class, a stream, and a type."
+
+TAGBODY 
+"{tag | statement}*"
+"[Special Form]"
+"A tagbody consists of a mixture of tags and forms. The tags indicate positions in the tagbody. During
+execution, the statements are evaluated sequentially, except that (go tag ) may redirect execution to
+the position of any tag. If the end of the body is reached, tagbody returns nil."
+
+TAILP 
+"sublist list"
+"[Function]"
+"returns true if and only if there exists an integer n such that (eql sublist (nthcdr n list)). list may
+be a dotted list."
+
+TAN 
+"radians"
+"[Function]"
+"returns the tangent of radians, a number in radians."
+
+TANH 
+"radians"
+"[Function]"
+"returns the hyperbolic tangent of radians, a number in radians."
+
+TENTH 
+"list"
+"[Function]"
+"returns the tenth element of list, using one-based addressing."
+
+TERPRI 
+"&optional output-stream"
+"[Function]"
+"writes a newline character to output-stream and returns nil."
+
+THE 
+"type form"
+"[Special Form]"
+"instructs the compiler that form is of type type. This information can be used by the compiler for
+performing optimizations."
+
+THIRD 
+"list"
+"[Function]"
+"returns the third element (caddr) of list, using one-based addressing."
+
+THROW 
+"tag result"
+"[Special Form]"
+"causes the dynamically active catch named tag to immediately return the value of result. This
+involves exiting any processes begun from the point of the catch."
+
+TIME 
+"form"
+"[Macro]"
+"Executes form, prints the amount of time used in execution (with a special note on garbage collection
+time, if any), and returns the value returned by form. time is useful for testing and optimizing code."
+
+TRACE 
+"{symbol | (symbol {option [modifier] }*) }*"
+"[Macro]"
+"causes the function named by symbol to be traced. Whenever the function is called, information can
+be printed or other options can be performed. modifier specifies that actions can be performed
+:before or :after the function is traced; the modifier :step specifies that the function is stepped when
+it is run. Functions that are compiled in-line cannot be traced."
+
+TREE-EQUAL 
+"x y &key :test :test-not"
+"[Function]"
+"returns true of x and y are equivalent trees, that is, if they have the same shape and the leaves are
+equal. It is true for atoms if they are equal according to the test function (by default eql), and it is
+true for conses if both the car and cdr are tree-equal."
+
+TRUENAME 
+"pathname"
+"[Function]"
+"returns the true name of pathname. This is the name of the pathname as it is actually represented by
+the file system. An error is signalled if pathname does not indicate an actual file or directory."
+
+TRUNCATE 
+"number &optional divisor"
+"[Function]"
+"returns two values: the integer part of number (i.e. number with the fractional part removed), and
+the fractional part. When there is a second argument, truncate divides divisor into number first, and
+then applies truncate to the result."
+
+TYPE-OF 
+"thing"
+"[Function]"
+"returns a type of which thing is a member. Various constraints are now placed on type-of; see
+Common Lisp: The Language, p. 65-67, for clarification."
+
+TYPECASE 
+"keyform {(type {form}* )}*"
+"[Macro]"
+"evaluates keyform, then evaluates as an implicit progn the forms whose type matches the value of
+keyform. Returns the last form evaluated. keyform is evaluated, but the type is not. typecase permits
+a final type, otherwise or t, that handles all types not otherwise covered."
+
+TYPEP 
+"thing type"
+"[Function]"
+"returns true if thing is of type type; otherwise returns nil."
+
+UNEXPORT 
+"symbols &optional package"
+"[Function]"
+"makes symbols (which should be a symbol or list of symbols) become internal symbols in package
+(which defaults to *package*), and returns t. It is an error to unexport symbols from the keyword
+package."
+
+UNINTERN 
+"symbol &optional package"
+"[Function]"
+"deletes symbol from the package package. unintern returns true if it removes symbol and nil if the
+symbol was not interned in the first place."
+
+UNION 
+"list1 list2 &key :test :test-not :key"
+"[Function]"
+"returns a list containing the union of the elements list1 and list2. Any element that is contained in
+list1 or list2 will be contained in the result list. If there are duplicate entries, only one will appear
+in the result. list1 and list2 are not modified."
+
+UNLESS 
+"testform {thenform}*"
+"[Macro]"
+"evaluates testform. If the result is non-nil, then no thenforms are evaluated and unless returns nil.
+If the result is nil, evaluates thenforms as an implicit progn, sequentially from left to right, and
+returns the value of the last thenform."
+
+UNREAD-CHAR 
+"character &optional input-stream"
+"[Function]"
+"puts character , the most recently read charadcter, back onto the front of input-stream so that it
+will be read again as the next input character. Returns nil."
+
+UNTRACE 
+"{symbol}*"
+"[Macro]"
+"stops each function named by symbol from being traced. Notices will not be printed when the function
+enters or returns."
+
+UNUSE-PACKAGE 
+"packages-to-unuse &optional package-unusing"
+"[Function]"
+"removes packages-to-unuse to the use-list of package-unusing. packages-to-unuse should be a
+package, package-name, or list of packages and package-names. package-unusing may be a package
+name or package object."
+
+UNWIND-PROTECT 
+"protected-form {cleanup-form}*"
+"[Special Form]"
+"executes protected-form and the cleanup-forms. The cleanup-forms are guaranteed to be executed,
+even if there is a non-local exit during the execution of body-forms. unwind-protect returns the
+value of protected-form if the exit is normal."
+
+UPPER-CASE-P 
+"char"
+"[Function]"
+"returns true if char is an uppercase character; otherwise returns false. char must be a character."
+
+USE-PACKAGE 
+"packages-to-use &optional package-using"
+"[Function]"
+"adds packages-to-use to the use-list of package-using. The external symbols of packages-to-use will
+be directly accessible in package-using. packages-to-use should be a package, package-name, or list
+of packages and package-names. package-using may be a package name or package object."
+
+#|
+USER-HOMEDIR-PATHNAME 
+"&optional host"
+"[Function]"
+"returns the userÕs home directory. This is the expanded form of the \"home:\" logical host. When
+Macintosh Common Lisp files run on the Macintosh, the host argument is ignored."
+|#
+
+VALUES 
+"&rest things"
+"[Function]"
+"returns things in order as multiple values."
+
+VALUES-LIST 
+"list"
+"[Function]"
+"returns the elements of list as multiple values."
+
+VECTOR 
+"&rest objects"
+"[Function]"
+"creates a simple vector (a non-adjustable one-dimensional array without a fill-pointer) whose
+elements are objects."
+
+VECTOR-POP 
+"vector"
+"[Function]"
+"returns the element of vector indicated by vectorÕs fill pointer and decrements the fill pointer.
+vector must be a one-dimensional array that has a fill pointer."
+
+VECTOR-PUSH 
+"new-element vector"
+"[Function]"
+"stores new-element in vector at the location indicated by vectorÕs fill pointer and increments the fill
+pointer by one. Returns the previous value of the fill pointer, or nil if the fill pointer does not
+designate an element of vector. vector must be a one-dimensional array that has a fill pointer."
+
+VECTOR-PUSH-EXTEND 
+"new-element vector &optional extension"
+"[Function]"
+"stores new-element in vector at the location indicated by the fill pointer. If the fill pointer is already
+at the end of vector, vector-push-extend increases the size of vector by an amount given by
+extension. This function is equivalent to vector-push except that it increases the size of the vector if
+it is already full (provided the vector is adjustable). vector must be a one-dimensional array that
+has a fill pointer."
+
+VECTORP 
+"object"
+"[Function]"
+"returns true if object is a vector; otherwise returns false. A vector is a one-dimensional array."
+
+WARN 
+"datum &rest args"
+"[Function]"
+"warns about a situation by signaling a condition of type warning."
+
+WHEN 
+"testform {thenform}*"
+"[Macro]"
+"evaluates testform. If the result is nil, returns nil without evaluating any thenform. If the result is
+true, evaluates thenforms as an implicit progn, sequentially from left to right, and returns the value
+of the last thenform."
+
+WITH-INPUT-FROM-STRING 
+"(var string {keyword value}*) {declaration}* {form}*"
+"[Macro]"
+"executes forms with var bound to an input stream that reads characters from string and returns the
+results from the last form of the body. The keyword options are :index, :start, and :end. The stream
+created by this macro is always of type string-stream."
+
+WITH-OPEN-FILE 
+"(stream filename {option}*) {declaration}* {form}*"
+"[Macro]"
+"evaluates the forms with a stream stream that reads or writes to filename, and returns the value of
+the last form. The file is closed when the body of the with-open-file exits, even if the exit is through
+an error, throw, or return."
+
+WITH-OPEN-STREAM 
+"(variable stream) {declaration}* {form}*"
+"[Macro]"
+"evaluates the forms with stream open and bound to variable. The stream is guaranteed to be closed
+when with-open-stream exits, even if the exit is abnormal (as through a throw). The stream created
+by with-open-stream is always of type file-stream."
+
+WITH-OUTPUT-TO-STRING 
+"(var [string [:element-type type]]) {declaration}* {form}*"
+"[Macro]"
+"executes forms with var bound to a string output stream. If string is supplied, it must be adjustable
+and have a fill-pointer. The value of the last form is returned. If nil is supplied instead of string, the
+:element-type keyword may be used to specify what characters must be accepted by the created
+stream. The stream created by this macro is always of type string-stream."
+
+WITH-PACKAGE-ITERATOR 
+"(mname package-list {symbol-type}*) {form}*"
+"[Macro]"
+"mname is defined as if by macrolet with forms as its lexical scope, such that each invocation of
+(mname) returns a symbol. Successive invocations eventually deliver all the symbols matching
+symbol-types from the packages that are the elements of package-list, which is evaluated exactly
+once. Each invocation of mname returns nil if there are no more symbols to be processed in the
+current package. If symbols remain to be processed, the function returns four values: t, the symbol,
+a keyword indicating its accessibility, and the package from which it was accessed."
+
+WRITE 
+"object &key :stream :escape :radix :base :circle :pretty :level :length :case :gensym :array
+:readably :right-margin :miser-width :lines :pprint-dispatch :simple-bit-vector :simple-vector
+:string-length :structure"
+"[Function]"
+"writes the printed representation of object to the stream specified by :stream and returns object. The
+other keyword arguments specify values used to control the printed representation; each defaults to
+the value of its corresponding global variable."
+
+WRITE-BYTE 
+"integer binary-output-stream"
+"[Function]"
+"writes one byte, the value of integer, to binary-output-stream. It is an error if integer is not of the
+type specified as the :element-type argument for binary-output-stream."
+
+WRITE-CHAR 
+"character &optional output-stream"
+"[Function]"
+"writes character to output-stream, and returns character."
+
+WRITE-LINE 
+"string &optional output-stream &key :start :end"
+"[Function]"
+"sends the specified portion of string to output-stream (which defaults to *standard-output*),
+followed by a newline, and returns string."
+
+WRITE-STRING 
+"string &optional stream &key :start :end"
+"[Function]"
+"sends the specified portion of string to stream (which defaults to *standard-output*), and returns
+string."
+
+WRITE-TO-STRING 
+"thing &key :escape :radix :base :circle :pretty :level :length :case :gensym
+:array :readably :right-margin :miser-width :lines :pprint-dispatch :simple-bit-vector
+:simple-vector :string-length :structure"
+"[Function]"
+"thing is printed, as if by write, but the output is collected in a string, which is returned."
+
+Y-OR-N-P 
+"&optional format-string &rest format-args"
+"[Function]"
+"prints a message from format-string and format-args, followed by (y or n), and waits for the user
+to type y or n. Returns T if the user typed y, or nil if the user typed n."
+
+YES-OR-NO-P 
+"&optional format-string &rest args"
+"[Function]"
+"prints a message from format-string and args, followed by (yes or no), and waits for the user to
+type yes or no followed by a carriage return. Returns t if the user typed yes, nil if the user typed no."
+
+ZEROP 
+"number"
+"[Function]"
+"returns true if number is zero (either the integer zero, a floating-point zero, or a complex zero);
+otherwise returns nil. (zerop -0.0) is always true."
Index: /trunk/contrib/foy/hemlock-commands-cm/hemlock-commands-1.lisp
===================================================================
--- /trunk/contrib/foy/hemlock-commands-cm/hemlock-commands-1.lisp	(revision 13946)
+++ /trunk/contrib/foy/hemlock-commands-cm/hemlock-commands-1.lisp	(revision 13946)
@@ -0,0 +1,155 @@
+;;;-*-Mode: LISP; Package: HEMLOCK-COMMANDS -*-
+
+;;; ----------------------------------------------------------------------------
+;;;
+;;;      hemlock-commands-1.lisp
+;;;
+;;;      copyright (c) 2009 Glen Foy
+;;;      (Permission is granted to Clozure Associates to distribute this file.)
+;;;
+;;;      This code adds a Hemlock Commands documentation tool to the Context-Menu 
+;;;      mechanism.  Right-Click displays a listing of essential Hemlock Commands
+;;;      for the new users.  Selecting an entry executes the command.
+;;;
+;;;      This software is offered "as is", without warranty of any kind.
+;;;
+;;;      Mod History, most recent first:
+;;;      9/2/9   Removed doc-path from hemlock-commands-menu.
+;;;      8/31/9  version 0.1b1
+;;;              First cut.
+;;;
+;;; ----------------------------------------------------------------------------
+
+(defpackage "HEMLOCK-COMMANDS" (:nicknames "HCOM") (:use :cl :ccl))
+(in-package "HEMLOCK-COMMANDS")
+
+(require :context-menu-cm)
+(cmenu:check-hyperspec-availability "Hemlock-Commands-CM")
+
+(defparameter *hemlock-commands-menu* nil "The hemlock-commands-menu instance.")
+(defparameter *hemlock-commands-keyword-menu* nil "The hemlock-commands-keyword-menu instance.")
+
+;;; ----------------------------------------------------------------------------
+;;;
+(defclass HEMLOCK-COMMAND-MENU-ITEM (ns:ns-menu-item)
+  ((key-event :initform nil :accessor key-event))
+  (:documentation "Support for the hemlock-commands-menu.")
+  (:metaclass ns:+ns-object))
+
+
+;;; ----------------------------------------------------------------------------
+;;;
+(defclass HEMLOCK-COMMANDS-MENU (ns:ns-menu)
+  ((tool-menu :initform nil :accessor tool-menu)
+   (sub-title :initform "basic commands" :reader sub-title)
+   (text-view :initform nil :accessor text-view))
+  (:documentation "A popup menu listing a useful subset of Hemlock commands: Hemlock's Greatest Hits, for new users.")
+  (:metaclass ns:+ns-object))
+
+(objc:defmethod (#/hemlockCommandAction: :void) ((m hemlock-commands-menu) (sender :id))
+  (let ((key-event (key-event sender))) ; can be a vector of events
+    (cond ((typep key-event 'hi::key-event)
+           (hi::handle-hemlock-event (gui::hemlock-view (text-view m)) key-event))
+          ((typep (key-event sender) 'simple-vector)
+           (hi::handle-hemlock-event (gui::hemlock-view (text-view m)) (aref key-event 0))
+           (hi::handle-hemlock-event (gui::hemlock-view (text-view m)) (aref key-event 1))))))
+
+(defmethod initialize-instance :after ((menu hemlock-commands-menu) &key)
+  (flet ((create-menu-item (name key-event)
+           (let ((menu-item (make-instance 'hemlock-command-menu-item))
+                 (attributed-string (#/initWithString:attributes:
+                                     (#/alloc ns:ns-attributed-string) 
+                                     (ccl::%make-nsstring name)
+                                     cmenu:*hemlock-menu-dictionary*)))
+             (#/setAttributedTitle: menu-item attributed-string)
+             (#/setAction: menu-item (ccl::@selector "hemlockCommandAction:"))
+             (#/setTarget: menu-item  menu)
+             (setf (key-event menu-item) key-event)
+             (#/addItem: menu menu-item))))
+    (setf (tool-menu menu) (cmenu:add-default-tool-menu menu))
+    
+    ;;; Hemlock's Greatest Hits:
+    (create-menu-item "Inspect Symbol  (control-x, control-i)" 
+                      #k"control-x control-i")
+    (create-menu-item "Symbol Documentation  (control-x, control-d)" 
+                      #k"control-x control-d")
+    (#/addItem: menu (#/separatorItem ns:ns-menu-item))
+    (create-menu-item "Current Function Arglist  (control-x, control-a)" 
+                      #k"control-x control-a")
+    (create-menu-item "Goto Definition  (meta-.)"
+                      #k"meta-.")
+    (create-menu-item "Show Callers  (control-meta-c)" 
+                      #k"control-meta-c")
+    (#/addItem: menu (#/separatorItem ns:ns-menu-item))
+    (create-menu-item "Macroexpand-1 Expression  (control-m)"
+                      #k"control-m")
+    (create-menu-item "Macroexpand Expression  (control-x, control-m)" 
+                      #k"control-x control-m")
+    (#/addItem: menu (#/separatorItem ns:ns-menu-item))
+    (create-menu-item "Editor Evaluate Defun  (control-x, control-e)" 
+                      #k"control-x control-e")
+    (create-menu-item "Editor Compile Defun  (control-x, control-c)" 
+                      #k"control-x control-c")
+    (create-menu-item "Editor Evaluate Region  (Enter)"
+                      #k"enter")
+    #|
+    (create-menu-item "Editor Compile Region  (unbound)" 
+                      #k"enter")
+    (create-menu-item "Editor Evaluate Buffer  (unbound)"
+                      #k"enter")
+    (create-menu-item "Editor Compile Buffer File  (unbound)"
+                      #k"enter")
+    |#
+    (#/addItem: menu (#/separatorItem ns:ns-menu-item))
+    (create-menu-item "Incremental Search  (control-s)"
+                      #k"control-s")
+    (create-menu-item "I-Search Repeat Forward  (control-s)"
+                      #k"control-s")
+    (create-menu-item "I-Search Repeat Backward  (control-r)"
+                      #k"control-r")
+    (create-menu-item "I-Search Abort  (control-g)"
+                      #k"control-g")
+    (#/addItem: menu (#/separatorItem ns:ns-menu-item))
+    (create-menu-item "Kill Line  (control-k)"
+                      #k"control-k")
+    (create-menu-item "Un-Kill  (control-y)"
+                      #k"control-y")
+    (#/addItem: menu (#/separatorItem ns:ns-menu-item))
+    (create-menu-item "Forward Character  (control-f)"
+                      #k"control-f")
+    (create-menu-item "Backward Character  (control-b)"
+                      #k"control-b")
+    (create-menu-item "Beginning of Line  (control-a)"
+                      #k"control-a")
+    (create-menu-item "End of Line  (control-e)"
+                      #k"control-e")
+    (create-menu-item "Previous Line  (control-p)"
+                      #k"control-p")
+    (create-menu-item "Next Line  (control-n)"
+                      #k"control-n")
+    (create-menu-item "Beginning of Buffer  (meta-<)"
+                      #k"meta-\<")
+    (create-menu-item "End of Buffer  (meta->)"
+                      #k"meta-\>")
+    (create-menu-item "Scroll Window Down  (control-v)"
+                      #k"control-v")
+    (create-menu-item "Scroll Window Up  (meta-v)"
+                      #k"meta-v")))
+
+(objc:defmethod (#/update :void) ((self hemlock-commands-menu))
+  (cmenu:update-tool-menu self (tool-menu self) :sub-title (sub-title self))
+  (call-next-method))
+
+(setq *hemlock-commands-menu* (make-instance 'hemlock-commands-menu))
+
+(defun get-hemlock-commands-menu (view event)
+  "Return the appropriate Hemlock Commands menu based on modifier keys."
+  (cond ((logtest #$NSCommandKeyMask (#/modifierFlags event))
+         (setf (text-view *hemlock-commands-menu*) view)           
+         *hemlock-commands-menu*)
+        (t
+         *hemlock-commands-keyword-menu*)))
+
+(cmenu:register-tool "Hemlock-Commands-CM" #'get-hemlock-commands-menu)
+
+
Index: /trunk/contrib/foy/hemlock-commands-cm/hemlock-commands-2.lisp
===================================================================
--- /trunk/contrib/foy/hemlock-commands-cm/hemlock-commands-2.lisp	(revision 13946)
+++ /trunk/contrib/foy/hemlock-commands-cm/hemlock-commands-2.lisp	(revision 13946)
@@ -0,0 +1,155 @@
+;;;-*-Mode: LISP; Package: HEMLOCK-COMMANDS -*-
+
+;;; ----------------------------------------------------------------------------
+;;;
+;;;      hemlock-commands-2.lisp
+;;;
+;;;      copyright (c) 2009 Glen Foy
+;;;      (Permission is granted to Clozure Associates to distribute this file.)
+;;;
+;;;      This code adds a Hemlock Commands documentation tool to the Context-Menu 
+;;;      mechanism.  Right-Click displays a list of submenus.  The submenus are keywords.
+;;;      Popping the submenu displays entries for all Hemlock Commands filtered by that 
+;;;      keyword.  Selecting an entry opens a documentation dialog.
+;;;
+;;;      This software is offered "as is", without warranty of any kind.
+;;;
+;;;      Mod History, most recent first:
+;;;      8/31/9  version 0.1b1
+;;;              First cut.
+;;;
+;;; ----------------------------------------------------------------------------
+
+(in-package "HEMLOCK-COMMANDS")
+
+;;; ----------------------------------------------------------------------------
+;;;
+(defclass HEMLOCK-COMMAND-KEYWORD-MENU-ITEM (ns:ns-menu-item)
+  ((command :initform nil :accessor item-command))
+  (:documentation "Support for the hemlock command keyword menu.")
+  (:metaclass ns:+ns-object))
+
+(defun display-doc (command)
+  "Open the documentation dialog for COMMAND."
+  (let ((keystroke-string
+         (do* ((bindings (hi::command-%bindings command) (rest bindings))
+               (bindings-length (length bindings))
+               (binding (car bindings) (car bindings))
+               (event-array (when binding (car binding))
+                            (when binding (car binding)))
+               (num-events (when event-array (array-dimension event-array 0))
+                           (when event-array (array-dimension event-array 0)))
+               (keystrokes "" (if binding 
+                                (concatenate 'string keystrokes ",   ")
+                                keystrokes)))
+              ((or (null bindings) (> bindings-length 4))
+                   (if (> bindings-length 4)
+                     "Too many bindings ..."
+                     keystrokes))
+           (when event-array
+             (cond ((= num-events 1)
+                    (setq keystrokes 
+                          (concatenate 'string
+                                       keystrokes
+                                       (hi::pretty-key-string (aref event-array 0) t))))
+                   (t
+                    (setq keystrokes
+                          (concatenate 'string 
+                                       keystrokes
+                                       (format nil "~A  ~A" 
+                                               (hi::pretty-key-string (aref event-array 0) t)
+                                               (hi::pretty-key-string (aref event-array 1) t))))))))))
+    (open-documentation-dialog (hi::command-%name command)
+                             (if (string= keystroke-string "") "no binding" keystroke-string)
+                             (hi::command-documentation command) :hemlock-p t)))
+
+(defun populate-submenu (menu command-list)
+  "Make menu-items for all commands in COMMAND-LIST, and add them to MENU"
+  (dolist (command-cons (reverse command-list))
+    (let* ((command-name (car command-cons))
+           (command (cdr command-cons))
+           (menu-item (make-instance 'hemlock-command-keyword-menu-item))
+           (attributed-string (#/initWithString:attributes:
+                               (#/alloc ns:ns-attributed-string) 
+                               (ccl::%make-nsstring command-name)
+                               cmenu:*hemlock-menu-dictionary*)))
+      (#/setAttributedTitle: menu-item attributed-string)
+      (#/setAction: menu-item (ccl::@selector "hemlockCommandDocAction:"))
+      (#/setTarget: menu-item  *hemlock-commands-keyword-menu*)
+      ;; (#/setImage: menu-item class-icon)
+      (setf (item-command menu-item) command)
+      (#/addItem: menu menu-item))))
+
+(defun make-submenu-item (title command-list)
+  "Create a menu-item with a submenu, and populate the submenu with the commands in COMMAND-LIST."
+  (let ((menu-item (make-instance ns:ns-menu-item))
+        (attributed-string (#/initWithString:attributes:
+                            (#/alloc ns:ns-attributed-string) 
+                            (ccl::%make-nsstring title)
+                            cmenu:*hemlock-menu-dictionary*))
+        (submenu (make-instance ns:ns-menu)))
+    (#/setAttributedTitle: menu-item attributed-string)
+    (#/setSubmenu: menu-item submenu)
+    (populate-submenu submenu command-list)
+    menu-item))
+
+(defparameter *hemlock-command-keywords*
+  '("auto" "backward" "beginning" "buffer" "character" "command" "comment" "compile" "completion" "count" "defun" "delete" "describe"
+    "down" "echo" "editor" "end" "evaluate" "expression" "file" "form" "forward" "function" "goto" "help" "i-search"
+    "indent" "insert" "interactive" "kill" "line" "list" "macroexpand" "mark" "mode" "next" "paragraph" "parse"
+    "point" "pop" "previous" "query" "region" "register" "save" "search" "select" "sentence" "set" "show" "space" 
+    "transpose" "up" "what" "word" "write"))
+
+;;; ----------------------------------------------------------------------------
+;;;
+(defclass HEMLOCK-COMMANDS-KEYWORD-MENU (ns:ns-menu)
+  ((tool-menu :initform nil :accessor tool-menu)
+   (sub-title :initform "keyword filters" :reader sub-title)
+   (doc-path :initform (merge-pathnames ";ReadMe.rtf" cl-user::*hemlock-commands-directory*) :reader doc-path))
+  (:documentation "A popup menu with keyword submenus for filtering Hemlock commands.")
+  (:metaclass ns:+ns-object))
+
+(objc:defmethod (#/hemlockCommandDocAction: :void) ((m hemlock-commands-keyword-menu) (sender :id))
+  (display-doc (item-command sender)))
+
+(defmethod initialize-instance :after ((menu hemlock-commands-keyword-menu) &key)
+  (setf (tool-menu menu) (cmenu:add-default-tool-menu menu :doc-file (doc-path menu))))
+
+(defmethod add-submenus ((menu hemlock-commands-keyword-menu))
+  (let ((keyword-array (make-array  (length *hemlock-command-keywords*) :initial-element nil))
+        miscellaneous)
+    (dotimes (index (hi::string-table-num-nodes hi::*command-names*))
+      (let* ((idx 0)
+             (command (hi::value-node-value (aref (hi::string-table-value-nodes hi::*command-names*) index)))
+             (command-name (hi::command-%name command))
+             (entry-found-p nil))
+        (dolist (keyword *hemlock-command-keywords*)
+          ;; commands will generally have multiple entries
+          (when (search keyword command-name :test #'string-equal)
+            (setq entry-found-p t)
+            (push (cons command-name command) (aref keyword-array idx)))
+          (incf idx))
+      (unless entry-found-p (push (cons command-name command) miscellaneous))))
+    (let ((idx 0))
+      (dolist (keyword *hemlock-command-keywords*)
+        (let ((submenu-item (make-submenu-item keyword (coerce (aref keyword-array idx) 'list))))
+          (#/addItem: menu submenu-item))
+        (incf idx)))
+    (when miscellaneous
+      (#/addItem: menu (#/separatorItem ns:ns-menu-item))    
+      (let ((submenu-item (make-submenu-item "Commands Without Keywords:" miscellaneous)))
+        (#/addItem: menu submenu-item)))))
+
+
+(objc:defmethod (#/update :void) ((self hemlock-commands-keyword-menu))
+  (cmenu:update-tool-menu self (tool-menu self) :sub-title (sub-title self))
+  (call-next-method))
+
+
+(setq *hemlock-commands-keyword-menu* (make-instance 'hemlock-commands-keyword-menu))
+
+(add-submenus *hemlock-commands-keyword-menu*)
+
+
+
+
Index: /trunk/contrib/foy/hemlock-commands-cm/hemlock-commands-cm.lisp
===================================================================
--- /trunk/contrib/foy/hemlock-commands-cm/hemlock-commands-cm.lisp	(revision 13946)
+++ /trunk/contrib/foy/hemlock-commands-cm/hemlock-commands-cm.lisp	(revision 13946)
@@ -0,0 +1,24 @@
+
+;;; hemlock-commands.lisp
+
+(in-package :common-lisp-user) 
+
+(unless (member "HEMLOCK-COMMANDS-CM" *modules* :test #'string-equal)
+  
+(eval-when (:load-toplevel :execute)
+  (defParameter *hemlock-commands-directory*
+    (make-pathname :name nil :type nil :defaults (if *load-pathname* 
+                                                     *load-pathname*
+                                                     *loading-file-source-file*)))
+  (defParameter *hemlock-commands-files* 
+    (list (merge-pathnames ";hemlock-commands-1.lisp" *hemlock-commands-directory*)
+          (merge-pathnames ";hemlock-commands-2.lisp" *hemlock-commands-directory*)
+          (merge-pathnames ";hemlock-documentation-dialog.lisp" *hemlock-commands-directory*)
+          (merge-pathnames ";hemlock-commands-new.lisp" *hemlock-commands-directory*))))
+ 
+(dolist (file *hemlock-commands-files*)
+  (load file))
+
+(provide :hemlock-commands-cm)
+
+)
Index: /trunk/contrib/foy/hemlock-commands-cm/hemlock-commands-new.lisp
===================================================================
--- /trunk/contrib/foy/hemlock-commands-cm/hemlock-commands-new.lisp	(revision 13946)
+++ /trunk/contrib/foy/hemlock-commands-cm/hemlock-commands-new.lisp	(revision 13946)
@@ -0,0 +1,176 @@
+;;;-*-Mode: LISP; Package: HEMLOCK-COMMANDS-TOOL -*-
+
+;;; ----------------------------------------------------------------------------
+;;;
+;;;      hemlock-commands-new.lisp
+;;;
+;;;      copyright (c) 2009 Glen Foy
+;;;      (Permission is granted to Clozure Associates to distribute this file.)
+;;;
+;;;      This code implements a two new Hemlock commands.
+;;;
+;;;      This software is offered "as is", without warranty of any kind.
+;;;
+;;;      Mod History, most recent first:
+;;;      9/2/9   Added "Show Callers" command.
+;;;      8/31/9  version 0.1b1
+;;;              First cut.
+;;;
+;;; ----------------------------------------------------------------------------
+
+(in-package "HEMLOCK-COMMANDS")
+
+(defparameter *MCL-doc* (merge-pathnames ";MCL-doc.lisp" cl-user::*hemlock-commands-directory*))
+
+;;; Hemlock has some internal code to do this, but it appears to be broken 
+;;; and definitely does not work for ObjC methods.
+(defun parse-symbol ()
+  "Parse and return the symbol at point."
+  (let ((point (hi::current-point)))
+    (hemlock::pre-command-parse-check point)
+    (hi::with-mark ((mark1 point)
+                    (mark2 point))
+      (hemlock::mark-symbol mark1 mark2)
+      ;; For an objc method, mark-symbol removes the prepended #\#
+      (let* ((string (hi::region-to-string (hi::region mark1 mark2)))
+             (objc-p (when string (char= (elt string 0) #\/)))
+             (colons-start-position (when string
+                                      (unless objc-p (position #\: string))))
+             (colons-end-position (when colons-start-position
+                                    (if (char= (elt string (1+ colons-start-position)) #\:)
+                                      (1+ colons-start-position)
+                                      colons-start-position)))
+             (package-prefix (when colons-start-position
+                               (string-upcase (subseq string 0 colons-start-position))))
+             (sym-string (if colons-end-position
+                           (subseq string (incf colons-end-position))
+                           string))
+             (package (if objc-p
+                        (find-package "NEXTSTEP-FUNCTIONS")
+                        (when package-prefix (find-package package-prefix))))
+             symbol)
+        (when (and sym-string objc-p)
+          (setq sym-string (subseq sym-string 1))) ;chuck the #\/
+        (setq symbol (if package
+                       (if objc-p
+                         (find-symbol sym-string package)
+                         (find-symbol (string-upcase sym-string) package))
+                       (find-symbol (string-upcase sym-string) (hemlock::buffer-package hi::*current-buffer*))))
+        symbol))))
+
+(hemlock::defcommand "Inspect Symbol" (p)
+  "Open the Inspector for the symbol at point."
+  (declare (ignore p))
+  (let ((symbol (parse-symbol)))
+    (cond (symbol 
+           (inspect symbol))
+          (t
+           (hi::editor-error "Could not parse a valid symbol at point.")))))
+
+(hi::bind-key "Inspect Symbol" #k"control-x control-i")
+
+(defun MCL-documentation (symbol)
+  "Fetch the MCL documentation for SYMBOL."
+  (let ((path *MCL-doc*))
+    (when (probe-file path)
+      (with-open-file (stream path :direction :input)
+        (let (sym args type doc)
+          (loop
+            (setq sym (read stream nil :eof))
+            (setq args (read stream nil :eof))
+            (setq type (read stream nil :eof))
+            (setq doc (read stream nil :eof))
+            (cond ((eq sym :eof)
+                   (return-from MCL-documentation))
+                  ((eq sym symbol)
+                   (return (values args type doc))))))))))
+
+(defun display-ccl-doc (sym text-view)
+  "Display the CCL documentation for SYM, if it exists."
+  (let (docstring args)
+    (dolist (doctype '(compiler-macro function method-combination
+                                      setf structure t type variable))
+      (when (setq docstring (documentation sym doctype))
+        (when (eq doctype 'function) 
+          (setq args (arglist sym))
+          (when (macro-function sym) (setq doctype 'macro))
+          (when (special-form-p sym) (setq doctype 'special-form)))
+        (when (eq doctype 'type)
+          (when (find-class sym nil)
+            (setq doctype 'class)))
+        (open-documentation-dialog
+         (if args
+           (format nil "~A  ~A" (string-upcase sym) 
+                   (string-downcase (format nil "~A" args)))
+           (string-upcase sym))
+         (format nil "[~A]" (string-capitalize (string-downcase (string doctype))))
+         docstring :text-view text-view :symbol sym)
+        (return t)))))
+
+(defun display-mcl-doc (sym text-view)
+  "Display the MCL documentation for SYM, if it exists."
+  (multiple-value-bind (args type doc)
+                       (MCL-documentation sym)
+    (when doc
+      (setq doc (substitute #\space #\newline doc))
+      (open-documentation-dialog
+       (if args
+         (format nil "~A  ~A" (string-upcase sym) 
+                 (string-downcase (format nil "~A" args)))
+         (string-upcase sym)) 
+       type 
+       (concatenate 'string doc "    (MCL)")
+       :text-view text-view :symbol sym) t)))
+  
+(hi:defcommand "Symbol Documentation" (p)
+  "Display the documentation for the symbol at point."
+  (declare (ignore p))
+  (let* ((sym (parse-symbol))
+         (hemlock-view (hi::current-view))
+         (pane (when hemlock-view (hi::hemlock-view-pane hemlock-view)))
+         (text-view (when pane (gui::text-pane-text-view pane))))
+      (cond ((and sym text-view)
+             (cond ((eq (symbol-package sym) (find-package :common-lisp))
+                    (or (display-ccl-doc sym text-view)
+                        (display-mcl-doc sym text-view)
+                        (gui::lookup-hyperspec-symbol sym text-view)))
+                   (t
+                    (or (display-ccl-doc sym text-view)
+                        (open-documentation-dialog
+                         (format nil "No documentation found for ~S" sym) nil nil)))))
+            (t
+             (hi::editor-error "Could not parse a valid symbol at point.")))))
+
+(hi::bind-key "Symbol Documentation" #k"control-x control-d")
+
+(hi:defcommand "Show Callers" (p)
+  "Display a scrolling list of the callers of the symbol at point.
+   Double-click a row to go to the caller's definition."
+  (declare (ignore p))
+  (let* ((symbol (parse-symbol))
+         (callers (ccl::callers symbol)))
+    (cond (symbol
+           (if callers
+             (make-instance 'gui::sequence-window-controller
+               :title (format nil "Callers of ~a" symbol)
+               :sequence (mapcar #'(lambda (entry)
+                                     (if (listp entry)
+                                       (car (last entry))
+                                       entry))
+                                 (ccl::callers symbol))
+               :result-callback #'hemlock::edit-definition
+               :display #'princ)
+             (gui::alert-window :title "Notification"
+                                :message (format nil "Could not find any callers for ~S" symbol))))
+          (t
+           (hi::editor-error "Could not parse a valid symbol at point.")))))
+
+(hi::bind-key "Show Callers" #k"control-meta-c")
+
+
+
+
+
+
+
+
Index: /trunk/contrib/foy/hemlock-commands-cm/hemlock-documentation-dialog.lisp
===================================================================
--- /trunk/contrib/foy/hemlock-commands-cm/hemlock-documentation-dialog.lisp	(revision 13946)
+++ /trunk/contrib/foy/hemlock-commands-cm/hemlock-documentation-dialog.lisp	(revision 13946)
@@ -0,0 +1,281 @@
+;;;-*-Mode: LISP; Package: HEMLOCK-COMMANDS -*-
+
+;;; ----------------------------------------------------------------------------
+;;;
+;;;      hemlock-documentation-dialog.lisp
+;;;
+;;;      copyright Â© 2009 Glen Foy
+;;;      (Permission is granted to Clozure Associates to distribute this file.)
+;;;
+;;;      A documentation dialog for Hemlock commands, CL function, symbols, etc.
+;;;
+;;;      This software is offered "as is", without warranty of any kind.
+;;;
+;;;      Mod History, most recent first:
+;;;      8/31/9  version 0.1b1
+;;;              First cut.
+;;;
+;;; ----------------------------------------------------------------------------
+
+(in-package "HEMLOCK-COMMANDS")
+
+(defparameter *doc-dialog* nil)
+(defparameter *hemlock-jpg* (merge-pathnames ";Hemlock.jpg" cl-user::*hemlock-commands-directory*))
+;;; I don't know the name of the artist who drew this graphic, but it is quite nice.
+;;; I also don't know what the copyright issues are, so this will have to be replaced when I get a chance:
+(defparameter *graphic-p* nil "To use, or not to use the eye candy.")
+
+
+;;; ----------------------------------------------------------------------------
+;;;
+(defclass doc-dialog (ns:ns-window)
+  ((name :accessor name)
+   (symbol :accessor symbol)
+   (name-field :accessor name-field)
+   (key-field :accessor key-field)
+   (doc-text-view :accessor doc-text-view)
+   (hemlock-p :initform nil :accessor hemlock-p)
+   (hyperspec-button :accessor hyperspec-button)
+   (inspect-button :accessor inspect-button)
+   (okay-button :accessor okay-button)
+   (source-button :accessor source-button)
+   (text-view :accessor text-view))
+  (:documentation "A dialog for displaying the documentation of Hemlock Commands, CL function, non-CL functions, etc.")
+  (:metaclass ns:+ns-object))
+
+(objc:defmethod (#/closeAction: :void) ((d doc-dialog) (sender :id))
+  (declare (ignore sender))
+  (#/close d))
+
+(objc:defmethod (#/hyperSpecAction: :void) ((d doc-dialog) (sender :id))
+  (declare (ignore sender))
+  (when (symbol d) 
+    (gui::lookup-hyperspec-symbol (symbol d) (text-view d))))
+
+(objc:defmethod (#/inspectSymbolAction: :void) ((d doc-dialog) (sender :id))
+  (declare (ignore sender))
+  (when (symbol d)
+    (inspect (symbol d))))
+
+;;; Should probably just make Hemlock-Commands require List-Definitions:
+#+:list-definitions
+(objc:defmethod (#/commandSourceAction: :void) ((d doc-dialog) (sender :id))
+  (declare (ignore sender))
+  (cond ((hemlock-p d)
+         (let* ((search-string (format nil "(defcommand \"~A\"" (name d)))
+                (hemlock-src-dir (merge-pathnames "cocoa-ide/hemlock/src/" (native-translated-namestring "ccl:")))
+                (files (mapcar #'namestring
+                               (remove-if #'(lambda (path)
+                                              (string-not-equal (pathname-type path) "lisp"))
+                                          (directory (merge-pathnames hemlock-src-dir "*.lisp") :files t :directories nil))))
+                (args (cons "-l" (cons search-string files)))
+                (source-path (string-trim '(#\newline #\space) (gui::call-grep args))))
+           (if (and (stringp source-path) (string-not-equal source-path ""))
+             (ldefs:find-and-display-definition (format nil "~S" (name d)) source-path)
+             (cmenu:notify (format nil "Could not find: ~S" (name d))))))
+        (t
+         (hemlock::edit-definition (symbol d)))))
+
+#-:list-definitions
+(objc:defmethod (#/commandSourceAction: :void) ((d doc-dialog) (sender :id))
+  (declare (ignore sender))
+  (cond ((hemlock-p d)
+         ;; deactivate the button instead of this?
+         (gui::alert-window :title "Notification" :message "Searching for source requires the List-Definitions tool."))
+        (t
+         (hemlock::edit-definition (symbol d)))))
+
+
+(defun open-documentation-dialog (name key-or-type doc &key symbol hemlock-p text-view)
+  "Open the dialog displaying the documentation for NAME."
+  (let* ((name-string (#/initWithString:attributes: (#/alloc ns:ns-attributed-string) 
+                                                   (ccl::%make-nsstring 
+                                                    (if hemlock-p
+                                                      ;; *** ~S
+                                                      (string-upcase (format nil "\"~A\"" name))
+                                                      (format nil "~A" name)))
+                                                   cmenu::*tool-label-dictionary*))
+        (key-string (#/initWithString:attributes: (#/alloc ns:ns-attributed-string) 
+                                                  (if key-or-type
+                                                    (ccl::%make-nsstring key-or-type)
+                                                    (ccl::%make-nsstring " "))
+                                                  cmenu::*tool-key-dictionary*))
+         (inspect-p doc) ; "No documentation found"
+         (source-p (when symbol (ccl::%source-files symbol)))
+         (hyperspec-p (when (and symbol text-view) (gethash symbol (gui::hyperspec-map-hash text-view)))))
+    (cond (*doc-dialog*
+           (cond (hemlock-p
+                  (setf (hemlock-p *doc-dialog*) t)
+                  (#/setTitle: *doc-dialog* #@"Hemlock Command Documentation")
+                  (#/setHidden: (inspect-button *doc-dialog*) t)
+                  (#/setHidden: (hyperspec-button *doc-dialog*) t))
+                 (t
+                  (setf (hemlock-p *doc-dialog*) nil)
+                  (if source-p
+                    (#/setEnabled: (source-button *doc-dialog*) t)
+                    (#/setEnabled: (source-button *doc-dialog*) nil))
+                  (if inspect-p
+                    (#/setEnabled: (inspect-button *doc-dialog*) t)
+                    (#/setEnabled: (inspect-button *doc-dialog*) nil))
+                  (#/setHidden: (hyperspec-button *doc-dialog*) nil)
+                  (#/setHidden: (inspect-button *doc-dialog*) nil)
+                  (#/setTitle: *doc-dialog* #@"Documentation")))
+           (setf (name *doc-dialog*) name)
+           (setf (symbol *doc-dialog*) symbol)
+           (setf (text-view *doc-dialog*) text-view)
+           (if hyperspec-p 
+             (#/setEnabled: (hyperspec-button *doc-dialog*) t)
+             (#/setEnabled: (hyperspec-button *doc-dialog*) nil))
+           (#/setStringValue: (name-field *doc-dialog*) name-string)
+           (#/setStringValue: (key-field *doc-dialog*) key-string)
+           (#/setString: (doc-text-view *doc-dialog*) (if doc (ccl::%make-nsstring doc) #@""))
+           (#/makeKeyAndOrderFront: *doc-dialog* nil))
+          (t
+           (let ((dialog (#/alloc doc-dialog)))
+             (setq *doc-dialog* dialog)
+             (ns:with-ns-rect (r 100 100 (if *graphic-p* 625 475) 230)
+               (#/initWithContentRect:styleMask:backing:defer: 
+                dialog
+                r
+                (logior  #$NSTitledWindowMask 
+                         #$NSClosableWindowMask  
+                         #$NSMiniaturizableWindowMask)
+                #$NSBackingStoreBuffered
+                #$NO))
+             (dolist (item (get-items dialog))
+               (#/addSubview: (#/contentView dialog) item))
+             (cond (hemlock-p
+                  (setf (hemlock-p dialog) t)
+                  (#/setTitle: dialog #@"Hemlock Command Documentation")
+                  (#/setHidden: (inspect-button dialog) t)
+                  (#/setHidden: (hyperspec-button dialog) t))
+                 (t
+                  (setf (hemlock-p dialog) nil)
+                  (if source-p
+                    (#/setEnabled: (source-button dialog) t)
+                    (#/setEnabled: (source-button dialog) nil))
+                  (if inspect-p
+                    (#/setEnabled: (inspect-button *doc-dialog*) t)
+                    (#/setEnabled: (inspect-button *doc-dialog*) nil))
+                  (#/setHidden: (hyperspec-button dialog) nil)
+                  (#/setHidden: (inspect-button dialog) nil)
+                  (#/setTitle: dialog #@"Documentation")))
+             (if hyperspec-p 
+               (#/setEnabled: (hyperspec-button *doc-dialog*) t)
+               (#/setEnabled: (hyperspec-button *doc-dialog*) nil))
+             (#/setReleasedWhenClosed: dialog nil)
+             (#/setDefaultButtonCell: dialog (okay-button dialog))
+             (#/center dialog)
+             (#/setStringValue: (name-field dialog) name-string)
+             (#/setStringValue: (key-field dialog) key-string)
+             (#/setString: (doc-text-view dialog) (if doc (ccl::%make-nsstring doc) #@""))
+             (setf (name dialog) name)
+             (setf (symbol dialog) symbol)
+             (setf (text-view dialog) text-view)
+             (#/makeKeyAndOrderFront: dialog nil))))))
+
+;;; This is a redefintion of the function in cl-documentation-1.lisp
+(defun cldoc::display-cl-doc (sym text-view)
+  "If there is CCL or MCL doc, use the doc-dialog to display documentation.  Otherwise use the HyperSpec."
+  (when (eq (symbol-package sym) (find-package :common-lisp))
+    (or (display-ccl-doc sym text-view)
+        (display-mcl-doc sym text-view)
+        (gui::lookup-hyperspec-symbol sym text-view))))
+
+(defmethod get-items ((d doc-dialog))
+  (append
+   (when *graphic-p* 
+     (make-hemlock-image))
+   (make-name-field d)
+   (make-key-field d)
+   (make-doc-text-view d)
+   (make-buttons d)))
+
+(defun make-hemlock-image ()
+  "Create the Hemlock graphic.  You can make this go away by set *graphic-p* to nil above."
+  (let ((image (#/alloc ns:ns-image))
+        (image-view (#/alloc ns:ns-image-view)))
+    (ns:with-ns-rect (frame 10 54 141 164)
+      (#/initWithFrame: image-view frame))
+    (#/initWithContentsOfFile: image (ccl::%make-nsstring (namestring *hemlock-jpg*)))
+    (#/setImage: image-view image)
+    (list image-view)))
+
+(defun make-name-field (dialog)
+  "Create the name text-field."
+  (list
+   (let* ((title (#/alloc ns:ns-text-field)))
+     (ns:with-ns-rect (frame (if *graphic-p* 165 15) 178 440 38)
+       (#/initWithFrame: title frame))
+     (#/setEditable: title nil)
+     (#/setDrawsBackground: title nil)
+     (#/setBordered: title nil)
+     (#/setStringValue: title #@"")
+     (setf (name-field dialog) title))))
+
+(defun make-key-field (dialog)
+  "Create the key text-field."
+  (list
+   (let* ((title (#/alloc ns:ns-text-field)))
+     (ns:with-ns-rect (frame (if *graphic-p* 165 15) 162 450 16)
+       (#/initWithFrame: title frame))
+     (#/setEditable: title nil)
+     (#/setDrawsBackground: title nil)
+     (#/setBordered: title nil)
+     (#/setStringValue: title #@"")
+     (setf (key-field dialog) title))))
+
+(defun make-doc-text-view (dialog)
+  "Create the documentation text-view."
+  (list
+   (let* ((scroll-view (#/alloc ns:ns-scroll-view))
+          (view (#/init (#/alloc ns:ns-text-view))))
+     (ns:with-ns-rect (frame (if *graphic-p* 165 15) 54 460 106)
+       (#/initWithFrame: scroll-view frame))
+     (ns:with-ns-rect (frame 4 60 445 200)
+       (#/initWithFrame: view frame))
+     (#/setString: view #@" ")
+     (#/setHasVerticalScroller: scroll-view t)
+     (#/setHasHorizontalScroller: scroll-view nil)
+     (#/setBorderType: scroll-view #$NSBezelBorder)
+     (#/setDocumentView: scroll-view view)
+     (#/setEditable: view nil)
+     (#/setFont: view (#/systemFontOfSize: ns:ns-font (#/smallSystemFontSize ns:ns-font)))
+     (#/setTextColor: view cmenu:*dark-turquoise-color*)
+     (#/setBackgroundColor: view cmenu:*light-gray-color*)
+     (setf (doc-text-view dialog) view)
+     scroll-view)))
+
+
+(defun make-buttons (dialog)
+  "Construct the buttons."
+  (flet ((make-button (title x-coord y-coord x-dim y-dim action)
+           (let ((button (#/alloc ns:ns-button)))
+             (ns:with-ns-rect (frame x-coord y-coord x-dim y-dim)
+               (#/initWithFrame: button frame))
+             (#/setButtonType: button #$NSMomentaryPushInButton)
+             ; (#/setImagePosition: button #$NSNoImage)
+             (#/setBezelStyle: button #$NSRoundedBezelStyle)
+             (#/setTitle: button title)
+             (#/setTarget: button dialog)
+             (#/setAction: button action)
+             button)))
+    (list
+     (setf (okay-button dialog)
+           (make-button #@"Okay" (if *graphic-p* 520 370) 10 80 32
+                        (ccl::@selector "closeAction:")))
+     (setf (source-button dialog)
+           (make-button #@"Source..." (if *graphic-p* 420 270) 10 90 32
+                        (ccl::@selector "commandSourceAction:")))
+     (setf (inspect-button dialog)
+           (make-button #@"Inspect..." (if *graphic-p* 320 170) 10 90 32
+                        (ccl::@selector "inspectSymbolAction:")))
+     (setf (hyperspec-button dialog)
+           (make-button #@"HyperSpec..." (if *graphic-p* 180 30) 10 130 32
+                        (ccl::@selector "hyperSpecAction:"))))))
+
+
+
+
+
+
Index: /trunk/contrib/foy/list-definitions-cm/history-lists.lisp
===================================================================
--- /trunk/contrib/foy/list-definitions-cm/history-lists.lisp	(revision 13946)
+++ /trunk/contrib/foy/list-definitions-cm/history-lists.lisp	(revision 13946)
@@ -0,0 +1,571 @@
+;;;-*- Mode: Lisp; Package: LIST-DEFINITIONS -*-
+
+;;; ----------------------------------------------------------------------------
+;;;
+;;;      history-lists.lisp
+;;;
+;;;      copyright (c) 2009 Glen Foy
+;;;      (Permission is granted to Clozure Associates to distribute this file.)
+;;;
+;;;      This code supports file and position history lists.
+;;;
+;;;      Alt-Right-Click produces a most-recently-visited list of definition 
+;;;      positions.  Alt-Command-Right-Click produces a most-recently-visited
+;;;      list of files.  Both lists are persistent and are stored here:
+;;;
+;;;      ~/Library/Preferences/org.clairvaux/list-definitions/file-history
+;;;      ~/Library/Preferences/org.clairvaux/list-definitions/position-history
+;;;
+;;;      This software is offered "as is", without warranty of any kind.
+;;;
+;;;      Mod History, most recent first:
+;;;      8/31/9  version 0.2b2
+;;;              Modified to work with Context-Menu mechanism.
+;;;      8/17/9  version 0.2b1
+;;;              This file added.
+;;;
+;;; ----------------------------------------------------------------------------
+
+(in-package "LIST-DEFINITIONS")
+
+(defParameter *position-history-list-length* 25)
+(defParameter *file-history-list-length* 25)
+
+(defun maybe-open-file (path)
+  "If a window with PATH is open, return it.  Otherwise open a new window."
+  (let ((w (cmenu:window-with-path path)))
+    (if w 
+      w
+      (let ((hemlock-view (gui::cocoa-edit path)))
+        (when hemlock-view (#/window (hi::hemlock-view-pane hemlock-view)))))))
+
+(defun construct-history-path (filename)
+  "Construct the path to the history file."
+    (merge-pathnames (concatenate 'string 
+                                  ";Library;Preferences;org.clairvaux;list-definitions;" 
+                                  filename)
+                     (hemlock::user-homedir-pathname)))
+
+
+;;; ----------------------------------------------------------------------------
+;;;
+(defClass HISTORY-LIST-ENTRY ()
+  ((name :initarg :name :reader hle-name)
+   (path :initarg :path :reader hle-path))
+  (:documentation "Support for the history lists."))  
+
+;;; ----------------------------------------------------------------------------
+;;;
+(defClass POSITION-LIST-ENTRY (history-list-entry) 
+  ((info :initarg :info :reader hle-info))
+  (:documentation "Support for the position history list."))
+
+(defMethod show-entry ((entry position-list-entry))
+  "Display the file and scroll to position."
+  (let* ((name (hle-name entry))
+         (path (hle-path entry))
+         (window (cmenu:window-with-path path))
+         mark def-list text-view hemlock-view)
+    (unless (probe-file path)
+      (cmenu:notify (format nil "~a does not exist.  It will be deleted from the history lists."
+                      path))
+      (purge-file-references *position-history-list* path)
+      (remove-path *file-history-list* path)
+      (return-from show-entry nil))
+    (cond (window 
+           (setq hemlock-view (gui::hemlock-view window))
+           (setq text-view (gui::text-pane-text-view (hi::hemlock-view-pane hemlock-view))))
+          (t
+           (setq hemlock-view (gui::cocoa-edit path))
+           (when hemlock-view
+             (setq window (#/window (hi::hemlock-view-pane hemlock-view)))
+             (setq text-view (gui::text-pane-text-view (hi::hemlock-view-pane hemlock-view))))))
+    (when window
+      (#/makeKeyAndOrderFront: window nil)
+      (setq def-list (list-definitions window))
+      (setq mark (cdr (assoc name def-list 
+                             :test #'string-equal
+                             :key #'(lambda (def-info)
+                                      (let ((def-type (first def-info)))
+                                        (if (or (eq def-type :defmethod)
+                                                (eq def-type :objc))
+                                          (third def-info)
+                                          (second def-info)))))))
+      (cond (mark
+             (display-position text-view mark)
+             (move-entry-to-front *file-history-list* path) t)
+            (t 
+             (cmenu:notify (format nil "Cannot find ~S.  It will be deleted from the position history list." 
+                             name))
+             (remove-entry *position-history-list* name) nil)))))
+
+;;; ----------------------------------------------------------------------------
+;;;
+(defClass FILE-LIST-ENTRY (history-list-entry) 
+  ((short-path :initarg :short-path :accessor hle-short-path))
+  (:documentation "Support for the file history list."))
+
+(defMethod show-entry ((entry file-list-entry))
+  (let ((path (hle-path entry)))
+    (unless (probe-file path)
+      (cmenu:notify (format nil "~S does not exist.  It will be deleted from the history lists." path))
+      (purge-file-references *position-history-list* path)
+      (remove-path *file-history-list* path)
+      (return-from show-entry nil))
+    (let ((window (cmenu:window-with-path path))) 
+      (unless window 
+        (let ((hemlock-view (gui::cocoa-edit path)))
+          (when hemlock-view 
+            (setq window (#/window (hi::hemlock-view-pane hemlock-view))))))
+      (when window
+        (#/makeKeyAndOrderFront: window nil) t))))
+
+;;; ----------------------------------------------------------------------------
+;;;
+(defClass HISTORY-LIST ()
+  ((capacity :initarg :capacity :reader hl-capacity)
+   (path :initarg :path :reader hl-path)
+   (list :initform nil :accessor hl-list))
+  (:documentation "Super class of position-history-list and file-history-list."))
+
+;;; ----------------------------------------------------------------------------
+;;;
+(defClass POSITION-HISTORY-LIST (history-list) 
+  ()
+  (:documentation "A persistent history list of most-recently-visited definition positions."))
+
+(setq *position-history-list* (make-instance 'position-history-list 
+                                :path (construct-history-path "position-history")
+                                :capacity *position-history-list-length*))
+
+(defMethod find-entry ((hl position-history-list) name)
+  (find-if  #'(lambda (entry) (string-equal name (hle-name entry)))
+            (hl-list hl)))
+
+(defMethod move-entry-to-front ((hl position-history-list) name)
+  (let ((entry (find-entry hl name)))
+    (when entry
+      (setf (hl-list hl) 
+            (cons entry (delete name (hl-list hl) :test #'string-equal :key #'hle-name)))
+      entry)))
+
+(defMethod purge-file-references ((hl position-history-list) path)
+  (setf (hl-list hl) (delete-if #'(lambda (entry)
+                                    (equal (hle-path entry) path))
+                                (hl-list hl))))
+
+(defMethod remove-entry ((hl position-history-list) name)
+  (setf (hl-list hl) (delete name (hl-list hl) :test #'string-equal :key #'hle-name)))
+
+(defMethod add-history-entry ((hl position-history-list) def-info path)
+  (let* ((def-type (first def-info))
+         (name (second def-info))
+         (signature (third def-info))
+         (entry (make-instance 'position-list-entry 
+                  :name (if (or (eq def-type :defmethod)
+                                (eq def-type :objc))
+                          signature
+                          name)
+                  :info def-info :path path)))
+    (setf (hl-list hl) (cons entry (hl-list hl)))
+    entry))
+
+(defMethod maybe-add-history-entry ((hl position-history-list) def-info path)
+  (let* ((def-type (first def-info))
+         (name (if (or (eq def-type :defmethod)
+                       (eq def-type :objc))
+                 (third def-info)
+                 (second def-info))))
+    (cond ((member name (hl-list hl) :test #'string-equal :key #'hle-name)
+           ;; it's there; move it to the front:
+           (move-entry-to-front hl name))
+          (t
+           (when (>= (length (hl-list hl)) (hl-capacity hl))
+             ;; bump the last entry, then add:
+             (setf (hl-list hl) (butlast (hl-list hl))))
+           (add-history-entry hl def-info path)))))
+
+(defun clear-position-history-list()
+  "Remove all the entries from the position history list."
+  (setf (hl-list *position-history-list*) nil))
+
+;;; ----------------------------------------------------------------------------
+;;;
+(defClass FILE-HISTORY-LIST (history-list) 
+  ()
+  (:documentation "A persistent history list of most-recently-visited files."))
+
+(setf *file-history-list* (make-instance 'file-history-list
+                            :path (construct-history-path "file-history")
+                            :capacity *file-history-list-length*))
+
+(defMethod find-entry ((hl file-history-list) path)
+  (find-if  #'(lambda (entry) (string-equal path (hle-path entry)))
+            (hl-list hl)))
+
+(defMethod move-entry-to-front ((hl file-history-list) path)
+  (let ((entry (find-entry hl path))) 
+    (when entry
+      (setf (hl-list hl) 
+            (cons entry (delete path (hl-list hl) :test #'string-equal :key #'hle-path)))
+      entry)))
+
+(defmethod remove-path ((hl file-history-list) path)
+  (setf (hl-list hl) (delete path (hl-list hl) 
+                             :test #'string-equal :key #'hle-path)))
+
+(defMethod add-history-entry ((hl file-history-list) name path)
+  (let* ((name-position (position #\/ path :test #'char= :from-end t))
+         (short-path (when name-position (subseq path 0 (incf name-position))))
+         (entry (when short-path (make-instance 'file-list-entry :name name 
+                                   :short-path short-path :path path))))
+    (when entry
+      (setf (hl-list hl) (cons entry (hl-list hl)))
+      entry)))
+
+(defMethod maybe-add-history-entry ((hl file-history-list) name path)
+  (cond ((member path (hl-list hl) :test #'string-equal :key #'hle-path)
+         (move-entry-to-front hl path))
+        (t 
+         (cond ((< (length (hl-list hl)) (hl-capacity hl))
+                (add-history-entry hl name path))
+               (t 
+                (setf (hl-list hl) (butlast (hl-list hl)))
+                (add-history-entry hl name path))))))
+
+(defun clear-file-history-list ()
+  "Remove all the entries from the file history list."
+  (setf (hl-list *file-history-list*) nil))
+
+;;; ----------------------------------------------------------------------------
+;;;
+(defclass POSITION-MENU-ITEM (ns:ns-menu-item)
+   ((path :accessor position-path)
+    (name :accessor position-name))
+  (:documentation "Support for the positions popup menu.")
+  (:metaclass ns:+ns-object))
+
+;;; ----------------------------------------------------------------------------
+;;;
+(defclass POSITIONS-MENU (ns:ns-menu)
+  ((tool-menu :initform nil :accessor tool-menu)
+   (sub-title :initform "position history" :reader sub-title))
+  (:documentation "A popup menu of most-recently-visited definition positions.")
+  (:metaclass ns:+ns-object))
+
+;;; Pressing the shift key when selecting an entry will delete the entry:
+(objc:defmethod (#/positionHistoryAction: :void) ((m positions-menu) (sender :id))
+  (let ((entry (find-entry *position-history-list* (position-name sender))))
+    (when entry
+      (cond ((gui::current-event-modifier-p #$NSShiftKeyMask)
+             (remove-entry *position-history-list* (position-name sender)))
+            (t
+             (show-entry entry)
+             (move-entry-to-front *position-history-list* (position-name sender)))))))
+
+(objc:defmethod (#/clearPositionHistoryAction: :void) ((m positions-menu) (sender :id))
+  (declare (ignore sender))
+  (clear-position-history-list))
+
+(objc:defmethod (#/update :void) ((self positions-menu))
+  (cmenu:update-tool-menu self (tool-menu self) :sub-title (sub-title self))
+  (call-next-method))
+
+(defun positions-context-menu ()
+  "Create the positions context menu."
+  (let* ((menu (make-instance 'positions-menu))
+         (class-icon (#/iconForFileType: (#/sharedWorkspace ns:ns-workspace) (ccl::%make-nsstring "lisp")))
+          menu-item)
+    (ns:with-ns-size (icon-size 16 16)
+      (#/setSize: class-icon icon-size))
+    (setf (tool-menu menu) (cmenu:add-default-tool-menu menu))
+    (dolist (entry (hl-list *position-history-list*))
+      (let* ((def-info (hle-info entry))
+             (def-type (first def-info))
+             (name (second def-info))
+             (signature (third def-info))
+             (dictionary (case def-type
+                           (:defclass *defclass-dictionary*)
+                           (:defstruct *defstruct-dictionary*)
+                           (:defmethod *defmethod-dictionary*)
+                           (:defun *defun-dictionary*)
+                           (:defmacro *defmacro-dictionary*)
+                           (:objc *objc-dictionary*)
+                           (t *generic-dictionary*)))
+             (attributed-string (#/initWithString:attributes:
+                                 (#/alloc ns:ns-attributed-string) 
+                                 (if (or (eq def-type :defmethod)
+                                         (eq def-type :objc))
+                                   (ccl::%make-nsstring signature)
+                                   (ccl::%make-nsstring name))
+                                 dictionary)))
+        (setq menu-item (make-instance 'position-menu-item))
+        (setf (position-path menu-item) (hle-path entry))
+        (if (or (eq def-type :defmethod) (eq def-type :objc))
+          (setf (position-name menu-item) signature)
+          (setf (position-name menu-item) name))
+        (#/setAttributedTitle: menu-item attributed-string)
+        ;; Classes have a prepended CCL icon:
+        (when (eq def-type :defclass) (#/setImage: menu-item class-icon))
+        (#/setAction: menu-item (ccl::@selector "positionHistoryAction:"))
+        (#/setTarget: menu-item  menu)
+        (#/addItem: menu menu-item)))
+    (#/addItem: menu (#/separatorItem ns:ns-menu-item))
+    (let ((attributed-string (#/initWithString:attributes:
+                              (#/alloc ns:ns-attributed-string)
+                              (ccl::%make-nsstring "Clear List")
+                              *generic-dictionary*)))
+      (setq menu-item (make-instance 'ns:ns-menu-item))
+      (#/setAttributedTitle: menu-item attributed-string)
+      (#/setTarget: menu-item menu)
+      (#/setAction: menu-item (ccl::@selector "clearPositionHistoryAction:"))
+      (#/addItem: menu menu-item))
+    menu))
+
+;;; ----------------------------------------------------------------------------
+;;; 
+(defclass FILE-MENU-ITEM (ns:ns-menu-item)
+   ((path :accessor file-path)
+    (name :accessor file-name))
+  (:documentation "Support for the files popup menu.")
+  (:metaclass ns:+ns-object))
+
+;;; ----------------------------------------------------------------------------
+;;;
+(defclass FILE-MENU (ns:ns-menu)
+  ((tool-menu :initform nil :accessor tool-menu)
+   (sub-title :initform "file history" :reader sub-title))
+  (:documentation "A popup menu of most-recently-visited files.")
+  (:metaclass ns:+ns-object))
+
+;;; Pressing the shift key when selecting an entry will delete the entry:
+(objc:defmethod (#/fileHistoryAction: :void) ((m file-menu) (sender :id))
+  (let ((entry (find-entry *file-history-list* (file-path sender))))
+    (when entry
+      (cond ((gui::current-event-modifier-p #$NSShiftKeyMask)
+             (remove-path *file-history-list* (file-path sender)))
+            (t
+             (show-entry entry)
+             (move-entry-to-front *file-history-list* (file-path sender)))))))
+
+(objc:defmethod (#/update :void) ((self file-menu))
+  (cmenu:update-tool-menu self (tool-menu self) :sub-title (sub-title self))
+  (call-next-method))
+
+(objc:defmethod (#/clearFileHistoryAction: :void) ((m file-menu) (sender :id))
+  (declare (ignore sender))
+  (clear-file-history-list))
+
+(defun files-context-menu ()
+  "Create the files context menu."
+  (let* ((menu (make-instance 'file-menu))
+          menu-item)
+    (setf (tool-menu menu) (cmenu:add-default-tool-menu menu))
+    (dolist (entry (hl-list *file-history-list*))
+      (let ((attributed-string (#/initWithString:attributes:
+                                (#/alloc ns:ns-attributed-string) 
+                                (ccl::%make-nsstring 
+                                 (format nil "~A  ~A" 
+                                         (hle-name entry)
+                                         (hle-short-path entry)))
+                                *file-history-dictionary*)))
+        (setq menu-item (make-instance 'file-menu-item))
+        (setf (file-name menu-item) (hle-name entry))
+        (setf (file-path menu-item) (hle-path entry))
+        (#/setAttributedTitle: menu-item attributed-string)
+        (#/setAction: menu-item (ccl::@selector "fileHistoryAction:"))
+        (#/setTarget: menu-item  menu)
+        (#/addItem: menu menu-item)))
+    (#/addItem: menu (#/separatorItem ns:ns-menu-item))
+    (let ((attributed-string (#/initWithString:attributes:
+                              (#/alloc ns:ns-attributed-string)
+                              (ccl::%make-nsstring "Clear List")
+                              *generic-dictionary*)))
+      (setq menu-item (make-instance 'ns:ns-menu-item))
+      (#/setAttributedTitle: menu-item attributed-string)
+      (#/setTarget: menu-item menu)
+      (#/setAction: menu-item (ccl::@selector "clearFileHistoryAction:"))
+      (#/addItem: menu menu-item))
+    menu))
+
+;;; ----------------------------------------------------------------------------
+;;; File I/O
+;;;
+(defun read-history-files ()
+  "Read the position and file history lists."
+  (let ((path (hl-path *file-history-list*)))
+    (when (probe-file path)
+      (with-open-file (stream path :direction :input)
+        (read-history-list *file-history-list* stream))))
+  (let ((path (hl-path *position-history-list*)))
+    (when (probe-file path)
+      (with-open-file (stream path :direction :input)
+        (read-history-list *position-history-list* stream t)))))
+
+(defMethod read-history-list ((hl history-list) stream &optional position-p)
+  (flet ((oops ()
+           (cmenu:notify (format nil "There is a problem with ~S. Setting the history to NIL." (hl-path hl)))
+           (setf (hl-list hl) nil)
+           ;;; delete the file?
+           (return-from read-history-list)))
+    (setf (hl-list hl) nil)
+    ;; For the position-history-list, ufo is the def-info list.
+    ;; For the file-history-list, ufo is the filename string.
+    (let (length ufo path input)
+      (setf input (read stream nil :eof))
+      (unless (numberp input) (oops))
+      (setf length input)
+      (dotimes (count length t)
+        (setf input (read stream nil :eof))
+        (when (or (eql input :eof)
+                  (if position-p
+                    (not (listp input))
+                    (not (stringp input))))
+          (oops))
+        (setf ufo input)
+        (setf input (read stream nil :eof))
+        (when (or (eql input :eof)
+                  (not (stringp input)))
+          (oops))
+        (setf path input)
+        (when (null (add-history-entry hl ufo path))
+          (oops))))))
+
+(defMethod write-history-list ((hl position-history-list) stream)
+  (format stream "~s~%" (length (hl-list hl)))
+  (dolist (entry (nreverse (hl-list hl)))
+    (format stream "~s~%" (hle-info entry))
+    (format stream "~s~%" (hle-path entry))))
+
+(defMethod write-history-list ((hl file-history-list) stream)
+  (format stream "~s~%" (length (hl-list hl)))
+  (dolist (entry (nreverse (hl-list hl)))
+    (format stream "~s~%" (hle-name entry))
+    (format stream "~s~%" (hle-path entry))))
+
+(defun write-history-files ()
+  "Write the history list entries to the path."
+  (let ((path (hl-path *position-history-list*)))
+    (with-open-file (stream path :direction :output :if-exists :supersede)
+      (write-history-list *position-history-list* stream)))
+  (let ((path (hl-path *file-history-list*)))
+    (with-open-file (stream path :direction :output :if-exists :supersede)
+      (write-history-list *file-history-list* stream))))
+
+(defun write-history-files-on-shutdown (&rest args)
+  "Writing function pushed into *lisp-cleanup-functions*."
+  (declare (ignore args))
+  (write-history-files))
+
+(defun read-history-files-on-startup (&rest args)
+  "Reading function (eventually) pushed into *lisp-startup-functions*."
+  (declare (ignore args))
+  (read-history-files))
+
+(pushnew 'write-history-files-on-shutdown ccl::*lisp-cleanup-functions*)
+
+;;; To Do:
+;;; Heap issues involved in saving an image with the utility loaded.
+;;; (pushnew 'read-history-files-on-startup ccl::*lisp-startup-functions*)
+
+;;; ----------------------------------------------------------------------------
+;;; File History Interface:
+;;;
+;;; *** Instead of doing all this stuff need the equivalent of:
+;;; *** (setf ccl::*default-editor-class* 'derived-hemlock-frame-class)
+#-syntax-styling 
+(objc:defMethod (#/becomeKeyWindow :void) ((w gui::hemlock-frame))
+  (let* ((path (cmenu:window-path w))
+         (name (when (and path (string-equal (pathname-type path) "lisp"))
+                 (concatenate 'string (pathname-name path) ".lisp"))))
+    (when (and name path)
+      (maybe-add-history-entry *file-history-list* name path)))
+  (let ((become-key-function (find-symbol "BECOME-KEY-WINDOW" (find-package :sax))))
+    (when become-key-function (funcall become-key-function w)))
+  (call-next-method))
+
+#+syntax-styling
+(defMethod become-key-window ((w gui::hemlock-frame))
+  (let* ((path (cmenu:window-path w))
+         (name (when (and path (string-equal (pathname-type path) "lisp"))
+                 (concatenate 'string (pathname-name path) ".lisp"))))
+    (when (and name path)
+      (maybe-add-history-entry *file-history-list* name path))))
+
+;;; ----------------------------------------------------------------------------
+;;; Position History Interface:
+;;; 
+(hemlock::defcommand "Add Definition Position" (p)
+  "Add the position of the definition containing point to *position-history-list*."
+  (declare (ignore p))
+  (let* ((buffer (hemlock::current-buffer))
+         (mark (hi::copy-mark (hemlock::buffer-point buffer) :temporary))
+         (path (hi::buffer-pathname buffer))
+         (start-mark (hi::top-level-offset mark -1))
+         (def-info (when start-mark (definition-info start-mark))))
+    (when (and def-info path)
+      (maybe-add-history-entry *position-history-list* def-info path))))
+
+(hemlock::bind-key "Add Definition Position" #k"control-shift-space")
+
+(defun add-top-level-position (&optional buffer)
+  "Maybe add the top-level definition position to the position history list."
+  (let* ((buf (or buffer (hi::current-buffer)))
+         (mark (hi::copy-mark (hemlock::buffer-point buf) :temporary))
+         (path (hi::buffer-pathname buf))
+         start-mark def-info)
+    (if (and (= (hi::mark-charpos mark) 0)
+             (char= (hi::next-character mark) #\())
+      (setq start-mark mark)
+      (setq start-mark (hemlock::top-level-offset mark -1)))
+    (when start-mark
+      (let* ((line-end (hi::line-end (hi::copy-mark start-mark :temporary)))
+             (def-mark (hi::copy-mark start-mark :temporary))
+             (objc-mark (hi::copy-mark start-mark :temporary))
+             (def-p (hi::find-pattern def-mark *def-search-pattern* line-end))
+             (objc-p (hi::find-pattern objc-mark *objc-defmethod-search-pattern* line-end)))
+        (cond (def-p
+               (setq def-info (definition-info start-mark)))
+              (objc-p
+               (setq def-info (definition-info start-mark t)))))
+      (when (and def-info path)
+        (maybe-add-history-entry *position-history-list* def-info path)))))
+
+;;; *** These three redefinitions are not a great way of doing this ***
+;;; *** Where's CLOS when you need it ...
+(hemlock::defcommand "Editor Evaluate Defun" (p)
+  "Evaluates the current or next top-level form in the editor Lisp.
+   If the current region is active, this evaluates the region."
+  "Evaluates the current or next top-level form in the editor Lisp."
+  (declare (ignore p))
+  (if (hemlock::region-active-p)
+    (hemlock::editor-evaluate-region-command nil)
+    (hemlock::eval-region (hemlock::defun-region (hi::current-point))))
+  (add-top-level-position))
+
+(hemlock::defcommand "Editor Compile Defun" (p)
+  "Compiles the current or next top-level form in the editor Lisp.
+   First the form is evaluated, then the result of this evaluation
+   is passed to compile.  If the current region is active, this
+   compiles the region."
+  "Evaluates the current or next top-level form in the editor Lisp."
+  (declare (ignore p))
+  (if (hemlock::region-active-p)
+      (hemlock::editor-compile-region (hemlock::current-region))
+      (hemlock::editor-compile-region (hemlock::defun-region (hi::current-point)) t))
+  (add-top-level-position))
+
+;;; gui::cocoa-edit-single-definition didn't last long.
+;;; This one's days are numbered:
+(defun hemlock::move-point-leaving-mark (target)
+  (let ((point (hi::current-point-collapsing-selection)))
+    (hemlock::push-new-buffer-mark point)
+    (hi::move-mark point target)
+    (add-top-level-position (hi::current-buffer))
+    point))
+
+
+(read-history-files)
+
+;;; Hemlock-Commands needs this, for now:
+(pushnew :list-definitions *features*)
Index: /trunk/contrib/foy/list-definitions-cm/list-definitions-cm.lisp
===================================================================
--- /trunk/contrib/foy/list-definitions-cm/list-definitions-cm.lisp	(revision 13946)
+++ /trunk/contrib/foy/list-definitions-cm/list-definitions-cm.lisp	(revision 13946)
@@ -0,0 +1,22 @@
+
+;;; list-definitions.lisp 
+
+(in-package :common-lisp-user)
+
+(unless (member "LIST-DEFINITIONS-CM" *modules* :test #'string-equal)
+  
+(eval-when (:load-toplevel :execute)
+  (defParameter *list-definitions-directory-string*
+    (make-pathname :name nil :type nil :defaults (if *load-pathname* 
+                                                     *load-pathname*
+                                                     *loading-file-source-file*)))
+  (defParameter *list-definition-files* 
+    (list (merge-pathnames ";list-definitions.lisp" *list-definitions-directory-string*)
+          (merge-pathnames ";history-lists.lisp" *list-definitions-directory-string*))))
+ 
+(dolist (file *list-definition-files*)
+  (load file))
+
+(provide :list-definitions-cm)
+
+)
Index: /trunk/contrib/foy/list-definitions-cm/list-definitions.lisp
===================================================================
--- /trunk/contrib/foy/list-definitions-cm/list-definitions.lisp	(revision 13946)
+++ /trunk/contrib/foy/list-definitions-cm/list-definitions.lisp	(revision 13946)
@@ -0,0 +1,383 @@
+;;;-*-Mode: LISP; Package: LIST-DEFINITIONS -*-
+
+;;; ----------------------------------------------------------------------------
+;;;
+;;;      list-definitions.lisp
+;;;
+;;;      copyright (c) 2009 Glen Foy
+;;;      (Permission is granted to Clozure Associates to distribute this file.)
+;;;
+;;;      This code adds a dynamic contextual popup menu to Hemlock.
+;;;
+;;;      Right-Click produces an alphabetized listing of the file's definitions.  
+;;;      Command-Right-Click produces a positional listing.
+;;;
+;;;      This software is offered "as is", without warranty of any kind.
+;;;
+;;;      Mod History, most recent first:
+;;;      9/19/9  Added parse-over-block to list-definitions.
+;;;      8/31/9  Modified to work with Context-Menu mechanism.
+;;;              Numerous interface suggestions, Rainer Joswig.
+;;;      8/17/9  Added position history list and file history list.
+;;;      8/12/9  Numerous interface suggestions, Alexander Repenning.
+;;;      8/10/9  First cut.
+;;;
+;;; ----------------------------------------------------------------------------
+
+(defpackage "LIST-DEFINITIONS" (:nicknames "LDEFS") (:use :cl :ccl))
+(in-package "LIST-DEFINITIONS")
+
+(require :context-menu-cm)
+
+(export '(find-and-display-definition window-path active-hemlock-window))
+
+(defParameter *objc-defmethod-search-pattern* (hi::new-search-pattern :string-insensitive :forward "(objc:defmethod"))
+(defParameter *def-search-pattern* (hi::new-search-pattern :string-insensitive :forward "(def"))
+(defParameter *left-paren-search-pattern* (hi::new-search-pattern :character :forward #\())
+(defParameter *colon-search-pattern* (hi::new-search-pattern :character :forward #\:))
+(defParameter *slash-search-pattern* (hi::new-search-pattern :character :forward #\/))
+
+(defVar *position-history-list* nil "The position-history-list instance.")
+(defVar *file-history-list* nil "The file-history-list instance.")
+
+(defmacro clone (mark) `(hi::copy-mark ,mark :temporary))
+
+;;; ----------------------------------------------------------------------------
+;;; 
+(defclass list-definitions-menu (ns:ns-menu)
+  ((text-view :initarg :menu-text-view :reader menu-text-view)
+   (path :initarg :menu-path :reader menu-path) ; *** history-path
+   (doc-path :initform (merge-pathnames ";ReadMe.rtf" cl-user::*list-definitions-directory-string*) :reader doc-path)
+   (tool-menu :initform nil :accessor tool-menu)
+   (sub-title :initform nil :initarg :sub-title :reader sub-title))
+  (:documentation "The definitions popup menu.")
+  (:metaclass ns:+ns-object))
+
+(objc:defmethod (#/listDefinitionsAction: :void) ((m list-definitions-menu) (sender :id))
+  (display-position (menu-text-view m) (item-mark sender))
+  (maybe-add-history-entry *position-history-list* (item-info sender) (menu-path m)))
+
+ (objc:defmethod (#/update :void) ((self list-definitions-menu))
+  (cmenu:update-tool-menu self (tool-menu self) :sub-title (sub-title self))
+  (call-next-method))
+
+(defun display-position (text-view mark)
+  "Display the position of MARK in TEXT-VIEW."
+  (let* ((def-pos (hi::mark-absolute-position mark))
+         (def-end-pos (let ((temp-mark (clone mark)))
+                        (when (hemlock::form-offset temp-mark 1)
+                          (hi::mark-absolute-position temp-mark)))))
+    (unless def-end-pos (when def-pos (setq def-end-pos (1+ def-pos))))
+    (when (and def-pos def-end-pos)
+      (ns:with-ns-range (range def-pos (- def-end-pos def-pos))
+        (#/scrollRangeToVisible: text-view range))
+      (hi::move-mark (hi::buffer-point (gui::hemlock-buffer text-view)) mark)
+      (gui::update-paren-highlight text-view))))
+
+;;; ----------------------------------------------------------------------------
+;;; 
+(defclass list-definitions-menu-item (ns:ns-menu-item)
+  ((mark :accessor item-mark)
+   (path :accessor item-path)
+   (info :accessor item-info))
+  (:documentation "Support for the definitions list menu.")
+  (:metaclass ns:+ns-object))
+
+(defparameter *dark-blue-color* (#/colorWithCalibratedRed:green:blue:alpha: ns:ns-color 0.2 0.2 0.5 1.0))
+(defparameter *dark-green-color* (#/colorWithCalibratedRed:green:blue:alpha: ns:ns-color 0.0 0.3 0.1 1.0))
+(defparameter *dark-gray-color* (#/colorWithCalibratedRed:green:blue:alpha: ns:ns-color 0.1 0.1 0.1 1.0))
+(defparameter *dark-brown-color* (#/colorWithCalibratedRed:green:blue:alpha: ns:ns-color 0.3 0.05 0.0 1.0))
+(defparameter *dark-turquoise-color* (#/colorWithCalibratedRed:green:blue:alpha: ns:ns-color 0.0 0.2 0.3 1.0))
+(defparameter *wine-red-color* (#/colorWithCalibratedRed:green:blue:alpha: ns:ns-color 0.4 0.1 0.2 1.0))
+
+(defparameter *generic-dictionary* (make-instance 'ns:ns-mutable-dictionary :with-capacity 2))
+(#/setObject:forKey: *generic-dictionary* (#/systemFontOfSize: ns:ns-font (#/smallSystemFontSize ns:ns-font)) #&NSFontAttributeName)
+(#/setObject:forKey: *generic-dictionary* *dark-gray-color* #&NSForegroundColorAttributeName)
+
+(defparameter *file-history-dictionary* (make-instance 'ns:ns-mutable-dictionary :with-capacity 2))
+(#/setObject:forKey: *file-history-dictionary* (#/systemFontOfSize: ns:ns-font (#/smallSystemFontSize ns:ns-font)) #&NSFontAttributeName)
+(#/setObject:forKey: *file-history-dictionary* *dark-blue-color* #&NSForegroundColorAttributeName)
+
+(defparameter *defclass-dictionary* (make-instance 'ns:ns-mutable-dictionary :with-capacity 3))
+(#/setObject:forKey: *defclass-dictionary* (#/systemFontOfSize: ns:ns-font (#/smallSystemFontSize ns:ns-font)) #&NSFontAttributeName)
+(#/setObject:forKey: *defclass-dictionary* *wine-red-color* #&NSForegroundColorAttributeName)
+(#/setObject:forKey: *defclass-dictionary* (#/numberWithInt: ns:ns-number 1) #&NSUnderlineStyleAttributeName)
+
+(defparameter *defstruct-dictionary* (make-instance 'ns:ns-mutable-dictionary :with-capacity 3))
+(#/setObject:forKey: *defstruct-dictionary* (#/systemFontOfSize: ns:ns-font (#/smallSystemFontSize ns:ns-font)) #&NSFontAttributeName)
+(#/setObject:forKey: *defstruct-dictionary* *dark-turquoise-color* #&NSForegroundColorAttributeName)
+(#/setObject:forKey: *defstruct-dictionary* (#/numberWithInt: ns:ns-number 1) #&NSUnderlineStyleAttributeName)
+
+(defparameter *defmethod-dictionary* (make-instance 'ns:ns-mutable-dictionary :with-capacity 2))
+(#/setObject:forKey: *defmethod-dictionary* (#/systemFontOfSize: ns:ns-font (#/smallSystemFontSize ns:ns-font)) #&NSFontAttributeName)
+(#/setObject:forKey: *defmethod-dictionary* *dark-blue-color* #&NSForegroundColorAttributeName)
+
+(defparameter *defun-dictionary* (make-instance 'ns:ns-mutable-dictionary :with-capacity 2))
+(#/setObject:forKey: *defun-dictionary* (#/systemFontOfSize: ns:ns-font (#/smallSystemFontSize ns:ns-font)) #&NSFontAttributeName)
+(#/setObject:forKey: *defun-dictionary* *dark-green-color* #&NSForegroundColorAttributeName)
+
+(defparameter *defmacro-dictionary* (make-instance 'ns:ns-mutable-dictionary :with-capacity 2))
+(#/setObject:forKey: *defmacro-dictionary* (#/systemFontOfSize: ns:ns-font (#/smallSystemFontSize ns:ns-font)) #&NSFontAttributeName)
+(#/setObject:forKey: *defmacro-dictionary* *dark-brown-color* #&NSForegroundColorAttributeName)
+
+(defparameter *objc-dictionary* (make-instance 'ns:ns-mutable-dictionary :with-capacity 2))
+(#/setObject:forKey: *objc-dictionary* (#/systemFontOfSize: ns:ns-font (#/smallSystemFontSize ns:ns-font)) #&NSFontAttributeName)
+(#/setObject:forKey: *objc-dictionary* *dark-blue-color* #&NSForegroundColorAttributeName)
+
+;;; This is not retained -- assumming autorelease.
+(defun list-definitions-context-menu (text-view &optional alpha-p)
+  "Construct the list-definitions popup menu."
+  (let* ((menu (make-instance 'list-definitions-menu 
+                 :sub-title (if alpha-p "alphabetical" "positional")
+                 :menu-text-view text-view 
+                 :menu-path (cmenu:window-path (#/window text-view))))
+         (window (cmenu:active-hemlock-window))
+         (alist (when window (list-definitions window alpha-p)))
+         (class-icon (#/iconForFileType: (#/sharedWorkspace ns:ns-workspace) (ccl::%make-nsstring "lisp")))
+         current-class menu-item)
+    (ns:with-ns-size (icon-size 16 16)
+      (#/setSize: class-icon icon-size))
+    (setf (tool-menu menu) 
+          (if alpha-p
+            (cmenu:add-default-tool-menu menu :doc-file (doc-path menu))
+            (cmenu:add-default-tool-menu menu)))
+    (dolist (entry alist)
+      (let* ((def-info (car entry))
+             (def-type (first def-info))
+             (name (second def-info))
+             (signature (third def-info))
+             (specializer (fourth def-info))
+             (dictionary (case def-type
+                           (:defclass *defclass-dictionary*)
+                           (:defstruct *defstruct-dictionary*)
+                           (:defmethod *defmethod-dictionary*)
+                           (:defun *defun-dictionary*)
+                           (:defmacro *defmacro-dictionary*)
+                           (:objc *objc-dictionary*)
+                           (t *generic-dictionary*)))
+             (attributed-string (#/initWithString:attributes:
+                                 (#/alloc ns:ns-attributed-string) 
+                                 ;; indent methods if directly under specializing class or struct:
+                                 (if (or (eq def-type :defmethod)
+                                         (eq def-type :objc))
+                                   (if (and (not alpha-p)
+                                            current-class specializer
+                                            (string-equal specializer current-class))
+                                     (ccl::%make-nsstring (format nil "      ~A" signature))
+                                     (ccl::%make-nsstring (format nil "~A" signature)))
+                                   (ccl::%make-nsstring name))
+                                 dictionary)))
+        (when (or (eq def-type :defclass) (eq def-type :defstruct)) (setq current-class name))
+        (setq menu-item (make-instance 'list-definitions-menu-item))
+        (setf (item-mark menu-item) (cdr entry))
+        (setf (item-info menu-item) def-info)
+        (#/setAttributedTitle: menu-item attributed-string)
+        ;; Prepend CCL icon to class names:
+        (when (eq def-type :defclass) (#/setImage: menu-item class-icon))
+        (#/setAction: menu-item (ccl::@selector "listDefinitionsAction:"))
+        (#/setTarget: menu-item  menu)
+        (#/addItem: menu menu-item)))
+    menu))
+
+(defun get-list-definitions-menu (view event)
+  (let ((view-window (#/window view)))
+    (#/makeKeyAndOrderFront: view-window nil)
+    (if (logtest #$NSAlternateKeyMask (#/modifierFlags event))
+      (if (logtest #$NSCommandKeyMask (#/modifierFlags event))
+        (files-context-menu)
+        (positions-context-menu))
+      (if (logtest #$NSCommandKeyMask (#/modifierFlags event))
+        (list-definitions-context-menu view nil)
+        (list-definitions-context-menu view t)))))
+
+;;; This includes definitions in sharp-stroke comments.  We'll claim it's a feature.
+(defun list-definitions (hemlock &optional alpha-p)
+  "Create a list of all the top-level definitions in the file."
+  (labels ((get-name (entry)
+             (let ((def-info (car entry)))
+               (second def-info)))
+           (get-defs (mark pattern &optional objc-p)
+             (do ((def-found-p (hi::find-pattern mark pattern)
+                               (hi::find-pattern mark pattern))
+                  alist)
+                 ((not def-found-p) (when alist
+                                      (if alpha-p 
+                                        (sort alist #'string-lessp :key #'get-name) 
+                                        (nreverse alist))))
+               (when (zerop (hi::mark-charpos mark)) 
+                 (let ((def-info (definition-info (clone mark) objc-p)))
+                   (when def-info
+                     (push (cons def-info (hi::line-start (clone mark))) alist))))
+               (hi::line-end mark))))
+    (let* ((pane (slot-value hemlock 'gui::pane))
+           (text-view (gui::text-pane-text-view pane))
+           (buffer (gui::hemlock-buffer text-view))
+           (hi::*current-buffer* buffer))
+      (hemlock::parse-over-block (hi::mark-line (hi::buffer-start-mark buffer))
+                                 (hi::mark-line (hi::buffer-end-mark buffer)))
+      (let* ((def-mark (clone (hi::buffer-start-mark buffer)))
+             (objc-mark (clone (hi::buffer-start-mark buffer)))
+             (def-alist (get-defs def-mark *def-search-pattern*))
+             (objc-alist (get-defs objc-mark *objc-defmethod-search-pattern* t)))
+        (when objc-alist
+          (setq def-alist
+                (if alpha-p
+                  (merge 'list def-alist objc-alist #'string-lessp :key #'get-name)
+                  (merge 'list def-alist objc-alist #'hi::mark< :key #'cdr))))
+        def-alist))))
+
+(defun definition-info (mark &optional objc-p)
+  "Returns (type name) or (type name signature specializer) for methods."
+  (flet ((substring-equal (string len)
+           (string-equal string 
+                         (hi::region-to-string 
+                          (hi::region mark (hi::character-offset (clone mark) len))))))
+    (let* ((def-type (cond (objc-p :objc)
+                           ((substring-equal "(defmethod" 10) :defmethod)
+                           ((substring-equal "(defun" 6) :defun)
+                           ((substring-equal "(defmacro" 9) :defmacro)
+                           ((substring-equal "(defclass" 9) :defclass)
+                           ((substring-equal "(defstruct" 10) :defstruct)
+                           (t :other)))
+           (end (let ((temp-mark (clone mark)))
+                  (when (hemlock::form-offset (hi::mark-after temp-mark) 2)
+                    temp-mark)))
+           (start (when end
+                    (let ((temp-mark (clone end)))
+                      (when (hemlock::form-offset temp-mark -1)
+                        temp-mark)))))
+      (when (and start end)
+        (let ((name (hi::region-to-string (hi::region start end)))
+              param-string specializer)
+          (when (and (stringp name) (string-not-equal name ""))
+            (case def-type
+              (:defmethod
+                  (let ((qualifier-start-mark (clone end))
+                        (left-paren-mark (clone end))
+                        right-paren-mark qualifier-end-mark qualifier-string)
+                    (when (hi::find-pattern left-paren-mark *left-paren-search-pattern*)
+                      (setq right-paren-mark (clone left-paren-mark))
+                      (when (hemlock::form-offset right-paren-mark 1)
+                        (multiple-value-setq (param-string specializer)
+                          (parse-parameters (clone left-paren-mark) right-paren-mark))))
+                    (when (hi::find-pattern qualifier-start-mark *colon-search-pattern* left-paren-mark)
+                      (setq qualifier-end-mark (clone qualifier-start-mark))
+                      (when (hemlock::form-offset qualifier-end-mark 1)
+                        (setq qualifier-string
+                              (hi::region-to-string (hi::region qualifier-start-mark qualifier-end-mark)))))
+                    (if qualifier-string
+                      ;; name is used to simplify the alpha sort:
+                      (list def-type name (format nil "(~A ~A ~A)" name qualifier-string param-string) specializer)
+                      (list def-type name (format nil "(~A ~A)" name param-string) specializer))))
+              (:objc
+               (let* ((name-start-mark (let ((temp-mark (clone start)))
+                                         (when (hi::find-pattern temp-mark *slash-search-pattern*)
+                                           (hi::mark-after temp-mark))))
+                      (name-end-mark (when name-start-mark
+                                       (let ((temp-mark (clone name-start-mark)))
+                                         (when (hemlock::form-offset temp-mark 1)
+                                           temp-mark))))
+                      (objc-name (when (and name-start-mark name-end-mark) 
+                                   (hi::region-to-string (hi::region name-start-mark name-end-mark))))
+                      (left-paren-mark (let ((temp-mark (clone end)))
+                                         (when (hi::find-pattern temp-mark *left-paren-search-pattern*)
+                                           temp-mark)))
+                      (right-paren-mark (when left-paren-mark 
+                                          (let ((temp-mark (clone left-paren-mark)))
+                                            (when (hi::form-offset temp-mark 1)
+                                              temp-mark)))))
+                 (when (and left-paren-mark right-paren-mark)
+                   (multiple-value-setq (param-string specializer)
+                     (parse-parameters left-paren-mark right-paren-mark t))
+                   ;; Using curly braces to distinguish objc methods from Lisp methods:
+                   (list def-type objc-name (format nil "{~A ~A}" objc-name param-string) specializer))))
+              (:defstruct
+                  (cond ((char= (hi::next-character start) #\()
+                         (let* ((space-position (position #\space name :test #'char=))
+                                (new-name (when space-position (subseq name 1 space-position))))
+                           (if new-name
+                             (list def-type new-name)
+                             (list def-type name))))
+                        (t
+                         (list def-type name))))
+              (t
+               (list def-type name)))))))))
+
+(defun parse-parameters (start-mark end-mark &optional objc-p)
+  "Construct the method's parameter string."
+  (let (specializers-processed-p specializer)
+    (flet ((get-param (start end)
+             (let ((next-character (hi::next-character start)))
+               (when (char= next-character #\&) (setq specializers-processed-p t))
+               (cond ((and (char= next-character #\() (not specializers-processed-p))
+                      (let* ((specializer-end (when (hemlock::form-offset (hi::mark-after start) 2) start))
+                             (specializer-start (when specializer-end (clone specializer-end))))
+                        (when (and specializer-end specializer-start
+                                   (hemlock::form-offset specializer-start -1)
+                                   (hi::mark< specializer-end end))
+                          (when objc-p (setq specializers-processed-p t))
+                          (hi::region-to-string (hi::region specializer-start specializer-end)))))
+                     (t 
+                      (unless (char= next-character #\&)
+                        (format nil "t")))))))
+      (do* ((sexp-end (let ((temp-mark (hi::mark-after (clone start-mark))))
+                        (when (hemlock::form-offset temp-mark 1) temp-mark))
+                      (when (hemlock::form-offset (hi::mark-after sexp-end) 1) sexp-end))
+            (sexp-start (when sexp-end
+                          (let ((temp-mark (clone sexp-end)))
+                            (when (hemlock::form-offset temp-mark -1) temp-mark)))
+                        (when sexp-end
+                          (let ((temp-mark (clone sexp-end)))
+                            (when (hemlock::form-offset temp-mark -1) temp-mark))))
+            (param-string (when (and sexp-start sexp-end) (get-param (clone sexp-start) 
+                                                                     (clone sexp-end)))
+                          (when (and sexp-start sexp-end) (get-param (clone sexp-start)
+                                                                     (clone sexp-end))))
+            (first-param-p t)
+            parameters)
+           ((or (null sexp-start) (null sexp-end) 
+                (hi::mark> sexp-start end-mark)
+                ;; Empty body case:
+                (hi::mark< sexp-start start-mark))
+            (values (concatenate 'string parameters ")") specializer))
+        (when param-string
+          (cond (first-param-p
+                 (setq parameters (concatenate 'string "(" param-string))
+                 (setq specializer param-string)
+                 (setq first-param-p nil))
+                (t
+                 (setq parameters (concatenate 'string parameters " " param-string)))))))))
+
+;;; This is used by the Hemlock-Commands tool.  
+(defun find-and-display-definition (name path)
+  "Display the file and scroll to the definition position."
+  (let ((window (cmenu:window-with-path path))
+         mark def-list text-view hemlock-view)
+    (unless (probe-file path)
+      (cmenu:notify (format nil "~a does not exist."
+                      path))
+      (return-from find-and-display-definition nil))
+    (cond (window 
+           (setq hemlock-view (gui::hemlock-view window))
+           (setq text-view (gui::text-pane-text-view (hi::hemlock-view-pane hemlock-view))))
+          (t
+           (setq hemlock-view (gui::cocoa-edit path))
+           (when hemlock-view
+             (setq window (#/window (hi::hemlock-view-pane hemlock-view)))
+             (setq text-view (gui::text-pane-text-view (hi::hemlock-view-pane hemlock-view))))))
+    (when window
+      (#/makeKeyAndOrderFront: window nil)
+      (setq def-list (list-definitions window))
+      (setq mark (cdr (assoc name def-list 
+                             :test #'string-equal
+                             :key #'(lambda (def-info)
+                                      (let ((def-type (first def-info)))
+                                        (if (or (eq def-type :defmethod)
+                                                (eq def-type :objc))
+                                          (third def-info)
+                                          (second def-info)))))))
+      (when mark (display-position text-view mark)))))
+
+
+(cmenu:register-tool "List-Definitions-CM" #'get-list-definitions-menu)
+
Index: /trunk/contrib/foy/list-definitions/history-lists.lisp
===================================================================
--- /trunk/contrib/foy/list-definitions/history-lists.lisp	(revision 13946)
+++ /trunk/contrib/foy/list-definitions/history-lists.lisp	(revision 13946)
@@ -0,0 +1,566 @@
+;;;-*- Mode: Lisp; Package: LIST-DEFINITIONS -*-
+
+;;; ----------------------------------------------------------------------------
+;;;
+;;;      history-lists.lisp
+;;;
+;;;      copyright (c) 2009 Glen Foy
+;;;      (Permission is granted to Clozure Associates to distribute this file.)
+;;;
+;;;      This code supports file and position history lists.
+;;;
+;;;      Alt-Right-Click produces a most-recently-visited list of definition 
+;;;      positions.  Alt-Command-Right-Click produces a most-recently-visited
+;;;      list of files.  Both lists are persistent and are stored here:
+;;;
+;;;      ~/Library/Preferences/org.clairvaux/list-definitions/file-history
+;;;      ~/Library/Preferences/org.clairvaux/list-definitions/position-history
+;;;
+;;;      This software is offered "as is", without warranty of any kind.
+;;;
+;;;      Mod History, most recent first:
+;;;      8/17/9  version 0.2b1
+;;;              This file added.
+;;;
+;;; ----------------------------------------------------------------------------
+
+(in-package "LIST-DEFINITIONS")
+
+(defParameter *position-history-list-length* 25)
+(defParameter *file-history-list-length* 25)
+
+;;; This includes a work-around for what appears to be a bug in the hemlock-frame
+;;; #/close method.  After a #/close, the window remains on the (#/orderedWindows *NSApp*)
+;;; list, but (hi::buffer-document buffer) in NIL.  Therefore the extra tests:
+(defun window-with-path (path)
+  "If a window with PATH is open, return it."
+  (gui::first-window-satisfying-predicate 
+   #'(lambda (w)
+       (when (and (typep w 'gui::hemlock-frame)
+                  (not (typep w 'gui::hemlock-listener-frame)))
+         (let* ((pane (slot-value w 'gui::pane))
+                (text-view (gui::text-pane-text-view pane))
+                (buffer (gui::hemlock-buffer text-view))
+                (document (when buffer (hi::buffer-document buffer)))
+                (p (hi::buffer-pathname buffer)))
+           (when (and document p) (string-equal path p)))))))
+
+(defun maybe-open-file (path)
+  "If a window with PATH is open, return it.  Otherwise open a new window."
+  (let ((w (window-with-path path)))
+    (if w 
+      w
+      (let ((hemlock-view (gui::cocoa-edit path)))
+        (when hemlock-view (#/window (hi::hemlock-view-pane hemlock-view)))))))
+
+(defun construct-history-path (filename)
+  "Construct the path to the history file."
+    (merge-pathnames (concatenate 'string 
+                                  ";Library;Preferences;org.clairvaux;list-definitions;" 
+                                  filename)
+                     (hemlock::user-homedir-pathname)))
+
+(defun notify (message)
+  "FYI"
+  (gui::alert-window :title "Notification" :message message))
+
+;;; ----------------------------------------------------------------------------
+;;;
+(defClass HISTORY-LIST-ENTRY ()
+  ((name :initarg :name :reader hle-name)
+   (path :initarg :path :reader hle-path))
+  (:documentation "Support for the history lists."))  
+
+;;; ----------------------------------------------------------------------------
+;;;
+(defClass POSITION-LIST-ENTRY (history-list-entry) 
+  ((info :initarg :info :reader hle-info))
+  (:documentation "Support for the position history list."))
+
+(defMethod show-entry ((entry position-list-entry))
+  "Display the file and scroll to position."
+  (let* ((name (hle-name entry))
+         (path (hle-path entry))
+         (window (window-with-path path))
+         mark def-list text-view hemlock-view)
+    (unless (probe-file path)
+      (notify (format nil "~a does not exist.  It will be deleted from the history lists."
+                      path))
+      (purge-file-references *position-history-list* path)
+      (remove-path *file-history-list* path)
+      (return-from show-entry nil))
+    (cond (window 
+           (setq hemlock-view (gui::hemlock-view window))
+           (setq text-view (gui::text-pane-text-view (hi::hemlock-view-pane hemlock-view))))
+          (t
+           (setq hemlock-view (gui::cocoa-edit path))
+           (when hemlock-view
+             (setq window (#/window (hi::hemlock-view-pane hemlock-view)))
+             (setq text-view (gui::text-pane-text-view (hi::hemlock-view-pane hemlock-view))))))
+    (when window
+      (#/makeKeyAndOrderFront: window nil)
+      (setq def-list (list-definitions window))
+      (setq mark (cdr (assoc name def-list 
+                             :test #'string-equal
+                             :key #'(lambda (def-info)
+                                      (let ((def-type (first def-info)))
+                                        (if (or (eq def-type :defmethod)
+                                                (eq def-type :objc))
+                                          (third def-info)
+                                          (second def-info)))))))
+      (cond (mark
+             (display-position text-view mark)
+             (move-entry-to-front *file-history-list* path) t)
+            (t 
+             (notify (format nil "Cannot find ~S.  It will be deleted from the position history list." 
+                             name))
+             (remove-entry *position-history-list* name) nil)))))
+
+;;; ----------------------------------------------------------------------------
+;;;
+(defClass FILE-LIST-ENTRY (history-list-entry) 
+  ((short-path :initarg :short-path :accessor hle-short-path))
+  (:documentation "Support for the file history list."))
+
+(defMethod show-entry ((entry file-list-entry))
+  (let ((path (hle-path entry)))
+    (unless (probe-file path)
+      (notify (format nil "~S does not exist.  It will be deleted from the history lists." path))
+      (purge-file-references *position-history-list* path)
+      (remove-path *file-history-list* path)
+      (return-from show-entry nil))
+    (let ((window (window-with-path path))) 
+      (unless window 
+        (let ((hemlock-view (gui::cocoa-edit path)))
+          (when hemlock-view 
+            (setq window (#/window (hi::hemlock-view-pane hemlock-view))))))
+      (when window
+        (#/makeKeyAndOrderFront: window nil) t))))
+
+;;; ----------------------------------------------------------------------------
+;;;
+(defClass HISTORY-LIST ()
+  ((capacity :initarg :capacity :reader hl-capacity)
+   (path :initarg :path :reader hl-path)
+   (list :initform nil :accessor hl-list))
+  (:documentation "Super class of position-history-list and file-history-list."))
+
+;;; ----------------------------------------------------------------------------
+;;;
+(defClass POSITION-HISTORY-LIST (history-list) 
+  ()
+  (:documentation "A persistent history list of most-recently-visited definition positions."))
+
+(setq *position-history-list* (make-instance 'position-history-list 
+                                :path (construct-history-path "position-history")
+                                :capacity *position-history-list-length*))
+
+(defMethod find-entry ((hl position-history-list) name)
+  (find-if  #'(lambda (entry) (string-equal name (hle-name entry)))
+            (hl-list hl)))
+
+(defMethod move-entry-to-front ((hl position-history-list) name)
+  (let ((entry (find-entry hl name)))
+    (when entry
+      (setf (hl-list hl) 
+            (cons entry (delete name (hl-list hl) :test #'string-equal :key #'hle-name)))
+      entry)))
+
+(defMethod purge-file-references ((hl position-history-list) path)
+  (setf (hl-list hl) (delete-if #'(lambda (entry)
+                                    (equal (hle-path entry) path))
+                                (hl-list hl))))
+
+(defMethod remove-entry ((hl position-history-list) name)
+  (setf (hl-list hl) (delete name (hl-list hl) :test #'string-equal :key #'hle-name)))
+
+(defMethod add-history-entry ((hl position-history-list) def-info path)
+  (let* ((def-type (first def-info))
+         (name (second def-info))
+         (signature (third def-info))
+         (entry (make-instance 'position-list-entry 
+                  :name (if (or (eq def-type :defmethod)
+                                (eq def-type :objc))
+                          signature
+                          name)
+                  :info def-info :path path)))
+    (setf (hl-list hl) (cons entry (hl-list hl)))
+    entry))
+
+(defMethod maybe-add-history-entry ((hl position-history-list) def-info path)
+  (let* ((def-type (first def-info))
+         (name (if (or (eq def-type :defmethod)
+                       (eq def-type :objc))
+                 (third def-info)
+                 (second def-info))))
+    (cond ((member name (hl-list hl) :test #'string-equal :key #'hle-name)
+           ;; it's there; move it to the front:
+           (move-entry-to-front hl name))
+          (t
+           (when (>= (length (hl-list hl)) (hl-capacity hl))
+             ;; bump the last entry, then add:
+             (setf (hl-list hl) (butlast (hl-list hl))))
+           (add-history-entry hl def-info path)))))
+
+(defun clear-position-history-list()
+  "Remove all the entries from the position history list."
+  (setf (hl-list *position-history-list*) nil))
+
+;;; ----------------------------------------------------------------------------
+;;;
+(defClass FILE-HISTORY-LIST (history-list) 
+  ()
+  (:documentation "A persistent history list of most-recently-visited files."))
+
+(setf *file-history-list* (make-instance 'file-history-list
+                            :path (construct-history-path "file-history")
+                            :capacity *file-history-list-length*))
+
+(defMethod find-entry ((hl file-history-list) path)
+  (find-if  #'(lambda (entry) (string-equal path (hle-path entry)))
+            (hl-list hl)))
+
+(defMethod move-entry-to-front ((hl file-history-list) path)
+  (let ((entry (find-entry hl path))) 
+    (when entry
+      (setf (hl-list hl) 
+            (cons entry (delete path (hl-list hl) :test #'string-equal :key #'hle-path)))
+      entry)))
+
+(defmethod remove-path ((hl file-history-list) path)
+  (setf (hl-list hl) (delete path (hl-list hl) 
+                             :test #'string-equal :key #'hle-path)))
+
+(defMethod add-history-entry ((hl file-history-list) name path)
+  (let* ((name-position (position #\/ path :test #'char= :from-end t))
+         (short-path (when name-position (subseq path 0 (incf name-position))))
+         (entry (when short-path (make-instance 'file-list-entry :name name 
+                                   :short-path short-path :path path))))
+    (when entry
+      (setf (hl-list hl) (cons entry (hl-list hl)))
+      entry)))
+
+(defMethod maybe-add-history-entry ((hl file-history-list) name path)
+  (cond ((member path (hl-list hl) :test #'string-equal :key #'hle-path)
+         (move-entry-to-front hl path))
+        (t 
+         (cond ((< (length (hl-list hl)) (hl-capacity hl))
+                (add-history-entry hl name path))
+               (t 
+                (setf (hl-list hl) (butlast (hl-list hl)))
+                (add-history-entry hl name path))))))
+
+(defun clear-file-history-list ()
+  "Remove all the entries from the file history list."
+  (setf (hl-list *file-history-list*) nil))
+
+;;; ----------------------------------------------------------------------------
+;;;
+(defclass POSITION-MENU-ITEM (ns:ns-menu-item)
+   ((path :accessor position-path)
+    (name :accessor position-name))
+  (:documentation "Support for the positions popup menu.")
+  (:metaclass ns:+ns-object))
+
+;;; ----------------------------------------------------------------------------
+;;;
+(defclass POSITIONS-MENU (ns:ns-menu)
+  ()
+  (:documentation "A popup menu of most-recently-visited definition positions.")
+  (:metaclass ns:+ns-object))
+
+;;; Pressing the shift key when selecting an entry will delete the entry:
+(objc:defmethod (#/positionHistoryAction: :void) ((m positions-menu) (sender :id))
+  (let ((entry (find-entry *position-history-list* (position-name sender))))
+    (when entry
+      (cond ((gui::current-event-modifier-p #$NSShiftKeyMask)
+             (remove-entry *position-history-list* (position-name sender)))
+            (t
+             (show-entry entry)
+             (move-entry-to-front *position-history-list* (position-name sender)))))))
+
+(objc:defmethod (#/clearPositionHistoryAction: :void) ((m positions-menu) (sender :id))
+  (declare (ignore sender))
+  (clear-position-history-list))
+
+(defun positions-context-menu ()
+  "Create the positions context menu."
+  (let* ((menu (make-instance 'positions-menu))
+         (class-icon (#/iconForFileType: (#/sharedWorkspace ns:ns-workspace) (ccl::%make-nsstring "lisp")))
+          menu-item)
+    (ns:with-ns-size (icon-size 16 16)
+      (#/setSize: class-icon icon-size))
+    (dolist (entry (hl-list *position-history-list*))
+      (let* ((def-info (hle-info entry))
+             (def-type (first def-info))
+             (name (second def-info))
+             (signature (third def-info))
+             (dictionary (case def-type
+                           (:defclass *defclass-dictionary*)
+                           (:defstruct *defstruct-dictionary*)
+                           (:defmethod *defmethod-dictionary*)
+                           (:defun *defun-dictionary*)
+                           (:defmacro *defmacro-dictionary*)
+                           (:objc *objc-dictionary*)
+                           (t *generic-dictionary*)))
+             (attributed-string (#/initWithString:attributes:
+                                 (#/alloc ns:ns-attributed-string) 
+                                 (if (or (eq def-type :defmethod)
+                                         (eq def-type :objc))
+                                   (ccl::%make-nsstring signature)
+                                   (ccl::%make-nsstring name))
+                                 dictionary)))
+        (setq menu-item (make-instance 'position-menu-item))
+        (setf (position-path menu-item) (hle-path entry))
+        (if (or (eq def-type :defmethod) (eq def-type :objc))
+          (setf (position-name menu-item) signature)
+          (setf (position-name menu-item) name))
+        (#/setAttributedTitle: menu-item attributed-string)
+        ;; Classes have a prepended CCL icon:
+        (when (eq def-type :defclass) (#/setImage: menu-item class-icon))
+        (#/setAction: menu-item (ccl::@selector "positionHistoryAction:"))
+        (#/setTarget: menu-item  menu)
+        (#/addItem: menu menu-item)))
+    (#/addItem: menu (#/separatorItem ns:ns-menu-item))
+    (let ((attributed-string (#/initWithString:attributes:
+                              (#/alloc ns:ns-attributed-string)
+                              (ccl::%make-nsstring "Clear List")
+                              *generic-dictionary*)))
+      (setq menu-item (make-instance 'ns:ns-menu-item))
+      (#/setAttributedTitle: menu-item attributed-string)
+      (#/setTarget: menu-item menu)
+      (#/setAction: menu-item (ccl::@selector "clearPositionHistoryAction:"))
+      (#/addItem: menu menu-item))
+    menu))
+
+;;; ----------------------------------------------------------------------------
+;;; 
+(defclass FILE-MENU-ITEM (ns:ns-menu-item)
+   ((path :accessor file-path)
+    (name :accessor file-name))
+  (:documentation "Support for the files popup menu.")
+  (:metaclass ns:+ns-object))
+
+;;; ----------------------------------------------------------------------------
+;;;
+(defclass FILE-MENU (ns:ns-menu)
+  ()
+  (:documentation "A popup menu of most-recently-visited files.")
+  (:metaclass ns:+ns-object))
+
+;;; Pressing the shift key when selecting an entry will delete the entry:
+(objc:defmethod (#/fileHistoryAction: :void) ((m file-menu) (sender :id))
+  (let ((entry (find-entry *file-history-list* (file-path sender))))
+    (when entry
+      (cond ((gui::current-event-modifier-p #$NSShiftKeyMask)
+             (remove-path *file-history-list* (file-path sender)))
+            (t
+             (show-entry entry)
+             (move-entry-to-front *file-history-list* (file-path sender)))))))
+
+(objc:defmethod (#/clearFileHistoryAction: :void) ((m file-menu) (sender :id))
+  (declare (ignore sender))
+  (clear-file-history-list))
+
+(defun files-context-menu ()
+  "Create the files context menu."
+  (let* ((menu (make-instance 'file-menu))
+          menu-item)
+    (dolist (entry (hl-list *file-history-list*))
+      (let ((attributed-string (#/initWithString:attributes:
+                                (#/alloc ns:ns-attributed-string) 
+                                (ccl::%make-nsstring 
+                                 (format nil "~A  ~A" 
+                                         (hle-name entry)
+                                         (hle-short-path entry)))
+                                *file-history-dictionary*)))
+        (setq menu-item (make-instance 'file-menu-item))
+        (setf (file-name menu-item) (hle-name entry))
+        (setf (file-path menu-item) (hle-path entry))
+        (#/setAttributedTitle: menu-item attributed-string)
+        (#/setAction: menu-item (ccl::@selector "fileHistoryAction:"))
+        (#/setTarget: menu-item  menu)
+        (#/addItem: menu menu-item)))
+    (#/addItem: menu (#/separatorItem ns:ns-menu-item))
+    (let ((attributed-string (#/initWithString:attributes:
+                              (#/alloc ns:ns-attributed-string)
+                              (ccl::%make-nsstring "Clear List")
+                              *generic-dictionary*)))
+      (setq menu-item (make-instance 'ns:ns-menu-item))
+      (#/setAttributedTitle: menu-item attributed-string)
+      (#/setTarget: menu-item menu)
+      (#/setAction: menu-item (ccl::@selector "clearFileHistoryAction:"))
+      (#/addItem: menu menu-item))
+    menu))
+
+;;; ----------------------------------------------------------------------------
+;;; File I/O
+;;;
+(defun read-history-files ()
+  "Read the position and file history lists."
+  (let ((path (hl-path *file-history-list*)))
+    (when (probe-file path)
+      (with-open-file (stream path :direction :input)
+        (read-history-list *file-history-list* stream))))
+  (let ((path (hl-path *position-history-list*)))
+    (when (probe-file path)
+      (with-open-file (stream path :direction :input)
+        (read-history-list *position-history-list* stream t)))))
+
+(defMethod read-history-list ((hl history-list) stream &optional position-p)
+  (flet ((oops ()
+           (notify (format nil "There is a problem with ~S. Setting the history to NIL." (hl-path hl)))
+           (setf (hl-list hl) nil)
+           ;;; delete the file?
+           (return-from read-history-list)))
+    (setf (hl-list hl) nil)
+    ;; For the position-history-list, ufo is the def-info list.
+    ;; For the file-history-list, ufo is the filename string.
+    (let (length ufo path input)
+      (setf input (read stream nil :eof))
+      (unless (numberp input) (oops))
+      (setf length input)
+      (dotimes (count length t)
+        (setf input (read stream nil :eof))
+        (when (or (eql input :eof)
+                  (if position-p
+                    (not (listp input))
+                    (not (stringp input))))
+          (oops))
+        (setf ufo input)
+        (setf input (read stream nil :eof))
+        (when (or (eql input :eof)
+                  (not (stringp input)))
+          (oops))
+        (setf path input)
+        (when (null (add-history-entry hl ufo path))
+          (oops))))))
+
+(defMethod write-history-list ((hl position-history-list) stream)
+  (format stream "~s~%" (length (hl-list hl)))
+  (dolist (entry (nreverse (hl-list hl)))
+    (format stream "~s~%" (hle-info entry))
+    (format stream "~s~%" (hle-path entry))))
+
+(defMethod write-history-list ((hl file-history-list) stream)
+  (format stream "~s~%" (length (hl-list hl)))
+  (dolist (entry (nreverse (hl-list hl)))
+    (format stream "~s~%" (hle-name entry))
+    (format stream "~s~%" (hle-path entry))))
+
+(defun write-history-files ()
+  "Write the history list entries to the path."
+  (let ((path (hl-path *position-history-list*)))
+    (with-open-file (stream path :direction :output :if-exists :supersede)
+      (write-history-list *position-history-list* stream)))
+  (let ((path (hl-path *file-history-list*)))
+    (with-open-file (stream path :direction :output :if-exists :supersede)
+      (write-history-list *file-history-list* stream))))
+
+(defun write-history-files-on-shutdown (&rest args)
+  "Writing function pushed into *lisp-cleanup-functions*."
+  (declare (ignore args))
+  (write-history-files))
+
+(defun read-history-files-on-startup (&rest args)
+  "Reading function (eventually) pushed into *lisp-startup-functions*."
+  (declare (ignore args))
+  (read-history-files))
+
+(pushnew 'write-history-files-on-shutdown ccl::*lisp-cleanup-functions*)
+
+;;; To Do:
+;;; Heap issues involved in saving an image with the utility loaded.
+;;; (pushnew 'read-history-files-on-startup ccl::*lisp-startup-functions*)
+
+;;; ----------------------------------------------------------------------------
+;;; File History Interface:
+;;;
+;;; *** Instead of doing all this stuff need the equivalent of:
+;;; *** (setf ccl::*default-editor-class* 'derived-hemlock-frame-class)
+#-syntax-styling 
+(objc:defMethod (#/becomeKeyWindow :void) ((w gui::hemlock-frame))
+  (let* ((path (cmenu:window-path w))
+         (name (when (and path (string-equal (pathname-type path) "lisp"))
+                 (concatenate 'string (pathname-name path) ".lisp"))))
+    (when (and name path)
+      (maybe-add-history-entry *file-history-list* name path)))
+  (let ((become-key-function (find-symbol "BECOME-KEY-WINDOW" (find-package :sax))))
+    (when become-key-function (funcall become-key-function w)))
+  (call-next-method))
+
+#+syntax-styling
+(defMethod become-key-window ((w gui::hemlock-frame))
+  (let* ((path (cmenu:window-path w))
+         (name (when (and path (string-equal (pathname-type path) "lisp"))
+                 (concatenate 'string (pathname-name path) ".lisp"))))
+    (when (and name path)
+      (maybe-add-history-entry *file-history-list* name path))))
+
+;;; ----------------------------------------------------------------------------
+;;; Position History Interface:
+;;; 
+(hemlock::defcommand "Add Definition Position" (p)
+  "Add the position of the definition containing point to *position-history-list*."
+  (declare (ignore p))
+  (let* ((buffer (hemlock::current-buffer))
+         (mark (hi::copy-mark (hemlock::buffer-point buffer) :temporary))
+         (path (hi::buffer-pathname buffer))
+         (start-mark (hi::top-level-offset mark -1))
+         (def-info (when start-mark (definition-info start-mark))))
+    (when (and def-info path)
+      (maybe-add-history-entry *position-history-list* def-info path))))
+
+(hemlock::bind-key "Add Definition Position" #k"control-shift-space")
+
+;;; *** buffer?
+(defun add-top-level-position (&optional buffer)
+  "Maybe add the top-level definition position to the position history list."
+  (let* ((buf (or buffer (hi::current-buffer)))
+         (mark (hi::copy-mark (hemlock::buffer-point buf) :temporary))
+         (path (hi::buffer-pathname buf))
+         start-mark def-info)
+    (if (and (= (hi::mark-charpos mark) 0)
+             (char= (hi::next-character mark) #\())
+      (setq start-mark mark)
+      (setq start-mark (hemlock::top-level-offset mark -1)))
+    (when start-mark
+      (setq def-info (definition-info start-mark))
+      (when (and def-info path)
+        (maybe-add-history-entry *position-history-list* def-info path)))))
+
+;;; *** These three redefinitions are not a great way of doing this ***
+;;; *** Where's CLOS when you need it ...
+(hemlock::defcommand "Editor Evaluate Defun" (p)
+  "Evaluates the current or next top-level form in the editor Lisp.
+   If the current region is active, this evaluates the region."
+  "Evaluates the current or next top-level form in the editor Lisp."
+  (declare (ignore p))
+  (if (hemlock::region-active-p)
+    (hemlock::editor-evaluate-region-command nil)
+    (hemlock::eval-region (hemlock::defun-region (hi::current-point))))
+  (add-top-level-position))
+
+(hemlock::defcommand "Editor Compile Defun" (p)
+  "Compiles the current or next top-level form in the editor Lisp.
+   First the form is evaluated, then the result of this evaluation
+   is passed to compile.  If the current region is active, this
+   compiles the region."
+  "Evaluates the current or next top-level form in the editor Lisp."
+  (declare (ignore p))
+  (if (hemlock::region-active-p)
+      (hemlock::editor-compile-region (hemlock::current-region))
+      (hemlock::editor-compile-region (hemlock::defun-region (hi::current-point)) t))
+  (add-top-level-position))
+
+;;; gui::cocoa-edit-single-definition didn't last long.
+;;; This one's days are numbered:
+(defun hemlock::move-point-leaving-mark (target)
+  (let ((point (hi::current-point-collapsing-selection)))
+    (hemlock::push-new-buffer-mark point)
+    (hi::move-mark point target)
+    (add-top-level-position (hi::current-buffer))
+    point))
+
+
+(read-history-files)
Index: /trunk/contrib/foy/list-definitions/list-definitions.lisp
===================================================================
--- /trunk/contrib/foy/list-definitions/list-definitions.lisp	(revision 13946)
+++ /trunk/contrib/foy/list-definitions/list-definitions.lisp	(revision 13946)
@@ -0,0 +1,350 @@
+;;;-*-Mode: LISP; Package: LIST-DEFINITIONS -*-
+
+;;; ----------------------------------------------------------------------------
+;;;
+;;;      list-definitions.lisp
+;;;
+;;;      copyright (c) 2009 Glen Foy
+;;;      (Permission is granted to Clozure Associates to distribute this file.)
+;;;
+;;;      This code adds a dynamic contextual popup menu to Hemlock.
+;;;
+;;;      Right-Click produces an alphabetized listing of the file's definitions.  
+;;;      Command-Right-Click produces a positional listing.
+;;;
+;;;      This software is offered "as is", without warranty of any kind.
+;;;
+;;;      Mod History, most recent first:
+;;;      9/19/9  Added parse-over-block to list-definitions.
+;;;      8/17/9  Added position history list and file history list.
+;;;      8/12/9  Numerous interface suggestions, Alexander Repenning.
+;;;      8/10/9  First cut.
+;;;
+;;; ----------------------------------------------------------------------------
+
+
+(defpackage "LIST-DEFINITIONS" (:nicknames "LDEFS") (:use :cl :ccl))
+(in-package "LIST-DEFINITIONS")
+
+(defParameter *objc-defmethod-search-pattern* (hi::new-search-pattern :string-insensitive :forward "(objc:defmethod"))
+(defParameter *def-search-pattern* (hi::new-search-pattern :string-insensitive :forward "(def"))
+(defParameter *left-paren-search-pattern* (hi::new-search-pattern :character :forward #\())
+(defParameter *colon-search-pattern* (hi::new-search-pattern :character :forward #\:))
+(defParameter *slash-search-pattern* (hi::new-search-pattern :character :forward #\/))
+
+(defVar *position-history-list* nil "The position-history-list instance.")
+(defVar *file-history-list* nil "The file-history-list instance.")
+
+(defmacro clone (mark) `(hi::copy-mark ,mark :temporary))
+
+(defun active-hemlock-window ()
+  "Return the active hemlock-frame."
+  (gui::first-window-satisfying-predicate 
+   #'(lambda (w)
+       (and (typep w 'gui::hemlock-frame)
+            (not (typep w 'gui::hemlock-listener-frame))
+            (#/isKeyWindow w)))))
+
+(defun window-path (w)
+  "Return the window's path."
+  (let* ((pane (slot-value w 'gui::pane))
+         (hemlock-view (when pane (gui::text-pane-hemlock-view pane)))
+         (buffer (when hemlock-view (hi::hemlock-view-buffer hemlock-view))))
+    (when buffer (hi::buffer-pathname buffer))))
+
+;;; ----------------------------------------------------------------------------
+;;; 
+(defclass list-definitions-menu (ns:ns-menu)
+  ((text-view :initarg :menu-text-view :reader menu-text-view)
+   (path :initarg :menu-path :reader menu-path))
+  (:documentation "The definitions popup menu.")
+  (:metaclass ns:+ns-object))
+
+(objc:defmethod (#/listDefinitionsAction: :void) ((m list-definitions-menu) (sender :id))
+  (display-position (menu-text-view m) (item-mark sender))
+  (maybe-add-history-entry *position-history-list* (item-info sender) (menu-path m)))
+
+(defun display-position (text-view mark)
+  "Display the position of MARK in TEXT-VIEW."
+  (let* ((def-pos (hi::mark-absolute-position mark))
+         (def-end-pos (let ((temp-mark (clone mark)))
+                        (when (hemlock::form-offset temp-mark 1)
+                          (hi::mark-absolute-position temp-mark)))))
+    (unless def-end-pos (when def-pos (setq def-end-pos (1+ def-pos))))
+    (when (and def-pos def-end-pos)
+      (ns:with-ns-range (range def-pos (- def-end-pos def-pos))
+        (#/scrollRangeToVisible: text-view range))
+      (hi::move-mark (hi::buffer-point (gui::hemlock-buffer text-view)) mark)
+      (gui::update-paren-highlight text-view))))
+
+;;; ----------------------------------------------------------------------------
+;;; 
+(defclass list-definitions-menu-item (ns:ns-menu-item)
+  ((mark :accessor item-mark)
+   (path :accessor item-path)
+   (info :accessor item-info))
+  (:documentation "Support for the definitions list menu.")
+  (:metaclass ns:+ns-object))
+
+(defparameter *dark-blue-color* (#/colorWithCalibratedRed:green:blue:alpha: ns:ns-color 0.2 0.2 0.5 1.0))
+(defparameter *dark-green-color* (#/colorWithCalibratedRed:green:blue:alpha: ns:ns-color 0.0 0.3 0.1 1.0))
+(defparameter *dark-gray-color* (#/colorWithCalibratedRed:green:blue:alpha: ns:ns-color 0.1 0.1 0.1 1.0))
+(defparameter *dark-brown-color* (#/colorWithCalibratedRed:green:blue:alpha: ns:ns-color 0.3 0.05 0.0 1.0))
+(defparameter *dark-turquoise-color* (#/colorWithCalibratedRed:green:blue:alpha: ns:ns-color 0.0 0.2 0.3 1.0))
+(defparameter *wine-red-color* (#/colorWithCalibratedRed:green:blue:alpha: ns:ns-color 0.4 0.1 0.2 1.0))
+
+(defparameter *generic-dictionary* (make-instance 'ns:ns-mutable-dictionary :with-capacity 2))
+(#/setObject:forKey: *generic-dictionary* (#/systemFontOfSize: ns:ns-font (#/smallSystemFontSize ns:ns-font)) #&NSFontAttributeName)
+(#/setObject:forKey: *generic-dictionary* *dark-gray-color* #&NSForegroundColorAttributeName)
+
+(defparameter *file-history-dictionary* (make-instance 'ns:ns-mutable-dictionary :with-capacity 2))
+(#/setObject:forKey: *file-history-dictionary* (#/systemFontOfSize: ns:ns-font (#/smallSystemFontSize ns:ns-font)) #&NSFontAttributeName)
+(#/setObject:forKey: *file-history-dictionary* *dark-blue-color* #&NSForegroundColorAttributeName)
+
+(defparameter *defclass-dictionary* (make-instance 'ns:ns-mutable-dictionary :with-capacity 3))
+(#/setObject:forKey: *defclass-dictionary* (#/systemFontOfSize: ns:ns-font (#/smallSystemFontSize ns:ns-font)) #&NSFontAttributeName)
+(#/setObject:forKey: *defclass-dictionary* *wine-red-color* #&NSForegroundColorAttributeName)
+(#/setObject:forKey: *defclass-dictionary* (#/numberWithInt: ns:ns-number 1) #&NSUnderlineStyleAttributeName)
+
+(defparameter *defstruct-dictionary* (make-instance 'ns:ns-mutable-dictionary :with-capacity 3))
+(#/setObject:forKey: *defstruct-dictionary* (#/systemFontOfSize: ns:ns-font (#/smallSystemFontSize ns:ns-font)) #&NSFontAttributeName)
+(#/setObject:forKey: *defstruct-dictionary* *dark-turquoise-color* #&NSForegroundColorAttributeName)
+(#/setObject:forKey: *defstruct-dictionary* (#/numberWithInt: ns:ns-number 1) #&NSUnderlineStyleAttributeName)
+
+(defparameter *defmethod-dictionary* (make-instance 'ns:ns-mutable-dictionary :with-capacity 2))
+(#/setObject:forKey: *defmethod-dictionary* (#/systemFontOfSize: ns:ns-font (#/smallSystemFontSize ns:ns-font)) #&NSFontAttributeName)
+(#/setObject:forKey: *defmethod-dictionary* *dark-blue-color* #&NSForegroundColorAttributeName)
+
+(defparameter *defun-dictionary* (make-instance 'ns:ns-mutable-dictionary :with-capacity 2))
+(#/setObject:forKey: *defun-dictionary* (#/systemFontOfSize: ns:ns-font (#/smallSystemFontSize ns:ns-font)) #&NSFontAttributeName)
+(#/setObject:forKey: *defun-dictionary* *dark-green-color* #&NSForegroundColorAttributeName)
+
+(defparameter *defmacro-dictionary* (make-instance 'ns:ns-mutable-dictionary :with-capacity 2))
+(#/setObject:forKey: *defmacro-dictionary* (#/systemFontOfSize: ns:ns-font (#/smallSystemFontSize ns:ns-font)) #&NSFontAttributeName)
+(#/setObject:forKey: *defmacro-dictionary* *dark-brown-color* #&NSForegroundColorAttributeName)
+
+(defparameter *objc-dictionary* (make-instance 'ns:ns-mutable-dictionary :with-capacity 2))
+(#/setObject:forKey: *objc-dictionary* (#/systemFontOfSize: ns:ns-font (#/smallSystemFontSize ns:ns-font)) #&NSFontAttributeName)
+(#/setObject:forKey: *objc-dictionary* *dark-blue-color* #&NSForegroundColorAttributeName)
+
+;;; This is not retained -- assumming autorelease.
+(defun list-definitions-context-menu (text-view &optional alpha-p)
+  "Construct the list-definitions popup menu."
+  (let* ((menu (make-instance 'list-definitions-menu 
+                 :menu-text-view text-view 
+                 :menu-path (window-path (#/window text-view))))
+         (window (active-hemlock-window))
+         (alist (when window (list-definitions window alpha-p)))
+         (class-icon (#/iconForFileType: (#/sharedWorkspace ns:ns-workspace) (ccl::%make-nsstring "lisp")))
+         current-class menu-item)
+    (ns:with-ns-size (icon-size 16 16)
+      (#/setSize: class-icon icon-size))
+    (dolist (entry alist)
+      (let* ((def-info (car entry))
+             (def-type (first def-info))
+             (name (second def-info))
+             (signature (third def-info))
+             (specializer (fourth def-info))
+             (dictionary (case def-type
+                           (:defclass *defclass-dictionary*)
+                           (:defstruct *defstruct-dictionary*)
+                           (:defmethod *defmethod-dictionary*)
+                           (:defun *defun-dictionary*)
+                           (:defmacro *defmacro-dictionary*)
+                           (:objc *objc-dictionary*)
+                           (t *generic-dictionary*)))
+             (attributed-string (#/initWithString:attributes:
+                                 (#/alloc ns:ns-attributed-string) 
+                                 ;; indent methods if directly under specializing class or struct:
+                                 (if (or (eq def-type :defmethod)
+                                         (eq def-type :objc))
+                                   (if (and (not alpha-p)
+                                            current-class specializer
+                                            (string-equal specializer current-class))
+                                     (ccl::%make-nsstring (format nil "      ~A" signature))
+                                     (ccl::%make-nsstring (format nil "~A" signature)))
+                                   (ccl::%make-nsstring name))
+                                 dictionary)))
+        (when (or (eq def-type :defclass) (eq def-type :defstruct)) (setq current-class name))
+        (setq menu-item (make-instance 'list-definitions-menu-item))
+        (setf (item-mark menu-item) (cdr entry))
+        (setf (item-info menu-item) def-info)
+        (#/setAttributedTitle: menu-item attributed-string)
+        ;; Prepend CCL icon to class names:
+        (when (eq def-type :defclass) (#/setImage: menu-item class-icon))
+        (#/setAction: menu-item (ccl::@selector "listDefinitionsAction:"))
+        (#/setTarget: menu-item  menu)
+        (#/addItem: menu menu-item)))
+    menu))
+
+(objc:defmethod #/menuForEvent: ((view gui::hemlock-text-view) (event :id))
+  (let ((view-window (#/window view)))
+    (#/makeKeyAndOrderFront: view-window nil)
+    (if (logtest #$NSAlternateKeyMask (#/modifierFlags event))
+      (if (logtest #$NSCommandKeyMask (#/modifierFlags event))
+        (files-context-menu)
+        (positions-context-menu))
+      (if (logtest #$NSCommandKeyMask (#/modifierFlags event))
+        (list-definitions-context-menu view nil)
+        (list-definitions-context-menu view t)))))
+
+;;; This includes definitions in sharp-stroke comments.  We'll claim it's a feature.
+(defun list-definitions (hemlock &optional alpha-p)
+  "Create a list of all the top-level definitions in the file."
+  (labels ((get-name (entry)
+             (let ((def-info (car entry)))
+               (second def-info)))
+           (get-defs (mark pattern &optional objc-p)
+             (do ((def-found-p (hi::find-pattern mark pattern)
+                               (hi::find-pattern mark pattern))
+                  alist)
+                 ((not def-found-p) (when alist
+                                      (if alpha-p 
+                                        (sort alist #'string-lessp :key #'get-name) 
+                                        (nreverse alist))))
+               (when (zerop (hi::mark-charpos mark)) 
+                 (let ((def-info (definition-info (clone mark) objc-p)))
+                   (when def-info
+                     (push (cons def-info (hi::line-start (clone mark))) alist))))
+               (hi::line-end mark))))
+    (let* ((pane (slot-value hemlock 'gui::pane))
+           (text-view (gui::text-pane-text-view pane))
+           (buffer (gui::hemlock-buffer text-view))
+           (hi::*current-buffer* buffer))
+      (hemlock::parse-over-block (hi::mark-line (hi::buffer-start-mark buffer))
+                                 (hi::mark-line (hi::buffer-end-mark buffer)))
+      (let* ((def-mark (clone (hi::buffer-start-mark buffer)))
+             (objc-mark (clone (hi::buffer-start-mark buffer)))
+             (def-alist (get-defs def-mark *def-search-pattern*))
+             (objc-alist (get-defs objc-mark *objc-defmethod-search-pattern* t)))
+        (when objc-alist
+          (setq def-alist
+                (if alpha-p
+                  (merge 'list def-alist objc-alist #'string-lessp :key #'get-name)
+                  (merge 'list def-alist objc-alist #'hi::mark< :key #'cdr))))
+        def-alist))))
+
+(defun definition-info (mark &optional objc-p)
+  "Returns (type name) or (type name signature specializer) for methods."
+  (flet ((substring-equal (string len)
+           (string-equal string 
+                         (hi::region-to-string 
+                          (hi::region mark (hi::character-offset (clone mark) len))))))
+    (let* ((def-type (cond (objc-p :objc)
+                           ((substring-equal "(defmethod" 10) :defmethod)
+                           ((substring-equal "(defun" 6) :defun)
+                           ((substring-equal "(defmacro" 9) :defmacro)
+                           ((substring-equal "(defclass" 9) :defclass)
+                           ((substring-equal "(defstruct" 10) :defstruct)
+                           (t :other)))
+           (end (let ((temp-mark (clone mark)))
+                  (when (hemlock::form-offset (hi::mark-after temp-mark) 2)
+                    temp-mark)))
+           (start (when end
+                    (let ((temp-mark (clone end)))
+                      (when (hemlock::form-offset temp-mark -1)
+                        temp-mark)))))
+      (when (and start end)
+        (let ((name (hi::region-to-string (hi::region start end)))
+              param-string specializer)
+          (when (and (stringp name) (string-not-equal name ""))
+            (case def-type
+              (:defmethod
+                  (let ((qualifier-start-mark (clone end))
+                        (left-paren-mark (clone end))
+                        right-paren-mark qualifier-end-mark qualifier-string)
+                    (when (hi::find-pattern left-paren-mark *left-paren-search-pattern*)
+                      (setq right-paren-mark (clone left-paren-mark))
+                      (when (hemlock::form-offset right-paren-mark 1)
+                        (multiple-value-setq (param-string specializer)
+                          (parse-parameters (clone left-paren-mark) right-paren-mark))))
+                    (when (hi::find-pattern qualifier-start-mark *colon-search-pattern* left-paren-mark)
+                      (setq qualifier-end-mark (clone qualifier-start-mark))
+                      (when (hemlock::form-offset qualifier-end-mark 1)
+                        (setq qualifier-string
+                              (hi::region-to-string (hi::region qualifier-start-mark qualifier-end-mark)))))
+                    (if qualifier-string
+                      ;; name is used to simplify the alpha sort:
+                      (list def-type name (format nil "(~A ~A ~A)" name qualifier-string param-string) specializer)
+                      (list def-type name (format nil "(~A ~A)" name param-string) specializer))))
+              (:objc
+               (let* ((name-start-mark (let ((temp-mark (clone start)))
+                                         (when (hi::find-pattern temp-mark *slash-search-pattern*)
+                                           (hi::mark-after temp-mark))))
+                      (name-end-mark (when name-start-mark
+                                       (let ((temp-mark (clone name-start-mark)))
+                                         (when (hemlock::form-offset temp-mark 1)
+                                           temp-mark))))
+                      (objc-name (when (and name-start-mark name-end-mark) 
+                                   (hi::region-to-string (hi::region name-start-mark name-end-mark))))
+                      (left-paren-mark (let ((temp-mark (clone end)))
+                                         (when (hi::find-pattern temp-mark *left-paren-search-pattern*)
+                                           temp-mark)))
+                      (right-paren-mark (when left-paren-mark 
+                                          (let ((temp-mark (clone left-paren-mark)))
+                                            (when (hi::form-offset temp-mark 1)
+                                              temp-mark)))))
+                 (when (and left-paren-mark right-paren-mark)
+                   (multiple-value-setq (param-string specializer)
+                     (parse-parameters left-paren-mark right-paren-mark t))
+                   ;; Using curly braces to distinguish objc methods from Lisp methods:
+                   (list def-type objc-name (format nil "{~A ~A}" objc-name param-string) specializer))))
+              (:defstruct
+                  (cond ((char= (hi::next-character start) #\()
+                         (let* ((space-position (position #\space name :test #'char=))
+                                (new-name (when space-position (subseq name 1 space-position))))
+                           (if new-name
+                             (list def-type new-name)
+                             (list def-type name))))
+                        (t
+                         (list def-type name))))
+              (t
+               (list def-type name)))))))))
+
+(defun parse-parameters (start-mark end-mark &optional objc-p)
+  "Construct the method's parameter string."
+  (let (specializers-processed-p specializer)
+    (flet ((get-param (start end)
+             (let ((next-character (hi::next-character start)))
+               (when (char= next-character #\&) (setq specializers-processed-p t))
+               (cond ((and (char= next-character #\() (not specializers-processed-p))
+                      (let* ((specializer-end (when (hemlock::form-offset (hi::mark-after start) 2) start))
+                             (specializer-start (when specializer-end (clone specializer-end))))
+                        (when (and specializer-end specializer-start
+                                   (hemlock::form-offset specializer-start -1)
+                                   (hi::mark< specializer-end end))
+                          (when objc-p (setq specializers-processed-p t))
+                          (hi::region-to-string (hi::region specializer-start specializer-end)))))
+                     (t 
+                      (unless (char= next-character #\&)
+                        (format nil "t")))))))
+      (do* ((sexp-end (let ((temp-mark (hi::mark-after (clone start-mark))))
+                        (when (hemlock::form-offset temp-mark 1) temp-mark))
+                      (when (hemlock::form-offset (hi::mark-after sexp-end) 1) sexp-end))
+            (sexp-start (when sexp-end
+                          (let ((temp-mark (clone sexp-end)))
+                            (when (hemlock::form-offset temp-mark -1) temp-mark)))
+                        (when sexp-end
+                          (let ((temp-mark (clone sexp-end)))
+                            (when (hemlock::form-offset temp-mark -1) temp-mark))))
+            (param-string (when (and sexp-start sexp-end) (get-param (clone sexp-start) 
+                                                                     (clone sexp-end)))
+                          (when (and sexp-start sexp-end) (get-param (clone sexp-start)
+                                                                     (clone sexp-end))))
+            (first-param-p t)
+            parameters)
+           ((or (null sexp-start) (null sexp-end) 
+                (hi::mark> sexp-start end-mark)
+                ;; Empty body case:
+                (hi::mark< sexp-start start-mark))
+            (values (concatenate 'string parameters ")") specializer))
+        (when param-string
+          (cond (first-param-p
+                 (setq parameters (concatenate 'string "(" param-string))
+                 (setq specializer param-string)
+                 (setq first-param-p nil))
+                (t
+                 (setq parameters (concatenate 'string parameters " " param-string)))))))))
+
+
+
Index: /trunk/contrib/foy/list-definitions/load-list-definitions.lisp
===================================================================
--- /trunk/contrib/foy/list-definitions/load-list-definitions.lisp	(revision 13946)
+++ /trunk/contrib/foy/list-definitions/load-list-definitions.lisp	(revision 13946)
@@ -0,0 +1,23 @@
+
+;;; load-list-definitions.lisp 
+
+(in-package :cl-user)
+
+(unless (member "LIST-DEFINITIONS" *modules* :test #'string-equal)
+  
+(eval-when (:load-toplevel :execute)
+  (defParameter *list-definitions-directory-string*
+    (make-pathname :name nil :type nil :defaults (if *load-pathname* 
+                                                     *load-pathname*
+                                                     *loading-file-source-file*)))
+  (defParameter *list-definition-files* 
+    (list (merge-pathnames ";list-definitions.lisp" *list-definitions-directory-string*)
+          (merge-pathnames ";history-lists.lisp" *list-definitions-directory-string*))))
+ 
+(dolist (file *list-definition-files*)
+  (load file))
+
+(provide :list-definitions)
+
+
+)
Index: /trunk/contrib/foy/source-comparison/source-compare-dialog.lisp
===================================================================
--- /trunk/contrib/foy/source-comparison/source-compare-dialog.lisp	(revision 13946)
+++ /trunk/contrib/foy/source-comparison/source-compare-dialog.lisp	(revision 13946)
@@ -0,0 +1,470 @@
+;;;-*- Mode: Lisp; Package: SOURCE-COMPARE -*-
+
+;;; ----------------------------------------------------------------------------
+;;;
+;;;      source-compare-dialog.lisp, version 0.1b1
+;;;
+;;;      copyright Â© 2009 Glen Foy
+;;;      (Permission is granted to Clozure Associates to distribute this file.)
+;;;
+;;;      This file provides a GUI for Mark Kantrowitz's source-compare.lisp.
+;;;      See source-compare.lisp for documentation.  
+;;;
+;;;      The GUI portion is straight forward.  The browse buttons let you browse 
+;;;      to select the two target files.  The Hemlock buttons will pull in the file 
+;;;      in the top Hemlock window.  
+;;;
+;;;      When the utility prints a diff specification, Alt-Double-Click it to
+;;;      pull up the relevant code in Hemlock windows.  There are various types of
+;;;      diff specs.  A typical one looks like this: 559,565c544,546
+;;;      
+;;;      The most recent version will be available at: www.clairvaux.org/downloads/
+;;;
+;;;      This code is offered "as is" without warranty of any kind.
+;;;
+;;; ----------------------------------------------------------------------------
+
+(in-package "SOURCE-COMPARE")
+
+(defConstant %dialog-width% 675)
+(defConstant %dialog-height% 410)
+
+(defParameter *source-compare-dialog* nil)
+
+(defun open-source-compare-dialog ()
+  (#/makeKeyAndOrderFront: *source-compare-dialog* nil))
+
+#|
+(setq *source-compare-dialog* nil)
+
+(gui::execute-in-gui 'open-source-compare-dialog)
+|#
+
+;;; This includes a work-around for what appears to be a bug in the hemlock-frame
+;;; #/close method.  After a #/close, the window remains on the (#/orderedWindows *NSApp*)
+;;; list, but (hi::buffer-document buffer) in NIL.  Therefore the extra tests:
+(defun display-hemlock-position (path start-line &optional end-line)
+  (labels ((window-buffer (w)
+             (let* ((pane (slot-value w 'gui::pane))
+                    (hemlock-view (gui::text-pane-hemlock-view pane)))
+               (hi::hemlock-view-buffer hemlock-view)))
+           (window-with-path (target-path)
+             (gui::first-window-satisfying-predicate 
+              #'(lambda (w)
+                  (when (and (typep w 'gui::hemlock-frame)
+                             (not (typep w 'gui::hemlock-listener-frame)))
+                    (let* ((buffer (window-buffer w))
+                           (document (when buffer (hi::buffer-document buffer)))
+                           (buffer-path (when buffer (hi::buffer-pathname buffer))))
+                      (when (and document (stringp buffer-path))
+                        (string-equal target-path buffer-path))))))))
+    (let* ((w (window-with-path path))
+           (hemlock-view (cond (w 
+                                (gui::hemlock-view w))
+                               (t
+                                (let ((view (gui::cocoa-edit path)))
+                                  (when view
+                                    (setq w (#/window (hi::hemlock-view-pane view)))
+                                    view)))))
+           (text-pane (when w (slot-value w 'gui::pane)))
+           (text-view (when text-pane (gui::text-pane-text-view text-pane)))
+           (buffer (when hemlock-view (hi::hemlock-view-buffer hemlock-view)))
+           (hi::*current-buffer* buffer)
+           (start-mark (when (and buffer start-line)
+                         (let ((temp (hi::copy-mark (hi::buffer-start-mark buffer) :temporary)))
+                           (when (hi::line-offset temp (1- start-line))
+                             temp))))
+           (start-pos (when start-mark (hi::mark-absolute-position start-mark)))
+           (end-mark (when (and buffer end-line)
+                         (let ((temp (hi::copy-mark (hi::buffer-start-mark buffer) :temporary)))
+                           (when (hi::line-offset temp (1- end-line))
+                             (hi::line-end temp)))))
+           (end-pos (if end-mark 
+                      (hi::mark-absolute-position end-mark)
+                      (when (and start-pos start-mark)
+                        (let ((temp (hi::copy-mark start-mark :temporary)))
+;                          (when (hi::line-offset temp 1)
+                          (hi::mark-absolute-position (hi::line-end temp)))))))
+      (when (and w text-view start-mark start-pos)
+        (#/makeKeyAndOrderFront: w nil)
+        (when (and start-pos end-pos)
+          (ns:with-ns-range (range start-pos (- end-pos start-pos))
+            (#/scrollRangeToVisible: text-view range)
+            (#/setSelectedRange: text-view range))
+          (hi::move-mark (hi::buffer-point buffer) start-mark)
+          (gui::update-paren-highlight text-view))))))
+
+;;; ----------------------------------------------------------------------------
+;;;
+(defclass sc-text-view (ns:ns-text-view)
+  ()
+  (:metaclass ns:+ns-object))
+
+(objc:defmethod (#/mouseDown: :void) ((self sc-text-view) event)
+  (cond ((and (logtest #$NSAlternateKeyMask (#/modifierFlags event))
+              (= (#/clickCount event) 2))
+         ; (#/selectWord: self self)
+         (call-next-method event)
+         (let* ((range (#/selectedRange self))
+                (substring (#/substringWithRange: (#/string self) range)))
+           (process-diff-string (#/window self) (ccl::lisp-string-from-nsstring substring))))
+        (t
+         (call-next-method event))))
+
+;;; ----------------------------------------------------------------------------
+;;;
+(defClass SOURCE-COMPARE-WINDOW (ns:ns-window)
+  ((path-1 :initform nil :accessor path-1)
+   (path-1-field :foreign-type :id :initform nil :accessor path-1-field)
+   (path-2 :initform nil :accessor path-2)
+   (path-2-field :foreign-type :id :initform nil :accessor path-2-field)
+   (difference-pane :foreign-type :id :initform nil :accessor difference-pane)
+   (ignore-case-check-box :foreign-type :id :initform nil :accessor ignore-case-check-box)
+   (ignore-whitespace-check-box :foreign-type :id :initform nil :accessor ignore-whitespace-check-box)
+   (ignore-comments-check-box :foreign-type :id :initform nil :accessor ignore-comments-check-box)
+   (ignore-blank-lines-check-box :foreign-type :id :initform nil :accessor ignore-blank-lines-check-box)
+   (print-context-check-box :foreign-type :id :initform nil :accessor print-context-check-box)
+   (print-fancy-header-check-box :foreign-type :id :initform nil :accessor print-fancy-header-check-box)
+   (compare-button :initform nil :accessor compare-button)
+   (action-alist :initform nil :accessor action-alist))
+  (:metaclass ns:+ns-object))
+
+;;; This is called for all GUI actions.  The source-compare-window is always the target.
+;;; Doing it this way means we can use lambdas in the code below rather than
+;;; writing a bunch of objc functions.  Old MCL habits die hard.
+(objc:defmethod (#/interfaceAction: :void) ((w source-compare-window) (sender :id))
+  (let ((pair (assoc sender (action-alist w))))
+    (cond (pair
+           ;; dispatch:
+           (funcall (cdr pair) sender))
+          (t
+           (error "~%Action function not found for ~S" sender)))))
+
+(defmethod clear-difference-pane ((w source-compare-window))
+  (#/setString: (difference-pane w) #@""))
+
+(defmethod process-diff-string ((w source-compare-window) string)
+  (when (and string
+             (every #'(lambda (char)
+                        (member char
+                                '(#\0 #\1 #\2 #\3 #\4 #\5 #\6 #\7 #\8 #\9
+                                      #\c #\a #\d #\,)))
+                    string))
+    (let* ((alpha-char-pos (find-if #'(lambda (char) (alpha-char-p char)) string))
+           (position (position alpha-char-pos string))
+           (lhs (subseq string 0 position))
+           (rhs (subseq string (1+ position)))
+           (lhs-comma (position #\, lhs))
+           (rhs-comma (position #\, rhs))
+           lhs-start lhs-end rhs-start rhs-end)
+      
+      (cond (lhs-comma
+             (setf lhs-start (read-from-string (subseq lhs 0 lhs-comma)))
+             (setf lhs-end (read-from-string (subseq lhs (1+ lhs-comma))))
+             (display-hemlock-position (path-1 w) lhs-start lhs-end))
+            (t
+             (setf lhs-start (read-from-string lhs))
+             (display-hemlock-position (path-1 w) lhs-start)))
+      
+      (cond (rhs-comma
+             (setf rhs-start (read-from-string (subseq rhs 0 rhs-comma)))
+             (setf rhs-end (read-from-string (subseq rhs (1+ rhs-comma))))
+             (display-hemlock-position (path-2 w) rhs-start rhs-end))
+            (t
+             (setf rhs-start (read-from-string rhs))
+             ;; single line 
+             (display-hemlock-position (path-2 w) rhs-start))))))
+          
+(defMethod get-scmp-items ((w source-compare-window))
+  (append 
+   (make-path-items w)
+   (make-button-items w)
+   (make-check-boxes w)
+   (make-miscel-items w)))
+
+(defMethod make-check-boxes ((w source-compare-window))
+  (flet ((make-check-box (title x-coord y-coord x-dim y-dim checked-p)
+           (let ((box (#/alloc ns:ns-button)))
+             (ns:with-ns-rect (frame x-coord y-coord x-dim y-dim)
+               (#/initWithFrame: box frame))
+             (#/setButtonType: box #$NSSwitchButton)
+             (#/setTitle: box title)
+             (#/setState: box (if checked-p #$NSOnState #$NSOffState))
+             box)))
+    (list
+     (setf (ignore-case-check-box w)
+           (make-check-box #@"ignore case" 10 30 130 20 t))
+
+     (setf (ignore-comments-check-box w)
+           (make-check-box #@"ignore comments" 160 30 130 20 t))
+
+     (setf (ignore-whitespace-check-box w)
+           (make-check-box #@"ignore whitespace" 310 30 130 20 t))
+
+     (setf (ignore-blank-lines-check-box w)
+           (make-check-box #@"ignore blank lines" 10 10 130 20 t))
+
+     (setf (print-context-check-box w)
+           (make-check-box #@"ignore context lines" 160 10 140 20 t))
+
+     (setf (print-fancy-header-check-box w)
+           (make-check-box #@"print fancy header" 310 10 140 20 nil)))))
+
+(defMethod make-button-items ((w source-compare-window))
+  (flet ((make-button (title x-coord y-coord x-dim y-dim lambda)
+           (let ((button (#/alloc ns:ns-button)))
+             (ns:with-ns-rect (frame x-coord y-coord x-dim y-dim)
+               (#/initWithFrame: button frame)
+               (#/setButtonType: button #$NSMomentaryPushInButton)
+               (#/setImagePosition: button #$NSNoImage)
+               (#/setBezelStyle: button #$NSRoundedBezelStyle))
+             (#/setTitle: button title)
+             (#/setTarget: button w)
+             (#/setAction: button (ccl::@selector "interfaceAction:"))
+             (pushnew (cons button lambda) (action-alist w))
+             button))
+         (front-hemlock-window ()
+           (gui::first-window-satisfying-predicate 
+            #'(lambda (w)
+                (and (typep w 'gui::hemlock-frame)
+                     (not (typep w 'gui::hemlock-listener-frame))))))
+                     ;; (#/isKeyWindow w)))))
+         (window-pathname (w)
+           (when w
+             (let* ((pane (slot-value w 'gui::pane))
+                    (text-view (gui::text-pane-text-view pane))
+                    (buffer (gui::hemlock-buffer text-view)))
+               (hi::buffer-pathname buffer)))))
+
+    (list (make-button #@"Browse" 480 368 80 32
+                       #'(lambda (item)
+                           (declare (ignore item))
+                           (let ((path (gui::cocoa-choose-file-dialog :button-string "select")))
+                             (when path
+                               (clear-difference-pane w)
+                               (setf (path-1 w) path)
+                               (#/setStringValue: (path-1-field w) (ccl::%make-nsstring path))))))
+
+          (make-button #@"Browse" 480 338 80 32
+                       #'(lambda (item)
+                           (declare (ignore item))
+                           (let ((path (gui::cocoa-choose-file-dialog :button-string "select")))
+                             (when path
+                               (clear-difference-pane w)
+                               (setf (path-2 w) path)
+                               (#/setStringValue: (path-2-field w) (ccl::%make-nsstring path))))))
+
+          (make-button #@"Hemlock" 570 368 90 32
+                       #'(lambda (item)
+                           (declare (ignore item))
+                           (let* ((window (front-hemlock-window))
+                                  (path (when window (window-pathname window))))
+                             (when path 
+                               (clear-difference-pane w)
+                               (setf (path-1 w) path)
+                               (#/setStringValue: (path-1-field w) (ccl::%make-nsstring path))))))
+
+          (make-button #@"Hemlock" 570 338 90 32
+                       #'(lambda (item)
+                           (declare (ignore item))
+                           (let* ((window (front-hemlock-window))
+                                  (path (when window (window-pathname window))))
+                             (when path 
+                               (clear-difference-pane w)
+                               (setf (path-2 w) path)
+                               (#/setStringValue: (path-2-field w) (ccl::%make-nsstring path))))))
+
+          (make-button #@"Cancel" 480 10 80 32
+                       #'(lambda (item)
+                           (declare (ignore item))
+                           (#/close w)))
+
+          (setf (compare-button w)
+                (make-button #@"Compare" 570 10 90 32
+                             #'(lambda (item)
+                                 (declare (ignore item))
+                                 (compare w)))))))
+
+(defMethod compare ((w source-compare-window))
+
+  (cond ((and (path-1 w) (path-2 w))
+         (unless (probe-file (path-1 w))
+           (format t "~%; File: ~A does not exist." (path-1 w))
+           (return-from compare))
+         (unless (probe-file (path-2 w))
+           (format t "~%; File: ~A does not exist." (path-2 w))
+           (return-from compare))
+
+         (let ((stream (make-string-output-stream)))         
+           ;; out with the old 
+           (#/setString: (difference-pane w) #@" ")
+           (source-compare (path-1 w) (path-2 w)
+                           :output-stream stream
+                           :ignore-case (eql (#/state (ignore-case-check-box w)) #$NSOnState)
+                           :ignore-whitespace (eql (#/state (ignore-whitespace-check-box w)) #$NSOnState)
+                           :ignore-comments (eql (#/state (ignore-comments-check-box w)) #$NSOnState)
+                           :ignore-blank-lines (eql (#/state (ignore-blank-lines-check-box w)) #$NSOnState)
+                           :print-context (eql (#/state (print-context-check-box w)) #$NSOnState)
+                           :print-fancy-header (eql (#/state (print-fancy-header-check-box w)) #$NSOnState))
+           (#/setString: (difference-pane w) (ccl::%make-nsstring (ccl::get-output-stream-string stream)))))
+        (t
+         (#/setString: (difference-pane w) #@"First enter two valid paths."))))
+
+(defMethod make-path-items ((w source-compare-window))
+  (let* ((small-sys-size (#/smallSystemFontSize ns:ns-font))
+         (small-sys-font (#/systemFontOfSize: ns:ns-font small-sys-size)))
+    (list
+     (setf (path-1-field w)
+           (let ((field (#/alloc ns:ns-text-field)))
+             (ns:with-ns-rect (frame 30 375 435 15)
+               (#/initWithFrame: field frame)
+               (#/setEditable: field nil)
+               (#/setDrawsBackground: field nil)
+               (#/setBordered: field nil)
+               (#/setFont: field small-sys-font)
+               (#/setStringValue: field #@""))
+             field))
+     
+     (setf (path-2-field w)
+           (let ((field (#/alloc ns:ns-text-field)))
+             (ns:with-ns-rect (frame 30 345 435 15)
+               (#/initWithFrame: field frame)
+               (#/setEditable: field nil)
+               (#/setDrawsBackground: field nil)
+               (#/setBordered: field nil)
+               (#/setFont: field small-sys-font)
+               (#/setStringValue: field #@""))
+             field)))))
+
+(defMethod make-miscel-items ((w source-compare-window))
+  (list
+   (let* ((scroll-view (#/alloc ns:ns-scroll-view))
+          (view (#/init (#/alloc sc-text-view))))
+     (ns:with-ns-rect (frame 4 60 650 200)
+       (#/initWithFrame: scroll-view frame))
+     (ns:with-ns-rect (frame 4 60 650 200)
+       (#/initWithFrame: view frame))
+     (#/insertText: view #@" ")
+     (#/setHasVerticalScroller: scroll-view t)
+     (#/setHasHorizontalScroller: scroll-view t)
+     (#/setBorderType: scroll-view #$NSBezelBorder)
+     (#/setDocumentView: scroll-view view)
+     (#/setEditable: view nil)
+     (setf (difference-pane w) view)
+     scroll-view)
+
+   (let* ((title (#/alloc ns:ns-text-field)))
+     (ns:with-ns-rect (frame 5 370 22 22)
+       (#/initWithFrame: title frame))
+     (#/setEditable: title nil)
+     (#/setDrawsBackground: title nil)
+     (#/setBordered: title nil)
+     ;; (#/setFont: title style-font)
+     (#/setStringValue: title #@"1:")
+     title)
+
+   (let ((box (#/alloc ns:ns-box)))
+      (ns:with-ns-rect (frame 25 370 450 40)
+        (#/initWithFrame: box frame))
+     (#/setTitle: box #@"")
+     box)
+
+   (let* ((title (#/alloc ns:ns-text-field)))
+     (ns:with-ns-rect (frame 5 340 22 22)
+       (#/initWithFrame: title frame))
+     (#/setEditable: title nil)
+     (#/setDrawsBackground: title nil)
+     (#/setBordered: title nil)
+     ;; (#/setFont: title style-font)
+     (#/setStringValue: title #@"2:")
+     title)
+
+   (let ((box (#/alloc ns:ns-box)))
+      (ns:with-ns-rect (frame 25 340 450 40)
+        (#/initWithFrame: box frame))
+     (#/setTitle: box #@"")
+     box)
+
+   (let* ((title (#/alloc ns:ns-text-field)))
+     (ns:with-ns-rect (frame 10 310 500 22)
+       (#/initWithFrame: title frame))
+     (#/setEditable: title nil)
+     (#/setDrawsBackground: title nil)
+     (#/setBordered: title nil)
+     ;; (#/setFont: title style-font)
+     (#/setStringValue: title #@"Mods required to make file 1 equivalent to file 2:")
+     title)
+
+  (let* ((small-sys-size (#/smallSystemFontSize ns:ns-font))
+         (small-sys-font (#/systemFontOfSize: ns:ns-font small-sys-size))
+         (title (#/alloc ns:ns-text-field)))
+    (ns:with-ns-rect (frame 10 290 500 22)
+      (#/initWithFrame: title frame))
+    (#/setEditable: title nil)
+    (#/setDrawsBackground: title nil)
+    (#/setBordered: title nil)
+    (#/setFont: title small-sys-font)
+    (#/setStringValue: title #@"(a = add, d = delete, c = change, < = file 1, > = file 2)")
+    title)
+
+  (let* ((small-sys-size (#/smallSystemFontSize ns:ns-font))
+         (small-sys-font (#/systemFontOfSize: ns:ns-font small-sys-size))
+         (title (#/alloc ns:ns-text-field)))
+    (ns:with-ns-rect (frame 10 270 500 22)
+      (#/initWithFrame: title frame))
+    (#/setEditable: title nil)
+    (#/setDrawsBackground: title nil)
+    (#/setBordered: title nil)
+    (#/setFont: title small-sys-font)
+    (#/setStringValue: title #@"(To display the relevant code, alt-double-click the difference spec, ie 559,565c544,546)")
+    title)))
+
+(setq *source-compare-dialog*
+      (let ((dialog (#/alloc source-compare-window)))
+        (ns:with-ns-rect (r 100 100 %dialog-width% %dialog-height%)
+          (#/initWithContentRect:styleMask:backing:defer: 
+           dialog
+           r
+           (logior  #$NSTitledWindowMask 
+                    #$NSClosableWindowMask  
+                    #$NSMiniaturizableWindowMask)
+           #$NSBackingStoreBuffered
+           #$NO))
+        (#/setTitle: dialog #@"Source Comparison")
+        (dolist (item (get-scmp-items dialog))
+          (#/addSubview: (#/contentView  dialog) item))
+        (#/setDefaultButtonCell: dialog (compare-button dialog))
+        (#/setReleasedWhenClosed: dialog nil)
+        (#/center dialog)
+        dialog))
+
+;;; ----------------------------------------------------------------------------
+;;; update the Tools Menu
+;;;
+(defParameter *tools-menu* 
+  (#/submenu (#/itemWithTitle: (#/mainMenu (ccl::application-ui-object ccl::*application*)) #@"Tools")))
+
+(let ((item (#/itemWithTitle: *tools-menu* #@"Source Compare...")))
+  (unless (%null-ptr-p item) (#/removeItem: *tools-menu* item))
+  (#/addItem: *tools-menu* (#/separatorItem ns:ns-menu-item))
+  (setf item (#/initWithTitle:action:keyEquivalent: (#/alloc ns:ns-menu-item)
+                                                    #@"Source Compare..."
+                                                    (ccl::@selector "interfaceAction:")
+                                                    #@""))
+  (#/setTarget: item *source-compare-dialog*)
+  (#/addItem: *tools-menu* item)
+  (pushnew (cons item
+                 #'(lambda (sender)
+                     (declare (ignore sender))
+                     (open-source-compare-dialog)))
+           (action-alist *source-compare-dialog*)))
+
+
+
+
+
+
+
+
+
+
Index: /trunk/contrib/foy/source-comparison/source-compare.lisp
===================================================================
--- /trunk/contrib/foy/source-comparison/source-compare.lisp	(revision 13946)
+++ /trunk/contrib/foy/source-comparison/source-compare.lisp	(revision 13946)
@@ -0,0 +1,1242 @@
+;;; Tue Dec 25 19:59:50 1990 by Mark Kantrowitz <mkant@GLINDA.OZ.CS.CMU.EDU>
+;;; source-compare.lisp
+
+;;; ****************************************************************
+;;; Source Compare: A 'diff' Program for Lisp **********************
+;;; ****************************************************************
+;;; 
+;;; Source Compare is a common-lisp portable tool for comparing 
+;;; lisp source files, similar to the unix program 'diff'. Like diff
+;;; it can ignore case, whitespace, and blank lines. In addition,
+;;; it can also ignore certain classes of lisp comments. It runs in
+;;; average-case O(m+n) time.
+;;;
+;;; Written by Mark Kantrowitz, December 1990.
+;;; Address:   School of Computer Science
+;;;            Carnegie Mellon University
+;;;            Pittsburgh, PA 15213
+;;;
+;;; Copyright (c) 1990. All rights reserved.
+;;;
+;;; See general license below.
+;;;
+
+;;; ****************************************************************
+;;; General License Agreement and Lack of Warranty *****************
+;;; ****************************************************************
+;;;
+;;; This software is distributed in the hope that it will be useful (both
+;;; in and of itself and as an example of lisp programming), but WITHOUT
+;;; ANY WARRANTY. The author(s) do not accept responsibility to anyone for
+;;; the consequences of using it or for whether it serves any particular
+;;; purpose or works at all. No warranty is made about the software or its
+;;; performance. 
+;;; 
+;;; Use and copying of this software and the preparation of derivative
+;;; works based on this software are permitted, so long as the following
+;;; conditions are met:
+;;; 	o  The copyright notice and this entire notice are included intact
+;;; 	   and prominently carried on all copies and supporting documentation.
+;;; 	o  No fees or compensation are charged for use, copies, or
+;;; 	   access to this software. You may charge a nominal
+;;; 	   distribution fee for the physical act of transferring a
+;;; 	   copy, but you may not charge for the program itself. 
+;;; 	o  If you modify this software, you must cause the modified
+;;; 	   file(s) to carry prominent notices (a Change Log)
+;;; 	   describing the changes, who made the changes, and the date
+;;; 	   of those changes.
+;;; 	o  Any work distributed or published that in whole or in part
+;;; 	   contains or is a derivative of this software or any part 
+;;; 	   thereof is subject to the terms of this agreement. The 
+;;; 	   aggregation of another unrelated program with this software
+;;; 	   or its derivative on a volume of storage or distribution
+;;; 	   medium does not bring the other program under the scope
+;;; 	   of these terms.
+;;; 	o  Permission is granted to manufacturers and distributors of
+;;; 	   lisp compilers and interpreters to include this software
+;;; 	   with their distribution. 
+;;; 
+;;; This software is made available AS IS, and is distributed without 
+;;; warranty of any kind, either expressed or implied.
+;;; 
+;;; In no event will the author(s) or their institutions be liable to you
+;;; for damages, including lost profits, lost monies, or other special,
+;;; incidental or consequential damages arising out of or in connection
+;;; with the use or inability to use (including but not limited to loss of
+;;; data or data being rendered inaccurate or losses sustained by third
+;;; parties or a failure of the program to operate as documented) the 
+;;; program, even if you have been advised of the possibility of such
+;;; damanges, or for any claim by any other party, whether in an action of
+;;; contract, negligence, or other tortious action.
+;;; 
+;;; The current version of this software and a variety of related
+;;; utilities may be obtained by anonymous ftp from a.gp.cs.cmu.edu
+;;; (128.2.242.7) or any other CS machine in the directory 
+;;;       /afs/cs.cmu.edu/user/mkant/Public/Lisp-Utilities/
+;;; You must cd to this directory in one fell swoop, as the CMU
+;;; security mechanisms prevent access to other directories from an
+;;; anonymous ftp. For users accessing the directory via an anonymous
+;;; ftp mail server, the file README contains a current listing and
+;;; description of the files in the directory. The file UPDATES describes
+;;; recent updates to the released versions of the software in the directory.
+;;; The file COPYING contains the current copy of this license agreement.
+;;; Of course, if your site runs the Andrew File System and you have
+;;; afs access, you can just cd to the directory and copy the files directly.
+;;; 
+;;; Please send bug reports, comments, questions and suggestions to
+;;; mkant@cs.cmu.edu. We would also appreciate receiving any changes
+;;; or improvements you may make. 
+;;; 
+;;; If you wish to be added to the CL-Utilities@cs.cmu.edu mailing list, 
+;;; send email to CL-Utilities-Request@cs.cmu.edu with your name, email
+;;; address, and affiliation. This mailing list is primarily for
+;;; notification about major updates, bug fixes, and additions to the lisp
+;;; utilities collection. The mailing list is intended to have low traffic.
+;;;
+
+;;; ********************************
+;;; Change Log *********************
+;;; ********************************
+;;;
+;;;  16-DEC-90  mk   File created.
+;;;  25-DEC-90  mk   First released version.
+;;;  24-JAN-91  mk   Added average-case running time analysis.
+
+;;; ********************************
+;;; To Do **************************
+;;; ********************************
+;;;
+;;; Extend so it can ignore documentation strings?
+;;;
+;;; Extend so it can ignore ALL whitespace (even within line)?
+;;;
+;;; Cache start and end positions for each line? [Modify line-start and
+;;; line-end to first check the cache before redoing the computation.]
+;;;    run the profiler on this code first, though.
+;;;
+;;; The file cache could be flushed after each loop in so-co. Possibly
+;;; worth doing to save space and/or reduce consing.
+;;;
+;;; Implement diff's O(p log n) algorithm using 2-3 trees and k-candidates.
+;;;
+;;; Given that in diff's find-merge-split algorithm the merge is on two
+;;; sets, one with elements less than the others, can we find a way to
+;;; do the find-find-split-merge in constant time? At least keep a table
+;;; of whether r-1,r are in the same k-candidate set. 
+;;;
+;;; Fancy indexing, div&conq, straight-line dist to TR corner metric.
+;;; Hierarchical LCS (i.e., abstract level first)?
+;;;
+;;; Make it aware of which definition it is in to aid matching. (Problem,
+;;; then, of function and variable renaming.)
+;;;
+
+;;; ********************************
+;;; Notes **************************
+;;; ********************************
+;;;
+;;;    SOURCE-COMPARE has been tested (successfully) in the following lisps:
+;;;       CMU Common Lisp (M2.9 15-Aug-90, Compiler M1.8 15-Aug-90)
+;;;       Macintosh Allegro Common Lisp (1.3.2)
+;;;       ExCL (Franz Allegro CL 3.1.12 [DEC 3100] 3/30/90)
+;;;       Lucid CL (Version 2.1 6-DEC-87)
+;;;
+;;;    SOURCE-COMPARE needs to be tested in the following lisps:
+;;;       Symbolics Common Lisp (8.0)
+;;;       Lucid Common Lisp (3.0, 4.0)
+;;;       KCL (June 3, 1987 or later)
+;;;       AKCL (1.86, June 30, 1987 or later)
+;;;       TI (Release 4.1 or later)
+;;;       Ibuki Common Lisp (01/01, October 15, 1987)
+;;;       Golden Common Lisp (3.1 IBM-PC)
+;;;       VAXLisp (2.0, 3.1)
+;;;       HP Common Lisp (same as Lucid?)
+;;;       Procyon Common Lisp
+
+;;; ****************************************************************
+;;; Documentation **************************************************
+;;; ****************************************************************
+;;;
+;;; Source Compare is a common-lisp portable tool for comparing 
+;;; lisp source files, similar to the unix program 'diff'. 
+;;;
+;;; It uses a greedy variation of the usual dynamic programming 
+;;; implementation of LCS (longest common substring) to do the 
+;;; comparison. It tries to maintain the two files being compared
+;;; in sync, and when a difference is encountered, uses the closest
+;;; next match, where distance is minimized against some metric.
+;;; Note that since this is a greedy algorithm, it is possible that it
+;;; will not find the optimum global match sequence. However, this case
+;;; hardly ever occurs in practice, and if it does ever occur, the
+;;; algorithm errs on the side of safety.
+;;;
+;;; Metrics should be chosen so that minimizing distance is
+;;; equivalent to minimizing the edits necessary to bring the two
+;;; files into agreement. Two such metrics include
+;;;     x + y    = *total* additions and deletions from both files
+;;;     max(x,y) = length of largest addition or deletion from either file
+;;; where x is a line number from the first file and y is a line number
+;;; from the second file. Both of these metrics are appropriate to the
+;;; problem, since the former tries to minimize the total changes and
+;;; the latter gives a preference to small changes.
+;;; 
+;;; While neither metric actually builds the dynamic programming table,
+;;; they can be considered as exploring the table in successive
+;;; rectilinear and diagonal manners, respectively.
+;;;                        #####          #
+;;;                            #           #
+;;;                            #            #
+;;;                            #             #
+;;; Both metrics have been implemented.
+;;;
+;;; Both of these metrics lead to a worst-case O(n^2) algorithm
+;;; (actually, O(nm), where n is the length of the first file and
+;;; m is the length of the second file). In practice, however, the
+;;; algorithm seems to have linear running time. This could be a function
+;;; of its use to compare source files, since comparing two completely
+;;; different files would lead to worst-case behavior. The diagonal
+;;; metric seems to be slightly faster and less of a space hog than
+;;; the rectilinear metric, so it has been made the default.
+;;; 
+;;; We show below that the average case running time is O(n+m).
+;;;
+
+;;; ********************************
+;;; Average Case Analysis **********
+;;; ********************************
+;;;
+;;; Thanks to Neil J Calkin (CMU Math Department) for the idea that led to
+;;; this proof.
+;;;
+;;; Let a(i) and b(i) be the ith distances between matches in files A and B,
+;;; respectively. Let k, an integer between 1 and n (inclusive), be the
+;;; number of matches. Then
+;;;	  Sum[i = 1 to k; a(i)] = m and Sum[i = 1 to k; b(i)] = n
+;;; where m is the length in lines of file A, and n is the corresponding
+;;; length for file B. The running time of the algorithm is proportional
+;;; to Sum[i = 1 to k; a(i)b(i)].
+;;;
+;;; Since a(i) and b(i) are positive integers, it follows that
+;;;	    Sum[i; a(i)b(i)] <= Sum[i; a(i)] Sum[i; b(i)] = m n
+;;; and hence the worst-case running time is O(mn). [Best case is, of course,
+;;; linear.]
+;;;
+;;; But the worst-case running time is atypical of the average-case behavior.
+;;; As we shall show, the average-case running time is O(m+n).
+;;;
+;;; Combining the Cauchy-Schwartz inequality
+;;;	 Sum[i;a(i)b(i)] <= Sqrt{Sum[i;a(i)^2]} sqrt{Sum[i;b(i)^2]}
+;;; with the arithmetic-mean geometric-mean inequality
+;;;			    Sqrt{xy} <= (x+y)/2
+;;; yields
+;;;	    Sum[i;a(i)b(i)] <= (Sum[i;a(i)^2] + Sum[i;b(i)^2])/2
+;;;
+;;; So it suffices to look at the average value of Sum[i = 1 to k; r(i)^2]
+;;; over all possible ordered sequences r(i) of positive integers for k = 1
+;;; to n such that Sum[i = 1 to k; r(i)] = n. Such a sequence r(k) is called a
+;;; composition of n into k distinct parts. (The word distinct here
+;;; signifies that permutations of a sequence r(k) are not considered
+;;; identical -- the cells are distinct.)
+;;;
+;;; To compute this average we sum Sum[i = 1 to k; r(i)^2] over all possible
+;;; compositions of n, and divide by the total number of such
+;;; compositions.
+;;;
+;;; Clearly r(i) is an integer between 1 and n (inclusive). For a given
+;;; integer i between 1 and n (inclusive), we count how often i occurs
+;;; in a composition of n into k distinct parts. Call this count
+;;; Comp[n,k,i]. Then the sum is equal to 
+;;;	    Sum[k = 1 to n; Sum[i = 1 to n; Comp[n,k,i] i^2]]
+;;;
+;;; Now the number of occurrences of i in the compositions of n into k
+;;; distinct parts is the same as multiplying together the number of
+;;; compositions of n-i into k-1 parts and the number of positions in
+;;; which i could be inserted to form a k-part composition of n. The 
+;;; latter quantity is clearly k. To see that the former is 
+;;; C(n-i-1,k-2), consider n-i ones separated by (n-i)-1 spaces, and
+;;; choose (k-1)-1 of them to form k-1 integers. Thus Comp[n,k,i] is
+;;; k C(n-i-1,k-2).
+;;; 
+;;; So our sum is equal to
+;;;    Sum[k = 1 to n; Sum[i = 1 to n; k(i^2)C(n-i-1,k-2)]]
+;;;	  = Sum[i = 1 to n; i^2 Sum[k = 1 to n; kC(n-i-1,k-2)]]
+;;;	  = Sum[i = 1 to n; i^2 Sum[k = 1 to n; 
+;;;                                 (k-2)C(n-i-1,k-2) + 2C(n-i-1,k-2)]]
+;;;	  = Sum[i = 1 to n; i^2 Sum[k = 1 to n; 
+;;;                                 (n-i-1)C(n-i-2,k-3) + 2C(n-i-1,k-2)]]
+;;;	  = Sum[i = 1 to n-2; i^2 (n-i-1) 2^(n-i-2)]
+;;;         + Sum[i = 1 to n; i^2 2^(n-i)]
+;;; Substituting j = n-i+1 yields
+;;;       = Sum[j = 3 to n; (n+1-j)^2 (j-2) 2^(j-3)] 
+;;;         + Sum[j = 1 to n; (n+1-j)^2 2^(j-1)]
+;;;       = Sum[j = 1 to n-2; (n-1-j)^2 j 2^(j-1)] 
+;;;         + Sum[j = 1 to n; (n+1-j)^2 2^(j-1)]
+;;;       = (Sum[j = 1 to n-2; 2^j (j^3 - (2n-2) j^2 + (n-1)^2 j)]
+;;;          + Sum[j = 1 to n; 2^j (j^2 - (2n+2)j + (n+1)^2)])/2
+;;; We substitute using the identities
+;;;    Sum[j = 1 to n; 2^j]     = 2^(n+1) - 2
+;;;    Sum[j = 1 to n; j 2^j]   = (n-1)2^(n+1) + 2
+;;;    Sum[j = 1 to n; j^2 2^j] = (2n^2 - 4n + 6)2^n - 6
+;;;    Sum[j = 1 to n; j^3 2^j] = (2n^3 - 6n^2 + 18n - 26)2^n + 26
+;;; to obtain
+;;;    1/2[2^(n-1)((n-2)^3 - 3(n-2)^2 + 9(n-2) - 13 
+;;;                - 2(n-1)((n-2)^2 - 2(n-2) + 3)
+;;;                + (n-1)^2(n-3))
+;;;        2^n(2n^2 - 4n + 6
+;;;            - (2n+2)(2n-2)
+;;;            + (n+1)^2(2))
+;;;        + (26 + 6(2n-2) + 2(n-1)^2 - 6 - 2(2n+2) - 2(n+1)^2)]
+;;; Luckily the n^3 and n^2 terms cancel, simplifying the expression to
+;;;    (3n-4) 2^(n-1) + 2
+;;; This closed form expression has been empirically verified for n = 1 to 15.
+;;;
+;;; Since there are C(n-1,k-1) compositions of n into k distinct parts, the
+;;; total number of compositions is Sum[k = 1 to n; C(n-1,k-1)] = 2^(n-1)
+;;; by the binomial theorem.
+;;;
+;;; Thus the average value of Sum[n,k; r(i)^2] is the total sum divided by
+;;; the total count, or
+;;;	     [(3n-4) 2^(n-1) + 2]/[2^(n-1)] = 3n-4 + 1/2^(n-2)
+;;; So Sum[i; a(i)b(i)] <= (Sum[i;a(i)^2] + Sum[i;b(i)^2])/2
+;;;                      = (3n-4 + 1/2^(n-2) + 3m-4 + 1/2^(m-2))/2
+;;;                      = 3/2(n+m) - 4 + 1/2^(n-1) + 1/2^(m-1)
+;;; on average, and hence the average case running time is O(m+n).
+;;;
+
+;;; ********************************
+;;; User Guide *********************
+;;; ********************************
+;;;
+;;; SOURCE-COMPARE (filename-1 filename-2 &key                    [FUNCTION]
+;;;                 (output-stream *standard-output*)
+;;;                 (ignore-case *ignore-case*)
+;;;                 (ignore-whitespace *ignore-whitespace*)
+;;;                 (ignore-comments *ignore-comments*)
+;;;                 (ignore-blank-lines *ignore-blank-lines*)
+;;;                 (print-context *print-context*)
+;;;                 (print-fancy-header *print-fancy-header*))
+;;;    Compares the contents of the two files, outputting a report of what
+;;;    lines must be changed to bring the files into agreement. The report
+;;;    is similar to that generated by 'diff': Lines of the forms
+;;;    n1 a n3,n4
+;;;    n1,n2 d n3
+;;;    n1,n2 c n3,n4
+;;;    (where a is ADD, d is DELETE, and c is CHANGE) are followed by the
+;;;    lines affected in the first (left) file flagged by '<' then all
+;;;    the lines affected in the second (right) file flagged by '>'. If
+;;;    PRINT-CONTEXT is T, will print out some additional contextual
+;;;    information, such as additional lines before and after the affected
+;;;    text and the definition most likely to be affected by the changes. If
+;;;    PRINT-FANCY-HEADER is T, prints the file-author and file-write-date
+;;;    in the header. The report is output to OUTPUT-STREAM. Returns T if
+;;;    the files were "identical", NIL otherwise.
+;;;    If IGNORE-CASE is T, uses a case insensitive comparison.
+;;;    If IGNORE-WHITESPACE is T, ignores spaces and tabs that occur at
+;;;    the beginning of the line. If IGNORE-COMMENTS is T, tries to ignore
+;;;    comments at the end of the line. If *dont-ignore-major-comments*
+;;;    is T, will also ignore major comments (comments with a semicolon at
+;;;    char 0 of the line). If IGNORE-BLANK-LINES is T, will ignore blank
+;;;    lines in both files, including lines that are effectively blank
+;;;    because of ignored comments.
+;;;
+;;; *GREEDY-METRIC* (quote find-next-diagonal-match)              [VARIABLE]
+;;;    Variable containing the name of the greedy matching function used
+;;;    to minimize distance to the next match:
+;;;    find-next-rectilinear-match  minimizes  max(x,y)
+;;;    find-next-diagonal-match     minimizes  x+y
+;;;    where x is a line number from the first file and y is a line
+;;;    number from the second file.
+;;;
+;;; FIND-NEXT-DIAGONAL-MATCH (file-1 start-1 file-2 start-2)      [FUNCTION]
+;;;    Difference detected, look ahead for a match [x+y version].
+;;;
+;;; FIND-NEXT-RECTILINEAR-MATCH (file-1 start-1 file-2 start-2)   [FUNCTION]
+;;;    Difference detected, look ahead for a match [max(x,y) version].
+;;;
+;;;
+;;; *** Display Parameters ***
+;;;
+;;; *PRINT-CONTEXT* t                                             [VARIABLE]
+;;;    If T, we print the context marking lines that occur before the
+;;;    difference.
+;;;
+;;; *PRINT-FANCY-HEADER* ()                                       [VARIABLE]
+;;;    If T, prints a fancy header instead of the simple one.
+;;;
+;;; *CONTEXT-LINES-BEFORE-DIFFERENCE* 0                                     [VARIABLE]
+;;;    Number of lines to print before a difference.
+;;;
+;;; *CONTEXT-LINES-AFTER-DIFFERENCE* 1                                      [VARIABLE]
+;;;    Number of lines to print after a difference.
+;;;
+;;;
+;;; *** Program Default Parameters ***
+;;;
+;;; *MINIMUM-MATCH-LENGTH* 2                                     [VARIABLE]
+;;;    The minimum number of lines that must match for it to be considered
+;;;    a match. This has the effect of collecting lots of adjacent small
+;;;    differences together into one larger difference.
+;;;
+;;; *IGNORE-WHITESPACE* t                                         [VARIABLE]
+;;;    If T, will ignore spaces and tabs that occur at the beginning of the
+;;;    line before other text appears and at the end of the line after
+;;;    the last text has appeared.
+;;;
+;;; *IGNORE-CASE* t                                               [VARIABLE]
+;;;    If T, uses a case insensitive comparison. Otherwise uses a case
+;;;    sensitive comparison.
+;;;
+;;; *IGNORE-COMMENTS* t                                           [VARIABLE]
+;;;    If T, will try to ignore comments of the semicolon variety when
+;;;    comparing lines. Tries to be rather intelligent about the context
+;;;    to avoid ignoring something that really isn't a comment. For
+;;;    example, semicolons appearing within strings, even multi-line
+;;;    strings, are not considered comment characters. Uses the following
+;;;    heuristics to decide if a semicolon is a comment character or not:
+;;;    o  Slashification (\) works inside strings ("foo\"bar")
+;;;       and symbol names (|foo\|bar|), but not balanced comments
+;;;       (#|foobar\|#).
+;;;    o  Balanced comments do not work inside strings ("#|") or
+;;;       symbol names.
+;;;    o  Strings do not work inside balanced comments (#|"|#)
+;;;    o  Regular semicolon comments do not work inside strings,
+;;;       symbol names, or balanced comments (#|foo;bar|#).
+;;;    All this is necessary for it to correctly identify when a
+;;;    semicolon indicates the beginning of a comment. Conceivably we should
+;;;    consider a semicolon as a comment when it is inside a balanced
+;;;    comment which isn't terminated from the semicolon to the end of the
+;;;    line. However, besides being complicated and time-consuming to
+;;;    implement, the lisp interpreter doesn't treat it this way, and we
+;;;    like to err on the side of caution. Anyway, changes in the comments
+;;;    within commented out regions of code is worth knowing about.
+;;;
+;;; *DONT-IGNORE-MAJOR-COMMENTS* ()                               [VARIABLE]
+;;;    If T, ignoring comments does not ignore comments with a semicolon
+;;;    at position 0 of the line.
+;;;
+;;; *IGNORE-BLANK-LINES* t                                        [VARIABLE]
+;;;    If T, will ignore blank lines when doing the comparison.
+;;;
+
+;;; ****************************************************************
+;;; Source Compare *************************************************
+;;; ****************************************************************
+
+(defPackage "SOURCE-COMPARE" (:nicknames "SCP") (:use :cl :ccl))
+(in-package "SOURCE-COMPARE")
+
+(export '(source-compare		; main routine
+	  ;; Core function parameters used to keep files in sync.
+	  *greedy-metric*		
+	  *minimum-match-length*
+	  ;; Program default display.
+	  *print-context*		
+	  *print-fancy-header*
+	  *context-lines-before-difference*
+	  *context-lines-after-difference*
+	  ;; Program default modes.
+	  *ignore-comments*
+	  *dont-ignore-major-comments*
+	  *ignore-case*
+	  *ignore-whitespace*
+	  *ignore-blank-lines*))
+
+;;; ********************************
+;;; Global Vars ********************
+;;; ********************************
+(defVar *print-context* t ;nil
+  "If T, we print the context marking lines that occur before the difference.")
+(defVar *print-fancy-header* nil ;t
+  "If T, prints a fancy header instead of the simple one.")
+(defVar *context-lines-before-difference* 0
+  "Number of lines to print before a difference.")
+(defVar *context-lines-after-difference* 1 
+  "Number of lines to print after a difference.")
+
+(defVar *greedy-metric* 'find-next-diagonal-match
+  "Variable containing the name of the greedy matching function used
+   to minimize distance to the next match:
+      find-next-rectilinear-match  minimizes  max(x,y)
+      find-next-diagonal-match     minimizes  x+y
+   where x is a line number from the first file and y is a line number
+   from the second file.")
+
+(defVar *minimum-match-length* 2
+  "The minimum number of lines that must match for it to be considered
+   a match. This has the effect of collecting lots of adjacent small
+   differences together into one larger difference.")
+
+(defVar *ignore-whitespace* t
+  "If T, will ignore spaces and tabs that occur at the beginning of the
+   line before other text appears and at the end of the line after
+   the last text has appeared.")
+(defVar *ignore-case* t
+  "If T, uses a case insensitive comparison. Otherwise uses a case
+   sensitive comparison.")
+(defVar *ignore-comments* t
+  "If T, will try to ignore comments of the semicolon variety when
+   comparing lines. Tries to be rather intelligent about the context
+   to avoid ignoring something that really isn't a comment. For example, 
+   semicolons appearing within strings, even multi-line strings, are not
+   considered comment characters. Uses the following heuristics to decide
+   if a semicolon is a comment character or not:
+       o  Slashification (\\) works inside strings (\"foo\\\"bar\")
+          and symbol names (\|foo\\\|bar\|), but not balanced comments
+          (#|foobar\\|#).
+       o  Balanced comments do not work inside strings (\"\#\|\") or
+          symbol names.
+       o  Strings do not work inside balanced comments (#|\"|#)
+       o  Regular semicolon comments do not work inside strings, symbol
+          names, or balanced comments (#|foo;bar|#).
+   All this is necessary for it to correctly identify when a semicolon
+   indicates the beginning of a comment. Conceivably we should consider
+   a semicolon as a comment when it is inside a balanced comment which
+   isn't terminated from the semicolon to the end of the line. However,
+   besides being complicated and time-consuming to implement, the lisp
+   interpreter doesn't treat it this way, and we like to err on the side
+   of caution. Anyway, changes in the comments within commented out
+   regions of code is worth knowing about.")
+(defVar *dont-ignore-major-comments* nil ;t
+  "If T, ignoring comments does not ignore comments with a semicolon
+   at position 0 of the line.")
+(defVar *ignore-blank-lines* t
+  "If T, will ignore blank lines when doing the comparison.")
+
+;;; ********************************
+;;; File Cache *********************
+;;; ********************************
+
+;;; File-cache is a defstruct used to cache the lines of the file as
+;;; they are read.
+(defStruct (FILE-CACHE (:print-function
+			(lambda (o s d)
+			  (declare (ignore d))
+			  (format s "#<file-cache: ~a ~d ~a>"
+				  (file-cache-file-name o)
+				  (file-cache-length o)
+				  (file-cache-eof o)))))
+  ;; LINE-TABLE is a cache of the lines of the file read so far.
+  ;; INSIDE-STRING-TABLE is a table of flags which indicate whether the line
+  ;; terminates while still inside a string. If so, this table indicates
+  ;; what character will close the string. This is useful for parsing
+  ;; multi-line strings.
+  ;; BALANCED-COMMENT-COUNT-TABLE is a table of flags which indicate whether
+  ;; the line terminates while still inside a balanced comment, and if so,
+  ;; how many are left to be closed. This is useful for parsing multi-line
+  ;; balanced comments. 
+  ;; FILE-NAME is the name of the file.
+  ;; FILE-STREAM is the input stream open to the file.
+  ;; EOF is a flag which is true when the end of the file has been reached.
+  ;; If so, it is one more than the last valid line number.
+  (line-table (make-array (list 100.) 
+			  :element-type t :fill-pointer 0 :adjustable t)) 
+  (inside-string-table (make-array (list 100.) 
+				   :element-type t
+				   :initial-element nil
+				   :fill-pointer 0 :adjustable t))
+  (balanced-comment-count-table (make-array (list 100.) 
+					    :element-type t
+					    :initial-element 0
+					    :fill-pointer 0 :adjustable t))
+  file-name
+  file-stream				
+  (eof nil))
+
+(defun file-cache-length (file)
+  "The number of lines cached is simply the length of the line table.
+   Note that since this table has a fill-pointer, it's length is the 
+   size indicated by the fill-pointer, not the array dimensions."
+  (length (file-cache-line-table file)))
+
+(defun cached-line (file line-no)
+  "Returns a cached line from the line cache, if it exists."
+  (when (< line-no (file-cache-length file))
+    (aref (file-cache-line-table file) line-no)))
+
+(defun cached-comment-position-info (file line-no)
+  "Returns the cached comment position (inside-string and 
+   balanced-comment-count) information for the line, if it exists."
+  (if (< line-no (file-cache-length file))
+      (values (aref (file-cache-inside-string-table file) line-no)
+	      (aref (file-cache-balanced-comment-count-table file) line-no))
+    (values nil 0)))
+(defun set-cached-comment-position-info (file line-no inside-string
+					      balanced-comment-count)
+  "Sets the cached comment position information (inside-string and
+   balanced-comment-count) for the line."
+  ;; We assume that get-and-cache-next-line has ensured that the
+  ;; flag tables are the right length -- otherwise we're hosed.
+  ;; Why doesn't CL have a defsetf with multiple values? That would
+  ;; make life here so much easier. [Done 12-24-90 MK. Not installing
+  ;; here to avoid clashes with other Lisps.]
+  (setf (aref (file-cache-inside-string-table file) line-no) 
+	inside-string)
+  (setf (aref (file-cache-balanced-comment-count-table file) line-no) 
+	balanced-comment-count))
+
+(defun get-and-cache-next-line (file)
+  "Gets the next line from the file, installing it in the cache."
+  (let ((line (read-line (file-cache-file-stream file) nil nil)))
+    (if line
+	;; If there's a line, add it to the cache.
+	(progn
+	  (vector-push-extend line (file-cache-line-table file))
+	  (vector-push-extend nil (file-cache-inside-string-table file))
+	  (vector-push-extend 
+	   0 (file-cache-balanced-comment-count-table file)))
+      ;; If the line was null, we've reached the end of the file.
+      ;; Set the eof flag to be the line number of the end of file.
+      (setf (file-cache-eof file) (file-cache-length file)))
+    ;; Return the line.
+    line))
+
+(defun get-line (file line-no)
+  "Get the line from the file cache. If not present, get it from the stream."
+  (or (cached-line file line-no)
+      (when (not (file-cache-eof file))
+	(get-and-cache-next-line file))))
+
+(defMacro with-open-file-cached ((var filename &rest open-args) &body forms)
+  (let ((abortp (gensym "ABORTP"))
+	(stream (gensym (symbol-name var))))
+    `(let* ((,stream (open ,filename ,@open-args))
+	    (,var (make-file-cache :file-stream ,stream :file-name ,filename))
+	    (,abortp t))
+       (when ,var
+         (unwind-protect
+             (multiple-value-prog1
+                 (progn ,@forms)
+               (setq ,abortp nil))
+           (close ,stream :abort ,abortp))))))
+
+;;; ********************************
+;;; Line Comparison ****************
+;;; ********************************
+(defun first-non-whitespace-char (line &key from-end (start 0) end)
+  "Finds the position of the first character of LINE which is neither
+   a space or a tab. Returns NIL if no character found."
+  (position '(#\space #\tab) line
+	    :test-not #'(lambda (set char)
+			  (find char set :test #'char=))
+	    :from-end from-end
+	    :start start :end end))
+
+(defun line-start (line &optional (start 0))
+  "Returns the position of where in LINE to start the comparison."
+  (if *ignore-whitespace*
+      (or (first-non-whitespace-char line) start)
+    start))
+
+(defVar *slash-char* #\\
+  "The character used to slashify other characters.")
+(defVar *comment-char* #\;
+  "The character used to begin comments.")
+(defVar *string-quotes-char* #\"
+  "The character used to begin and end strings.")
+(defVar *string-bar-char* #\|
+  "The character used to begin and end symbols.")
+(defVar *splat-char* #\#
+  "One of the characters used to begin balanced comments.")
+(defVar *bar-char* #\|
+  "One of the characters used to begin balanced comments.")
+
+(defun find-comment-position (line &optional (start 0) end 
+				   &key inside-string (splat-bar-count 0))
+  "Tries to find the position of the beginning of the comment at the
+   end of LINE, if there is one. START and END delimit the search. END
+   defaults to the end of the line. If INSIDE-STRING is non-nil, it is
+   assumed that we're inside a string before we began (if so, INSIDE-STRING
+   is set to the character which will terminate the string (\#\\\" or \#\\\|).
+   SPLAT-BAR-COUNT is the number of unbalanced begin balanced comments
+   (\#\|'s) that have been seen so far."
+  (unless end (setf end (length line)))
+  (if (< start (length line))
+    (do ((position start (1+ position))
+	 (last-char-was-slash nil)
+	 (inside-string inside-string)
+	 (splat-bar-count splat-bar-count)
+	 (splat-flag nil)(bar-flag nil))
+	((= position end)
+	 ;; If we run off the end, return nil to signify 
+	 ;; that nothing was found.
+	 (values nil inside-string splat-bar-count))
+      (let ((char (char line position)))
+	;; Slashification works inside strings but not balanced comments.
+	;; Balanced comments do not work inside strings. 
+	;; Strings do not work inside balanced comments.
+	;; Regular comments do not work inside strings or balanced comments
+	(cond (last-char-was-slash 
+	       ;; If the last character was a slash, throw this one away
+	       ;; and reset the flag.
+	       (setf last-char-was-slash nil))
+	      ((and (zerop splat-bar-count) (char= char *slash-char*))
+	       ;; This is an unslashed slash occurring outside balanced
+	       ;; comments, so set the slash flag.
+	       (setf last-char-was-slash t))
+	      ((and (not inside-string)(char= char *splat-char*))
+	       ;; We saw a SPLAT which could begin/end a balanced comment.
+	       (cond (bar-flag
+		      ;; This is the second char of an end balanced comment.
+		      (when (plusp splat-bar-count)
+			;; If we see an extra end balanced comment
+			;; (splat-bar-count is zero), ignore it.
+			(decf splat-bar-count))
+		      (setf bar-flag nil))
+		     ((not bar-flag)
+		      ;; This is the first char of a begin balanced comment.
+		      (setf splat-flag t))))
+	      ((and (not inside-string) splat-flag (char= char *bar-char*))
+	       ;; We saw a BAR which could begin a balanced comment.
+	       ;; This is the second char of a begin balanced comment.
+	       (incf splat-bar-count)
+	       (setf splat-flag nil))
+	      ((and (not inside-string) (not splat-flag)
+		    (plusp splat-bar-count) (char= char *bar-char*))
+	       ;; We saw a BAR which could end a balanced comment.
+	       ;; This is the first char of an end balanced comment.
+	       (setf bar-flag t))
+	      ((and (zerop splat-bar-count)
+		    inside-string
+		    (char= char inside-string))
+	       ;; This is an unslashed end string or end symbol occurring
+	       ;; outside balanced comments. So reset inside-string to nil.
+	       (setf inside-string nil))
+	      ((and (zerop splat-bar-count)
+		    (null inside-string)
+		    (or (char= char *string-quotes-char*)
+			(char= char *string-bar-char*)))
+	       ;; This is an unslashed start string or start symbol occurring
+	       ;; outside balanced comments. So set inside-string to the
+	       ;; character which will end the string or symbol.
+	       (setf inside-string char))
+	      ((and (zerop splat-bar-count) (not inside-string)
+		    (char= char *comment-char*))
+	       ;; We're not slashified or inside a string or balanced comment
+	       ;; and we're a comment char, so we must begin a comment.
+	       (return (values position nil 0)))
+	      ((or bar-flag splat-flag)
+	       ;; We last saw a BAR or SPLAT, but some other unimportant
+	       ;; character was seen, so reset the flags.
+	       (setf splat-flag nil
+		     bar-flag nil)))))
+    (values nil nil 0)))
+
+;;; To see GNU-Emacs (and some lesser imitations) die miserably, put the
+;;; cursor before the # on the next line, and try doing C-M-f or C-M-e. Ha!
+#|
+;;; Test find-comment-position on the various combinations of
+;;; #| |#, ;, "foo", |foo|, and \. Note that this commented out
+;;; region of this source file will itself serve as a good test
+;;; when source-compare is run on this file! 
+(find-comment-position "#| ; |# ;")
+(find-comment-position "\" ; \" ;")
+(find-comment-position "| ; | ;")
+(find-comment-position "#\| ; | ;")
+(find-comment-position "#\\| ; | ;")
+(find-comment-position "| ; #\| ;")
+(find-comment-position "| ; #\| \" ;")
+|#
+
+(defun get-comment-position (line file line-no &optional (start 0) end)
+  "Returns the position of the beginning of the semicolon variety comment
+   on this line."
+  ;; Get the cached position info for the previous line. 
+  (multiple-value-bind (inside-string balanced-comment-count)
+      (if (zerop line-no)
+	  ;; Default for first line of the file.
+	  (values nil 0)
+	(cached-comment-position-info file (1- line-no)))
+    ;; Find the comment position for this line.
+    (multiple-value-bind (end new-is new-bcc)
+	(find-comment-position line start end 
+			       :inside-string inside-string
+			       :splat-bar-count balanced-comment-count)
+      ;; Cache the position info for this line.
+      (set-cached-comment-position-info file line-no new-is new-bcc)
+      ;; Return the comment end.
+      end)))
+
+(defun line-end (line file line-no &optional (start 0) end)
+  "Returns the position of where in LINE to end the comparison.
+   If the comparison should end at the end of the line, returns NIL.
+   START, if supplied, is where to start looking for the end."
+  ;; Note that find-comment-position will return nil if it doesn't
+  ;; find a comment, which is the default value of :end keywords
+  ;; in the string comparison functions (signifying the end of the string).
+  (let ((new-end (when *ignore-comments* 
+		   (get-comment-position line file line-no start end))))
+    (cond ((and *dont-ignore-major-comments*
+		*ignore-comments*
+		;; found a comment char and it's at the beginning of the line.
+		new-end (zerop new-end))
+	   ;; If we're not ignoring major comments (one's with the semicolon
+	   ;; at char 0 of the line), return the end of the line.
+	   (or end (length line)))
+	  ((or *ignore-whitespace* *ignore-comments*)
+	   ;; Ignoring comments means that we ignore the whitespace at the
+	   ;; end of the line, no matter what we do at the beginning. Otherwise
+	   ;; ignoring comments would have no affect.
+	   (or (first-non-whitespace-char line :start start :end new-end
+					  :from-end t)
+	       new-end (length line)))
+	  (t
+	   new-end))))
+
+(defun null-string (string &optional (start 0) end)
+  "Returns T if STRING is the null string \"\" between START and END."
+  (unless end (setf end (length string)))
+  (string-equal string "" :start1 start :end1 end))
+
+(defun compare-lines (file-1 line-no-1 file-2 line-no-2)
+  "Intelligently compare two lines. If *ignore-case* is T, uses
+   case-insensitive comparison. If *ignore-whitespace* is T, ignores
+   spaces and tabs at the beginning of the line. If *ignore-comments* 
+   is T, tries to ignore comments at the end of the line."
+  (let ((string-1 (get-line file-1 line-no-1))
+	(string-2 (get-line file-2 line-no-2)))
+    (if (or (null string-1) (null string-2))
+	;; If either of the lines is nil, both must be.
+	(and (null string-1) (null string-2))
+      ;; Both lines are non-nil, compare them!
+      (let* ((start-1 (line-start string-1))
+	     (start-2 (line-start string-2))
+	     (end-1 (line-end string-1 file-1 line-no-1 start-1))
+	     (end-2 (line-end string-2 file-2 line-no-2 start-2))
+	     lines-same)
+	(setf lines-same
+	      (funcall (if *ignore-case* #'string-equal #'string=)
+		       string-1 string-2
+		       :start1 start-1 :start2 start-2
+		       :end1 end-1 :end2 end-2))
+	;; If lines-same is NIL, returns values: lines-same l1-null l2-null
+	;; Otherwise returns just lines-same.
+	(if *ignore-blank-lines*
+	    (values lines-same
+		    (null-string string-1 start-1 end-1)
+		    (null-string string-2 start-2 end-2))
+	  lines-same)))))
+
+;;; ********************************
+;;; Main Routine *******************
+;;; ********************************
+(defun source-compare (filename-1 filename-2
+                                  &key (output-stream *standard-output*) 
+                                  (ignore-case *ignore-case*)
+				  (ignore-whitespace *ignore-whitespace*)
+				  (ignore-comments *ignore-comments*)
+				  (ignore-blank-lines *ignore-blank-lines*)
+				  (print-context *print-context*)
+				  (print-fancy-header *print-fancy-header*))
+  "Compares the contents of the two files, outputting a report of what lines
+   must be changed to bring the files into agreement. The report is similar
+   to that generated by 'diff': Lines of the forms
+      n1 a n3,n4
+      n1,n2 d n3
+      n1,n2 c n3,n4
+   (where a is ADD, d is DELETE, and c is CHANGE) are followed by the
+   lines affected in the first (left) file flagged by '<' then all the
+   lines affected in the second (right) file flagged by '>'. If PRINT-CONTEXT
+   is T, will print out some additional contextual information, such as 
+   additional lines before and after the affected text and the definition
+   most likely to be affected by the changes. If PRINT-FANCY-HEADER is T,
+   prints the file-author and file-write-date in the header. The report is
+   output to OUTPUT-STREAM. Returns T if the files were \"identical\",
+   NIL otherwise.
+   If IGNORE-CASE is T, uses a case insensitive comparison. 
+   If IGNORE-WHITESPACE is T, ignores spaces and tabs that occur at the
+   beginning of the line. If IGNORE-COMMENTS is T, tries to ignore
+   comments at the end of the line. If *dont-ignore-major-comments* is T, will
+   also ignore major comments (comments with a semicolon at char 0 of the
+   line). If IGNORE-BLANK-LINES is T, will ignore blank lines in both
+   files, including lines that are effectively blank because of ignored 
+   comments."
+  (with-open-file-cached (file-1 filename-1 :direction :input)
+    (with-open-file-cached (file-2 filename-2 :direction :input)
+      ;; Print the header.
+      (draw-header filename-1 filename-2 
+		   :stream output-stream 
+		   :print-fancy-header print-fancy-header)
+      ;; Do the actual comparisons.
+      (let ((no-changes
+	     (source-compare-internal file-1 file-2 :stream output-stream 
+				      :ignore-case ignore-case
+				      :ignore-whitespace ignore-whitespace
+				      :ignore-comments ignore-comments
+				      :ignore-blank-lines ignore-blank-lines
+				      :print-context print-context)))
+	;; Print the trailer.
+	(format output-stream  "~&~:[Done.~;No differences found.~]~%"
+		no-changes)
+	no-changes))))
+
+(defun source-compare-internal (file-1 file-2
+				       &key (stream *standard-output*)
+				       ignore-case ignore-whitespace
+				       ignore-comments ignore-blank-lines
+				       print-context)
+  "A greedy implementation of LCS (longest common substring) suitably
+   modified for source comparison. It is similar to the standard
+   O(n^2) dynamic programming algorithm, but we don't actually keep
+   distances or an explicit table. We assume that what has matched so
+   far is a correct match. When we encounter a difference, we find the
+   closest next match, where \"close\" is defined in terms of some
+   metric. Two common metrics are max(x,y) and x+y, where x is a line number
+   from file-2 and y is a line number from file-1. The former leads to 
+   expanding (exploring) the table by increasing rectangles, and the
+   latter by increasing triangles:
+                     #####          #
+                         #           #
+                         #            #
+                         #             #
+   The average case running time of this algorithm is O(m+n), where m and n
+   are the lengths of the two files. This seems to hold in practice. Worst
+   case, of course, is still O(n^2), but this hardly ever occurs for source
+   comparison. The metric is implemented by *greedy-metric*,
+   which is either FIND-NEXT-RECTILINEAR-MATCH or FIND-NEXT-DIAGONAL-MATCH."
+  (let ((*ignore-whitespace* ignore-whitespace) 
+        (*ignore-case* ignore-case)
+        (*ignore-comments* ignore-comments)
+	(*ignore-blank-lines* ignore-blank-lines)
+	(*print-context* print-context)
+	(no-changes t))
+    ;; Loop down both files, until a difference is encountered. Use
+    ;; the function *greedy-metric* to find where they match up again,
+    ;; print out the differences report for this divergence, and continue
+    ;; from where they match.
+    (do ((line-no-1 0 (1+ line-no-1))
+	 (line-no-2 0 (1+ line-no-2)))
+        ((and (file-cache-eof file-1) (>= line-no-1 (file-cache-eof file-1))
+	      (file-cache-eof file-2) (>= line-no-2 (file-cache-eof file-2)))
+	 ;; When we are at the end of both files, return whether the
+	 ;; files are identical or not.
+	 ;; use (eql (file-cache-eof file-1) (1- line-no-1)) here?
+	 ;; need the 1- because of where the incrementing is happening. 
+	 ;; could always have a 1+ in file-cache-eof.... 
+	 ;; well, the >= is safer.
+	 no-changes)
+      (multiple-value-bind (lines-same line-1-blank line-2-blank)
+	  (compare-lines file-1 line-no-1 file-2 line-no-2)
+	(cond (lines-same
+	       ;; The lines are the same. Do nothing.
+	       nil)
+	      ((and *ignore-blank-lines*
+		    (or line-1-blank line-2-blank))
+	       ;; The lines are different, but one is blank.
+	       ;; Skip over the blank lines.
+	       (cond ((and line-1-blank line-2-blank)
+		      ;; Do nothing -- they'll be skipped automatically.
+		      nil)
+		     (line-1-blank
+		      (decf line-no-2))
+		     (line-2-blank
+		      (decf line-no-1))))
+	      (t
+	       ;; Otherwise, a genuine difference has been encountered.
+	       ;; A difference has been encountered.
+	       (setq no-changes nil)
+	       (multiple-value-bind (same-line-no-1 same-line-no-2)
+		   ;; Find where they match up again.
+		   (funcall *greedy-metric* file-1 line-no-1 file-2 line-no-2)
+		 ;; Print the difference report
+		 (print-differences file-1 line-no-1 same-line-no-1
+				    file-2 line-no-2 same-line-no-2 stream)
+		 ;; Continue from where they match.
+		 (setq line-no-1 same-line-no-1
+		       line-no-2 same-line-no-2))))))))
+
+;;; ********************************
+;;; The Metrics ********************
+;;; ********************************
+
+(defun find-next-diagonal-match (file-1 start-1 file-2 start-2)
+  "First difference detected, look ahead for a match [x+y version]."
+  (let ((sum 0)
+	line-1 line-2
+	eof-1 eof-2)
+    ;; Starts sum (x+y) initially at zero, checks for a match on that
+    ;; diagonal, and then tries the next diagonal by incrementing sum.
+    (loop
+     ;; Check for a diagonal match.
+     (multiple-value-setq (line-1 line-2 eof-1 eof-2)
+	 (find-diagonal-match sum file-1 start-1 eof-1 file-2 start-2 eof-2))
+     ;; Have we found a match? If so, exit.
+     (when (and line-1 line-2)
+       (return (values line-1 line-2)))
+     ;; Increment sum
+     (incf sum))))
+
+(defun find-diagonal-match (sum file-1 start-1 eof-1 file-2 start-2 eof-2)
+  "Explores the diagonal with left-corner start-1 start-2 and index (x+y)
+   equal to sum, searching for a match. Returns the match if found."
+  ;; This starts at top left and works toward bottom right. This gives
+  ;; a slight favoring to deletions from file-1.
+  ;; For line-1 from (+ start-1 sum) downto start-1
+  ;; and line-2 from start-2 upto (+ start-2 sum).
+  ;; Need to ensure that the starts and ends aren't beyond the bounds
+  ;; of the files, so check them against eof-1 and eof-2.
+  (let ((init-1 (+ sum start-1))
+	(init-2 start-2)
+	(end-1 start-1)
+	(end-2 (+ sum start-2)))
+    ;; Ensure we have the current EOF line numbers.
+    (unless (or eof-1 (get-line file-1 init-1))
+      (setf eof-1 (file-cache-eof file-1)))
+    (unless (or eof-2 (get-line file-2 end-2))
+      (setf eof-2 (file-cache-eof file-2)))
+    ;; Adjust start and end to fit EOF.
+    (when (and eof-1 (> init-1 eof-1))
+      (setf init-2 (- init-1 eof-1))
+      (setf init-1 eof-1))
+    (when (and eof-2 (> init-2 eof-2))
+      (setf end-1 (- end-2 eof-2))
+      (setf end-2 eof-2))
+    ;; Check all the entries in the diagonal...
+    (do ((line-1 init-1 (1- line-1))
+	 (line-2 init-2 (1+ line-2)))
+	((or (< line-1 end-1)
+	     (> line-2 end-2))
+	 ;; We've walked off the end of the graph.
+	 (values nil nil eof-1 eof-2))
+      ;; If we've found a match, return it. Note that if we've hit
+      ;; EOF on both files, it will be considered a match.
+      (when (found-match file-1 line-1 file-2 line-2)
+	(return (values line-1 line-2 eof-1 eof-2))))))
+
+(defun find-next-rectilinear-match (file-1 start-1 file-2 start-2)
+  "First difference detected, look ahead for a match [max(x,y) version]."
+  (let ((line-1 start-1) 
+	(line-2 start-2)
+        eof-1 eof-2)
+    (loop
+     (when (and eof-1 eof-2)
+       (return (values line-1 line-2)))
+     (when (not eof-1)
+       ;; Check next line from first file against lines from second file.
+       ;; Finds horizontal match.
+       (incf line-1)
+       (let ((match (find-linear-match file-2 start-2 line-2 file-1 line-1)))
+	 (cond ((eq match :eof)
+		(setq eof-1 :eof))
+	       (match
+		(return (values line-1 match))))))
+     (when (not eof-2)
+       ;; Check next line from second file against lines from first file.
+       ;; Finds vertical match.
+       (incf line-2)
+       (let ((match (find-linear-match file-1 start-1 line-1 file-2 line-2)))
+	 (cond ((eq match :eof)
+		(setq eof-2 :eof))
+	       (match
+		(return (values match line-2)))))))))
+
+(defun find-linear-match (file line-start line-end comp-file comp-line-no)
+  "Proceeds linearly in file from line-start to line-end until it 
+   finds a match against comp-line-no of comp-file."
+  (do ((line-no line-start (1+ line-no)))
+      ((> line-no line-end))
+    (cond ((found-match file line-no comp-file comp-line-no)
+	   ;; returns the match
+	   (return line-no))
+	  ((file-cache-eof comp-file)
+	   (return :eof)))))
+
+(defun found-match (file-1 line-1 file-2 line-2)
+  "Check if we've found a match by verifying that the next few lines
+   are identical. If *minimum-match-length* is more than 1, has the
+   effect of grouping together differences separated only by one 
+   matching line."
+  ;; Note that this declares a match as early as possible, keeping
+  ;; comments out of the match region. so-co then has to
+  ;; skip over the same blank lines as we did. Any way to optimize
+  ;; this?
+  (do ((line-1 line-1 (1+ line-1))
+       (line-2 line-2 (1+ line-2))
+       (first-match t)
+       (count 0 (1+ count)))
+      ((= count *minimum-match-length*)
+       t)
+    ;; Should we wrap a (let ((*ignore-comments* nil))) around this
+    ;; so that comments *do* count for matching up? Probably not.
+    (multiple-value-bind (lines-same line-1-blank line-2-blank)
+	(compare-lines file-1 line-1 file-2 line-2)
+      ;; Note that only if *ignore-blank-lines* is T could
+      ;; line-1-blank and line-2-blank be non-nil. 
+      (cond ((and lines-same (not (or line-1-blank line-2-blank)))
+	     ;; A real line matching a real line. Do nothing since
+	     ;; the count is automatically incremented.
+	     nil)
+	    (lines-same
+	     ;; A fake line matching by at least one blank. Skip it
+	     ;; and keep it out of the count.
+	     (decf count))
+	    ((or line-1-blank line-2-blank)
+	     ;; We have a match fail, but because of at least one
+	     ;; blank line. Skip over the blank line,
+	     (cond ((and line-1-blank line-2-blank)
+		    ;; Two blank lines. Do nothing -- they'll be
+		    ;; skipped automatically.
+		    nil)
+		   (first-match 
+		    ;; We have a mismatch of real against blank, and it's on
+		    ;; the first real pairing. Skipping the blank line would
+		    ;; lead to so-co getting out of sync, so we
+		    ;; must fail here and exit.
+		    (return nil))
+		   (line-1-blank
+		    ;; Skip over this blank line (the line number is
+		    ;; automatically incremented), but not over the other.
+		    (decf line-2))
+		   (line-2-blank
+		    (decf line-1)))
+	     ;; and keep this match fail out of the count.
+	     (decf count))
+	    (t
+	     ;; A true non-match. Exit.
+	     (return nil)))
+      (when first-match (setf first-match nil)))))
+
+
+
+#|
+;;; older version
+(defun found-match (file-1 line-1 file-2 line-2)
+  "Check if we've found a match by verifying that the next few lines
+   are identical. If *minimum-match-length* is more than 1, has the
+   effect of grouping together differences separated only by one 
+   matching line."
+  (do ((line-1 line-1 (1+ line-1))
+       (line-2 line-2 (1+ line-2))
+       (count 0 (1+ count)))
+      ((= count *minimum-match-length*)
+       t)
+    ;; Should we wrap a (let ((*ignore-comments* nil))) around this
+    ;; so that comments *do* count for matching up? Probably not.
+    (multiple-value-bind (lines-same line-1-blank line-2-blank)
+	(compare-lines file-1 line-1 file-2 line-2)
+      ;; Note that only if *ignore-blank-lines* is T could
+      ;; line-1-blank and line-2-blank be non-nil. 
+      (cond ((and lines-same (not (or line-1-blank line-2-blank)))
+	     ;; A real line matching a real line. Do nothing.
+	     nil)
+	    (lines-same
+	     ;; A fake line matching by at least one blank. Skip it
+	     ;; and keep it out of the count.
+	     (decf count))
+	    (t
+	     ;; A non-match. Exit.
+	     (return nil))))))
+|#
+
+;;; ********************************
+;;; Line Contexts ******************
+;;; ********************************
+(defun start-context (file line-no)
+  "Walks backwards from LINE-NO until it finds the beginning of a 
+   definition (a line with a left-parenthesis on char 0)."
+  (when (plusp line-no)
+    (do* ((i (1- line-no) (1- i))
+	  (line (get-line file i) (get-line file i)))
+	((zerop i))
+      (when (and (plusp (length line))
+		 (char-equal #\( (char line 0)))
+	(return (values line i))))))
+
+;;; ********************************
+;;; Report Generator ***************
+;;; ********************************
+(defun draw-header (filename-1 filename-2 
+			       &key (stream *standard-output*)
+			       print-fancy-header)
+  "Draw the header for the source compare report."
+  (draw-bar stream)
+  (cond (print-fancy-header
+	 ;; Print the file write dates of the files.
+	 (format stream "~&Source compare of")
+	 (format stream "~&     ~A~&     (written by ~A, ~A)"
+		 filename-1
+		 (file-author filename-1) 
+		 (time-string (file-write-date filename-1)))
+	 (format stream "~&  with")
+	 (format stream "~&     ~A~&     (written by ~A, ~A)"
+		 filename-2 
+		 (file-author filename-2)
+		 (time-string (file-write-date filename-2))))
+	(t
+	 (format stream "~&Source compare of ~A with ~A"
+		 filename-1 filename-2)))
+  (draw-bar stream)	 
+  (finish-output stream))
+
+;;; changed universal-time to u-time - gef 
+(defun time-string (u-time)
+  (when u-time
+    (multiple-value-bind (secs min hour date month year dow)
+	(decode-universal-time u-time)
+      (format nil "~@:(~A ~A-~A-~A ~2,'0d:~2,'0d:~2,'0d~)"
+	      (svref '#("Mon" "Tue" "Wed" "Thu" "Fri" "Sat" "Sun") dow)
+	      date 
+	      (svref '#(0 "Jan" "Feb" "Mar" "Apr" "May"
+			  "Jun" "Jul" "Aug" "Sep" "Oct"
+			  "Nov" "Dec")
+		     month)
+	      (mod year 100)
+	      hour min secs))))
+
+(defun draw-bar (&optional (stream *standard-output*))
+  "Draws a dash across the line."
+  (format stream "~&~V,,,'=A~%" 75 "="))
+
+(defun print-range (start end &optional (stream *standard-output*))
+  "Prints a representation of the range from START to END."
+  (cond ((= start end)
+	 (format stream "~D" start))
+	((= start (1- end))
+	 (format stream "~D" (1+ start)))
+	(t
+	 (format stream "~D,~D" (1+ start) end))))
+
+(defun print-differences (file-1 start-1 end-1 file-2 start-2 end-2
+				 &optional (stream *standard-output*))
+  "Print the differences in the two files in a format similar to diff." 
+  (print-range start-1 end-1 stream)
+  (cond ((= end-1 start-1)
+	 ;; We added the text in file2
+	 (format stream "a"))
+	((= end-2 start-2)
+	 ;; We deleted the text from file1
+	 (format stream "d"))
+	(t
+	 ;; We replaced the text from file1 with the text from file2
+	 (format stream "c")))
+  (print-range start-2 end-2 stream)
+  (print-file-segment file-1 start-1 end-1 stream "< ")
+  (format stream "~&---")
+  (print-file-segment file-2 start-2 end-2 stream "> ")
+  (draw-bar stream)
+  ;; Make sure that the output is displayed piecemeal.
+  (finish-output stream))
+
+(defun print-file-segment (file start end 
+				&optional (stream *standard-output*)
+				(left-margin ""))
+  "Prints the region of FILE from START to END."
+  (when *print-context*
+    ;; If we want to provide a little context for the changes,
+    ;; first change the start and end to add in the specified number
+    ;; of extra lines to print.
+    (setf start (max 0 (- start *context-lines-before-difference*))
+	  end (+ end *context-lines-after-difference*))
+    ;; Then print the name of the file and the beginning of the
+    ;; current definition.
+    (let ((context (start-context file start)))
+      (format stream "~&**** File ~A~@[, After \"~A\"~]"
+	      (file-cache-file-name file) context)))
+  ;; Then print the lines from start to end, with a left margin as specified.
+  (do ((line-no start (1+ line-no))
+       (line))
+      ((= line-no end))
+    (unless (setq line (get-line file line-no))
+      (return nil))
+    (format stream "~%~A~A" left-margin line)))
+
+;;; *EOF*
Index: /trunk/contrib/foy/source-comparison/source-comparison.lisp
===================================================================
--- /trunk/contrib/foy/source-comparison/source-comparison.lisp	(revision 13946)
+++ /trunk/contrib/foy/source-comparison/source-comparison.lisp	(revision 13946)
@@ -0,0 +1,20 @@
+
+;;; source-comparison.lisp 
+
+(unless (member "SOURCE-COMPARISON" *modules* :test #'string-equal)
+  
+(eval-when (:load-toplevel :execute)
+  (defParameter *source-compare-directory*
+    (make-pathname :name nil :type nil :defaults (if *load-pathname* 
+                                                     *load-pathname*
+                                                     *loading-file-source-file*)))
+  (defParameter *source-compare-files* 
+    (list (merge-pathnames ";source-compare.lisp" *source-compare-directory*)
+          (merge-pathnames ";source-compare-dialog.lisp" *source-compare-directory*))))
+ 
+(dolist (file *source-compare-files*)
+  (load file))
+
+(provide :source-comparison)
+
+)
Index: /trunk/contrib/foy/syntax-styling/syntax-styling-1.lisp
===================================================================
--- /trunk/contrib/foy/syntax-styling/syntax-styling-1.lisp	(revision 13946)
+++ /trunk/contrib/foy/syntax-styling/syntax-styling-1.lisp	(revision 13946)
@@ -0,0 +1,1024 @@
+;;;-*- mode: lisp; package: (syntax-styling (cl ccl hemlock-internals)) -*-
+
+;;; ****************************************************************************
+;;; 
+;;;      syntax-styling-1.lisp
+;;;      
+;;;      copyright (c) 2009 Glen Foy
+;;;      (Permission is granted to Clozure Associates to distribute this file.)
+;;;
+;;;      This software is offered "as is", without warranty of any kind.
+;;;
+;;;      Mod history, most recent first:
+;;;      10/18/9   first cut.
+;;;
+;;; ****************************************************************************
+
+
+(in-package "SAX")
+
+;;; *** redefinition ***
+(let ((text-view nil)
+      (text-view-vscroll -100000))
+  (defMethod gui::compute-temporary-attributes ((self gui::hemlock-textstorage-text-view))
+    #+sax-debug (when *compute-temporary-attributes-debug* 
+                   (debug-out "~%~%~S" 'compute-temporary-attributes)
+                   (debug-out "~%*style-screen-p*: ~S" *style-screen-p*)
+                   (debug-out "~%*style-top-level-form-p*: ~S" *style-top-level-form-p*)
+                   (debug-out "~%*paste-p*: ~S" *paste-p*)
+                   (debug-out "~%*paste-start*: ~S" *paste-start*)
+                   (debug-out "~%*paste-end*: ~S" *paste-end*))
+    (let ((current-vscroll (gui::text-view-vscroll self)))
+      (when (or (not (equal self text-view))
+                (not (= current-vscroll text-view-vscroll)))
+        (when (and *styling-p* *style-screen-p* (not *paste-p*))
+         (style-screen self)))
+        (setq text-view self)
+        (setq text-view-vscroll current-vscroll))
+    (cond (*style-top-level-form-p* 
+           (style-top-level-form self))
+          (*paste-p* 
+           (setq *paste-end* (sexpr-end *paste-start*))
+           (yank-after (gui::hemlock-view self) *paste-start* *paste-end*)))
+    (let* ((container (#/textContainer self))
+           (layout (#/layoutManager container)))
+      (when (eql #$YES (gui::text-view-paren-highlight-enabled self))
+        (let* ((background #&NSBackgroundColorAttributeName)
+               (paren-highlight-left (gui::text-view-paren-highlight-left-pos self))
+               (paren-highlight-right (gui::text-view-paren-highlight-right-pos self))
+               (paren-highlight-color (gui::text-view-paren-highlight-color self))
+               (attrs (#/dictionaryWithObject:forKey: ns:ns-dictionary
+                                                      paren-highlight-color
+                                                      background)))
+          (#/addTemporaryAttributes:forCharacterRange:
+           layout attrs (ns:make-ns-range paren-highlight-left 1))
+          (#/addTemporaryAttributes:forCharacterRange:
+           layout attrs (ns:make-ns-range paren-highlight-right 1))))))
+
+  (defun reset-text-view () (setq text-view nil)))
+
+;;; *** Buffer-writable is broken
+;;; *** Instead of doing all this stuff need the equivalent of:
+;;; *** (setf ccl::*default-editor-class* 'derived-hemlock-frame-class)
+#-list-definitions
+(let ((writable-p t)
+      (lisp-file-p t)
+      (hemlock-frame nil))
+  (objc:defMethod (#/becomeKeyWindow :void) ((w gui::hemlock-frame))
+    (unless (equal w hemlock-frame)
+      (let ((path (window-path w))
+            (file-manager (#/defaultManager ns:ns-file-manager)))
+        (setq writable-p 
+              (if path
+                (#/isWritableFileAtPath: file-manager (ccl::%make-nsstring path))
+                t)) ; new files may not have a path yet.
+        (setq lisp-file-p
+              (if path
+                (string-equal (pathname-type path) "lisp")
+                t))) ; we assume a new file is a lisp file.
+      (setq hemlock-frame w))
+    (let ((become-key-function (find-symbol "BECOME-KEY-WINDOW" (find-package :ldefs))))
+      (when become-key-function (funcall become-key-function w)))
+    (call-next-method))
+  (defun lisp-file-p () lisp-file-p)
+  (defun writable-p () writable-p))
+
+#+list-definitions
+(let ((writable-p t)
+      (lisp-file-p t)
+      (hemlock-frame nil))
+  (defMethod become-key-window ((w gui::hemlock-frame))
+    (unless (equal w hemlock-frame)
+      (let ((path (window-path w))
+            (file-manager (#/defaultManager ns:ns-file-manager)))
+        (setq writable-p 
+              (if path
+                (#/isWritableFileAtPath: file-manager (ccl::%make-nsstring path))
+                t)) ; new files may not have a path yet.
+        (setq lisp-file-p
+              (if path
+                (string-equal (pathname-type path) "lisp")
+                t))) ; we assume a new file is a lisp file.
+      (setq hemlock-frame w)))
+  (defun lisp-file-p () lisp-file-p)
+  (defun writable-p () writable-p))
+
+(defun style-screen (text-view &optional generic-start generic-end)
+  (when *styling-p*
+    #+sax-debug (when *style-screen-debug* 
+                  (debug-out "~%~%~S" 'style-screen)
+                  (debug-out "~%*paste-start*: ~S" *paste-start*)
+                  (debug-out "~%*paste-end*: ~S" *paste-end*))
+    (let* ((container (#/textContainer text-view))
+           (scrollview (#/enclosingScrollView text-view))
+           (contentview (if (%null-ptr-p scrollview) text-view (#/contentView scrollview)))
+           (rect (#/bounds contentview))
+           (layout (#/layoutManager container))
+           (glyph-range (#/glyphRangeForBoundingRect:inTextContainer:
+                         layout rect container))
+           (char-range (#/characterRangeForGlyphRange:actualGlyphRange:
+                        layout glyph-range +null-ptr+))
+           (window (#/window scrollview))
+           (hemlock-view (gui::hemlock-view text-view))
+           (current-buffer (hi::hemlock-view-buffer hemlock-view))
+           (*buf* current-buffer)
+           (hi::*current-buffer* *buf*)
+           (*inc-pos* (clone (buffer-point *buf*)))
+           (*layout* (#/layoutManager container))
+           top-pos bot-pos start-mark end-mark)
+      (unless (typep (#/window scrollview) 'gui::hemlock-listener-frame)
+        (setq top-pos (ns:ns-range-location char-range))
+        (setq bot-pos (+ top-pos (ns:ns-range-length char-range)))
+        (setq start-mark (hemlock::top-level-offset (mark-offset (buf-start-mark current-buffer) top-pos) -1))
+        (setq end-mark (hemlock::top-level-offset (mark-offset (buf-start-mark current-buffer)  bot-pos) 1))
+        (when (null start-mark) (setq start-mark (buf-start-mark)))
+        (when (null end-mark) (setq end-mark (buf-end-mark)))
+        (when (and start-mark end-mark)
+          (hemlock::parse-over-block (hemlock-internals::mark-line start-mark) 
+                                     (hemlock-internals::mark-line end-mark))
+          (if (and generic-start generic-end)
+            (set-generic-text-style text-view generic-start generic-end)
+            (set-generic-text-style text-view start-mark end-mark))
+          (style-comments start-mark end-mark)
+          (style-forms window :start start-mark :end end-mark :caps-p nil :toplevel-p t))))))
+
+(defParameter *defstyle-hash-table* (make-hash-table :test 'equal))
+
+(defun get-function (name)
+  (gethash (string-upcase name) *defstyle-hash-table*))
+
+(defun add-style (name-string func)
+  (setf (gethash (string-upcase name-string) *defstyle-hash-table*) func))
+
+(defun style-elements (symbol-start form-end &optional loop-p)
+  "Step through the code sexpr by sexpr, styling appropriately."
+  #+sax-debug (when *style-elements-debug* 
+               (debug-out "~%~%~S" 'style-elements)
+               (debug-out "~%element symbol-start: ~S" symbol-start)
+               (debug-out "~%element form-end: ~S" form-end))
+  (flet ((not-char-constant-p (element-start)
+           (or (< (mark-charpos element-start) 2)
+               (char/= (mark-char element-start -1) #\\)
+               (char/= (mark-char element-start -2) #\#)))
+         (check-dynamic-p (element-start element-end)
+           (or (not *inc-p*)
+               (and *inc-p*
+                    (mark>= *inc-pos* element-start)
+                    (mark<= *inc-pos* element-end))))
+         (loop-keywd-p (string)
+           ;; hash table?
+           (member string
+                   '("above" "across" "always" "and" "append" "appending" "by" "collect" "collecting" "count" 
+                     "counting" "do" "doing" "downfrom" "downto" "each" "else" "end" "external-symbol" 
+                     "external-symbols" "finally" "for" "from" "hash-key" "hash-keys" "hash-value"
+                     "hash-values" "if" "in" "into" "initially" "loop-finish" "maximize maximizing" 
+                     "minimize" "minimizing" "named" "nconc" "nconcing" "never" "of" "on" "present-symbol" 
+                     "present-symbols" "repeat" "return" "sum" "summing" "symbol" "symbols" "the" "then" 
+                     "thereis" "to" "unless" "until" "upfrom" "upto" "using" "when" "while" "with")
+                   :test #'string-equal)))
+    (do* ((element-start symbol-start
+                         (when element-end (next-sexpr-start element-end)))
+          (element-end (when element-start (sexpr-end element-start))
+                       (when element-start (sexpr-end element-start)))
+          (current-char (when element-start (mark-char element-start))
+                        (when element-start (mark-char element-start))))
+         ((or (null element-start) (null element-end) (mark>= element-start form-end)))
+      #+sax-debug (when *style-elements-debug* 
+                   (debug-out "~%element-start: ~S" element-start)
+                   (debug-out "~%element-end: ~S" element-end))
+      (when (or (not *segment-array*)
+                (not-embedded-in-segment-p *segment-array* element-start))
+        (when (or (char= current-char #\')
+                  (char= current-char #\`)
+                  (char= current-char #\,))
+          (nmark-next element-start)
+          (setf current-char (mark-char element-start)))
+        (when (char= current-char #\@)
+          (nmark-next element-start)
+          (setf current-char (mark-char element-start)))
+        (when (char= current-char #\')
+          (nmark-next element-start)
+          (setf current-char (mark-char element-start)))
+        (when (char= current-char #\,)
+          (nmark-next element-start)
+          (setf current-char (mark-char element-start)))
+        (cond ((and (char= current-char #\()
+                    (not-char-constant-p element-start)
+                    (check-dynamic-p element-start element-end))
+               (rd-style-forms :start element-start :end element-end))
+              ((and (char= current-char #\#)
+                    (mark< element-start (mark-offset (buf-end-mark) -2))
+                    (char= (mark-char element-start 1) #\')
+                    (char= (mark-char element-start 2) #\()
+                    (check-dynamic-p element-start element-end))
+               (rd-style-forms :start (mark-offset element-start 2) :end element-end))
+              ((and (char= current-char #\:)
+                    (not-char-constant-p element-start))
+               (style-region *keyword-package-style*
+                             element-start (sexpr-end element-start)))
+              ((and loop-p
+                    (alpha-char-p current-char)
+                    (loop-keywd-p (region-to-string (region element-start element-end))))
+               (style-region *loop-keyword-style* 
+                             element-start element-end)))))))
+
+(defun backward-top-level-list (start)
+  "Get the previous #\( in charpos 0, that is not embedded in a comment."
+  #+sax-debug (when *backward-top-level-list-debug*
+               (debug-out "~%~%~S" 'backward-top-level-list)
+               (debug-out "~%start: ~S" start))
+  (when (null start) (return-from backward-top-level-list nil))
+  (do* ((next (pattern-search start *l-paren-backward-pattern*)
+              (pattern-search (mark-prev next) *l-paren-backward-pattern*))
+        not-embedded)
+       ((null next) (return nil))
+    #+sax-debug (when *backward-top-level-list-debug* 
+                  (debug-out "~%next: ~S" next))
+    (if *segment-array*
+      (setf not-embedded (not-embedded-in-segment-p *segment-array* next))
+      (setf not-embedded t))
+    #+sax-debug (when *backward-top-level-list-debug* 
+                  (debug-out "~%*segment-array*: ~S" *segment-array*)
+                  (debug-out "~%not-embedded: ~S" not-embedded))
+    (when (and (= (mark-charpos next) 0) not-embedded)
+      (return next))))
+
+(defun forward-top-level-list (start &optional (end (buf-end-mark)))
+  "Get the next #\( in charpos 0, that is not embedded in a comment."
+  #+sax-debug (when *forward-top-level-list-debug*
+               (debug-out "~%~%~S" 'forward-top-level-list)
+               (debug-out "~%start: ~S" start)
+               (debug-out "~%end: ~S" end))
+  (when (or (null start) (null end)) (return-from forward-top-level-list nil))
+  (do* ((next (pattern-search start *l-paren-forward-pattern* end)
+              (pattern-search (mark-next next) *l-paren-forward-pattern* end))
+        not-embedded)
+       ((null next) (return nil))
+    #+sax-debug (when *forward-top-level-list-debug* 
+                  (debug-out "~%next: ~S" next))
+    (if *segment-array*
+      (setf not-embedded (not-embedded-in-segment-p *segment-array* next))
+      (setf not-embedded t))
+    #+sax-debug (when *forward-top-level-list-debug* 
+                  (debug-out "~%*segment-array*: ~S" *segment-array*)
+                  (debug-out "~%not-embedded: ~S" not-embedded))
+    (when (and (= (mark-charpos next) 0) not-embedded)
+      (return next))))
+
+;;; This will skip incomplete forms and continue with the next toplevel list.
+(defun list-top-level-forms (&optional (start (buf-start-mark)) (end (buf-end-mark)))
+  "Returns a list of starting marks for all the top-level lists in the range START, END."
+   #+sax-debug (when *list-top-level-forms-debug* 
+               (debug-out "~%~%~S" 'list-top-level-forms)
+               (debug-out "~%start: ~S" start)
+               (debug-out "~%end: ~S" end)) 
+  (do* ((positions nil)
+        (sexpr-start (forward-top-level-list start  end)
+                     (when sexpr-end (forward-top-level-list sexpr-end end)))
+        (sexpr-end (when sexpr-start (limited-sexpr-end sexpr-start end))
+                   (when sexpr-start (limited-sexpr-end sexpr-start end))))
+       ((or (null sexpr-start)
+            (mark> sexpr-start end))
+        (return (nreverse positions)))
+    (cond (sexpr-end ; ie a complete list
+           (push sexpr-start positions))
+          (t ; an incomplete list - skip it
+           (setq sexpr-end (mark-next sexpr-start))))))
+  
+(defun forward-list (start &optional (end (buf-end-mark)))
+  "Get the next #\( that is not embedded in a comment and not a character constant."
+  #+sax-debug (when *forward-list-debug*
+               (debug-out "~%~%~S" 'forward-list)
+               (debug-out "~%forward-list start: ~S" start)
+               (debug-out "~%forward-list end: ~S" end))
+  (when (or (null start) (null end)) (return-from forward-list nil))
+  (do* ((next (pattern-search start *l-paren-forward-pattern* end)
+              (pattern-search (mark-next next) *l-paren-forward-pattern* end))
+        not-embedded)
+       ((null next) (return nil))
+    #+sax-debug (when *forward-list-debug* 
+                 (debug-out "~%next: ~S" next))
+    (if *segment-array*
+      (setf not-embedded (not-embedded-in-segment-p *segment-array* next))
+      (setf not-embedded t))
+    #+sax-debug (when *forward-list-debug* 
+                  (debug-out "~%*segment-array*: ~S" *segment-array*)
+                  (debug-out "~%not-embedded: ~S" not-embedded))
+    (cond ((>= (mark-charpos next) 2)
+           #+sax-debug (when *forward-list-debug* 
+                        (debug-out "~%(>= (mark-charpos next) 2)"))
+           (when (and not-embedded
+                      (not (and (eq (mark-char next -1) #\\)
+                                (eq (mark-char next -2) #\#)))
+                      (neq (mark-char next -1) #\#))
+             #+sax-debug (when *forward-list-debug* 
+                          (debug-out "~%returning: ~S" next))
+             (return next)))
+          (t 
+           #+sax-debug (when *forward-list-debug* 
+                        (debug-out "~%(< (mark-charpos next) 2)"))
+           (when not-embedded 
+             #+sax-debug (when *forward-list-debug* 
+                          (debug-out "~%returning: ~S" next))
+             (return next))))))
+
+(defun list-forms (&optional (start (buf-start-mark)) (end (buf-end-mark)))
+  "Returns a list of starting marks for all the lists in the range START, END."
+  #+sax-debug (when *list-forms-debug* 
+               (debug-out "~%~%~S" 'list-forms)
+               (debug-out "~%start: ~S" start)
+               (debug-out "~%end: ~S" end))
+  (do* ((positions nil)
+        (sexpr-start (forward-list start end)
+                    (forward-list sexpr-end end))
+        (sexpr-end (when sexpr-start (limited-sexpr-end sexpr-start end))
+                   (when sexpr-start (limited-sexpr-end sexpr-start end)))
+        (current-char (when sexpr-start (mark-char sexpr-start))
+                      (when sexpr-start (mark-char sexpr-start))))
+       ((or (null sexpr-end)
+            (null sexpr-start)
+            (mark> sexpr-start end))
+        (return (nreverse positions)))
+    #+sax-debug (when *list-forms-debug* 
+                 (debug-out "~%sexpr-start: ~S" sexpr-start)
+                 (debug-out "~%sexpr-end: ~S" sexpr-end)
+                 (debug-out "~%*inc-pos*: ~S" *inc-pos*)
+                 (debug-out "~%current-char: ~S" current-char))
+    (when (or (char= current-char #\')
+              (char= current-char #\`)
+              (char= current-char #\,))
+      (nmark-next sexpr-start) 
+      (setf current-char (mark-char sexpr-start)))
+    (when (char= current-char #\@)
+      (nmark-next sexpr-start) 
+      (setf current-char (mark-char sexpr-start)))
+    (when (char= current-char #\')
+      (nmark-next sexpr-start) 
+      (setf current-char (mark-char sexpr-start)))
+    (when (char= current-char #\,)
+      (nmark-next sexpr-start) 
+      (setf current-char (mark-char sexpr-start)))
+    ;; when styling incrementally, only include forms 
+    ;; if *inc-pos* is inside the form.
+    (cond ((char= current-char #\()
+           (when (or (not *inc-p*)
+                     (and *inc-p*
+                          (mark>= *inc-pos* sexpr-start)
+                          (mark<= *inc-pos* sexpr-end)))
+             #+sax-debug (when *list-forms-debug* 
+                           (debug-out "~%pushing: ~S" (region-to-string (region sexpr-start sexpr-end))))
+             (push sexpr-start positions)))
+          ((char= current-char #\#)
+           (cond ((and (mark< sexpr-start (buf-end-mark))
+                       (char= (mark-char sexpr-start 1) #\')
+                       (char= (mark-char sexpr-start 2) #\())
+                  (when (or (not *inc-p*)
+                            (and *inc-p*
+                                 (mark>= *inc-pos* sexpr-start)
+                                 (mark<= *inc-pos* sexpr-end)))
+                    (push (nmark-next (nmark-next sexpr-start)) positions))))))))
+
+(defun defstyle-form-styled-p (position)
+  "If there is a defstyle form at POSITION, style it and return T.  If not, return NIL."
+  (when position
+    #+sax-debug (when *defstyle-form-styled-p-debug* 
+                 (debug-out "~%~%~S" 'defstyle-form-styled-p)
+                 (debug-out "~%defstyle position: ~S" position))
+    (let* ((symbol-start (mark-next position)) ; skip paren
+           (symbol-end (sexpr-end symbol-start))
+           (string (region-to-string (region symbol-start symbol-end)))
+           (styling-function (get-function string)))
+      (when styling-function 
+        (funcall styling-function position) 
+        t))))
+
+(defun package-form-styled-p (position)
+  "If there is a :cl function at POSITION, style it and return T.  If not, return NIL."
+  (when position
+    #+sax-debug (when *package-form-styled-p-debug* 
+                 (debug-out "~%~%~S" 'package-form-styled-p)
+                 (debug-out "~%package position: ~S" position))
+    (let* ((symbol-start (mark-next position))
+           (symbol-end (sexpr-end symbol-start)))
+      (cond ((char= (mark-char position) #\:)
+             (style-region *keyword-package-style* symbol-start symbol-end) t)
+            ((find-symbol (string-upcase (region-to-string (region symbol-start symbol-end))) :cl)
+             (style-region *cl-package-style* symbol-start symbol-end)
+             #+sax-debug (when *package-form-styled-p-debug* (debug-out "~%package styled"))
+             t)))))
+
+(defun rd-style-forms (&key (start (buf-start-mark)) (end (buf-end-mark)) top-level-p)
+  "Style the buffer using a recursive descent algorithm, given the range START, END."
+  #+sax-debug (when *rd-style-forms-debug* 
+                 (debug-out "~%~%~S" 'rd-style-forms)
+                 (debug-out "~%rd-style-forms start: ~S" start)
+                 (debug-out "~%rd-style-forms end: ~S" end))
+  (let ((positions (if top-level-p (list-top-level-forms start end) (list-forms start end)))
+        form-end)
+    #+sax-debug (when *rd-style-forms-debug* 
+                 (debug-out "~%rd-style-forms positions: ~S" positions))
+    (cond (positions 
+           (dolist (position positions)
+             #+sax-debug (when *rd-style-forms-debug* 
+                           (debug-out "~%all positions: ~S" positions)
+                           (debug-out "~%rd position list position: ~S" position))
+             (unless (defstyle-form-styled-p position)
+               (when (setf form-end (limited-sexpr-end position end))
+                 (cond ((package-form-styled-p position)
+                        #+sax-debug (when *rd-style-forms-debug* 
+                                      (debug-out "~%rd position after package style: ~S" position))
+                        (let* ((next (nmark-next position))
+                               (end (sexpr-end next))
+                               (next-start (next-sexpr-start end)))
+                          #+sax-debug (when *rd-style-forms-debug* 
+                                       (debug-out "~%next: ~S" next)
+                                       (debug-out "~%end: ~S" end)
+                                       (debug-out "~%next-start: ~S" next-start))
+                          (setf position next-start))
+                        #+sax-debug (when *rd-style-forms-debug* 
+                                     (debug-out "~%rd position after next-sexpr: ~S" position)))
+                       (t
+                        (nmark-next position)))
+                 (when position (style-elements position form-end))))))
+          (t
+           #+sax-debug (when *rd-style-forms-debug* 
+                        (debug-out "~%No positions in rd positions list -- doing style-elements."))
+           (style-elements (nmark-next start) end)))))
+
+(defMethod style-top-level-form ((text-view gui::hemlock-textstorage-text-view))
+  #+sax-debug (when *style-top-level-form-debug* 
+                (debug-out  (format nil "~%~%~S" 'style-top-level-form)))
+  (setq *style-top-level-form-p* nil)
+  (let* ((hemlock-view (gui::hemlock-view text-view))
+         (*buf* (hemlock-view-buffer hemlock-view))
+         (hi::*current-buffer* *buf*)
+         (*layout* (#/layoutManager (#/textContainer text-view)))
+         (*current-package* (hemlock::buffer-package *buf*))
+         (*style-case-p* (if (null *style-case-p*) nil (writable-p))))
+    (cond ((not (buffer-empty-p))
+           (let* ((start (backward-top-level-list (clone (buffer-point *buf*))))
+                  (end (when start (clone start))))
+             (when (and end (hemlock::form-offset end 1))
+               #+sax-debug (when *style-top-level-form-debug* 
+                             (debug-out  (format nil "~%start: ~S" start))
+                             (debug-out  (format nil "~%end: ~S" end)))
+               (hemlock::parse-over-block (mark-line start) (mark-line end))
+               (set-generic-text-style text-view start end)
+               (rd-style-forms :start start :end end :top-level-p t))))
+          (t
+           (ed-beep)))))
+
+(defMethod style-forms ((hemlock-view hi::hemlock-view) &key (caps-p t) start end toplevel-p)
+  (let* ((text-view (gui::text-pane-text-view (hi::hemlock-view-pane hemlock-view)))
+         (*buf* (hemlock-view-buffer hemlock-view))
+         (hi::*current-buffer* *buf*)
+         (*layout* (#/layoutManager (#/textContainer text-view)))
+         (*current-package* (hemlock::buffer-package *buf*))
+         (*style-case-p* (if (null caps-p) nil *style-case-p*)))
+    (cond ((not (buffer-empty-p))
+           (unless (and start end)
+             (multiple-value-setq (start end)
+               (selection-marks text-view)))
+           (unless (and start end)
+             (setf start (buf-start-mark) end (buf-end-mark)))
+           (hemlock::parse-over-block (mark-line start) (mark-line end))
+           (rd-style-forms :start start :end end :top-level-p toplevel-p))
+          (t
+           (ed-beep)))))
+
+(defMethod style-forms ((window gui::hemlock-frame) &key (caps-p t) start end toplevel-p)
+  (style-forms (gui::hemlock-view window) :start start :end end :caps-p caps-p :toplevel-p toplevel-p))
+
+
+;;; ----------------------------------------------------------------------------
+;;; The batch styling interface:
+;;; ----------------------------------------------------------------------------
+;;;
+(defMethod style-window ((window gui::hemlock-frame))
+  (if (writable-p)
+    (let* ((hemlock-view (gui::hemlock-view window))
+           (text-view (gui::text-pane-text-view (hi::hemlock-view-pane hemlock-view)))
+           (*buf* (hemlock-view-buffer hemlock-view))
+           (hi::*current-buffer* *buf*)
+           (*layout* (#/layoutManager (#/textContainer text-view)))
+           (*current-package* (hemlock::buffer-package *buf*))
+           ;; If a file is not writable, style with color and underlining, but not caps.
+           (*style-case-p* (if (null *style-case-p*) nil (writable-p))))
+      (multiple-value-bind (start end) (selection-marks text-view)
+        (unless (and start end)
+          (setf start (buf-start-mark) end (buf-end-mark)))   
+        (hemlock::parse-over-block (mark-line start) (mark-line end))
+        (set-generic-text-style text-view start end)
+        (style-comments start end)     
+        (style-forms window :start start :end end)))
+    (listener-msg "~%~S is not writable." (window-path window))))
+
+(defun style-folder-recursively ()
+  (let ((dir (gui::cocoa-choose-directory-dialog)))
+    (when dir
+      (cond ((pathnamep dir)
+             (listener-msg "~%~%~a files styled."
+                           (style-folder (directory-namestring dir))))
+            (t
+             (listener-msg "~%~%~a files styled."
+                           (style-folder dir)))))))
+
+(defun style-folder (folder)
+  (let ((files (directory (merge-pathnames folder "*.lisp") :files t :directories nil))
+        (folders (directory (merge-pathnames folder "*") :files nil :directories t))
+        (file-count 0))
+    (dolist (file files)
+      (listener-msg "~%;;; Styling: ~a" file)
+      (incf file-count)
+      (let* ((view (gui::cocoa-edit file))
+             (window (#/window (hi::hemlock-view-pane view)))
+             (buffer (hemlock-view-buffer view))
+             (document (hi::buffer-document buffer)))
+      (cond ((writable-p)
+             (style-window window)
+             (gui::save-hemlock-document document)
+             (#/close window))
+            (t
+             (listener-msg "~%;;; File is read-only: ~S" file)))))
+    (dolist (folder folders)
+      (incf file-count (style-folder folder)))
+    file-count))
+
+(defun vanilla-style (buffer start end)
+  ;; Set the font spec of the text to the default; but leave the capitalization
+  ;; of strings, comments and various constants alone.
+  (let ((buf-start (buf-start-mark buffer))
+        (buf-end (buf-end-mark buffer))
+        skip-list case)
+    (hemlock::parse-over-block (mark-line start) (mark-line end))
+    (set-style-attributes (attribute-dictionary *vanilla-styling*) start end)
+    ;; *** this should use start and end
+    (setf skip-list (get-combined-segment-list))
+    (setf case (style-case *vanilla-styling*))
+    ;; (pprint skip-list)
+    (cond (skip-list
+           (do* ((segment (pop skip-list) (pop skip-list))
+                 (seg-start buf-start next-start)
+                 (seg-end (first segment) (first segment))
+                 (next-start (second segment) (second segment)))
+                ((or (mark>= seg-start end)
+                     (null seg-start)
+                     (null seg-end)))
+             (when (and (mark>= seg-start start)
+                        (mark<= seg-start end))
+               (cond ((eql case :up)
+                      (upcase-region seg-start (mark-min seg-end end)))
+                     ((eql case :down)
+                      (downcase-region seg-start (mark-min seg-end end)))))))
+          (t 
+           (cond ((eql case :up)
+                  (upcase-region buf-start buf-end))
+                 ((eql case :down)
+                  (downcase-region buf-start buf-end)))))))
+
+(defMethod style-vanilla ((window gui::hemlock-frame))
+  (let* ((hemlock-view (gui::hemlock-view window))
+         (text-view (gui::text-pane-text-view (hi::hemlock-view-pane hemlock-view)))
+         (*layout* (#/layoutManager (#/textContainer text-view)))
+         (*buf* (hemlock-view-buffer hemlock-view))
+         (hi::*current-buffer* *buf*))
+    (cond ((writable-p)
+           (multiple-value-bind (start end) (selection-marks text-view)
+             (unless (and start end)
+               (setf start (buf-start-mark) end (buf-end-mark)))
+             (vanilla-style *buf* start end)))
+          (t
+           (listener-msg "~%;;; File is read-only: ~S" (window-path window))))))
+
+;;; ----------------------------------------------------------------------------
+;;; The interface for the incremental algorithm:
+;;; ----------------------------------------------------------------------------
+;;;
+(defConstant %inserted-parens% 37)
+
+(defun dynamically-style-buffer (hemlock-view)
+  (let* ((*inc-p* t)
+         (*buf* (hemlock-view-buffer hemlock-view))
+         (*form-style* nil)
+         (*form-start* nil)
+         (*form-end* nil)
+         (*superparen-closure* nil)
+         (*segment-array* nil)
+         (hi::*current-buffer* *buf*)
+         (text-view (gui::text-pane-text-view (hi::hemlock-view-pane hemlock-view)))
+         (*layout* (#/layoutManager (#/textContainer text-view)))
+         (*inc-pos* (clone (buffer-point *buf*)))
+         (comment-end (or (buffer-top-level-sexpr-end *buf*) (buf-end-mark)))
+         (atom-start (atom-start (mark-prev *inc-pos*))) ; *** ?
+         (atom-end (or (atom-end *inc-pos*) *inc-pos*))
+         (char (mark-char (mark-max (buf-start-mark) (or (mark-prev *inc-pos*) *inc-pos*))))
+         (*style-case-p* (if (null *style-case-p*) nil (writable-p)))
+         style-end)
+    (when char
+      #+sax-debug (when *dynamically-style-buffer-debug* 
+                     (debug-out "~%~%~S" 'dynamically-style-buffer)
+                     (debug-out "~%*inc-pos*: ~S" *inc-pos*)
+                     (debug-out "~%char: ~S" char)
+                     (debug-out "~%atom-start: ~s" atom-start)
+                     (debug-out "~%atom-end: ~s" atom-end))
+      (cond ((and (char= char #\#)
+                  (char= (mark-char (mark-max (buf-start-mark) (mark-offset *inc-pos* -2))) #\|))
+             ;; *** could do better than buf-start-mark
+             (style-comments (buf-start-mark) comment-end))
+            (t
+             (multiple-value-bind (start inside-quotes-p semi-colon-pos)
+                                  (calculate-context char)
+               #+sax-debug (when *dynamically-style-buffer-debug* 
+                              (debug-out "~%~%start: ~S" start)
+                              (debug-out "~%inside-quotes-p: ~S" inside-quotes-p)
+                              (debug-out "~%semi-colon-pos: ~S" semi-colon-pos))
+               (unless start (setq start (buf-start-mark)))
+               (dynamically-style-comments start comment-end t t)
+               (when (or inside-quotes-p
+                         (and (char= char #\") (not inside-quotes-p)))
+                 #+sax-debug (when *dynamically-style-buffer-debug* 
+                                (debug-out "~%start: ~S" start)
+                                (debug-out "~%comment-end: ~S" comment-end))
+                 (return-from dynamically-style-buffer (values atom-start atom-end)))
+               (cond (semi-colon-pos
+                      (let ((line-end (line-end (clone semi-colon-pos))))
+                        (when line-end
+                          ;; eliminate paren highlighting:
+                          (let* ((begin (mark-absolute-position start))
+                                 (count (- (mark-absolute-position line-end) begin)))
+                            (when (and begin count)
+                              (ns:with-ns-range  (char-range begin count)
+                                (let* ((layout (#/layoutManager text-view)))
+                                  (#/removeTemporaryAttribute:forCharacterRange: 
+                                   layout #&NSBackgroundColorAttributeName 
+                                   char-range)))))
+                          (set-style-attributes (attribute-dictionary *semi-colon-comment-style*) 
+                                                semi-colon-pos line-end))))
+                     (t
+                      (unwind-protect
+                          (progn
+                            (#/beginEditing (#/textStorage text-view))
+                            (insert-string (copy-mark atom-end) " o ))))))))))))))))))))))))))))))))))")
+                            (setf style-end (mark-offset (copy-mark atom-end) %inserted-parens%))
+                            (hemlock::parse-over-block (hi::mark-line start) (hi::mark-line style-end))
+                            (rd-style-forms :start start :end style-end)
+                            (unless (or *form-style* *paste-p* (member char '(#\( #\) #\" #\space #\;)))
+                              (when atom-start
+                                (setq *form-style* *generic-text-style*
+                                      *form-start* atom-start
+                                      *form-end* atom-end))))
+                        (delete-characters atom-end %inserted-parens%)
+                        (#/endEditing (#/textStorage text-view))
+                        (when *form-style*
+                          (set-style-attributes (attribute-dictionary *form-style*) *form-start* *form-end*))
+                        (when *superparen-closure* 
+                          (funcall *superparen-closure*))
+                        ;; Setting attributes for a region leaves point at the end 
+                        ;; of the symbol.  Move it back, unless editing there:
+                        (let ((point (buffer-point *buf*)))
+                          (when (not (mark= point *inc-pos*))
+                            (let ((offset (- (mark-charpos point) (mark-charpos *inc-pos*))))
+                              (dotimes (count offset)
+                                ;; a less moronic way to do this??
+                                (hi::handle-hemlock-event hemlock-view %backward-char-event%)))))))))))
+      (values atom-start atom-end))))
+
+(defun calculate-context (new-char)
+  "Calculate top-level-start-pos inside-quotes-p semi-colon-pos"
+  #+sax-debug (when *calculate-context-debug* 
+                 (debug-out "~%~%~S" 'calculate-context)
+                 (debug-out "~%new-char: ~S" new-char)
+                 (debug-out "~%*inc-pos*: ~S" *inc-pos*)
+                 (debug-out "~%point: ~S" (buffer-point *buf*))
+                 (debug-out "~%(mark-char point): ~S" (mark-char (buffer-point *buf*))))
+  (let* ((point (clone (buffer-point *buf*)))
+         (right-quote-pos (when (char= new-char #\") (clone point)))
+         top-level-start-pos inside-quotes-p semi-colon-pos left-quote-pos)
+    (flet ((return-even-quote-values ()
+             (when (and right-quote-pos left-quote-pos semi-colon-pos)
+               ;; mark< is not trinary
+               (when (and (mark< left-quote-pos semi-colon-pos)
+                          (mark< semi-colon-pos right-quote-pos))
+                 (setq semi-colon-pos nil)))
+             (return-from calculate-context
+                          (values top-level-start-pos inside-quotes-p semi-colon-pos)))
+           (return-odd-quote-values ()
+             (when (and semi-colon-pos left-quote-pos)
+               (cond ((mark< left-quote-pos semi-colon-pos)
+                      (setq semi-colon-pos nil))
+                     (t
+                      (setq inside-quotes-p nil))))
+             (return-from calculate-context
+                          (values top-level-start-pos inside-quotes-p semi-colon-pos))))
+      (do* ((buf-start (buf-start-mark))
+            (pos (or (mark-prev *inc-pos*) buf-start))
+            (char (mark-char pos) (mark-char pos))
+            (char-1 (mark-char (mark-max (or (mark-prev pos) pos) buf-start))
+                    (mark-char (mark-max (or (mark-prev pos) pos) buf-start)))
+            (first-char-p t nil)
+            (quote-count 0)
+            line-start-p)
+           ((and char char-1 (char= char #\() (or (char-eolp char-1) (mark= pos buf-start)))
+            (setq top-level-start-pos pos)
+            #+sax-debug (when *calculate-context-debug* 
+                           (debug-out "~%quote-count: ~S" quote-count))
+            (cond ((= (mod quote-count 2) 0) ; even quotes
+                   (setf inside-quotes-p nil)
+                   (return-even-quote-values))
+                  (t
+                   (setf inside-quotes-p t)
+                   (return-odd-quote-values))))
+        (cond ((null char)
+               (setq semi-colon-pos nil))
+              ((and (char-eolp char) (not first-char-p))
+               (setq line-start-p t))
+              ((and (char= char #\;) (not line-start-p) (not (char= char-1 #\\)))
+               (setq semi-colon-pos pos))
+              ((and (char= char #\") (not (char= char-1 #\\)))
+               (incf quote-count)
+               (unless right-quote-pos (setq right-quote-pos pos))
+               (setq left-quote-pos pos)))
+        (setq pos (mark-prev pos))
+        (when (null pos)
+          (setq top-level-start-pos nil)
+          (cond ((= (mod quote-count 2) 0) 
+                 (setq inside-quotes-p nil)
+                 #+sax-debug (when *calculate-context-debug* 
+                                (debug-out "~%inside-quotes-p is nil"))
+                 (return-even-quote-values))
+                (t
+                 (setq inside-quotes-p t)
+                 #+sax-debug (when *calculate-context-debug* 
+                                (debug-out "~%inside-quotes-p: t"))
+                 (return-odd-quote-values))))))))
+
+;;; *** This need work:
+(defun char-printable-p (char event)
+  "Is the char printable?"
+  (let ((code (char-code char)))
+    #+sax-debug (when *char-printable-p-debug* 
+                 (debug-out "~%~%~S" 'char-printable-p)
+                 (debug-out "~%char: ~s" char)
+                 ;; (hi::print-pretty-key-event (hi::char-key-event char) t t)
+                 (debug-out "~%code: ~s" code))
+    (let ((control-key-p (hi::key-event-bit-p event "Control"))
+          (option-key-p (hi::key-event-bit-p event "Meta")))
+      #+sax-debug
+      (when *automated-testing-p*
+        (setq control-key-p nil
+              option-key-p nil))
+      #+sax-debug (when *char-printable-p-debug* (debug-out "~%control-key-p: ~s" control-key-p))
+      #+sax-debug (when *char-printable-p-debug* (debug-out "~%option-key-p: ~s" option-key-p))
+      (cond ((not (or control-key-p option-key-p))
+             (when (or (and (>= code 32) (<= code 127)) ; this is the primary case
+                       ;; *** define constants
+                       (= code 13) ; #\newline
+                       (= code 8)  ; #\delete, #\backspace
+                       ; #\tab, to accommodate anticipatory-symbol-complete
+                       (= code 9)
+                       (= code 10) ; $\linefeed
+                       (= code 127)) ; #\del
+               #+sax-debug (when *char-printable-p-debug* (debug-out "~%printable1"))
+               t))
+            #+elvis
+            ((and control-key-p option-key-p) 
+             #+sax-debug (when *char-printable-p-debug* (debug-out "~%printable2"))
+             (when (or (= code 8)) ; control-meta-h & control-meta-delete ****
+               t))
+            (control-key-p
+             (when (or (= code 100) ; control-d
+                       ;; (= code 4) ; *** ?
+                       (= code 11) ; control-k
+                       (= code 23)) ; control-w
+               #+sax-debug (when *char-printable-p-debug* (debug-out "~%printable3"))
+               t))
+            (option-key-p
+             (when (or (= code 182) ; meta-d
+                       (= code 202) ; meta-space ?? ***
+                       (= code 199)) ; meta-\ ?? ***
+               #+sax-debug (when *char-printable-p-debug* (debug-out "~%printable4"))
+               t))
+            (t nil)))))
+
+(defun restyle-comment (view)
+  #+sax-debug (when *handle-hemlock-event-debug* (debug-out "~%restyle-comment-p"))
+  (let* ((line-start (buffer-line-start *buf*))
+         (line-end (buffer-line-end *buf*))
+         (hi::*current-buffer* *buf*)
+         (*current-package* (hemlock::buffer-package *buf*))
+         (text-view (gui::text-pane-text-view (hi::hemlock-view-pane view)))
+         (*layout* (#/layoutManager (#/textContainer text-view))))
+    (when (and line-start line-end)
+      (style-region *generic-text-style* line-start line-end nil)
+      (style-comments line-start line-end)
+      (style-forms view :start line-start :end line-end))))
+
+;;; *** redefinition ***
+(defMethod hi::handle-hemlock-event :around ((view hi:hemlock-view) event)
+  (let* ((*buf* (hemlock-view-buffer view))
+         (hi::*current-buffer* *buf*)
+         (*inc-pos* nil)
+         (*paste-p* nil)
+         (*paste-start* nil)
+         (*paste-end* nil)
+         (keysym (when (typep event 'hi::key-event)
+                   (hi::key-event-keysym event)))
+         (keysym-code (when keysym (hi::code-for-keysym keysym))))
+    (cond ((and keysym *styling-p* (not (keywordp  keysym)) ; char can be :end, :home, etc
+                (not (hi::buffer-minor-mode *buf* "I-Search")))
+           (let ((char (code-char keysym-code)))
+           #+sax-debug (when *handle-hemlock-event-debug* 
+                        (debug-out "~%~%~S" 'handle-hemlock-event)
+                        (debug-out "~%char: ~S" char))
+             (when (key-event= event %control-y%)
+               #+sax-debug (when *handle-hemlock-event-debug* 
+                            (debug-out "~%*paste-start*: ~S" (clone (buffer-point *buf*))))
+               (setq *paste-p* t)
+               (setq *paste-start* (clone (buffer-point *buf*))))
+             (when (key-event= event %control-j%)
+               (setq *style-top-level-form-p* t))
+             (if (and char (not (typep (#/window (hi::hemlock-view-pane view)) 'gui::hemlock-listener-frame))
+                      (char-printable-p char event) (lisp-file-p))
+               (let* ((point (buffer-point *buf*))
+                      (point-char (mark-char point))
+                      (char-1 (mark-char (mark-max (or (mark-prev point) point) (buffer-start-mark *buf*))))
+                      (*style-screen-p* nil)
+                      ;; If a file is not writable, style with color and underlining, but not caps.
+                      (*style-case-p* (if (null *style-case-p*) nil (writable-p)))
+                      restyle-comment-p)
+                 #+sax-debug (when *handle-hemlock-event-debug* 
+                              (debug-out "~%point: ~S" point)
+                              (debug-out "~%point-char: ~S" point-char)
+                              (debug-out "~%char-1: ~S" char-1))
+                 (cond ((and (key-event= event %backspace%) ; backspace & delete
+                             char-1
+                             (char= char-1 #\;))
+                        (setf restyle-comment-p t))
+                       ((and point-char (char= point-char #\;)
+                             ;; (or (key-event= event %del%) ; #\del
+                             (key-event= event %control-d%)) ; control-d                             
+                        (setf restyle-comment-p t)))
+
+                 ;; insert the char:
+                 #+sax-debug (when *handle-hemlock-event-debug* 
+                                (debug-out "~%~%inserting char: ~S" char))
+                 (ccl::with-autorelease-pool
+                     (call-next-method view event))
+                 #+sax-debug (when *handle-hemlock-event-debug* 
+                                (debug-out "~%~%char inserted"))
+
+                 (cond (restyle-comment-p
+                        (restyle-comment view))
+                       (t 
+                        (dynamically-style-buffer view))))
+               (ccl::with-autorelease-pool
+                 #+sax-debug (when *handle-hemlock-event-debug* 
+                              (debug-out "~%~%not styled -- calling next method."))
+                 (call-next-method view event)
+                 (cond ((key-event= event %control-y%)
+                        #+sax-debug (when *handle-hemlock-event-debug* 
+                                      (debug-out "~%setting *paste-end*: ~S" (clone (buffer-point *buf*))))
+                        (setq *paste-end* (clone (buffer-point *buf*)))))))))
+                       ; (yank-after view *paste-start* *paste-end*)))))))
+                       ; ((key-event= event %control-meta-q%)
+                        ; (indentation-after view)))))))
+          (t
+           (ccl::with-autorelease-pool
+               (call-next-method view event))))))
+
+;;; Neither of these two are right.  See the note below.
+(objc:defMethod (#/paste: :void) ((text-view gui::hemlock-text-view) (sender :id))
+  (reset-text-view)
+  (call-next-method sender))
+  
+(defMethod yank-after ((view  hi::hemlock-view) generic-start generic-end)
+  (let ((text-view (gui::text-pane-text-view (hi::hemlock-view-pane view))))
+    (hi::handle-hemlock-event view #'(lambda () (style-screen text-view generic-start generic-end)))))
+
+#|
+;;; This is the right way to do paste and yank, but the text
+;;; is being set back to plain by some disagreeable and as yet
+;;; unidentified function. (Cocoa??)
+(defMethod yank-after ((view  hi::hemlock-view) generic-start generic-end)
+  (when (and *styling-p* (lisp-file-p)
+             (not (typep (#/window (hi::hemlock-view-pane view)) 'gui::hemlock-listener-frame)))
+    (let* ((text-view (gui::text-pane-text-view (hi::hemlock-view-pane view)))
+           (*buf* (hi::hemlock-view-buffer view))
+           (hi::*current-buffer* *buf*)
+           (*layout* (#/layoutManager (#/textContainer text-view)))
+           (*current-package* (hemlock::buffer-package *buf*))
+           (start (buffer-top-level-sexpr-start *buf*))
+           (end (buffer-point *buf*))
+           (*style-screen-p* nil)
+           ;; If a file is not writable, style with color and underlining, but not caps.
+           (*style-case-p* (if (null *style-case-p*) nil (writable-p))))
+      #+sax-debug (when *yank-after-debug* 
+                    (debug-out "~%~%~S" 'yank-or-paste-after)
+                    (debug-out "~%start: ~S" start)
+                    (debug-out "~%end: ~S" end)
+                    (debug-out "~%*inc-pos*: ~S" *inc-pos*))
+      ;; *paste-p*, *paste-start* and *paste-end* are set above.
+      (when (and start end)
+        (hemlock::parse-over-block (hemlock-internals::mark-line start) 
+                                   (hemlock-internals::mark-line end))
+        (set-generic-text-style text-view generic-start generic-end) 
+        (dynamically-style-comments start end t t)
+        (dynamically-style-buffer view))
+      (setq *paste-p* nil *paste-start* nil *paste-end* nil))))
+      ;; (gui::update-paren-highlight text-view))))
+|#
+
+;;; ----------------------------------------------------------------------------
+;;; styling menu items
+;;; ----------------------------------------------------------------------------
+;;;
+(defParameter *edit-menu* 
+  (#/submenu (#/itemWithTitle: (#/mainMenu (ccl::application-ui-object ccl::*application*)) #@"Edit")))
+
+(objc:defMethod (#/toggleStylingAction: :void) ((item ns:ns-menu-item) (sender :id))
+  (cond (*styling-p* 
+         (setq *styling-p* nil)
+         (#/setState: sender #$NSOffState))
+        (t
+         (setq *styling-p* t)
+         (#/setState: sender #$NSOnState))))
+
+(let ((styling-item (#/itemWithTitle: *edit-menu* #@"Styling"))
+      item)
+  (unless (%null-ptr-p styling-item) (#/removeItem: *edit-menu* styling-item))
+  (when (%null-ptr-p styling-item)
+    (#/addItem: *edit-menu* (#/separatorItem ns:ns-menu-item))
+    (setf item (#/initWithTitle:action:keyEquivalent: (#/alloc ns:ns-menu-item)
+                                                      #@"Syntax Styling"
+                                                      (ccl::@selector "toggleStylingAction:")
+                                                      #@""))
+    (#/setTarget: item item)
+    (#/setState: item #$NSOnState)
+    (#/addItem: *edit-menu* item)))
+
+
+
+(when *style-case-p*
+
+(defParameter *style-file-item* nil)
+(defParameter *style-file-vanilla-item* nil)
+
+(defClass STYLING-MENU-ITEM (ns:ns-menu-item)
+  ()
+  (:metaclass ns:+ns-object))
+
+(objc:defMethod (#/styleFileAction: :void) ((item styling-menu-item) (sender :id))
+  (declare (ignore sender))
+  (let ((window (active-hemlock-window)))
+    (when window
+      (style-window window))))
+
+(objc:defMethod (#/styleFileVanillaAction: :void) ((item styling-menu-item) (sender :id))
+  (declare (ignore sender))
+  (let ((window (active-hemlock-window)))
+    (when window
+      (style-vanilla window)))) 
+
+(objc:defMethod (#/styleFolderAction: :void) ((item styling-menu-item) (sender :id))
+  (declare (ignore sender))
+  (style-folder-recursively))
+
+(objc:defMethod (#/validateMenuItem: :<BOOL>) ((item styling-menu-item) item)
+  *styling-p*)
+
+(let ((style-file-item (#/itemWithTitle: *edit-menu* #@"Style File"))
+      item)
+  (when (%null-ptr-p style-file-item)
+    (setf item (#/initWithTitle:action:keyEquivalent: (#/alloc styling-menu-item)
+                                                      #@"Style File"
+                                                      (ccl::@selector "styleFileAction:")
+                                                      #@"u"))
+    (#/setTarget: item item)
+    (setq *style-file-item* item)
+    (#/addItem: *edit-menu* item)))
+
+(let ((style-file-vanilla-item (#/itemWithTitle: *edit-menu* #@"Style File Vanilla"))
+      item)
+  (when (%null-ptr-p style-file-vanilla-item)
+    (setf item (#/initWithTitle:action:keyEquivalent: (#/alloc styling-menu-item)
+                                                      #@"Style File Vanilla"
+                                                      (ccl::@selector "styleFileVanillaAction:")
+                                                      #@"U"))
+    (#/setTarget: item item)
+    (setq *style-file-vanilla-item* item)
+    (#/addItem: *edit-menu* item)))
+
+(let ((style-folder-item (#/itemWithTitle: *edit-menu* #@"Style Folder ..."))
+      item)
+  (when (%null-ptr-p style-folder-item)
+    (setf item (#/initWithTitle:action:keyEquivalent: (#/alloc styling-menu-item)
+                                                      #@"Style Folder ..."
+                                                      (ccl::@selector "styleFolderAction:")
+                                                      #@""))
+    (#/setTarget: item item)
+    (#/addItem: *edit-menu* item)))
+
+) ; closing paren for when
+
+
+
Index: /trunk/contrib/foy/syntax-styling/syntax-styling-2.lisp
===================================================================
--- /trunk/contrib/foy/syntax-styling/syntax-styling-2.lisp	(revision 13946)
+++ /trunk/contrib/foy/syntax-styling/syntax-styling-2.lisp	(revision 13946)
@@ -0,0 +1,757 @@
+;;;-*- Mode: Lisp; Package: (SYNTAX-STYLING (CL CCL HEMLOCK-INTERNALS)) -*-
+
+;;; ****************************************************************************
+;;; 
+;;;      syntax-styling-2.lisp
+;;;      
+;;;      copyright (c) 2009 Glen Foy
+;;;      (Permission is granted to Clozure Associates to distribute this file.)
+;;;
+;;;      Macros and styling functions.
+;;;      
+;;;      This software is offered "as is", without warranty of any kind.
+;;;
+;;;      Mod History, most recent first:
+;;;      10/18/9   First cut.
+;;;
+;;; ****************************************************************************
+
+(in-package "SAX")
+
+;;; ----------------------------------------------------------------------------
+;;; Macros used to construct the styling functions below.
+;;; ----------------------------------------------------------------------------
+;;; 
+;;; NOTE: Not bothering to gensym these macros.  They are only used in this file,
+;;; and the only variable capture is the intensional variable capture of POS.
+;;;
+(defMacro sparen (style debug-flag name)
+  (declare (ignorable debug-flag name))
+  `(when pos 
+     #+sax-debug (when (and debug-function-p ,debug-flag) 
+                   (debug-out "~%~%~S" ,name)
+                   (debug-out "~%pos: ~S" pos))
+     (let ((end (mark-next pos)))
+       #+sax-debug (when (and debug-function-p ,debug-flag) 
+                     (debug-out "~%end: ~S" end))
+       (when end 
+         (if *inc-p*             
+           (when (mark< pos *inc-pos*)
+             (let* ((macro-start (next-sexpr-start end))
+                    (macro-end (sexpr-end macro-start)))
+               (when (or (mark= end *inc-pos*) 
+                         (and macro-end macro-start (alpha-char-p (mark-char macro-start))
+                              (mark= *inc-pos* macro-end) (mark= macro-start end)))
+                 #+sax-debug (when (and debug-function-p ,debug-flag) 
+                               (debug-out "~%*inc-pos*: ~S" *inc-pos*)
+                               (debug-out "~%macro-end: ~S" macro-end))
+                 (let ((start (clone pos)))
+                   (setq *superparen-closure*
+                         #'(lambda () 
+                             #+sax-debug (when (and debug-function-p ,debug-flag)
+                                           (debug-out "~%~%closure being called."))
+                             (set-style-attributes (attribute-dictionary ,style)
+                                                   start end)))))))
+           (style-region ,style pos end nil))
+         (setq pos (nnext-sexpr-start end))))))
+
+(defMacro superparen ()
+  "Super parens surround top-level forms and embedded function definitions."
+  `(sparen *superparen-style* *superparen-debug* 'superparen))
+
+(defMacro eval-when-superparen ()
+  "Eval-when deserves a distinctive style for its parens."
+  `(sparen *eval-when-superparen-style* *eval-when-superparen-debug* 'eval-when-superparen))
+
+(defMacro loop-superparen ()
+  "Loop deserves a distinctive style for its parens."
+  `(sparen *loop-superparen-style* *loop-superparen-debug* 'loop-superparen))
+
+(defMacro paren ()
+  "This does no styling; it just increments POS."
+  `(when pos #+sax-debug (when (and debug-function-p *paren-debug*) 
+                          (debug-out "~%~%~S" 'paren))
+     (setq pos (nnext-sexpr-start (mark-next pos)))))
+
+(defMacro optional-paren ()
+  "This does no styling; it just increments POS, if there is a paren."
+  `(when pos #+sax-debug (when (and debug-function-p *optional-paren-debug*)
+                          (debug-out "~%~%~S" 'optional-paren))
+     (let ((pos-char (mark-char pos)))
+       (when (or (char= pos-char #\()
+                 (char= pos-char #\)))
+         (setq pos (nnext-sexpr-start (mark-next pos)))))))
+
+(defMacro objc-symbl (pos)
+  "Style an objc symbol, or list containing symbol and return value."
+  `(setq ,pos (objc-symbol-styling-function ,pos)))
+
+(defMacro symbl ()
+  "Style a symbol-name, taking into account exported symbols."
+  `(when pos #+sax-debug (when (and debug-function-p *symbol-debug*)
+                          (debug-out "~%~%~S" 'symbl)
+                           (debug-out "~%symbol-style: ~S" symbol-style))
+     (let ((pos-end (sexpr-end pos)))
+       (when pos-end 
+         #+sax-debug (when (and debug-function-p *symbol-debug*)
+                      (debug-out "~%pos-end: ~S" pos-end))
+         (let ((name (string-upcase (region-to-string (region pos pos-end)))))
+           (when name
+             (multiple-value-bind (symbol kind)
+                                  (find-symbol name *current-package*)
+               (cond ((and symbol *current-package* (eq kind :external)
+                           (not (eq symbol-style *variable-definition-symbol-style*)))
+                      (cond ((char= (mark-char pos) #\") 
+                             ; a string, don't set caps  
+                             (style-region *exported-symbol-style* pos pos-end nil))
+                            (t
+                             (style-region *exported-symbol-style* pos pos-end))))
+                     (t
+                      (cond ((char= (mark-char pos) #\")
+                             (style-region symbol-style pos pos-end nil))
+                            (t
+                             (style-region symbol-style pos pos-end))))))))
+         (setq pos (next-sexpr-start pos-end))))))
+
+(defMacro struct-sym ()
+  "Style the name of a structure."
+  `(when pos #+sax-debug (when (and debug-function-p *struct-sym-debug*)
+                          (debug-out "~%~%~S" 'struct-sym))
+     (setq pos (next-sexpr-start (struct-sym-styling-function pos)))))
+
+(defMacro struct-fields ()
+  "Style structure fields."
+  `(when pos #+sax-debug (when (and debug-function-p *struct-fields-debug*)
+                          (debug-out "~%~%~S" 'struct-fields))
+     (do* ((field-start pos (next-sexpr-start field-end))
+           (field-end (when field-start (sexpr-end field-start))
+                      (when field-start (sexpr-end field-start))))
+          ((or (null field-start) (mark> field-start form-end)))
+       (cond ((char= (mark-char field-start) #\()
+              (let* ((symbol-start (mark-next field-start))
+                     (symbol-end (when symbol-start (sexpr-end symbol-start)))
+                     (next-start (when symbol-end (next-sexpr-start symbol-end))))
+                (style-region *defstruct-field-style* symbol-start symbol-end)
+                (when next-start (rd-style-forms :start next-start :end field-end))))
+             (t
+              (style-region *defstruct-field-style* field-start field-end))))
+     (setq pos (mark-prev form-end))))
+
+(defMacro ancestor ()
+  "Style a structure's ancestor."
+  `(when pos #+sax-debug (when (and debug-function-p *ancestor-debug*)
+                          (debug-out "~%~%~S" 'ancestor))
+     (let* ((start (next-sexpr-start (mark-next pos)))
+            (end (when start (sexpr-end start)))
+            (string (when (and start end) (region-to-string (region start end))))
+            ancestor-start)
+       (when (and string (string-equal string ":include"))
+         (style-region *keyword-package-style* start end)
+         (when (setq ancestor-start (next-sexpr-start end))
+           (style-region *defstruct-ancestor-style* ancestor-start
+                         (sexpr-end ancestor-start)))
+         (setq pos (next-sexpr-start (sexpr-end pos)))))))
+
+(defMacro macro ()
+  "Style the name of the macro."
+  `(when pos #+sax-debug (when (and debug-function-p *macro-debug*)
+                          (debug-out "~%~%~S" 'macro))
+     (let ((pos-end (sexpr-end pos)))
+       #+sax-debug (when (and debug-function-p *macro-debug*)
+                    (debug-out "~%pos-end: ~S" pos-end))
+       (when pos-end
+         (style-region macro-style pos pos-end)
+         (setq pos (next-sexpr-start pos-end))))))
+
+(defMacro derivation-list ()
+  "Style the DEFCLASS derivation list."
+  `(when pos #+sax-debug (when (and debug-function-p *derivation-list-debug*)
+                          (debug-out "~%~%~S" 'derivation-list))
+     (let* ((pos-char (mark-char pos))
+            (pos-next (mark-next pos))
+            (pos-end (sexpr-end pos))
+            (end-prev (when pos-end (mark-prev pos-end))))
+       (when (and pos-next end-prev pos-char (char= pos-char #\())
+         #+sax-debug (when (and debug-function-p *derivation-list-debug*)
+                      (debug-out "~%pos-next: ~S" pos-next)
+                      (debug-out "~%end-prev: ~S" end-prev))
+         (style-region *defclass-derivation-style* pos-next end-prev))
+     (setq pos (next-sexpr-start pos-end)))))
+
+(defMacro slot-list ()
+  "Style DEFCLASS slots."
+  `(when pos #+sax-debug (when (and debug-function-p *derivation-list-debug*)
+                          (debug-out "~%~%~S" 'slot-list))
+     (let (slot-positions
+           (pos-end (sexpr-end pos)))
+       (do ((current-start (sexpr-start (mark-prev pos-end))
+                           (sexpr-start (mark-prev current-start))))
+           ((mark<= current-start pos))
+         (when (or (not *inc-p*)
+                   (and *inc-p*
+                        (mark>= *inc-pos* current-start)
+                        (mark<= *inc-pos* (sexpr-end current-start))))
+           (push current-start slot-positions)))
+       (dolist (slot-position slot-positions)
+         (rd-style-forms :start slot-position :end (sexpr-end slot-position))
+         (style-region *defclass-slot-style* (mark-next slot-position)
+                       (sexpr-end (mark-next slot-position))))
+       (setq pos (next-sexpr-start pos-end)))))
+
+(defMacro qualifier ()
+  "Style method qualifiers."
+  `(when pos #+sax-debug (when (and debug-function-p *qualifier-debug*)
+                          (debug-out "~%~%~S" 'qualifier))
+     (let ((pos-end (sexpr-end pos)))
+       (when (char= (mark-char pos) #\:)
+         (style-region *keyword-package-style* pos pos-end)
+         (setq pos (next-sexpr-start pos-end))))))
+
+(defun list-regions (start end  &aux e1-start e1-end e2-start e2-end)
+  "List parameter and specializer or optional parameter and defaults."
+  (declare (ignorable end))
+  #+sax-debug (when (and debug-function-p *list-regions-debug*)
+                (debug-out "~%~%~S" 'list-regions)
+                (debug-out "~%start: ~S" start)
+                (debug-out "~%end: ~S" end))
+  (setq e1-end (sexpr-end (mark-next start))
+        e1-start (sexpr-start e1-end))
+  (setq e2-start (next-sexpr-start (mark-next e1-end))
+        e2-end (sexpr-end e2-start))
+  (list e1-start e1-end e2-start e2-end))
+
+(defun parameter-regions (list-start)
+  "Collect specialized and non-specialized parameter regions. Style the defaults for
+  lambda-list-keyword parameters."
+  #+sax-debug (when (and debug-function-p *parameter-regions-debug*)
+                (debug-out "~%~%~S" 'parameter-regions))
+  (let ((list-end (sexpr-end list-start))
+        results option-p)
+    (do* ((start (next-sexpr-start (mark-next list-start)) 
+                 (when (sexpr-end start) (next-sexpr-start (sexpr-end start))))
+          (char (when start (mark-char start)) (when start (mark-char start))))
+         ((or (null start) (mark>= start list-end)) results)
+      #+sax-debug (when (and debug-function-p *parameter-regions-debug*)
+                    (debug-out "~%start: ~S" start))
+      (cond ((char= char #\()
+             (let ((specializer-regions (list-regions start (sexpr-end start))))
+               #+sax-debug (when (and debug-function-p *parameter-regions-debug*)
+                             (debug-out "~%specializer-regions: ~S" specializer-regions))
+               (when (and option-p (third specializer-regions) (fourth specializer-regions))
+                 (rd-style-forms :start (third specializer-regions) :end (fourth specializer-regions)))
+               (push (subseq specializer-regions 0 (when option-p 2))
+                     results)))
+            ((char= char #\&) 
+             (style-region *keyword-package-style* start (sexpr-end start))
+             (setq option-p t))
+            (t 
+             (push (list start (sexpr-end start)) results))))))
+
+(defMacro parameter-list ()
+  "Style the parameter list.  This is called by both functions and methods."
+  `(when pos #+sax-debug (when (and debug-function-p *parameter-list-debug*)
+                          (debug-out "~%~%~S" 'parameter-list))
+     (let ((parameter-regions (parameter-regions pos)))
+       #+sax-debug (when (and debug-function-p *parameter-list-debug*)
+                     (debug-out "~%parameter-regions: ~S" parameter-regions))
+       (dolist (arg parameter-regions)
+         (style-region *parameter-style* (first arg) (second arg))
+         (when (and (third arg) (fourth arg))
+           #+sax-debug (when (and debug-function-p *parameter-list-debug*)
+                         (debug-out "~%third: ~S" (third arg))
+                         (debug-out "~%fourth: ~S" (fourth arg))
+                         (debug-out "~%*specializer-style*: ~S" *specializer-style*))
+           (style-region *specializer-style* (third arg) (fourth arg))))
+       (setq pos (next-sexpr-start (sexpr-end pos))))))
+
+(defMacro embedded-function-definitions ()
+  "Style the functions defined by LABELS and FLET."
+  `(when pos #+sax-debug (when (and debug-function-p *embedded-function-definitions-debug*)
+                          (debug-out "~%~%~S" 'embedded-function-definitions))
+     (let ((pos-end (sexpr-end pos)))
+       (do ((position (next-sexpr-start (mark-next pos))
+                      (next-sexpr-start (nmark-next (sexpr-end position)))))
+           ((or (null position) (mark>= position pos-end)))
+         (embedded-function-styling-function (clone position)))
+       (setq pos (next-sexpr-start pos-end)))))
+
+(defMacro variable-definitions ()
+  "Style the variables and default values defined by LET, DO*, etc."
+  `(when pos #+sax-debug (when (and debug-function-p *variable-definitions-debug*)
+                          (debug-out "~%~%~S" 'variable-definitions)
+                          (debug-out "~%pos: ~S" pos))
+     (let ((pos-end (sexpr-end pos)))
+       (do ((position (next-sexpr-start (mark-next pos))
+                      (next-sexpr-start (nmark-next (sexpr-end position)))))
+           ((or (null position) (mark>= position pos-end)))
+         #+sax-debug (when (and debug-function-p *variable-definitions-debug*)
+                      (debug-out "~%variable-definition position: ~S" position))
+         (variable-definition-styling-function (clone position)))
+       (setq pos (next-sexpr-start pos-end)))))
+
+(defMacro case-match-forms ()
+  "Style the match forms of a case statement"
+  `(when pos #+sax-debug (when (and debug-function-p *case-match-forms-debug*)
+                          (debug-out "~%~%~S" 'case-match-forms))
+     (let ((end (mark-prev form-end)))
+       (do ((position (next-sexpr-start pos)
+                      (next-sexpr-start (nmark-next (sexpr-end position)))))
+           ((or (null position) (mark>= position end)))
+         (case-match-styling-function position))
+       (setq pos (next-sexpr-start end)))))
+
+(defMacro loop-test ()
+  "Style the test form used by an iteration macro."
+  `(when pos #+sax-debug (when (and debug-function-p *loop-test-debug*)
+                          (debug-out "~%~%~S" 'loop-test))
+     (let ((pos-end (sexpr-end pos)))
+       (rd-style-forms :start pos :end pos-end)
+       (setq pos (next-sexpr-start pos-end)))))
+
+(defMacro variable-form ()
+  "Style the initialization form of a variable definition."
+  `(when pos #+sax-debug (when (and debug-function-p *variable-form-debug*)
+                          (debug-out "~%~%~S" 'variable-form))
+     (let ((pos-end (sexpr-end pos)))
+       (variable-definition-styling-function pos)
+       (setq pos (next-sexpr-start pos-end)))))
+
+(defMacro variable-list ()
+  "Style the variable list of multiple-value-setq, multiple-value-bind, etc."
+  `(when pos #+sax-debug (when (and debug-function-p *variable-list-debug*)
+                          (debug-out "~%~%~S" 'variable-list))
+     (let ((pos-end (sexpr-end pos)))
+       (do* ((var-start (next-sexpr-start (mark-next pos)) 
+                        (next-sexpr-start (nmark-next var-end)))
+             (var-end (when var-start (sexpr-end var-start))
+                      (when var-start (sexpr-end var-start))))
+            ((or (null var-start) (mark> var-start pos-end)))
+         (style-region *variable-definition-symbol-style* var-start var-end nil))
+       (setq pos (next-sexpr-start pos-end)))))
+
+(defMacro body ()
+  "Style the body of a macro."
+  `(when pos #+sax-debug (when (and debug-function-p *body-debug*)
+                          (debug-out "~%~%~S" 'body)
+                           (debug-out "~%pos: ~S" pos)
+                           (debug-out "~%form-end: ~S" form-end))
+     (rd-style-forms :start pos :end (mark-prev form-end))
+     (setq pos (mark-prev form-end))))
+
+(defMacro loop-body ()
+  "Style the body of a loop macro."
+  `(when pos #+sax-debug (when (and debug-function-p *loop-body-debug*)
+                          (debug-out "~%~%~S" 'loop-body))
+     (style-elements pos (mark-prev form-end) t)
+     (setq pos (mark-prev form-end))))
+
+(defMacro form ()
+  "Style a single form."
+  `(when pos #+sax-debug (when (and debug-function-p *form-debug*)
+                          (debug-out "~%~%~S" 'form)
+                          (debug-out "~%pos: ~S" pos))
+     (let ((pos-end (sexpr-end pos)))
+       #+sax-debug (when (and debug-function-p *form-debug*)
+                    (debug-out "~%pos-end: ~S" pos-end))
+       (rd-style-forms :start pos :end pos-end)
+       (setq pos (if (next-sexpr-start pos-end)
+                   (mark-min (or (mark-prev form-end) form-end)
+                             (next-sexpr-start pos-end))
+                   (mark-prev form-end))))))
+
+(defMacro doc ()
+  "Style the doc in DEFUN, DEFMETHOD, DEFMACRO, DEFPARAMETER, etc."
+  `(when pos #+sax-debug (when (and debug-function-p *doc-debug*)
+                          (debug-out "~%~%~S" 'doc))
+     (let ((pos-end (sexpr-end pos)))
+       (cond ((mark< pos form-end)
+              (cond ((char-equal #\" (mark-char pos))
+                     (cond (*inc-p*
+                            (style-region *string-style* 
+                                          pos (mark-min *inc-pos* (or pos-end pos))
+                                          nil))
+                           (t
+                            (style-region *string-style* pos pos-end nil)))
+                     (setq pos (if (next-sexpr-start pos-end)
+                                 (if (mark< (mark-prev form-end) 
+                                            (next-sexpr-start pos-end))
+                                   (mark-prev form-end)
+                                   (next-sexpr-start pos-end))
+                                 (mark-prev form-end))))
+                    (t
+                     pos)))
+             (t 
+              form-end)))))
+
+(defMacro options ()
+  "Style DEFCLASS and DEFGENERIC options."
+  `(when pos #+sax-debug (when (and debug-function-p *options-debug*)
+                          (debug-out "~%~%~S" 'options))
+     (do* ((option-start pos (next-sexpr-start (sexpr-end option-start)))
+           (symbol-start (when option-start (mark-next option-start))
+                         (when option-start (mark-next option-start)))
+           (symbol-end (when symbol-start (sexpr-end symbol-start))
+                       (when symbol-start (sexpr-end symbol-start))))
+          ((or (null symbol-start) (mark>= symbol-start form-end)))
+       (when (char-equal #\: (mark-char symbol-start))
+         (style-region *keyword-package-style* symbol-start symbol-end nil)
+         (cond ((string-equal (region-to-string (region symbol-start symbol-end))
+                              ":documentation")
+                (when (next-sexpr-start symbol-end)
+                  (style-region *string-style* 
+                                (next-sexpr-start symbol-end)
+                                (sexpr-end (next-sexpr-start symbol-end)) nil)))
+               (t 
+                (when (next-sexpr-start (sexpr-end symbol-start))
+                  (style-elements (next-sexpr-start symbol-end) form-end))))))
+     (setq pos (mark-prev form-end))))
+
+
+;;; These are called by the macros above:
+(defun struct-sym-styling-function (pos)
+  (let ((form-end (sexpr-end pos))
+        (symbol-style *defstruct-symbol-style*))
+    (optional-paren) (symbl) (ancestor) (body) (optional-paren) pos))
+
+(defun embedded-function-styling-function (pos)
+  #+sax-debug (when *embedded-function-styling-function-debug*
+                 (debug-out "~%~%~S" 'embedded-function-styling-function))
+  (let ((form-end (sexpr-end pos))
+        (symbol-style *embedded-function-symbol-style*))
+    (superparen) (symbl) (parameter-list) (doc) (body) (superparen) pos))
+
+(defun variable-definition-styling-function (pos)
+  (let ((form-end (sexpr-end pos))
+        (symbol-style *variable-definition-symbol-style*))
+    (optional-paren) (symbl) (body) (optional-paren) pos))
+
+(defun case-match-styling-function (pos)
+  (let ((form-end (sexpr-end pos))
+        (symbol-style *case-match-style*))
+    (paren) (symbl) (body) (paren) pos))
+
+(defun objc-symbol-styling-function (pos)
+  (let ((form-end (sexpr-end pos))
+        (symbol-style *objc-symbol-style*))
+    (optional-paren) (symbl) (body) (optional-paren) pos))
+
+
+;;; The defstyle styles:
+(defun defpackage-styling-function (pos)
+  (let ((form-end (sexpr-end pos))
+        (symbol-style *defpackage-symbol-style*)
+        (macro-style *generic-macro-style*))
+    (superparen) (macro) (symbl) (body) (superparen)))
+
+(add-style "defpackage" #'defpackage-styling-function)
+
+(defun defparameter-styling-function (pos)
+  (let ((form-end (sexpr-end pos))
+        (symbol-style *defparameter-symbol-style*)
+        (macro-style *generic-macro-style*))
+    (superparen) (macro) (symbl) (form) (doc) (superparen)))
+
+(add-style "defparameter" #'defparameter-styling-function)
+
+(defun defvar-styling-function (pos)
+  (let ((form-end (sexpr-end pos))
+        (symbol-style *defvar-symbol-style*)
+        (macro-style *generic-macro-style*))
+    (superparen) (macro) (symbl) (form) (doc) (superparen)))
+
+(add-style "defvar" #'defvar-styling-function)
+
+(defun defconstant-styling-function (pos)
+  (let ((form-end (sexpr-end pos))
+        (symbol-style *defconstant-symbol-style*)
+        (macro-style *generic-macro-style*))
+    (superparen) (macro) (symbl) (form) (doc) (superparen)))
+
+(add-style "defconstant" #'defconstant-styling-function)
+
+(defun defclass-styling-function (pos)
+  (let ((form-end (sexpr-end pos))
+        (symbol-style *defclass-symbol-style*)
+        (macro-style *generic-macro-style*))
+    (superparen) (macro) (symbl) (derivation-list) (slot-list) (options) (superparen)))
+
+(add-style "defclass" #'defclass-styling-function)
+
+(defun defun-styling-function (pos)
+  #+sax-debug (when *defun-styling-function-debug*
+                 (debug-out "~%~%~S" 'defun-styling-function))
+  (let ((form-end (sexpr-end pos))
+        (symbol-style *defun-symbol-style*)
+        (macro-style *defun-macro-style*))
+    (superparen) (macro) (symbl) (parameter-list) (doc) (body) (superparen)))
+
+(add-style "defun" #'defun-styling-function)
+
+(defun defmacro-styling-function (pos)
+  (let ((form-end (sexpr-end pos))
+        (symbol-style *defmacro-symbol-style*)
+        (macro-style *generic-macro-style*))
+    (superparen) (macro) (symbl) (parameter-list) (doc) (body) (superparen)))
+
+(add-style "defmacro" #'defmacro-styling-function)
+
+(defun define-compiler-macro-styling-function (pos)
+  (let ((form-end (sexpr-end pos))
+        (symbol-style *generic-function-symbol-style*)
+        (macro-style *defun-macro-style*))
+    (superparen) (macro) (symbl) (parameter-list) (doc) (body) (superparen)))
+
+(add-style "define-compiler-macro" #'define-compiler-macro-styling-function)
+
+(defun define-modify-macro-styling-function (pos)
+  (let ((form-end (sexpr-end pos))
+        (symbol-style *generic-function-symbol-style*)
+        (macro-style *defun-macro-style*))
+    (superparen) (macro) (symbl) (parameter-list) (form) (doc) (superparen)))
+
+(add-style "define-modify-macro" #'define-modify-macro-styling-function)
+
+(defun define-setf-expander-styling-function (pos)
+  (let ((form-end (sexpr-end pos))
+        (symbol-style *generic-function-symbol-style*)
+        (macro-style *defun-macro-style*))
+    (superparen) (macro) (symbl) (parameter-list) (doc) (body) (superparen)))
+
+(add-style "define-setf-expander" #'define-setf-expander-styling-function)
+
+(defun define-condition-styling-function (pos)
+  (let ((form-end (sexpr-end pos))
+        (symbol-style *generic-function-symbol-style*)
+        (macro-style *defun-macro-style*))
+    (superparen) (macro) (symbl) (derivation-list) (slot-list) (options) (superparen)))
+
+(add-style "define-condition" #'define-condition-styling-function)
+
+(defun defgeneric-styling-function (pos)
+  (let ((form-end (sexpr-end pos))
+        (symbol-style *defgeneric-symbol-style*)
+        (macro-style *generic-macro-style*))
+    (superparen) (macro) (symbl) (parameter-list) (options) (superparen)))
+
+(add-style "defgeneric" #'defgeneric-styling-function)
+
+(defun defmethod-styling-function (pos)
+  (let ((form-end (sexpr-end pos))
+        (symbol-style *defmethod-symbol-style*)
+        (macro-style *generic-macro-style*))
+    (when pos 
+    (superparen) (macro) (symbl) (qualifier) (parameter-list) (doc) (body) (superparen))))
+
+(add-style "defmethod" #'defmethod-styling-function)
+
+(defun objc-defmethod-styling-function (pos)
+  (let ((form-end (sexpr-end pos))
+        (macro-style *objc-macro-style*))
+    (superparen) (macro) (objc-symbl pos) (parameter-list) (doc) (body) (superparen)))
+
+(add-style "objc:defmethod" #'objc-defmethod-styling-function)
+
+(defun defcommand-styling-function (pos)
+  (let ((form-end (sexpr-end pos))
+        (symbol-style *defcommand-symbol-style*)
+        (macro-style *defcommand-macro-style*))
+    (superparen) (macro) (symbl) (parameter-list) (doc) (doc) (body) (superparen)))
+
+(add-style "hemlock::defcommand" #'defcommand-styling-function)
+
+(defun labels-styling-function (pos)
+  (let ((form-end (sexpr-end pos))
+        (macro-style *cl-package-style*))
+    (paren) (macro) (embedded-function-definitions) (body) (paren)))
+
+(add-style "labels" #'labels-styling-function)
+
+(defun lambda-styling-function (pos)
+  #+sax-debug (when *lambda-styling-function-debug*
+                (debug-out "~%~%~S" 'lambda-styling-function))
+  (let ((form-end (sexpr-end pos))
+        (macro-style *lambda-macro-style*))
+    (superparen) (macro) (parameter-list) (doc) (body) (superparen)))
+
+(add-style "lambda" #'lambda-styling-function)
+
+(defun flet-styling-function (pos)
+  (let ((form-end (sexpr-end pos))
+        (macro-style *cl-package-style*))
+    (paren) (macro) (embedded-function-definitions) (body) (paren)))
+
+(add-style "flet" #'flet-styling-function)
+
+(defun loop-styling-function (pos)
+  (let ((form-end (sexpr-end pos))
+        (macro-style *loop-macro-style*))
+    (loop-superparen) (macro) (loop-body) (loop-superparen)))
+
+(add-style "loop" #'loop-styling-function)
+
+(defun defstruct-styling-function (pos)
+  (let ((form-end (sexpr-end pos))
+        (macro-style *generic-macro-style*))
+    (superparen) (macro) (struct-sym) (doc) (struct-fields) (superparen)))
+
+(add-style "defstruct" #'defstruct-styling-function)
+
+(defun dotimes-styling-function (pos)
+  (let ((form-end (sexpr-end pos))
+        (macro-style *cl-package-style*))
+    (paren) (macro) (variable-form) (body) (paren)))
+
+(add-style "dotimes" #'dotimes-styling-function)
+
+(defun dolist-styling-function (pos)
+  (let ((form-end (sexpr-end pos))
+        (macro-style *cl-package-style*))
+    (paren) (macro) (variable-form) (body) (paren)))
+
+(add-style "dolist" #'dolist-styling-function)
+
+(defun multiple-value-bind-styling-function (pos)
+  (let ((form-end (sexpr-end pos))
+        (macro-style *cl-package-style*))
+    (paren) (macro) (variable-list) (body) (paren)))
+
+(add-style "multiple-value-bind" #'multiple-value-bind-styling-function)
+
+(defun multiple-value-setq-styling-function (pos)
+  (let ((form-end (sexpr-end pos))
+        (macro-style *cl-package-style*))
+    (paren) (macro) (variable-list) (body) (paren)))
+
+(add-style "multiple-value-setq" #'multiple-value-setq-styling-function)
+
+(defun destructuring-bind-styling-function (pos)
+  (let ((form-end (sexpr-end pos))
+        (macro-style *cl-package-style*))
+    (paren) (macro) (parameter-list) (body) (paren)))
+
+(add-style "destructuring-bind" #'destructuring-bind-styling-function)
+
+(defun do-styling-function (pos)
+  (let ((form-end (sexpr-end pos))
+        (macro-style *cl-package-style*))
+    (paren) (macro) (variable-definitions) (form) (body) (paren)))
+
+(add-style "do" #'do-styling-function)
+
+(defun do*-styling-function (pos)
+  (let ((form-end (sexpr-end pos))
+        (macro-style *cl-package-style*))
+    (paren) (macro) (variable-definitions) (form) (body) (paren)))
+
+(add-style "do*" #'do-styling-function)
+
+(defun let-styling-function (pos)
+  (let ((form-end (sexpr-end pos))
+        (macro-style *cl-package-style*))
+    (paren) (macro) (variable-definitions) (body) (paren)))
+
+(add-style "let" #'let-styling-function)
+
+(defun let*-styling-function (pos)
+  (let ((form-end (sexpr-end pos))
+        (macro-style *cl-package-style*))
+    (paren) (macro) (variable-definitions) (body) (paren)))
+
+(add-style "let*" #'let-styling-function)
+
+(defun prog-styling-function (pos)
+  (let ((form-end (sexpr-end pos))
+        (macro-style *cl-package-style*))
+    (paren) (macro) (variable-definitions) (body) (paren)))
+
+(add-style "prog" #'prog-styling-function)
+
+(defun prog*-styling-function (pos)
+  (let ((form-end (sexpr-end pos))
+        (macro-style *cl-package-style*))
+    (paren) (macro) (variable-definitions) (body) (paren)))
+
+(add-style "prog*" #'prog*-styling-function)
+
+(defun with-slots-styling-function (pos)
+  (let ((form-end (sexpr-end pos))
+        (macro-style *cl-package-style*))
+    (paren) (macro) (variable-definitions) (form) (body) (paren)))
+
+(add-style "with-slots" #'with-slots-styling-function)
+
+(defun with-accessors-styling-function (pos)
+  (let ((form-end (sexpr-end pos))
+        (macro-style *cl-package-style*))
+    (paren) (macro) (variable-definitions) (form) (body) (paren)))
+
+(add-style "with-accessors" #'with-accessors-styling-function)
+
+(defun with-open-file-styling-function (pos)
+  (let ((form-end (sexpr-end pos))
+        (macro-style *cl-package-style*))
+    (paren) (macro) (variable-form) (body) (paren)))
+
+(add-style "with-open-file" #'with-open-file-styling-function)
+
+(defun macrolet-styling-function (pos)
+  (let ((form-end (sexpr-end pos))
+        (macro-style *cl-package-style*))
+    (paren) (macro) (embedded-function-definitions) (body) (paren)))
+
+(add-style "macrolet" #'macrolet-styling-function)
+
+(defun case-styling-function (pos)
+  (let ((form-end (sexpr-end pos))
+        (macro-style *cl-package-style*))
+    (paren) (macro) (form) (case-match-forms) (paren)))
+
+(add-style "case" #'case-styling-function)
+(add-style "ccase" #'case-styling-function)
+(add-style "ecase" #'case-styling-function)
+(add-style "typecase" #'case-styling-function)
+(add-style "etypecase" #'case-styling-function)
+(add-style "ctypecase" #'case-styling-function)
+
+(defun eval-when-styling-function (pos)
+  (let ((form-end (sexpr-end pos))
+        (macro-style *cl-package-style*))
+    (eval-when-superparen) (macro) (form) (body) (eval-when-superparen)))
+
+(add-style "eval-when" #'eval-when-styling-function)
+
+;;; history-lists.lisp needs this, for now:
+(pushnew :syntax-styling *features*)
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
Index: /trunk/contrib/foy/syntax-styling/syntax-styling-comments.lisp
===================================================================
--- /trunk/contrib/foy/syntax-styling/syntax-styling-comments.lisp	(revision 13946)
+++ /trunk/contrib/foy/syntax-styling/syntax-styling-comments.lisp	(revision 13946)
@@ -0,0 +1,400 @@
+;;;-*- Mode: Lisp; Package: (SYNTAX-STYLING (CL CCL HEMLOCK-INTERNALS)) -*-
+
+;;; ****************************************************************************
+;;; 
+;;;      syntax-styling-comments.lisp
+;;;
+;;;      copyright © 2009 Glen Foy, all rights reserved,
+;;;
+;;;     These classes support the styling of semi-colon and sharp-stroke comments,
+;;;     and strings.  Most unusual cases are correctly handled: strings embedded in 
+;;;     comments, comments inside of strings, etc.
+;;;
+;;;      Mod history, most recent first:
+;;;      10/18/9   first cut.
+;;; 
+;;; ****************************************************************************
+
+(in-package "SAX")
+
+
+;;; ----------------------------------------------------------------------------
+;;;
+(defClass STYLED-COMMENT ()
+  ((comment-start :initarg :comment-start :initform nil :reader comment-start)
+   (comment-end :initform nil :initarg :comment-end :reader comment-end))
+  (:documentation "Support for styled comments."))
+
+(defClass STYLED-SEMI-COLON-COMMENT (styled-comment) ())
+
+(defClass STYLED-SHARP-COMMENT (styled-comment) ())
+
+(defMethod style-comment ((comment styled-semi-colon-comment))
+  (set-style-attributes (attribute-dictionary *semi-colon-comment-style*)
+                        (comment-start comment) (comment-end comment)))
+
+(defMethod style-comment ((comment styled-sharp-comment))
+  (set-style-attributes (attribute-dictionary *sharp-comment-style*)
+                        (comment-start comment) (comment-end comment)))
+
+;;; ----------------------------------------------------------------------------
+;;;
+(defClass STYLED-STRING ()
+  ((string-start :initarg :string-start :initform nil :reader string-start)
+   (string-end :initform nil :initarg :string-end :reader string-end))
+  (:documentation "Support for styled strings."))
+
+(defMethod style-string ((string styled-string))
+  (cond (*inc-p* ; if dynamic, never style past *inc-pos* 
+         (set-style-attributes (attribute-dictionary *string-style*)
+                               (string-start string) *inc-pos*))
+        (t
+         (set-style-attributes (attribute-dictionary *string-style*)
+                               (string-start string) (string-end string)))))
+
+;;; ----------------------------------------------------------------------------
+;;;
+(defClass SEGMENT-ARRAY ()
+  ((array :initarg :array :reader segment-array-array)
+   (length :initarg :length :accessor segment-array-length))
+  (:documentation 
+   "A sorted 2d array of the start and end positions for segments  in
+a buffer.  There are three segment types: strings, semi-colon comments, 
+and sharp-stroke comments.  The method not-embedded-in-segment-p does
+ a binary search for the position of a particular char to see if the 
+char is embedded."))
+
+(defMethod print-object ((array segment-array) stream)
+  (declare (ignore stream))
+  #+sax-debug (when *print-object-segment-array-debug*
+                (dump-segment-array array))
+  #-sax-debug (call-next-method))
+
+(defmethod dump-segment-array ((a segment-array))
+  (format t "~%~%segment-array length: ~S" (segment-array-length a))
+  (dotimes (idx (segment-array-length a))
+    (format t "~%   ~S" (aref (segment-array-array a) idx 0))
+    (format t "~%   ~S~%" (aref (segment-array-array a) idx 1))))
+
+(defun unify-segment-lists (segment-list-1 segment-list-2)
+  "Merge two lists, discarding segments which are embedded in segments of the other list."
+  (do* ((list-1 segment-list-1)
+        (list-2 segment-list-2)
+        (segment-1 (first list-1) (first list-1))
+        (segment-2 (first list-2) (first list-2))
+        (unified-list nil))
+       ((and (endp list-1) (endp list-2)) (nreverse unified-list))
+    (cond ((and list-1 list-2)
+           (cond ((mark< (first segment-1) (first segment-2))
+                  (cond ((mark< (first segment-2) (second segment-1))
+                         (pop list-2))
+                        (t 
+                         (push segment-1 unified-list)
+                         (pop list-1))))
+                 (t
+                  (cond ((mark< (first segment-1) (second segment-2))
+                         (pop list-1))
+                        (t 
+                         (push segment-2 unified-list)
+                         (pop list-2))))))
+          (t ; one list is empty - add what's left of the other
+           (cond ((endp list-1)
+                  (return (append (nreverse unified-list) list-2)))
+                 (t
+                  (return (append (nreverse unified-list) list-1))))))))
+
+(defun make-segment-array (table)
+  "Constructor for the segment-array class."
+  (let ((table-length (length table)))
+    (make-instance 'segment-array
+      :length table-length
+      :array (make-array `(,table-length 2)
+                         :initial-contents table))))
+
+;;; This is called when constructing the segment array and to get a list of strings
+;;; to style. When styling dynamically, cull the string list. When constructing the 
+;;; segment array, don't.
+;;;
+(defun create-string-list (start end  &optional styling-p)
+  "Return a list of the form, (start end), for each string in buffer.
+The list is in reverse order."
+  (flet ((semi-colon-commented-p (pos)
+           (do* ((start (mark-move pos 0) (nmark-next start))
+                 (char (mark-char start) (mark-char start)))
+                ((mark>= start pos))
+             (when (char= char #\;) (return-from semi-colon-commented-p t))))
+         (sharp-stroke-commented-p (pos)
+           (do ((start (clone pos) (nmark-prev start))
+                (char (mark-char start) (mark-char start))
+                (char-minus-one 
+                 (when (>= (mark-charpos start) 1) (mark-char (mark-prev pos)))
+                 (when (>= (mark-charpos start) 1) (mark-char (mark-prev pos)))))
+               ((or (= (mark-charpos start) 1)
+                    (and (char= char #\#) (char= char-minus-one #\|))))
+             (when (and (char= char #\|) 
+                        (char= char-minus-one #\|))
+               (return-from sharp-stroke-commented-p t)))))
+    (do* ((position (clone start))
+          string-list string-end)
+         ((or (null position) (mark>= position end)) string-list)
+      (cond ((and (eql (mark-char position) #\") 
+                  (not (eql (mark-char (if (> (mark-charpos position) 0)
+                                         (mark-prev position)
+                                         position)) #\\))
+                  ;; Too expensive; may have a rare mis-styled file
+                  ;; because of an unmatched quote in a sharp-comment.
+                  ;; (not (sharp-stroke-commented-p position))
+                  (not (semi-colon-commented-p position)))
+             (setf string-end (sexpr-end position))
+             (cond ((and string-end (mark<= string-end end))
+                    ;; Support for dynamic styling - only cull the string list
+                    ;; when styling strings, not when constructing the segment array
+                    (if *inc-p* 
+                      (if styling-p
+                        ;; cull
+                        (when (and (mark>= *inc-pos* position)
+                                   (mark<= *inc-pos* string-end))
+                          (push (list position string-end) string-list))
+                        (push (list position string-end) string-list))
+                      (push (list position string-end) string-list))
+                    (setf position (clone string-end)))
+                   (t 
+                    (return string-list))))
+            (t 
+             (nmark-next position))))))
+
+;;; This is only called by get-combined-segment-list, when doing vanilla styling.
+(defun create-semi-colon-comment-list (start end )
+   "Return a list of the form, (start end), for each comment in buffer."
+   (do* ((position (clone start))
+         comment-list comment-end)
+        ((or (null position) (mark> position end)) (nreverse comment-list))
+      (cond ((and (eql (mark-char position) #\;) 
+                  (mark> position (buf-start-mark)) ; *** mode line ???
+                  (not (eql (mark-char (mark-prev position)) #\\)))
+              (setf comment-end (line-end (clone position)))
+              (cond ((and comment-end (mark<= comment-end end))
+                      (push (list (clone position) (mark-next comment-end)) comment-list)
+                      (setf position (mark-next comment-end)))
+                     (t ; hum ...
+                      (setf position (mark-next position)))))
+             (t
+              (setf position (mark-next position))))))
+
+;;; This is only called by get-combined-segment-list, when doing vanilla styling.
+(defun create-sharp-stroke-comment-list (start end )
+  "Return a list of the form, (start end), for each comment in buffer."
+  (do* ((position (clone start))
+        comment-list comment-end)
+       ((or (null position) (mark> position end)) (nreverse comment-list))
+    (cond ((and (eql (mark-char position) #\#)
+                (eql (mark-char (mark-next position)) #\|)
+                (mark> position (buf-start-mark))
+                (not (eql (mark-char (mark-prev position)) #\\)))
+           (setf comment-end (pattern-search position *stroke-sharp-forward-pattern* end))
+           (cond ((and comment-end (mark<= comment-end end))
+                  (push (list position comment-end) comment-list)
+                  (setf position (mark-next comment-end)))
+                 (t 
+                  (return (nreverse comment-list)))))
+          (t
+           (setq position (mark-next position))))))
+
+;;; This is only called by get-combined-segment-list, when doing vanilla styling.
+(defun create-cocoa-syntax-list (start end pattern)
+  "Return a list of the form, (start end), for each Cocoa function name in buffer."
+  (do* ((position (pattern-search (clone start) pattern end)
+                  (pattern-search (clone name-end) pattern end))
+        (name-end (when position (sexpr-end position)) (when position (sexpr-end position)))
+        name-list)
+       ((or (null position) (null name-end) (mark> position end)) (nreverse name-list))
+    (push (list position name-end) name-list)))
+
+(defMethod not-embedded-in-segment-p ((array segment-array) position)
+  ;; Do a binary search of the segment-array to see if the position is embedded.
+  #+sax-debug (when *not-embedded-in-segment-p-debug*
+               (debug-out "~%~%~S" 'not-embedded-in-segment-p)
+               (dump-segment-array array)
+               (debug-out "~%position: ~S" position))
+  (when (or (zerop (segment-array-length array)) (null position))
+    (return-from not-embedded-in-segment-p t))
+  (do* ((top (1- (segment-array-length array)))
+        (bottom 0)
+        (index (truncate (+ bottom top) 2) (truncate (+ bottom top) 2)))
+       ((< top bottom) t)
+    (when (and (mark< (aref (segment-array-array array) index 0) position)
+               (mark> (aref (segment-array-array array) index 1) position))
+      ;; embedded - return the end of the containing segment as the second value:
+      (return (values nil (aref (segment-array-array array) index 1))))
+    (cond ((mark<= position (aref (segment-array-array array) index 0))
+           (setf top (1- index)))
+          ((mark>= position (aref (segment-array-array array) index 1))
+           (setf bottom (1+ index)))
+          (t (error "~&Bad value in binary search: ~a" position)))))
+
+(defun embedded-in-segment-p (pos)
+  (when *segment-array*
+    (multiple-value-bind (not-embedded-p end-of-segment)
+                         (not-embedded-in-segment-p *segment-array* pos)
+      (values (not not-embedded-p) end-of-segment))))
+
+(defun style-strings (&optional (start (buf-start-mark)) (end (buf-end-mark))
+                                &aux string-instances)
+  #+sax-debug (when *style-strings-debug*
+               (debug-out "~%~%~S" 'style-strings))
+  (setf *segment-list* (create-string-list start end *inc-p*))
+  (do* ((string-list *segment-list* (rest string-list))
+        (start-string (first (first string-list)) (first (first string-list)))
+        (end-string (second (first string-list)) (second (first string-list))))
+       ((null start-string))
+    (push (make-instance 'styled-string
+            :string-start start-string
+            :string-end end-string)
+          string-instances))
+  ;; Create the segment array - if styling dynamically.
+  ;; Create the inclusive string list for the segment array.
+  (setf *segment-array* (make-segment-array 
+                         (if *inc-p*
+                           (setf *segment-list* (nreverse (create-string-list start end)))
+                           (setf *segment-list* (nreverse *segment-list*)))))
+  (dolist (string string-instances)
+    (style-string string))
+  string-instances)
+
+(defun style-semi-colon-comments (&optional (start (buf-start-mark)) (end (buf-end-mark)))
+  #+sax-debug (when *style-semi-colon-comments-debug*
+                (debug-out "~%~%~S" 'style-semi-colon-comments))
+  (let ((comment-instances nil)
+        (comment-segment-list nil))
+    (do* ((start-comment (pattern-search start *semicolon-forward-pattern* end)
+                         (pattern-search end-comment *semicolon-forward-pattern* end))
+          (end-comment (when start-comment (line-end (clone start-comment)))
+                       (when start-comment (line-end (clone start-comment)))))
+         ((or (not start-comment)
+              (not end-comment)
+              (mark> start-comment end)))
+      #+sax-debug (when *style-semi-colon-comments-debug*
+                   (debug-out "~%start-comment: ~S" start-comment)
+                   (debug-out "~%end-comment: ~S" end-comment))
+
+      ;; The first AND handles the case where a string spans two comments. 
+      (when (or (and (mark= start-comment (mark-line-start start-comment))
+                     (or (not *inc-p*)
+                         (and *inc-p* 
+                              (mark>= *inc-pos* start-comment)
+                              (mark<= (mark-prev *inc-pos*) end-comment))))
+                ;; with dynamically-style-comments *segment-array* may not be there yet.
+                (and (not (embedded-in-segment-p start-comment))
+                     (not (and (>= (mark-charpos start-comment) 2)
+                               (eq (mark-char start-comment -1) #\\)
+                               (eq (mark-char start-comment -2) #\#)))))
+        ;; Need the entire segment array for accurate parsing, even when
+        ;; not styling this comment:
+        (push (list start-comment end-comment) comment-segment-list)
+        (when (or (not *inc-p*)
+                  (and *inc-p* 
+                       (mark>= *inc-pos* start-comment)
+                       (mark<= (mark-prev *inc-pos*) end-comment)))
+          (push (make-instance 'styled-semi-colon-comment 
+                  :comment-start start-comment
+                  :comment-end end-comment)
+                comment-instances))))
+    (setf *segment-list* 
+          (unify-segment-lists (nreverse comment-segment-list) *segment-list*))
+    (setf *segment-array* (make-segment-array *segment-list*))
+    (setf comment-instances (nreverse comment-instances))
+    (dolist (comment comment-instances)
+      (style-comment comment))
+    comment-instances))
+
+(defun style-sharp-comments (&optional (start (buf-start-mark)) (end (buf-end-mark)))
+  (flet ((find-end-comment (start-comment)
+           (do* ((level-count 1)
+                 (next-end-comment (pattern-search start-comment *stroke-sharp-forward-pattern* end)
+                                   (when next-start-comment
+                                     (pattern-search (nmark-offset next-start-comment 2) *stroke-sharp-forward-pattern* end)))
+                 (next-start-comment (pattern-search (nmark-offset start-comment 2) *sharp-stroke-forward-pattern* end)
+                                     (when next-start-comment
+                                       (pattern-search (nmark-offset next-start-comment 2) *sharp-stroke-forward-pattern* end))))
+                ((null next-end-comment))
+             (when (and next-start-comment (mark< next-start-comment next-end-comment))
+               ;; nested
+               (incf level-count))
+             (decf level-count)
+             (when (= level-count 0) (return next-end-comment)))))
+    (let ((comment-instances nil)
+          (comment-segment-list nil))
+      (do* ((start-comment (pattern-search start *sharp-stroke-forward-pattern* end)
+                           (pattern-search end-comment *sharp-stroke-forward-pattern* end))
+            (end-comment (when (and start-comment (mark<= start-comment end)) ; *** redundant
+                           (find-end-comment start-comment))
+                         (when (and start-comment (mark<= start-comment end))
+                           (find-end-comment start-comment))))
+           ((or (not start-comment) 
+                (not end-comment)))
+        (cond ((and (not-embedded-in-segment-p *segment-array* start-comment)
+                    (not-embedded-in-segment-p *segment-array* end-comment)
+                    (or (not *inc-p*)
+                        (and *inc-p* 
+                             (mark>= *inc-pos* start-comment)
+                             (mark<= (mark-offset *inc-pos* -3) end-comment))))
+               (push (list start-comment end-comment) comment-segment-list)
+               (push (make-instance 'styled-sharp-comment 
+                       :comment-start (mark-offset start-comment -2)
+                       :comment-end (mark-offset end-comment 2))
+                     comment-instances))))
+      (when comment-instances
+        (setf *segment-list* (unify-segment-lists (nreverse comment-segment-list) *segment-list*))
+        (setf *segment-array* (make-segment-array *segment-list*))
+        (setf comment-instances (nreverse comment-instances))
+        (dolist (comment comment-instances)
+          (style-comment comment))
+        comment-instances))))
+
+(defun style-comments (start end)
+  (style-strings start end)
+  (style-semi-colon-comments start end)
+  (style-sharp-comments start end))
+
+(defun dynamically-style-comments (start end style-strings-p style-semi-colon-comments-p)
+  #+sax-debug (when *dynamically-style-comments-debug*
+                (debug-out "~%~%~S" 'dynamically-style-comments))
+  (let ((hi::*current-buffer* *buf*))
+    (hemlock::parse-over-block (mark-line start) (mark-line end))
+    (when style-strings-p (style-strings start end))
+    (when style-semi-colon-comments-p 
+      ;; (style-semi-colon-comments (mark-line-start end) end))))
+      ;; Start is necessary to generate an complete segment-array for subsequent styling:
+      (style-semi-colon-comments start end))))
+
+;;; *** this needs to use start and end
+(defun get-combined-segment-list ()
+  (let* ((start (buf-start-mark))
+         (end (buf-end-mark))
+         (string-list (nreverse (create-string-list start end)))
+         (semi-colon-comment-list (create-semi-colon-comment-list start end))
+         (sharp-stroke-comment-list (create-sharp-stroke-comment-list start end))
+         (cocoa-function-list (create-cocoa-syntax-list start end *sharp-slash-forward-pattern*))
+         (cocoa-constant1-list (create-cocoa-syntax-list start end *sharp-dollar-forward-pattern*))
+         (cocoa-constant2-list (create-cocoa-syntax-list start end *sharp-ampersand-forward-pattern*))
+         (cocoa-constant3-list (create-cocoa-syntax-list start end *colon-lessthan-forward-pattern*))
+         (cocoa-constant4-list (create-cocoa-syntax-list start end *sharp-backslash-forward-pattern*)))
+    (unify-segment-lists 
+     string-list 
+     (unify-segment-lists 
+      cocoa-constant1-list
+      (unify-segment-lists 
+       cocoa-constant2-list
+       (unify-segment-lists 
+        cocoa-constant3-list
+        (unify-segment-lists 
+         cocoa-constant4-list
+         (unify-segment-lists 
+          cocoa-function-list
+          (unify-segment-lists 
+           semi-colon-comment-list
+           sharp-stroke-comment-list)))))))))
+
+
+
+
Index: /trunk/contrib/foy/syntax-styling/syntax-styling-specials.lisp
===================================================================
--- /trunk/contrib/foy/syntax-styling/syntax-styling-specials.lisp	(revision 13946)
+++ /trunk/contrib/foy/syntax-styling/syntax-styling-specials.lisp	(revision 13946)
@@ -0,0 +1,671 @@
+;;;-*- Mode: Lisp; Package: SYNTAX-STYLING -*-
+
+;;; ****************************************************************************
+;;; 
+;;;      syntax-styling-specials.lisp
+;;;
+;;;      copyright (c) 2009 Glen Foy
+;;;      (Permission is granted to Clozure Associates to distribute this file.)
+;;;
+;;;      Special variables, utility functions and macros.
+;;;
+;;;      This software is offered "as is", without warranty of any kind.
+;;;
+;;;      Mod History, most recent first:
+;;;      10/18/9   First cut.
+;;;
+;;; ****************************************************************************
+
+#-sax-debug
+(defPackage syntax-styling (:use :cl :ccl :hemlock-internals) (:nicknames "SAX"))
+
+(in-package "SAX")
+
+(defParameter *style-case-p* t "To set case, or not to set case.")
+
+;;; ----------------------------------------------------------------------------
+;;; Configure your style by hacking the colors and style parameters below:
+;;; ----------------------------------------------------------------------------
+;;;
+(defParameter *black-color* (#/colorWithCalibratedRed:green:blue:alpha: ns:ns-color 0.0 0.0 0.0 1.0))
+(defParameter *gray-color* (#/colorWithCalibratedRed:green:blue:alpha: ns:ns-color 0.92 0.92 0.92 1.0))
+(defParameter *medium-gray-color* (#/colorWithCalibratedRed:green:blue:alpha: ns:ns-color 0.30 0.30 0.30 1.0))
+(defParameter *darker-gray-color* (#/colorWithCalibratedRed:green:blue:alpha: ns:ns-color 0.11 0.11 0.11 1.0))
+(defParameter *dark-gray-color* (#/colorWithCalibratedRed:green:blue:alpha: ns:ns-color 0.01 0.01 0.01 1.0))
+(defParameter *blue-color* (#/colorWithCalibratedRed:green:blue:alpha: ns:ns-color 0.0 0.1 0.65 1.0))
+(defParameter *light-blue-color* (#/colorWithCalibratedRed:green:blue:alpha: ns:ns-color 0.0 0.35 0.65 1.0))
+(defParameter *green-color* (#/colorWithCalibratedRed:green:blue:alpha: ns:ns-color 0.0 0.2 0.0 1.0))
+(defParameter *turquoise-color* (#/colorWithCalibratedRed:green:blue:alpha: ns:ns-color 0.0 0.3 0.4 1.0))
+(defParameter *violet-color* (#/colorWithCalibratedRed:green:blue:alpha: ns:ns-color 0.15 0.1 0.7 1.0))
+(defParameter *wine-red-color* (#/colorWithCalibratedRed:green:blue:alpha: ns:ns-color 0.5 0.1 0.2 1.0))
+(defParameter *medium-red-color* (#/colorWithCalibratedRed:green:blue:alpha: ns:ns-color 0.8 0.0 0.2 1.0))
+(defParameter *magenta-color* (#/colorWithCalibratedRed:green:blue:alpha: ns:ns-color 0.75 0.0 0.5 1.0))
+(defParameter *dark-magenta-color* (#/colorWithCalibratedRed:green:blue:alpha: ns:ns-color 0.35 0.0 0.25 1.0))
+(defParameter *brown-color* (#/colorWithCalibratedRed:green:blue:alpha: ns:ns-color 0.35 0.2 0.0 1.0))
+
+(defParameter *generic-symbol-color* *blue-color*)
+(defParameter *generic-macro-color* *wine-red-color*)
+
+;;; Convert style-spec to an ns-dictionary with the specified attributes.
+;;; Temporary text attributes only support color and underlining.
+(defun spec-to-dict (font-spec)
+  (let* ((dict (make-instance 'ns:ns-mutable-dictionary :with-capacity 2))
+         (color (getf font-spec :font-color)) 
+         (underline (getf font-spec :font-underline)) ; :single :double :thick
+         (underline-int (case underline (:single 1) (:double 2) (:thick 3))))
+    (when color (#/setObject:forKey: dict color 
+                                     #&NSForegroundColorAttributeName))
+    (when (and underline underline-int) 
+      (#/setObject:forKey: dict (#/numberWithInt: ns:ns-number underline-int)
+                           #&NSUnderlineStyleAttributeName))
+    dict))
+
+;;; ----------------------------------------------------------------------------
+;;; The Styles:
+;;; ----------------------------------------------------------------------------
+;;;
+;;; The cdr of each dotted-pair is the capitalization spec:
+(defParameter *vanilla-styling* (cons (spec-to-dict (list :font-color *black-color*)) :down))
+(defParameter *generic-text-style* (cons (spec-to-dict (list :font-color *darker-gray-color*)) :down))
+(defParameter *generic-macro-style* (cons (spec-to-dict (list :font-color *generic-macro-color*)) :cap3))
+(defParameter *generic-symbol-style* (cons (spec-to-dict (list :font-color *generic-symbol-color*)) :down))
+(defParameter *generic-function-symbol-style* (cons (spec-to-dict (list :font-color *generic-symbol-color* :font-underline :single)) :down))  
+(defParameter *embedded-function-symbol-style* (cons (spec-to-dict (list :font-color *generic-symbol-color* :font-underline :single)) :down))  
+;;; This is also the style for lambda-list keywords:
+(defParameter *keyword-package-style* (cons (spec-to-dict (list :font-color *dark-magenta-color*)) :down))
+(defParameter *cl-package-style* (cons (spec-to-dict (list :font-color *blue-color*)) :down))
+(defParameter *exported-symbol-style* (cons (spec-to-dict (list :font-color *generic-symbol-color* :font-underline :double)) :up))
+
+(defParameter *semi-colon-comment-style* (cons (spec-to-dict (list :font-color *turquoise-color*)) :unchanged))
+(defParameter *sharp-comment-style* (cons (spec-to-dict (list :font-color *medium-gray-color*)) :unchanged))
+(defParameter *string-style* (cons (spec-to-dict (list :font-color *turquoise-color*)) :unchanged))
+
+(defParameter *superparen-style* (cons (spec-to-dict (list :font-color *magenta-color*)) :unchanged))
+(defParameter *eval-when-superparen-style* (cons (spec-to-dict (list :font-color *magenta-color*)) :unchanged))
+(defParameter *loop-superparen-style* (cons (spec-to-dict (list :font-color *turquoise-color*)) :unchanged))
+
+(defParameter *variable-definition-symbol-style* (cons (spec-to-dict (list :font-color *light-blue-color*)) :down))
+(defParameter *defstruct-field-style* (cons (spec-to-dict (list :font-color *blue-color*)) :down))
+(defParameter *defstruct-ancestor-style* (cons (spec-to-dict (list :font-color *blue-color*)) :down))
+(defParameter *defclass-derivation-style* (cons (spec-to-dict (list :font-color *blue-color*)) :down))
+(defParameter *defclass-slot-style* (cons (spec-to-dict (list :font-color *blue-color*)) :down))
+(defParameter *parameter-style* (cons (spec-to-dict (list :font-color *light-blue-color*)) :down))
+(defParameter *specializer-style* (cons (spec-to-dict (list :font-color *green-color*)) :unchanged))
+(defParameter *case-match-style* (cons (spec-to-dict (list :font-color *light-blue-color*)) :down))
+
+(defParameter *defpackage-symbol-style* (cons (spec-to-dict (list :font-color *generic-symbol-color*)) :down))
+(defParameter *defparameter-symbol-style* (cons (spec-to-dict (list :font-color *generic-symbol-color*)) :down))
+(defParameter *defvar-symbol-style* (cons (spec-to-dict (list :font-color *generic-symbol-color*)) :down))
+(defParameter *defconstant-symbol-style* (cons (spec-to-dict (list :font-color *generic-symbol-color*)) :down))
+(defParameter *defclass-symbol-style* (cons (spec-to-dict (list :font-color *generic-symbol-color* :font-underline :single)) :up))
+(defParameter *defun-symbol-style* (cons (spec-to-dict (list :font-color *generic-symbol-color* :font-underline :single)) :down))
+(defParameter *defmacro-symbol-style* (cons (spec-to-dict (list :font-color *generic-symbol-color* :font-underline :single)) :down))
+(defParameter *defgeneric-symbol-style* (cons (spec-to-dict (list :font-color *generic-symbol-color* :font-underline :single)) :down))
+(defParameter *defmethod-symbol-style* (cons (spec-to-dict (list :font-color *generic-symbol-color* :font-underline :single)) :down))
+(defParameter *objc-symbol-style* (cons (spec-to-dict (list :font-color *generic-symbol-color* :font-underline :single)) :unchanged))
+(defParameter *defcommand-symbol-style* (cons (spec-to-dict (list :font-color *generic-symbol-color* :font-underline :single)) :unchanged))
+(defParameter *defstruct-symbol-style* (cons (spec-to-dict (list :font-color *generic-symbol-color* :font-underline :single)) :up))
+
+(defParameter *lambda-macro-style* (cons (spec-to-dict (list :font-color *generic-symbol-color* :font-underline :single)) :down))
+(defParameter *loop-macro-style* (cons (spec-to-dict (list :font-color *magenta-color*)) :up))
+(defParameter *loop-keyword-style* (cons (spec-to-dict (list :font-color *dark-magenta-color*)) :down))
+(defParameter *defun-macro-style* (cons (spec-to-dict (list :font-color *generic-macro-color*)) :down))
+(defParameter *objc-macro-style* (cons (spec-to-dict (list :font-color *generic-macro-color*)) :cap8))
+(defParameter *defcommand-macro-style* (cons (spec-to-dict (list :font-color *generic-macro-color*)) :cap12))
+
+;;; ----------------------------------------------------------------------------
+;;; Various:
+;;; ----------------------------------------------------------------------------
+;;;
+(defParameter *styling-p* t "To style or not to style.")
+(defParameter *buf* nil "The target buffer.")
+(defParameter *layout* nil "The NSLayoutManager of the target text-view.")
+(defParameter *current-package* nil "Package used to style exported symbols.")
+;;; consolidate these two:
+(defParameter *inc-p* nil "Styling incrementally?")
+(defParameter *inc-pos* nil "Buffer-point during an incremental parse.")
+(defParameter *inside-semi-colon-comment-p* nil)
+(defParameter *paste-p* nil "Is a paste in progress?")
+(defParameter *paste-start* nil "Starting position of a paste operation.")
+(defParameter *paste-end* nil "Ending position of a paste operation.")
+
+;;; test
+(defParameter *style-screen-p* t "To style or not to style the screen after a given operation.")
+(defParameter *style-top-level-form-p* nil "To style or not to style the top-level form after a given operation.")
+(defParameter *segment-list* nil "Comment and string code data structure.")
+(defParameter *segment-array* nil "Comment and string code data structure.")
+
+(defParameter *form-style* nil "The style of the atom being processed incrementally.")
+(defParameter *form-start* nil "The start position of the atom being processed incrementally.")
+(defParameter *form-end* nil "The end position of the atom being processed incrementally.")
+(defParameter *superparen-closure* nil "An ugly hack to style superparens.")
+
+;;; key-event constants:
+(defParameter %control-y% #k"control-y")
+(defParameter %control-meta-q% #k"control-meta-q")
+(defParameter %control-d% #k"control-d")
+(defParameter %backspace% #k"Backspace")
+(defParameter %control-j% #k"control-j")
+(defparameter %backward-char-event% (hi::get-key-event* 98 8))
+
+;;; Search patterns:
+(defparameter *l-paren-forward-pattern* (new-search-pattern :character :forward #\())
+(defparameter *l-paren-backward-pattern* (new-search-pattern :character :backward #\())
+(defparameter *sharp-stroke-forward-pattern* (new-search-pattern :string-insensitive :forward "#|"))
+(defparameter *stroke-sharp-forward-pattern* (new-search-pattern :string-insensitive :forward "|#"))
+(defparameter *semicolon-forward-pattern* (new-search-pattern :character :forward #\;))
+(defParameter *sharp-slash-forward-pattern* (new-search-pattern :string-insensitive :forward "#/"))
+(defParameter *sharp-backslash-forward-pattern* (new-search-pattern :string-insensitive :forward "#\\"))
+(defParameter *sharp-dollar-forward-pattern* (new-search-pattern :string-insensitive :forward "#$"))
+(defParameter *sharp-ampersand-forward-pattern* (new-search-pattern :string-insensitive :forward "#&"))
+(defParameter *colon-lessthan-forward-pattern* (new-search-pattern :string-insensitive :forward ":<"))
+
+;;; ----------------------------------------------------------------------------
+;;; Mark functions and macros.
+;;; ----------------------------------------------------------------------------
+;;;
+;;; Hemlock's BUFFER is a doubly linked list of LINES.  MARKS specify relative positions 
+;;; within LINES.  Programming Hemlock involves a lot of MARK manipulation. These are some 
+;;; useful macros that operate on MARKS.  Destructive and non-destructive versions
+;;; are usually provided, using the prepended "n" convention for destructive functions.
+
+(defmacro clone (mark) `(hi::copy-mark ,mark :temporary))
+
+(defmacro set-storage (storage source)
+  `(progn
+     (setf (mark-charpos ,storage) (mark-charpos ,source))
+     (setf (mark-line ,storage) (mark-line ,source))
+     ,storage))
+
+;;; Needs to support nested forms as in: (mark-next (sexpr-end pos)),
+;;; only evaluating MARK-OR-FORM once.
+;;; No error, if MARK-OR-FORM evaluates to nil, just return nil.
+(defmacro mark-next (mark-or-form)
+  (let ((param (gensym))
+        (new-mark (gensym)))
+    `(let ((,param ,mark-or-form))
+       (when ,param
+         (let ((,new-mark (clone ,param)))
+           (setq ,new-mark (mark-after ,new-mark))
+           #+sax-debug (when (and *mark-next-debug* (null ,new-mark))
+                         (debug-out "~%mark-next returning nil."))
+           ,new-mark)))))
+
+(defmacro nmark-next (mark-or-form)
+  (let ((param (gensym)))
+    `(let ((,param ,mark-or-form))
+       (when ,param (mark-after ,param)))))
+
+(defmacro mark-prev (mark-or-form)
+  (let ((param (gensym))
+        (new-mark (gensym)))
+    `(let ((,param ,mark-or-form))
+       (when ,param
+         (let ((,new-mark (clone ,param)))
+           (setq ,new-mark (mark-before ,new-mark))
+           #+sax-debug (when (and *mark-prev-debug* (null ,new-mark))
+                         (debug-out "~%mark-prev returning nil."))
+           ,new-mark)))))
+
+(defmacro nmark-prev (mark-or-form)
+  (let ((param (gensym)))
+    `(let ((,param ,mark-or-form))
+       (when ,param (mark-before ,param)))))
+
+;;; This does not cross lines
+(defmacro mark-char (mark &optional offset)
+  (if offset
+    (let ((line (gensym))
+          (line-length (gensym))
+          (mark-charpos (gensym))
+          (offset-position (gensym)))
+      `(when ,mark
+         (let* ((,line (mark-line ,mark))
+                (,line-length (line-length ,line))
+                (,mark-charpos (mark-charpos ,mark))
+                (,offset-position (+ ,mark-charpos ,offset)))
+           (cond ((and (<= 0 ,offset-position) ; offset can be negative
+                       (< ,offset-position ,line-length))
+                  (line-character ,line ,offset-position))
+                 (t
+                  nil)))))
+      `(when ,mark
+         (next-character ,mark))))
+
+(defmacro mark-move (mark pos)
+  (let ((new-mark (gensym)))
+    `(when ,mark
+       (let ((,new-mark (clone ,mark)))
+         (move-to-position ,new-mark ,pos)))))
+
+(defmacro nmark-move (mark pos)
+  `(move-to-position ,mark ,pos))
+
+(defmacro mark-line-start (mark)
+  (let ((new-mark (gensym)))
+    `(when ,mark 
+       (let ((,new-mark (clone ,mark)))
+         (line-start ,new-mark)))))
+
+(defmacro mark-offset (mark offset)
+  (let ((new-mark (gensym)))
+    `(when ,mark
+       (let ((,new-mark (clone ,mark)))
+         (character-offset ,new-mark ,offset)))))
+
+(defmacro nmark-offset (mark offset)
+  `(when ,mark
+     (character-offset ,mark ,offset)
+     ,mark))
+
+(defMacro mark-min (m1 m2) `(if (mark< ,m1 ,m2) ,m1 ,m2))
+
+(defMacro mark-max (m1 m2) `(if (mark> ,m1 ,m2) ,m1 ,m2))
+
+(defmacro buf-end-mark (&optional buffer) 
+  `(clone (buffer-end-mark (if ,buffer ,buffer *buf*))))
+
+(defmacro buf-start-mark (&optional buffer) 
+  `(clone (buffer-start-mark (if ,buffer ,buffer *buf*))))
+
+;;; ----------------------------------------------------------------------------
+;;; Buffer functions and macros.
+;;; ----------------------------------------------------------------------------
+;;;
+(defmacro buffer-empty-p () `(mark= (buffer-start-mark *buf*) (buffer-end-mark *buf*)))
+
+(defun buffer-line-start (buffer &optional storage)
+  (let ((line (mark-line (buffer-point buffer))))
+    (cond (storage
+           (setf (mark-line storage) line)
+           (setf (mark-charpos storage) 0)
+           storage)
+          (
+           (mark line 0)))))
+
+(defun buffer-line-end (buffer &optional storage)
+  (let ((line (mark-line (buffer-point buffer))))
+    (cond (storage
+           (setf (mark-line storage) line)
+           (setf (mark-charpos storage) (line-length line)))
+          (t
+           (mark line (line-length line))))))
+
+;;; ----------------------------------------------------------------------------
+;;; Lisp syntax functions and macros.
+;;; ----------------------------------------------------------------------------
+;;;
+(defmacro sexpr-end (start)
+    (let ((sexpr-start (gensym))
+          (sexpr-end (gensym)))
+      `(when ,start
+         (let* ((,sexpr-start (clone ,start))
+                (,sexpr-end (when (hemlock::form-offset ,sexpr-start 1) ,sexpr-start)))
+           (if ,sexpr-end
+             ,sexpr-end
+             #+sax-debug (when *sexpr-end-debug* 
+                           (debug-out "~%sexpr-end returning nil - start-mark: ~S" ,start)))))))
+
+(defmacro sexpr-start (pos)
+  (let ((sexpr-start (gensym)))
+    `(when ,pos
+       (let ((,sexpr-start (clone ,pos)))
+         (if (hemlock::form-offset ,sexpr-start -1) 
+           ,sexpr-start
+           #+sax-debug (when *sexpr-start-debug* 
+                         (debug-out "~%sexpr-start returning nil - pos-mark: ~S" ,pos)))))))
+
+(defmacro limited-sexpr-end (start limit)
+  (let ((sexpr-start (gensym))
+        (sexpr-end (gensym))) 
+    `(when ,start
+       #+sax-debug (when *limited-sexpr-end-debug* 
+                     (debug-out "~%~%~S" 'limited-sexpr-end)
+                     (debug-out "~%start: ~S" ,start)
+                     (debug-out "~%limit: ~S" ,limit))
+       (let* ((,sexpr-start (clone ,start))
+              (,sexpr-end (when (hemlock::form-offset ,sexpr-start 1) ,sexpr-start)))
+         #+sax-debug (when *limited-sexpr-end-debug*
+                       (debug-out "~%sexpr-end: ~S" ,sexpr-end))
+         (if ,sexpr-end
+           (when (mark<= ,sexpr-end ,limit) ,sexpr-end)
+           #+sax-debug (when *limited-sexpr-end-debug* 
+                         (debug-out "~%limited-sexpr-end returning nil - start-mark: ~S" ,start)))))))
+
+(defmacro next-sexpr-start (mark-or-form)
+  (let ((position (gensym))
+        (forward (gensym))
+        (start (gensym))
+        (param (gensym)))
+    ;; evaluate mark-or-form once, only:
+    `(let ((,param ,mark-or-form)) 
+       (when ,param
+         #+sax-debug (when *next-sexpr-start-debug*
+                      (debug-out "~%next-sexpr-start mark-or-form: ~S" ,mark-or-form)
+                      (debug-out "~%next-sexpr-start param: ~S" ,param))
+         (do* ((,position (clone ,param))
+               (,forward (when (hemlock::form-offset ,position 1) ,position)
+                         (when (hemlock::form-offset ,position 1) ,position))
+               (,start (when ,forward (when (hemlock::form-offset ,forward -1) ,forward))
+                       (when ,forward (when (hemlock::form-offset ,forward -1) ,forward))))
+              ((or (null ,start) (mark>= ,start ,param)) 
+               #+sax-debug (when (and *next-sexpr-start-debug* (null ,start)) 
+                            (debug-out "~%next-sexpr-start returning nil"))
+               (if *inc-p*
+                 (when (and ,start (mark< ,start *inc-pos*))
+                   ,start)
+                 ,start))
+           #+sax-debug (when *next-sexpr-start-debug* (debug-out "~%start: ~S" ,start))
+           (hemlock::form-offset ,position 1)
+           #+sax-debug (when *next-sexpr-start-debug* (debug-out "~%(form-offset position 1): ~S" ,position))
+           (cond ((null ,position) 
+                  #+sax-debug (when *next-sexpr-start-debug* (debug-out "~%next-sexpr-start returning nil"))
+                  (return nil))
+                 ((mark<= ,position ,param)
+                  ;; wretched special case: avoid getting stuck:  ie.  (eq ,errsym #.^#$ o )
+                  #+sax-debug (when *next-sexpr-start-debug* (debug-out "~%next-sexpr-start returning (mark-next ,position)"))
+                  (set-storage ,position ,param)
+                  (return (mark-next ,position)))))))))
+
+(defMacro nnext-sexpr-start (mark-or-form)
+  (let ((position (gensym))
+        (forward (gensym))
+        (start (gensym))
+        (param (gensym)))
+    `(let ((,param ,mark-or-form))
+       (when ,param
+         #+sax-debug (when *nnext-sexpr-start-debug*
+                      (debug-out "~%nnext-sexpr-start mark-or-form: ~S" ,mark-or-form)
+                      (debug-out "~%nnext-sexpr-start param: ~S" ,param))
+         (let* ((,position ,param)
+                (,forward (when (hemlock::form-offset ,position 1) ,position))
+                (,start (when ,forward (when (hemlock::form-offset ,forward -1) ,forward))))
+           #+sax-debug (when *nnext-sexpr-start-debug* 
+                        (if (null ,start)
+                          (debug-out "~%nnext-sexpr-start returning nil")
+                          (debug-out "~%nnext-sexpr-start returning: ~S" ,start)))
+           (if *inc-p*
+             (when (and ,start (mark< ,start *inc-pos*))
+               ,start)
+             ,start))))))
+
+(defMacro atom-start (start)
+  (let ((pos (gensym))
+        (char (gensym))
+        (buf-start (gensym)))
+    `(when ,start
+       (let ((,buf-start (buf-start-mark *buf*)))
+         (do* ((,pos ,start (mark-before ,pos))
+               (,char (when (and ,pos (mark>= ,pos ,buf-start))
+                        (mark-char ,pos))
+                      (when (and ,pos (mark>= ,pos ,buf-start))
+                        (mark-char ,pos))))
+              ((or (null ,char) ; ***
+                   (whitespacep ,char) (char= ,char #\() 
+                   (char= ,char #\)) (char= ,char #\"))
+               (if ,pos (mark-after ,pos) ,buf-start)))))))
+
+(defMacro atom-end (s)
+  (let ((start (gensym))
+        (buffer-end-mark (gensym))
+        (pos (gensym))
+        (char (gensym)))
+    `(when ,s
+       (let ((,start (clone ,s))
+             (,buffer-end-mark (buffer-end-mark *buf*)))
+         (do* ((,pos ,start (mark-after ,pos))
+               (,char (when (mark<= ,pos ,buffer-end-mark) (mark-char ,pos))
+                      (when (mark<= ,pos ,buffer-end-mark) (mark-char ,pos))))
+              ((or (null ,char) ; ***
+                   (whitespacep ,char) (char= ,char #\)) (char= ,char #\() 
+                   (char= ,char #\") (char= ,char #\;)) 
+               ,pos))))))
+
+(defun buffer-top-level-sexpr-start (buffer &optional storage)
+  (cond (storage
+         (set-storage storage (buffer-point buffer))
+         (hemlock::top-level-offset storage -1))
+        (t
+         (let ((mark (clone (buffer-point buffer))))
+           (hemlock::top-level-offset mark -1)))))
+
+(defun buffer-top-level-sexpr-end (buffer &optional storage)
+  (cond (storage
+         (set-storage storage (buffer-point buffer))
+         (hemlock::top-level-offset storage 1))
+        (t
+         (let ((mark (clone (buffer-point buffer))))
+           (hemlock::top-level-offset mark 1)))))
+
+
+;;; ----------------------------------------------------------------------------
+;;; Miscellaneous functions and macros.
+;;; ----------------------------------------------------------------------------
+;;;
+(defun pattern-search (mark pattern &optional end)
+  (with-mark ((m mark))
+    (if end 
+      (when (and (find-pattern m pattern) (mark< m end)) m)
+      (when (find-pattern m pattern) m))))
+
+#|
+;;; (buffer-writable buffer) is broken
+(defun writable-p (thing)
+  (declare (ignore thing))
+  t)
+
+(defun writable-path-p (path)
+  (let* ((file-manager (#/defaultManager ns:ns-file-manager))
+         (path (ccl::%make-nsstring path)))
+    (#/isWritableFileAtPath: file-manager path)))
+
+(defMethod writable-p ((hemlock-view hi::hemlock-view))
+  (let ((buffer (hemlock-view-buffer hemlock-view)))
+    (or (not *style-case-p*)
+        (format t "~%view-writable-p: ~S" (buffer-writable buffer))
+        ;; *** broken
+        (buffer-writable buffer))))
+
+(defMethod writable-p ((text-view gui::hemlock-textstorage-text-view))
+  (let* ((hemlock-view (gui::hemlock-view text-view))
+         (buffer (hemlock-view-buffer hemlock-view)))
+    (or (not *style-case-p*)
+        (format t "~%writable-p: ~S" (buffer-writable buffer))
+        (buffer-writable buffer))))
+
+(defMethod writable-p ((window gui::hemlock-frame))
+  (let* ((hemlock-view (gui::hemlock-view window))
+         (buffer (hemlock-view-buffer hemlock-view)))
+    (or (not *style-case-p*)
+        (format t "~%writable-p: ~S" (buffer-writable buffer))
+        (buffer-writable buffer))))
+|#
+
+(defun active-hemlock-window ()
+  "Return the active hemlock-frame."
+  (gui::first-window-satisfying-predicate 
+   #'(lambda (w)
+       (and (typep w 'gui::hemlock-frame)
+            (not (typep w 'gui::hemlock-listener-frame))
+            (#/isKeyWindow w)))))
+
+(defun window-path (w)
+  "Return the window's path."
+  (let* ((pane (slot-value w 'gui::pane))
+         (hemlock-view (when pane (gui::text-pane-hemlock-view pane)))
+         (buffer (when hemlock-view (hi::hemlock-view-buffer hemlock-view))))
+    (when buffer (hi::buffer-pathname buffer))))
+
+(defmacro char-eolp (char) 
+  `(member ,char '(#\return #\linefeed #\newline ,(code-char #x2028) ,(code-char #x2029))))
+
+(defun ed-beep () (#_NSBeep)) ; *** this beeper doesn't beep
+
+(define-symbol-macro *listener-output* (hemlock-ext::top-listener-output-stream))
+
+(defun listener-msg (string &rest args)
+  (apply 'format *listener-output* string args))
+
+(defun selection-marks (text-view)
+  (let ((selection (#/selectedRange text-view))
+        start end)
+    (when selection
+      (let ((length (ns:ns-range-length selection))
+            (location (ns:ns-range-location selection)))
+        (unless (zerop length)
+          (setf start (move-to-absolute-position (buf-start-mark) location))
+          (setf end (character-offset (clone start) length)))))
+    (values start end)))
+
+(defun key-event= (k1 k2)
+  (and (= (hi::key-event-keysym k1) (hi::key-event-keysym k2))
+       (= (hi::key-event-bits k1) (hi::key-event-bits k2))))
+
+(defmethod hemlock-update ((view hi:hemlock-view) start end &optional count)
+  (let* ((buffer (hemlock-view-buffer view))
+         (document (hi::buffer-document buffer))
+         (text-storage (if document (slot-value document 'gui::textstorage)))
+         (location (mark-absolute-position start))
+         (length (or count (- (mark-absolute-position end) location))))
+;         (count (hemlock::count-characters (region start end))))
+    #+sax-debug (when *hemlock-update-debug*
+                   (debug-out "~%~%~S" 'hemlock-update)
+                   (debug-out "~%start: ~S" start)
+                   (debug-out "~%end: ~S" end)
+                   (debug-out "~%location: ~S" location)
+                   (debug-out "~%length: ~S" length))
+    ;;; 0 is the fontnum
+    (gui::perform-edit-change-notification 
+     text-storage
+     (objc:@selector #/noteHemlockAttrChangeAtPosition:length:)
+     location length 0)))        
+
+(defmethod hemlock-update ((frame gui::hemlock-frame) start end &optional count)
+  (let ((hemlock-view (gui::hemlock-view frame)))
+    (hemlock-update hemlock-view start end count)))
+
+(defMacro attribute-dictionary (var) `(car ,var)) 
+
+(defMacro style-case (var) `(cdr ,var))
+
+(defun set-style-attributes (dictionary &optional (start (buf-start-mark))
+                                        (end (buf-end-mark)))
+  #+sax-debug (when *set-style-attributes-debug* 
+                 (debug-out "~%~%~S" 'set-style-attributes)
+                 (debug-out "~%dictionary: ~S" dictionary)
+                 (debug-out "~%start: ~S" start)
+                 (debug-out "~%end: ~S" end))
+
+  (ns:with-ns-range (range)
+    (let* ((location (mark-absolute-position start))
+           (length (- (mark-absolute-position end) location)))
+      (setf (ns:ns-range-location range) location)
+      (setf (ns:ns-range-length range) length)
+      ;; Remove all temporary attributes from the character range
+      (#/removeTemporaryAttribute:forCharacterRange:
+       *layout* #&NSForegroundColorAttributeName range)
+      (#/removeTemporaryAttribute:forCharacterRange:
+       *layout* #&NSUnderlineStyleAttributeName range)
+      (#/addTemporaryAttributes:forCharacterRange: *layout* dictionary range))))
+
+(defun set-generic-text-style (text-view &optional (start (buf-start-mark)) (end (buf-end-mark)))
+  ;; eliminate paren highlighting:
+  (let* ((begin (mark-absolute-position start))
+         (count (- (mark-absolute-position end) begin)))
+    (when (and begin count)
+      (ns:with-ns-range  (char-range begin count)
+        (let* ((layout (#/layoutManager text-view)))
+          (#/removeTemporaryAttribute:forCharacterRange: 
+           layout #&NSBackgroundColorAttributeName 
+           char-range)))))
+  ;; *** maybe chuck this:
+  (set-style-attributes  (attribute-dictionary *generic-text-style*) start end))
+
+(defun downcase-region (start end)
+  ;; downcases all nonescaped characters in region
+  (filter-region #'string-downcase (region start end)))
+
+(defun upcase-region (start end)
+  (filter-region #'string-upcase (region start end)))
+
+(defun capitalize-region (start end)
+  (filter-region #'string-capitalize (region start end)))
+
+(defMethod set-style-case ((case (eql :down)) start end)
+  (downcase-region start end))
+
+(defMethod set-style-case ((case (eql :up)) start end)
+  ;; don't use eupcase region...
+  (upcase-region start end))
+
+(defMethod set-style-case ((case (eql :unchanged)) start end)
+  (declare (ignore start end)) ())
+
+(defMethod set-style-case ((case (eql :cap)) start end)
+  (capitalize-region start end))
+
+(defMethod set-style-case ((case (eql :cap3)) start end)
+  (set-style-case :down start end)
+  (capitalize-region (mark-offset start 3) (mark-offset start 4)))
+
+(defMethod set-style-case ((case (eql :cap03)) start end)
+  (set-style-case :down start end)
+  (capitalize-region start end)
+  (capitalize-region (mark-offset start 3) (mark-offset start 4)))
+
+(defMethod set-style-case ((case (eql :cap8)) start end)
+  (set-style-case :down start end)
+  (capitalize-region (mark-offset start 8) (mark-offset start 9)))
+
+(defMethod set-style-case ((case (eql :cap12)) start end)
+  (set-style-case :down start end)
+  (capitalize-region (mark-offset start 12) (mark-offset start 13)))
+
+(defMacro style-region (style start end  &optional (set-case-p t))
+  "This is the basic styling macro that calls SET-STYLE-ATTRIBUTES and SET-STYLE-CASE."
+  `(progn
+     #+sax-debug (when *style-region-debug* 
+                  (debug-out "~%~%~S" 'style-region)
+                  (debug-out "~%start: ~S" ,start)
+                  (debug-out "~%end: ~S" ,end)
+                  (debug-out "~%style: ~S" ,style)
+                  (debug-out "~%set-case-p: ~S" ,set-case-p)
+                  (debug-out "~%*paste-p*: ~S" *paste-p*)
+                  (debug-out "~%*paste-start*: ~S" *paste-start*)
+                  (debug-out "~%*paste-end*: ~S" *paste-end*)
+                  (debug-out "~%*inc-p*: ~S" *inc-p*)
+                  (debug-out "~%*inc-pos*: ~S" *inc-pos*))
+     (when (or (and *inc-p* (not *paste-p*)
+                    (mark>= *inc-pos* ,start)
+                    (mark<= *inc-pos* ,end))
+               (not *inc-p*)
+               (and *paste-p*
+                    (mark>= ,start *paste-start*)
+                    (mark<= ,end *paste-end*)))
+
+       (when (and *style-case-p* ,set-case-p (style-case ,style))
+         #+sax-debug (when *style-region-debug*
+                      (debug-out "~%set-style-case, case: ~S" (style-case ,style))
+                      (debug-out "~%set-style-case, region: ~S" (region ,start ,end)))
+           (set-style-case (style-case ,style) ,start ,end))
+
+       (cond ((and *inc-p* (not *paste-p*))
+              ;; Don't set attributes when doing incremental. We are
+              ;; inside #/beginEditing, #/endEditing.  Save the values.
+              #+sax-debug (when *style-region-debug* 
+                            (debug-out "~%~%*** setting *form-style* for: ~S ***" 
+                                       (region-to-string (region ,start ,end))))
+              (setq *form-style* ,style
+                    *form-start* ,start
+                    *form-end* ,end))
+             (t
+              #+sax-debug (when *style-region-debug*
+                             (if (equalp ,style *generic-text-style*)
+                               (debug-out "~%*** styling-region-generically: ~S ***"
+                                          (region-to-string (region ,start ,end)))
+                               (debug-out "~%*** styling-region: ~S ***"
+                                          (region-to-string (region ,start ,end))))
+                             (debug-out "~%style: ~S" ,style))
+              (set-style-attributes (attribute-dictionary ,style) ,start ,end))))))
+
+
Index: /trunk/contrib/foy/syntax-styling/syntax-styling.lisp
===================================================================
--- /trunk/contrib/foy/syntax-styling/syntax-styling.lisp	(revision 13946)
+++ /trunk/contrib/foy/syntax-styling/syntax-styling.lisp	(revision 13946)
@@ -0,0 +1,29 @@
+
+;;; syntax-styling.lisp 
+
+(in-package :common-lisp-user)
+
+;;; (pushnew :sax-debug *features*)
+
+(unless (member "SYNTAX-STYLING" *modules* :test #'string-equal)
+  (eval-when (:load-toplevel :execute)
+    (defParameter *syntax-styling-directory*
+      (make-pathname :name nil :type nil :defaults (if *load-pathname* 
+                                                     *load-pathname*
+                                                     *loading-file-source-file*)))
+    (defParameter *syntax-styling-files* 
+      (list #+sax-debug (merge-pathnames ";testing-specials.lisp" *syntax-styling-directory*)
+            (merge-pathnames ";syntax-styling-specials.lisp" *syntax-styling-directory*)
+            (merge-pathnames ";syntax-styling-comments.lisp" *syntax-styling-directory*)
+            (merge-pathnames ";syntax-styling-1.lisp" *syntax-styling-directory*)
+            (merge-pathnames ";syntax-styling-2.lisp" *syntax-styling-directory*)
+            #+sax-debug (merge-pathnames ";testing1.lisp" *syntax-styling-directory*)
+            #+sax-debug (merge-pathnames ";testing2.lisp" *syntax-styling-directory*)
+            )))
+ 
+(dolist (file *syntax-styling-files*)
+  (load file))
+
+(provide :syntax-styling)
+
+)
Index: /trunk/contrib/foy/window-parking-cm/window-parking-cm.lisp
===================================================================
--- /trunk/contrib/foy/window-parking-cm/window-parking-cm.lisp	(revision 13946)
+++ /trunk/contrib/foy/window-parking-cm/window-parking-cm.lisp	(revision 13946)
@@ -0,0 +1,22 @@
+
+;;; cl-documentation.lisp 
+
+(in-package :common-lisp-user)
+
+(unless (member "WINDOW-PARKING-CM" *modules* :test #'string-equal)
+  
+(eval-when (:load-toplevel :execute)
+  (defParameter *window-parking-directory*
+    (make-pathname :name nil :type nil :defaults (if *load-pathname* 
+                                                     *load-pathname*
+                                                     *loading-file-source-file*)))
+  (defParameter *window-parking-files* 
+    (list (merge-pathnames ";window-parking.lisp" *window-parking-directory*)
+          (merge-pathnames ";window-parking-dialogs.lisp" *window-parking-directory*))))
+ 
+(dolist (file *window-parking-files*)
+  (load file))
+
+(provide :window-parking-cm)
+
+)
Index: /trunk/contrib/foy/window-parking-cm/window-parking-dialogs.lisp
===================================================================
--- /trunk/contrib/foy/window-parking-cm/window-parking-dialogs.lisp	(revision 13946)
+++ /trunk/contrib/foy/window-parking-cm/window-parking-dialogs.lisp	(revision 13946)
@@ -0,0 +1,321 @@
+;;;-*- Mode: Lisp; Package: WINDOW-PARKING -*-
+
+;;; ----------------------------------------------------------------------------
+;;; 
+;;;      window-parking-dialogs.lisp
+;;;
+;;;      copyright (c) 2009 Glen Foy
+;;;      (Permission is granted to Clozure Associates to distribute this file.)
+;;;
+;;;      Dialogs for defining and deleting parking spots.
+;;;
+;;;      This software is offered "as is", without warranty of any kind.
+;;;
+;;;      Mod History (most recent edit first)
+;;;      9/9/9  first cut
+;;;
+;;; ----------------------------------------------------------------------------
+
+(in-package "WINDOW-PARKING")
+
+(defparameter *dps-dialog* nil "The define-parking-spot-dialog instance.")
+(defparameter *del-dialog* nil "The delete-parking-spot-dialog instance.")
+
+
+;;; ----------------------------------------------------------------------------
+;;;
+(defclass DEFINE-PARKING-SPOT-DIALOG (ns:ns-window)
+  ((path :initform nil :accessor psd-path)
+   (okay-button :initform nil :accessor psd-okay-button)
+   (function-key-buttons :initform nil :accessor psd-function-key-buttons)
+   (function-key-matrix :initform nil :accessor psd-function-key-matrix))
+  (:documentation "A dialog for associating a window size and position with a function key.")
+  (:metaclass ns:+ns-object))
+
+(defmethod selected-function-key ((d define-parking-spot-dialog))
+  (read-from-string (ccl::lisp-string-from-nsstring 
+                     (#/title (#/selectedCell (psd-function-key-matrix d))))))
+
+(objc:defmethod (#/okayAction: :void) ((d define-parking-spot-dialog) (sender :id))
+  (declare (ignore sender))
+  (#/stopModalWithCode: ccl::*nsapp* 0))
+
+(objc:defmethod (#/cancelAction: :void) ((d define-parking-spot-dialog) (sender :id))
+  (declare (ignore sender))
+  (#/stopModalWithCode: ccl::*nsapp* 1))
+
+(defun open-define-parking-spot-dialog (path &optional (function-key 1))
+  "Open the define-parking-spot-dialog for PATH."
+  (let* ((path-string (#/initWithString:attributes: (#/alloc ns:ns-attributed-string) 
+                                                    (ccl::%make-nsstring 
+                                                     (format nil "~A" path))
+                                                    cmenu::*tool-key-dictionary*)))
+    (flet ((selectFunctionKey (num)
+             (dolist (button (psd-function-key-buttons *dps-dialog*))
+               (let ((key (read-from-string (ccl::lisp-string-from-nsstring (#/title button)))))
+                 (when (= num key)
+                   (#/selectCell: (psd-function-key-matrix *dps-dialog*) button)
+                   (return))))))
+      (cond (*dps-dialog*
+             (#/setStringValue: (psd-path *dps-dialog*) path-string)
+             (selectFunctionKey function-key)
+             (#/makeKeyAndOrderFront: *dps-dialog* nil)
+             (let ((ret (#/runModalForWindow: ccl::*nsapp* *dps-dialog*)))
+               (#/close *dps-dialog*)
+               (when (zerop ret) (selected-function-key *dps-dialog*))))
+            (t
+             (let ((dialog (#/alloc define-parking-spot-dialog)))
+               (setq *dps-dialog* dialog)
+               (ns:with-ns-rect (r 10 300 600 140)
+                 (#/initWithContentRect:styleMask:backing:defer: 
+                  dialog
+                  r
+                  #$NSTitledWindowMask 
+                  #$NSBackingStoreBuffered
+                  #$NO))
+               (dolist (item (get-items dialog))
+                 (#/addSubview: (#/contentView dialog) item))
+               (#/setTitle: dialog #@"Define Parking Spot")
+               (#/setReleasedWhenClosed: dialog nil)
+               (#/setDefaultButtonCell: dialog (psd-okay-button dialog))
+               (#/center dialog)
+               (#/setStringValue: (psd-path dialog) path-string)
+               (selectFunctionKey function-key)
+               (#/makeKeyAndOrderFront: dialog nil)
+               (let ((ret (#/runModalForWindow: ccl::*nsapp* dialog)))
+                 (#/close dialog)
+                 (when (zerop ret) (selected-function-key dialog)))))))))
+
+(defmethod get-items ((d define-parking-spot-dialog))
+  (append
+   (make-prompt-field)
+   (make-path-field d)
+   (make-function-key-items d)
+   (make-buttons d)))
+
+(defun make-prompt-field ()
+  "Create the prompt text-field."
+  (list
+   (let* ((string (#/initWithString:attributes: 
+                   (#/alloc ns:ns-attributed-string) 
+                   #@"Save the front window size, position and function key:"
+                   cmenu::*tool-label-dictionary*))
+          (title (#/alloc ns:ns-text-field)))
+     (ns:with-ns-rect (frame 15 90 410 32)
+       (#/initWithFrame: title frame))
+     (#/setEditable: title nil)
+     (#/setDrawsBackground: title nil)
+     (#/setBordered: title nil)
+     (#/setStringValue: title string)
+     title)))
+
+(defun make-path-field (dialog)
+  "Create the path text-field."
+  (list
+   (setf (psd-path dialog)
+         (let* ((string (#/initWithString:attributes: 
+                         (#/alloc ns:ns-attributed-string) 
+                         #@""
+                         cmenu::*tool-doc-dictionary*))
+                (title (#/alloc ns:ns-text-field)))
+           (ns:with-ns-rect (frame 15 72 580 22)
+             (#/initWithFrame: title frame))
+           (#/setEditable: title nil)
+           (#/setDrawsBackground: title nil)
+           (#/setBordered: title nil)
+           (#/setStringValue: title string)
+           title))))
+
+(defun make-function-key-items (dialog)
+  (list
+   (let* ((string (#/initWithString:attributes: 
+                   (#/alloc ns:ns-attributed-string) 
+                   #@"Associated Function Key:"
+                   cmenu::*tool-label-dictionary*))
+          (title (#/alloc ns:ns-text-field)))
+     (ns:with-ns-rect (frame 15 40 200 32)
+       (#/initWithFrame: title frame))
+     (#/setEditable: title nil)
+     (#/setDrawsBackground: title nil)
+     (#/setBordered: title nil)
+     (#/setStringValue: title string)
+     title)
+   (setf (psd-function-key-matrix dialog)
+         (ns:with-ns-rect (frame 190 40 350 32)
+           (let* ((matrix (#/alloc ns:ns-matrix))
+                  (prototype (#/init (#/alloc ns:ns-button-cell)))
+                  buttons cell-array)
+             (#/setTitle: prototype #@"7     ")
+             (#/setButtonType: prototype #$NSRadioButton)
+             (#/initWithFrame:mode:prototype:numberOfRows:numberOfColumns: 
+              matrix frame #$NSRadioModeMatrix prototype 1 7)
+             (setq cell-array (#/cells matrix))
+             (#/setTitle: (#/objectAtIndex: cell-array 0) #@"1")
+             (push (#/objectAtIndex: cell-array 0) buttons)
+             (#/setTitle: (#/objectAtIndex: cell-array 1) #@"2")
+             (push (#/objectAtIndex: cell-array 1) buttons)
+             (#/setTitle: (#/objectAtIndex: cell-array 2) #@"3")
+             (push (#/objectAtIndex: cell-array 2) buttons)
+             (#/setTitle: (#/objectAtIndex: cell-array 3) #@"4")
+             (push (#/objectAtIndex: cell-array 3) buttons)
+             (#/setTitle: (#/objectAtIndex: cell-array 4) #@"5")
+             (push (#/objectAtIndex: cell-array 4) buttons)
+             (#/setTitle: (#/objectAtIndex: cell-array 5) #@"6")
+             (push (#/objectAtIndex: cell-array 5) buttons)
+             (#/setTitle: (#/objectAtIndex: cell-array 6) #@"7")
+             (push (#/objectAtIndex: cell-array 6) buttons)
+             (setf (psd-function-key-buttons dialog) buttons)
+             matrix)))))
+
+(defun make-buttons (dialog)
+  "Construct the buttons."
+  (flet ((make-button (title x-coord y-coord x-dim y-dim action)
+           (let ((button (#/alloc ns:ns-button)))
+             (ns:with-ns-rect (frame x-coord y-coord x-dim y-dim)
+               (#/initWithFrame: button frame))
+             (#/setButtonType: button #$NSMomentaryPushInButton)
+             (#/setBezelStyle: button #$NSRoundedBezelStyle)
+             (#/setTitle: button title)
+             (#/setTarget: button dialog)
+             (#/setAction: button action)
+             button)))
+    (list
+     (setf (psd-okay-button dialog)
+           (make-button #@"Okay" 500 10 80 32
+                        (ccl::@selector "okayAction:")))
+     (make-button #@"Cancel" 400 10 90 32
+                  (ccl::@selector "cancelAction:")))))
+
+
+;;; ----------------------------------------------------------------------------
+;;;
+(defclass DELETE-PARKING-SPOT-DIALOG (ns:ns-window)
+  ((path :initform nil :accessor psd-path)
+   (okay-button :initform nil :accessor psd-okay-button)
+   (function-key-buttons :initform nil :accessor psd-function-key-buttons)
+   (function-key-matrix :initform nil :accessor psd-function-key-matrix))
+  (:documentation "A dialog for deleting parking spots.")
+  (:metaclass ns:+ns-object))
+
+(defmethod selected-function-key ((d delete-parking-spot-dialog))
+  (read-from-string (ccl::lisp-string-from-nsstring 
+                     (#/title (#/selectedCell (psd-function-key-matrix d))))))
+
+(objc:defmethod (#/deleteAction: :void) ((d delete-parking-spot-dialog) (sender :id))
+  (declare (ignore sender))
+  (#/stopModalWithCode: ccl::*nsapp* 0))
+
+(objc:defmethod (#/cancelAction: :void) ((d delete-parking-spot-dialog) (sender :id))
+  (declare (ignore sender))
+  (#/stopModalWithCode: ccl::*nsapp* 1))
+
+(defun open-delete-parking-spot-dialog ()
+  "Open the delete-parking-spot-dialog for PATH."
+  (cond (*del-dialog*
+         (#/makeKeyAndOrderFront: *del-dialog* nil)
+         (let ((ret (#/runModalForWindow: ccl::*nsapp* *del-dialog*)))
+           (#/close *del-dialog*)
+           (when (zerop ret) (selected-function-key *del-dialog*))))
+        (t
+         (let ((dialog (#/alloc delete-parking-spot-dialog)))
+           (setq *del-dialog* dialog)
+           (ns:with-ns-rect (r 10 300 600 140)
+             (#/initWithContentRect:styleMask:backing:defer: 
+              dialog
+              r
+              #$NSTitledWindowMask 
+              #$NSBackingStoreBuffered
+              #$NO))
+           (dolist (item (get-delete-items dialog))
+             (#/addSubview: (#/contentView dialog) item))
+           (#/setTitle: dialog #@"Delete Parking Spot")
+           (#/setReleasedWhenClosed: dialog nil)
+           (#/setDefaultButtonCell: dialog (psd-okay-button dialog))
+           (#/center dialog)
+           (#/makeKeyAndOrderFront: dialog nil)
+           (let ((ret (#/runModalForWindow: ccl::*nsapp* dialog)))
+             (#/close dialog)
+             (when (zerop ret) (selected-function-key dialog)))))))
+
+(defmethod get-delete-items ((d delete-parking-spot-dialog))
+  (append
+   (make-delete-prompt-field)
+   (make-delete-function-key-items d)
+   (make-delete-buttons d)))
+
+(defun make-delete-prompt-field ()
+  "Create the prompt text-field."
+  (list
+   (let* ((string (#/initWithString:attributes: 
+                   (#/alloc ns:ns-attributed-string) 
+                   #@"Click the number of the parking spot you want to delete:"
+                   cmenu::*tool-label-dictionary*))
+          (title (#/alloc ns:ns-text-field)))
+     (ns:with-ns-rect (frame 15 90 410 32)
+       (#/initWithFrame: title frame))
+     (#/setEditable: title nil)
+     (#/setDrawsBackground: title nil)
+     (#/setBordered: title nil)
+     (#/setStringValue: title string)
+     title)))
+
+(defun make-delete-function-key-items (dialog)
+  (list
+   (let* ((string (#/initWithString:attributes: 
+                   (#/alloc ns:ns-attributed-string) 
+                   #@"Associated Function Key:"
+                   cmenu::*tool-label-dictionary*))
+          (title (#/alloc ns:ns-text-field)))
+     (ns:with-ns-rect (frame 15 40 200 32)
+       (#/initWithFrame: title frame))
+     (#/setEditable: title nil)
+     (#/setDrawsBackground: title nil)
+     (#/setBordered: title nil)
+     (#/setStringValue: title string)
+     title)
+   (setf (psd-function-key-matrix dialog)
+         (ns:with-ns-rect (frame 190 40 350 32)
+           (let* ((matrix (#/alloc ns:ns-matrix))
+                  (prototype (#/init (#/alloc ns:ns-button-cell)))
+                  buttons cell-array)
+             (#/setTitle: prototype #@"7     ")
+             (#/setButtonType: prototype #$NSRadioButton)
+             (#/initWithFrame:mode:prototype:numberOfRows:numberOfColumns: 
+              matrix frame #$NSRadioModeMatrix prototype 1 7)
+             (setq cell-array (#/cells matrix))
+             (#/setTitle: (#/objectAtIndex: cell-array 0) #@"1")
+             (push (#/objectAtIndex: cell-array 0) buttons)
+             (#/setTitle: (#/objectAtIndex: cell-array 1) #@"2")
+             (push (#/objectAtIndex: cell-array 1) buttons)
+             (#/setTitle: (#/objectAtIndex: cell-array 2) #@"3")
+             (push (#/objectAtIndex: cell-array 2) buttons)
+             (#/setTitle: (#/objectAtIndex: cell-array 3) #@"4")
+             (push (#/objectAtIndex: cell-array 3) buttons)
+             (#/setTitle: (#/objectAtIndex: cell-array 4) #@"5")
+             (push (#/objectAtIndex: cell-array 4) buttons)
+             (#/setTitle: (#/objectAtIndex: cell-array 5) #@"6")
+             (push (#/objectAtIndex: cell-array 5) buttons)
+             (#/setTitle: (#/objectAtIndex: cell-array 6) #@"7")
+             (push (#/objectAtIndex: cell-array 6) buttons)
+             (setf (psd-function-key-buttons dialog) buttons)
+             matrix)))))
+
+(defun make-delete-buttons (dialog)
+  "Construct the buttons."
+  (flet ((make-button (title x-coord y-coord x-dim y-dim action)
+           (let ((button (#/alloc ns:ns-button)))
+             (ns:with-ns-rect (frame x-coord y-coord x-dim y-dim)
+               (#/initWithFrame: button frame))
+             (#/setButtonType: button #$NSMomentaryPushInButton)
+             (#/setBezelStyle: button #$NSRoundedBezelStyle)
+             (#/setTitle: button title)
+             (#/setTarget: button dialog)
+             (#/setAction: button action)
+             button)))
+    (list
+     (setf (psd-okay-button dialog)
+           (make-button #@"Delete" 500 10 80 32
+                        (ccl::@selector "deleteAction:")))
+     (make-button #@"Cancel" 400 10 90 32
+                  (ccl::@selector "cancelAction:")))))
+
Index: /trunk/contrib/foy/window-parking-cm/window-parking.lisp
===================================================================
--- /trunk/contrib/foy/window-parking-cm/window-parking.lisp	(revision 13946)
+++ /trunk/contrib/foy/window-parking-cm/window-parking.lisp	(revision 13946)
@@ -0,0 +1,556 @@
+;;;-*- Mode: Lisp; Package: WINDOW-PARKING -*-
+
+;;; ----------------------------------------------------------------------------
+;;; 
+;;;      window-parking.lisp
+;;;
+;;;      copyright (c) 2009 Glen Foy
+;;;      (Permission is granted to Clozure Associates to distribute this file.)
+;;;
+;;;      This code provides a Hemlock window manager and is part of the Context-Menu 
+;;;      tool set.  See the ReadMe file for details.
+;;;
+;;;      This software is offered "as is", without warranty of any kind.
+;;;
+;;;      Mod History (most recent edit first)
+;;;      9/17/9 Fix bogus move after #/saveDocument.
+;;;      9/16/9 Park new window.
+;;;      9/9/9  first cut
+;;;
+;;; ----------------------------------------------------------------------------
+
+
+(defpackage "WINDOW-PARKING" (:nicknames "WP") (:use :cl :ccl))
+(in-package "WINDOW-PARKING")
+
+(require :context-menu-cm)
+(require :list-definitions-cm)
+
+(defparameter *window-parker* nil "The window-parker instance.")
+(defparameter *window-parking-menu* nil "The window-parking-menu instance.")
+(defParameter *park-p* t "To park or not to park.")
+
+;;; ----------------------------------------------------------------------------
+;;;
+(defClass WINDOW-PARKING-MENU (ns:ns-menu) 
+  ((tool-menu :initform nil :accessor tool-menu)
+   (doc-path :initform (merge-pathnames ";ReadMe.rtf" cl-user::*window-parking-directory*) :reader doc-path))
+  (:documentation "A menu for adding and deleting parking spots.")
+  (:metaclass ns:+ns-object))
+
+;;; This can be called to add a new parking spot or adjust an existing spot.
+(objc:defmethod (#/defineAction: :void) ((m window-parking-menu) (sender :id))
+  (declare (ignore sender))
+  (let* ((window (cmenu:active-hemlock-window))
+         (path (when window (cmenu:window-path window)))
+         ;; Possibly a re-definition.
+         (current-function-key (get-function-key *window-parker* window))
+         (defined-function-key
+             (when path
+               (if current-function-key
+                 (open-define-parking-spot-dialog path current-function-key)
+                 (open-define-parking-spot-dialog path)))))
+    (when defined-function-key
+      (cond (current-function-key 
+             (cond ((= current-function-key defined-function-key)
+                    ;; Adjusting an existing spot.
+                    (let ((spot (parking-spot-with-function-key *window-parker* current-function-key)))
+                      (init-parking-spot-values spot window current-function-key))
+                    (cmenu:echo-msg "Parking spot ~S modified." current-function-key))
+                   (t
+                    (vacate-current-location *window-parker* window)
+                    (add-parking-spot *window-parker* window defined-function-key)
+                    (cmenu:echo-msg "Parking spot ~S defined." current-function-key))))
+            (t
+             (add-parking-spot *window-parker* window defined-function-key))
+            (cmenu:echo-msg "Parking spot ~S defined." defined-function-key)))))
+
+(objc:defmethod (#/deleteAction: :void) ((m window-parking-menu) (sender :id))
+  (declare (ignore sender))
+  (let ((function-key (open-delete-parking-spot-dialog)))
+    (when function-key
+      (delete-parking-spot *window-parker* function-key))))
+
+(objc:defmethod (#/update :void) ((m window-parking-menu))
+  (cmenu:update-tool-menu m (tool-menu m))
+  (call-next-method))
+
+(defmethod initialize-instance :after ((m window-parking-menu) &key)
+  (setf (tool-menu m) (cmenu:add-default-tool-menu m :doc-file (doc-path m)))
+  (flet ((create-menu-item (name action)
+           (let ((menu-item (make-instance 'ns:ns-menu-item))
+                 (attributed-string (#/initWithString:attributes:
+                                     (#/alloc ns:ns-attributed-string) 
+                                     (ccl::%make-nsstring name)
+                                     cmenu:*hemlock-menu-dictionary*)))
+             (#/setAttributedTitle: menu-item attributed-string)
+             (#/setAction: menu-item action)
+             (#/setTarget: menu-item  m)
+             (#/addItem: m menu-item))))
+    (create-menu-item "Define Parking Spot..." 
+                      (ccl::@selector "defineAction:"))
+    (create-menu-item "Delete Parking Spot..." 
+                      (ccl::@selector "deleteAction:"))))
+  
+(setq *window-parking-menu* (make-instance 'window-parking-menu))
+
+(defun get-window-parking-menu (view event) 
+  (declare (ignore view event))
+  *window-parking-menu*)
+
+(cmenu:register-tool "Window-Parking-CM" #'get-window-parking-menu)
+
+
+;;; ----------------------------------------------------------------------------
+;;;
+(defclass PARKABLE-HEMLOCK-FRAME (gui::hemlock-frame)
+  ((parked-p :initform nil :accessor parked-p)
+   (front-p :initform nil :accessor front-p))
+  (:metaclass ns:+ns-object))
+
+(defmethod init-parking ((w parkable-hemlock-frame))
+  (setf (parked-p w) nil)
+  (setf (front-p w) nil))
+
+(defmethod h-position ((w parkable-hemlock-frame))
+  (let ((rect (#/frame w)))
+    (pref rect :<NSR>ect.origin.x)))
+
+(defmethod v-position ((w parkable-hemlock-frame))
+  (let ((rect (#/frame w)))
+    (pref rect :<NSR>ect.origin.y)))
+
+(defmethod h-dimension ((w parkable-hemlock-frame))
+  (let ((rect (#/frame w)))
+    (pref rect :<NSR>ect.size.width)))
+
+(defmethod v-dimension ((w parkable-hemlock-frame))
+  (let ((rect (#/frame w)))
+    (pref rect :<NSR>ect.size.height)))
+
+(objc:defmethod (#/close :void) ((w parkable-hemlock-frame))
+  (vacate-current-location *window-parker* w)
+  (call-next-method))
+
+(defmethod modified-p ((w parkable-hemlock-frame))
+  (when w
+    (let* ((pane (slot-value w 'gui::pane))
+           (hemlock-view (when pane (gui::text-pane-hemlock-view pane)))
+           (buffer (when hemlock-view (hi::hemlock-view-buffer hemlock-view))))
+      (when buffer
+        (hi::buffer-modified buffer)))))
+
+(defmethod print-object ((w parkable-hemlock-frame) stream)
+  (format stream "<parkable-hemlock-frame: ~S>" (namestring (cmenu:window-path w))))
+
+;;; This is a work-around for some odd #/saveDocument behavior:
+;;; Why is the frame being set on a save operation?
+(objc:defmethod (#/saveDocument: :void) ((self gui::hemlock-editor-document) (sender :id))
+  (let* ((url (#/fileURL self))
+         (path (ccl::lisp-string-from-nsstring (#/path url)))
+         (window (cmenu:window-with-path path)))
+    (when window (init-parking window))
+    (call-next-method sender)
+    (when window (setf (parked-p window) t))))
+
+;;; ----------------------------------------------------------------------------
+;;; *** redefinition ***
+;;; Need the equivalent of: (setf ccl::*default-editor-class* 'parkable-hemlock-frame)
+(defun gui::new-hemlock-document-window (class)
+  (let* ((w (gui::new-cocoa-window :class (if (or (eq class 'gui::hemlock-listener-frame)
+                                                  (eq class (find-class 'gui::hemlock-listener-frame)))
+                                            'gui::hemlock-listener-frame
+                                            'parkable-hemlock-frame)
+                                   :auto-display t
+                                   :activate nil))
+         (echo-area-height (+ 1 (gui::size-of-char-in-font gui::*editor-font*))))
+      (values w (gui::add-pane-to-window w :reserve-below echo-area-height))))
+
+(objc:defmethod (#/makeKeyAndOrderFront: :void) ((w parkable-hemlock-frame) (sender :id))
+  (setf (front-p w) t)
+  (call-next-method sender))
+
+(objc:defmethod (#/setFrame:display: :void) ((w parkable-hemlock-frame) (rect :<NSR>ect) (display-p :<BOOL>))
+ (cond ((parked-p w)
+         (call-next-method rect display-p))
+        (t
+         (when (front-p w) (setf (parked-p w) t))
+         (multiple-value-bind (h-position v-position h-dimension v-dimension)
+                              (park *window-parker* w)
+           (if (and h-position v-position h-dimension v-dimension)
+             (ns:with-ns-rect (r h-position v-position h-dimension v-dimension)
+               (call-next-method r display-p))
+             (call-next-method rect display-p))))))
+
+;;; ----------------------------------------------------------------------------
+;;;
+(defClass PARKING-SPOT ()
+  ((h-dimension :initform nil :initarg :h-dimension :accessor ps-h-dimension)
+   (v-dimension :initform nil :initarg :v-dimension :accessor ps-v-dimension)
+   (h-position :initform nil :initarg :h-position :accessor ps-h-position)
+   (v-position :initform nil :initarg :v-position :accessor ps-v-position)
+   (tenant :initform nil :initarg :tenant :accessor ps-tenant)
+   (function-key :initform nil :initarg :function-key :accessor ps-function-key))
+  (:documentation "Parking spot position, size, tenant and function key information."))
+
+(defMethod initialize-instance :after ((ps parking-spot) &key window 
+                                       function-key h-dimension v-dimension
+                                       h-position v-position)
+  (cond ((and h-dimension v-dimension h-position v-position function-key)
+         (setf (ps-tenant ps) window)
+         (setf (ps-h-dimension ps) h-dimension)
+         (setf (ps-v-dimension ps) v-dimension)
+         (setf (ps-h-position ps) h-position)
+         (setf (ps-v-position ps) v-position)
+         (setf (ps-function-key ps) function-key))
+        ((and window function-key)
+         (init-parking-spot-values ps window function-key))
+        (t
+         (error "Bogus condition in parking-spot i-i :after"))))
+
+(defMethod init-parking-spot-values ((ps parking-spot) window function-key)
+  (setf (ps-tenant ps) window)
+  (setf (ps-h-dimension ps) (h-dimension window))
+  (setf (ps-v-dimension ps) (v-dimension window))
+  (setf (ps-h-position ps) (h-position window))
+  (setf (ps-v-position ps) (v-position window))
+  (setf (ps-function-key ps) function-key))
+
+(defMethod parking-spot-on-screen-p ((ps parking-spot) &optional window)
+  (let* ((screen (if window 
+                   (#/screen window)
+                   (#/mainScreen ns:ns-screen)))
+         (screen-rect (if (%null-ptr-p screen)
+                        (#/visibleFrame (#/mainScreen ns:ns-screen))
+                        (#/visibleFrame screen)))
+         (screen-left (pref screen-rect :<NSR>ect.origin.x))
+         (screen-right (+ screen-left (pref screen-rect :<NSR>ect.size.width)))
+         (screen-bottom (pref screen-rect :<NSR>ect.origin.y))
+         (screen-top (+ screen-bottom (pref screen-rect :<NSR>ect.size.height))))
+    (and (>= (ps-h-position ps) screen-left)
+         (<= (+ (ps-h-position ps) (ps-h-dimension ps)) screen-right)
+         (>= (ps-v-position ps) screen-bottom)
+         (<= (+ (ps-v-position ps) (ps-v-dimension ps)) screen-top))))
+
+(defMethod print-object ((ps parking-spot) stream)
+  (format stream "<~a ~a ~a>" (type-of ps) (ps-function-key ps)
+          (if (ps-tenant ps) (ps-tenant ps) "empty")))
+
+(defMethod apply-parking-spot-values ((ps parking-spot) window)
+  (setf (ps-tenant ps) window)
+  (when (or (neq (ps-h-dimension ps) (h-dimension window))
+            (neq (ps-v-dimension ps) (v-dimension window))
+            (neq (ps-h-position ps) (h-position window))
+            (neq (ps-v-position ps) (v-position window)))
+    ;; park it
+    (init-parking window)
+    (ns:with-ns-rect (r (ps-h-position ps) (ps-v-position ps) (ps-h-dimension ps) (ps-v-dimension ps))
+      (#/setFrame:display: window r t))
+    (#/makeKeyAndOrderFront: window nil))
+  (let ((style-screen-function (find-symbol "STYLE-SCREEN" (find-package :sax))))
+    (when style-screen-function
+      (let* ((hemlock-view (gui::hemlock-view window))
+             (text-view (gui::text-pane-text-view (hi::hemlock-view-pane hemlock-view))))
+        (when text-view
+          (funcall style-screen-function text-view))))))
+
+;;; ----------------------------------------------------------------------------
+;;;
+(defClass WINDOW-PARKER ()
+  ((parking-spots :initform nil :accessor wp-parking-spots)
+   (parking-lot-path :initform (merge-pathnames ";Library;Preferences;org.clairvaux;window-parking;parking-lot" 
+                                                 (hemlock::user-homedir-pathname))
+                      :reader wp-parking-lot-path))
+  (:documentation "A window manager."))
+
+(setf *window-parker* (make-instance 'window-parker))
+
+(defMethod park ((wp window-parker) (window parkable-hemlock-frame))
+  (when (and (wp-parking-spots wp) *park-p*)
+    ;; Already parked?
+    (let* ((position (position window (wp-parking-spots wp) :key #'ps-tenant))
+           spot)
+      (when (null position)
+        (or (setf position (get-empty-position wp))
+            (setf position (bump-position wp (1- (length (wp-parking-spots wp)))))))
+      (cond (position
+             (setq spot (nth position (wp-parking-spots wp)))
+             (move-position-to-front wp position)
+             (setf (ps-tenant spot) window)
+             (values (ps-h-position spot) (ps-v-position spot)
+                     (ps-h-dimension spot) (ps-v-dimension spot)))
+            (t
+             ;; only try to park it once
+             (setf (parked-p window) t))))))
+
+;;; Test to make sure that POSITION is on screen.  If not, call recursively with
+;;; (1- position).  Return POSITION or NIL
+(defMethod bump-position ((wp window-parker) position)
+  ;; Has the recursive call run out of positions?
+  (when (< position 0)
+    (cmenu:notify "There are no on-screen parking spots with unmodified buffers.")
+    (return-from bump-position nil))
+  (let* ((bump-location (nth position (wp-parking-spots wp)))
+         (tenant (when bump-location (ps-tenant bump-location))))
+    (cond ((and bump-location 
+                (parking-spot-on-screen-p bump-location)
+                (not (modified-p tenant)))
+             (when tenant (#/close tenant))
+             position)
+          (t ; location is off-screen or not defined, recursive call
+           (bump-position wp (1- position))))))
+
+;;; Assumes that WINDOW's buffer is unmodified.
+(defMethod bump-location-and-set-location-values ((wp window-parker) location window)
+  (let ((tenant (ps-tenant location)))
+    (when tenant
+      (#/close tenant))
+    (apply-parking-spot-values location window)))
+
+(defMethod move-position-to-front ((wp window-parker) position)
+  (let ((current-location (nth position (wp-parking-spots wp))))
+    (setf (wp-parking-spots wp) 
+          (cons current-location (delete current-location (wp-parking-spots wp))))))
+
+(defMethod parking-spot-with-function-key ((wp window-parker) function-key)
+  (find  function-key (wp-parking-spots wp) :test #'= :key #'ps-function-key))
+
+;;; Find the lowest number parking-spot that has no tenant.
+(defMethod get-empty-position ((wp window-parker))
+  (let ((parking-spots (sort (copy-list (wp-parking-spots wp))
+                             #'(lambda (s1 s2)
+                                 (< (ps-function-key s1) (ps-function-key s2))))))
+    (dolist (spot parking-spots)
+      (when (and (null (ps-tenant spot))
+                 (parking-spot-on-screen-p spot))
+        ;; Return the position in the unsorted list. 
+        (return (position spot (wp-parking-spots wp)))))))
+
+(defMethod add-parking-spot ((wp window-parker) window function-key)
+  (let ((new-parking-spot (make-instance 'parking-spot :window window :function-key function-key)))
+    (setf (wp-parking-spots wp) (cons new-parking-spot (wp-parking-spots wp)))
+    (cmenu:echo-msg "Parking Spot ~a defined." function-key)))
+
+(defMethod add-parking-spot-2 ((wp window-parker) function-key
+                               h-dimension v-dimension h-position v-position)
+  (cond ((and (wp-parking-spots wp)
+              (find-if #'(lambda (spot) (= function-key (ps-function-key spot)))
+                       (wp-parking-spots wp)))
+         (cmenu:notify "Duplicate parking-spot ignored."))
+        (t
+         (let ((new-parking-spot (make-instance 'parking-spot
+                                   :function-key function-key
+                                   :h-dimension h-dimension :v-dimension v-dimension
+                                   :h-position h-position :v-position v-position)))
+           (setf (wp-parking-spots wp) (cons new-parking-spot (wp-parking-spots wp)))))))
+
+(defMethod delete-parking-spot ((wp window-parker) function-key)
+  (let ((parking-spot (find function-key (wp-parking-spots wp) :key #'ps-function-key)))
+    (cond (parking-spot
+           (let ((tenant (ps-tenant parking-spot)))
+             (cond (tenant
+                    (cond ((modified-p tenant)
+                           (cmenu:notify (format nil "First save: ~S.  Then try again."
+                                                 (cmenu:window-path tenant))))
+                          (t
+                           (setf (wp-parking-spots wp) (delete parking-spot (wp-parking-spots wp)))  
+                           (#/close tenant)
+                           (cmenu:echo-msg "Parking Spot ~a deleted." function-key))))
+                   (t
+                    (setf (wp-parking-spots wp) (delete parking-spot (wp-parking-spots wp)))  
+                    (cmenu:echo-msg "Parking Spot ~a deleted." function-key)))))                    
+          (t 
+           (cmenu:notify (format nil "Parking Spot ~a is not currently defined." function-key))))))
+
+(defMethod get-function-key ((wp window-parker) window)
+  (dolist (spot (wp-parking-spots wp))
+    (when (eql window (ps-tenant spot)) (return (ps-function-key spot)))))
+
+(defMethod vacate-current-location ((wp window-parker) window)
+  (let ((location (find window (wp-parking-spots wp) :key #'ps-tenant)))
+    (when location 
+      (setf (ps-tenant location) nil)
+      t)))
+
+(defMethod clear-parking-lot ((wp window-parker))
+  (setf (wp-parking-spots wp) nil))
+
+;;; Move WINDOW to the parking-spot corresponding to the pressed function key,
+;;; unless the parking-spot is not on screen or the window is already in that location.
+(defMethod move-window-to-position ((wp window-parker) window function-key)
+  (when *park-p*
+    (let* ((parking-spot (find function-key (wp-parking-spots wp) :key #'ps-function-key))
+           (tenant (when parking-spot (ps-tenant parking-spot))))
+      (cond ((and parking-spot (parking-spot-on-screen-p parking-spot window))
+             (cond (tenant
+                    (cond ((eql window tenant)
+                           (cmenu:echo-msg "Already in parking-spot ~a." function-key))
+                          (t
+                           (cond ((modified-p tenant)
+                                  (cmenu:notify (format nil "First save: ~S. Then try again." 
+                                                        (cmenu:window-path tenant)))
+                                  (init-parking tenant))
+                                 (t
+                                  (vacate-current-location wp window)
+                                  (bump-location-and-set-location-values wp parking-spot window)
+                                  (#/makeKeyAndOrderFront: window nil)
+                                  (cmenu:echo-msg "Moved to parking-spot ~a." function-key))))))
+                   (t 
+                    (vacate-current-location wp window)
+                    (apply-parking-spot-values parking-spot window)
+                    (#/makeKeyAndOrderFront: window nil)
+                    (cmenu:echo-msg "Moved to parking-spot ~a." function-key))))
+            (t
+             (if (null parking-spot)
+               (cmenu:notify (format nil "Parking-spot ~a is not defined." function-key))
+               (cmenu:notify (format nil "Parking-spot ~a is off screen." function-key))))))))
+
+;;; ----------------------------------------------------------------------------
+;;; file I/O
+;;;
+(defMethod read-parking-spot-entries ((wp window-parker) stream)
+  (let (length h-dimension v-dimension h-position v-position function-key input)
+    (setf input (read stream nil :eof))
+    (when (not (numberp input))
+      (return-from read-parking-spot-entries))
+    (setf length input)
+    (dotimes (count length t)
+      (setf input (read stream nil :eof))
+      ;; *** null ?
+      (when (not (or (numberp input) (null input))) (return nil))
+      (setf function-key input)
+      (setf input (read stream nil :eof))
+      (when (not (or (numberp input) (null input))) (return nil))
+      (setf h-dimension input)
+      (setf input (read stream nil :eof))
+      (when (not (or (numberp input) (null input))) (return nil))
+      (setf v-dimension input)
+      (setf input (read stream nil :eof))
+      (when (not (or (numberp input) (null input))) (return nil))
+      (setf h-position input)
+      (setf input (read stream nil :eof))
+      (when (not (or (numberp input) (null input))) (return nil))
+      (setf v-position input)
+      (add-parking-spot-2 wp function-key h-dimension v-dimension
+                            h-position v-position))))
+
+(defMethod write-parking-spot-entries ((wp window-parker) stream)
+  (let (;; write the positions in reverse order based on their function key order
+        (sorted-parking-spots (sort (copy-list (wp-parking-spots wp)) #'> :key #'ps-function-key)))
+    (format stream "~s~%" (length sorted-parking-spots))
+    (dolist (entry sorted-parking-spots)
+      (format stream "~s~%" (ps-function-key entry))
+      (format stream "~s~%" (ps-h-dimension entry))
+      (format stream "~s~%" (ps-v-dimension entry))
+      (format stream "~s~%" (ps-h-position entry)) 
+      (format stream "~s~%" (ps-v-position entry)))))
+
+(defun read-parking-lot-file ()
+  "Read the parking-lot file."
+  (let ((path (wp-parking-lot-path *window-parker*)))
+    (when (probe-file path)
+      (with-open-file (stream path :direction :input)
+        (unless (read-parking-spot-entries *window-parker* stream)
+          (cmenu:notify "There is a problem with the parking-lot file.  You will have to redefine your parking spots.")
+          (clear-parking-lot *window-parker*))))))
+
+(defun write-parking-lot-file (&rest args)
+  "Writing function pushed into *lisp-cleanup-functions*."
+  (declare (ignore args))
+  (let ((path (wp-parking-lot-path *window-parker*)))
+    (with-open-file (stream path :direction :output :if-exists :supersede)
+      (write-parking-spot-entries *window-parker* stream))))
+
+(pushnew 'write-parking-lot-file ccl::*lisp-cleanup-functions*)
+
+;;; To Do:
+;;; Heap issues involved in saving an image with the utility loaded.
+;;; (pushnew 'read-parking-lot-file ccl::*lisp-startup-functions*)
+
+;;; ----------------------------------------------------------------------------
+;;; Commands and bindings:
+;;;
+(hemlock::defcommand "Move Window to Position 1" (p)
+  "Move the front Hemlock window to parking spot 1."
+  (declare (ignore p))
+  (let ((window (cmenu:active-hemlock-window)))
+    (cond (window
+           (move-window-to-position *window-parker* window 1))
+          (t
+           (hi::editor-error "There is no active Hemlock window to move.")))))
+
+(hi::bind-key "Move Window to Position 1" #k"F1")
+
+(hemlock::defcommand "Move Window to Position 2" (p)
+  "Move the front Hemlock window to parking spot 2."
+  (declare (ignore p))
+  (let ((window (cmenu:active-hemlock-window)))
+    (cond (window
+           (move-window-to-position *window-parker* window 2))
+          (t
+           (hi::editor-error "There is no active Hemlock window to move.")))))
+
+(hi::bind-key "Move Window to Position 2" #k"F2")
+
+(hemlock::defcommand "Move Window to Position 3" (p)
+  "Move the front Hemlock window to parking spot 3."
+  (declare (ignore p))
+  (let ((window (cmenu:active-hemlock-window)))
+    (cond (window
+           (move-window-to-position *window-parker* window 3))
+          (t
+           (hi::editor-error "There is no active Hemlock window to move.")))))
+
+(hi::bind-key "Move Window to Position 3" #k"F3")
+
+(hemlock::defcommand "Move Window to Position 4" (p)
+  "Move the front Hemlock window to parking spot 4."
+  (declare (ignore p))
+  (let ((window (cmenu:active-hemlock-window)))
+    (cond (window
+           (move-window-to-position *window-parker* window 4))
+          (t
+           (hi::editor-error "There is no active Hemlock window to move.")))))
+
+(hi::bind-key "Move Window to Position 4" #k"F4")
+
+(hemlock::defcommand "Move Window to Position 5" (p)
+  "Move the front Hemlock window to parking spot 5."
+  (declare (ignore p))
+  (let ((window (cmenu:active-hemlock-window)))
+    (cond (window
+           (move-window-to-position *window-parker* window 5))
+          (t
+           (hi::editor-error "There is no active Hemlock window to move.")))))
+
+(hi::bind-key "Move Window to Position 5" #k"F5")
+
+(hemlock::defcommand "Move Window to Position 6" (p)
+  "Move the front Hemlock window to parking spot 6."
+  (declare (ignore p))
+  (let ((window (cmenu:active-hemlock-window)))
+    (cond (window
+           (move-window-to-position *window-parker* window 6))
+          (t
+           (hi::editor-error "There is no active Hemlock window to move.")))))
+
+(hi::bind-key "Move Window to Position 6" #k"F6")
+
+(hemlock::defcommand "Move Window to Position 7" (p)
+  "Move the front Hemlock window to parking spot 7."
+  (declare (ignore p))
+  (let ((window (cmenu:active-hemlock-window)))
+    (cond (window
+           (move-window-to-position *window-parker* window 7))
+          (t
+           (hi::editor-error "There is no active Hemlock window to move.")))))
+
+(hi::bind-key "Move Window to Position 7" #k"F7")
+
+
+(read-parking-lot-file)
+
+
+
+
+
Index: /trunk/contrib/garret/combination-hook.lisp
===================================================================
--- /trunk/contrib/garret/combination-hook.lisp	(revision 13946)
+++ /trunk/contrib/garret/combination-hook.lisp	(revision 13946)
@@ -0,0 +1,87 @@
+
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;;;
+;;;  Combination hook -- intercept the CCL compiler's treatment of combinations
+;;;  to allow extensions.  The two most notable applications are to allow CL to
+;;;  support Scheme's ((...) ...) syntax (which lets you do cool pedagogical things
+;;;  like compute factorials without defining any functions -- see below) and
+;;;  supporting Lexicons handling of calling undefined functions.  See lexicons.lisp
+;;;  for details.
+;;;
+;;;  Written by Ron Garret, released to the public domain 22 February 2010.
+;;;
+
+(defpackage :combination-hook
+  (:export :combination-hook :undefined-function-hook))
+
+(in-package :combination-hook)
+
+(defun combination-hook (form) form)
+(defun undefined-function-hook (form) form)
+
+(defmacro hook-em-dano (callback)                  ; With apologies to Dragnet
+  `(destructuring-bind (form env) ccl::arglist
+     (if (atom form)
+       (:do-it)
+       (let* ((op (car form))
+              (hook (cond ((and (symbolp op)
+                                (not (fboundp op))
+                                (not (ccl::function-information op env)))
+                           'undefined-function-hook)
+                           ((and (consp op)
+                                 (not (ccl::lambda-expression-p op)))
+                            'combination-hook))))
+         (if (null hook)
+           (:do-it)
+           (let ((new-form (funcall hook form)))
+             (if (equalp form new-form)
+               (:do-it)
+               (,callback new-form env))))))))
+
+(advise ccl::nx1-combination
+  (hook-em-dano ccl::nx1-combination)
+  :when :around
+  :name combination-hook)
+
+(advise ccl::cheap-eval-in-environment
+  (hook-em-dano ccl::cheap-eval-in-environment)
+  :when :around
+  :name combination-hook)
+
+
+#|
+; Test: factorial using the Y combinator
+
+; ((...) ...) ==> (funcall (...) ...)
+(defun combination-hook (form) (cons 'funcall form))
+
+(defun convert-args (args)
+  (cond ( (null args) nil )
+        ( (atom args) (list '&rest args) )
+        (t (cons (car args) (convert-args (cdr args))))))
+
+(defmacro Î» (args &body body)
+  (let ((args (remove-if (lambda (x) (eql #\& (elt (symbol-name x) 0))) args)))
+    `(lambda ,(convert-args args)
+       (flet ,(mapcar (lambda (arg) `(,arg (&rest args) (apply ,arg args))) args)
+         ,@body))))
+
+(defmacro define (name value)
+  `(progn
+     (define-symbol-macro ,name ,value)
+     (defun ,name (&rest args) (apply ,name args))))
+
+(define y (Î» (f) ((Î» (h) (Î» (x) ((f (h h)) x))) (Î» (h) (Î» (x) ((f (h h)) x))))))
+
+(define y (Î» (f) ((Î» (g) (g g)) (Î» (h) (Î» (x) ((f (h h)) x))))))
+
+(define fact* (Î» (f) (Î» (n) (if (zerop n) 1 (* n (f (1- n)))))))
+
+((y fact*) 15)
+
+((y (Î» (f) (Î» (n) (if (zerop n) 1 (* n (f (1- n))))))) 15)
+
+(((Î» (f) ((Î» (g) (g g)) (Î» (h) (Î» (x) ((f (h h)) x)))))
+  (Î» (f) (Î» (n) (if (zerop n) 1 (* n (f (1- n)))))))
+ 15)
+|#
Index: /trunk/contrib/huebner/advice-profiler/overhead.lisp
===================================================================
--- /trunk/contrib/huebner/advice-profiler/overhead.lisp	(revision 13946)
+++ /trunk/contrib/huebner/advice-profiler/overhead.lisp	(revision 13946)
@@ -0,0 +1,62 @@
+;;; -*- Lisp -*-
+
+;;;   Copyright (c) 2008, Hans Huebner.
+;;;   This file is part of Clozure CL.  
+
+;;;   Clozure CL is licensed under the terms of the Lisp Lesser GNU Public
+;;;   License , known as the LLGPL and distributed with Clozure CL as the
+;;;   file "LICENSE".  The LLGPL consists of a preamble and the LGPL,
+;;;   which is distributed with Clozure CL as the file "LGPL".  Where these
+;;;   conflict, the preamble takes precedence.  
+;;;
+;;;   Clozure CL is referenced in the preamble as the "LIBRARY."
+;;;
+;;;   The LLGPL is also available online at
+;;;   http://opensource.franz.com/preamble.html
+
+;;; Profiling overhead calculation
+
+;;; This is in a separate file so that the profiler.lisp file can be
+;;; compiled and loaded beforehand, making the macrology available.
+
+(in-package "PROFILER")
+
+(eval-when (:compile-toplevel :load-toplevel :execute)
+  (defun stub-function (x)
+    (declare (ignore x))
+    nil)
+  (proclaim '(notinline stub-function)))
+
+(defconstant +overhead-iterations+ 10000
+  "Number of iterations to make through the empty stub function to
+   determine profiling overhead.")
+
+(defvar *determining-overhead* nil
+  "Set while determining overhead in order to prevent recursion")
+
+(defun determine-overhead ()
+  (format *trace-output* "; Calculating profiling overhead...")
+  (force-output *trace-output*)
+  (reset)
+  (process-enable-profiling *current-process*)
+  (unprofile stub-function)
+  ;; Determine loop and function call overhead
+  (with-real/cpu/cons (bare-real bare-cpu bare-cons)
+      (dotimes (i +overhead-iterations+)
+        (stub-function nil))
+    (profile stub-function)
+    (with-real/cpu/cons (alloc-real alloc-cpu alloc-cons)
+        (stub-function nil)             ; call once in order to allocate call record structure
+      ;; Determine profiling overhead
+      (with-real/cpu/cons (profiled-real profiled-cpu profiled-cons)
+          (dotimes (i +overhead-iterations+)
+            (stub-function nil))
+        (unprofile stub-function)
+        (setf *real-overhead* (round (/ (- profiled-real bare-real) +overhead-iterations+))
+              *cpu-overhead* (round (/ (- profiled-cpu bare-cpu) +overhead-iterations+))
+              *cons-overhead* (round (/ (- profiled-cons bare-cons alloc-cons) +overhead-iterations+)))))
+    (reset)
+    (format *trace-output* "~&; per call overheads: cpu time ~A, real time ~A, cons ~A bytes~%"
+            (format-time *cpu-overhead*) (format-time *real-overhead*) *cons-overhead*)))
+
+(determine-overhead)
Index: /trunk/contrib/huebner/advice-profiler/package.lisp
===================================================================
--- /trunk/contrib/huebner/advice-profiler/package.lisp	(revision 13946)
+++ /trunk/contrib/huebner/advice-profiler/package.lisp	(revision 13946)
@@ -0,0 +1,28 @@
+;;; -*- Lisp -*-
+
+;;;   Copyright (c) 2008, Hans Huebner.
+;;;   This file is part of Clozure CL.  
+
+;;;   Clozure CL is licensed under the terms of the Lisp Lesser GNU Public
+;;;   License , known as the LLGPL and distributed with Clozure CL as the
+;;;   file "LICENSE".  The LLGPL consists of a preamble and the LGPL,
+;;;   which is distributed with Clozure CL as the file "LGPL".  Where these
+;;;   conflict, the preamble takes precedence.  
+;;;
+;;;   Clozure CL is referenced in the preamble as the "LIBRARY."
+;;;
+;;;   The LLGPL is also available online at
+;;;   http://opensource.franz.com/preamble.html
+
+(in-package "CL-USER")
+
+(defpackage "PROFILER"
+  (:nicknames "PROF")
+  (:use "COMMON-LISP" "CCL")
+  (:export "PROFILE" "UNPROFILE"
+           "UNPROFILE-ALL"
+           "PROFILE-PACKAGE" "UNPROFILE-PACKAGE"
+           "ENABLE-PROFILING" "DISABLE-PROFILING"
+           "PROCESS-ENABLE-PROFILING" "PROCESS-DISABLE-PROFILING"
+	   "RESET"
+	   "REPORT"))
Index: /trunk/contrib/huebner/advice-profiler/profiler.asd
===================================================================
--- /trunk/contrib/huebner/advice-profiler/profiler.asd	(revision 13946)
+++ /trunk/contrib/huebner/advice-profiler/profiler.asd	(revision 13946)
@@ -0,0 +1,29 @@
+;;; -*- Lisp -*-
+
+;;;   Copyright (c) 2008, Hans Huebner.
+;;;   This file is part of Clozure CL.  
+
+;;;   Clozure CL is licensed under the terms of the Lisp Lesser GNU Public
+;;;   License , known as the LLGPL and distributed with Clozure CL as the
+;;;   file "LICENSE".  The LLGPL consists of a preamble and the LGPL,
+;;;   which is distributed with Clozure CL as the file "LGPL".  Where these
+;;;   conflict, the preamble takes precedence.  
+;;;
+;;;   Clozure CL is referenced in the preamble as the "LIBRARY."
+;;;
+;;;   The LLGPL is also available online at
+;;;   http://opensource.franz.com/preamble.html
+
+(in-package "CL-USER")
+
+(defpackage "PROFILER-SYSTEM"
+  (:use "CL" "ASDF"))
+
+(in-package "PROFILER-SYSTEM")
+
+(defsystem :profiler
+  :name "Clozure CL deterministic multithread-profiler"
+  :author "Hans Huebner <hans@clozure.com>"
+  :components ((:file "package")
+               (:file "profiler" :depends-on ("package"))
+               (:file "overhead" :depends-on ("profiler"))))
Index: /trunk/contrib/huebner/advice-profiler/profiler.lisp
===================================================================
--- /trunk/contrib/huebner/advice-profiler/profiler.lisp	(revision 13946)
+++ /trunk/contrib/huebner/advice-profiler/profiler.lisp	(revision 13946)
@@ -0,0 +1,653 @@
+;;; -*- Lisp -*-
+
+;;;   Copyright (c) 2008, Hans Huebner.
+;;;   This file is part of Clozure CL.  
+
+;;;   Clozure CL is licensed under the terms of the Lisp Lesser GNU Public
+;;;   License , known as the LLGPL and distributed with Clozure CL as the
+;;;   file "LICENSE".  The LLGPL consists of a preamble and the LGPL,
+;;;   which is distributed with Clozure CL as the file "LGPL".  Where these
+;;;   conflict, the preamble takes precedence.  
+;;;
+;;;   Clozure CL is referenced in the preamble as the "LIBRARY."
+;;;
+;;;   The LLGPL is also available online at
+;;;   http://opensource.franz.com/preamble.html
+
+;;; Deterministic profiler for Clozure CL
+
+;;; Inspired by the public domain profiler written by Mark Kantrowitz
+
+;;; To get accurate profiling results, you need to make sure that your
+;;; processor runs at full speed.  Modern CPUs adjust their CPU clock
+;;; dynamically, which will have negative effects on accuracy of the
+;;; profiling result.
+
+;;; In virtual machines, the profiling results may also be inaccurate
+;;; due to virtualized timers.
+
+;;; Bottom line: Always try to profile on the bare metal, with all
+;;; power saving techniques switched off.  Repeat your profiling to get
+;;; a feel for the precision of the results.
+
+;;; The code has provisions for measuring CPU time in addition to real
+;;; time, but it seems that no operating system can deliver consistent
+;;; and accurate per-thread CPU time usage.
+
+;;; All clock values that are handled by this profiler are specified
+;;; in nanoseconds.  This means that it will use bignums on 32 bit
+;;; platforms.
+
+(in-package "PROFILER")
+
+(defvar *profiler-loaded* nil)
+ 
+(eval-when (:load-toplevel :execute)
+  (when (and (not *profiler-loaded*)
+             (> (length (all-processes)) 2))
+    (error "Profiler can't be loaded with active application threads.  Please load from ccl-init.lisp"))
+  (setf *profiler-loaded* t))
+
+;;; Process specific variables
+(eval-when (:compile-toplevel :load-toplevel :execute)
+  (defmacro defvar-process-specific (var init doc)
+    `(progn
+       (defvar ,var ,init ,doc)
+       (ccl::def-standard-initial-binding ,var ,init))))
+
+(defvar-process-specific *process-profile-results* nil
+  "Variable to hold profiling information, in a hash table.  If NIL,
+   profiling is disabled for this process.")
+
+(defvar-process-specific *total-cpu-time* 0
+  "Amount of CPU time used by profiled functions so far")
+(defvar-process-specific *total-real-time* 0
+  "Amount of real time used by profiled functions so far")
+(defvar-process-specific *total-cons* 0
+  "Amount of consing in profiled functions so far")
+(defvar-process-specific *total-calls* 0
+  "Number of calls to profiled functions so far")
+
+;;; Global variables
+
+;;; Profiler overhead is determined by the function DETERMINE-OVERHEAD
+
+(eval-when (:compile-toplevel :load-toplevel :execute)
+  (defvar *real-overhead* 0 "Real time overhead")
+  (defvar *cpu-overhead* 0 "CPU time overhead")
+  (defvar *cons-overhead* 0 "Consing overhead (additional consing per call)"))
+
+(defvar *profiled-functions* nil
+  "List of function names that are currently being profiled.")
+
+(defvar *clock-errors* nil
+  "This flag indicates that the CPU and real time clock have shown to be inconsistent.  A warning
+   will be printed in the report if this is found to be true.")
+
+(defparameter *profile-new-processes* t
+  "This flag indicates that profiling should automatically be enabled for new processes that are
+   created.  If it nil, no call recording takes place for processes until after
+   PROCESS-ENABLE-PROFILING has been called for them.")
+
+(defvar *profiler-lock* (make-lock "Profiler lock")
+  "Lock to guard accesses to global profiler structures")
+
+(defmacro with-profiler-locked (() &body body)
+  `(with-lock-grabbed (*profiler-lock*)
+     ,@body))
+
+#+darwin
+(defun mach-timespec->nanoseconds (ts)
+  "Convert the given typespec structure into nanoseconds."
+  (+ (* 1000000000 (pref ts :mach_timespec.tv_sec))
+     (pref ts :mach_timespec.tv_nsec)))
+#+darwin
+(declaim (inline mach-timespec->nanoseconds))
+
+(defun timespec->nanoseconds (ts)
+  "Convert the given typespec structure into nanoseconds."
+  (+ (* 1000000000 (pref ts :timespec.tv_sec))
+     (pref ts :timespec.tv_nsec)))
+(declaim (inline timespec->nanoseconds))
+
+;;; Clock handling
+
+;;; For Darwin, we use the Mach clock service
+
+#+darwin
+(let ((clock-port (make-record :clock_serv_t)))
+  (#_host_get_clock_service (#_mach_host_self) #$REALTIME_CLOCK clock-port)
+  (defun get-real-time ()
+    (ccl:rlet ((ts :mach_timespec))
+      (unless (zerop (#_clock_get_time (%get-ptr clock-port) ts))
+        (error "error reading Mach clock: ~A~%" (ccl::%strerror (ccl::%get-errno))))
+      (mach-timespec->nanoseconds ts))))
+
+;;; For non-Darwin platforms, we use clock_gettime() with the
+;;; CLOCK_MONOTONIC clock.
+
+#-darwin
+(defun get-posix-clock (id)
+  (ccl:rlet ((ts :timespec))
+    (unless (zerop (#_clock_gettime id ts))
+      (error "error reading clock ~A: ~A~%" id (ccl::%strerror (ccl::%get-errno))))
+    (timespec->nanoseconds ts)))
+(declaim (inline get-posix-clock))
+
+#-darwin
+(defun get-real-time ()
+  (get-posix-clock #$CLOCK_MONOTONIC))
+
+;;; Per-thread CPU time measurement is only available on Linux
+
+(defun get-cpu-time ()
+  #+linux-target
+  (get-posix-clock #$CLOCK_THREAD_CPUTIME_ID)
+  #-linux-target
+  0)
+
+(defparameter *can-report-cpu* #+linux-target t #-linux-target nil)
+
+(defun get-cons ()
+  (ccl::total-bytes-allocated))
+
+(declaim (inline get-cpu-time get-real-time get-cons))
+
+;;; Helper macro to measure elapsed time
+
+(eval-when (:compile-toplevel :load-toplevel :execute)
+  (defmacro with-real/cpu/cons ((delta-real delta-cpu delta-cons &key adjusted) form &body post-process)
+    "Evaluate FORM, then run POST-PROCESS with DELTA-REAL, DELTA-CPU and
+   DELTA-CONS bound to the elapsed real time, elapsed CPU time and
+   amount of consing that happened in FORM.  If ADJUSTED is non-nil,
+   the values are adjusted by the overhead values."
+    (let ((start-real (gensym "START-REAL-"))
+          (start-cpu (gensym "START-CPU-"))
+          (start-cons (gensym "START-CONS-")))
+      `(let ((,start-real (get-real-time))
+             (,start-cpu (get-cpu-time))
+             (,start-cons (get-cons)))
+         (declare (type fixnum ,start-real ,start-cpu ,start-cons))
+         (multiple-value-prog1 ,form
+           (let ((,delta-real (- (get-real-time) ,start-real ,@(when adjusted (list '*real-overhead*))))
+                 (,delta-cpu (- (get-cpu-time) ,start-cpu ,@(when adjusted (list '*cpu-overhead*))))
+                 (,delta-cons (- (get-cons) ,start-cons ,@(when adjusted (list '*cons-overhead*)))))
+             (declare (type fixnum ,delta-real ,delta-cpu ,delta-cons))
+             ;; If there is clock imprecision, we can end up with
+             ;; negative delta values here.  For now, we just make
+             ;; sure that we never pass negative deltas back to the
+             ;; reporting code, but it may be preferable to take a
+             ;; note of such events and mark the report as being
+             ;; questionable.
+             (when (minusp ,delta-real) (setf ,delta-real 0))
+             (when (minusp ,delta-cpu) (setf ,delta-cpu 0))
+             (when (minusp ,delta-cons) (setf ,delta-cons 0))
+             (when (>= ,delta-real ,delta-cpu)
+               (setf *clock-errors* t))
+             ,@post-process))))))
+
+;;; Formatting
+
+(defun format-time (nanoseconds)
+  "Given a time in NANOSECONDS, return a human readable string with
+   the time scaled.  Times shorter than a second are reported with the
+   proper sub-second unit (ns, us, ms), times longer than a second are
+   reported in wall clock format (HH:MM:SSh)."
+  (cond
+    ((> 1000 nanoseconds)
+     (format nil "~Ans" (floor nanoseconds)))
+    ((> 1000000 nanoseconds)
+     (format nil "~,1Fus" (/ nanoseconds 1000)))
+    ((> 1000000000 nanoseconds)
+     (format nil "~,1Fms" (/ nanoseconds 1000000)))
+    ((> 100000000000 nanoseconds)
+     (format nil "~,1Fs " (/ nanoseconds 1000000000)))
+    (t
+     (let* ((seconds (floor nanoseconds 1000000000))
+            (minutes (floor seconds 60))
+            (hours (floor minutes 60)))
+       (format nil "~A:~2,'0D:~2,'0Dh"
+               hours
+               (- minutes (* 60 hours))
+               (- seconds (* 60 minutes)))))))
+               
+;; For each profiled function that is called within a process, a
+;; function-call-record structure is created that carries the counters
+;; and timing information.
+
+(defstruct (function-call-record
+             (:conc-name fcr-)
+             (:constructor make-function-call-record%))
+  (process *current-process* :type process)
+  (name nil :type symbol)
+  (inclusive-real-time 0 :type fixnum)
+  (exclusive-real-time 0 :type fixnum)
+  (inclusive-cpu-time 0 :type fixnum)
+  (exclusive-cpu-time 0 :type fixnum)
+  (inclusive-cons 0 :type fixnum)
+  (exclusive-cons 0 :type fixnum)
+  (calls 0 :type fixnum)
+  (nested-calls 0 :type fixnum))
+
+(defun make-function-call-record (name)
+  "Create a function-call-record structure for the function named NAME.  The
+   current process is written into the structure created for later
+   analysis."
+  (let ((fcr (make-function-call-record%)))
+    (setf (fcr-name fcr) name)
+    fcr))
+
+(defun sum-fcrs (fcrs)
+  (let ((sum (make-function-call-record (fcr-name (first fcrs)))))
+    (setf (fcr-inclusive-real-time sum) (reduce #'+ fcrs :key #'fcr-inclusive-real-time)
+          (fcr-exclusive-real-time sum) (reduce #'+ fcrs :key #'fcr-exclusive-real-time)
+          (fcr-inclusive-cpu-time sum) (reduce #'+ fcrs :key #'fcr-inclusive-cpu-time)
+          (fcr-exclusive-cpu-time sum) (reduce #'+ fcrs :key #'fcr-exclusive-cpu-time)
+          (fcr-inclusive-cons sum) (reduce #'+ fcrs :key #'fcr-inclusive-cons)
+          (fcr-exclusive-cons sum) (reduce #'+ fcrs :key #'fcr-exclusive-cons)
+          (fcr-calls sum) (reduce #'+ fcrs :key #'fcr-calls)
+          (fcr-nested-calls sum) (reduce #'+ fcrs :key #'fcr-nested-calls))
+    sum))
+
+(defmacro profile (&rest names)
+  "Profile the functions named by NAMES.  As in TRACE, the names are
+   not evaluated.  Strings and keywords are interpreted as package
+   designators and will cause all functions named by external symbols
+   in the package to be profiled.  If a function is already profiled,
+   then unprofile and reprofile (useful to notice function
+   redefinition).  If a name is undefined, give a warning and ignore
+   it."
+  `(progn
+     (let (new-names)
+       ,@(mapcar
+          (lambda (name)
+            (if (or (stringp name)
+                    (keywordp name))
+              `(setf new-names (append (profile-package ,name :external-only t) new-names))
+              `(with-profiler-locked ()
+                 (if (find ',name *profiled-functions*)
+                   (unprofile ,name)
+                   (push ',name new-names))
+                 (cond
+                   ((not (fboundp ',name))
+                    (warn "ignored argument ~A, which is not the name of a function" ',name))
+                   (t
+                    (ccl:advise ,name
+                                (progn
+                                  (when (and (null *process-profile-results*)
+                                             *profile-new-processes*)
+                                    (setf *process-profile-results* (make-hash-table)))
+                                  (if *process-profile-results*
+                                    (let ((prev-cpu-time *total-cpu-time*)
+                                          (prev-real-time *total-real-time*)
+                                          (prev-cons *total-cons*)
+                                          (prev-calls *total-calls*))
+                                      (declare (type fixnum prev-cpu-time prev-real-time prev-cons prev-calls))
+                                      (with-real/cpu/cons (delta-real delta-cpu delta-cons :adjusted t)
+                                          (:do-it)
+                                        (multiple-value-bind (fcr presentp)
+                                            (gethash ',name *process-profile-results*)
+                                          (unless presentp
+                                            (setf fcr (make-function-call-record ',name))
+                                            (setf (gethash ',name *process-profile-results*) fcr))
+                                          ;; Call counters
+                                          (incf *total-calls*)
+                                          (incf (fcr-calls fcr))
+                                          (incf (fcr-nested-calls fcr) (- *total-calls* prev-calls))
+                                          ;; Real time
+                                          (incf (fcr-inclusive-real-time fcr) delta-real)
+                                          (incf (fcr-exclusive-real-time fcr) (- delta-real
+                                                                                 (- *total-real-time* prev-real-time)))
+                                          (setf *total-real-time* (+ delta-real prev-real-time))
+                                          ;; CPU time
+                                          (incf (fcr-inclusive-cpu-time fcr) delta-cpu)
+                                          (incf (fcr-exclusive-cpu-time fcr) (- delta-cpu
+                                                                                (- *total-cpu-time* prev-cpu-time)))
+                                          (setf *total-cpu-time* (+ delta-cpu prev-cpu-time))
+                                          ;; consing
+                                          (incf (fcr-inclusive-cons fcr) delta-cons)
+                                          (incf (fcr-exclusive-cons fcr) (- delta-cons
+                                                                            (- *total-cons* prev-cons)))
+                                          (setf *total-cons* (+ delta-cons prev-cons)))))
+                                    (:do-it)))
+                                :when :around)
+                    (pushnew ',name *profiled-functions*))))))
+          names)
+       new-names)))
+
+(defun symbol-external-p (symbol)
+  "Return non-nil if the SYMBOL is external in its package (being
+exported)."
+  (eq :external (nth-value 1 (find-symbol (symbol-name symbol) (symbol-package symbol)))))
+
+(defun functions-in-package (package external-only)
+  "Return the list of symbols in PACKAGE that have a function bound to
+   them.  If EXTERNAL-ONLY is true, only returns those symbols that
+   are external."
+  (let ((package (if (packagep package)
+                   package
+                   (or (find-package package)
+                       (error "package ~S not found" package))))
+        symbols)
+    (do-symbols (symbol package)
+      (when (and (fboundp symbol)
+                 (not (macro-function symbol))
+                 (eq (symbol-package symbol) package)
+                 (or (not external-only)
+                     (symbol-external-p symbol)))
+        (pushnew symbol symbols)))
+    symbols))
+
+;;; Per-process profiling API
+
+(defmacro within-process ((process) &body body)
+  "Run BODY within PROCESS, using PROCESS-INTERRUPT."
+  (let ((sem (gensym "SEM-")))
+    `(let ((,sem (make-semaphore)))
+       (process-interrupt ,process
+                          (lambda ()
+                            (unwind-protect
+                                 (progn ,@body)
+                              (signal-semaphore, sem))))
+       (wait-on-semaphore ,sem))))
+
+(defun process-enable-profiling (&optional (process *current-process*))
+  "Enable profiling for the given process."
+  (within-process (process)
+    (unless *process-profile-results*
+      (setf *process-profile-results* (make-hash-table)))))
+
+(defun process-disable-profiling (&optional (process *current-process*))
+  "Disable profiling for the given process."
+  (within-process (process)
+    (setf *process-profile-results* nil)))
+
+(defun enable-profiling ()
+  "Enable profiling in all current and future processes."
+  (dolist (process (all-processes))
+    (process-enable-profiling process))
+  (setf *profile-new-processes* t))
+
+(defun disable-profiling ()
+  "Disable profiling in all current and future processes."
+  (dolist (process (all-processes))
+    (process-enable-profiling process))
+  (setf *profile-new-processes* nil))
+
+;;; Global profiling API
+
+(defmacro profile-package (&optional (package *package*) &key external-only)
+  "Profile all functions in the specified package."
+  `(profile ,@(functions-in-package package external-only)))
+
+(eval-when (:compile-toplevel :load-toplevel :execute)
+  (defmacro unprofile (&rest names)
+    "Unprofile the functions named by NAMES.  If an argument is a
+     keyword or a string, it is considered to be a package name and
+     all (!) symbols in the package will be unprofiled."
+    `(with-profiler-locked ()
+       ,@(mapcar (lambda (name)
+                   (if (or (stringp name)
+                           (keywordp name))
+                       `(unprofile-package ,name)
+                       `(ccl:unadvise ,name)))
+                 names)
+       (setf *profiled-functions* (set-difference *profiled-functions* ',names)))))
+
+(defmacro unprofile-all ()
+  "Unprofile all functions that are currently profiled."
+  `(with-profiler-locked ()
+     ,@(mapcar (lambda (name) `(ccl:unadvise ,name)) *profiled-functions*)
+     (setf *profiled-functions* nil)))
+
+(defmacro unprofile-package (&optional (package *package*) &key external-only)
+  "Profile all functions in the specified PACKAGE, which may be either
+   a string, a keyword symbol or a package instance.  If EXTERNAL-ONLY
+   is t, only functions named by symbols which are external in PACKAGE
+   are unprofiled."
+  `(unprofile ,@(functions-in-package package external-only)))
+
+(defun reset ()
+  "Reset profiling information in all processes."
+  (setf *total-cpu-time* 0
+        *total-real-time* 0
+        *total-cons* 0
+        *total-calls* 0)
+  (dolist (process (all-processes))
+    (within-process (process)
+      (when *process-profile-results*
+        (clrhash *process-profile-results*)))))
+
+(defun collect-profiling-results (&key reset)
+  "Collect profiling results from all processes.  If RESET is true,
+   the profiling results are cleared when they have been read."
+  (let (results)
+    (dolist (process (all-processes))
+      (within-process (process)
+        (when *process-profile-results*
+          (with-profiler-locked ()
+            (maphash (lambda (key value)
+                       (declare (ignore key))
+                       (push value results))
+                     *process-profile-results*))
+          (when reset
+            (clrhash *process-profile-results*)))))
+    results))
+
+;; Reporting
+
+(defun write-results-xml (&key (stream *standard-output*))
+  "Write the profiling results to the given STREAM in an XML format,
+   one 'entry' element for each function call record that has been
+   collected."
+  (format stream "<profile-results>~%")
+  (dolist (fcr (collect-profiling-results))
+    (format stream "  <entry function='~S' ~
+                             process='~A' ~
+                             inclusive-real-time='~A' exclusive-real-time='~A' ~
+                             inclusive-cpu-time='~A' exclusive-cpu-time='~A' ~
+                             inclusive-cons='~A' exclusive-cons='~A' ~
+                             calls='~A' nested-calls='~A'/>~%"
+            (fcr-name fcr)
+            (process-name (fcr-process fcr))
+            (fcr-inclusive-real-time fcr) (fcr-exclusive-real-time fcr)
+            (fcr-inclusive-cpu-time fcr) (fcr-exclusive-cpu-time fcr)
+            (fcr-inclusive-cons fcr) (fcr-exclusive-cons fcr)
+            (fcr-calls fcr) (fcr-nested-calls fcr)))
+  (format stream "</profile-results>~%"))
+
+(defun write-results-csv (&key (stream *standard-output*))
+  "Write the profiling results to the given STREAM in a CSV format
+   which can be imported into excel for further analysis."
+  (format stream "package;function;process;inclusive-real-time;exclusive-real-time;inclusive-cpu-time;exclusive-cpu-time;~
+                  inclusive-cons;exclusive-cons;calls;nested-calls~%")
+  (dolist (fcr (collect-profiling-results))
+    (format stream "\"~S\";\"~A\";~A;~A;~A;~A;~A;~A;~A;~A~%"
+            (fcr-name fcr)
+            (process-name (fcr-process fcr))
+            (fcr-inclusive-real-time fcr) (fcr-exclusive-real-time fcr)
+            (fcr-inclusive-cpu-time fcr) (fcr-exclusive-cpu-time fcr)
+            (fcr-inclusive-cons fcr) (fcr-exclusive-cons fcr)
+            (fcr-calls fcr) (fcr-nested-calls fcr))))
+
+(defstruct (profile-results
+            (:conc-name pr-)
+            (:constructor make-profile-results
+                          (name process
+                                calls
+                                real-time cpu-time cons
+                                percent-real-time percent-cpu-time percent-cons)))
+  name
+  process
+  calls
+  real-time
+  cpu-time
+  cons
+  percent-real-time
+  percent-cpu-time
+  percent-cons)
+
+(defun group-on (list &key (test #'eql) (key #'identity) (include-key t))
+  (let ((hash (make-hash-table :test test))
+        keys)
+    (dolist (el list)
+      (let ((key (funcall key el)))
+        (unless (nth-value 1 (gethash key hash))
+          (push key keys))
+        (push el (gethash key hash))))    
+    (mapcar (lambda (key) (let ((keys (nreverse (gethash key hash))))
+                            (if include-key
+                                (cons key keys)
+                                keys)))
+            (nreverse keys))))
+
+(defun get-postprocessed (&key (by-process t) reset sort-by)
+  "Collect profiling results from all processes and compress them for
+   display, return a list of lists of PROFILE-RESULTS.  BY-PROCESS
+   determines whether the report will be per process or one report for
+   all processes combined."
+  (labels
+      ((percentage (value total)
+         (if (and (plusp value) (plusp total))
+           (/ value (/ total 100))
+           0))
+       (postprocess (records)
+         (let ((total-real-time 0)
+               (total-cpu-time 0)
+               (total-cons 0))
+           (dolist (record records)
+             (incf total-real-time (fcr-exclusive-real-time record))
+             (incf total-cpu-time (fcr-exclusive-cpu-time record))
+             (incf total-cons (fcr-exclusive-cons record)))
+           (sort (mapcar (lambda (fcr)
+                           (make-profile-results (let ((*package* (find-package :keyword)))
+                                                   (prin1-to-string (fcr-name fcr)))
+                                                 (fcr-process fcr)
+                                                 (fcr-calls fcr)
+                                                 (fcr-exclusive-real-time fcr)
+                                                 (fcr-exclusive-cpu-time fcr)
+                                                 (fcr-exclusive-cons fcr)
+                                                 (percentage (fcr-exclusive-real-time fcr) total-real-time)
+                                                 (percentage (fcr-exclusive-cpu-time fcr) total-cpu-time)
+                                                 (percentage (fcr-exclusive-cons fcr) total-cons)))
+                         records)
+                 #'<
+                 :key sort-by))))
+    (if by-process
+      (mapcar #'postprocess
+              (group-on (collect-profiling-results :reset reset)
+                        :key #'fcr-process
+                        :test #'eq
+                        :include-key nil))
+      (list (postprocess (mapcar #'sum-fcrs (group-on (collect-profiling-results :reset reset)
+                                                      :key #'fcr-name
+                                                      :test #'eq
+                                                      :include-key nil)))))))
+
+(defun sort-key-function (keyword)
+  (let ((valid-sort-keys (append '(:calls
+                                   :cons :percent-cons
+                                   :real-time :percent-real-time)
+                                 (when *can-report-cpu*
+                                   '(:cpu-time :percent-cpu-time)))))
+    (unless (member keyword valid-sort-keys)
+      (error "invalid sort key ~S, specify one of ~S"
+             keyword valid-sort-keys))
+    (fdefinition (find-symbol (format nil "PR-~A" keyword) :profiler))))
+
+(defun report (&key
+               (threshold 0.01)
+               (by-process t)
+               (stream *trace-output*)
+               (report-cpu *can-report-cpu*)
+               (sort-by (if *can-report-cpu* :cpu-time :real-time))
+               report-overhead)
+  (labels
+      ((do-report (records)
+         (let ((max-length 8)           ; Function header size
+               (max-cons-length 8)
+               (max-colon-pos 0)        ; Maximum offset of a colon in any name
+               (total-real-time 0)
+               (total-cpu-time 0)
+               (total-consed 0)
+               (total-calls 0)
+               (total-percent-real-time 0)
+               (total-percent-cpu-time 0)
+               (total-percent-cons 0))
+           (dolist (result records)
+             (when (or (zerop threshold)
+                       (> (pr-percent-real-time result) threshold))
+               (setq max-colon-pos
+                     (max max-colon-pos
+                          (position #\: (pr-name result))))
+               (setq max-length
+                     (max max-length
+                          (length (pr-name result))))
+               (setq max-cons-length
+                     (max max-cons-length
+                          (/ (pr-cons result) (pr-calls result))))))
+           (incf max-length 2)
+           (setf max-cons-length (max 4 (ceiling (log max-cons-length 10))))
+           (format stream
+                   "~
+             ~&   %      ~@[~* %      ~]                          ~@[~*          ~]~V@A~
+	     ~%  Real    ~@[~*CPU     ~] %             Real Time  ~@[~*CPU Time  ~]~V@A      Total  ~@[~*   Total  ~]     Total~
+	     ~%  Time    ~@[~*Time    ~]Cons    Calls      /Call  ~@[~*   /Call  ~]~V@A  Real Time  ~@[~*CPU Time  ~]      Cons  Name~
+             ~%~V,,,'-A"
+                   report-cpu report-cpu max-cons-length "Cons"
+                   report-cpu report-cpu max-cons-length "Per"  report-cpu
+                   report-cpu report-cpu max-cons-length "Call" report-cpu
+                   (+ max-length (if report-cpu 92 64) (max 0 (- max-cons-length 5))) "-")
+           (dolist (result records)
+             (when (or (zerop threshold)
+                       (> (pr-percent-real-time result) threshold))
+               (format stream
+                       "~%~6,2F  ~@[~6,2F  ~]~6,2F  ~7D   ~8@A  ~@[~8@A  ~]~VD   ~8@A  ~@[~8@A  ~]~10D  ~V@A"
+                       (pr-percent-real-time result)
+                       (and report-cpu (pr-percent-cpu-time result))
+                       (pr-percent-cons result)
+                       (pr-calls result)
+                       (format-time (/ (pr-real-time result) (pr-calls result)))
+                       (and report-cpu (format-time (/ (pr-cpu-time result) (pr-calls result))))
+                       max-cons-length
+                       (floor (/ (pr-cons result) (pr-calls result)))
+                       (format-time (pr-real-time result))
+                       (and report-cpu (format-time (pr-cpu-time result)))
+                       (pr-cons result)
+                       (+ (length (pr-name result))
+                          (- max-colon-pos (position #\: (pr-name result))))
+                       (pr-name result))
+               (incf total-real-time (pr-real-time result))
+               (incf total-cpu-time (pr-cpu-time result))
+               (incf total-consed (pr-cons result))
+               (incf total-calls (pr-calls result))
+               (incf total-percent-real-time (pr-percent-real-time result))
+               (incf total-percent-cpu-time (pr-percent-cpu-time result))
+               (incf total-percent-cons (pr-percent-cons result))))
+           (format stream
+                   "~%~V,,,'-A~
+	    ~%~6,2F  ~@[~6,2F  ~]~6,2F  ~7D  ~9@T ~VA~@[~*          ~]    ~8@A~@[  ~8@A~]  ~10D~%"
+                   (+ max-length (if report-cpu 92 64) (max 0 (- max-cons-length 5))) "-"
+                   total-percent-real-time
+                   (and report-cpu total-percent-cpu-time)
+                   total-percent-cons
+                   total-calls
+                   max-cons-length " "
+                   report-cpu
+                   (format-time total-real-time)
+                   (and report-cpu (format-time total-cpu-time))
+                   total-consed)
+           (when report-overhead
+             (format stream "Estimated monitoring overhead: real: ~A cons: ~A~%"
+                   (format-time (* *real-overhead* total-calls))
+                   (* *cons-overhead* total-calls)))
+           (terpri stream)
+           (values))))
+    (dolist (results (get-postprocessed :by-process by-process
+                                        :sort-by (sort-key-function sort-by)))
+      (if by-process
+          (format stream "Profile results for process ~A~%~%" (pr-process (car results)))
+          (format stream "Profile results combined for all profiledy processes~%~%"))
+      (do-report results))
+    (when (and *can-report-cpu* *clock-errors*)
+      (format stream "Warning: real time and CPU time clocks are inconsistent.~%"))))
Index: /trunk/contrib/krueger/InterfaceProjects/BindingTest/binding.lisp
===================================================================
--- /trunk/contrib/krueger/InterfaceProjects/BindingTest/binding.lisp	(revision 13946)
+++ /trunk/contrib/krueger/InterfaceProjects/BindingTest/binding.lisp	(revision 13946)
@@ -0,0 +1,125 @@
+;;; binding.lisp
+
+#|
+The MIT license.
+
+Copyright (c) 2009 Paul L. Krueger
+
+Permission is hereby granted, free of charge, to any person obtaining a copy of this software 
+and associated documentation files (the "Software"), to deal in the Software without restriction, 
+including without limitation the rights to use, copy, modify, merge, publish, distribute, 
+sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is 
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all copies or substantial 
+portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT 
+LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. 
+IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, 
+WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE 
+SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+|#
+
+;;; Sample lisp/Cocoa interface that uses a NIB file defined with interface builder;
+;;; A definition is provided for the "Foo" class that was specified to interface builder
+;;; so that when the NIB file is loaded an instance of that class will be created and
+;;; linked appropriately to the input fields, output sum text field, and Sum button.
+;;; When the Sum button is pushed the sum will be computed and placed into the sum 
+;;; field in the window.
+
+(eval-when (:compile-toplevel :load-toplevel :execute)
+  (require :nib)
+  (require :ns-object-utils)
+  (require :nslog-utils)
+  (require :lisp-controller))
+
+(defpackage :binding 
+  (:nicknames :bnd)
+  (:use :iu :ccl :common-lisp :lc)
+  (:export test-binding
+           random-sum-owner
+           input-1
+           input-2
+           sum
+           sum-owner
+           controller))
+
+(in-package :bnd)
+
+(defclass sum-owner ()
+  ((input-1 :reader input-1 :initarg :input-1)
+   (input-2 :reader input-2  :initarg :input-2)
+   (sum :reader sum :initform 0))
+  (:default-initargs
+     :input-1 0
+     :input-2 0))
+
+(defmethod (setf input-1) (new-value (self sum-owner))
+  ;; we set up the slot writer to note a change in value to make it KVC compliant
+  (will-change-value-for-key self 'input-1)
+  (setf (slot-value self 'input-1) new-value)
+  (did-change-value-for-key self 'input-1))
+
+(defmethod (setf input-2) (new-value (self sum-owner))
+  ;; we set up the slot writer to note a change in value to make it KVC compliant
+  (will-change-value-for-key self 'input-2)
+  (setf (slot-value self 'input-2) new-value)
+  (did-change-value-for-key self 'input-2))
+
+(defmethod (setf sum) (new-value (self sum-owner))
+  ;; we set up the slot writer to note a change in value to make it KVC compliant
+  (will-change-value-for-key self 'sum)
+  (setf (slot-value self 'sum) new-value)
+  (did-change-value-for-key self 'sum))
+
+(defmethod  initialize-instance :after ((self sum-owner) 
+                                       &key &allow-other-keys)
+  (setf (sum self) (+ (input-1 self) (input-2 self))))
+
+(defun random-sum-owner ()
+  ;; return a sum-owner instance with random initial values
+  (make-instance 'sum-owner
+    :input-1 (random 100)
+    :input-2 (random 100)))
+
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+
+(defclass binding-window-owner (ns:ns-object)
+  ((controller :foreign-type :id
+               :accessor controller)
+   (nib-objects :accessor nib-objects :initform nil))
+  (:metaclass ns:+ns-object))
+
+(defmethod initialize-instance :after ((self binding-window-owner) 
+                                       &key &allow-other-keys)
+  (setf (nib-objects self)
+        (load-nibfile 
+         (truename "ip:BindingTest;binding.nib") 
+         :nib-owner self
+         :retain-top-objs t))
+  ;; we do the following so that ccl:terminate will be called before we are garbage 
+  ;; collected and we can release the top-level objects from the NIB that we retained
+  ;; when loaded
+  (ccl:terminate-when-unreachable self))
+
+(defmethod ccl:terminate ((self binding-window-owner))
+  (dolist (top-obj (nib-objects self))
+    (unless (eql top-obj (%null-ptr))
+      (#/release top-obj))))
+
+;; methods called as a result of button actions
+
+(objc:defmethod (#/doSum: :void) 
+                ((self binding-window-owner) (s :id))
+  (declare (ignore s))
+  (with-slots (input-1 input-2) (root (controller self))
+    (setf (sum (root (controller self)))
+          (+ input-1 input-2))))
+
+;; test by
+(defun test-binding ()
+  (make-instance 'binding-window-owner))
+
+(provide :binding)
Index: /trunk/contrib/krueger/InterfaceProjects/Controller Test 1/controller-test1.lisp
===================================================================
--- /trunk/contrib/krueger/InterfaceProjects/Controller Test 1/controller-test1.lisp	(revision 13946)
+++ /trunk/contrib/krueger/InterfaceProjects/Controller Test 1/controller-test1.lisp	(revision 13946)
@@ -0,0 +1,66 @@
+;; controller-test1.lisp
+
+;; Test window that displays lisp lists using an NSTableView
+
+(eval-when (:compile-toplevel :load-toplevel :execute)
+  (require :lisp-controller)
+  (require :ns-string-utils)
+  (require :nslog-utils)
+  (require :date))
+
+(defpackage :controller-test1
+  (:nicknames :ct1)
+  (:use :ccl :common-lisp :iu :lc)
+  (:export test-controller get-root))
+
+(in-package :ct1)
+
+(defclass lisp-controller-test (ns:ns-window-controller)
+   ((lisp-ctrl :foreign-type :id :accessor lisp-ctrl))
+  (:metaclass ns:+ns-object))
+
+(defmethod get-root ((self lisp-controller-test))
+  (when (lisp-ctrl self)
+    (root (lisp-ctrl self))))
+
+(objc:defmethod (#/initWithNibPath: :id)
+                ((self lisp-controller-test) (nib-path :id))
+  (let* ((init-self (#/initWithWindowNibPath:owner: self nib-path self)))
+    init-self))
+
+(defun make-dated-list ()
+  (list (now) 0 (random 20) (random 30)))
+
+(defun selected-cell (window controller root row-num col-num obj)
+  (declare (ignore window controller root))
+  (cond ((and (minusp row-num) (minusp col-num))
+         (ns-log "Nothing selected"))
+        ((minusp row-num)
+         (ns-log (format nil "Selected column ~s with title ~s" col-num obj)))
+        ((minusp col-num)
+         (ns-log (format nil "Selected row ~s: ~s" row-num obj)))
+        (t
+         (ns-log (format nil "Selected ~s in row ~s,  col ~s" obj row-num col-num)))))
+
+(defun edited-cell (window controller root row-num col-num obj old-val new-val)
+  (declare (ignore window controller root))
+  (ns-log (format nil "Changed ~s in row ~s, col ~s: ~s to ~s"
+                  old-val row-num col-num obj new-val)))
+
+(defun added-row (window controller root parent new-row)
+  (declare (ignore window controller root))
+  (ns-log (format nil "Added ~s to ~s" new-row parent)))
+
+(defun removed-row (window controller root parent old-row)
+  (declare (ignore window controller root))
+  (ns-log (format nil "Removed row ~s from ~s " old-row parent)))
+
+(defun test-controller ()
+  (let* ((nib-name (lisp-to-temp-nsstring
+                    (namestring (truename "ip:Controller Test 1;lc-test1.nib"))))
+         (wc (make-instance 'lisp-controller-test
+               :with-nib-path nib-name)))
+    (#/window wc)
+    wc))
+                  
+(provide :controller-test1)
Index: /trunk/contrib/krueger/InterfaceProjects/Controller Test 1/lc-test1.nib/designable.nib
===================================================================
--- /trunk/contrib/krueger/InterfaceProjects/Controller Test 1/lc-test1.nib/designable.nib	(revision 13946)
+++ /trunk/contrib/krueger/InterfaceProjects/Controller Test 1/lc-test1.nib/designable.nib	(revision 13946)
@@ -0,0 +1,908 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<archive type="com.apple.InterfaceBuilder3.Cocoa.XIB" version="7.03">
+	<data>
+		<int key="IBDocument.SystemTarget">1050</int>
+		<string key="IBDocument.SystemVersion">9L30</string>
+		<string key="IBDocument.InterfaceBuilderVersion">680</string>
+		<string key="IBDocument.AppKitVersion">949.54</string>
+		<string key="IBDocument.HIToolboxVersion">353.00</string>
+		<object class="NSMutableArray" key="IBDocument.EditedObjectIDs">
+			<bool key="EncodedWithXMLCoder">YES</bool>
+			<integer value="16"/>
+		</object>
+		<object class="NSArray" key="IBDocument.PluginDependencies">
+			<bool key="EncodedWithXMLCoder">YES</bool>
+			<string>com.clozure.ClozureCL.ibplugin</string>
+			<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
+		</object>
+		<object class="NSMutableDictionary" key="IBDocument.Metadata">
+			<bool key="EncodedWithXMLCoder">YES</bool>
+			<object class="NSArray" key="dict.sortedKeys">
+				<bool key="EncodedWithXMLCoder">YES</bool>
+			</object>
+			<object class="NSMutableArray" key="dict.values">
+				<bool key="EncodedWithXMLCoder">YES</bool>
+			</object>
+		</object>
+		<object class="NSMutableArray" key="IBDocument.RootObjects" id="1000">
+			<bool key="EncodedWithXMLCoder">YES</bool>
+			<object class="NSCustomObject" id="1001">
+				<string key="NSClassName">LispControllerTest</string>
+			</object>
+			<object class="NSCustomObject" id="1003">
+				<string key="NSClassName">FirstResponder</string>
+			</object>
+			<object class="NSCustomObject" id="1004">
+				<string key="NSClassName">NSApplication</string>
+			</object>
+			<object class="NSWindowTemplate" id="1005">
+				<int key="NSWindowStyleMask">15</int>
+				<int key="NSWindowBacking">2</int>
+				<string key="NSWindowRect">{{196, 243}, {487, 267}}</string>
+				<int key="NSWTFlags">536870912</int>
+				<string key="NSWindowTitle">Lisp Controller Test 1</string>
+				<string key="NSWindowClass">NSWindow</string>
+				<nil key="NSViewClass"/>
+				<string key="NSWindowContentMaxSize">{3.40282e+38, 3.40282e+38}</string>
+				<object class="NSView" key="NSWindowView" id="1006">
+					<reference key="NSNextResponder"/>
+					<int key="NSvFlags">256</int>
+					<object class="NSMutableArray" key="NSSubviews">
+						<bool key="EncodedWithXMLCoder">YES</bool>
+						<object class="NSButton" id="896457276">
+							<reference key="NSNextResponder" ref="1006"/>
+							<int key="NSvFlags">268</int>
+							<string key="NSFrame">{{46, 25}, {32, 19}}</string>
+							<reference key="NSSuperview" ref="1006"/>
+							<bool key="NSEnabled">YES</bool>
+							<object class="NSButtonCell" key="NSCell" id="946741485">
+								<int key="NSCellFlags">-2080244224</int>
+								<int key="NSCellFlags2">134217728</int>
+								<string key="NSContents">+</string>
+								<object class="NSFont" key="NSSupport" id="215416028">
+									<string key="NSName">LucidaGrande</string>
+									<double key="NSSize">1.200000e+01</double>
+									<int key="NSfFlags">16</int>
+								</object>
+								<reference key="NSControlView" ref="896457276"/>
+								<int key="NSButtonFlags">-2038152961</int>
+								<int key="NSButtonFlags2">164</int>
+								<string key="NSAlternateContents"/>
+								<string key="NSKeyEquivalent"/>
+								<int key="NSPeriodicDelay">400</int>
+								<int key="NSPeriodicInterval">75</int>
+							</object>
+						</object>
+						<object class="NSButton" id="113258462">
+							<reference key="NSNextResponder" ref="1006"/>
+							<int key="NSvFlags">268</int>
+							<string key="NSFrame">{{81, 25}, {32, 19}}</string>
+							<reference key="NSSuperview" ref="1006"/>
+							<bool key="NSEnabled">YES</bool>
+							<object class="NSButtonCell" key="NSCell" id="675814069">
+								<int key="NSCellFlags">-2080244224</int>
+								<int key="NSCellFlags2">134217728</int>
+								<string key="NSContents">-</string>
+								<reference key="NSSupport" ref="215416028"/>
+								<reference key="NSControlView" ref="113258462"/>
+								<int key="NSButtonFlags">-2038152961</int>
+								<int key="NSButtonFlags2">164</int>
+								<string key="NSAlternateContents"/>
+								<string key="NSKeyEquivalent"/>
+								<int key="NSPeriodicDelay">400</int>
+								<int key="NSPeriodicInterval">75</int>
+							</object>
+						</object>
+						<object class="NSScrollView" id="505926526">
+							<reference key="NSNextResponder" ref="1006"/>
+							<int key="NSvFlags">268</int>
+							<object class="NSMutableArray" key="NSSubviews">
+								<bool key="EncodedWithXMLCoder">YES</bool>
+								<object class="NSClipView" id="799074370">
+									<reference key="NSNextResponder" ref="505926526"/>
+									<int key="NSvFlags">2304</int>
+									<object class="NSMutableArray" key="NSSubviews">
+										<bool key="EncodedWithXMLCoder">YES</bool>
+										<object class="NSTableView" id="420834863">
+											<reference key="NSNextResponder" ref="799074370"/>
+											<int key="NSvFlags">256</int>
+											<string key="NSFrameSize">{430, 168}</string>
+											<reference key="NSSuperview" ref="799074370"/>
+											<bool key="NSEnabled">YES</bool>
+											<object class="NSTableHeaderView" key="NSHeaderView" id="801281011">
+												<reference key="NSNextResponder" ref="1045754935"/>
+												<int key="NSvFlags">256</int>
+												<string key="NSFrameSize">{430, 17}</string>
+												<reference key="NSSuperview" ref="1045754935"/>
+												<reference key="NSTableView" ref="420834863"/>
+											</object>
+											<object class="_NSCornerView" key="NSCornerView" id="737673031">
+												<reference key="NSNextResponder" ref="505926526"/>
+												<int key="NSvFlags">256</int>
+												<string key="NSFrame">{{431, 0}, {16, 17}}</string>
+												<reference key="NSSuperview" ref="505926526"/>
+											</object>
+											<object class="NSMutableArray" key="NSTableColumns">
+												<bool key="EncodedWithXMLCoder">YES</bool>
+												<object class="NSTableColumn" id="152879606">
+													<string key="NSIdentifier">0</string>
+													<double key="NSWidth">1.230000e+02</double>
+													<double key="NSMinWidth">4.000000e+01</double>
+													<double key="NSMaxWidth">1.000000e+03</double>
+													<object class="NSTableHeaderCell" key="NSHeaderCell">
+														<int key="NSCellFlags">75628032</int>
+														<int key="NSCellFlags2">0</int>
+														<string key="NSContents">Column A</string>
+														<object class="NSFont" key="NSSupport" id="26">
+															<string key="NSName">LucidaGrande</string>
+															<double key="NSSize">1.100000e+01</double>
+															<int key="NSfFlags">3100</int>
+														</object>
+														<object class="NSColor" key="NSBackgroundColor" id="63871200">
+															<int key="NSColorSpace">3</int>
+															<bytes key="NSWhite">MC4zMzMzMzI5OQA</bytes>
+														</object>
+														<object class="NSColor" key="NSTextColor" id="145989834">
+															<int key="NSColorSpace">6</int>
+															<string key="NSCatalogName">System</string>
+															<string key="NSColorName">headerTextColor</string>
+															<object class="NSColor" key="NSColor" id="122788521">
+																<int key="NSColorSpace">3</int>
+																<bytes key="NSWhite">MAA</bytes>
+															</object>
+														</object>
+													</object>
+													<object class="NSTextFieldCell" key="NSDataCell" id="5365232">
+														<int key="NSCellFlags">337772096</int>
+														<int key="NSCellFlags2">2048</int>
+														<string key="NSContents">Text Cell</string>
+														<object class="NSFont" key="NSSupport" id="389194177">
+															<string key="NSName">LucidaGrande</string>
+															<double key="NSSize">1.300000e+01</double>
+															<int key="NSfFlags">1044</int>
+														</object>
+														<reference key="NSControlView" ref="420834863"/>
+														<object class="NSColor" key="NSBackgroundColor" id="686228904">
+															<int key="NSColorSpace">6</int>
+															<string key="NSCatalogName">System</string>
+															<string key="NSColorName">controlBackgroundColor</string>
+															<object class="NSColor" key="NSColor">
+																<int key="NSColorSpace">3</int>
+																<bytes key="NSWhite">MC42NjY2NjY2OQA</bytes>
+															</object>
+														</object>
+														<object class="NSColor" key="NSTextColor" id="557243287">
+															<int key="NSColorSpace">6</int>
+															<string key="NSCatalogName">System</string>
+															<string key="NSColorName">controlTextColor</string>
+															<reference key="NSColor" ref="122788521"/>
+														</object>
+													</object>
+													<int key="NSResizingMask">3</int>
+													<bool key="NSIsResizeable">YES</bool>
+													<bool key="NSIsEditable">YES</bool>
+													<reference key="NSTableView" ref="420834863"/>
+												</object>
+												<object class="NSTableColumn" id="211559945">
+													<string key="NSIdentifier">1</string>
+													<double key="NSWidth">1.080000e+02</double>
+													<double key="NSMinWidth">4.000000e+01</double>
+													<double key="NSMaxWidth">1.000000e+03</double>
+													<object class="NSTableHeaderCell" key="NSHeaderCell">
+														<int key="NSCellFlags">75628032</int>
+														<int key="NSCellFlags2">0</int>
+														<string key="NSContents">Column B</string>
+														<reference key="NSSupport" ref="26"/>
+														<reference key="NSBackgroundColor" ref="63871200"/>
+														<reference key="NSTextColor" ref="145989834"/>
+													</object>
+													<object class="NSTextFieldCell" key="NSDataCell" id="18307911">
+														<int key="NSCellFlags">337772096</int>
+														<int key="NSCellFlags2">2048</int>
+														<string key="NSContents">Text Cell</string>
+														<reference key="NSSupport" ref="389194177"/>
+														<reference key="NSControlView" ref="420834863"/>
+														<reference key="NSBackgroundColor" ref="686228904"/>
+														<reference key="NSTextColor" ref="557243287"/>
+													</object>
+													<int key="NSResizingMask">3</int>
+													<bool key="NSIsResizeable">YES</bool>
+													<bool key="NSIsEditable">YES</bool>
+													<reference key="NSTableView" ref="420834863"/>
+												</object>
+												<object class="NSTableColumn" id="786351807">
+													<string type="base64-UTF8" key="NSIdentifier">Iyd0aGlyZA</string>
+													<double key="NSWidth">1.030000e+02</double>
+													<double key="NSMinWidth">1.000000e+01</double>
+													<double key="NSMaxWidth">3.402823e+38</double>
+													<object class="NSTableHeaderCell" key="NSHeaderCell">
+														<int key="NSCellFlags">75628032</int>
+														<int key="NSCellFlags2">0</int>
+														<string key="NSContents">Column C</string>
+														<reference key="NSSupport" ref="26"/>
+														<object class="NSColor" key="NSBackgroundColor" id="366758978">
+															<int key="NSColorSpace">6</int>
+															<string key="NSCatalogName">System</string>
+															<string key="NSColorName">headerColor</string>
+															<object class="NSColor" key="NSColor" id="936743010">
+																<int key="NSColorSpace">3</int>
+																<bytes key="NSWhite">MQA</bytes>
+															</object>
+														</object>
+														<reference key="NSTextColor" ref="145989834"/>
+													</object>
+													<object class="NSTextFieldCell" key="NSDataCell" id="909365266">
+														<int key="NSCellFlags">337772096</int>
+														<int key="NSCellFlags2">2048</int>
+														<string key="NSContents">Text Cell</string>
+														<reference key="NSSupport" ref="389194177"/>
+														<reference key="NSControlView" ref="420834863"/>
+														<reference key="NSBackgroundColor" ref="686228904"/>
+														<reference key="NSTextColor" ref="557243287"/>
+													</object>
+													<int key="NSResizingMask">3</int>
+													<bool key="NSIsResizeable">YES</bool>
+													<bool key="NSIsEditable">YES</bool>
+													<reference key="NSTableView" ref="420834863"/>
+												</object>
+												<object class="NSTableColumn" id="979909669">
+													<string key="NSIdentifier">(nth 3 :row)</string>
+													<double key="NSWidth">8.400000e+01</double>
+													<double key="NSMinWidth">1.000000e+01</double>
+													<double key="NSMaxWidth">3.402823e+38</double>
+													<object class="NSTableHeaderCell" key="NSHeaderCell">
+														<int key="NSCellFlags">75628032</int>
+														<int key="NSCellFlags2">0</int>
+														<string key="NSContents">Column D</string>
+														<reference key="NSSupport" ref="26"/>
+														<reference key="NSBackgroundColor" ref="366758978"/>
+														<reference key="NSTextColor" ref="145989834"/>
+													</object>
+													<object class="NSTextFieldCell" key="NSDataCell" id="475532581">
+														<int key="NSCellFlags">337772096</int>
+														<int key="NSCellFlags2">2048</int>
+														<string key="NSContents">Text Cell</string>
+														<reference key="NSSupport" ref="389194177"/>
+														<reference key="NSControlView" ref="420834863"/>
+														<reference key="NSBackgroundColor" ref="686228904"/>
+														<reference key="NSTextColor" ref="557243287"/>
+													</object>
+													<int key="NSResizingMask">3</int>
+													<bool key="NSIsResizeable">YES</bool>
+													<bool key="NSIsEditable">YES</bool>
+													<reference key="NSTableView" ref="420834863"/>
+												</object>
+											</object>
+											<double key="NSIntercellSpacingWidth">3.000000e+00</double>
+											<double key="NSIntercellSpacingHeight">2.000000e+00</double>
+											<reference key="NSBackgroundColor" ref="936743010"/>
+											<object class="NSColor" key="NSGridColor">
+												<int key="NSColorSpace">6</int>
+												<string key="NSCatalogName">System</string>
+												<string key="NSColorName">gridColor</string>
+												<object class="NSColor" key="NSColor">
+													<int key="NSColorSpace">3</int>
+													<bytes key="NSWhite">MC41AA</bytes>
+												</object>
+											</object>
+											<double key="NSRowHeight">1.700000e+01</double>
+											<int key="NSTvFlags">-700448768</int>
+											<int key="NSColumnAutoresizingStyle">4</int>
+											<int key="NSDraggingSourceMaskForLocal">15</int>
+											<int key="NSDraggingSourceMaskForNonLocal">0</int>
+											<bool key="NSAllowsTypeSelect">YES</bool>
+										</object>
+									</object>
+									<string key="NSFrame">{{1, 17}, {430, 168}}</string>
+									<reference key="NSSuperview" ref="505926526"/>
+									<reference key="NSNextKeyView" ref="420834863"/>
+									<reference key="NSDocView" ref="420834863"/>
+									<reference key="NSBGColor" ref="686228904"/>
+									<int key="NScvFlags">4</int>
+								</object>
+								<object class="NSScroller" id="614450346">
+									<reference key="NSNextResponder" ref="505926526"/>
+									<int key="NSvFlags">256</int>
+									<string key="NSFrame">{{431, 17}, {15, 168}}</string>
+									<reference key="NSSuperview" ref="505926526"/>
+									<reference key="NSTarget" ref="505926526"/>
+									<string key="NSAction">_doScroller:</string>
+									<double key="NSCurValue">3.700000e+01</double>
+									<double key="NSPercent">1.947368e-01</double>
+								</object>
+								<object class="NSScroller" id="949749883">
+									<reference key="NSNextResponder" ref="505926526"/>
+									<int key="NSvFlags">256</int>
+									<string key="NSFrame">{{1, 185}, {430, 15}}</string>
+									<reference key="NSSuperview" ref="505926526"/>
+									<int key="NSsFlags">1</int>
+									<reference key="NSTarget" ref="505926526"/>
+									<string key="NSAction">_doScroller:</string>
+									<double key="NSPercent">9.976798e-01</double>
+								</object>
+								<object class="NSClipView" id="1045754935">
+									<reference key="NSNextResponder" ref="505926526"/>
+									<int key="NSvFlags">2304</int>
+									<object class="NSMutableArray" key="NSSubviews">
+										<bool key="EncodedWithXMLCoder">YES</bool>
+										<reference ref="801281011"/>
+									</object>
+									<string key="NSFrame">{{1, 0}, {430, 17}}</string>
+									<reference key="NSSuperview" ref="505926526"/>
+									<reference key="NSNextKeyView" ref="801281011"/>
+									<reference key="NSDocView" ref="801281011"/>
+									<reference key="NSBGColor" ref="686228904"/>
+									<int key="NScvFlags">4</int>
+								</object>
+								<reference ref="737673031"/>
+							</object>
+							<string key="NSFrame">{{13, 52}, {447, 201}}</string>
+							<reference key="NSSuperview" ref="1006"/>
+							<reference key="NSNextKeyView" ref="799074370"/>
+							<int key="NSsFlags">50</int>
+							<reference key="NSVScroller" ref="614450346"/>
+							<reference key="NSHScroller" ref="949749883"/>
+							<reference key="NSContentView" ref="799074370"/>
+							<reference key="NSHeaderClipView" ref="1045754935"/>
+							<reference key="NSCornerView" ref="737673031"/>
+							<bytes key="NSScrollAmts">QSAAAEEgAABBmAAAQZgAAA</bytes>
+						</object>
+					</object>
+					<string key="NSFrameSize">{487, 267}</string>
+					<reference key="NSSuperview"/>
+				</object>
+				<string key="NSScreenRect">{{0, 0}, {1680, 1028}}</string>
+				<string key="NSMaxSize">{3.40282e+38, 3.40282e+38}</string>
+			</object>
+			<object class="LispController" id="691871786">
+				<object class="NSMutableArray" key="typeInfo">
+					<bool key="EncodedWithXMLCoder">YES</bool>
+					<object class="NSMutableArray">
+						<bool key="EncodedWithXMLCoder">YES</bool>
+						<string>list</string>
+						<string>cons</string>
+						<string/>
+					</object>
+					<object class="NSMutableArray">
+						<bool key="EncodedWithXMLCoder">YES</bool>
+						<string type="base64-UTF8">PG5ldyB0eXBlPg</string>
+						<string/>
+						<string/>
+					</object>
+				</object>
+				<object class="NSMutableArray" key="initforms">
+					<bool key="EncodedWithXMLCoder">YES</bool>
+					<object class="NSMutableArray">
+						<bool key="EncodedWithXMLCoder">YES</bool>
+						<string>cons</string>
+						<string>(ct1::make-dated-list)</string>
+					</object>
+					<object class="NSMutableArray">
+						<bool key="EncodedWithXMLCoder">YES</bool>
+						<string>list</string>
+						<string>nil</string>
+					</object>
+					<object class="NSMutableArray">
+						<bool key="EncodedWithXMLCoder">YES</bool>
+						<string type="base64-UTF8">PG5ldyB0eXBlPg</string>
+						<string/>
+					</object>
+				</object>
+				<object class="NSMutableArray" key="sortInfo">
+					<bool key="EncodedWithXMLCoder">YES</bool>
+					<object class="NSMutableArray">
+						<bool key="EncodedWithXMLCoder">YES</bool>
+						<string>cons</string>
+						<string type="base64-UTF8">IydzZWNvbmQ</string>
+						<string type="base64-UTF8">Iyc+A</string>
+					</object>
+					<object class="NSMutableArray">
+						<bool key="EncodedWithXMLCoder">YES</bool>
+						<string type="base64-UTF8">PG5ldyB0eXBlPg</string>
+						<string/>
+						<string/>
+					</object>
+				</object>
+				<string key="rootType">list</string>
+				<string key="readerFunc"/>
+				<string key="writerFunc"/>
+				<string key="countFunc"/>
+				<string type="base64-UTF8" key="selectFunc">IydjdDE6OnNlbGVjdGVkLWNlbGw</string>
+				<string type="base64-UTF8" key="editedFunc">IydjdDE6OmVkaXRlZC1jZWxsA</string>
+				<string type="base64-UTF8" key="addedFunc">IydjdDE6OmFkZGVkLXJvdw</string>
+				<string type="base64-UTF8" key="removedFunc">IydjdDE6OnJlbW92ZWQtcm93A</string>
+				<string key="deleteFunc"/>
+				<string key="addChildFunc"/>
+				<string key="childrenFunc"/>
+				<bool key="genRoot">YES</bool>
+			</object>
+			<object class="NSNumberFormatter" id="515955304">
+				<object class="NSMutableDictionary" key="NS.attributes">
+					<bool key="EncodedWithXMLCoder">YES</bool>
+					<object class="NSMutableArray" key="dict.sortedKeys">
+						<bool key="EncodedWithXMLCoder">YES</bool>
+						<string>allowsFloats</string>
+						<string>formatterBehavior</string>
+						<string>minimumIntegerDigits</string>
+					</object>
+					<object class="NSMutableArray" key="dict.values">
+						<bool key="EncodedWithXMLCoder">YES</bool>
+						<integer value="1" id="9"/>
+						<integer value="1040"/>
+						<integer value="0" id="8"/>
+					</object>
+				</object>
+				<string key="NS.positiveformat">#</string>
+				<string key="NS.negativeformat">#</string>
+				<nil key="NS.positiveattrs"/>
+				<nil key="NS.negativeattrs"/>
+				<object class="NSAttributedString" key="NS.zero">
+					<nil key="NSString"/>
+				</object>
+				<object class="NSAttributedString" key="NS.nil">
+					<nil key="NSString"/>
+				</object>
+				<object class="NSAttributedString" key="NS.nan">
+					<string key="NSString">NaN</string>
+					<object class="NSDictionary" key="NSAttributes">
+						<bool key="EncodedWithXMLCoder">YES</bool>
+						<object class="NSArray" key="dict.sortedKeys">
+							<bool key="EncodedWithXMLCoder">YES</bool>
+						</object>
+						<object class="NSMutableArray" key="dict.values">
+							<bool key="EncodedWithXMLCoder">YES</bool>
+						</object>
+					</object>
+				</object>
+				<object class="NSDecimalNumberPlaceholder" key="NS.min" id="562785679">
+					<int key="NS.exponent">0</int>
+					<int key="NS.length">0</int>
+					<bool key="NS.negative">YES</bool>
+					<bool key="NS.compact">NO</bool>
+					<int key="NS.mantissa.bo">1</int>
+					<bytes key="NS.mantissa">AAAAAAAAAAAAAAAAAAAAAA</bytes>
+				</object>
+				<reference key="NS.max" ref="562785679"/>
+				<object class="NSDecimalNumberHandler" key="NS.rounding">
+					<int key="NS.roundingmode">3</int>
+					<bool key="NS.raise.overflow">YES</bool>
+					<bool key="NS.raise.underflow">YES</bool>
+					<bool key="NS.raise.dividebyzero">YES</bool>
+				</object>
+				<string key="NS.decimal">.</string>
+				<string key="NS.thousand">,</string>
+				<bool key="NS.hasthousands">NO</bool>
+				<bool key="NS.localized">YES</bool>
+				<bool key="NS.allowsfloats">YES</bool>
+			</object>
+			<object class="NSDateFormatter" id="233590295">
+				<object class="NSMutableDictionary" key="NS.attributes">
+					<bool key="EncodedWithXMLCoder">YES</bool>
+					<object class="NSMutableArray" key="dict.sortedKeys">
+						<bool key="EncodedWithXMLCoder">YES</bool>
+						<string>dateFormat_10_0</string>
+						<string>dateStyle</string>
+						<string>formatterBehavior</string>
+						<string>timeStyle</string>
+					</object>
+					<object class="NSMutableArray" key="dict.values">
+						<bool key="EncodedWithXMLCoder">YES</bool>
+						<string>%m/%d/%y</string>
+						<reference ref="9"/>
+						<integer value="1040"/>
+						<reference ref="8"/>
+					</object>
+				</object>
+				<string key="NS.format">M/d/yy</string>
+				<bool key="NS.natural">NO</bool>
+			</object>
+		</object>
+		<object class="IBObjectContainer" key="IBDocument.Objects">
+			<object class="NSMutableArray" key="connectionRecords">
+				<bool key="EncodedWithXMLCoder">YES</bool>
+				<object class="IBConnectionRecord">
+					<object class="IBActionConnection" key="connection">
+						<string key="label">insert:</string>
+						<reference key="source" ref="691871786"/>
+						<reference key="destination" ref="896457276"/>
+					</object>
+					<int key="connectionID">9</int>
+				</object>
+				<object class="IBConnectionRecord">
+					<object class="IBActionConnection" key="connection">
+						<string key="label">remove:</string>
+						<reference key="source" ref="691871786"/>
+						<reference key="destination" ref="113258462"/>
+					</object>
+					<int key="connectionID">12</int>
+				</object>
+				<object class="IBConnectionRecord">
+					<object class="IBOutletConnection" key="connection">
+						<string key="label">view</string>
+						<reference key="source" ref="691871786"/>
+						<reference key="destination" ref="420834863"/>
+					</object>
+					<int key="connectionID">26</int>
+				</object>
+				<object class="IBConnectionRecord">
+					<object class="IBOutletConnection" key="connection">
+						<string key="label">dataSource</string>
+						<reference key="source" ref="420834863"/>
+						<reference key="destination" ref="691871786"/>
+					</object>
+					<int key="connectionID">28</int>
+				</object>
+				<object class="IBConnectionRecord">
+					<object class="IBOutletConnection" key="connection">
+						<string key="label">delegate</string>
+						<reference key="source" ref="420834863"/>
+						<reference key="destination" ref="691871786"/>
+					</object>
+					<int key="connectionID">29</int>
+				</object>
+				<object class="IBConnectionRecord">
+					<object class="IBOutletConnection" key="connection">
+						<string key="label">lispCtrl</string>
+						<reference key="source" ref="1001"/>
+						<reference key="destination" ref="691871786"/>
+					</object>
+					<int key="connectionID">31</int>
+				</object>
+				<object class="IBConnectionRecord">
+					<object class="IBOutletConnection" key="connection">
+						<string key="label">delegate</string>
+						<reference key="source" ref="1005"/>
+						<reference key="destination" ref="1001"/>
+					</object>
+					<int key="connectionID">32</int>
+				</object>
+				<object class="IBConnectionRecord">
+					<object class="IBBindingConnection" key="connection">
+						<string key="label">enabled: canInsert</string>
+						<reference key="source" ref="896457276"/>
+						<reference key="destination" ref="691871786"/>
+						<object class="NSNibBindingConnector" key="connector">
+							<reference key="NSSource" ref="896457276"/>
+							<reference key="NSDestination" ref="691871786"/>
+							<string key="NSLabel">enabled: canInsert</string>
+							<string key="NSBinding">enabled</string>
+							<string key="NSKeyPath">canInsert</string>
+							<int key="NSNibBindingConnectorVersion">2</int>
+						</object>
+					</object>
+					<int key="connectionID">34</int>
+				</object>
+				<object class="IBConnectionRecord">
+					<object class="IBBindingConnection" key="connection">
+						<string key="label">enabled: canRemove</string>
+						<reference key="source" ref="113258462"/>
+						<reference key="destination" ref="691871786"/>
+						<object class="NSNibBindingConnector" key="connector">
+							<reference key="NSSource" ref="113258462"/>
+							<reference key="NSDestination" ref="691871786"/>
+							<string key="NSLabel">enabled: canRemove</string>
+							<string key="NSBinding">enabled</string>
+							<string key="NSKeyPath">canRemove</string>
+							<int key="NSNibBindingConnectorVersion">2</int>
+						</object>
+					</object>
+					<int key="connectionID">36</int>
+				</object>
+				<object class="IBConnectionRecord">
+					<object class="IBOutletConnection" key="connection">
+						<string key="label">formatter</string>
+						<reference key="source" ref="18307911"/>
+						<reference key="destination" ref="515955304"/>
+					</object>
+					<int key="connectionID">41</int>
+				</object>
+				<object class="IBConnectionRecord">
+					<object class="IBOutletConnection" key="connection">
+						<string key="label">owner</string>
+						<reference key="source" ref="691871786"/>
+						<reference key="destination" ref="1001"/>
+					</object>
+					<int key="connectionID">42</int>
+				</object>
+				<object class="IBConnectionRecord">
+					<object class="IBOutletConnection" key="connection">
+						<string key="label">formatter</string>
+						<reference key="source" ref="5365232"/>
+						<reference key="destination" ref="233590295"/>
+					</object>
+					<int key="connectionID">44</int>
+				</object>
+			</object>
+			<object class="IBMutableOrderedSet" key="objectRecords">
+				<object class="NSArray" key="orderedObjects">
+					<bool key="EncodedWithXMLCoder">YES</bool>
+					<object class="IBObjectRecord">
+						<int key="objectID">0</int>
+						<object class="NSArray" key="object" id="1002">
+							<bool key="EncodedWithXMLCoder">YES</bool>
+						</object>
+						<reference key="children" ref="1000"/>
+						<nil key="parent"/>
+					</object>
+					<object class="IBObjectRecord">
+						<int key="objectID">-2</int>
+						<reference key="object" ref="1001"/>
+						<reference key="parent" ref="1002"/>
+						<string type="base64-UTF8" key="objectName">RmlsZSdzIE93bmVyA</string>
+					</object>
+					<object class="IBObjectRecord">
+						<int key="objectID">-1</int>
+						<reference key="object" ref="1003"/>
+						<reference key="parent" ref="1002"/>
+						<string key="objectName">First Responder</string>
+					</object>
+					<object class="IBObjectRecord">
+						<int key="objectID">-3</int>
+						<reference key="object" ref="1004"/>
+						<reference key="parent" ref="1002"/>
+						<string key="objectName">Application</string>
+					</object>
+					<object class="IBObjectRecord">
+						<int key="objectID">1</int>
+						<reference key="object" ref="1005"/>
+						<object class="NSMutableArray" key="children">
+							<bool key="EncodedWithXMLCoder">YES</bool>
+							<reference ref="1006"/>
+						</object>
+						<reference key="parent" ref="1002"/>
+					</object>
+					<object class="IBObjectRecord">
+						<int key="objectID">2</int>
+						<reference key="object" ref="1006"/>
+						<object class="NSMutableArray" key="children">
+							<bool key="EncodedWithXMLCoder">YES</bool>
+							<reference ref="113258462"/>
+							<reference ref="896457276"/>
+							<reference ref="505926526"/>
+						</object>
+						<reference key="parent" ref="1005"/>
+					</object>
+					<object class="IBObjectRecord">
+						<int key="objectID">3</int>
+						<reference key="object" ref="691871786"/>
+						<reference key="parent" ref="1002"/>
+					</object>
+					<object class="IBObjectRecord">
+						<int key="objectID">7</int>
+						<reference key="object" ref="896457276"/>
+						<object class="NSMutableArray" key="children">
+							<bool key="EncodedWithXMLCoder">YES</bool>
+							<reference ref="946741485"/>
+						</object>
+						<reference key="parent" ref="1006"/>
+					</object>
+					<object class="IBObjectRecord">
+						<int key="objectID">8</int>
+						<reference key="object" ref="946741485"/>
+						<reference key="parent" ref="896457276"/>
+					</object>
+					<object class="IBObjectRecord">
+						<int key="objectID">10</int>
+						<reference key="object" ref="113258462"/>
+						<object class="NSMutableArray" key="children">
+							<bool key="EncodedWithXMLCoder">YES</bool>
+							<reference ref="675814069"/>
+						</object>
+						<reference key="parent" ref="1006"/>
+					</object>
+					<object class="IBObjectRecord">
+						<int key="objectID">11</int>
+						<reference key="object" ref="675814069"/>
+						<reference key="parent" ref="113258462"/>
+					</object>
+					<object class="IBObjectRecord">
+						<int key="objectID">13</int>
+						<reference key="object" ref="505926526"/>
+						<object class="NSMutableArray" key="children">
+							<bool key="EncodedWithXMLCoder">YES</bool>
+							<reference ref="614450346"/>
+							<reference ref="949749883"/>
+							<reference ref="420834863"/>
+							<reference ref="801281011"/>
+						</object>
+						<reference key="parent" ref="1006"/>
+					</object>
+					<object class="IBObjectRecord">
+						<int key="objectID">14</int>
+						<reference key="object" ref="614450346"/>
+						<reference key="parent" ref="505926526"/>
+					</object>
+					<object class="IBObjectRecord">
+						<int key="objectID">15</int>
+						<reference key="object" ref="949749883"/>
+						<reference key="parent" ref="505926526"/>
+					</object>
+					<object class="IBObjectRecord">
+						<int key="objectID">16</int>
+						<reference key="object" ref="420834863"/>
+						<object class="NSMutableArray" key="children">
+							<bool key="EncodedWithXMLCoder">YES</bool>
+							<reference ref="152879606"/>
+							<reference ref="211559945"/>
+							<reference ref="786351807"/>
+							<reference ref="979909669"/>
+						</object>
+						<reference key="parent" ref="505926526"/>
+					</object>
+					<object class="IBObjectRecord">
+						<int key="objectID">17</int>
+						<reference key="object" ref="801281011"/>
+						<reference key="parent" ref="505926526"/>
+					</object>
+					<object class="IBObjectRecord">
+						<int key="objectID">18</int>
+						<reference key="object" ref="152879606"/>
+						<object class="NSMutableArray" key="children">
+							<bool key="EncodedWithXMLCoder">YES</bool>
+							<reference ref="5365232"/>
+						</object>
+						<reference key="parent" ref="420834863"/>
+					</object>
+					<object class="IBObjectRecord">
+						<int key="objectID">19</int>
+						<reference key="object" ref="211559945"/>
+						<object class="NSMutableArray" key="children">
+							<bool key="EncodedWithXMLCoder">YES</bool>
+							<reference ref="18307911"/>
+						</object>
+						<reference key="parent" ref="420834863"/>
+					</object>
+					<object class="IBObjectRecord">
+						<int key="objectID">20</int>
+						<reference key="object" ref="18307911"/>
+						<reference key="parent" ref="211559945"/>
+					</object>
+					<object class="IBObjectRecord">
+						<int key="objectID">21</int>
+						<reference key="object" ref="5365232"/>
+						<reference key="parent" ref="152879606"/>
+					</object>
+					<object class="IBObjectRecord">
+						<int key="objectID">22</int>
+						<reference key="object" ref="786351807"/>
+						<object class="NSMutableArray" key="children">
+							<bool key="EncodedWithXMLCoder">YES</bool>
+							<reference ref="909365266"/>
+						</object>
+						<reference key="parent" ref="420834863"/>
+					</object>
+					<object class="IBObjectRecord">
+						<int key="objectID">23</int>
+						<reference key="object" ref="909365266"/>
+						<reference key="parent" ref="786351807"/>
+					</object>
+					<object class="IBObjectRecord">
+						<int key="objectID">24</int>
+						<reference key="object" ref="979909669"/>
+						<object class="NSMutableArray" key="children">
+							<bool key="EncodedWithXMLCoder">YES</bool>
+							<reference ref="475532581"/>
+						</object>
+						<reference key="parent" ref="420834863"/>
+					</object>
+					<object class="IBObjectRecord">
+						<int key="objectID">25</int>
+						<reference key="object" ref="475532581"/>
+						<reference key="parent" ref="979909669"/>
+					</object>
+					<object class="IBObjectRecord">
+						<int key="objectID">40</int>
+						<reference key="object" ref="515955304"/>
+						<reference key="parent" ref="1002"/>
+					</object>
+					<object class="IBObjectRecord">
+						<int key="objectID">43</int>
+						<reference key="object" ref="233590295"/>
+						<reference key="parent" ref="1002"/>
+					</object>
+				</object>
+			</object>
+			<object class="NSMutableDictionary" key="flattenedProperties">
+				<bool key="EncodedWithXMLCoder">YES</bool>
+				<object class="NSMutableArray" key="dict.sortedKeys">
+					<bool key="EncodedWithXMLCoder">YES</bool>
+					<string>-1.IBPluginDependency</string>
+					<string>-2.IBPluginDependency</string>
+					<string>-3.IBPluginDependency</string>
+					<string>1.IBEditorWindowLastContentRect</string>
+					<string>1.IBPluginDependency</string>
+					<string>1.IBWindowTemplateEditedContentRect</string>
+					<string>1.NSWindowTemplate.visibleAtLaunch</string>
+					<string>1.WindowOrigin</string>
+					<string>1.editorWindowContentRectSynchronizationRect</string>
+					<string>10.IBPluginDependency</string>
+					<string>11.IBPluginDependency</string>
+					<string>13.IBPluginDependency</string>
+					<string>14.IBPluginDependency</string>
+					<string>15.IBPluginDependency</string>
+					<string>16.IBPluginDependency</string>
+					<string>17.IBPluginDependency</string>
+					<string>18.IBPluginDependency</string>
+					<string>19.IBPluginDependency</string>
+					<string>2.IBPluginDependency</string>
+					<string>20.IBPluginDependency</string>
+					<string>21.IBPluginDependency</string>
+					<string>3.IBPluginDependency</string>
+					<string>40.IBPluginDependency</string>
+					<string>43.IBPluginDependency</string>
+					<string>7.IBPluginDependency</string>
+					<string>8.IBPluginDependency</string>
+				</object>
+				<object class="NSMutableArray" key="dict.values">
+					<bool key="EncodedWithXMLCoder">YES</bool>
+					<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
+					<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
+					<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
+					<string>{{96, 101}, {487, 267}}</string>
+					<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
+					<string>{{96, 101}, {487, 267}}</string>
+					<reference ref="9"/>
+					<string>{196, 240}</string>
+					<string>{{357, 418}, {480, 270}}</string>
+					<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
+					<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
+					<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
+					<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
+					<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
+					<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
+					<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
+					<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
+					<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
+					<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
+					<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
+					<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
+					<string>com.clozure.ClozureCL.ibplugin</string>
+					<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
+					<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
+					<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
+					<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
+				</object>
+			</object>
+			<object class="NSMutableDictionary" key="unlocalizedProperties">
+				<bool key="EncodedWithXMLCoder">YES</bool>
+				<object class="NSArray" key="dict.sortedKeys">
+					<bool key="EncodedWithXMLCoder">YES</bool>
+				</object>
+				<object class="NSMutableArray" key="dict.values">
+					<bool key="EncodedWithXMLCoder">YES</bool>
+				</object>
+			</object>
+			<nil key="activeLocalization"/>
+			<object class="NSMutableDictionary" key="localizations">
+				<bool key="EncodedWithXMLCoder">YES</bool>
+				<object class="NSArray" key="dict.sortedKeys">
+					<bool key="EncodedWithXMLCoder">YES</bool>
+				</object>
+				<object class="NSMutableArray" key="dict.values">
+					<bool key="EncodedWithXMLCoder">YES</bool>
+				</object>
+			</object>
+			<nil key="sourceID"/>
+			<int key="maxID">73</int>
+		</object>
+		<object class="IBClassDescriber" key="IBDocument.Classes">
+			<object class="NSMutableArray" key="referencedPartialClassDescriptions">
+				<bool key="EncodedWithXMLCoder">YES</bool>
+				<object class="IBPartialClassDescription">
+					<string key="className">LispControllerTest</string>
+					<object class="NSMutableDictionary" key="outlets">
+						<string key="NS.key.0">lispCtrl</string>
+						<string key="NS.object.0">id</string>
+					</object>
+					<object class="IBClassDescriptionSource" key="sourceIdentifier">
+						<string key="majorKey">IBUserSource</string>
+						<string key="minorKey"/>
+					</object>
+				</object>
+			</object>
+		</object>
+		<int key="IBDocument.localizationMode">0</int>
+		<nil key="IBDocument.LastKnownRelativeProjectPath"/>
+		<int key="IBDocument.defaultPropertyAccessControl">3</int>
+	</data>
+</archive>
Index: /trunk/contrib/krueger/InterfaceProjects/Controller Test 2/controller-test2.lisp
===================================================================
--- /trunk/contrib/krueger/InterfaceProjects/Controller Test 2/controller-test2.lisp	(revision 13946)
+++ /trunk/contrib/krueger/InterfaceProjects/Controller Test 2/controller-test2.lisp	(revision 13946)
@@ -0,0 +1,40 @@
+;; controller-test2.lisp
+
+;; Test window that implements a class browser using an NSOutlineView to show
+;; standard Lisp class objects
+
+(eval-when (:compile-toplevel :load-toplevel :execute)
+  (require :lisp-controller)
+  (require :ns-string-utils))
+
+(defpackage :controller-test2
+  (:nicknames :ct2)
+  (:use :ccl :common-lisp :iu :lc)
+  (:export test-browser))
+
+(in-package :ct2)
+
+(defclass lisp-browser (ns:ns-window-controller)
+   ((lisp-ctrl :foreign-type :id :accessor lisp-ctrl))
+  (:metaclass ns:+ns-object))
+
+(objc:defmethod (#/initWithNibPath: :id)
+                ((self lisp-browser) (nib-path :id))
+  (let* ((init-self (#/initWithWindowNibPath:owner: self nib-path self)))
+    init-self))
+
+(defun cl-name (cls)
+  (symbol-name (class-name cls)))
+
+(defun cl-package (cls)
+  (package-name (symbol-package (class-name cls))))
+
+(defun test-browser ()
+  (let* ((nib-name (lisp-to-temp-nsstring
+                    (namestring (truename "ip:Controller Test 2;lc-test2.nib"))))
+         (wc (make-instance 'lisp-browser
+               :with-nib-path nib-name)))
+    (#/window wc)
+    wc))
+
+(provide :controller-test2)
Index: /trunk/contrib/krueger/InterfaceProjects/Controller Test 2/lc-test2.nib/designable.nib
===================================================================
--- /trunk/contrib/krueger/InterfaceProjects/Controller Test 2/lc-test2.nib/designable.nib	(revision 13946)
+++ /trunk/contrib/krueger/InterfaceProjects/Controller Test 2/lc-test2.nib/designable.nib	(revision 13946)
@@ -0,0 +1,577 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<archive type="com.apple.InterfaceBuilder3.Cocoa.XIB" version="7.03">
+	<data>
+		<int key="IBDocument.SystemTarget">1050</int>
+		<string key="IBDocument.SystemVersion">9L30</string>
+		<string key="IBDocument.InterfaceBuilderVersion">680</string>
+		<string key="IBDocument.AppKitVersion">949.54</string>
+		<string key="IBDocument.HIToolboxVersion">353.00</string>
+		<object class="NSMutableArray" key="IBDocument.EditedObjectIDs">
+			<bool key="EncodedWithXMLCoder">YES</bool>
+			<integer value="49"/>
+		</object>
+		<object class="NSArray" key="IBDocument.PluginDependencies">
+			<bool key="EncodedWithXMLCoder">YES</bool>
+			<string>com.clozure.ClozureCL.ibplugin</string>
+			<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
+		</object>
+		<object class="NSMutableDictionary" key="IBDocument.Metadata">
+			<bool key="EncodedWithXMLCoder">YES</bool>
+			<object class="NSArray" key="dict.sortedKeys">
+				<bool key="EncodedWithXMLCoder">YES</bool>
+			</object>
+			<object class="NSMutableArray" key="dict.values">
+				<bool key="EncodedWithXMLCoder">YES</bool>
+			</object>
+		</object>
+		<object class="NSMutableArray" key="IBDocument.RootObjects" id="1000">
+			<bool key="EncodedWithXMLCoder">YES</bool>
+			<object class="NSCustomObject" id="1001">
+				<string key="NSClassName">LispBrowser</string>
+			</object>
+			<object class="NSCustomObject" id="1003">
+				<string key="NSClassName">FirstResponder</string>
+			</object>
+			<object class="NSCustomObject" id="1004">
+				<string key="NSClassName">NSApplication</string>
+			</object>
+			<object class="NSWindowTemplate" id="1005">
+				<int key="NSWindowStyleMask">15</int>
+				<int key="NSWindowBacking">2</int>
+				<string key="NSWindowRect">{{196, 251}, {482, 259}}</string>
+				<int key="NSWTFlags">536870912</int>
+				<string key="NSWindowTitle">Class Browser</string>
+				<string key="NSWindowClass">NSWindow</string>
+				<nil key="NSViewClass"/>
+				<string key="NSWindowContentMaxSize">{3.40282e+38, 3.40282e+38}</string>
+				<string key="NSWindowContentMinSize">{482, 259}</string>
+				<object class="NSView" key="NSWindowView" id="1006">
+					<reference key="NSNextResponder"/>
+					<int key="NSvFlags">256</int>
+					<object class="NSMutableArray" key="NSSubviews">
+						<bool key="EncodedWithXMLCoder">YES</bool>
+						<object class="NSScrollView" id="1060842980">
+							<reference key="NSNextResponder" ref="1006"/>
+							<int key="NSvFlags">274</int>
+							<object class="NSMutableArray" key="NSSubviews">
+								<bool key="EncodedWithXMLCoder">YES</bool>
+								<object class="NSClipView" id="375811294">
+									<reference key="NSNextResponder" ref="1060842980"/>
+									<int key="NSvFlags">2304</int>
+									<object class="NSMutableArray" key="NSSubviews">
+										<bool key="EncodedWithXMLCoder">YES</bool>
+										<object class="NSOutlineView" id="1045897523">
+											<reference key="NSNextResponder" ref="375811294"/>
+											<int key="NSvFlags">274</int>
+											<string key="NSFrameSize">{445, 196}</string>
+											<reference key="NSSuperview" ref="375811294"/>
+											<bool key="NSEnabled">YES</bool>
+											<object class="NSTableHeaderView" key="NSHeaderView" id="403972319">
+												<reference key="NSNextResponder" ref="196060644"/>
+												<int key="NSvFlags">256</int>
+												<string key="NSFrameSize">{445, 17}</string>
+												<reference key="NSSuperview" ref="196060644"/>
+												<reference key="NSTableView" ref="1045897523"/>
+											</object>
+											<object class="_NSCornerView" key="NSCornerView" id="644891160">
+												<reference key="NSNextResponder" ref="1060842980"/>
+												<int key="NSvFlags">-2147483392</int>
+												<string key="NSFrame">{{-26, 0}, {16, 17}}</string>
+												<reference key="NSSuperview" ref="1060842980"/>
+											</object>
+											<object class="NSMutableArray" key="NSTableColumns">
+												<bool key="EncodedWithXMLCoder">YES</bool>
+												<object class="NSTableColumn" id="190046595">
+													<string type="base64-UTF8" key="NSIdentifier">IydjdDI6OmNsLW5hbWU</string>
+													<double key="NSWidth">2.780000e+02</double>
+													<double key="NSMinWidth">1.600000e+01</double>
+													<double key="NSMaxWidth">1.000000e+03</double>
+													<object class="NSTableHeaderCell" key="NSHeaderCell">
+														<int key="NSCellFlags">75628032</int>
+														<int key="NSCellFlags2">0</int>
+														<string key="NSContents">Class Name</string>
+														<object class="NSFont" key="NSSupport" id="26">
+															<string key="NSName">LucidaGrande</string>
+															<double key="NSSize">1.100000e+01</double>
+															<int key="NSfFlags">3100</int>
+														</object>
+														<object class="NSColor" key="NSBackgroundColor" id="377456851">
+															<int key="NSColorSpace">3</int>
+															<bytes key="NSWhite">MC4zMzMzMzI5OQA</bytes>
+														</object>
+														<object class="NSColor" key="NSTextColor" id="145989834">
+															<int key="NSColorSpace">6</int>
+															<string key="NSCatalogName">System</string>
+															<string key="NSColorName">headerTextColor</string>
+															<object class="NSColor" key="NSColor" id="122788521">
+																<int key="NSColorSpace">3</int>
+																<bytes key="NSWhite">MAA</bytes>
+															</object>
+														</object>
+													</object>
+													<object class="NSTextFieldCell" key="NSDataCell" id="508041835">
+														<int key="NSCellFlags">337772096</int>
+														<int key="NSCellFlags2">2048</int>
+														<string key="NSContents">Text Cell</string>
+														<object class="NSFont" key="NSSupport" id="389194177">
+															<string key="NSName">LucidaGrande</string>
+															<double key="NSSize">1.300000e+01</double>
+															<int key="NSfFlags">1044</int>
+														</object>
+														<reference key="NSControlView" ref="1045897523"/>
+														<object class="NSColor" key="NSBackgroundColor" id="686228904">
+															<int key="NSColorSpace">6</int>
+															<string key="NSCatalogName">System</string>
+															<string key="NSColorName">controlBackgroundColor</string>
+															<object class="NSColor" key="NSColor">
+																<int key="NSColorSpace">3</int>
+																<bytes key="NSWhite">MC42NjY2NjY2OQA</bytes>
+															</object>
+														</object>
+														<object class="NSColor" key="NSTextColor" id="557243287">
+															<int key="NSColorSpace">6</int>
+															<string key="NSCatalogName">System</string>
+															<string key="NSColorName">controlTextColor</string>
+															<reference key="NSColor" ref="122788521"/>
+														</object>
+													</object>
+													<int key="NSResizingMask">3</int>
+													<bool key="NSIsResizeable">YES</bool>
+													<reference key="NSTableView" ref="1045897523"/>
+												</object>
+												<object class="NSTableColumn" id="495767371">
+													<string type="base64-UTF8" key="NSIdentifier">IydjdDI6OmNsLXBhY2thZ2U</string>
+													<double key="NSWidth">1.610000e+02</double>
+													<double key="NSMinWidth">4.000000e+01</double>
+													<double key="NSMaxWidth">1.000000e+03</double>
+													<object class="NSTableHeaderCell" key="NSHeaderCell">
+														<int key="NSCellFlags">75628032</int>
+														<int key="NSCellFlags2">0</int>
+														<string key="NSContents">Package</string>
+														<reference key="NSSupport" ref="26"/>
+														<reference key="NSBackgroundColor" ref="377456851"/>
+														<reference key="NSTextColor" ref="145989834"/>
+													</object>
+													<object class="NSTextFieldCell" key="NSDataCell" id="408416411">
+														<int key="NSCellFlags">337772096</int>
+														<int key="NSCellFlags2">2048</int>
+														<string key="NSContents">Text Cell</string>
+														<reference key="NSSupport" ref="389194177"/>
+														<reference key="NSControlView" ref="1045897523"/>
+														<reference key="NSBackgroundColor" ref="686228904"/>
+														<reference key="NSTextColor" ref="557243287"/>
+													</object>
+													<int key="NSResizingMask">3</int>
+													<bool key="NSIsResizeable">YES</bool>
+													<reference key="NSTableView" ref="1045897523"/>
+												</object>
+											</object>
+											<double key="NSIntercellSpacingWidth">3.000000e+00</double>
+											<double key="NSIntercellSpacingHeight">2.000000e+00</double>
+											<object class="NSColor" key="NSBackgroundColor">
+												<int key="NSColorSpace">3</int>
+												<bytes key="NSWhite">MQA</bytes>
+											</object>
+											<object class="NSColor" key="NSGridColor">
+												<int key="NSColorSpace">6</int>
+												<string key="NSCatalogName">System</string>
+												<string key="NSColorName">gridColor</string>
+												<object class="NSColor" key="NSColor">
+													<int key="NSColorSpace">3</int>
+													<bytes key="NSWhite">MC41AA</bytes>
+												</object>
+											</object>
+											<double key="NSRowHeight">1.700000e+01</double>
+											<int key="NSTvFlags">-767557632</int>
+											<int key="NSColumnAutoresizingStyle">5</int>
+											<int key="NSDraggingSourceMaskForLocal">15</int>
+											<int key="NSDraggingSourceMaskForNonLocal">0</int>
+											<bool key="NSAllowsTypeSelect">YES</bool>
+										</object>
+									</object>
+									<string key="NSFrame">{{1, 17}, {445, 196}}</string>
+									<reference key="NSSuperview" ref="1060842980"/>
+									<reference key="NSNextKeyView" ref="1045897523"/>
+									<reference key="NSDocView" ref="1045897523"/>
+									<reference key="NSBGColor" ref="686228904"/>
+									<int key="NScvFlags">4</int>
+								</object>
+								<object class="NSScroller" id="321977608">
+									<reference key="NSNextResponder" ref="1060842980"/>
+									<int key="NSvFlags">-2147483392</int>
+									<string key="NSFrame">{{431, 17}, {15, 181}}</string>
+									<reference key="NSSuperview" ref="1060842980"/>
+									<reference key="NSTarget" ref="1060842980"/>
+									<string key="NSAction">_doScroller:</string>
+									<double key="NSPercent">9.171271e-01</double>
+								</object>
+								<object class="NSScroller" id="787488017">
+									<reference key="NSNextResponder" ref="1060842980"/>
+									<int key="NSvFlags">-2147483392</int>
+									<string key="NSFrame">{{1, 198}, {445, 15}}</string>
+									<reference key="NSSuperview" ref="1060842980"/>
+									<int key="NSsFlags">1</int>
+									<reference key="NSTarget" ref="1060842980"/>
+									<string key="NSAction">_doScroller:</string>
+									<double key="NSPercent">3.457654e-01</double>
+								</object>
+								<object class="NSClipView" id="196060644">
+									<reference key="NSNextResponder" ref="1060842980"/>
+									<int key="NSvFlags">2304</int>
+									<object class="NSMutableArray" key="NSSubviews">
+										<bool key="EncodedWithXMLCoder">YES</bool>
+										<reference ref="403972319"/>
+									</object>
+									<string key="NSFrame">{{1, 0}, {445, 17}}</string>
+									<reference key="NSSuperview" ref="1060842980"/>
+									<reference key="NSNextKeyView" ref="403972319"/>
+									<reference key="NSDocView" ref="403972319"/>
+									<reference key="NSBGColor" ref="686228904"/>
+									<int key="NScvFlags">4</int>
+								</object>
+								<reference ref="644891160"/>
+							</object>
+							<string key="NSFrame">{{20, 20}, {447, 214}}</string>
+							<reference key="NSSuperview" ref="1006"/>
+							<reference key="NSNextKeyView" ref="375811294"/>
+							<int key="NSsFlags">562</int>
+							<reference key="NSVScroller" ref="321977608"/>
+							<reference key="NSHScroller" ref="787488017"/>
+							<reference key="NSContentView" ref="375811294"/>
+							<reference key="NSHeaderClipView" ref="196060644"/>
+							<reference key="NSCornerView" ref="644891160"/>
+							<bytes key="NSScrollAmts">QSAAAEEgAABBmAAAQZgAAA</bytes>
+						</object>
+					</object>
+					<string key="NSFrameSize">{482, 259}</string>
+					<reference key="NSSuperview"/>
+				</object>
+				<string key="NSScreenRect">{{0, 0}, {1680, 1028}}</string>
+				<string key="NSMinSize">{482, 281}</string>
+				<string key="NSMaxSize">{3.40282e+38, 3.40282e+38}</string>
+			</object>
+			<object class="LispController" id="775414032">
+				<object class="NSMutableArray" key="typeInfo">
+					<bool key="EncodedWithXMLCoder">YES</bool>
+					<object class="NSMutableArray">
+						<bool key="EncodedWithXMLCoder">YES</bool>
+						<string>class</string>
+						<string>class</string>
+						<string type="base64-UTF8">IydjY2w6OmNsYXNzLWRpcmVjdC1zdWJjbGFzc2VzA</string>
+					</object>
+					<object class="NSMutableArray">
+						<bool key="EncodedWithXMLCoder">YES</bool>
+						<string type="base64-UTF8">PG5ldyB0eXBlPg</string>
+						<string/>
+						<string/>
+					</object>
+				</object>
+				<object class="NSMutableArray" key="initforms">
+					<bool key="EncodedWithXMLCoder">YES</bool>
+					<object class="NSMutableArray">
+						<bool key="EncodedWithXMLCoder">YES</bool>
+						<string>class</string>
+						<string>(find-class t)</string>
+					</object>
+					<object class="NSMutableArray">
+						<bool key="EncodedWithXMLCoder">YES</bool>
+						<string type="base64-UTF8">PG5ldyB0eXBlPg</string>
+						<string/>
+					</object>
+				</object>
+				<object class="NSMutableArray" key="sortInfo">
+					<bool key="EncodedWithXMLCoder">YES</bool>
+					<object class="NSMutableArray">
+						<bool key="EncodedWithXMLCoder">YES</bool>
+						<string>class</string>
+						<string type="base64-UTF8">IydjdDI6OmNsLW5hbWU</string>
+						<string type="base64-UTF8">IydzdHJpbmc8A</string>
+					</object>
+					<object class="NSMutableArray">
+						<bool key="EncodedWithXMLCoder">YES</bool>
+						<string type="base64-UTF8">PG5ldyB0eXBlPg</string>
+						<string/>
+						<string/>
+					</object>
+				</object>
+				<string key="rootType">class</string>
+				<string key="readerFunc"/>
+				<string key="writerFunc"/>
+				<string key="countFunc"/>
+				<string key="selectFunc"/>
+				<string key="editedFunc"/>
+				<nil key="addedFunc"/>
+				<nil key="removedFunc"/>
+				<string key="deleteFunc"/>
+				<string key="addChildFunc"/>
+				<string key="childrenFunc"/>
+				<bool key="genRoot">YES</bool>
+			</object>
+		</object>
+		<object class="IBObjectContainer" key="IBDocument.Objects">
+			<object class="NSMutableArray" key="connectionRecords">
+				<bool key="EncodedWithXMLCoder">YES</bool>
+				<object class="IBConnectionRecord">
+					<object class="IBOutletConnection" key="connection">
+						<string key="label">delegate</string>
+						<reference key="source" ref="1005"/>
+						<reference key="destination" ref="1001"/>
+					</object>
+					<int key="connectionID">32</int>
+				</object>
+				<object class="IBConnectionRecord">
+					<object class="IBOutletConnection" key="connection">
+						<string key="label">delegate</string>
+						<reference key="source" ref="1045897523"/>
+						<reference key="destination" ref="775414032"/>
+					</object>
+					<int key="connectionID">65</int>
+				</object>
+				<object class="IBConnectionRecord">
+					<object class="IBOutletConnection" key="connection">
+						<string key="label">dataSource</string>
+						<reference key="source" ref="1045897523"/>
+						<reference key="destination" ref="775414032"/>
+					</object>
+					<int key="connectionID">66</int>
+				</object>
+				<object class="IBConnectionRecord">
+					<object class="IBOutletConnection" key="connection">
+						<string key="label">view</string>
+						<reference key="source" ref="775414032"/>
+						<reference key="destination" ref="1045897523"/>
+					</object>
+					<int key="connectionID">67</int>
+				</object>
+				<object class="IBConnectionRecord">
+					<object class="IBOutletConnection" key="connection">
+						<string key="label">owner</string>
+						<reference key="source" ref="775414032"/>
+						<reference key="destination" ref="1001"/>
+					</object>
+					<int key="connectionID">68</int>
+				</object>
+				<object class="IBConnectionRecord">
+					<object class="IBOutletConnection" key="connection">
+						<string key="label">lispCtrl</string>
+						<reference key="source" ref="1001"/>
+						<reference key="destination" ref="775414032"/>
+					</object>
+					<int key="connectionID">69</int>
+				</object>
+			</object>
+			<object class="IBMutableOrderedSet" key="objectRecords">
+				<object class="NSArray" key="orderedObjects">
+					<bool key="EncodedWithXMLCoder">YES</bool>
+					<object class="IBObjectRecord">
+						<int key="objectID">0</int>
+						<object class="NSArray" key="object" id="1002">
+							<bool key="EncodedWithXMLCoder">YES</bool>
+						</object>
+						<reference key="children" ref="1000"/>
+						<nil key="parent"/>
+					</object>
+					<object class="IBObjectRecord">
+						<int key="objectID">-2</int>
+						<reference key="object" ref="1001"/>
+						<reference key="parent" ref="1002"/>
+						<string type="base64-UTF8" key="objectName">RmlsZSdzIE93bmVyA</string>
+					</object>
+					<object class="IBObjectRecord">
+						<int key="objectID">-1</int>
+						<reference key="object" ref="1003"/>
+						<reference key="parent" ref="1002"/>
+						<string key="objectName">First Responder</string>
+					</object>
+					<object class="IBObjectRecord">
+						<int key="objectID">-3</int>
+						<reference key="object" ref="1004"/>
+						<reference key="parent" ref="1002"/>
+						<string key="objectName">Application</string>
+					</object>
+					<object class="IBObjectRecord">
+						<int key="objectID">1</int>
+						<reference key="object" ref="1005"/>
+						<object class="NSMutableArray" key="children">
+							<bool key="EncodedWithXMLCoder">YES</bool>
+							<reference ref="1006"/>
+						</object>
+						<reference key="parent" ref="1002"/>
+					</object>
+					<object class="IBObjectRecord">
+						<int key="objectID">2</int>
+						<reference key="object" ref="1006"/>
+						<object class="NSMutableArray" key="children">
+							<bool key="EncodedWithXMLCoder">YES</bool>
+							<reference ref="1060842980"/>
+						</object>
+						<reference key="parent" ref="1005"/>
+					</object>
+					<object class="IBObjectRecord">
+						<int key="objectID">45</int>
+						<reference key="object" ref="775414032"/>
+						<reference key="parent" ref="1002"/>
+					</object>
+					<object class="IBObjectRecord">
+						<int key="objectID">46</int>
+						<reference key="object" ref="1060842980"/>
+						<object class="NSMutableArray" key="children">
+							<bool key="EncodedWithXMLCoder">YES</bool>
+							<reference ref="321977608"/>
+							<reference ref="787488017"/>
+							<reference ref="1045897523"/>
+							<reference ref="403972319"/>
+						</object>
+						<reference key="parent" ref="1006"/>
+					</object>
+					<object class="IBObjectRecord">
+						<int key="objectID">47</int>
+						<reference key="object" ref="321977608"/>
+						<reference key="parent" ref="1060842980"/>
+					</object>
+					<object class="IBObjectRecord">
+						<int key="objectID">48</int>
+						<reference key="object" ref="787488017"/>
+						<reference key="parent" ref="1060842980"/>
+					</object>
+					<object class="IBObjectRecord">
+						<int key="objectID">49</int>
+						<reference key="object" ref="1045897523"/>
+						<object class="NSMutableArray" key="children">
+							<bool key="EncodedWithXMLCoder">YES</bool>
+							<reference ref="190046595"/>
+							<reference ref="495767371"/>
+						</object>
+						<reference key="parent" ref="1060842980"/>
+					</object>
+					<object class="IBObjectRecord">
+						<int key="objectID">50</int>
+						<reference key="object" ref="403972319"/>
+						<reference key="parent" ref="1060842980"/>
+					</object>
+					<object class="IBObjectRecord">
+						<int key="objectID">51</int>
+						<reference key="object" ref="190046595"/>
+						<object class="NSMutableArray" key="children">
+							<bool key="EncodedWithXMLCoder">YES</bool>
+							<reference ref="508041835"/>
+						</object>
+						<reference key="parent" ref="1045897523"/>
+					</object>
+					<object class="IBObjectRecord">
+						<int key="objectID">52</int>
+						<reference key="object" ref="495767371"/>
+						<object class="NSMutableArray" key="children">
+							<bool key="EncodedWithXMLCoder">YES</bool>
+							<reference ref="408416411"/>
+						</object>
+						<reference key="parent" ref="1045897523"/>
+					</object>
+					<object class="IBObjectRecord">
+						<int key="objectID">53</int>
+						<reference key="object" ref="408416411"/>
+						<reference key="parent" ref="495767371"/>
+					</object>
+					<object class="IBObjectRecord">
+						<int key="objectID">54</int>
+						<reference key="object" ref="508041835"/>
+						<reference key="parent" ref="190046595"/>
+					</object>
+				</object>
+			</object>
+			<object class="NSMutableDictionary" key="flattenedProperties">
+				<bool key="EncodedWithXMLCoder">YES</bool>
+				<object class="NSMutableArray" key="dict.sortedKeys">
+					<bool key="EncodedWithXMLCoder">YES</bool>
+					<string>-1.IBPluginDependency</string>
+					<string>-2.IBPluginDependency</string>
+					<string>-3.IBPluginDependency</string>
+					<string>1.IBEditorWindowLastContentRect</string>
+					<string>1.IBPluginDependency</string>
+					<string>1.IBWindowTemplateEditedContentRect</string>
+					<string>1.NSWindowTemplate.visibleAtLaunch</string>
+					<string>1.WindowOrigin</string>
+					<string>1.editorWindowContentRectSynchronizationRect</string>
+					<string>1.windowTemplate.hasMinSize</string>
+					<string>1.windowTemplate.minSize</string>
+					<string>2.IBPluginDependency</string>
+					<string>45.IBPluginDependency</string>
+					<string>46.IBPluginDependency</string>
+					<string>47.IBPluginDependency</string>
+					<string>48.IBPluginDependency</string>
+					<string>49.IBPluginDependency</string>
+					<string>50.IBPluginDependency</string>
+					<string>51.IBPluginDependency</string>
+					<string>52.IBPluginDependency</string>
+					<string>53.IBPluginDependency</string>
+					<string>54.IBPluginDependency</string>
+				</object>
+				<object class="NSMutableArray" key="dict.values">
+					<bool key="EncodedWithXMLCoder">YES</bool>
+					<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
+					<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
+					<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
+					<string>{{52, 587}, {482, 259}}</string>
+					<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
+					<string>{{52, 587}, {482, 259}}</string>
+					<integer value="1"/>
+					<string>{196, 240}</string>
+					<string>{{357, 418}, {480, 270}}</string>
+					<boolean value="YES"/>
+					<string>{482, 259}</string>
+					<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
+					<string>com.clozure.ClozureCL.ibplugin</string>
+					<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
+					<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
+					<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
+					<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
+					<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
+					<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
+					<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
+					<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
+					<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
+				</object>
+			</object>
+			<object class="NSMutableDictionary" key="unlocalizedProperties">
+				<bool key="EncodedWithXMLCoder">YES</bool>
+				<object class="NSArray" key="dict.sortedKeys">
+					<bool key="EncodedWithXMLCoder">YES</bool>
+				</object>
+				<object class="NSMutableArray" key="dict.values">
+					<bool key="EncodedWithXMLCoder">YES</bool>
+				</object>
+			</object>
+			<nil key="activeLocalization"/>
+			<object class="NSMutableDictionary" key="localizations">
+				<bool key="EncodedWithXMLCoder">YES</bool>
+				<object class="NSArray" key="dict.sortedKeys">
+					<bool key="EncodedWithXMLCoder">YES</bool>
+				</object>
+				<object class="NSMutableArray" key="dict.values">
+					<bool key="EncodedWithXMLCoder">YES</bool>
+				</object>
+			</object>
+			<nil key="sourceID"/>
+			<int key="maxID">70</int>
+		</object>
+		<object class="IBClassDescriber" key="IBDocument.Classes">
+			<object class="NSMutableArray" key="referencedPartialClassDescriptions">
+				<bool key="EncodedWithXMLCoder">YES</bool>
+				<object class="IBPartialClassDescription">
+					<string key="className">LispBrowser</string>
+					<object class="NSMutableDictionary" key="outlets">
+						<string key="NS.key.0">lispCtrl</string>
+						<string key="NS.object.0">id</string>
+					</object>
+					<object class="IBClassDescriptionSource" key="sourceIdentifier">
+						<string key="majorKey">IBUserSource</string>
+						<string key="minorKey"/>
+					</object>
+				</object>
+			</object>
+		</object>
+		<int key="IBDocument.localizationMode">0</int>
+		<nil key="IBDocument.LastKnownRelativeProjectPath"/>
+		<int key="IBDocument.defaultPropertyAccessControl">3</int>
+	</data>
+</archive>
Index: /trunk/contrib/krueger/InterfaceProjects/Controller Test 3/controller-test3.lisp
===================================================================
--- /trunk/contrib/krueger/InterfaceProjects/Controller Test 3/controller-test3.lisp	(revision 13946)
+++ /trunk/contrib/krueger/InterfaceProjects/Controller Test 3/controller-test3.lisp	(revision 13946)
@@ -0,0 +1,136 @@
+;; controller-test3.lisp
+
+;; Test window that shows an assoc-array using an NSOutlineView to show
+;; each level of the array (which are nested hash-tables).
+
+(eval-when (:compile-toplevel :load-toplevel :execute)
+  (require :lisp-controller)
+  (require :ns-string-utils)
+  (require :list-utils)
+  (require :assoc-array))
+
+(defpackage :controller-test3
+  (:nicknames :ct3)
+  (:use :ccl :common-lisp :iu :lc)
+  (:export test-deal))
+
+(in-package :ct3)
+
+(defclass hand-of-cards (ns:ns-window-controller)
+   ((lisp-ctrl :foreign-type :id :accessor lisp-ctrl))
+  (:metaclass ns:+ns-object))
+
+(objc:defmethod (#/initWithNibPath: :id)
+                ((self hand-of-cards) (nib-path :id))
+  (let* ((init-self (#/initWithWindowNibPath:owner: self nib-path self)))
+    init-self))
+
+(objc:defmethod (#/deal: :void)
+                ((self hand-of-cards) (sender :id))
+  (declare (ignore sender))
+  (unless (eql (lisp-ctrl self) (%null-ptr))
+    (setf (root (lisp-ctrl self)) (deal-cards))))
+
+(defun hand-children (hand)
+  ;; hand will be an assoc-array
+  (iu::index1-ht hand))
+
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;;
+;; Utility Functions for hands
+;;
+;; A hand is represented as a bit vector that is 52 bits long. Cards in the hand
+;; have a corresponding bit value of 1. Cards not in the hand have a corresponding
+;; bit of 0.
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+
+(deftype rank-list ()
+  '(satisfies all-ranks))
+
+(defconstant *aces* #*1000000000000100000000000010000000000001000000000000)
+(defconstant *kings* #*0100000000000010000000000001000000000000100000000000)
+(defconstant *queens* #*0010000000000001000000000000100000000000010000000000)
+(defconstant *jacks* #*0001000000000000100000000000010000000000001000000000)
+(defconstant *spades* #*1111111111111000000000000000000000000000000000000000)
+(defconstant *hearts* #*0000000000000111111111111100000000000000000000000000)
+(defconstant *diamonds* #*0000000000000000000000000011111111111110000000000000)
+(defconstant *clubs* #*0000000000000000000000000000000000000001111111111111)
+(defconstant *card-ranks* '("A" "K" "Q" "J" "10" "9" "8" "7" "6" "5" "4" "3" "2"))
+(defconstant *card-suits* '("Spades" "Hearts" "Diamonds" "Clubs"))
+(defconstant *hand-suits* '("Spades" "Hearts" "Diamonds" "Clubs" "North" "East" "South" "West"))
+
+(defun full-deck ()
+  (make-array '(52) :element-type 'bit :initial-element 1))
+
+(defun card-rank (card)
+  ;; card is a bit index
+  (nth (mod card 13) *card-ranks*))
+
+(defun all-ranks (rank-list)
+  (and (listp rank-list)
+       (null (set-difference rank-list *card-ranks* :test #'string=))))
+
+(defun hand-suit-order (a b)
+  (< (position a *hand-suits* :test #'string=) (position b *hand-suits* :test #'string=)))
+
+(defun higher-rank (r1 r2)
+  (< (position r1 *card-ranks* :test #'string=) (position r2 *card-ranks* :test #'string=)))
+
+(defun sorted-by-rank (rlist)
+  (when (typep rlist 'rank-list)
+    (format nil "~{~a~^, ~}" (sort-list-in-place rlist #'higher-rank))))
+
+(defun card-suit (card)
+  ;; card is a bit index
+  (nth (floor card 13) *card-suits*))
+
+(defun pick-random-card (deck)
+  ;; returns a card index
+  (let* ((cnt (count 1 deck))
+         (card (1+ (random cnt))))
+    (position-if #'(lambda (bit)
+                     (when (plusp bit)
+                       (decf card))
+                     (zerop card))
+                 deck)))
+
+(defun add-card (deal hand card)
+  (setf (assoc-aref deal hand (card-suit card))
+        (cons (card-rank card) (assoc-aref deal hand (card-suit card)))))
+
+(defun remove-card (card deck)
+  ;; card is a bit index
+  (setf (aref deck card) 0))
+
+(defun deal-cards ()
+  ;; randomizes and returns four unique hands
+  (let ((deck (full-deck))
+        (deal (make-instance 'assoc-array :rank 2))
+        (card nil))
+    (dotimes (i 13)
+      (setf card (pick-random-card deck))
+      (add-card deal "West" card)
+      (remove-card card deck)
+      (setf card (pick-random-card deck))
+      (add-card deal "North" card)
+      (remove-card card deck)
+      (setf card (pick-random-card deck))
+      (add-card deal "East" card)
+      (remove-card card deck)
+      (setf card (pick-random-card deck))
+      (add-card deal "South" card)
+      (remove-card card deck))
+    deal))
+
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;; Test Function
+
+(defun test-deal ()
+  (let* ((nib-name (lisp-to-temp-nsstring
+                    (namestring (truename "ip:Controller Test 3;lc-test3.nib"))))
+         (wc (make-instance 'hand-of-cards
+               :with-nib-path nib-name)))
+    (#/window wc)
+    wc))
+
+(provide :controller-test3)
Index: /trunk/contrib/krueger/InterfaceProjects/Controller Test 3/lc-test3.nib/designable.nib
===================================================================
--- /trunk/contrib/krueger/InterfaceProjects/Controller Test 3/lc-test3.nib/designable.nib	(revision 13946)
+++ /trunk/contrib/krueger/InterfaceProjects/Controller Test 3/lc-test3.nib/designable.nib	(revision 13946)
@@ -0,0 +1,630 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<archive type="com.apple.InterfaceBuilder3.Cocoa.XIB" version="7.03">
+	<data>
+		<int key="IBDocument.SystemTarget">1050</int>
+		<string key="IBDocument.SystemVersion">9L30</string>
+		<string key="IBDocument.InterfaceBuilderVersion">680</string>
+		<string key="IBDocument.AppKitVersion">949.54</string>
+		<string key="IBDocument.HIToolboxVersion">353.00</string>
+		<object class="NSMutableArray" key="IBDocument.EditedObjectIDs">
+			<bool key="EncodedWithXMLCoder">YES</bool>
+			<integer value="49"/>
+		</object>
+		<object class="NSArray" key="IBDocument.PluginDependencies">
+			<bool key="EncodedWithXMLCoder">YES</bool>
+			<string>com.clozure.ClozureCL.ibplugin</string>
+			<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
+		</object>
+		<object class="NSMutableDictionary" key="IBDocument.Metadata">
+			<bool key="EncodedWithXMLCoder">YES</bool>
+			<object class="NSArray" key="dict.sortedKeys">
+				<bool key="EncodedWithXMLCoder">YES</bool>
+			</object>
+			<object class="NSMutableArray" key="dict.values">
+				<bool key="EncodedWithXMLCoder">YES</bool>
+			</object>
+		</object>
+		<object class="NSMutableArray" key="IBDocument.RootObjects" id="1000">
+			<bool key="EncodedWithXMLCoder">YES</bool>
+			<object class="NSCustomObject" id="1001">
+				<string key="NSClassName">HandOfCards</string>
+			</object>
+			<object class="NSCustomObject" id="1003">
+				<string key="NSClassName">FirstResponder</string>
+			</object>
+			<object class="NSCustomObject" id="1004">
+				<string key="NSClassName">NSApplication</string>
+			</object>
+			<object class="NSWindowTemplate" id="1005">
+				<int key="NSWindowStyleMask">15</int>
+				<int key="NSWindowBacking">2</int>
+				<string key="NSWindowRect">{{196, 213}, {487, 297}}</string>
+				<int key="NSWTFlags">536870912</int>
+				<string key="NSWindowTitle">Deal It!</string>
+				<string key="NSWindowClass">NSWindow</string>
+				<nil key="NSViewClass"/>
+				<string key="NSWindowContentMaxSize">{3.40282e+38, 3.40282e+38}</string>
+				<string key="NSWindowContentMinSize">{482, 259}</string>
+				<object class="NSView" key="NSWindowView" id="1006">
+					<reference key="NSNextResponder"/>
+					<int key="NSvFlags">256</int>
+					<object class="NSMutableArray" key="NSSubviews">
+						<bool key="EncodedWithXMLCoder">YES</bool>
+						<object class="NSScrollView" id="1060842980">
+							<reference key="NSNextResponder" ref="1006"/>
+							<int key="NSvFlags">274</int>
+							<object class="NSMutableArray" key="NSSubviews">
+								<bool key="EncodedWithXMLCoder">YES</bool>
+								<object class="NSClipView" id="375811294">
+									<reference key="NSNextResponder" ref="1060842980"/>
+									<int key="NSvFlags">2304</int>
+									<object class="NSMutableArray" key="NSSubviews">
+										<bool key="EncodedWithXMLCoder">YES</bool>
+										<object class="NSOutlineView" id="1045897523">
+											<reference key="NSNextResponder" ref="375811294"/>
+											<int key="NSvFlags">274</int>
+											<string key="NSFrameSize">{445, 196}</string>
+											<reference key="NSSuperview" ref="375811294"/>
+											<bool key="NSEnabled">YES</bool>
+											<object class="NSTableHeaderView" key="NSHeaderView" id="403972319">
+												<reference key="NSNextResponder" ref="196060644"/>
+												<int key="NSvFlags">256</int>
+												<string key="NSFrameSize">{445, 17}</string>
+												<reference key="NSSuperview" ref="196060644"/>
+												<reference key="NSTableView" ref="1045897523"/>
+											</object>
+											<object class="_NSCornerView" key="NSCornerView" id="644891160">
+												<reference key="NSNextResponder" ref="1060842980"/>
+												<int key="NSvFlags">-2147483392</int>
+												<string key="NSFrame">{{-26, 0}, {16, 17}}</string>
+												<reference key="NSSuperview" ref="1060842980"/>
+											</object>
+											<object class="NSMutableArray" key="NSTableColumns">
+												<bool key="EncodedWithXMLCoder">YES</bool>
+												<object class="NSTableColumn" id="190046595">
+													<string key="NSIdentifier">:key</string>
+													<double key="NSWidth">2.070000e+02</double>
+													<double key="NSMinWidth">1.600000e+01</double>
+													<double key="NSMaxWidth">1.000000e+03</double>
+													<object class="NSTableHeaderCell" key="NSHeaderCell">
+														<int key="NSCellFlags">75628032</int>
+														<int key="NSCellFlags2">0</int>
+														<string key="NSContents">Position and Suit</string>
+														<object class="NSFont" key="NSSupport" id="26">
+															<string key="NSName">LucidaGrande</string>
+															<double key="NSSize">1.100000e+01</double>
+															<int key="NSfFlags">3100</int>
+														</object>
+														<object class="NSColor" key="NSBackgroundColor" id="377456851">
+															<int key="NSColorSpace">3</int>
+															<bytes key="NSWhite">MC4zMzMzMzI5OQA</bytes>
+														</object>
+														<object class="NSColor" key="NSTextColor" id="145989834">
+															<int key="NSColorSpace">6</int>
+															<string key="NSCatalogName">System</string>
+															<string key="NSColorName">headerTextColor</string>
+															<object class="NSColor" key="NSColor" id="122788521">
+																<int key="NSColorSpace">3</int>
+																<bytes key="NSWhite">MAA</bytes>
+															</object>
+														</object>
+													</object>
+													<object class="NSTextFieldCell" key="NSDataCell" id="508041835">
+														<int key="NSCellFlags">337772096</int>
+														<int key="NSCellFlags2">2048</int>
+														<string key="NSContents">Text Cell</string>
+														<object class="NSFont" key="NSSupport" id="389194177">
+															<string key="NSName">LucidaGrande</string>
+															<double key="NSSize">1.300000e+01</double>
+															<int key="NSfFlags">1044</int>
+														</object>
+														<reference key="NSControlView" ref="1045897523"/>
+														<object class="NSColor" key="NSBackgroundColor" id="686228904">
+															<int key="NSColorSpace">6</int>
+															<string key="NSCatalogName">System</string>
+															<string key="NSColorName">controlBackgroundColor</string>
+															<object class="NSColor" key="NSColor">
+																<int key="NSColorSpace">3</int>
+																<bytes key="NSWhite">MC42NjY2NjY2OQA</bytes>
+															</object>
+														</object>
+														<object class="NSColor" key="NSTextColor" id="557243287">
+															<int key="NSColorSpace">6</int>
+															<string key="NSCatalogName">System</string>
+															<string key="NSColorName">controlTextColor</string>
+															<reference key="NSColor" ref="122788521"/>
+														</object>
+													</object>
+													<int key="NSResizingMask">3</int>
+													<bool key="NSIsResizeable">YES</bool>
+													<reference key="NSTableView" ref="1045897523"/>
+												</object>
+												<object class="NSTableColumn" id="495767371">
+													<string type="base64-UTF8" key="NSIdentifier">IydjdDM6OnNvcnRlZC1ieS1yYW5rA</string>
+													<double key="NSWidth">2.320000e+02</double>
+													<double key="NSMinWidth">4.000000e+01</double>
+													<double key="NSMaxWidth">1.000000e+03</double>
+													<object class="NSTableHeaderCell" key="NSHeaderCell">
+														<int key="NSCellFlags">75628032</int>
+														<int key="NSCellFlags2">0</int>
+														<string key="NSContents">Cards</string>
+														<reference key="NSSupport" ref="26"/>
+														<reference key="NSBackgroundColor" ref="377456851"/>
+														<reference key="NSTextColor" ref="145989834"/>
+													</object>
+													<object class="NSTextFieldCell" key="NSDataCell" id="408416411">
+														<int key="NSCellFlags">337772096</int>
+														<int key="NSCellFlags2">2048</int>
+														<string key="NSContents">Text Cell</string>
+														<reference key="NSSupport" ref="389194177"/>
+														<reference key="NSControlView" ref="1045897523"/>
+														<reference key="NSBackgroundColor" ref="686228904"/>
+														<reference key="NSTextColor" ref="557243287"/>
+													</object>
+													<int key="NSResizingMask">2</int>
+													<bool key="NSIsResizeable">YES</bool>
+													<reference key="NSTableView" ref="1045897523"/>
+												</object>
+											</object>
+											<double key="NSIntercellSpacingWidth">3.000000e+00</double>
+											<double key="NSIntercellSpacingHeight">2.000000e+00</double>
+											<object class="NSColor" key="NSBackgroundColor">
+												<int key="NSColorSpace">3</int>
+												<bytes key="NSWhite">MQA</bytes>
+											</object>
+											<object class="NSColor" key="NSGridColor">
+												<int key="NSColorSpace">6</int>
+												<string key="NSCatalogName">System</string>
+												<string key="NSColorName">gridColor</string>
+												<object class="NSColor" key="NSColor">
+													<int key="NSColorSpace">3</int>
+													<bytes key="NSWhite">MC41AA</bytes>
+												</object>
+											</object>
+											<double key="NSRowHeight">1.700000e+01</double>
+											<int key="NSTvFlags">-767524864</int>
+											<int key="NSColumnAutoresizingStyle">1</int>
+											<int key="NSDraggingSourceMaskForLocal">15</int>
+											<int key="NSDraggingSourceMaskForNonLocal">0</int>
+											<bool key="NSAllowsTypeSelect">YES</bool>
+										</object>
+									</object>
+									<string key="NSFrame">{{1, 17}, {445, 196}}</string>
+									<reference key="NSSuperview" ref="1060842980"/>
+									<reference key="NSNextKeyView" ref="1045897523"/>
+									<reference key="NSDocView" ref="1045897523"/>
+									<reference key="NSBGColor" ref="686228904"/>
+									<int key="NScvFlags">4</int>
+								</object>
+								<object class="NSScroller" id="321977608">
+									<reference key="NSNextResponder" ref="1060842980"/>
+									<int key="NSvFlags">-2147483392</int>
+									<string key="NSFrame">{{431, 17}, {15, 181}}</string>
+									<reference key="NSSuperview" ref="1060842980"/>
+									<reference key="NSTarget" ref="1060842980"/>
+									<string key="NSAction">_doScroller:</string>
+									<double key="NSPercent">9.234694e-01</double>
+								</object>
+								<object class="NSScroller" id="787488017">
+									<reference key="NSNextResponder" ref="1060842980"/>
+									<int key="NSvFlags">-2147483392</int>
+									<string key="NSFrame">{{1, 198}, {445, 15}}</string>
+									<reference key="NSSuperview" ref="1060842980"/>
+									<int key="NSsFlags">1</int>
+									<reference key="NSTarget" ref="1060842980"/>
+									<string key="NSAction">_doScroller:</string>
+									<double key="NSCurValue">1.000000e+00</double>
+									<double key="NSPercent">9.845133e-01</double>
+								</object>
+								<object class="NSClipView" id="196060644">
+									<reference key="NSNextResponder" ref="1060842980"/>
+									<int key="NSvFlags">2304</int>
+									<object class="NSMutableArray" key="NSSubviews">
+										<bool key="EncodedWithXMLCoder">YES</bool>
+										<reference ref="403972319"/>
+									</object>
+									<string key="NSFrame">{{1, 0}, {445, 17}}</string>
+									<reference key="NSSuperview" ref="1060842980"/>
+									<reference key="NSNextKeyView" ref="403972319"/>
+									<reference key="NSDocView" ref="403972319"/>
+									<reference key="NSBGColor" ref="686228904"/>
+									<int key="NScvFlags">4</int>
+								</object>
+								<reference ref="644891160"/>
+							</object>
+							<string key="NSFrame">{{20, 58}, {447, 214}}</string>
+							<reference key="NSSuperview" ref="1006"/>
+							<reference key="NSNextKeyView" ref="375811294"/>
+							<int key="NSsFlags">562</int>
+							<reference key="NSVScroller" ref="321977608"/>
+							<reference key="NSHScroller" ref="787488017"/>
+							<reference key="NSContentView" ref="375811294"/>
+							<reference key="NSHeaderClipView" ref="196060644"/>
+							<reference key="NSCornerView" ref="644891160"/>
+							<bytes key="NSScrollAmts">QSAAAEEgAABBmAAAQZgAAA</bytes>
+						</object>
+						<object class="NSButton" id="16200144">
+							<reference key="NSNextResponder" ref="1006"/>
+							<int key="NSvFlags">292</int>
+							<string key="NSFrame">{{28, 12}, {99, 32}}</string>
+							<reference key="NSSuperview" ref="1006"/>
+							<bool key="NSEnabled">YES</bool>
+							<object class="NSButtonCell" key="NSCell" id="1036187108">
+								<int key="NSCellFlags">67239424</int>
+								<int key="NSCellFlags2">134217728</int>
+								<string key="NSContents">New Deal</string>
+								<reference key="NSSupport" ref="389194177"/>
+								<reference key="NSControlView" ref="16200144"/>
+								<int key="NSButtonFlags">-2038284033</int>
+								<int key="NSButtonFlags2">129</int>
+								<string key="NSAlternateContents"/>
+								<string key="NSKeyEquivalent"/>
+								<int key="NSPeriodicDelay">200</int>
+								<int key="NSPeriodicInterval">25</int>
+							</object>
+						</object>
+					</object>
+					<string key="NSFrameSize">{487, 297}</string>
+					<reference key="NSSuperview"/>
+				</object>
+				<string key="NSScreenRect">{{0, 0}, {1680, 1028}}</string>
+				<string key="NSMinSize">{482, 281}</string>
+				<string key="NSMaxSize">{3.40282e+38, 3.40282e+38}</string>
+			</object>
+			<object class="LispController" id="775414032">
+				<object class="NSMutableArray" key="typeInfo">
+					<bool key="EncodedWithXMLCoder">YES</bool>
+					<object class="NSMutableArray">
+						<bool key="EncodedWithXMLCoder">YES</bool>
+						<string>iu::assoc-array</string>
+						<string/>
+						<string type="base64-UTF8">IydjdDM6OmhhbmQtY2hpbGRyZW4</string>
+					</object>
+					<object class="NSMutableArray">
+						<bool key="EncodedWithXMLCoder">YES</bool>
+						<string>cons</string>
+						<string/>
+						<string type="base64-UTF8">IydudWxsA</string>
+					</object>
+					<object class="NSMutableArray">
+						<bool key="EncodedWithXMLCoder">YES</bool>
+						<string type="base64-UTF8">PG5ldyB0eXBlPg</string>
+						<string/>
+						<string/>
+					</object>
+				</object>
+				<object class="NSMutableArray" key="initforms">
+					<bool key="EncodedWithXMLCoder">YES</bool>
+					<object class="NSMutableArray">
+						<bool key="EncodedWithXMLCoder">YES</bool>
+						<string type="base64-UTF8">PG5ldyB0eXBlPg</string>
+						<string/>
+					</object>
+				</object>
+				<object class="NSMutableArray" key="sortInfo">
+					<bool key="EncodedWithXMLCoder">YES</bool>
+					<object class="NSMutableArray">
+						<bool key="EncodedWithXMLCoder">YES</bool>
+						<string>lc::ht-entry</string>
+						<string>lc::ht-key</string>
+						<string>ct3::hand-suit-order</string>
+					</object>
+					<object class="NSMutableArray">
+						<bool key="EncodedWithXMLCoder">YES</bool>
+						<string type="base64-UTF8">PG5ldyB0eXBlPg</string>
+						<string/>
+						<string/>
+					</object>
+				</object>
+				<string key="rootType">iu::assoc-array</string>
+				<string key="readerFunc"/>
+				<string key="writerFunc"/>
+				<string key="countFunc"/>
+				<string key="selectFunc"/>
+				<string key="editedFunc"/>
+				<nil key="addedFunc"/>
+				<nil key="removedFunc"/>
+				<string key="deleteFunc"/>
+				<string key="addChildFunc"/>
+				<string key="childrenFunc"/>
+				<bool key="genRoot">NO</bool>
+			</object>
+		</object>
+		<object class="IBObjectContainer" key="IBDocument.Objects">
+			<object class="NSMutableArray" key="connectionRecords">
+				<bool key="EncodedWithXMLCoder">YES</bool>
+				<object class="IBConnectionRecord">
+					<object class="IBOutletConnection" key="connection">
+						<string key="label">delegate</string>
+						<reference key="source" ref="1005"/>
+						<reference key="destination" ref="1001"/>
+					</object>
+					<int key="connectionID">32</int>
+				</object>
+				<object class="IBConnectionRecord">
+					<object class="IBOutletConnection" key="connection">
+						<string key="label">delegate</string>
+						<reference key="source" ref="1045897523"/>
+						<reference key="destination" ref="775414032"/>
+					</object>
+					<int key="connectionID">65</int>
+				</object>
+				<object class="IBConnectionRecord">
+					<object class="IBOutletConnection" key="connection">
+						<string key="label">dataSource</string>
+						<reference key="source" ref="1045897523"/>
+						<reference key="destination" ref="775414032"/>
+					</object>
+					<int key="connectionID">66</int>
+				</object>
+				<object class="IBConnectionRecord">
+					<object class="IBOutletConnection" key="connection">
+						<string key="label">view</string>
+						<reference key="source" ref="775414032"/>
+						<reference key="destination" ref="1045897523"/>
+					</object>
+					<int key="connectionID">67</int>
+				</object>
+				<object class="IBConnectionRecord">
+					<object class="IBOutletConnection" key="connection">
+						<string key="label">owner</string>
+						<reference key="source" ref="775414032"/>
+						<reference key="destination" ref="1001"/>
+					</object>
+					<int key="connectionID">68</int>
+				</object>
+				<object class="IBConnectionRecord">
+					<object class="IBOutletConnection" key="connection">
+						<string key="label">lispCtrl</string>
+						<reference key="source" ref="1001"/>
+						<reference key="destination" ref="775414032"/>
+					</object>
+					<int key="connectionID">69</int>
+				</object>
+				<object class="IBConnectionRecord">
+					<object class="IBActionConnection" key="connection">
+						<string key="label">deal:</string>
+						<reference key="source" ref="1001"/>
+						<reference key="destination" ref="16200144"/>
+					</object>
+					<int key="connectionID">72</int>
+				</object>
+			</object>
+			<object class="IBMutableOrderedSet" key="objectRecords">
+				<object class="NSArray" key="orderedObjects">
+					<bool key="EncodedWithXMLCoder">YES</bool>
+					<object class="IBObjectRecord">
+						<int key="objectID">0</int>
+						<object class="NSArray" key="object" id="1002">
+							<bool key="EncodedWithXMLCoder">YES</bool>
+						</object>
+						<reference key="children" ref="1000"/>
+						<nil key="parent"/>
+					</object>
+					<object class="IBObjectRecord">
+						<int key="objectID">-2</int>
+						<reference key="object" ref="1001"/>
+						<reference key="parent" ref="1002"/>
+						<string type="base64-UTF8" key="objectName">RmlsZSdzIE93bmVyA</string>
+					</object>
+					<object class="IBObjectRecord">
+						<int key="objectID">-1</int>
+						<reference key="object" ref="1003"/>
+						<reference key="parent" ref="1002"/>
+						<string key="objectName">First Responder</string>
+					</object>
+					<object class="IBObjectRecord">
+						<int key="objectID">-3</int>
+						<reference key="object" ref="1004"/>
+						<reference key="parent" ref="1002"/>
+						<string key="objectName">Application</string>
+					</object>
+					<object class="IBObjectRecord">
+						<int key="objectID">1</int>
+						<reference key="object" ref="1005"/>
+						<object class="NSMutableArray" key="children">
+							<bool key="EncodedWithXMLCoder">YES</bool>
+							<reference ref="1006"/>
+						</object>
+						<reference key="parent" ref="1002"/>
+					</object>
+					<object class="IBObjectRecord">
+						<int key="objectID">2</int>
+						<reference key="object" ref="1006"/>
+						<object class="NSMutableArray" key="children">
+							<bool key="EncodedWithXMLCoder">YES</bool>
+							<reference ref="1060842980"/>
+							<reference ref="16200144"/>
+						</object>
+						<reference key="parent" ref="1005"/>
+					</object>
+					<object class="IBObjectRecord">
+						<int key="objectID">45</int>
+						<reference key="object" ref="775414032"/>
+						<reference key="parent" ref="1002"/>
+					</object>
+					<object class="IBObjectRecord">
+						<int key="objectID">46</int>
+						<reference key="object" ref="1060842980"/>
+						<object class="NSMutableArray" key="children">
+							<bool key="EncodedWithXMLCoder">YES</bool>
+							<reference ref="321977608"/>
+							<reference ref="787488017"/>
+							<reference ref="1045897523"/>
+							<reference ref="403972319"/>
+						</object>
+						<reference key="parent" ref="1006"/>
+					</object>
+					<object class="IBObjectRecord">
+						<int key="objectID">47</int>
+						<reference key="object" ref="321977608"/>
+						<reference key="parent" ref="1060842980"/>
+					</object>
+					<object class="IBObjectRecord">
+						<int key="objectID">48</int>
+						<reference key="object" ref="787488017"/>
+						<reference key="parent" ref="1060842980"/>
+					</object>
+					<object class="IBObjectRecord">
+						<int key="objectID">49</int>
+						<reference key="object" ref="1045897523"/>
+						<object class="NSMutableArray" key="children">
+							<bool key="EncodedWithXMLCoder">YES</bool>
+							<reference ref="190046595"/>
+							<reference ref="495767371"/>
+						</object>
+						<reference key="parent" ref="1060842980"/>
+					</object>
+					<object class="IBObjectRecord">
+						<int key="objectID">50</int>
+						<reference key="object" ref="403972319"/>
+						<reference key="parent" ref="1060842980"/>
+					</object>
+					<object class="IBObjectRecord">
+						<int key="objectID">51</int>
+						<reference key="object" ref="190046595"/>
+						<object class="NSMutableArray" key="children">
+							<bool key="EncodedWithXMLCoder">YES</bool>
+							<reference ref="508041835"/>
+						</object>
+						<reference key="parent" ref="1045897523"/>
+					</object>
+					<object class="IBObjectRecord">
+						<int key="objectID">52</int>
+						<reference key="object" ref="495767371"/>
+						<object class="NSMutableArray" key="children">
+							<bool key="EncodedWithXMLCoder">YES</bool>
+							<reference ref="408416411"/>
+						</object>
+						<reference key="parent" ref="1045897523"/>
+					</object>
+					<object class="IBObjectRecord">
+						<int key="objectID">53</int>
+						<reference key="object" ref="408416411"/>
+						<reference key="parent" ref="495767371"/>
+					</object>
+					<object class="IBObjectRecord">
+						<int key="objectID">54</int>
+						<reference key="object" ref="508041835"/>
+						<reference key="parent" ref="190046595"/>
+					</object>
+					<object class="IBObjectRecord">
+						<int key="objectID">70</int>
+						<reference key="object" ref="16200144"/>
+						<object class="NSMutableArray" key="children">
+							<bool key="EncodedWithXMLCoder">YES</bool>
+							<reference ref="1036187108"/>
+						</object>
+						<reference key="parent" ref="1006"/>
+					</object>
+					<object class="IBObjectRecord">
+						<int key="objectID">71</int>
+						<reference key="object" ref="1036187108"/>
+						<reference key="parent" ref="16200144"/>
+					</object>
+				</object>
+			</object>
+			<object class="NSMutableDictionary" key="flattenedProperties">
+				<bool key="EncodedWithXMLCoder">YES</bool>
+				<object class="NSMutableArray" key="dict.sortedKeys">
+					<bool key="EncodedWithXMLCoder">YES</bool>
+					<string>-1.IBPluginDependency</string>
+					<string>-2.IBPluginDependency</string>
+					<string>-3.IBPluginDependency</string>
+					<string>1.IBEditorWindowLastContentRect</string>
+					<string>1.IBPluginDependency</string>
+					<string>1.IBWindowTemplateEditedContentRect</string>
+					<string>1.NSWindowTemplate.visibleAtLaunch</string>
+					<string>1.WindowOrigin</string>
+					<string>1.editorWindowContentRectSynchronizationRect</string>
+					<string>1.windowTemplate.hasMinSize</string>
+					<string>1.windowTemplate.minSize</string>
+					<string>2.IBPluginDependency</string>
+					<string>45.IBPluginDependency</string>
+					<string>46.IBPluginDependency</string>
+					<string>47.IBPluginDependency</string>
+					<string>48.IBPluginDependency</string>
+					<string>49.IBPluginDependency</string>
+					<string>50.IBPluginDependency</string>
+					<string>51.IBPluginDependency</string>
+					<string>52.IBPluginDependency</string>
+					<string>53.IBPluginDependency</string>
+					<string>54.IBPluginDependency</string>
+					<string>70.IBPluginDependency</string>
+					<string>71.IBPluginDependency</string>
+				</object>
+				<object class="NSMutableArray" key="dict.values">
+					<bool key="EncodedWithXMLCoder">YES</bool>
+					<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
+					<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
+					<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
+					<string>{{77, 470}, {487, 297}}</string>
+					<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
+					<string>{{77, 470}, {487, 297}}</string>
+					<integer value="1"/>
+					<string>{196, 240}</string>
+					<string>{{357, 418}, {480, 270}}</string>
+					<boolean value="YES"/>
+					<string>{482, 259}</string>
+					<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
+					<string>com.clozure.ClozureCL.ibplugin</string>
+					<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
+					<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
+					<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
+					<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
+					<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
+					<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
+					<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
+					<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
+					<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
+					<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
+					<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
+				</object>
+			</object>
+			<object class="NSMutableDictionary" key="unlocalizedProperties">
+				<bool key="EncodedWithXMLCoder">YES</bool>
+				<object class="NSArray" key="dict.sortedKeys">
+					<bool key="EncodedWithXMLCoder">YES</bool>
+				</object>
+				<object class="NSMutableArray" key="dict.values">
+					<bool key="EncodedWithXMLCoder">YES</bool>
+				</object>
+			</object>
+			<nil key="activeLocalization"/>
+			<object class="NSMutableDictionary" key="localizations">
+				<bool key="EncodedWithXMLCoder">YES</bool>
+				<object class="NSArray" key="dict.sortedKeys">
+					<bool key="EncodedWithXMLCoder">YES</bool>
+				</object>
+				<object class="NSMutableArray" key="dict.values">
+					<bool key="EncodedWithXMLCoder">YES</bool>
+				</object>
+			</object>
+			<nil key="sourceID"/>
+			<int key="maxID">72</int>
+		</object>
+		<object class="IBClassDescriber" key="IBDocument.Classes">
+			<object class="NSMutableArray" key="referencedPartialClassDescriptions">
+				<bool key="EncodedWithXMLCoder">YES</bool>
+				<object class="IBPartialClassDescription">
+					<string key="className">HandOfCards</string>
+					<object class="NSMutableDictionary" key="actions">
+						<string key="NS.key.0">deal:</string>
+						<string key="NS.object.0">id</string>
+					</object>
+					<object class="NSMutableDictionary" key="outlets">
+						<string key="NS.key.0">lispCtrl</string>
+						<string key="NS.object.0">id</string>
+					</object>
+					<object class="IBClassDescriptionSource" key="sourceIdentifier">
+						<string key="majorKey">IBUserSource</string>
+						<string key="minorKey"/>
+					</object>
+				</object>
+			</object>
+		</object>
+		<int key="IBDocument.localizationMode">0</int>
+		<nil key="IBDocument.LastKnownRelativeProjectPath"/>
+		<int key="IBDocument.defaultPropertyAccessControl">3</int>
+	</data>
+</archive>
Index: /trunk/contrib/krueger/InterfaceProjects/Documentation/DocFigures/Loan Flowchart.graffle
===================================================================
--- /trunk/contrib/krueger/InterfaceProjects/Documentation/DocFigures/Loan Flowchart.graffle	(revision 13946)
+++ /trunk/contrib/krueger/InterfaceProjects/Documentation/DocFigures/Loan Flowchart.graffle	(revision 13946)
@@ -0,0 +1,1152 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
+<plist version="1.0">
+<dict>
+	<key>CanvasColor</key>
+	<dict>
+		<key>w</key>
+		<string>1</string>
+	</dict>
+	<key>ColumnAlign</key>
+	<integer>1</integer>
+	<key>ColumnSpacing</key>
+	<real>36</real>
+	<key>CreationDate</key>
+	<string>2009-12-11 17:19:42 -0600</string>
+	<key>Creator</key>
+	<string>Paul Krueger</string>
+	<key>GraphDocumentVersion</key>
+	<integer>4</integer>
+	<key>GraphicsList</key>
+	<array>
+		<dict>
+			<key>Class</key>
+			<string>LineGraphic</string>
+			<key>Head</key>
+			<dict>
+				<key>ID</key>
+				<integer>65</integer>
+				<key>Info</key>
+				<integer>1</integer>
+			</dict>
+			<key>ID</key>
+			<integer>81</integer>
+			<key>OrthogonalBarAutomatic</key>
+			<true/>
+			<key>OrthogonalBarPosition</key>
+			<real>20</real>
+			<key>Points</key>
+			<array>
+				<string>{313.5, 581}</string>
+				<string>{489.007, 517}</string>
+			</array>
+			<key>Style</key>
+			<dict>
+				<key>stroke</key>
+				<dict>
+					<key>HeadArrow</key>
+					<string>0</string>
+					<key>LineType</key>
+					<integer>2</integer>
+					<key>TailArrow</key>
+					<string>FilledArrow</string>
+				</dict>
+			</dict>
+			<key>Tail</key>
+			<dict>
+				<key>ID</key>
+				<integer>66</integer>
+				<key>Info</key>
+				<integer>2</integer>
+			</dict>
+		</dict>
+		<dict>
+			<key>Class</key>
+			<string>LineGraphic</string>
+			<key>Head</key>
+			<dict>
+				<key>ID</key>
+				<integer>61</integer>
+				<key>Info</key>
+				<integer>1</integer>
+			</dict>
+			<key>ID</key>
+			<integer>80</integer>
+			<key>OrthogonalBarAutomatic</key>
+			<true/>
+			<key>OrthogonalBarPosition</key>
+			<real>20</real>
+			<key>Points</key>
+			<array>
+				<string>{313.5, 581}</string>
+				<string>{369.003, 517}</string>
+			</array>
+			<key>Style</key>
+			<dict>
+				<key>stroke</key>
+				<dict>
+					<key>HeadArrow</key>
+					<string>FilledArrow</string>
+					<key>LineType</key>
+					<integer>2</integer>
+					<key>TailArrow</key>
+					<string>FilledArrow</string>
+				</dict>
+			</dict>
+			<key>Tail</key>
+			<dict>
+				<key>ID</key>
+				<integer>66</integer>
+				<key>Info</key>
+				<integer>2</integer>
+			</dict>
+		</dict>
+		<dict>
+			<key>Class</key>
+			<string>LineGraphic</string>
+			<key>Head</key>
+			<dict>
+				<key>ID</key>
+				<integer>62</integer>
+				<key>Info</key>
+				<integer>1</integer>
+			</dict>
+			<key>ID</key>
+			<integer>79</integer>
+			<key>OrthogonalBarAutomatic</key>
+			<true/>
+			<key>OrthogonalBarPosition</key>
+			<real>20</real>
+			<key>Points</key>
+			<array>
+				<string>{313.5, 581}</string>
+				<string>{248.998, 517}</string>
+			</array>
+			<key>Style</key>
+			<dict>
+				<key>stroke</key>
+				<dict>
+					<key>HeadArrow</key>
+					<string>0</string>
+					<key>LineType</key>
+					<integer>2</integer>
+					<key>TailArrow</key>
+					<string>FilledArrow</string>
+				</dict>
+			</dict>
+			<key>Tail</key>
+			<dict>
+				<key>ID</key>
+				<integer>66</integer>
+				<key>Info</key>
+				<integer>2</integer>
+			</dict>
+		</dict>
+		<dict>
+			<key>Class</key>
+			<string>LineGraphic</string>
+			<key>Head</key>
+			<dict>
+				<key>ID</key>
+				<integer>60</integer>
+				<key>Info</key>
+				<integer>1</integer>
+			</dict>
+			<key>ID</key>
+			<integer>78</integer>
+			<key>OrthogonalBarAutomatic</key>
+			<true/>
+			<key>OrthogonalBarPosition</key>
+			<real>20</real>
+			<key>Points</key>
+			<array>
+				<string>{313.5, 581}</string>
+				<string>{128.994, 517}</string>
+			</array>
+			<key>Style</key>
+			<dict>
+				<key>stroke</key>
+				<dict>
+					<key>HeadArrow</key>
+					<string>0</string>
+					<key>LineType</key>
+					<integer>2</integer>
+					<key>TailArrow</key>
+					<string>FilledArrow</string>
+				</dict>
+			</dict>
+			<key>Tail</key>
+			<dict>
+				<key>ID</key>
+				<integer>66</integer>
+				<key>Info</key>
+				<integer>2</integer>
+			</dict>
+		</dict>
+		<dict>
+			<key>Class</key>
+			<string>LineGraphic</string>
+			<key>Head</key>
+			<dict>
+				<key>ID</key>
+				<integer>57</integer>
+				<key>Info</key>
+				<integer>1</integer>
+			</dict>
+			<key>ID</key>
+			<integer>77</integer>
+			<key>OrthogonalBarAutomatic</key>
+			<true/>
+			<key>OrthogonalBarPosition</key>
+			<real>7</real>
+			<key>Points</key>
+			<array>
+				<string>{489.007, 472}</string>
+				<string>{313.5, 432.75}</string>
+			</array>
+			<key>Style</key>
+			<dict>
+				<key>stroke</key>
+				<dict>
+					<key>HeadArrow</key>
+					<string>0</string>
+					<key>LineType</key>
+					<integer>2</integer>
+					<key>TailArrow</key>
+					<string>FilledArrow</string>
+				</dict>
+			</dict>
+			<key>Tail</key>
+			<dict>
+				<key>ID</key>
+				<integer>65</integer>
+				<key>Info</key>
+				<integer>2</integer>
+			</dict>
+		</dict>
+		<dict>
+			<key>Class</key>
+			<string>LineGraphic</string>
+			<key>Head</key>
+			<dict>
+				<key>ID</key>
+				<integer>57</integer>
+				<key>Info</key>
+				<integer>1</integer>
+			</dict>
+			<key>ID</key>
+			<integer>76</integer>
+			<key>OrthogonalBarAutomatic</key>
+			<true/>
+			<key>OrthogonalBarPosition</key>
+			<real>7</real>
+			<key>Points</key>
+			<array>
+				<string>{369.003, 472}</string>
+				<string>{313.5, 432.75}</string>
+			</array>
+			<key>Style</key>
+			<dict>
+				<key>stroke</key>
+				<dict>
+					<key>HeadArrow</key>
+					<string>0</string>
+					<key>LineType</key>
+					<integer>2</integer>
+					<key>TailArrow</key>
+					<string>FilledArrow</string>
+				</dict>
+			</dict>
+			<key>Tail</key>
+			<dict>
+				<key>ID</key>
+				<integer>61</integer>
+				<key>Info</key>
+				<integer>2</integer>
+			</dict>
+		</dict>
+		<dict>
+			<key>Class</key>
+			<string>LineGraphic</string>
+			<key>Head</key>
+			<dict>
+				<key>ID</key>
+				<integer>57</integer>
+				<key>Info</key>
+				<integer>1</integer>
+			</dict>
+			<key>ID</key>
+			<integer>75</integer>
+			<key>OrthogonalBarAutomatic</key>
+			<true/>
+			<key>OrthogonalBarPosition</key>
+			<real>7</real>
+			<key>Points</key>
+			<array>
+				<string>{248.998, 472}</string>
+				<string>{313.5, 432.75}</string>
+			</array>
+			<key>Style</key>
+			<dict>
+				<key>stroke</key>
+				<dict>
+					<key>HeadArrow</key>
+					<string>0</string>
+					<key>LineType</key>
+					<integer>2</integer>
+					<key>TailArrow</key>
+					<string>FilledArrow</string>
+				</dict>
+			</dict>
+			<key>Tail</key>
+			<dict>
+				<key>ID</key>
+				<integer>62</integer>
+				<key>Info</key>
+				<integer>2</integer>
+			</dict>
+		</dict>
+		<dict>
+			<key>Class</key>
+			<string>LineGraphic</string>
+			<key>Head</key>
+			<dict>
+				<key>ID</key>
+				<integer>57</integer>
+				<key>Info</key>
+				<integer>1</integer>
+			</dict>
+			<key>ID</key>
+			<integer>74</integer>
+			<key>OrthogonalBarAutomatic</key>
+			<true/>
+			<key>OrthogonalBarPosition</key>
+			<real>7</real>
+			<key>Points</key>
+			<array>
+				<string>{128.994, 472}</string>
+				<string>{313.5, 432.75}</string>
+			</array>
+			<key>Style</key>
+			<dict>
+				<key>stroke</key>
+				<dict>
+					<key>HeadArrow</key>
+					<string>0</string>
+					<key>LineType</key>
+					<integer>2</integer>
+					<key>TailArrow</key>
+					<string>FilledArrow</string>
+				</dict>
+			</dict>
+			<key>Tail</key>
+			<dict>
+				<key>ID</key>
+				<integer>60</integer>
+				<key>Info</key>
+				<integer>2</integer>
+			</dict>
+		</dict>
+		<dict>
+			<key>Class</key>
+			<string>LineGraphic</string>
+			<key>Head</key>
+			<dict>
+				<key>ID</key>
+				<integer>64</integer>
+			</dict>
+			<key>ID</key>
+			<integer>73</integer>
+			<key>OrthogonalBarAutomatic</key>
+			<true/>
+			<key>OrthogonalBarPosition</key>
+			<real>-1</real>
+			<key>Points</key>
+			<array>
+				<string>{496, 219.5}</string>
+				<string>{496, 159}</string>
+			</array>
+			<key>Style</key>
+			<dict>
+				<key>stroke</key>
+				<dict>
+					<key>HeadArrow</key>
+					<string>0</string>
+					<key>LineType</key>
+					<integer>2</integer>
+					<key>TailArrow</key>
+					<string>FilledArrow</string>
+				</dict>
+			</dict>
+			<key>Tail</key>
+			<dict>
+				<key>ID</key>
+				<integer>72</integer>
+				<key>Info</key>
+				<integer>2</integer>
+			</dict>
+		</dict>
+		<dict>
+			<key>Bounds</key>
+			<string>{{450.5, 219.5}, {91, 45}}</string>
+			<key>Class</key>
+			<string>ShapedGraphic</string>
+			<key>ID</key>
+			<integer>72</integer>
+			<key>Magnets</key>
+			<array>
+				<string>{0, 1}</string>
+				<string>{0, -1}</string>
+				<string>{1, 0}</string>
+				<string>{-1, 0}</string>
+			</array>
+			<key>Shape</key>
+			<string>Rectangle</string>
+			<key>Text</key>
+			<dict>
+				<key>Text</key>
+				<string>{\rtf1\ansi\ansicpg1252\cocoartf949\cocoasubrtf540
+{\fonttbl\f0\fswiss\fcharset0 Helvetica;}
+{\colortbl;\red255\green255\blue255;}
+\pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\qc\pardirnatural
+
+\f0\fs20 \cf0 Set new dates}</string>
+			</dict>
+		</dict>
+		<dict>
+			<key>Class</key>
+			<string>LineGraphic</string>
+			<key>Head</key>
+			<dict>
+				<key>ID</key>
+				<integer>72</integer>
+				<key>Info</key>
+				<integer>1</integer>
+			</dict>
+			<key>ID</key>
+			<integer>71</integer>
+			<key>OrthogonalBarAutomatic</key>
+			<false/>
+			<key>OrthogonalBarPosition</key>
+			<real>14.350006103515625</real>
+			<key>Points</key>
+			<array>
+				<string>{309, 347}</string>
+				<string>{496, 264.5}</string>
+			</array>
+			<key>Style</key>
+			<dict>
+				<key>stroke</key>
+				<dict>
+					<key>HeadArrow</key>
+					<string>0</string>
+					<key>LineType</key>
+					<integer>2</integer>
+					<key>TailArrow</key>
+					<string>FilledArrow</string>
+				</dict>
+			</dict>
+			<key>Tail</key>
+			<dict>
+				<key>ID</key>
+				<integer>55</integer>
+				<key>Info</key>
+				<integer>2</integer>
+			</dict>
+		</dict>
+		<dict>
+			<key>Class</key>
+			<string>LineGraphic</string>
+			<key>Head</key>
+			<dict>
+				<key>ID</key>
+				<integer>59</integer>
+				<key>Info</key>
+				<integer>1</integer>
+			</dict>
+			<key>ID</key>
+			<integer>70</integer>
+			<key>OrthogonalBarAutomatic</key>
+			<true/>
+			<key>OrthogonalBarPosition</key>
+			<real>-1</real>
+			<key>Points</key>
+			<array>
+				<string>{309, 347}</string>
+				<string>{309, 264.5}</string>
+			</array>
+			<key>Style</key>
+			<dict>
+				<key>stroke</key>
+				<dict>
+					<key>HeadArrow</key>
+					<string>0</string>
+					<key>LineType</key>
+					<integer>2</integer>
+					<key>TailArrow</key>
+					<string>FilledArrow</string>
+				</dict>
+			</dict>
+			<key>Tail</key>
+			<dict>
+				<key>ID</key>
+				<integer>55</integer>
+				<key>Info</key>
+				<integer>2</integer>
+			</dict>
+		</dict>
+		<dict>
+			<key>Class</key>
+			<string>LineGraphic</string>
+			<key>Head</key>
+			<dict>
+				<key>ID</key>
+				<integer>56</integer>
+				<key>Info</key>
+				<integer>1</integer>
+			</dict>
+			<key>ID</key>
+			<integer>69</integer>
+			<key>OrthogonalBarAutomatic</key>
+			<true/>
+			<key>OrthogonalBarPosition</key>
+			<real>1</real>
+			<key>Points</key>
+			<array>
+				<string>{309, 347}</string>
+				<string>{124, 320}</string>
+				<string>{122, 264.5}</string>
+			</array>
+			<key>Style</key>
+			<dict>
+				<key>stroke</key>
+				<dict>
+					<key>HeadArrow</key>
+					<string>0</string>
+					<key>LineType</key>
+					<integer>2</integer>
+					<key>TailArrow</key>
+					<string>FilledArrow</string>
+				</dict>
+			</dict>
+			<key>Tail</key>
+			<dict>
+				<key>ID</key>
+				<integer>55</integer>
+			</dict>
+		</dict>
+		<dict>
+			<key>Class</key>
+			<string>LineGraphic</string>
+			<key>Head</key>
+			<dict>
+				<key>ID</key>
+				<integer>63</integer>
+				<key>Info</key>
+				<integer>1</integer>
+			</dict>
+			<key>ID</key>
+			<integer>68</integer>
+			<key>OrthogonalBarAutomatic</key>
+			<true/>
+			<key>OrthogonalBarPosition</key>
+			<real>-1</real>
+			<key>Points</key>
+			<array>
+				<string>{309, 219.5}</string>
+				<string>{309, 159}</string>
+			</array>
+			<key>Style</key>
+			<dict>
+				<key>stroke</key>
+				<dict>
+					<key>HeadArrow</key>
+					<string>0</string>
+					<key>LineType</key>
+					<integer>2</integer>
+					<key>TailArrow</key>
+					<string>FilledArrow</string>
+				</dict>
+			</dict>
+			<key>Tail</key>
+			<dict>
+				<key>ID</key>
+				<integer>59</integer>
+				<key>Info</key>
+				<integer>2</integer>
+			</dict>
+		</dict>
+		<dict>
+			<key>Class</key>
+			<string>LineGraphic</string>
+			<key>Head</key>
+			<dict>
+				<key>ID</key>
+				<integer>58</integer>
+				<key>Info</key>
+				<integer>1</integer>
+			</dict>
+			<key>ID</key>
+			<integer>67</integer>
+			<key>OrthogonalBarAutomatic</key>
+			<true/>
+			<key>OrthogonalBarPosition</key>
+			<real>-1</real>
+			<key>Points</key>
+			<array>
+				<string>{122, 219.5}</string>
+				<string>{122, 159}</string>
+			</array>
+			<key>Style</key>
+			<dict>
+				<key>stroke</key>
+				<dict>
+					<key>HeadArrow</key>
+					<string>0</string>
+					<key>LineType</key>
+					<integer>2</integer>
+					<key>TailArrow</key>
+					<string>FilledArrow</string>
+				</dict>
+			</dict>
+			<key>Tail</key>
+			<dict>
+				<key>ID</key>
+				<integer>56</integer>
+				<key>Info</key>
+				<integer>2</integer>
+			</dict>
+		</dict>
+		<dict>
+			<key>Bounds</key>
+			<string>{{270.506, 581}, {85.9873, 45}}</string>
+			<key>Class</key>
+			<string>ShapedGraphic</string>
+			<key>ID</key>
+			<integer>66</integer>
+			<key>Magnets</key>
+			<array>
+				<string>{0, 1}</string>
+				<string>{0, -1}</string>
+				<string>{1, 0}</string>
+				<string>{-1, 0}</string>
+			</array>
+			<key>Shape</key>
+			<string>Rectangle</string>
+			<key>Text</key>
+			<dict>
+				<key>Text</key>
+				<string>{\rtf1\ansi\ansicpg1252\cocoartf949\cocoasubrtf540
+{\fonttbl\f0\fswiss\fcharset0 Helvetica;}
+{\colortbl;\red255\green255\blue255;}
+\pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\qc\pardirnatural
+
+\f0\fs20 \cf0 Compute Pay Schedule}</string>
+			</dict>
+		</dict>
+		<dict>
+			<key>Bounds</key>
+			<string>{{446.013, 472}, {85.9873, 45}}</string>
+			<key>Class</key>
+			<string>ShapedGraphic</string>
+			<key>ID</key>
+			<integer>65</integer>
+			<key>Magnets</key>
+			<array>
+				<string>{0, 1}</string>
+				<string>{0, -1}</string>
+				<string>{1, 0}</string>
+				<string>{-1, 0}</string>
+			</array>
+			<key>Shape</key>
+			<string>Rectangle</string>
+			<key>Text</key>
+			<dict>
+				<key>Text</key>
+				<string>{\rtf1\ansi\ansicpg1252\cocoartf949\cocoasubrtf540
+{\fonttbl\f0\fswiss\fcharset0 Helvetica;}
+{\colortbl;\red255\green255\blue255;}
+\pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\qc\pardirnatural
+
+\f0\fs20 \cf0 Compute Monthly Payment}</string>
+			</dict>
+		</dict>
+		<dict>
+			<key>Bounds</key>
+			<string>{{450.5, 105}, {91, 54}}</string>
+			<key>Class</key>
+			<string>ShapedGraphic</string>
+			<key>ID</key>
+			<integer>64</integer>
+			<key>Magnets</key>
+			<array>
+				<string>{0, 1}</string>
+				<string>{0, -1}</string>
+				<string>{1, 0}</string>
+				<string>{-1, 0}</string>
+			</array>
+			<key>Shape</key>
+			<string>Trapazoid</string>
+			<key>Text</key>
+			<dict>
+				<key>Text</key>
+				<string>{\rtf1\ansi\ansicpg1252\cocoartf949\cocoasubrtf540
+{\fonttbl\f0\fswiss\fcharset0 Helvetica;}
+{\colortbl;\red255\green255\blue255;}
+\pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\qc\pardirnatural
+
+\f0\fs20 \cf0 Loan Date\
+Change}</string>
+			</dict>
+		</dict>
+		<dict>
+			<key>Bounds</key>
+			<string>{{263.5, 105}, {91, 54}}</string>
+			<key>Class</key>
+			<string>ShapedGraphic</string>
+			<key>ID</key>
+			<integer>63</integer>
+			<key>Magnets</key>
+			<array>
+				<string>{0, 1}</string>
+				<string>{0, -1}</string>
+				<string>{1, 0}</string>
+				<string>{-1, 0}</string>
+			</array>
+			<key>Shape</key>
+			<string>Trapazoid</string>
+			<key>Text</key>
+			<dict>
+				<key>Text</key>
+				<string>{\rtf1\ansi\ansicpg1252\cocoartf949\cocoasubrtf540
+{\fonttbl\f0\fswiss\fcharset0 Helvetica;}
+{\colortbl;\red255\green255\blue255;}
+\pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\ql\qnatural\pardirnatural
+
+\f0\fs20 \cf0 Compute Mode\
+\pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\qc\pardirnatural
+\cf0 Change}</string>
+			</dict>
+		</dict>
+		<dict>
+			<key>Bounds</key>
+			<string>{{206.004, 472}, {85.9873, 45}}</string>
+			<key>Class</key>
+			<string>ShapedGraphic</string>
+			<key>ID</key>
+			<integer>62</integer>
+			<key>Magnets</key>
+			<array>
+				<string>{0, 1}</string>
+				<string>{0, -1}</string>
+				<string>{1, 0}</string>
+				<string>{-1, 0}</string>
+			</array>
+			<key>Shape</key>
+			<string>Rectangle</string>
+			<key>Text</key>
+			<dict>
+				<key>Text</key>
+				<string>{\rtf1\ansi\ansicpg1252\cocoartf949\cocoasubrtf540
+{\fonttbl\f0\fswiss\fcharset0 Helvetica;}
+{\colortbl;\red255\green255\blue255;}
+\pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\qc\pardirnatural
+
+\f0\fs20 \cf0 Compute Interest Rate}</string>
+			</dict>
+		</dict>
+		<dict>
+			<key>Bounds</key>
+			<string>{{326.009, 472}, {85.9873, 45}}</string>
+			<key>Class</key>
+			<string>ShapedGraphic</string>
+			<key>ID</key>
+			<integer>61</integer>
+			<key>Magnets</key>
+			<array>
+				<string>{0, 1}</string>
+				<string>{0, -1}</string>
+				<string>{1, 0}</string>
+				<string>{-1, 0}</string>
+			</array>
+			<key>Shape</key>
+			<string>Rectangle</string>
+			<key>Text</key>
+			<dict>
+				<key>Text</key>
+				<string>{\rtf1\ansi\ansicpg1252\cocoartf949\cocoasubrtf540
+{\fonttbl\f0\fswiss\fcharset0 Helvetica;}
+{\colortbl;\red255\green255\blue255;}
+\pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\qc\pardirnatural
+
+\f0\fs20 \cf0 Compute Loan Duration}</string>
+			</dict>
+		</dict>
+		<dict>
+			<key>Bounds</key>
+			<string>{{86, 472}, {85.9873, 45}}</string>
+			<key>Class</key>
+			<string>ShapedGraphic</string>
+			<key>ID</key>
+			<integer>60</integer>
+			<key>Magnets</key>
+			<array>
+				<string>{0, 1}</string>
+				<string>{0, -1}</string>
+				<string>{1, 0}</string>
+				<string>{-1, 0}</string>
+			</array>
+			<key>Shape</key>
+			<string>Rectangle</string>
+			<key>Text</key>
+			<dict>
+				<key>Text</key>
+				<string>{\rtf1\ansi\ansicpg1252\cocoartf949\cocoasubrtf540
+{\fonttbl\f0\fswiss\fcharset0 Helvetica;}
+{\colortbl;\red255\green255\blue255;}
+\pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\qc\pardirnatural
+
+\f0\fs20 \cf0 Compute Loan\
+Value}</string>
+			</dict>
+		</dict>
+		<dict>
+			<key>Bounds</key>
+			<string>{{263.5, 219.5}, {91, 45}}</string>
+			<key>Class</key>
+			<string>ShapedGraphic</string>
+			<key>ID</key>
+			<integer>59</integer>
+			<key>Magnets</key>
+			<array>
+				<string>{0, 1}</string>
+				<string>{0, -1}</string>
+				<string>{1, 0}</string>
+				<string>{-1, 0}</string>
+			</array>
+			<key>Shape</key>
+			<string>Rectangle</string>
+			<key>Text</key>
+			<dict>
+				<key>Text</key>
+				<string>{\rtf1\ansi\ansicpg1252\cocoartf949\cocoasubrtf540
+{\fonttbl\f0\fswiss\fcharset0 Helvetica;}
+{\colortbl;\red255\green255\blue255;}
+\pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\qc\pardirnatural
+
+\f0\fs20 \cf0 Set new compute\
+mode}</string>
+			</dict>
+		</dict>
+		<dict>
+			<key>Bounds</key>
+			<string>{{76.5, 105}, {91, 54}}</string>
+			<key>Class</key>
+			<string>ShapedGraphic</string>
+			<key>ID</key>
+			<integer>58</integer>
+			<key>Magnets</key>
+			<array>
+				<string>{0, 1}</string>
+				<string>{0, -1}</string>
+				<string>{1, 0}</string>
+				<string>{-1, 0}</string>
+			</array>
+			<key>Shape</key>
+			<string>Trapazoid</string>
+			<key>Text</key>
+			<dict>
+				<key>Text</key>
+				<string>{\rtf1\ansi\ansicpg1252\cocoartf949\cocoasubrtf540
+{\fonttbl\f0\fswiss\fcharset0 Helvetica;}
+{\colortbl;\red255\green255\blue255;}
+\pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\qc\pardirnatural
+
+\f0\fs20 \cf0 Loan Parameter\
+Change}</string>
+			</dict>
+		</dict>
+		<dict>
+			<key>Bounds</key>
+			<string>{{268.5, 378.75}, {90, 54}}</string>
+			<key>Class</key>
+			<string>ShapedGraphic</string>
+			<key>ID</key>
+			<integer>57</integer>
+			<key>Magnets</key>
+			<array>
+				<string>{0, 1}</string>
+				<string>{0, -1}</string>
+				<string>{1, 0}</string>
+				<string>{-1, 0}</string>
+			</array>
+			<key>Shape</key>
+			<string>Diamond</string>
+			<key>Text</key>
+			<dict>
+				<key>Text</key>
+				<string>{\rtf1\ansi\ansicpg1252\cocoartf949\cocoasubrtf540
+{\fonttbl\f0\fswiss\fcharset0 Helvetica;}
+{\colortbl;\red255\green255\blue255;}
+\pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\qc\pardirnatural
+
+\f0\fs20 \cf0 Compute\
+Mode?}</string>
+			</dict>
+		</dict>
+		<dict>
+			<key>Bounds</key>
+			<string>{{76.5, 219.5}, {91, 45}}</string>
+			<key>Class</key>
+			<string>ShapedGraphic</string>
+			<key>ID</key>
+			<integer>56</integer>
+			<key>Magnets</key>
+			<array>
+				<string>{0, 1}</string>
+				<string>{0, -1}</string>
+				<string>{1, 0}</string>
+				<string>{-1, 0}</string>
+			</array>
+			<key>Shape</key>
+			<string>Rectangle</string>
+			<key>Text</key>
+			<dict>
+				<key>Text</key>
+				<string>{\rtf1\ansi\ansicpg1252\cocoartf949\cocoasubrtf540
+{\fonttbl\f0\fswiss\fcharset0 Helvetica;}
+{\colortbl;\red255\green255\blue255;}
+\pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\qc\pardirnatural
+
+\f0\fs20 \cf0 Set new param value}</string>
+			</dict>
+		</dict>
+		<dict>
+			<key>Bounds</key>
+			<string>{{62, 347}, {494, 356}}</string>
+			<key>Class</key>
+			<string>ShapedGraphic</string>
+			<key>ID</key>
+			<integer>55</integer>
+			<key>Magnets</key>
+			<array>
+				<string>{0, 1}</string>
+				<string>{0, -1}</string>
+				<string>{1, 0}</string>
+				<string>{-1, 0}</string>
+			</array>
+			<key>Shape</key>
+			<string>Rectangle</string>
+			<key>Text</key>
+			<dict>
+				<key>Text</key>
+				<string>{\rtf1\ansi\ansicpg1252\cocoartf949\cocoasubrtf540
+{\fonttbl\f0\fswiss\fcharset0 Helvetica;}
+{\colortbl;\red255\green255\blue255;}
+\pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\qc\pardirnatural
+
+\f0\fs20 \cf0 Compute New Loan Values}</string>
+			</dict>
+			<key>TextPlacement</key>
+			<integer>0</integer>
+		</dict>
+	</array>
+	<key>GridInfo</key>
+	<dict/>
+	<key>GuidesLocked</key>
+	<string>NO</string>
+	<key>GuidesVisible</key>
+	<string>YES</string>
+	<key>HPages</key>
+	<integer>1</integer>
+	<key>ImageCounter</key>
+	<integer>1</integer>
+	<key>IsPalette</key>
+	<string>NO</string>
+	<key>Layers</key>
+	<array>
+		<dict>
+			<key>Lock</key>
+			<string>NO</string>
+			<key>Name</key>
+			<string>Layer 1</string>
+			<key>Print</key>
+			<string>YES</string>
+			<key>View</key>
+			<string>YES</string>
+		</dict>
+	</array>
+	<key>LayoutInfo</key>
+	<dict>
+		<key>ChildOrdering</key>
+		<integer>0</integer>
+	</dict>
+	<key>LinksVisible</key>
+	<string>NO</string>
+	<key>MagnetsVisible</key>
+	<string>NO</string>
+	<key>ModificationDate</key>
+	<string>2009-12-14 15:48:29 -0600</string>
+	<key>Modifier</key>
+	<string>Paul Krueger</string>
+	<key>Orientation</key>
+	<integer>2</integer>
+	<key>PageBreaks</key>
+	<string>YES</string>
+	<key>PageSetup</key>
+	<data>
+	BAt0eXBlZHN0cmVhbYED6IQBQISEhAtOU1ByaW50SW5mbwGEhAhOU09iamVjdACFkoSE
+	hBNOU011dGFibGVEaWN0aW9uYXJ5AISEDE5TRGljdGlvbmFyeQCUhAFpE5KEhIQITlNT
+	dHJpbmcBlIQBKxROU1ZlcnRpY2FsUGFnaW5hdGlvboaShISECE5TTnVtYmVyAISEB05T
+	VmFsdWUAlIQBKoSXlwCGkoSZmRlOU1ByaW50UmV2ZXJzZU9yaWVudGF0aW9uhpKakoSZ
+	mRZOU0hvcml6b250YWxseUNlbnRlcmVkhpKEm5ydlwGGkoSZmQhOU0NvcGllc4aSoJKE
+	mZkUTlNWZXJ0aWNhbGx5Q2VudGVyZWSGkqCShJmZC05TRmlyc3RQYWdlhpKgkoSZmQ9O
+	U1NjYWxpbmdGYWN0b3KGkoSbnISEAWSdAYaShJmZC05TVG9wTWFyZ2luhpKEm5ymnQCG
+	koSZmRBOU0pvYkRpc3Bvc2l0aW9uhpKEmZkPTlNQcmludFNwb29sSm9ihpKEmZkOTlNC
+	b3R0b21NYXJnaW6GkoSbnKadg0BEAAqAAAAAhpKEmZkPTlNQcmludEFsbFBhZ2VzhpKa
+	koSZmQpOU0xhc3RQYWdlhpKEm5ydl4J/////hpKEmZkNTlNPcmllbnRhdGlvboaSmpKE
+	mZkNTlNSaWdodE1hcmdpboaShJucpp0ShpKEmZkVTlNIb3Jpem9uYWxQYWdpbmF0aW9u
+	hpKakoSZmQxOU0xlZnRNYXJnaW6GkoSbnKadAIaShJmZC05TUGFwZXJOYW1lhpKEmZkJ
+	bmEtbGV0dGVyhpKEmZkOTlNQTVBhZ2VGb3JtYXSGkoSEhA1OU011dGFibGVEYXRhAISE
+	Bk5TRGF0YQCUl4EVLoQHWzU0MjJjXTw/eG1sIHZlcnNpb249IjEuMCIgZW5jb2Rpbmc9
+	IlVURi04Ij8+CjwhRE9DVFlQRSBwbGlzdCBQVUJMSUMgIi0vL0FwcGxlLy9EVEQgUExJ
+	U1QgMS4wLy9FTiIgImh0dHA6Ly93d3cuYXBwbGUuY29tL0RURHMvUHJvcGVydHlMaXN0
+	LTEuMC5kdGQiPgo8cGxpc3QgdmVyc2lvbj0iMS4wIj4KPGRpY3Q+Cgk8a2V5PmNvbS5h
+	cHBsZS5wcmludC5QYWdlRm9ybWF0LlBNSG9yaXpvbnRhbFJlczwva2V5PgoJPGRpY3Q+
+	CgkJPGtleT5jb20uYXBwbGUucHJpbnQudGlja2V0LmNyZWF0b3I8L2tleT4KCQk8c3Ry
+	aW5nPmNvbS5hcHBsZS5qb2J0aWNrZXQ8L3N0cmluZz4KCQk8a2V5PmNvbS5hcHBsZS5w
+	cmludC50aWNrZXQuaXRlbUFycmF5PC9rZXk+CgkJPGFycmF5PgoJCQk8ZGljdD4KCQkJ
+	CTxrZXk+Y29tLmFwcGxlLnByaW50LlBhZ2VGb3JtYXQuUE1Ib3Jpem9udGFsUmVzPC9r
+	ZXk+CgkJCQk8cmVhbD43MjwvcmVhbD4KCQkJCTxrZXk+Y29tLmFwcGxlLnByaW50LnRp
+	Y2tldC5zdGF0ZUZsYWc8L2tleT4KCQkJCTxpbnRlZ2VyPjA8L2ludGVnZXI+CgkJCTwv
+	ZGljdD4KCQk8L2FycmF5PgoJPC9kaWN0PgoJPGtleT5jb20uYXBwbGUucHJpbnQuUGFn
+	ZUZvcm1hdC5QTU9yaWVudGF0aW9uPC9rZXk+Cgk8ZGljdD4KCQk8a2V5PmNvbS5hcHBs
+	ZS5wcmludC50aWNrZXQuY3JlYXRvcjwva2V5PgoJCTxzdHJpbmc+Y29tLmFwcGxlLmpv
+	YnRpY2tldDwvc3RyaW5nPgoJCTxrZXk+Y29tLmFwcGxlLnByaW50LnRpY2tldC5pdGVt
+	QXJyYXk8L2tleT4KCQk8YXJyYXk+CgkJCTxkaWN0PgoJCQkJPGtleT5jb20uYXBwbGUu
+	cHJpbnQuUGFnZUZvcm1hdC5QTU9yaWVudGF0aW9uPC9rZXk+CgkJCQk8aW50ZWdlcj4x
+	PC9pbnRlZ2VyPgoJCQkJPGtleT5jb20uYXBwbGUucHJpbnQudGlja2V0LnN0YXRlRmxh
+	Zzwva2V5PgoJCQkJPGludGVnZXI+MDwvaW50ZWdlcj4KCQkJPC9kaWN0PgoJCTwvYXJy
+	YXk+Cgk8L2RpY3Q+Cgk8a2V5PmNvbS5hcHBsZS5wcmludC5QYWdlRm9ybWF0LlBNU2Nh
+	bGluZzwva2V5PgoJPGRpY3Q+CgkJPGtleT5jb20uYXBwbGUucHJpbnQudGlja2V0LmNy
+	ZWF0b3I8L2tleT4KCQk8c3RyaW5nPmNvbS5hcHBsZS5qb2J0aWNrZXQ8L3N0cmluZz4K
+	CQk8a2V5PmNvbS5hcHBsZS5wcmludC50aWNrZXQuaXRlbUFycmF5PC9rZXk+CgkJPGFy
+	cmF5PgoJCQk8ZGljdD4KCQkJCTxrZXk+Y29tLmFwcGxlLnByaW50LlBhZ2VGb3JtYXQu
+	UE1TY2FsaW5nPC9rZXk+CgkJCQk8cmVhbD4xPC9yZWFsPgoJCQkJPGtleT5jb20uYXBw
+	bGUucHJpbnQudGlja2V0LnN0YXRlRmxhZzwva2V5PgoJCQkJPGludGVnZXI+MDwvaW50
+	ZWdlcj4KCQkJPC9kaWN0PgoJCTwvYXJyYXk+Cgk8L2RpY3Q+Cgk8a2V5PmNvbS5hcHBs
+	ZS5wcmludC5QYWdlRm9ybWF0LlBNVmVydGljYWxSZXM8L2tleT4KCTxkaWN0PgoJCTxr
+	ZXk+Y29tLmFwcGxlLnByaW50LnRpY2tldC5jcmVhdG9yPC9rZXk+CgkJPHN0cmluZz5j
+	b20uYXBwbGUuam9idGlja2V0PC9zdHJpbmc+CgkJPGtleT5jb20uYXBwbGUucHJpbnQu
+	dGlja2V0Lml0ZW1BcnJheTwva2V5PgoJCTxhcnJheT4KCQkJPGRpY3Q+CgkJCQk8a2V5
+	PmNvbS5hcHBsZS5wcmludC5QYWdlRm9ybWF0LlBNVmVydGljYWxSZXM8L2tleT4KCQkJ
+	CTxyZWFsPjcyPC9yZWFsPgoJCQkJPGtleT5jb20uYXBwbGUucHJpbnQudGlja2V0LnN0
+	YXRlRmxhZzwva2V5PgoJCQkJPGludGVnZXI+MDwvaW50ZWdlcj4KCQkJPC9kaWN0PgoJ
+	CTwvYXJyYXk+Cgk8L2RpY3Q+Cgk8a2V5PmNvbS5hcHBsZS5wcmludC5QYWdlRm9ybWF0
+	LlBNVmVydGljYWxTY2FsaW5nPC9rZXk+Cgk8ZGljdD4KCQk8a2V5PmNvbS5hcHBsZS5w
+	cmludC50aWNrZXQuY3JlYXRvcjwva2V5PgoJCTxzdHJpbmc+Y29tLmFwcGxlLmpvYnRp
+	Y2tldDwvc3RyaW5nPgoJCTxrZXk+Y29tLmFwcGxlLnByaW50LnRpY2tldC5pdGVtQXJy
+	YXk8L2tleT4KCQk8YXJyYXk+CgkJCTxkaWN0PgoJCQkJPGtleT5jb20uYXBwbGUucHJp
+	bnQuUGFnZUZvcm1hdC5QTVZlcnRpY2FsU2NhbGluZzwva2V5PgoJCQkJPHJlYWw+MTwv
+	cmVhbD4KCQkJCTxrZXk+Y29tLmFwcGxlLnByaW50LnRpY2tldC5zdGF0ZUZsYWc8L2tl
+	eT4KCQkJCTxpbnRlZ2VyPjA8L2ludGVnZXI+CgkJCTwvZGljdD4KCQk8L2FycmF5PgoJ
+	PC9kaWN0PgoJPGtleT5jb20uYXBwbGUucHJpbnQuc3ViVGlja2V0LnBhcGVyX2luZm9f
+	dGlja2V0PC9rZXk+Cgk8ZGljdD4KCQk8a2V5PmNvbS5hcHBsZS5wcmludC5QYWdlRm9y
+	bWF0LlBNQWRqdXN0ZWRQYWdlUmVjdDwva2V5PgoJCTxkaWN0PgoJCQk8a2V5PmNvbS5h
+	cHBsZS5wcmludC50aWNrZXQuY3JlYXRvcjwva2V5PgoJCQk8c3RyaW5nPmNvbS5hcHBs
+	ZS5qb2J0aWNrZXQ8L3N0cmluZz4KCQkJPGtleT5jb20uYXBwbGUucHJpbnQudGlja2V0
+	Lml0ZW1BcnJheTwva2V5PgoJCQk8YXJyYXk+CgkJCQk8ZGljdD4KCQkJCQk8a2V5PmNv
+	bS5hcHBsZS5wcmludC5QYWdlRm9ybWF0LlBNQWRqdXN0ZWRQYWdlUmVjdDwva2V5PgoJ
+	CQkJCTxhcnJheT4KCQkJCQkJPHJlYWw+MC4wPC9yZWFsPgoJCQkJCQk8cmVhbD4wLjA8
+	L3JlYWw+CgkJCQkJCTxyZWFsPjczNDwvcmVhbD4KCQkJCQkJPHJlYWw+NTc2PC9yZWFs
+	PgoJCQkJCTwvYXJyYXk+CgkJCQkJPGtleT5jb20uYXBwbGUucHJpbnQudGlja2V0LnN0
+	YXRlRmxhZzwva2V5PgoJCQkJCTxpbnRlZ2VyPjA8L2ludGVnZXI+CgkJCQk8L2RpY3Q+
+	CgkJCTwvYXJyYXk+CgkJPC9kaWN0PgoJCTxrZXk+Y29tLmFwcGxlLnByaW50LlBhZ2VG
+	b3JtYXQuUE1BZGp1c3RlZFBhcGVyUmVjdDwva2V5PgoJCTxkaWN0PgoJCQk8a2V5PmNv
+	bS5hcHBsZS5wcmludC50aWNrZXQuY3JlYXRvcjwva2V5PgoJCQk8c3RyaW5nPmNvbS5h
+	cHBsZS5qb2J0aWNrZXQ8L3N0cmluZz4KCQkJPGtleT5jb20uYXBwbGUucHJpbnQudGlj
+	a2V0Lml0ZW1BcnJheTwva2V5PgoJCQk8YXJyYXk+CgkJCQk8ZGljdD4KCQkJCQk8a2V5
+	PmNvbS5hcHBsZS5wcmludC5QYWdlRm9ybWF0LlBNQWRqdXN0ZWRQYXBlclJlY3Q8L2tl
+	eT4KCQkJCQk8YXJyYXk+CgkJCQkJCTxyZWFsPi0xODwvcmVhbD4KCQkJCQkJPHJlYWw+
+	LTE4PC9yZWFsPgoJCQkJCQk8cmVhbD43NzQ8L3JlYWw+CgkJCQkJCTxyZWFsPjU5NDwv
+	cmVhbD4KCQkJCQk8L2FycmF5PgoJCQkJCTxrZXk+Y29tLmFwcGxlLnByaW50LnRpY2tl
+	dC5zdGF0ZUZsYWc8L2tleT4KCQkJCQk8aW50ZWdlcj4wPC9pbnRlZ2VyPgoJCQkJPC9k
+	aWN0PgoJCQk8L2FycmF5PgoJCTwvZGljdD4KCQk8a2V5PmNvbS5hcHBsZS5wcmludC5Q
+	YXBlckluZm8uUE1QYXBlck5hbWU8L2tleT4KCQk8ZGljdD4KCQkJPGtleT5jb20uYXBw
+	bGUucHJpbnQudGlja2V0LmNyZWF0b3I8L2tleT4KCQkJPHN0cmluZz5jb20uYXBwbGUu
+	am9idGlja2V0PC9zdHJpbmc+CgkJCTxrZXk+Y29tLmFwcGxlLnByaW50LnRpY2tldC5p
+	dGVtQXJyYXk8L2tleT4KCQkJPGFycmF5PgoJCQkJPGRpY3Q+CgkJCQkJPGtleT5jb20u
+	YXBwbGUucHJpbnQuUGFwZXJJbmZvLlBNUGFwZXJOYW1lPC9rZXk+CgkJCQkJPHN0cmlu
+	Zz5uYS1sZXR0ZXI8L3N0cmluZz4KCQkJCQk8a2V5PmNvbS5hcHBsZS5wcmludC50aWNr
+	ZXQuc3RhdGVGbGFnPC9rZXk+CgkJCQkJPGludGVnZXI+MDwvaW50ZWdlcj4KCQkJCTwv
+	ZGljdD4KCQkJPC9hcnJheT4KCQk8L2RpY3Q+CgkJPGtleT5jb20uYXBwbGUucHJpbnQu
+	UGFwZXJJbmZvLlBNVW5hZGp1c3RlZFBhZ2VSZWN0PC9rZXk+CgkJPGRpY3Q+CgkJCTxr
+	ZXk+Y29tLmFwcGxlLnByaW50LnRpY2tldC5jcmVhdG9yPC9rZXk+CgkJCTxzdHJpbmc+
+	Y29tLmFwcGxlLmpvYnRpY2tldDwvc3RyaW5nPgoJCQk8a2V5PmNvbS5hcHBsZS5wcmlu
+	dC50aWNrZXQuaXRlbUFycmF5PC9rZXk+CgkJCTxhcnJheT4KCQkJCTxkaWN0PgoJCQkJ
+	CTxrZXk+Y29tLmFwcGxlLnByaW50LlBhcGVySW5mby5QTVVuYWRqdXN0ZWRQYWdlUmVj
+	dDwva2V5PgoJCQkJCTxhcnJheT4KCQkJCQkJPHJlYWw+MC4wPC9yZWFsPgoJCQkJCQk8
+	cmVhbD4wLjA8L3JlYWw+CgkJCQkJCTxyZWFsPjczNDwvcmVhbD4KCQkJCQkJPHJlYWw+
+	NTc2PC9yZWFsPgoJCQkJCTwvYXJyYXk+CgkJCQkJPGtleT5jb20uYXBwbGUucHJpbnQu
+	dGlja2V0LnN0YXRlRmxhZzwva2V5PgoJCQkJCTxpbnRlZ2VyPjA8L2ludGVnZXI+CgkJ
+	CQk8L2RpY3Q+CgkJCTwvYXJyYXk+CgkJPC9kaWN0PgoJCTxrZXk+Y29tLmFwcGxlLnBy
+	aW50LlBhcGVySW5mby5QTVVuYWRqdXN0ZWRQYXBlclJlY3Q8L2tleT4KCQk8ZGljdD4K
+	CQkJPGtleT5jb20uYXBwbGUucHJpbnQudGlja2V0LmNyZWF0b3I8L2tleT4KCQkJPHN0
+	cmluZz5jb20uYXBwbGUuam9idGlja2V0PC9zdHJpbmc+CgkJCTxrZXk+Y29tLmFwcGxl
+	LnByaW50LnRpY2tldC5pdGVtQXJyYXk8L2tleT4KCQkJPGFycmF5PgoJCQkJPGRpY3Q+
+	CgkJCQkJPGtleT5jb20uYXBwbGUucHJpbnQuUGFwZXJJbmZvLlBNVW5hZGp1c3RlZFBh
+	cGVyUmVjdDwva2V5PgoJCQkJCTxhcnJheT4KCQkJCQkJPHJlYWw+LTE4PC9yZWFsPgoJ
+	CQkJCQk8cmVhbD4tMTg8L3JlYWw+CgkJCQkJCTxyZWFsPjc3NDwvcmVhbD4KCQkJCQkJ
+	PHJlYWw+NTk0PC9yZWFsPgoJCQkJCTwvYXJyYXk+CgkJCQkJPGtleT5jb20uYXBwbGUu
+	cHJpbnQudGlja2V0LnN0YXRlRmxhZzwva2V5PgoJCQkJCTxpbnRlZ2VyPjA8L2ludGVn
+	ZXI+CgkJCQk8L2RpY3Q+CgkJCTwvYXJyYXk+CgkJPC9kaWN0PgoJCTxrZXk+Y29tLmFw
+	cGxlLnByaW50LlBhcGVySW5mby5wcGQuUE1QYXBlck5hbWU8L2tleT4KCQk8ZGljdD4K
+	CQkJPGtleT5jb20uYXBwbGUucHJpbnQudGlja2V0LmNyZWF0b3I8L2tleT4KCQkJPHN0
+	cmluZz5jb20uYXBwbGUuam9idGlja2V0PC9zdHJpbmc+CgkJCTxrZXk+Y29tLmFwcGxl
+	LnByaW50LnRpY2tldC5pdGVtQXJyYXk8L2tleT4KCQkJPGFycmF5PgoJCQkJPGRpY3Q+
+	CgkJCQkJPGtleT5jb20uYXBwbGUucHJpbnQuUGFwZXJJbmZvLnBwZC5QTVBhcGVyTmFt
+	ZTwva2V5PgoJCQkJCTxzdHJpbmc+TGV0dGVyPC9zdHJpbmc+CgkJCQkJPGtleT5jb20u
+	YXBwbGUucHJpbnQudGlja2V0LnN0YXRlRmxhZzwva2V5PgoJCQkJCTxpbnRlZ2VyPjA8
+	L2ludGVnZXI+CgkJCQk8L2RpY3Q+CgkJCTwvYXJyYXk+CgkJPC9kaWN0PgoJCTxrZXk+
+	Y29tLmFwcGxlLnByaW50LnRpY2tldC5BUElWZXJzaW9uPC9rZXk+CgkJPHN0cmluZz4w
+	MC4yMDwvc3RyaW5nPgoJCTxrZXk+Y29tLmFwcGxlLnByaW50LnRpY2tldC50eXBlPC9r
+	ZXk+CgkJPHN0cmluZz5jb20uYXBwbGUucHJpbnQuUGFwZXJJbmZvVGlja2V0PC9zdHJp
+	bmc+Cgk8L2RpY3Q+Cgk8a2V5PmNvbS5hcHBsZS5wcmludC50aWNrZXQuQVBJVmVyc2lv
+	bjwva2V5PgoJPHN0cmluZz4wMC4yMDwvc3RyaW5nPgoJPGtleT5jb20uYXBwbGUucHJp
+	bnQudGlja2V0LnR5cGU8L2tleT4KCTxzdHJpbmc+Y29tLmFwcGxlLnByaW50LlBhZ2VG
+	b3JtYXRUaWNrZXQ8L3N0cmluZz4KPC9kaWN0Pgo8L3BsaXN0PgqGkoSZmQtOU1BhcGVy
+	U2l6ZYaShJychIQMe19OU1NpemU9ZmZ9oYECZIEDGIaGhg==
+	</data>
+	<key>ReadOnly</key>
+	<string>NO</string>
+	<key>RowAlign</key>
+	<integer>1</integer>
+	<key>RowSpacing</key>
+	<real>36</real>
+	<key>SheetTitle</key>
+	<string>Canvas 1</string>
+	<key>SmartAlignmentGuidesActive</key>
+	<string>YES</string>
+	<key>SmartDistanceGuidesActive</key>
+	<string>YES</string>
+	<key>UseEntirePage</key>
+	<false/>
+	<key>VPages</key>
+	<integer>1</integer>
+	<key>WindowInfo</key>
+	<dict>
+		<key>CurrentSheet</key>
+		<string>0</string>
+		<key>Frame</key>
+		<string>{{424, 54}, {591, 823}}</string>
+		<key>ShowRuler</key>
+		<false/>
+		<key>ShowStatusBar</key>
+		<true/>
+		<key>VisibleRegion</key>
+		<string>{{0, 0}, {576, 725}}</string>
+		<key>Zoom</key>
+		<string>1</string>
+	</dict>
+</dict>
+</plist>
Index: /trunk/contrib/krueger/InterfaceProjects/Hello World/hello.nib/designable.nib
===================================================================
--- /trunk/contrib/krueger/InterfaceProjects/Hello World/hello.nib/designable.nib	(revision 13946)
+++ /trunk/contrib/krueger/InterfaceProjects/Hello World/hello.nib/designable.nib	(revision 13946)
@@ -0,0 +1,222 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<archive type="com.apple.InterfaceBuilder3.Cocoa.XIB" version="7.03">
+	<data>
+		<int key="IBDocument.SystemTarget">1050</int>
+		<string key="IBDocument.SystemVersion">9L30</string>
+		<string key="IBDocument.InterfaceBuilderVersion">680</string>
+		<string key="IBDocument.AppKitVersion">949.54</string>
+		<string key="IBDocument.HIToolboxVersion">353.00</string>
+		<object class="NSMutableArray" key="IBDocument.EditedObjectIDs">
+			<bool key="EncodedWithXMLCoder">YES</bool>
+			<integer value="2"/>
+		</object>
+		<object class="NSArray" key="IBDocument.PluginDependencies">
+			<bool key="EncodedWithXMLCoder">YES</bool>
+			<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
+		</object>
+		<object class="NSMutableDictionary" key="IBDocument.Metadata">
+			<bool key="EncodedWithXMLCoder">YES</bool>
+			<object class="NSArray" key="dict.sortedKeys">
+				<bool key="EncodedWithXMLCoder">YES</bool>
+			</object>
+			<object class="NSMutableArray" key="dict.values">
+				<bool key="EncodedWithXMLCoder">YES</bool>
+			</object>
+		</object>
+		<object class="NSMutableArray" key="IBDocument.RootObjects" id="1000">
+			<bool key="EncodedWithXMLCoder">YES</bool>
+			<object class="NSCustomObject" id="1001">
+				<string key="NSClassName">NSObject</string>
+			</object>
+			<object class="NSCustomObject" id="1003">
+				<string key="NSClassName">FirstResponder</string>
+			</object>
+			<object class="NSCustomObject" id="1004">
+				<string key="NSClassName">NSApplication</string>
+			</object>
+			<object class="NSWindowTemplate" id="1005">
+				<int key="NSWindowStyleMask">15</int>
+				<int key="NSWindowBacking">2</int>
+				<string key="NSWindowRect">{{196, 240}, {480, 270}}</string>
+				<int key="NSWTFlags">536870912</int>
+				<string key="NSWindowTitle">Hi there!</string>
+				<string key="NSWindowClass">NSWindow</string>
+				<nil key="NSViewClass"/>
+				<string key="NSWindowContentMaxSize">{3.40282e+38, 3.40282e+38}</string>
+				<object class="NSView" key="NSWindowView" id="1006">
+					<reference key="NSNextResponder"/>
+					<int key="NSvFlags">256</int>
+					<object class="NSMutableArray" key="NSSubviews">
+						<bool key="EncodedWithXMLCoder">YES</bool>
+						<object class="NSTextField" id="485456714">
+							<reference key="NSNextResponder" ref="1006"/>
+							<int key="NSvFlags">268</int>
+							<string key="NSFrame">{{203, 141}, {81, 17}}</string>
+							<reference key="NSSuperview" ref="1006"/>
+							<bool key="NSEnabled">YES</bool>
+							<object class="NSTextFieldCell" key="NSCell" id="272763383">
+								<int key="NSCellFlags">68288064</int>
+								<int key="NSCellFlags2">272630784</int>
+								<string key="NSContents">Hello World!</string>
+								<object class="NSFont" key="NSSupport">
+									<string key="NSName">LucidaGrande</string>
+									<double key="NSSize">1.300000e+01</double>
+									<int key="NSfFlags">1044</int>
+								</object>
+								<reference key="NSControlView" ref="485456714"/>
+								<object class="NSColor" key="NSBackgroundColor">
+									<int key="NSColorSpace">6</int>
+									<string key="NSCatalogName">System</string>
+									<string key="NSColorName">controlColor</string>
+									<object class="NSColor" key="NSColor">
+										<int key="NSColorSpace">3</int>
+										<bytes key="NSWhite">MC42NjY2NjY2OQA</bytes>
+									</object>
+								</object>
+								<object class="NSColor" key="NSTextColor">
+									<int key="NSColorSpace">6</int>
+									<string key="NSCatalogName">System</string>
+									<string key="NSColorName">controlTextColor</string>
+									<object class="NSColor" key="NSColor">
+										<int key="NSColorSpace">3</int>
+										<bytes key="NSWhite">MAA</bytes>
+									</object>
+								</object>
+							</object>
+						</object>
+					</object>
+					<string key="NSFrameSize">{480, 270}</string>
+					<reference key="NSSuperview"/>
+				</object>
+				<string key="NSScreenRect">{{0, 0}, {1680, 1028}}</string>
+				<string key="NSMaxSize">{3.40282e+38, 3.40282e+38}</string>
+			</object>
+		</object>
+		<object class="IBObjectContainer" key="IBDocument.Objects">
+			<object class="NSMutableArray" key="connectionRecords">
+				<bool key="EncodedWithXMLCoder">YES</bool>
+			</object>
+			<object class="IBMutableOrderedSet" key="objectRecords">
+				<object class="NSArray" key="orderedObjects">
+					<bool key="EncodedWithXMLCoder">YES</bool>
+					<object class="IBObjectRecord">
+						<int key="objectID">0</int>
+						<object class="NSArray" key="object" id="1002">
+							<bool key="EncodedWithXMLCoder">YES</bool>
+						</object>
+						<reference key="children" ref="1000"/>
+						<nil key="parent"/>
+					</object>
+					<object class="IBObjectRecord">
+						<int key="objectID">-2</int>
+						<reference key="object" ref="1001"/>
+						<reference key="parent" ref="1002"/>
+						<string type="base64-UTF8" key="objectName">RmlsZSdzIE93bmVyA</string>
+					</object>
+					<object class="IBObjectRecord">
+						<int key="objectID">-1</int>
+						<reference key="object" ref="1003"/>
+						<reference key="parent" ref="1002"/>
+						<string key="objectName">First Responder</string>
+					</object>
+					<object class="IBObjectRecord">
+						<int key="objectID">-3</int>
+						<reference key="object" ref="1004"/>
+						<reference key="parent" ref="1002"/>
+						<string key="objectName">Application</string>
+					</object>
+					<object class="IBObjectRecord">
+						<int key="objectID">1</int>
+						<reference key="object" ref="1005"/>
+						<object class="NSMutableArray" key="children">
+							<bool key="EncodedWithXMLCoder">YES</bool>
+							<reference ref="1006"/>
+						</object>
+						<reference key="parent" ref="1002"/>
+					</object>
+					<object class="IBObjectRecord">
+						<int key="objectID">2</int>
+						<reference key="object" ref="1006"/>
+						<object class="NSMutableArray" key="children">
+							<bool key="EncodedWithXMLCoder">YES</bool>
+							<reference ref="485456714"/>
+						</object>
+						<reference key="parent" ref="1005"/>
+					</object>
+					<object class="IBObjectRecord">
+						<int key="objectID">3</int>
+						<reference key="object" ref="485456714"/>
+						<object class="NSMutableArray" key="children">
+							<bool key="EncodedWithXMLCoder">YES</bool>
+							<reference ref="272763383"/>
+						</object>
+						<reference key="parent" ref="1006"/>
+					</object>
+					<object class="IBObjectRecord">
+						<int key="objectID">4</int>
+						<reference key="object" ref="272763383"/>
+						<reference key="parent" ref="485456714"/>
+					</object>
+				</object>
+			</object>
+			<object class="NSMutableDictionary" key="flattenedProperties">
+				<bool key="EncodedWithXMLCoder">YES</bool>
+				<object class="NSMutableArray" key="dict.sortedKeys">
+					<bool key="EncodedWithXMLCoder">YES</bool>
+					<string>-1.IBPluginDependency</string>
+					<string>-2.IBPluginDependency</string>
+					<string>-3.IBPluginDependency</string>
+					<string>1.IBEditorWindowLastContentRect</string>
+					<string>1.IBPluginDependency</string>
+					<string>1.IBWindowTemplateEditedContentRect</string>
+					<string>1.NSWindowTemplate.visibleAtLaunch</string>
+					<string>1.WindowOrigin</string>
+					<string>1.editorWindowContentRectSynchronizationRect</string>
+					<string>2.IBPluginDependency</string>
+					<string>3.IBPluginDependency</string>
+					<string>4.IBPluginDependency</string>
+				</object>
+				<object class="NSMutableArray" key="dict.values">
+					<bool key="EncodedWithXMLCoder">YES</bool>
+					<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
+					<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
+					<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
+					<string>{{29, 559}, {480, 270}}</string>
+					<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
+					<string>{{29, 559}, {480, 270}}</string>
+					<integer value="1"/>
+					<string>{196, 240}</string>
+					<string>{{357, 418}, {480, 270}}</string>
+					<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
+					<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
+					<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
+				</object>
+			</object>
+			<object class="NSMutableDictionary" key="unlocalizedProperties">
+				<bool key="EncodedWithXMLCoder">YES</bool>
+				<object class="NSArray" key="dict.sortedKeys">
+					<bool key="EncodedWithXMLCoder">YES</bool>
+				</object>
+				<object class="NSMutableArray" key="dict.values">
+					<bool key="EncodedWithXMLCoder">YES</bool>
+				</object>
+			</object>
+			<nil key="activeLocalization"/>
+			<object class="NSMutableDictionary" key="localizations">
+				<bool key="EncodedWithXMLCoder">YES</bool>
+				<object class="NSArray" key="dict.sortedKeys">
+					<bool key="EncodedWithXMLCoder">YES</bool>
+				</object>
+				<object class="NSMutableArray" key="dict.values">
+					<bool key="EncodedWithXMLCoder">YES</bool>
+				</object>
+			</object>
+			<nil key="sourceID"/>
+			<int key="maxID">4</int>
+		</object>
+		<object class="IBClassDescriber" key="IBDocument.Classes"/>
+		<int key="IBDocument.localizationMode">0</int>
+		<nil key="IBDocument.LastKnownRelativeProjectPath"/>
+		<int key="IBDocument.defaultPropertyAccessControl">3</int>
+	</data>
+</archive>
Index: /trunk/contrib/krueger/InterfaceProjects/Lisp IB Plugins/LispControllerPlugin/English.lproj/LispControllerInspector.xib
===================================================================
--- /trunk/contrib/krueger/InterfaceProjects/Lisp IB Plugins/LispControllerPlugin/English.lproj/LispControllerInspector.xib	(revision 13946)
+++ /trunk/contrib/krueger/InterfaceProjects/Lisp IB Plugins/LispControllerPlugin/English.lproj/LispControllerInspector.xib	(revision 13946)
@@ -0,0 +1,2309 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<archive type="com.apple.InterfaceBuilder3.Cocoa.XIB" version="7.03">
+	<data>
+		<int key="IBDocument.SystemTarget">1050</int>
+		<string key="IBDocument.SystemVersion">9L30</string>
+		<string key="IBDocument.InterfaceBuilderVersion">680</string>
+		<string key="IBDocument.AppKitVersion">949.54</string>
+		<string key="IBDocument.HIToolboxVersion">353.00</string>
+		<object class="NSMutableArray" key="IBDocument.EditedObjectIDs">
+			<bool key="EncodedWithXMLCoder">YES</bool>
+			<integer value="21"/>
+		</object>
+		<object class="NSArray" key="IBDocument.PluginDependencies">
+			<bool key="EncodedWithXMLCoder">YES</bool>
+			<string>com.apple.InterfaceBuilderKit</string>
+			<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
+		</object>
+		<object class="NSMutableDictionary" key="IBDocument.Metadata">
+			<bool key="EncodedWithXMLCoder">YES</bool>
+			<object class="NSArray" key="dict.sortedKeys">
+				<bool key="EncodedWithXMLCoder">YES</bool>
+			</object>
+			<object class="NSMutableArray" key="dict.values">
+				<bool key="EncodedWithXMLCoder">YES</bool>
+			</object>
+		</object>
+		<object class="NSMutableArray" key="IBDocument.RootObjects" id="1015158983">
+			<bool key="EncodedWithXMLCoder">YES</bool>
+			<object class="NSCustomObject" id="893560672">
+				<string key="NSClassName">LispControllerInspector</string>
+			</object>
+			<object class="NSCustomObject" id="904349417">
+				<string key="NSClassName">FirstResponder</string>
+			</object>
+			<object class="NSCustomObject" id="510210961">
+				<string key="NSClassName">NSApplication</string>
+			</object>
+			<object class="NSCustomView" id="148061301">
+				<reference key="NSNextResponder"/>
+				<int key="NSvFlags">256</int>
+				<object class="NSMutableArray" key="NSSubviews">
+					<bool key="EncodedWithXMLCoder">YES</bool>
+					<object class="NSTextField" id="767324328">
+						<reference key="NSNextResponder" ref="148061301"/>
+						<int key="NSvFlags">268</int>
+						<string key="NSFrame">{{100, 660}, {155, 16}}</string>
+						<reference key="NSSuperview" ref="148061301"/>
+						<bool key="NSEnabled">YES</bool>
+						<object class="NSTextFieldCell" key="NSCell" id="361495836">
+							<int key="NSCellFlags">-1804468671</int>
+							<int key="NSCellFlags2">-1874590720</int>
+							<string key="NSContents"/>
+							<object class="NSFont" key="NSSupport" id="22">
+								<string key="NSName">LucidaGrande</string>
+								<double key="NSSize">9.000000e+00</double>
+								<int key="NSfFlags">3614</int>
+							</object>
+							<reference key="NSControlView" ref="767324328"/>
+							<bool key="NSDrawsBackground">YES</bool>
+							<object class="NSColor" key="NSBackgroundColor" id="1033003658">
+								<int key="NSColorSpace">6</int>
+								<string key="NSCatalogName">System</string>
+								<string key="NSColorName">textBackgroundColor</string>
+								<object class="NSColor" key="NSColor" id="440740257">
+									<int key="NSColorSpace">3</int>
+									<bytes key="NSWhite">MQA</bytes>
+								</object>
+							</object>
+							<object class="NSColor" key="NSTextColor" id="363125112">
+								<int key="NSColorSpace">6</int>
+								<string key="NSCatalogName">System</string>
+								<string key="NSColorName">textColor</string>
+								<object class="NSColor" key="NSColor" id="692185638">
+									<int key="NSColorSpace">3</int>
+									<bytes key="NSWhite">MAA</bytes>
+								</object>
+							</object>
+						</object>
+					</object>
+					<object class="NSTextField" id="771170495">
+						<reference key="NSNextResponder" ref="148061301"/>
+						<int key="NSvFlags">268</int>
+						<string key="NSFrame">{{8, 660}, {83, 14}}</string>
+						<reference key="NSSuperview" ref="148061301"/>
+						<bool key="NSEnabled">YES</bool>
+						<object class="NSTextFieldCell" key="NSCell" id="272507628">
+							<int key="NSCellFlags">67239488</int>
+							<int key="NSCellFlags2">4326400</int>
+							<string key="NSContents">Root Type</string>
+							<object class="NSFont" key="NSSupport" id="75607641">
+								<string key="NSName">LucidaGrande-Bold</string>
+								<double key="NSSize">1.100000e+01</double>
+								<int key="NSfFlags">16</int>
+							</object>
+							<reference key="NSControlView" ref="771170495"/>
+							<object class="NSColor" key="NSBackgroundColor" id="492759629">
+								<int key="NSColorSpace">6</int>
+								<string key="NSCatalogName">System</string>
+								<string key="NSColorName">controlColor</string>
+								<object class="NSColor" key="NSColor" id="701463694">
+									<int key="NSColorSpace">3</int>
+									<bytes key="NSWhite">MC42NjY2NjY2OQA</bytes>
+								</object>
+							</object>
+							<object class="NSColor" key="NSTextColor" id="378390125">
+								<int key="NSColorSpace">6</int>
+								<string key="NSCatalogName">System</string>
+								<string key="NSColorName">controlTextColor</string>
+								<reference key="NSColor" ref="692185638"/>
+							</object>
+						</object>
+					</object>
+					<object class="NSTextField" id="318678771">
+						<reference key="NSNextResponder" ref="148061301"/>
+						<int key="NSvFlags">268</int>
+						<string key="NSFrame">{{100, 210}, {155, 16}}</string>
+						<reference key="NSSuperview" ref="148061301"/>
+						<bool key="NSEnabled">YES</bool>
+						<object class="NSTextFieldCell" key="NSCell" id="646248930">
+							<int key="NSCellFlags">-1804468671</int>
+							<int key="NSCellFlags2">-1874590720</int>
+							<string key="NSContents"/>
+							<reference key="NSSupport" ref="22"/>
+							<reference key="NSControlView" ref="318678771"/>
+							<bool key="NSDrawsBackground">YES</bool>
+							<reference key="NSBackgroundColor" ref="1033003658"/>
+							<reference key="NSTextColor" ref="363125112"/>
+						</object>
+					</object>
+					<object class="NSTextField" id="105666546">
+						<reference key="NSNextResponder" ref="148061301"/>
+						<int key="NSvFlags">268</int>
+						<string key="NSFrame">{{8, 211}, {86, 14}}</string>
+						<reference key="NSSuperview" ref="148061301"/>
+						<bool key="NSEnabled">YES</bool>
+						<object class="NSTextFieldCell" key="NSCell" id="725974029">
+							<int key="NSCellFlags">67239488</int>
+							<int key="NSCellFlags2">4326400</int>
+							<string key="NSContents">When Selected</string>
+							<reference key="NSSupport" ref="75607641"/>
+							<reference key="NSControlView" ref="105666546"/>
+							<reference key="NSBackgroundColor" ref="492759629"/>
+							<reference key="NSTextColor" ref="378390125"/>
+						</object>
+					</object>
+					<object class="NSTextField" id="187508141">
+						<reference key="NSNextResponder" ref="148061301"/>
+						<int key="NSvFlags">268</int>
+						<string key="NSFrame">{{100, 193}, {155, 16}}</string>
+						<reference key="NSSuperview" ref="148061301"/>
+						<bool key="NSEnabled">YES</bool>
+						<object class="NSTextFieldCell" key="NSCell" id="344238193">
+							<int key="NSCellFlags">-1804468671</int>
+							<int key="NSCellFlags2">-1874590720</int>
+							<string key="NSContents"/>
+							<reference key="NSSupport" ref="22"/>
+							<reference key="NSControlView" ref="187508141"/>
+							<bool key="NSDrawsBackground">YES</bool>
+							<reference key="NSBackgroundColor" ref="1033003658"/>
+							<reference key="NSTextColor" ref="363125112"/>
+						</object>
+					</object>
+					<object class="NSTextField" id="407866252">
+						<reference key="NSNextResponder" ref="148061301"/>
+						<int key="NSvFlags">268</int>
+						<string key="NSFrame">{{8, 194}, {83, 14}}</string>
+						<reference key="NSSuperview" ref="148061301"/>
+						<bool key="NSEnabled">YES</bool>
+						<object class="NSTextFieldCell" key="NSCell" id="1073664548">
+							<int key="NSCellFlags">67239488</int>
+							<int key="NSCellFlags2">4326400</int>
+							<string key="NSContents">When Edited</string>
+							<reference key="NSSupport" ref="75607641"/>
+							<reference key="NSControlView" ref="407866252"/>
+							<reference key="NSBackgroundColor" ref="492759629"/>
+							<reference key="NSTextColor" ref="378390125"/>
+						</object>
+					</object>
+					<object class="NSTextField" id="562507321">
+						<reference key="NSNextResponder" ref="148061301"/>
+						<int key="NSvFlags">268</int>
+						<string key="NSFrame">{{100, 176}, {155, 16}}</string>
+						<reference key="NSSuperview" ref="148061301"/>
+						<bool key="NSEnabled">YES</bool>
+						<object class="NSTextFieldCell" key="NSCell" id="269625364">
+							<int key="NSCellFlags">-1804468671</int>
+							<int key="NSCellFlags2">-1874590720</int>
+							<string key="NSContents"/>
+							<reference key="NSSupport" ref="22"/>
+							<reference key="NSControlView" ref="562507321"/>
+							<bool key="NSDrawsBackground">YES</bool>
+							<reference key="NSBackgroundColor" ref="1033003658"/>
+							<reference key="NSTextColor" ref="363125112"/>
+						</object>
+					</object>
+					<object class="NSTextField" id="1023286907">
+						<reference key="NSNextResponder" ref="148061301"/>
+						<int key="NSvFlags">268</int>
+						<string key="NSFrame">{{100, 159}, {155, 16}}</string>
+						<reference key="NSSuperview" ref="148061301"/>
+						<bool key="NSEnabled">YES</bool>
+						<object class="NSTextFieldCell" key="NSCell" id="117861619">
+							<int key="NSCellFlags">-1804468671</int>
+							<int key="NSCellFlags2">-1874590720</int>
+							<string key="NSContents"/>
+							<reference key="NSSupport" ref="22"/>
+							<reference key="NSControlView" ref="1023286907"/>
+							<bool key="NSDrawsBackground">YES</bool>
+							<reference key="NSBackgroundColor" ref="1033003658"/>
+							<reference key="NSTextColor" ref="363125112"/>
+						</object>
+					</object>
+					<object class="NSTextField" id="741831275">
+						<reference key="NSNextResponder" ref="148061301"/>
+						<int key="NSvFlags">268</int>
+						<string key="NSFrame">{{8, 177}, {83, 14}}</string>
+						<reference key="NSSuperview" ref="148061301"/>
+						<bool key="NSEnabled">YES</bool>
+						<object class="NSTextFieldCell" key="NSCell" id="1071223370">
+							<int key="NSCellFlags">67239488</int>
+							<int key="NSCellFlags2">4326400</int>
+							<string key="NSContents">When Added</string>
+							<reference key="NSSupport" ref="75607641"/>
+							<reference key="NSControlView" ref="741831275"/>
+							<reference key="NSBackgroundColor" ref="492759629"/>
+							<reference key="NSTextColor" ref="378390125"/>
+						</object>
+					</object>
+					<object class="NSTextField" id="1072792659">
+						<reference key="NSNextResponder" ref="148061301"/>
+						<int key="NSvFlags">268</int>
+						<string key="NSFrame">{{8, 160}, {91, 14}}</string>
+						<reference key="NSSuperview" ref="148061301"/>
+						<bool key="NSEnabled">YES</bool>
+						<object class="NSTextFieldCell" key="NSCell" id="136537671">
+							<int key="NSCellFlags">67239488</int>
+							<int key="NSCellFlags2">4326400</int>
+							<string key="NSContents">When Removed</string>
+							<reference key="NSSupport" ref="75607641"/>
+							<reference key="NSControlView" ref="1072792659"/>
+							<reference key="NSBackgroundColor" ref="492759629"/>
+							<reference key="NSTextColor" ref="378390125"/>
+						</object>
+					</object>
+					<object class="NSTextField" id="705814818">
+						<reference key="NSNextResponder" ref="148061301"/>
+						<int key="NSvFlags">268</int>
+						<string key="NSFrame">{{100, 114}, {155, 16}}</string>
+						<reference key="NSSuperview" ref="148061301"/>
+						<bool key="NSEnabled">YES</bool>
+						<object class="NSTextFieldCell" key="NSCell" id="21424487">
+							<int key="NSCellFlags">-1804468671</int>
+							<int key="NSCellFlags2">-1874590720</int>
+							<string key="NSContents"/>
+							<reference key="NSSupport" ref="22"/>
+							<reference key="NSControlView" ref="705814818"/>
+							<bool key="NSDrawsBackground">YES</bool>
+							<reference key="NSBackgroundColor" ref="1033003658"/>
+							<reference key="NSTextColor" ref="363125112"/>
+						</object>
+					</object>
+					<object class="NSTextField" id="42828080">
+						<reference key="NSNextResponder" ref="148061301"/>
+						<int key="NSvFlags">268</int>
+						<string key="NSFrame">{{8, 115}, {83, 14}}</string>
+						<reference key="NSSuperview" ref="148061301"/>
+						<bool key="NSEnabled">YES</bool>
+						<object class="NSTextFieldCell" key="NSCell" id="55897682">
+							<int key="NSCellFlags">67239488</int>
+							<int key="NSCellFlags2">4326400</int>
+							<string key="NSContents">Children Key</string>
+							<reference key="NSSupport" ref="75607641"/>
+							<reference key="NSControlView" ref="42828080"/>
+							<reference key="NSBackgroundColor" ref="492759629"/>
+							<reference key="NSTextColor" ref="378390125"/>
+						</object>
+					</object>
+					<object class="NSTextField" id="770669533">
+						<reference key="NSNextResponder" ref="148061301"/>
+						<int key="NSvFlags">268</int>
+						<string key="NSFrame">{{100, 95}, {155, 16}}</string>
+						<reference key="NSSuperview" ref="148061301"/>
+						<bool key="NSEnabled">YES</bool>
+						<object class="NSTextFieldCell" key="NSCell" id="47473596">
+							<int key="NSCellFlags">-1804468671</int>
+							<int key="NSCellFlags2">-1874590720</int>
+							<string key="NSContents"/>
+							<reference key="NSSupport" ref="22"/>
+							<reference key="NSControlView" ref="770669533"/>
+							<bool key="NSDrawsBackground">YES</bool>
+							<reference key="NSBackgroundColor" ref="1033003658"/>
+							<reference key="NSTextColor" ref="363125112"/>
+						</object>
+					</object>
+					<object class="NSTextField" id="139589133">
+						<reference key="NSNextResponder" ref="148061301"/>
+						<int key="NSvFlags">268</int>
+						<string key="NSFrame">{{8, 96}, {83, 14}}</string>
+						<reference key="NSSuperview" ref="148061301"/>
+						<bool key="NSEnabled">YES</bool>
+						<object class="NSTextFieldCell" key="NSCell" id="312100719">
+							<int key="NSCellFlags">67239488</int>
+							<int key="NSCellFlags2">4326400</int>
+							<string key="NSContents">Child Count</string>
+							<reference key="NSSupport" ref="75607641"/>
+							<reference key="NSControlView" ref="139589133"/>
+							<reference key="NSBackgroundColor" ref="492759629"/>
+							<reference key="NSTextColor" ref="378390125"/>
+						</object>
+					</object>
+					<object class="NSTextField" id="7062143">
+						<reference key="NSNextResponder" ref="148061301"/>
+						<int key="NSvFlags">268</int>
+						<string key="NSFrame">{{100, 76}, {155, 16}}</string>
+						<reference key="NSSuperview" ref="148061301"/>
+						<bool key="NSEnabled">YES</bool>
+						<object class="NSTextFieldCell" key="NSCell" id="584905870">
+							<int key="NSCellFlags">-1804468671</int>
+							<int key="NSCellFlags2">-1874590720</int>
+							<string key="NSContents"/>
+							<reference key="NSSupport" ref="22"/>
+							<reference key="NSControlView" ref="7062143"/>
+							<bool key="NSDrawsBackground">YES</bool>
+							<reference key="NSBackgroundColor" ref="1033003658"/>
+							<reference key="NSTextColor" ref="363125112"/>
+						</object>
+					</object>
+					<object class="NSTextField" id="637960900">
+						<reference key="NSNextResponder" ref="148061301"/>
+						<int key="NSvFlags">268</int>
+						<string key="NSFrame">{{8, 77}, {83, 14}}</string>
+						<reference key="NSSuperview" ref="148061301"/>
+						<bool key="NSEnabled">YES</bool>
+						<object class="NSTextFieldCell" key="NSCell" id="287121334">
+							<int key="NSCellFlags">67239488</int>
+							<int key="NSCellFlags2">4326400</int>
+							<string key="NSContents">Col Reader</string>
+							<reference key="NSSupport" ref="75607641"/>
+							<reference key="NSControlView" ref="637960900"/>
+							<reference key="NSBackgroundColor" ref="492759629"/>
+							<reference key="NSTextColor" ref="378390125"/>
+						</object>
+					</object>
+					<object class="NSTextField" id="431874124">
+						<reference key="NSNextResponder" ref="148061301"/>
+						<int key="NSvFlags">268</int>
+						<string key="NSFrame">{{100, 57}, {155, 16}}</string>
+						<reference key="NSSuperview" ref="148061301"/>
+						<bool key="NSEnabled">YES</bool>
+						<object class="NSTextFieldCell" key="NSCell" id="584699695">
+							<int key="NSCellFlags">-1804468671</int>
+							<int key="NSCellFlags2">-1874590720</int>
+							<string key="NSContents"/>
+							<reference key="NSSupport" ref="22"/>
+							<reference key="NSControlView" ref="431874124"/>
+							<bool key="NSDrawsBackground">YES</bool>
+							<reference key="NSBackgroundColor" ref="1033003658"/>
+							<reference key="NSTextColor" ref="363125112"/>
+						</object>
+					</object>
+					<object class="NSTextField" id="472784790">
+						<reference key="NSNextResponder" ref="148061301"/>
+						<int key="NSvFlags">268</int>
+						<string key="NSFrame">{{8, 58}, {83, 14}}</string>
+						<reference key="NSSuperview" ref="148061301"/>
+						<bool key="NSEnabled">YES</bool>
+						<object class="NSTextFieldCell" key="NSCell" id="1012841858">
+							<int key="NSCellFlags">67239488</int>
+							<int key="NSCellFlags2">4326400</int>
+							<string key="NSContents">Col Writer</string>
+							<reference key="NSSupport" ref="75607641"/>
+							<reference key="NSControlView" ref="472784790"/>
+							<reference key="NSBackgroundColor" ref="492759629"/>
+							<reference key="NSTextColor" ref="378390125"/>
+						</object>
+					</object>
+					<object class="NSTextField" id="57441347">
+						<reference key="NSNextResponder" ref="148061301"/>
+						<int key="NSvFlags">268</int>
+						<string key="NSFrame">{{100, 38}, {155, 16}}</string>
+						<reference key="NSSuperview" ref="148061301"/>
+						<bool key="NSEnabled">YES</bool>
+						<object class="NSTextFieldCell" key="NSCell" id="510999695">
+							<int key="NSCellFlags">-1804468671</int>
+							<int key="NSCellFlags2">-1874590720</int>
+							<string key="NSContents"/>
+							<reference key="NSSupport" ref="22"/>
+							<reference key="NSControlView" ref="57441347"/>
+							<bool key="NSDrawsBackground">YES</bool>
+							<reference key="NSBackgroundColor" ref="1033003658"/>
+							<reference key="NSTextColor" ref="363125112"/>
+						</object>
+					</object>
+					<object class="NSTextField" id="1039472622">
+						<reference key="NSNextResponder" ref="148061301"/>
+						<int key="NSvFlags">268</int>
+						<string key="NSFrame">{{100, 19}, {155, 16}}</string>
+						<reference key="NSSuperview" ref="148061301"/>
+						<bool key="NSEnabled">YES</bool>
+						<object class="NSTextFieldCell" key="NSCell" id="12702536">
+							<int key="NSCellFlags">-1804468671</int>
+							<int key="NSCellFlags2">-1874590720</int>
+							<string key="NSContents"/>
+							<reference key="NSSupport" ref="22"/>
+							<reference key="NSControlView" ref="1039472622"/>
+							<bool key="NSDrawsBackground">YES</bool>
+							<reference key="NSBackgroundColor" ref="1033003658"/>
+							<reference key="NSTextColor" ref="363125112"/>
+						</object>
+					</object>
+					<object class="NSTextField" id="841479602">
+						<reference key="NSNextResponder" ref="148061301"/>
+						<int key="NSvFlags">268</int>
+						<string key="NSFrame">{{8, 39}, {83, 14}}</string>
+						<reference key="NSSuperview" ref="148061301"/>
+						<bool key="NSEnabled">YES</bool>
+						<object class="NSTextFieldCell" key="NSCell" id="93304674">
+							<int key="NSCellFlags">67239488</int>
+							<int key="NSCellFlags2">4326400</int>
+							<string key="NSContents">Add Child</string>
+							<reference key="NSSupport" ref="75607641"/>
+							<reference key="NSControlView" ref="841479602"/>
+							<reference key="NSBackgroundColor" ref="492759629"/>
+							<reference key="NSTextColor" ref="378390125"/>
+						</object>
+					</object>
+					<object class="NSTextField" id="1025033535">
+						<reference key="NSNextResponder" ref="148061301"/>
+						<int key="NSvFlags">268</int>
+						<string key="NSFrame">{{8, 20}, {83, 14}}</string>
+						<reference key="NSSuperview" ref="148061301"/>
+						<bool key="NSEnabled">YES</bool>
+						<object class="NSTextFieldCell" key="NSCell" id="340627346">
+							<int key="NSCellFlags">67239488</int>
+							<int key="NSCellFlags2">4326400</int>
+							<string key="NSContents">Remove</string>
+							<reference key="NSSupport" ref="75607641"/>
+							<reference key="NSControlView" ref="1025033535"/>
+							<reference key="NSBackgroundColor" ref="492759629"/>
+							<reference key="NSTextColor" ref="378390125"/>
+						</object>
+					</object>
+					<object class="NSTextField" id="934891252">
+						<reference key="NSNextResponder" ref="148061301"/>
+						<int key="NSvFlags">268</int>
+						<string key="NSFrame">{{78, 621}, {103, 14}}</string>
+						<reference key="NSSuperview" ref="148061301"/>
+						<bool key="NSEnabled">YES</bool>
+						<object class="NSTextFieldCell" key="NSCell" id="941111433">
+							<int key="NSCellFlags">67239488</int>
+							<int key="NSCellFlags2">4326400</int>
+							<string key="NSContents">Type Information</string>
+							<reference key="NSSupport" ref="75607641"/>
+							<reference key="NSControlView" ref="934891252"/>
+							<reference key="NSBackgroundColor" ref="492759629"/>
+							<reference key="NSTextColor" ref="378390125"/>
+						</object>
+					</object>
+					<object class="NSTextField" id="988079201">
+						<reference key="NSNextResponder" ref="148061301"/>
+						<int key="NSvFlags">268</int>
+						<string key="NSFrame">{{91, 238}, {77, 14}}</string>
+						<reference key="NSSuperview" ref="148061301"/>
+						<bool key="NSEnabled">YES</bool>
+						<object class="NSTextFieldCell" key="NSCell" id="493724135">
+							<int key="NSCellFlags">67239488</int>
+							<int key="NSCellFlags2">4326400</int>
+							<string key="NSContents">Notification</string>
+							<reference key="NSSupport" ref="75607641"/>
+							<reference key="NSControlView" ref="988079201"/>
+							<reference key="NSBackgroundColor" ref="492759629"/>
+							<reference key="NSTextColor" ref="378390125"/>
+						</object>
+					</object>
+					<object class="NSTextField" id="730601649">
+						<reference key="NSNextResponder" ref="148061301"/>
+						<int key="NSvFlags">268</int>
+						<string key="NSFrame">{{78, 136}, {124, 14}}</string>
+						<reference key="NSSuperview" ref="148061301"/>
+						<bool key="NSEnabled">YES</bool>
+						<object class="NSTextFieldCell" key="NSCell" id="341674719">
+							<int key="NSCellFlags">67239488</int>
+							<int key="NSCellFlags2">4326400</int>
+							<string key="NSContents">Override Information</string>
+							<reference key="NSSupport" ref="75607641"/>
+							<reference key="NSControlView" ref="730601649"/>
+							<reference key="NSBackgroundColor" ref="492759629"/>
+							<reference key="NSTextColor" ref="378390125"/>
+						</object>
+					</object>
+					<object class="NSButton" id="544542550">
+						<reference key="NSNextResponder" ref="148061301"/>
+						<int key="NSvFlags">268</int>
+						<string key="NSFrame">{{103, 641}, {98, 18}}</string>
+						<reference key="NSSuperview" ref="148061301"/>
+						<bool key="NSEnabled">YES</bool>
+						<object class="NSButtonCell" key="NSCell" id="427936988">
+							<int key="NSCellFlags">-2080244224</int>
+							<int key="NSCellFlags2">131072</int>
+							<string key="NSContents">Generate Root</string>
+							<object class="NSFont" key="NSSupport" id="26">
+								<string key="NSName">LucidaGrande</string>
+								<double key="NSSize">1.100000e+01</double>
+								<int key="NSfFlags">3100</int>
+							</object>
+							<reference key="NSControlView" ref="544542550"/>
+							<int key="NSButtonFlags">1211912703</int>
+							<int key="NSButtonFlags2">130</int>
+							<object class="NSCustomResource" key="NSNormalImage">
+								<string key="NSClassName">NSImage</string>
+								<string key="NSResourceName">NSSwitch</string>
+							</object>
+							<object class="NSButtonImageSource" key="NSAlternateImage">
+								<string key="NSImageName">NSSwitch</string>
+							</object>
+							<string key="NSAlternateContents"/>
+							<string key="NSKeyEquivalent"/>
+							<int key="NSPeriodicDelay">200</int>
+							<int key="NSPeriodicInterval">25</int>
+						</object>
+					</object>
+					<object class="NSScrollView" id="975221980">
+						<reference key="NSNextResponder" ref="148061301"/>
+						<int key="NSvFlags">268</int>
+						<object class="NSMutableArray" key="NSSubviews">
+							<bool key="EncodedWithXMLCoder">YES</bool>
+							<object class="NSClipView" id="213599629">
+								<reference key="NSNextResponder" ref="975221980"/>
+								<int key="NSvFlags">2304</int>
+								<object class="NSMutableArray" key="NSSubviews">
+									<bool key="EncodedWithXMLCoder">YES</bool>
+									<object class="NSTableView" id="184705836">
+										<reference key="NSNextResponder" ref="213599629"/>
+										<int key="NSvFlags">256</int>
+										<string key="NSFrameSize">{227, 84}</string>
+										<reference key="NSSuperview" ref="213599629"/>
+										<bool key="NSEnabled">YES</bool>
+										<object class="NSTableHeaderView" key="NSHeaderView" id="331472812">
+											<reference key="NSNextResponder" ref="16398937"/>
+											<int key="NSvFlags">256</int>
+											<string key="NSFrameSize">{227, 17}</string>
+											<reference key="NSSuperview" ref="16398937"/>
+											<reference key="NSTableView" ref="184705836"/>
+										</object>
+										<object class="_NSCornerView" key="NSCornerView" id="398710236">
+											<reference key="NSNextResponder" ref="975221980"/>
+											<int key="NSvFlags">256</int>
+											<string key="NSFrame">{{228, 0}, {16, 17}}</string>
+											<reference key="NSSuperview" ref="975221980"/>
+										</object>
+										<object class="NSMutableArray" key="NSTableColumns">
+											<bool key="EncodedWithXMLCoder">YES</bool>
+											<object class="NSTableColumn" id="607675685">
+												<string key="NSIdentifier">0</string>
+												<double key="NSWidth">7.300000e+01</double>
+												<double key="NSMinWidth">4.000000e+01</double>
+												<double key="NSMaxWidth">1.000000e+03</double>
+												<object class="NSTableHeaderCell" key="NSHeaderCell">
+													<int key="NSCellFlags">75628032</int>
+													<int key="NSCellFlags2">0</int>
+													<string key="NSContents">Type</string>
+													<reference key="NSSupport" ref="26"/>
+													<object class="NSColor" key="NSBackgroundColor" id="335076708">
+														<int key="NSColorSpace">3</int>
+														<bytes key="NSWhite">MC4zMzMzMzI5OQA</bytes>
+													</object>
+													<object class="NSColor" key="NSTextColor" id="143965671">
+														<int key="NSColorSpace">6</int>
+														<string key="NSCatalogName">System</string>
+														<string key="NSColorName">headerTextColor</string>
+														<reference key="NSColor" ref="692185638"/>
+													</object>
+												</object>
+												<object class="NSTextFieldCell" key="NSDataCell" id="1048414942">
+													<int key="NSCellFlags">337772096</int>
+													<int key="NSCellFlags2">264192</int>
+													<string key="NSContents">Text Cell</string>
+													<reference key="NSSupport" ref="22"/>
+													<reference key="NSControlView" ref="184705836"/>
+													<object class="NSColor" key="NSBackgroundColor" id="1064587807">
+														<int key="NSColorSpace">6</int>
+														<string key="NSCatalogName">System</string>
+														<string key="NSColorName">controlBackgroundColor</string>
+														<reference key="NSColor" ref="701463694"/>
+													</object>
+													<reference key="NSTextColor" ref="378390125"/>
+												</object>
+												<int key="NSResizingMask">3</int>
+												<bool key="NSIsResizeable">YES</bool>
+												<bool key="NSIsEditable">YES</bool>
+												<reference key="NSTableView" ref="184705836"/>
+											</object>
+											<object class="NSTableColumn" id="571901659">
+												<string key="NSIdentifier">1</string>
+												<double key="NSWidth">7.100000e+01</double>
+												<double key="NSMinWidth">4.000000e+01</double>
+												<double key="NSMaxWidth">1.000000e+03</double>
+												<object class="NSTableHeaderCell" key="NSHeaderCell">
+													<int key="NSCellFlags">75628032</int>
+													<int key="NSCellFlags2">0</int>
+													<string key="NSContents">Child Type</string>
+													<reference key="NSSupport" ref="26"/>
+													<reference key="NSBackgroundColor" ref="335076708"/>
+													<reference key="NSTextColor" ref="143965671"/>
+												</object>
+												<object class="NSTextFieldCell" key="NSDataCell" id="903371474">
+													<int key="NSCellFlags">337772096</int>
+													<int key="NSCellFlags2">264192</int>
+													<string key="NSContents">Text Cell</string>
+													<reference key="NSSupport" ref="22"/>
+													<reference key="NSControlView" ref="184705836"/>
+													<reference key="NSBackgroundColor" ref="1064587807"/>
+													<reference key="NSTextColor" ref="378390125"/>
+												</object>
+												<int key="NSResizingMask">3</int>
+												<bool key="NSIsResizeable">YES</bool>
+												<bool key="NSIsEditable">YES</bool>
+												<reference key="NSTableView" ref="184705836"/>
+											</object>
+											<object class="NSTableColumn" id="931955417">
+												<string key="NSIdentifier">2</string>
+												<double key="NSWidth">7.400000e+01</double>
+												<double key="NSMinWidth">1.000000e+01</double>
+												<double key="NSMaxWidth">3.402823e+38</double>
+												<object class="NSTableHeaderCell" key="NSHeaderCell">
+													<int key="NSCellFlags">75628032</int>
+													<int key="NSCellFlags2">0</int>
+													<string key="NSContents">Children Key</string>
+													<reference key="NSSupport" ref="26"/>
+													<object class="NSColor" key="NSBackgroundColor" id="334445875">
+														<int key="NSColorSpace">6</int>
+														<string key="NSCatalogName">System</string>
+														<string key="NSColorName">headerColor</string>
+														<reference key="NSColor" ref="440740257"/>
+													</object>
+													<reference key="NSTextColor" ref="143965671"/>
+												</object>
+												<object class="NSTextFieldCell" key="NSDataCell" id="256923828">
+													<int key="NSCellFlags">337772096</int>
+													<int key="NSCellFlags2">264192</int>
+													<string key="NSContents">Text Cell</string>
+													<reference key="NSSupport" ref="22"/>
+													<reference key="NSControlView" ref="184705836"/>
+													<reference key="NSBackgroundColor" ref="1064587807"/>
+													<reference key="NSTextColor" ref="378390125"/>
+												</object>
+												<int key="NSResizingMask">3</int>
+												<bool key="NSIsResizeable">YES</bool>
+												<bool key="NSIsEditable">YES</bool>
+												<reference key="NSTableView" ref="184705836"/>
+											</object>
+										</object>
+										<double key="NSIntercellSpacingWidth">3.000000e+00</double>
+										<double key="NSIntercellSpacingHeight">2.000000e+00</double>
+										<reference key="NSBackgroundColor" ref="440740257"/>
+										<object class="NSColor" key="NSGridColor" id="602240491">
+											<int key="NSColorSpace">6</int>
+											<string key="NSCatalogName">System</string>
+											<string key="NSColorName">gridColor</string>
+											<object class="NSColor" key="NSColor">
+												<int key="NSColorSpace">3</int>
+												<bytes key="NSWhite">MC41AA</bytes>
+											</object>
+										</object>
+										<double key="NSRowHeight">1.200000e+01</double>
+										<int key="NSTvFlags">-700448768</int>
+										<int key="NSColumnAutoresizingStyle">4</int>
+										<int key="NSDraggingSourceMaskForLocal">15</int>
+										<int key="NSDraggingSourceMaskForNonLocal">0</int>
+										<bool key="NSAllowsTypeSelect">YES</bool>
+									</object>
+								</object>
+								<string key="NSFrame">{{1, 17}, {227, 84}}</string>
+								<reference key="NSSuperview" ref="975221980"/>
+								<reference key="NSNextKeyView" ref="184705836"/>
+								<reference key="NSDocView" ref="184705836"/>
+								<reference key="NSBGColor" ref="1064587807"/>
+								<int key="NScvFlags">4</int>
+							</object>
+							<object class="NSScroller" id="1003246578">
+								<reference key="NSNextResponder" ref="975221980"/>
+								<int key="NSvFlags">256</int>
+								<string key="NSFrame">{{228, 17}, {15, 84}}</string>
+								<reference key="NSSuperview" ref="975221980"/>
+								<reference key="NSTarget" ref="975221980"/>
+								<string key="NSAction">_doScroller:</string>
+								<double key="NSCurValue">3.700000e+01</double>
+								<double key="NSPercent">1.947368e-01</double>
+							</object>
+							<object class="NSScroller" id="1073303088">
+								<reference key="NSNextResponder" ref="975221980"/>
+								<int key="NSvFlags">256</int>
+								<string key="NSFrame">{{1, 101}, {227, 15}}</string>
+								<reference key="NSSuperview" ref="975221980"/>
+								<int key="NSsFlags">1</int>
+								<reference key="NSTarget" ref="975221980"/>
+								<string key="NSAction">_doScroller:</string>
+								<double key="NSPercent">9.957806e-01</double>
+							</object>
+							<object class="NSClipView" id="16398937">
+								<reference key="NSNextResponder" ref="975221980"/>
+								<int key="NSvFlags">2304</int>
+								<object class="NSMutableArray" key="NSSubviews">
+									<bool key="EncodedWithXMLCoder">YES</bool>
+									<reference ref="331472812"/>
+								</object>
+								<string key="NSFrame">{{1, 0}, {227, 17}}</string>
+								<reference key="NSSuperview" ref="975221980"/>
+								<reference key="NSNextKeyView" ref="331472812"/>
+								<reference key="NSDocView" ref="331472812"/>
+								<reference key="NSBGColor" ref="1064587807"/>
+								<int key="NScvFlags">4</int>
+							</object>
+							<reference ref="398710236"/>
+						</object>
+						<string key="NSFrame">{{11, 499}, {244, 117}}</string>
+						<reference key="NSSuperview" ref="148061301"/>
+						<reference key="NSNextKeyView" ref="213599629"/>
+						<int key="NSsFlags">50</int>
+						<reference key="NSVScroller" ref="1003246578"/>
+						<reference key="NSHScroller" ref="1073303088"/>
+						<reference key="NSContentView" ref="213599629"/>
+						<reference key="NSHeaderClipView" ref="16398937"/>
+						<reference key="NSCornerView" ref="398710236"/>
+						<bytes key="NSScrollAmts">QSAAAEEgAABBYAAAQWAAAA</bytes>
+					</object>
+					<object class="NSScrollView" id="30781231">
+						<reference key="NSNextResponder" ref="148061301"/>
+						<int key="NSvFlags">268</int>
+						<object class="NSMutableArray" key="NSSubviews">
+							<bool key="EncodedWithXMLCoder">YES</bool>
+							<object class="NSClipView" id="1046073659">
+								<reference key="NSNextResponder" ref="30781231"/>
+								<int key="NSvFlags">2304</int>
+								<object class="NSMutableArray" key="NSSubviews">
+									<bool key="EncodedWithXMLCoder">YES</bool>
+									<object class="NSTableView" id="170369365">
+										<reference key="NSNextResponder" ref="1046073659"/>
+										<int key="NSvFlags">256</int>
+										<string key="NSFrameSize">{227, 84}</string>
+										<reference key="NSSuperview" ref="1046073659"/>
+										<bool key="NSEnabled">YES</bool>
+										<object class="NSTableHeaderView" key="NSHeaderView" id="452175770">
+											<reference key="NSNextResponder" ref="770228798"/>
+											<int key="NSvFlags">256</int>
+											<string key="NSFrameSize">{227, 17}</string>
+											<reference key="NSSuperview" ref="770228798"/>
+											<reference key="NSTableView" ref="170369365"/>
+										</object>
+										<object class="_NSCornerView" key="NSCornerView" id="633607368">
+											<reference key="NSNextResponder" ref="30781231"/>
+											<int key="NSvFlags">256</int>
+											<string key="NSFrame">{{228, 0}, {16, 17}}</string>
+											<reference key="NSSuperview" ref="30781231"/>
+										</object>
+										<object class="NSMutableArray" key="NSTableColumns">
+											<bool key="EncodedWithXMLCoder">YES</bool>
+											<object class="NSTableColumn" id="929638513">
+												<string key="NSIdentifier">0</string>
+												<double key="NSWidth">6.900000e+01</double>
+												<double key="NSMinWidth">4.000000e+01</double>
+												<double key="NSMaxWidth">1.000000e+03</double>
+												<object class="NSTableHeaderCell" key="NSHeaderCell">
+													<int key="NSCellFlags">75628032</int>
+													<int key="NSCellFlags2">0</int>
+													<string key="NSContents">Type</string>
+													<reference key="NSSupport" ref="26"/>
+													<object class="NSColor" key="NSBackgroundColor" id="1053132804">
+														<int key="NSColorSpace">3</int>
+														<bytes key="NSWhite">MC4zMzMzMzI5OQA</bytes>
+													</object>
+													<reference key="NSTextColor" ref="143965671"/>
+												</object>
+												<object class="NSTextFieldCell" key="NSDataCell" id="308070460">
+													<int key="NSCellFlags">337772096</int>
+													<int key="NSCellFlags2">264192</int>
+													<string key="NSContents">Text Cell</string>
+													<reference key="NSSupport" ref="22"/>
+													<reference key="NSControlView" ref="170369365"/>
+													<reference key="NSBackgroundColor" ref="1064587807"/>
+													<reference key="NSTextColor" ref="378390125"/>
+												</object>
+												<int key="NSResizingMask">3</int>
+												<bool key="NSIsResizeable">YES</bool>
+												<bool key="NSIsEditable">YES</bool>
+												<reference key="NSTableView" ref="170369365"/>
+											</object>
+											<object class="NSTableColumn" id="458070426">
+												<string key="NSIdentifier">1</string>
+												<double key="NSWidth">6.600000e+01</double>
+												<double key="NSMinWidth">4.000000e+01</double>
+												<double key="NSMaxWidth">1.000000e+03</double>
+												<object class="NSTableHeaderCell" key="NSHeaderCell">
+													<int key="NSCellFlags">75628032</int>
+													<int key="NSCellFlags2">0</int>
+													<string key="NSContents">Sort Key</string>
+													<reference key="NSSupport" ref="26"/>
+													<reference key="NSBackgroundColor" ref="1053132804"/>
+													<reference key="NSTextColor" ref="143965671"/>
+												</object>
+												<object class="NSTextFieldCell" key="NSDataCell" id="1060309917">
+													<int key="NSCellFlags">337772096</int>
+													<int key="NSCellFlags2">264192</int>
+													<string key="NSContents">Text Cell</string>
+													<reference key="NSSupport" ref="22"/>
+													<reference key="NSControlView" ref="170369365"/>
+													<reference key="NSBackgroundColor" ref="1064587807"/>
+													<reference key="NSTextColor" ref="378390125"/>
+												</object>
+												<int key="NSResizingMask">3</int>
+												<bool key="NSIsResizeable">YES</bool>
+												<bool key="NSIsEditable">YES</bool>
+												<reference key="NSTableView" ref="170369365"/>
+											</object>
+											<object class="NSTableColumn" id="599415714">
+												<string key="NSIdentifier">2</string>
+												<double key="NSWidth">8.300000e+01</double>
+												<double key="NSMinWidth">1.000000e+01</double>
+												<double key="NSMaxWidth">3.402823e+38</double>
+												<object class="NSTableHeaderCell" key="NSHeaderCell">
+													<int key="NSCellFlags">75628032</int>
+													<int key="NSCellFlags2">0</int>
+													<string key="NSContents">Sort Predicate</string>
+													<reference key="NSSupport" ref="26"/>
+													<reference key="NSBackgroundColor" ref="334445875"/>
+													<reference key="NSTextColor" ref="143965671"/>
+												</object>
+												<object class="NSTextFieldCell" key="NSDataCell" id="933860589">
+													<int key="NSCellFlags">337772096</int>
+													<int key="NSCellFlags2">264192</int>
+													<string key="NSContents">Text Cell</string>
+													<reference key="NSSupport" ref="22"/>
+													<reference key="NSControlView" ref="170369365"/>
+													<reference key="NSBackgroundColor" ref="1064587807"/>
+													<reference key="NSTextColor" ref="378390125"/>
+												</object>
+												<int key="NSResizingMask">3</int>
+												<bool key="NSIsResizeable">YES</bool>
+												<bool key="NSIsEditable">YES</bool>
+												<reference key="NSTableView" ref="170369365"/>
+											</object>
+										</object>
+										<double key="NSIntercellSpacingWidth">3.000000e+00</double>
+										<double key="NSIntercellSpacingHeight">2.000000e+00</double>
+										<reference key="NSBackgroundColor" ref="440740257"/>
+										<reference key="NSGridColor" ref="602240491"/>
+										<double key="NSRowHeight">1.200000e+01</double>
+										<int key="NSTvFlags">-700448768</int>
+										<int key="NSColumnAutoresizingStyle">4</int>
+										<int key="NSDraggingSourceMaskForLocal">15</int>
+										<int key="NSDraggingSourceMaskForNonLocal">0</int>
+										<bool key="NSAllowsTypeSelect">YES</bool>
+									</object>
+								</object>
+								<string key="NSFrame">{{1, 17}, {227, 84}}</string>
+								<reference key="NSSuperview" ref="30781231"/>
+								<reference key="NSNextKeyView" ref="170369365"/>
+								<reference key="NSDocView" ref="170369365"/>
+								<reference key="NSBGColor" ref="1064587807"/>
+								<int key="NScvFlags">4</int>
+							</object>
+							<object class="NSScroller" id="659680838">
+								<reference key="NSNextResponder" ref="30781231"/>
+								<int key="NSvFlags">256</int>
+								<string key="NSFrame">{{228, 17}, {15, 84}}</string>
+								<reference key="NSSuperview" ref="30781231"/>
+								<reference key="NSTarget" ref="30781231"/>
+								<string key="NSAction">_doScroller:</string>
+								<double key="NSCurValue">3.700000e+01</double>
+								<double key="NSPercent">1.947368e-01</double>
+							</object>
+							<object class="NSScroller" id="417904569">
+								<reference key="NSNextResponder" ref="30781231"/>
+								<int key="NSvFlags">256</int>
+								<string key="NSFrame">{{1, 101}, {227, 15}}</string>
+								<reference key="NSSuperview" ref="30781231"/>
+								<int key="NSsFlags">1</int>
+								<reference key="NSTarget" ref="30781231"/>
+								<string key="NSAction">_doScroller:</string>
+								<double key="NSPercent">9.956141e-01</double>
+							</object>
+							<object class="NSClipView" id="770228798">
+								<reference key="NSNextResponder" ref="30781231"/>
+								<int key="NSvFlags">2304</int>
+								<object class="NSMutableArray" key="NSSubviews">
+									<bool key="EncodedWithXMLCoder">YES</bool>
+									<reference ref="452175770"/>
+								</object>
+								<string key="NSFrame">{{1, 0}, {227, 17}}</string>
+								<reference key="NSSuperview" ref="30781231"/>
+								<reference key="NSNextKeyView" ref="452175770"/>
+								<reference key="NSDocView" ref="452175770"/>
+								<reference key="NSBGColor" ref="1064587807"/>
+								<int key="NScvFlags">4</int>
+							</object>
+							<reference ref="633607368"/>
+						</object>
+						<string key="NSFrame">{{11, 260}, {244, 117}}</string>
+						<reference key="NSSuperview" ref="148061301"/>
+						<reference key="NSNextKeyView" ref="1046073659"/>
+						<int key="NSsFlags">50</int>
+						<reference key="NSVScroller" ref="659680838"/>
+						<reference key="NSHScroller" ref="417904569"/>
+						<reference key="NSContentView" ref="1046073659"/>
+						<reference key="NSHeaderClipView" ref="770228798"/>
+						<reference key="NSCornerView" ref="633607368"/>
+						<bytes key="NSScrollAmts">QSAAAEEgAABBYAAAQWAAAA</bytes>
+					</object>
+					<object class="NSScrollView" id="924255883">
+						<reference key="NSNextResponder" ref="148061301"/>
+						<int key="NSvFlags">268</int>
+						<object class="NSMutableArray" key="NSSubviews">
+							<bool key="EncodedWithXMLCoder">YES</bool>
+							<object class="NSClipView" id="427418615">
+								<reference key="NSNextResponder" ref="924255883"/>
+								<int key="NSvFlags">2304</int>
+								<object class="NSMutableArray" key="NSSubviews">
+									<bool key="EncodedWithXMLCoder">YES</bool>
+									<object class="NSTableView" id="785403312">
+										<reference key="NSNextResponder" ref="427418615"/>
+										<int key="NSvFlags">256</int>
+										<string key="NSFrameSize">{227, 84}</string>
+										<reference key="NSSuperview" ref="427418615"/>
+										<bool key="NSEnabled">YES</bool>
+										<object class="NSTableHeaderView" key="NSHeaderView" id="26052107">
+											<reference key="NSNextResponder" ref="369194281"/>
+											<int key="NSvFlags">256</int>
+											<string key="NSFrameSize">{227, 17}</string>
+											<reference key="NSSuperview" ref="369194281"/>
+											<reference key="NSTableView" ref="785403312"/>
+										</object>
+										<object class="_NSCornerView" key="NSCornerView" id="256204037">
+											<reference key="NSNextResponder" ref="924255883"/>
+											<int key="NSvFlags">256</int>
+											<string key="NSFrame">{{228, 0}, {16, 17}}</string>
+											<reference key="NSSuperview" ref="924255883"/>
+										</object>
+										<object class="NSMutableArray" key="NSTableColumns">
+											<bool key="EncodedWithXMLCoder">YES</bool>
+											<object class="NSTableColumn" id="902930739">
+												<string key="NSIdentifier">0</string>
+												<double key="NSWidth">7.000000e+01</double>
+												<double key="NSMinWidth">4.000000e+01</double>
+												<double key="NSMaxWidth">1.000000e+03</double>
+												<object class="NSTableHeaderCell" key="NSHeaderCell">
+													<int key="NSCellFlags">75628032</int>
+													<int key="NSCellFlags2">0</int>
+													<string key="NSContents">Type</string>
+													<reference key="NSSupport" ref="26"/>
+													<object class="NSColor" key="NSBackgroundColor" id="341753994">
+														<int key="NSColorSpace">3</int>
+														<bytes key="NSWhite">MC4zMzMzMzI5OQA</bytes>
+													</object>
+													<reference key="NSTextColor" ref="143965671"/>
+												</object>
+												<object class="NSTextFieldCell" key="NSDataCell" id="950249531">
+													<int key="NSCellFlags">337772096</int>
+													<int key="NSCellFlags2">264192</int>
+													<string key="NSContents">Text Cell</string>
+													<reference key="NSSupport" ref="22"/>
+													<reference key="NSControlView" ref="785403312"/>
+													<reference key="NSBackgroundColor" ref="1064587807"/>
+													<reference key="NSTextColor" ref="378390125"/>
+												</object>
+												<int key="NSResizingMask">3</int>
+												<bool key="NSIsResizeable">YES</bool>
+												<bool key="NSIsEditable">YES</bool>
+												<reference key="NSTableView" ref="785403312"/>
+											</object>
+											<object class="NSTableColumn" id="977919695">
+												<string key="NSIdentifier">1</string>
+												<double key="NSWidth">1.510000e+02</double>
+												<double key="NSMinWidth">4.000000e+01</double>
+												<double key="NSMaxWidth">1.000000e+03</double>
+												<object class="NSTableHeaderCell" key="NSHeaderCell">
+													<int key="NSCellFlags">75628032</int>
+													<int key="NSCellFlags2">0</int>
+													<string key="NSContents">Initform</string>
+													<reference key="NSSupport" ref="26"/>
+													<reference key="NSBackgroundColor" ref="341753994"/>
+													<reference key="NSTextColor" ref="143965671"/>
+												</object>
+												<object class="NSTextFieldCell" key="NSDataCell" id="287704059">
+													<int key="NSCellFlags">337772096</int>
+													<int key="NSCellFlags2">264192</int>
+													<string key="NSContents">Text Cell</string>
+													<reference key="NSSupport" ref="22"/>
+													<reference key="NSControlView" ref="785403312"/>
+													<reference key="NSBackgroundColor" ref="1064587807"/>
+													<reference key="NSTextColor" ref="378390125"/>
+												</object>
+												<int key="NSResizingMask">3</int>
+												<bool key="NSIsResizeable">YES</bool>
+												<bool key="NSIsEditable">YES</bool>
+												<reference key="NSTableView" ref="785403312"/>
+											</object>
+										</object>
+										<double key="NSIntercellSpacingWidth">3.000000e+00</double>
+										<double key="NSIntercellSpacingHeight">2.000000e+00</double>
+										<reference key="NSBackgroundColor" ref="440740257"/>
+										<reference key="NSGridColor" ref="602240491"/>
+										<double key="NSRowHeight">1.200000e+01</double>
+										<int key="NSTvFlags">-700448768</int>
+										<int key="NSColumnAutoresizingStyle">4</int>
+										<int key="NSDraggingSourceMaskForLocal">15</int>
+										<int key="NSDraggingSourceMaskForNonLocal">0</int>
+										<bool key="NSAllowsTypeSelect">YES</bool>
+									</object>
+								</object>
+								<string key="NSFrame">{{1, 17}, {227, 84}}</string>
+								<reference key="NSSuperview" ref="924255883"/>
+								<reference key="NSNextKeyView" ref="785403312"/>
+								<reference key="NSDocView" ref="785403312"/>
+								<reference key="NSBGColor" ref="1064587807"/>
+								<int key="NScvFlags">4</int>
+							</object>
+							<object class="NSScroller" id="243232151">
+								<reference key="NSNextResponder" ref="924255883"/>
+								<int key="NSvFlags">256</int>
+								<string key="NSFrame">{{228, 17}, {15, 84}}</string>
+								<reference key="NSSuperview" ref="924255883"/>
+								<reference key="NSTarget" ref="924255883"/>
+								<string key="NSAction">_doScroller:</string>
+								<double key="NSCurValue">3.700000e+01</double>
+								<double key="NSPercent">1.947368e-01</double>
+							</object>
+							<object class="NSScroller" id="239648738">
+								<reference key="NSNextResponder" ref="924255883"/>
+								<int key="NSvFlags">256</int>
+								<string key="NSFrame">{{1, 101}, {227, 15}}</string>
+								<reference key="NSSuperview" ref="924255883"/>
+								<int key="NSsFlags">1</int>
+								<reference key="NSTarget" ref="924255883"/>
+								<string key="NSAction">_doScroller:</string>
+								<double key="NSPercent">9.957806e-01</double>
+							</object>
+							<object class="NSClipView" id="369194281">
+								<reference key="NSNextResponder" ref="924255883"/>
+								<int key="NSvFlags">2304</int>
+								<object class="NSMutableArray" key="NSSubviews">
+									<bool key="EncodedWithXMLCoder">YES</bool>
+									<reference ref="26052107"/>
+								</object>
+								<string key="NSFrame">{{1, 0}, {227, 17}}</string>
+								<reference key="NSSuperview" ref="924255883"/>
+								<reference key="NSNextKeyView" ref="26052107"/>
+								<reference key="NSDocView" ref="26052107"/>
+								<reference key="NSBGColor" ref="1064587807"/>
+								<int key="NScvFlags">4</int>
+							</object>
+							<reference ref="256204037"/>
+						</object>
+						<string key="NSFrame">{{11, 380}, {244, 117}}</string>
+						<reference key="NSSuperview" ref="148061301"/>
+						<reference key="NSNextKeyView" ref="427418615"/>
+						<int key="NSsFlags">50</int>
+						<reference key="NSVScroller" ref="243232151"/>
+						<reference key="NSHScroller" ref="239648738"/>
+						<reference key="NSContentView" ref="427418615"/>
+						<reference key="NSHeaderClipView" ref="369194281"/>
+						<reference key="NSCornerView" ref="256204037"/>
+						<bytes key="NSScrollAmts">QSAAAEEgAABBYAAAQWAAAA</bytes>
+					</object>
+				</object>
+				<string key="NSFrameSize">{272, 686}</string>
+				<reference key="NSSuperview"/>
+				<string key="NSClassName">NSView</string>
+				<string key="NSExtension">NSResponder</string>
+			</object>
+		</object>
+		<object class="IBObjectContainer" key="IBDocument.Objects">
+			<object class="NSMutableArray" key="connectionRecords">
+				<bool key="EncodedWithXMLCoder">YES</bool>
+				<object class="IBConnectionRecord">
+					<object class="IBOutletConnection" key="connection">
+						<string key="label">inspectorView</string>
+						<reference key="source" ref="893560672"/>
+						<reference key="destination" ref="148061301"/>
+					</object>
+					<int key="connectionID">36</int>
+				</object>
+				<object class="IBConnectionRecord">
+					<object class="IBBindingConnection" key="connection">
+						<string key="label">value: inspectedObjectsController.selection.rootType</string>
+						<reference key="source" ref="767324328"/>
+						<reference key="destination" ref="893560672"/>
+						<object class="NSNibBindingConnector" key="connector">
+							<reference key="NSSource" ref="767324328"/>
+							<reference key="NSDestination" ref="893560672"/>
+							<string key="NSLabel">value: inspectedObjectsController.selection.rootType</string>
+							<string key="NSBinding">value</string>
+							<string key="NSKeyPath">inspectedObjectsController.selection.rootType</string>
+							<int key="NSNibBindingConnectorVersion">2</int>
+						</object>
+					</object>
+					<int key="connectionID">124</int>
+				</object>
+				<object class="IBConnectionRecord">
+					<object class="IBBindingConnection" key="connection">
+						<string key="label">value: inspectedObjectsController.selection.genRoot</string>
+						<reference key="source" ref="544542550"/>
+						<reference key="destination" ref="893560672"/>
+						<object class="NSNibBindingConnector" key="connector">
+							<reference key="NSSource" ref="544542550"/>
+							<reference key="NSDestination" ref="893560672"/>
+							<string key="NSLabel">value: inspectedObjectsController.selection.genRoot</string>
+							<string key="NSBinding">value</string>
+							<string key="NSKeyPath">inspectedObjectsController.selection.genRoot</string>
+							<object class="NSDictionary" key="NSOptions">
+								<string key="NS.key.0">NSConditionallySetsEnabled</string>
+								<boolean value="NO" key="NS.object.0"/>
+							</object>
+							<int key="NSNibBindingConnectorVersion">2</int>
+						</object>
+					</object>
+					<int key="connectionID">131</int>
+				</object>
+				<object class="IBConnectionRecord">
+					<object class="IBOutletConnection" key="connection">
+						<string key="label">dataSource</string>
+						<reference key="source" ref="184705836"/>
+						<reference key="destination" ref="893560672"/>
+					</object>
+					<int key="connectionID">143</int>
+				</object>
+				<object class="IBConnectionRecord">
+					<object class="IBOutletConnection" key="connection">
+						<string key="label">delegate</string>
+						<reference key="source" ref="184705836"/>
+						<reference key="destination" ref="893560672"/>
+					</object>
+					<int key="connectionID">144</int>
+				</object>
+				<object class="IBConnectionRecord">
+					<object class="IBBindingConnection" key="connection">
+						<string key="label">value: inspectedObjectsController.selection.selectFunc</string>
+						<reference key="source" ref="318678771"/>
+						<reference key="destination" ref="893560672"/>
+						<object class="NSNibBindingConnector" key="connector">
+							<reference key="NSSource" ref="318678771"/>
+							<reference key="NSDestination" ref="893560672"/>
+							<string key="NSLabel">value: inspectedObjectsController.selection.selectFunc</string>
+							<string key="NSBinding">value</string>
+							<string key="NSKeyPath">inspectedObjectsController.selection.selectFunc</string>
+							<int key="NSNibBindingConnectorVersion">2</int>
+						</object>
+					</object>
+					<int key="connectionID">217</int>
+				</object>
+				<object class="IBConnectionRecord">
+					<object class="IBBindingConnection" key="connection">
+						<string key="label">value: inspectedObjectsController.selection.editedFunc</string>
+						<reference key="source" ref="187508141"/>
+						<reference key="destination" ref="893560672"/>
+						<object class="NSNibBindingConnector" key="connector">
+							<reference key="NSSource" ref="187508141"/>
+							<reference key="NSDestination" ref="893560672"/>
+							<string key="NSLabel">value: inspectedObjectsController.selection.editedFunc</string>
+							<string key="NSBinding">value</string>
+							<string key="NSKeyPath">inspectedObjectsController.selection.editedFunc</string>
+							<int key="NSNibBindingConnectorVersion">2</int>
+						</object>
+					</object>
+					<int key="connectionID">219</int>
+				</object>
+				<object class="IBConnectionRecord">
+					<object class="IBBindingConnection" key="connection">
+						<string key="label">value: inspectedObjectsController.selection.childrenFunc</string>
+						<reference key="source" ref="705814818"/>
+						<reference key="destination" ref="893560672"/>
+						<object class="NSNibBindingConnector" key="connector">
+							<reference key="NSSource" ref="705814818"/>
+							<reference key="NSDestination" ref="893560672"/>
+							<string key="NSLabel">value: inspectedObjectsController.selection.childrenFunc</string>
+							<string key="NSBinding">value</string>
+							<string key="NSKeyPath">inspectedObjectsController.selection.childrenFunc</string>
+							<int key="NSNibBindingConnectorVersion">2</int>
+						</object>
+					</object>
+					<int key="connectionID">221</int>
+				</object>
+				<object class="IBConnectionRecord">
+					<object class="IBBindingConnection" key="connection">
+						<string key="label">value: inspectedObjectsController.selection.countFunc</string>
+						<reference key="source" ref="770669533"/>
+						<reference key="destination" ref="893560672"/>
+						<object class="NSNibBindingConnector" key="connector">
+							<reference key="NSSource" ref="770669533"/>
+							<reference key="NSDestination" ref="893560672"/>
+							<string key="NSLabel">value: inspectedObjectsController.selection.countFunc</string>
+							<string key="NSBinding">value</string>
+							<string key="NSKeyPath">inspectedObjectsController.selection.countFunc</string>
+							<int key="NSNibBindingConnectorVersion">2</int>
+						</object>
+					</object>
+					<int key="connectionID">223</int>
+				</object>
+				<object class="IBConnectionRecord">
+					<object class="IBBindingConnection" key="connection">
+						<string key="label">value: inspectedObjectsController.selection.readerFunc</string>
+						<reference key="source" ref="7062143"/>
+						<reference key="destination" ref="893560672"/>
+						<object class="NSNibBindingConnector" key="connector">
+							<reference key="NSSource" ref="7062143"/>
+							<reference key="NSDestination" ref="893560672"/>
+							<string key="NSLabel">value: inspectedObjectsController.selection.readerFunc</string>
+							<string key="NSBinding">value</string>
+							<string key="NSKeyPath">inspectedObjectsController.selection.readerFunc</string>
+							<int key="NSNibBindingConnectorVersion">2</int>
+						</object>
+					</object>
+					<int key="connectionID">225</int>
+				</object>
+				<object class="IBConnectionRecord">
+					<object class="IBBindingConnection" key="connection">
+						<string key="label">value: inspectedObjectsController.selection.writerFunc</string>
+						<reference key="source" ref="431874124"/>
+						<reference key="destination" ref="893560672"/>
+						<object class="NSNibBindingConnector" key="connector">
+							<reference key="NSSource" ref="431874124"/>
+							<reference key="NSDestination" ref="893560672"/>
+							<string key="NSLabel">value: inspectedObjectsController.selection.writerFunc</string>
+							<string key="NSBinding">value</string>
+							<string key="NSKeyPath">inspectedObjectsController.selection.writerFunc</string>
+							<int key="NSNibBindingConnectorVersion">2</int>
+						</object>
+					</object>
+					<int key="connectionID">227</int>
+				</object>
+				<object class="IBConnectionRecord">
+					<object class="IBBindingConnection" key="connection">
+						<string key="label">value: inspectedObjectsController.selection.addChildFunc</string>
+						<reference key="source" ref="57441347"/>
+						<reference key="destination" ref="893560672"/>
+						<object class="NSNibBindingConnector" key="connector">
+							<reference key="NSSource" ref="57441347"/>
+							<reference key="NSDestination" ref="893560672"/>
+							<string key="NSLabel">value: inspectedObjectsController.selection.addChildFunc</string>
+							<string key="NSBinding">value</string>
+							<string key="NSKeyPath">inspectedObjectsController.selection.addChildFunc</string>
+							<int key="NSNibBindingConnectorVersion">2</int>
+						</object>
+					</object>
+					<int key="connectionID">231</int>
+				</object>
+				<object class="IBConnectionRecord">
+					<object class="IBBindingConnection" key="connection">
+						<string key="label">value: inspectedObjectsController.selection.addedFunc</string>
+						<reference key="source" ref="562507321"/>
+						<reference key="destination" ref="893560672"/>
+						<object class="NSNibBindingConnector" key="connector">
+							<reference key="NSSource" ref="562507321"/>
+							<reference key="NSDestination" ref="893560672"/>
+							<string key="NSLabel">value: inspectedObjectsController.selection.addedFunc</string>
+							<string key="NSBinding">value</string>
+							<string key="NSKeyPath">inspectedObjectsController.selection.addedFunc</string>
+							<int key="NSNibBindingConnectorVersion">2</int>
+						</object>
+					</object>
+					<int key="connectionID">239</int>
+				</object>
+				<object class="IBConnectionRecord">
+					<object class="IBOutletConnection" key="connection">
+						<string key="label">dataSource</string>
+						<reference key="source" ref="785403312"/>
+						<reference key="destination" ref="893560672"/>
+					</object>
+					<int key="connectionID">240</int>
+				</object>
+				<object class="IBConnectionRecord">
+					<object class="IBOutletConnection" key="connection">
+						<string key="label">delegate</string>
+						<reference key="source" ref="785403312"/>
+						<reference key="destination" ref="893560672"/>
+					</object>
+					<int key="connectionID">241</int>
+				</object>
+				<object class="IBConnectionRecord">
+					<object class="IBOutletConnection" key="connection">
+						<string key="label">delegate</string>
+						<reference key="source" ref="170369365"/>
+						<reference key="destination" ref="893560672"/>
+					</object>
+					<int key="connectionID">242</int>
+				</object>
+				<object class="IBConnectionRecord">
+					<object class="IBOutletConnection" key="connection">
+						<string key="label">dataSource</string>
+						<reference key="source" ref="170369365"/>
+						<reference key="destination" ref="893560672"/>
+					</object>
+					<int key="connectionID">243</int>
+				</object>
+				<object class="IBConnectionRecord">
+					<object class="IBOutletConnection" key="connection">
+						<string key="label">initformTable</string>
+						<reference key="source" ref="893560672"/>
+						<reference key="destination" ref="785403312"/>
+					</object>
+					<int key="connectionID">244</int>
+				</object>
+				<object class="IBConnectionRecord">
+					<object class="IBOutletConnection" key="connection">
+						<string key="label">sortTable</string>
+						<reference key="source" ref="893560672"/>
+						<reference key="destination" ref="170369365"/>
+					</object>
+					<int key="connectionID">245</int>
+				</object>
+				<object class="IBConnectionRecord">
+					<object class="IBOutletConnection" key="connection">
+						<string key="label">typeTable</string>
+						<reference key="source" ref="893560672"/>
+						<reference key="destination" ref="184705836"/>
+					</object>
+					<int key="connectionID">246</int>
+				</object>
+				<object class="IBConnectionRecord">
+					<object class="IBBindingConnection" key="connection">
+						<string key="label">value: inspectedObjectsController.selection.deleteFunc</string>
+						<reference key="source" ref="1039472622"/>
+						<reference key="destination" ref="893560672"/>
+						<object class="NSNibBindingConnector" key="connector">
+							<reference key="NSSource" ref="1039472622"/>
+							<reference key="NSDestination" ref="893560672"/>
+							<string key="NSLabel">value: inspectedObjectsController.selection.deleteFunc</string>
+							<string key="NSBinding">value</string>
+							<string key="NSKeyPath">inspectedObjectsController.selection.deleteFunc</string>
+							<int key="NSNibBindingConnectorVersion">2</int>
+						</object>
+					</object>
+					<int key="connectionID">247</int>
+				</object>
+				<object class="IBConnectionRecord">
+					<object class="IBBindingConnection" key="connection">
+						<string key="label">value: inspectedObjectsController.selection.removedFunc</string>
+						<reference key="source" ref="1023286907"/>
+						<reference key="destination" ref="893560672"/>
+						<object class="NSNibBindingConnector" key="connector">
+							<reference key="NSSource" ref="1023286907"/>
+							<reference key="NSDestination" ref="893560672"/>
+							<string key="NSLabel">value: inspectedObjectsController.selection.removedFunc</string>
+							<string key="NSBinding">value</string>
+							<string key="NSKeyPath">inspectedObjectsController.selection.removedFunc</string>
+							<int key="NSNibBindingConnectorVersion">2</int>
+						</object>
+					</object>
+					<int key="connectionID">254</int>
+				</object>
+			</object>
+			<object class="IBMutableOrderedSet" key="objectRecords">
+				<object class="NSArray" key="orderedObjects">
+					<bool key="EncodedWithXMLCoder">YES</bool>
+					<object class="IBObjectRecord">
+						<int key="objectID">0</int>
+						<object class="NSArray" key="object" id="1054652676">
+							<bool key="EncodedWithXMLCoder">YES</bool>
+						</object>
+						<reference key="children" ref="1015158983"/>
+						<nil key="parent"/>
+					</object>
+					<object class="IBObjectRecord">
+						<int key="objectID">-2</int>
+						<reference key="object" ref="893560672"/>
+						<reference key="parent" ref="1054652676"/>
+						<string type="base64-UTF8" key="objectName">RmlsZSdzIE93bmVyA</string>
+					</object>
+					<object class="IBObjectRecord">
+						<int key="objectID">-1</int>
+						<reference key="object" ref="904349417"/>
+						<reference key="parent" ref="1054652676"/>
+						<string key="objectName">First Responder</string>
+					</object>
+					<object class="IBObjectRecord">
+						<int key="objectID">-3</int>
+						<reference key="object" ref="510210961"/>
+						<reference key="parent" ref="1054652676"/>
+						<string key="objectName">Application</string>
+					</object>
+					<object class="IBObjectRecord">
+						<int key="objectID">21</int>
+						<reference key="object" ref="148061301"/>
+						<object class="NSMutableArray" key="children">
+							<bool key="EncodedWithXMLCoder">YES</bool>
+							<reference ref="771170495"/>
+							<reference ref="767324328"/>
+							<reference ref="318678771"/>
+							<reference ref="544542550"/>
+							<reference ref="934891252"/>
+							<reference ref="975221980"/>
+							<reference ref="924255883"/>
+							<reference ref="30781231"/>
+							<reference ref="988079201"/>
+							<reference ref="187508141"/>
+							<reference ref="105666546"/>
+							<reference ref="562507321"/>
+							<reference ref="741831275"/>
+							<reference ref="705814818"/>
+							<reference ref="42828080"/>
+							<reference ref="770669533"/>
+							<reference ref="139589133"/>
+							<reference ref="7062143"/>
+							<reference ref="637960900"/>
+							<reference ref="431874124"/>
+							<reference ref="472784790"/>
+							<reference ref="57441347"/>
+							<reference ref="1039472622"/>
+							<reference ref="841479602"/>
+							<reference ref="1025033535"/>
+							<reference ref="730601649"/>
+							<reference ref="1072792659"/>
+							<reference ref="1023286907"/>
+							<reference ref="407866252"/>
+						</object>
+						<reference key="parent" ref="1054652676"/>
+						<string key="objectName">Inspector View</string>
+					</object>
+					<object class="IBObjectRecord">
+						<int key="objectID">52</int>
+						<reference key="object" ref="767324328"/>
+						<object class="NSMutableArray" key="children">
+							<bool key="EncodedWithXMLCoder">YES</bool>
+							<reference ref="361495836"/>
+						</object>
+						<reference key="parent" ref="148061301"/>
+					</object>
+					<object class="IBObjectRecord">
+						<int key="objectID">62</int>
+						<reference key="object" ref="771170495"/>
+						<object class="NSMutableArray" key="children">
+							<bool key="EncodedWithXMLCoder">YES</bool>
+							<reference ref="272507628"/>
+						</object>
+						<reference key="parent" ref="148061301"/>
+					</object>
+					<object class="IBObjectRecord">
+						<int key="objectID">66</int>
+						<reference key="object" ref="272507628"/>
+						<reference key="parent" ref="771170495"/>
+					</object>
+					<object class="IBObjectRecord">
+						<int key="objectID">82</int>
+						<reference key="object" ref="361495836"/>
+						<reference key="parent" ref="767324328"/>
+					</object>
+					<object class="IBObjectRecord">
+						<int key="objectID">125</int>
+						<reference key="object" ref="544542550"/>
+						<object class="NSMutableArray" key="children">
+							<bool key="EncodedWithXMLCoder">YES</bool>
+							<reference ref="427936988"/>
+						</object>
+						<reference key="parent" ref="148061301"/>
+					</object>
+					<object class="IBObjectRecord">
+						<int key="objectID">126</int>
+						<reference key="object" ref="427936988"/>
+						<reference key="parent" ref="544542550"/>
+					</object>
+					<object class="IBObjectRecord">
+						<int key="objectID">127</int>
+						<reference key="object" ref="934891252"/>
+						<object class="NSMutableArray" key="children">
+							<bool key="EncodedWithXMLCoder">YES</bool>
+							<reference ref="941111433"/>
+						</object>
+						<reference key="parent" ref="148061301"/>
+					</object>
+					<object class="IBObjectRecord">
+						<int key="objectID">128</int>
+						<reference key="object" ref="941111433"/>
+						<reference key="parent" ref="934891252"/>
+					</object>
+					<object class="IBObjectRecord">
+						<int key="objectID">132</int>
+						<reference key="object" ref="975221980"/>
+						<object class="NSMutableArray" key="children">
+							<bool key="EncodedWithXMLCoder">YES</bool>
+							<reference ref="1003246578"/>
+							<reference ref="1073303088"/>
+							<reference ref="184705836"/>
+							<reference ref="331472812"/>
+						</object>
+						<reference key="parent" ref="148061301"/>
+					</object>
+					<object class="IBObjectRecord">
+						<int key="objectID">133</int>
+						<reference key="object" ref="1003246578"/>
+						<reference key="parent" ref="975221980"/>
+					</object>
+					<object class="IBObjectRecord">
+						<int key="objectID">134</int>
+						<reference key="object" ref="1073303088"/>
+						<reference key="parent" ref="975221980"/>
+					</object>
+					<object class="IBObjectRecord">
+						<int key="objectID">135</int>
+						<reference key="object" ref="184705836"/>
+						<object class="NSMutableArray" key="children">
+							<bool key="EncodedWithXMLCoder">YES</bool>
+							<reference ref="607675685"/>
+							<reference ref="571901659"/>
+							<reference ref="931955417"/>
+						</object>
+						<reference key="parent" ref="975221980"/>
+					</object>
+					<object class="IBObjectRecord">
+						<int key="objectID">136</int>
+						<reference key="object" ref="331472812"/>
+						<reference key="parent" ref="975221980"/>
+					</object>
+					<object class="IBObjectRecord">
+						<int key="objectID">137</int>
+						<reference key="object" ref="607675685"/>
+						<object class="NSMutableArray" key="children">
+							<bool key="EncodedWithXMLCoder">YES</bool>
+							<reference ref="1048414942"/>
+						</object>
+						<reference key="parent" ref="184705836"/>
+					</object>
+					<object class="IBObjectRecord">
+						<int key="objectID">138</int>
+						<reference key="object" ref="571901659"/>
+						<object class="NSMutableArray" key="children">
+							<bool key="EncodedWithXMLCoder">YES</bool>
+							<reference ref="903371474"/>
+						</object>
+						<reference key="parent" ref="184705836"/>
+					</object>
+					<object class="IBObjectRecord">
+						<int key="objectID">139</int>
+						<reference key="object" ref="903371474"/>
+						<reference key="parent" ref="571901659"/>
+					</object>
+					<object class="IBObjectRecord">
+						<int key="objectID">140</int>
+						<reference key="object" ref="1048414942"/>
+						<reference key="parent" ref="607675685"/>
+					</object>
+					<object class="IBObjectRecord">
+						<int key="objectID">141</int>
+						<reference key="object" ref="931955417"/>
+						<object class="NSMutableArray" key="children">
+							<bool key="EncodedWithXMLCoder">YES</bool>
+							<reference ref="256923828"/>
+						</object>
+						<reference key="parent" ref="184705836"/>
+					</object>
+					<object class="IBObjectRecord">
+						<int key="objectID">142</int>
+						<reference key="object" ref="256923828"/>
+						<reference key="parent" ref="931955417"/>
+					</object>
+					<object class="IBObjectRecord">
+						<int key="objectID">145</int>
+						<reference key="object" ref="924255883"/>
+						<object class="NSMutableArray" key="children">
+							<bool key="EncodedWithXMLCoder">YES</bool>
+							<reference ref="26052107"/>
+							<reference ref="785403312"/>
+							<reference ref="239648738"/>
+							<reference ref="243232151"/>
+						</object>
+						<reference key="parent" ref="148061301"/>
+					</object>
+					<object class="IBObjectRecord">
+						<int key="objectID">146</int>
+						<reference key="object" ref="26052107"/>
+						<reference key="parent" ref="924255883"/>
+					</object>
+					<object class="IBObjectRecord">
+						<int key="objectID">147</int>
+						<reference key="object" ref="785403312"/>
+						<object class="NSMutableArray" key="children">
+							<bool key="EncodedWithXMLCoder">YES</bool>
+							<reference ref="977919695"/>
+							<reference ref="902930739"/>
+						</object>
+						<reference key="parent" ref="924255883"/>
+					</object>
+					<object class="IBObjectRecord">
+						<int key="objectID">148</int>
+						<reference key="object" ref="239648738"/>
+						<reference key="parent" ref="924255883"/>
+					</object>
+					<object class="IBObjectRecord">
+						<int key="objectID">149</int>
+						<reference key="object" ref="243232151"/>
+						<reference key="parent" ref="924255883"/>
+					</object>
+					<object class="IBObjectRecord">
+						<int key="objectID">151</int>
+						<reference key="object" ref="977919695"/>
+						<object class="NSMutableArray" key="children">
+							<bool key="EncodedWithXMLCoder">YES</bool>
+							<reference ref="287704059"/>
+						</object>
+						<reference key="parent" ref="785403312"/>
+					</object>
+					<object class="IBObjectRecord">
+						<int key="objectID">152</int>
+						<reference key="object" ref="902930739"/>
+						<object class="NSMutableArray" key="children">
+							<bool key="EncodedWithXMLCoder">YES</bool>
+							<reference ref="950249531"/>
+						</object>
+						<reference key="parent" ref="785403312"/>
+					</object>
+					<object class="IBObjectRecord">
+						<int key="objectID">153</int>
+						<reference key="object" ref="950249531"/>
+						<reference key="parent" ref="902930739"/>
+					</object>
+					<object class="IBObjectRecord">
+						<int key="objectID">154</int>
+						<reference key="object" ref="287704059"/>
+						<reference key="parent" ref="977919695"/>
+					</object>
+					<object class="IBObjectRecord">
+						<int key="objectID">165</int>
+						<reference key="object" ref="30781231"/>
+						<object class="NSMutableArray" key="children">
+							<bool key="EncodedWithXMLCoder">YES</bool>
+							<reference ref="452175770"/>
+							<reference ref="170369365"/>
+							<reference ref="417904569"/>
+							<reference ref="659680838"/>
+						</object>
+						<reference key="parent" ref="148061301"/>
+					</object>
+					<object class="IBObjectRecord">
+						<int key="objectID">166</int>
+						<reference key="object" ref="452175770"/>
+						<reference key="parent" ref="30781231"/>
+					</object>
+					<object class="IBObjectRecord">
+						<int key="objectID">167</int>
+						<reference key="object" ref="170369365"/>
+						<object class="NSMutableArray" key="children">
+							<bool key="EncodedWithXMLCoder">YES</bool>
+							<reference ref="599415714"/>
+							<reference ref="458070426"/>
+							<reference ref="929638513"/>
+						</object>
+						<reference key="parent" ref="30781231"/>
+					</object>
+					<object class="IBObjectRecord">
+						<int key="objectID">168</int>
+						<reference key="object" ref="417904569"/>
+						<reference key="parent" ref="30781231"/>
+					</object>
+					<object class="IBObjectRecord">
+						<int key="objectID">169</int>
+						<reference key="object" ref="659680838"/>
+						<reference key="parent" ref="30781231"/>
+					</object>
+					<object class="IBObjectRecord">
+						<int key="objectID">170</int>
+						<reference key="object" ref="599415714"/>
+						<object class="NSMutableArray" key="children">
+							<bool key="EncodedWithXMLCoder">YES</bool>
+							<reference ref="933860589"/>
+						</object>
+						<reference key="parent" ref="170369365"/>
+					</object>
+					<object class="IBObjectRecord">
+						<int key="objectID">171</int>
+						<reference key="object" ref="458070426"/>
+						<object class="NSMutableArray" key="children">
+							<bool key="EncodedWithXMLCoder">YES</bool>
+							<reference ref="1060309917"/>
+						</object>
+						<reference key="parent" ref="170369365"/>
+					</object>
+					<object class="IBObjectRecord">
+						<int key="objectID">172</int>
+						<reference key="object" ref="929638513"/>
+						<object class="NSMutableArray" key="children">
+							<bool key="EncodedWithXMLCoder">YES</bool>
+							<reference ref="308070460"/>
+						</object>
+						<reference key="parent" ref="170369365"/>
+					</object>
+					<object class="IBObjectRecord">
+						<int key="objectID">173</int>
+						<reference key="object" ref="308070460"/>
+						<reference key="parent" ref="929638513"/>
+					</object>
+					<object class="IBObjectRecord">
+						<int key="objectID">174</int>
+						<reference key="object" ref="1060309917"/>
+						<reference key="parent" ref="458070426"/>
+					</object>
+					<object class="IBObjectRecord">
+						<int key="objectID">175</int>
+						<reference key="object" ref="933860589"/>
+						<reference key="parent" ref="599415714"/>
+					</object>
+					<object class="IBObjectRecord">
+						<int key="objectID">176</int>
+						<reference key="object" ref="988079201"/>
+						<object class="NSMutableArray" key="children">
+							<bool key="EncodedWithXMLCoder">YES</bool>
+							<reference ref="493724135"/>
+						</object>
+						<reference key="parent" ref="148061301"/>
+					</object>
+					<object class="IBObjectRecord">
+						<int key="objectID">177</int>
+						<reference key="object" ref="493724135"/>
+						<reference key="parent" ref="988079201"/>
+					</object>
+					<object class="IBObjectRecord">
+						<int key="objectID">178</int>
+						<reference key="object" ref="318678771"/>
+						<object class="NSMutableArray" key="children">
+							<bool key="EncodedWithXMLCoder">YES</bool>
+							<reference ref="646248930"/>
+						</object>
+						<reference key="parent" ref="148061301"/>
+					</object>
+					<object class="IBObjectRecord">
+						<int key="objectID">179</int>
+						<reference key="object" ref="105666546"/>
+						<object class="NSMutableArray" key="children">
+							<bool key="EncodedWithXMLCoder">YES</bool>
+							<reference ref="725974029"/>
+						</object>
+						<reference key="parent" ref="148061301"/>
+					</object>
+					<object class="IBObjectRecord">
+						<int key="objectID">180</int>
+						<reference key="object" ref="725974029"/>
+						<reference key="parent" ref="105666546"/>
+					</object>
+					<object class="IBObjectRecord">
+						<int key="objectID">181</int>
+						<reference key="object" ref="646248930"/>
+						<reference key="parent" ref="318678771"/>
+					</object>
+					<object class="IBObjectRecord">
+						<int key="objectID">182</int>
+						<reference key="object" ref="187508141"/>
+						<object class="NSMutableArray" key="children">
+							<bool key="EncodedWithXMLCoder">YES</bool>
+							<reference ref="344238193"/>
+						</object>
+						<reference key="parent" ref="148061301"/>
+					</object>
+					<object class="IBObjectRecord">
+						<int key="objectID">183</int>
+						<reference key="object" ref="407866252"/>
+						<object class="NSMutableArray" key="children">
+							<bool key="EncodedWithXMLCoder">YES</bool>
+							<reference ref="1073664548"/>
+						</object>
+						<reference key="parent" ref="148061301"/>
+					</object>
+					<object class="IBObjectRecord">
+						<int key="objectID">184</int>
+						<reference key="object" ref="1073664548"/>
+						<reference key="parent" ref="407866252"/>
+					</object>
+					<object class="IBObjectRecord">
+						<int key="objectID">185</int>
+						<reference key="object" ref="344238193"/>
+						<reference key="parent" ref="187508141"/>
+					</object>
+					<object class="IBObjectRecord">
+						<int key="objectID">186</int>
+						<reference key="object" ref="705814818"/>
+						<object class="NSMutableArray" key="children">
+							<bool key="EncodedWithXMLCoder">YES</bool>
+							<reference ref="21424487"/>
+						</object>
+						<reference key="parent" ref="148061301"/>
+					</object>
+					<object class="IBObjectRecord">
+						<int key="objectID">187</int>
+						<reference key="object" ref="42828080"/>
+						<object class="NSMutableArray" key="children">
+							<bool key="EncodedWithXMLCoder">YES</bool>
+							<reference ref="55897682"/>
+						</object>
+						<reference key="parent" ref="148061301"/>
+					</object>
+					<object class="IBObjectRecord">
+						<int key="objectID">188</int>
+						<reference key="object" ref="55897682"/>
+						<reference key="parent" ref="42828080"/>
+					</object>
+					<object class="IBObjectRecord">
+						<int key="objectID">189</int>
+						<reference key="object" ref="21424487"/>
+						<reference key="parent" ref="705814818"/>
+					</object>
+					<object class="IBObjectRecord">
+						<int key="objectID">190</int>
+						<reference key="object" ref="730601649"/>
+						<object class="NSMutableArray" key="children">
+							<bool key="EncodedWithXMLCoder">YES</bool>
+							<reference ref="341674719"/>
+						</object>
+						<reference key="parent" ref="148061301"/>
+					</object>
+					<object class="IBObjectRecord">
+						<int key="objectID">191</int>
+						<reference key="object" ref="341674719"/>
+						<reference key="parent" ref="730601649"/>
+					</object>
+					<object class="IBObjectRecord">
+						<int key="objectID">192</int>
+						<reference key="object" ref="770669533"/>
+						<object class="NSMutableArray" key="children">
+							<bool key="EncodedWithXMLCoder">YES</bool>
+							<reference ref="47473596"/>
+						</object>
+						<reference key="parent" ref="148061301"/>
+					</object>
+					<object class="IBObjectRecord">
+						<int key="objectID">193</int>
+						<reference key="object" ref="139589133"/>
+						<object class="NSMutableArray" key="children">
+							<bool key="EncodedWithXMLCoder">YES</bool>
+							<reference ref="312100719"/>
+						</object>
+						<reference key="parent" ref="148061301"/>
+					</object>
+					<object class="IBObjectRecord">
+						<int key="objectID">194</int>
+						<reference key="object" ref="312100719"/>
+						<reference key="parent" ref="139589133"/>
+					</object>
+					<object class="IBObjectRecord">
+						<int key="objectID">195</int>
+						<reference key="object" ref="47473596"/>
+						<reference key="parent" ref="770669533"/>
+					</object>
+					<object class="IBObjectRecord">
+						<int key="objectID">196</int>
+						<reference key="object" ref="7062143"/>
+						<object class="NSMutableArray" key="children">
+							<bool key="EncodedWithXMLCoder">YES</bool>
+							<reference ref="584905870"/>
+						</object>
+						<reference key="parent" ref="148061301"/>
+					</object>
+					<object class="IBObjectRecord">
+						<int key="objectID">197</int>
+						<reference key="object" ref="637960900"/>
+						<object class="NSMutableArray" key="children">
+							<bool key="EncodedWithXMLCoder">YES</bool>
+							<reference ref="287121334"/>
+						</object>
+						<reference key="parent" ref="148061301"/>
+					</object>
+					<object class="IBObjectRecord">
+						<int key="objectID">198</int>
+						<reference key="object" ref="287121334"/>
+						<reference key="parent" ref="637960900"/>
+					</object>
+					<object class="IBObjectRecord">
+						<int key="objectID">199</int>
+						<reference key="object" ref="584905870"/>
+						<reference key="parent" ref="7062143"/>
+					</object>
+					<object class="IBObjectRecord">
+						<int key="objectID">200</int>
+						<reference key="object" ref="431874124"/>
+						<object class="NSMutableArray" key="children">
+							<bool key="EncodedWithXMLCoder">YES</bool>
+							<reference ref="584699695"/>
+						</object>
+						<reference key="parent" ref="148061301"/>
+					</object>
+					<object class="IBObjectRecord">
+						<int key="objectID">201</int>
+						<reference key="object" ref="472784790"/>
+						<object class="NSMutableArray" key="children">
+							<bool key="EncodedWithXMLCoder">YES</bool>
+							<reference ref="1012841858"/>
+						</object>
+						<reference key="parent" ref="148061301"/>
+					</object>
+					<object class="IBObjectRecord">
+						<int key="objectID">202</int>
+						<reference key="object" ref="1012841858"/>
+						<reference key="parent" ref="472784790"/>
+					</object>
+					<object class="IBObjectRecord">
+						<int key="objectID">203</int>
+						<reference key="object" ref="584699695"/>
+						<reference key="parent" ref="431874124"/>
+					</object>
+					<object class="IBObjectRecord">
+						<int key="objectID">208</int>
+						<reference key="object" ref="57441347"/>
+						<object class="NSMutableArray" key="children">
+							<bool key="EncodedWithXMLCoder">YES</bool>
+							<reference ref="510999695"/>
+						</object>
+						<reference key="parent" ref="148061301"/>
+					</object>
+					<object class="IBObjectRecord">
+						<int key="objectID">209</int>
+						<reference key="object" ref="510999695"/>
+						<reference key="parent" ref="57441347"/>
+					</object>
+					<object class="IBObjectRecord">
+						<int key="objectID">210</int>
+						<reference key="object" ref="1039472622"/>
+						<object class="NSMutableArray" key="children">
+							<bool key="EncodedWithXMLCoder">YES</bool>
+							<reference ref="12702536"/>
+						</object>
+						<reference key="parent" ref="148061301"/>
+					</object>
+					<object class="IBObjectRecord">
+						<int key="objectID">211</int>
+						<reference key="object" ref="12702536"/>
+						<reference key="parent" ref="1039472622"/>
+					</object>
+					<object class="IBObjectRecord">
+						<int key="objectID">212</int>
+						<reference key="object" ref="841479602"/>
+						<object class="NSMutableArray" key="children">
+							<bool key="EncodedWithXMLCoder">YES</bool>
+							<reference ref="93304674"/>
+						</object>
+						<reference key="parent" ref="148061301"/>
+					</object>
+					<object class="IBObjectRecord">
+						<int key="objectID">213</int>
+						<reference key="object" ref="93304674"/>
+						<reference key="parent" ref="841479602"/>
+					</object>
+					<object class="IBObjectRecord">
+						<int key="objectID">214</int>
+						<reference key="object" ref="1025033535"/>
+						<object class="NSMutableArray" key="children">
+							<bool key="EncodedWithXMLCoder">YES</bool>
+							<reference ref="340627346"/>
+						</object>
+						<reference key="parent" ref="148061301"/>
+					</object>
+					<object class="IBObjectRecord">
+						<int key="objectID">215</int>
+						<reference key="object" ref="340627346"/>
+						<reference key="parent" ref="1025033535"/>
+					</object>
+					<object class="IBObjectRecord">
+						<int key="objectID">234</int>
+						<reference key="object" ref="562507321"/>
+						<object class="NSMutableArray" key="children">
+							<bool key="EncodedWithXMLCoder">YES</bool>
+							<reference ref="269625364"/>
+						</object>
+						<reference key="parent" ref="148061301"/>
+					</object>
+					<object class="IBObjectRecord">
+						<int key="objectID">235</int>
+						<reference key="object" ref="741831275"/>
+						<object class="NSMutableArray" key="children">
+							<bool key="EncodedWithXMLCoder">YES</bool>
+							<reference ref="1071223370"/>
+						</object>
+						<reference key="parent" ref="148061301"/>
+					</object>
+					<object class="IBObjectRecord">
+						<int key="objectID">236</int>
+						<reference key="object" ref="1071223370"/>
+						<reference key="parent" ref="741831275"/>
+					</object>
+					<object class="IBObjectRecord">
+						<int key="objectID">237</int>
+						<reference key="object" ref="269625364"/>
+						<reference key="parent" ref="562507321"/>
+					</object>
+					<object class="IBObjectRecord">
+						<int key="objectID">249</int>
+						<reference key="object" ref="1072792659"/>
+						<object class="NSMutableArray" key="children">
+							<bool key="EncodedWithXMLCoder">YES</bool>
+							<reference ref="136537671"/>
+						</object>
+						<reference key="parent" ref="148061301"/>
+					</object>
+					<object class="IBObjectRecord">
+						<int key="objectID">250</int>
+						<reference key="object" ref="136537671"/>
+						<reference key="parent" ref="1072792659"/>
+					</object>
+					<object class="IBObjectRecord">
+						<int key="objectID">251</int>
+						<reference key="object" ref="1023286907"/>
+						<object class="NSMutableArray" key="children">
+							<bool key="EncodedWithXMLCoder">YES</bool>
+							<reference ref="117861619"/>
+						</object>
+						<reference key="parent" ref="148061301"/>
+					</object>
+					<object class="IBObjectRecord">
+						<int key="objectID">252</int>
+						<reference key="object" ref="117861619"/>
+						<reference key="parent" ref="1023286907"/>
+					</object>
+				</object>
+			</object>
+			<object class="NSMutableDictionary" key="flattenedProperties">
+				<bool key="EncodedWithXMLCoder">YES</bool>
+				<object class="NSMutableArray" key="dict.sortedKeys">
+					<bool key="EncodedWithXMLCoder">YES</bool>
+					<string>-1.IBPluginDependency</string>
+					<string>-2.IBPluginDependency</string>
+					<string>-3.IBPluginDependency</string>
+					<string>-3.ImportedFromIB2</string>
+					<string>125.IBPluginDependency</string>
+					<string>126.IBPluginDependency</string>
+					<string>127.IBPluginDependency</string>
+					<string>128.IBPluginDependency</string>
+					<string>132.IBPluginDependency</string>
+					<string>133.IBPluginDependency</string>
+					<string>134.IBPluginDependency</string>
+					<string>135.IBPluginDependency</string>
+					<string>136.IBPluginDependency</string>
+					<string>137.IBPluginDependency</string>
+					<string>138.IBPluginDependency</string>
+					<string>139.IBPluginDependency</string>
+					<string>140.IBPluginDependency</string>
+					<string>141.IBPluginDependency</string>
+					<string>142.IBPluginDependency</string>
+					<string>145.IBPluginDependency</string>
+					<string>146.IBPluginDependency</string>
+					<string>147.IBPluginDependency</string>
+					<string>148.IBPluginDependency</string>
+					<string>149.IBPluginDependency</string>
+					<string>151.IBPluginDependency</string>
+					<string>152.IBPluginDependency</string>
+					<string>153.IBPluginDependency</string>
+					<string>154.IBPluginDependency</string>
+					<string>165.IBPluginDependency</string>
+					<string>166.IBPluginDependency</string>
+					<string>167.IBPluginDependency</string>
+					<string>168.IBPluginDependency</string>
+					<string>169.IBPluginDependency</string>
+					<string>170.IBPluginDependency</string>
+					<string>171.IBPluginDependency</string>
+					<string>172.IBPluginDependency</string>
+					<string>173.IBPluginDependency</string>
+					<string>174.IBPluginDependency</string>
+					<string>175.IBPluginDependency</string>
+					<string>176.IBPluginDependency</string>
+					<string>177.IBPluginDependency</string>
+					<string>178.IBPluginDependency</string>
+					<string>179.IBPluginDependency</string>
+					<string>180.IBPluginDependency</string>
+					<string>181.IBPluginDependency</string>
+					<string>182.IBPluginDependency</string>
+					<string>183.IBPluginDependency</string>
+					<string>184.IBPluginDependency</string>
+					<string>185.IBPluginDependency</string>
+					<string>186.IBPluginDependency</string>
+					<string>187.IBPluginDependency</string>
+					<string>188.IBPluginDependency</string>
+					<string>189.IBPluginDependency</string>
+					<string>190.IBPluginDependency</string>
+					<string>191.IBPluginDependency</string>
+					<string>192.IBPluginDependency</string>
+					<string>193.IBPluginDependency</string>
+					<string>194.IBPluginDependency</string>
+					<string>195.IBPluginDependency</string>
+					<string>196.IBPluginDependency</string>
+					<string>197.IBPluginDependency</string>
+					<string>198.IBPluginDependency</string>
+					<string>199.IBPluginDependency</string>
+					<string>200.IBPluginDependency</string>
+					<string>201.IBPluginDependency</string>
+					<string>202.IBPluginDependency</string>
+					<string>203.IBPluginDependency</string>
+					<string>208.IBPluginDependency</string>
+					<string>209.IBPluginDependency</string>
+					<string>21.GUserGuides</string>
+					<string>21.IBEditorWindowLastContentRect</string>
+					<string>21.IBPluginDependency</string>
+					<string>21.IBUserGuides</string>
+					<string>21.ImportedFromIB2</string>
+					<string>21.WindowOrigin</string>
+					<string>21.editorWindowContentRectSynchronizationRect</string>
+					<string>210.IBPluginDependency</string>
+					<string>211.IBPluginDependency</string>
+					<string>212.IBPluginDependency</string>
+					<string>213.IBPluginDependency</string>
+					<string>214.IBPluginDependency</string>
+					<string>215.IBPluginDependency</string>
+					<string>234.IBPluginDependency</string>
+					<string>235.IBPluginDependency</string>
+					<string>236.IBPluginDependency</string>
+					<string>237.IBPluginDependency</string>
+					<string>249.IBPluginDependency</string>
+					<string>250.IBPluginDependency</string>
+					<string>251.IBPluginDependency</string>
+					<string>252.IBPluginDependency</string>
+					<string>52.IBPluginDependency</string>
+					<string>62.IBPluginDependency</string>
+					<string>66.IBPluginDependency</string>
+					<string>82.IBPluginDependency</string>
+				</object>
+				<object class="NSMutableArray" key="dict.values">
+					<bool key="EncodedWithXMLCoder">YES</bool>
+					<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
+					<string>com.apple.InterfaceBuilderKit</string>
+					<string>com.apple.InterfaceBuilderKit</string>
+					<integer value="1" id="9"/>
+					<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
+					<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
+					<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
+					<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
+					<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
+					<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
+					<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
+					<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
+					<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
+					<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
+					<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
+					<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
+					<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
+					<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
+					<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
+					<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
+					<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
+					<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
+					<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
+					<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
+					<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
+					<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
+					<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
+					<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
+					<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
+					<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
+					<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
+					<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
+					<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
+					<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
+					<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
+					<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
+					<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
+					<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
+					<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
+					<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
+					<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
+					<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
+					<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
+					<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
+					<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
+					<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
+					<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
+					<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
+					<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
+					<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
+					<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
+					<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
+					<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
+					<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
+					<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
+					<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
+					<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
+					<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
+					<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
+					<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
+					<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
+					<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
+					<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
+					<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
+					<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
+					<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
+					<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
+					<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
+					<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
+					<object class="NSMutableArray">
+						<bool key="EncodedWithXMLCoder">YES</bool>
+						<object class="IBUserGuide">
+							<reference key="view" ref="148061301"/>
+							<float key="location">9.000000e+01</float>
+							<int key="affinity">0</int>
+						</object>
+						<object class="IBUserGuide">
+							<reference key="view" ref="148061301"/>
+							<float key="location">2.270000e+02</float>
+							<int key="affinity">0</int>
+						</object>
+					</object>
+					<string>{{56, 142}, {272, 686}}</string>
+					<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
+					<object class="NSMutableArray">
+						<bool key="EncodedWithXMLCoder">YES</bool>
+						<object class="IBUserGuide">
+							<reference key="view" ref="148061301"/>
+							<float key="location">1.000000e+02</float>
+							<int key="affinity">0</int>
+						</object>
+						<object class="IBUserGuide">
+							<reference key="view" ref="148061301"/>
+							<float key="location">2.550000e+02</float>
+							<int key="affinity">0</int>
+						</object>
+						<object class="IBUserGuide">
+							<reference key="view" ref="148061301"/>
+							<float key="location">1.780000e+02</float>
+							<int key="affinity">0</int>
+						</object>
+						<object class="IBUserGuide">
+							<reference key="view" ref="148061301"/>
+							<float key="location">4.000000e+00</float>
+							<int key="affinity">3</int>
+						</object>
+						<object class="IBUserGuide">
+							<reference key="view" ref="148061301"/>
+							<float key="location">1.100000e+01</float>
+							<int key="affinity">0</int>
+						</object>
+						<object class="IBUserGuide">
+							<reference key="view" ref="148061301"/>
+							<float key="location">2.080000e+02</float>
+							<int key="affinity">1</int>
+						</object>
+						<object class="IBUserGuide">
+							<reference key="view" ref="148061301"/>
+							<float key="location">1.700000e+02</float>
+							<int key="affinity">0</int>
+						</object>
+					</object>
+					<reference ref="9"/>
+					<string>{155, 478}</string>
+					<string>{{474, 671}, {272, 296}}</string>
+					<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
+					<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
+					<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
+					<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
+					<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
+					<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
+					<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
+					<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
+					<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
+					<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
+					<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
+					<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
+					<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
+					<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
+					<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
+					<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
+					<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
+					<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
+				</object>
+			</object>
+			<object class="NSMutableDictionary" key="unlocalizedProperties">
+				<bool key="EncodedWithXMLCoder">YES</bool>
+				<object class="NSArray" key="dict.sortedKeys">
+					<bool key="EncodedWithXMLCoder">YES</bool>
+				</object>
+				<object class="NSMutableArray" key="dict.values">
+					<bool key="EncodedWithXMLCoder">YES</bool>
+				</object>
+			</object>
+			<nil key="activeLocalization"/>
+			<object class="NSMutableDictionary" key="localizations">
+				<bool key="EncodedWithXMLCoder">YES</bool>
+				<object class="NSArray" key="dict.sortedKeys">
+					<bool key="EncodedWithXMLCoder">YES</bool>
+				</object>
+				<object class="NSMutableArray" key="dict.values">
+					<bool key="EncodedWithXMLCoder">YES</bool>
+				</object>
+			</object>
+			<nil key="sourceID"/>
+			<int key="maxID">254</int>
+		</object>
+		<object class="IBClassDescriber" key="IBDocument.Classes">
+			<object class="NSMutableArray" key="referencedPartialClassDescriptions">
+				<bool key="EncodedWithXMLCoder">YES</bool>
+				<object class="IBPartialClassDescription">
+					<string key="className">LispControllerInspector</string>
+					<string key="superclassName">IBInspector</string>
+					<object class="NSMutableDictionary" key="outlets">
+						<bool key="EncodedWithXMLCoder">YES</bool>
+						<object class="NSMutableArray" key="dict.sortedKeys">
+							<bool key="EncodedWithXMLCoder">YES</bool>
+							<string>initformTable</string>
+							<string>sortTable</string>
+							<string>typeTable</string>
+						</object>
+						<object class="NSMutableArray" key="dict.values">
+							<bool key="EncodedWithXMLCoder">YES</bool>
+							<string>NSTableView</string>
+							<string>NSTableView</string>
+							<string>NSTableView</string>
+						</object>
+					</object>
+					<object class="IBClassDescriptionSource" key="sourceIdentifier">
+						<string key="majorKey">IBProjectSource</string>
+						<string key="minorKey">LispControllerInspector.h</string>
+					</object>
+				</object>
+			</object>
+		</object>
+		<int key="IBDocument.localizationMode">0</int>
+		<string key="IBDocument.LastKnownRelativeProjectPath">../LispControllerPlugin.xcodeproj</string>
+		<int key="IBDocument.defaultPropertyAccessControl">3</int>
+	</data>
+</archive>
Index: /trunk/contrib/krueger/InterfaceProjects/Lisp IB Plugins/LispControllerPlugin/English.lproj/LispControllerPluginLibrary.nib/designable.nib
===================================================================
--- /trunk/contrib/krueger/InterfaceProjects/Lisp IB Plugins/LispControllerPlugin/English.lproj/LispControllerPluginLibrary.nib/designable.nib	(revision 13946)
+++ /trunk/contrib/krueger/InterfaceProjects/Lisp IB Plugins/LispControllerPlugin/English.lproj/LispControllerPluginLibrary.nib/designable.nib	(revision 13946)
@@ -0,0 +1,426 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<archive type="com.apple.InterfaceBuilder3.Cocoa.XIB" version="7.03">
+	<data>
+		<int key="IBDocument.SystemTarget">1050</int>
+		<string key="IBDocument.SystemVersion">9L30</string>
+		<string key="IBDocument.InterfaceBuilderVersion">680</string>
+		<string key="IBDocument.AppKitVersion">949.54</string>
+		<string key="IBDocument.HIToolboxVersion">353.00</string>
+		<object class="NSMutableArray" key="IBDocument.EditedObjectIDs">
+			<bool key="EncodedWithXMLCoder">YES</bool>
+			<integer value="7"/>
+		</object>
+		<object class="NSArray" key="IBDocument.PluginDependencies">
+			<bool key="EncodedWithXMLCoder">YES</bool>
+			<string>com.apple.InterfaceBuilderKit</string>
+			<string>com.apple.InterfaceBuilder.IBSDKPlugin</string>
+			<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
+		</object>
+		<object class="NSMutableDictionary" key="IBDocument.Metadata">
+			<bool key="EncodedWithXMLCoder">YES</bool>
+			<object class="NSArray" key="dict.sortedKeys">
+				<bool key="EncodedWithXMLCoder">YES</bool>
+			</object>
+			<object class="NSMutableArray" key="dict.values">
+				<bool key="EncodedWithXMLCoder">YES</bool>
+			</object>
+		</object>
+		<object class="NSMutableArray" key="IBDocument.RootObjects" id="1012">
+			<bool key="EncodedWithXMLCoder">YES</bool>
+			<object class="NSCustomObject" id="1013">
+				<string key="NSClassName">NSObject</string>
+			</object>
+			<object class="NSCustomObject" id="1015">
+				<string key="NSClassName">FirstResponder</string>
+			</object>
+			<object class="NSCustomObject" id="1016">
+				<string key="NSClassName">NSApplication</string>
+			</object>
+			<object class="NSCustomView" id="1000">
+				<reference key="NSNextResponder"/>
+				<int key="NSvFlags">268</int>
+				<object class="NSMutableArray" key="NSSubviews">
+					<bool key="EncodedWithXMLCoder">YES</bool>
+					<object class="NSTextField" id="71754860">
+						<reference key="NSNextResponder" ref="1000"/>
+						<int key="NSvFlags">268</int>
+						<string key="NSFrame">{{20, 290}, {117, 17}}</string>
+						<reference key="NSSuperview" ref="1000"/>
+						<bool key="NSEnabled">YES</bool>
+						<object class="NSTextFieldCell" key="NSCell" id="787386790">
+							<int key="NSCellFlags">67239488</int>
+							<int key="NSCellFlags2">272630784</int>
+							<string key="NSContents">Template</string>
+							<object class="NSFont" key="NSSupport" id="1007">
+								<string key="NSName">LucidaGrande</string>
+								<double key="NSSize">1.300000e+01</double>
+								<int key="NSfFlags">1044</int>
+							</object>
+							<reference key="NSControlView" ref="71754860"/>
+							<object class="NSColor" key="NSBackgroundColor" id="907990938">
+								<int key="NSColorSpace">6</int>
+								<string key="NSCatalogName">System</string>
+								<string key="NSColorName">controlColor</string>
+								<object class="NSColor" key="NSColor">
+									<int key="NSColorSpace">3</int>
+									<bytes key="NSWhite">MC42NjY2NjY2OQA</bytes>
+								</object>
+							</object>
+							<object class="NSColor" key="NSTextColor" id="544577700">
+								<int key="NSColorSpace">6</int>
+								<string key="NSCatalogName">System</string>
+								<string key="NSColorName">controlTextColor</string>
+								<object class="NSColor" key="NSColor">
+									<int key="NSColorSpace">3</int>
+									<bytes key="NSWhite">MAA</bytes>
+								</object>
+							</object>
+						</object>
+					</object>
+					<object class="NSTextField" id="448392701">
+						<reference key="NSNextResponder" ref="1000"/>
+						<int key="NSvFlags">268</int>
+						<string key="NSFrame">{{17, 20}, {230, 50}}</string>
+						<reference key="NSSuperview" ref="1000"/>
+						<bool key="NSEnabled">YES</bool>
+						<object class="NSTextFieldCell" key="NSCell" id="313792194">
+							<int key="NSCellFlags">67239424</int>
+							<int key="NSCellFlags2">272629760</int>
+							<string key="NSContents">Select the views and buttons above for instructions on how to setup your custom Library object.</string>
+							<reference key="NSSupport" ref="1007"/>
+							<reference key="NSControlView" ref="448392701"/>
+							<reference key="NSBackgroundColor" ref="907990938"/>
+							<reference key="NSTextColor" ref="544577700"/>
+						</object>
+					</object>
+					<object class="NSBox" id="1025445589">
+						<reference key="NSNextResponder" ref="1000"/>
+						<int key="NSvFlags">12</int>
+						<string key="NSFrame">{{20, 288}, {224, 5}}</string>
+						<reference key="NSSuperview" ref="1000"/>
+						<string key="NSOffsets">{0, 0}</string>
+						<object class="NSTextFieldCell" key="NSTitleCell">
+							<int key="NSCellFlags">67239424</int>
+							<int key="NSCellFlags2">0</int>
+							<string key="NSContents">Box</string>
+							<reference key="NSSupport" ref="1007"/>
+							<object class="NSColor" key="NSBackgroundColor">
+								<int key="NSColorSpace">6</int>
+								<string key="NSCatalogName">System</string>
+								<string key="NSColorName">textBackgroundColor</string>
+								<object class="NSColor" key="NSColor">
+									<int key="NSColorSpace">3</int>
+									<bytes key="NSWhite">MQA</bytes>
+								</object>
+							</object>
+							<object class="NSColor" key="NSTextColor">
+								<int key="NSColorSpace">3</int>
+								<bytes key="NSWhite">MCAwLjgwMDAwMDAxAA</bytes>
+							</object>
+						</object>
+						<int key="NSBorderType">3</int>
+						<int key="NSBoxType">2</int>
+						<int key="NSTitlePosition">0</int>
+						<bool key="NSTransparent">NO</bool>
+					</object>
+					<object class="IBLibraryObjectTemplate" id="374094120">
+						<reference key="NSNextResponder" ref="1000"/>
+						<int key="NSvFlags">268</int>
+						<object class="NSMutableArray" key="NSSubviews">
+							<bool key="EncodedWithXMLCoder">YES</bool>
+							<object class="NSImageView" id="860527440">
+								<reference key="NSNextResponder" ref="374094120"/>
+								<int key="NSvFlags">268</int>
+								<object class="NSMutableSet" key="NSDragTypes">
+									<bool key="EncodedWithXMLCoder">YES</bool>
+									<object class="NSMutableArray" key="set.sortedObjects">
+										<bool key="EncodedWithXMLCoder">YES</bool>
+										<string>Apple PDF pasteboard type</string>
+										<string>Apple PICT pasteboard type</string>
+										<string>Apple PNG pasteboard type</string>
+										<string>NSFilenamesPboardType</string>
+										<string>NeXT Encapsulated PostScript v1.2 pasteboard type</string>
+										<string>NeXT TIFF v4.0 pasteboard type</string>
+									</object>
+								</object>
+								<string key="NSFrameSize">{48, 48}</string>
+								<reference key="NSSuperview" ref="374094120"/>
+								<bool key="NSEnabled">YES</bool>
+								<object class="NSImageCell" key="NSCell" id="364918982">
+									<int key="NSCellFlags">130560</int>
+									<int key="NSCellFlags2">33554432</int>
+									<object class="NSCustomResource" key="NSContents">
+										<string key="NSClassName">NSImage</string>
+										<string key="NSResourceName">LispList</string>
+									</object>
+									<int key="NSAlign">0</int>
+									<int key="NSScale">0</int>
+									<int key="NSStyle">0</int>
+									<bool key="NSAnimates">NO</bool>
+								</object>
+								<bool key="NSEditable">YES</bool>
+							</object>
+						</object>
+						<string key="NSFrame">{{35, 100}, {48, 48}}</string>
+						<reference key="NSSuperview" ref="1000"/>
+						<string key="label">Lisp Controller</string>
+						<string key="identifier">B76974F4-E3DA-4D3A-AFF8-5FBBC9CF41D3</string>
+						<string key="briefDescription">A controller for Lisp objects</string>
+						<object class="NSAttributedString" key="fullDescription">
+							<string key="NSString">A controller for any Lisp object that makes it suitable as a data source for NSTableViews or NSOutlineViews.</string>
+							<object class="NSDictionary" key="NSAttributes">
+								<bool key="EncodedWithXMLCoder">YES</bool>
+								<object class="NSMutableArray" key="dict.sortedKeys">
+									<bool key="EncodedWithXMLCoder">YES</bool>
+									<string>NSFont</string>
+									<string>NSParagraphStyle</string>
+								</object>
+								<object class="NSMutableArray" key="dict.values">
+									<bool key="EncodedWithXMLCoder">YES</bool>
+									<object class="NSFont">
+										<string key="NSName">Helvetica</string>
+										<double key="NSSize">1.200000e+01</double>
+										<int key="NSfFlags">16</int>
+									</object>
+									<object class="NSParagraphStyle">
+										<int key="NSAlignment">4</int>
+										<nil key="NSTabStops"/>
+									</object>
+								</object>
+							</object>
+						</object>
+						<string key="initialCategoryPath"/>
+						<nil key="draggableView"/>
+						<nil key="draggedView"/>
+						<nil key="representedObject"/>
+						<nil key="filterableNames"/>
+						<nil key="subtitle"/>
+						<int key="animationScalingMode">0</int>
+					</object>
+				</object>
+				<string key="NSFrameSize">{264, 327}</string>
+				<reference key="NSSuperview"/>
+				<string key="NSClassName">NSView</string>
+			</object>
+			<object class="NSCustomObject" id="730315722">
+				<string key="NSClassName">LispController</string>
+			</object>
+		</object>
+		<object class="IBObjectContainer" key="IBDocument.Objects">
+			<object class="NSMutableArray" key="connectionRecords">
+				<bool key="EncodedWithXMLCoder">YES</bool>
+				<object class="IBConnectionRecord">
+					<object class="IBOutletConnection" key="connection">
+						<string key="label">representedObject</string>
+						<reference key="source" ref="374094120"/>
+						<reference key="destination" ref="730315722"/>
+					</object>
+					<int key="connectionID">48</int>
+				</object>
+			</object>
+			<object class="IBMutableOrderedSet" key="objectRecords">
+				<object class="NSArray" key="orderedObjects">
+					<bool key="EncodedWithXMLCoder">YES</bool>
+					<object class="IBObjectRecord">
+						<int key="objectID">0</int>
+						<object class="NSArray" key="object" id="1014">
+							<bool key="EncodedWithXMLCoder">YES</bool>
+						</object>
+						<reference key="children" ref="1012"/>
+						<nil key="parent"/>
+					</object>
+					<object class="IBObjectRecord">
+						<int key="objectID">-2</int>
+						<reference key="object" ref="1013"/>
+						<reference key="parent" ref="1014"/>
+						<string type="base64-UTF8" key="objectName">RmlsZSdzIE93bmVyA</string>
+					</object>
+					<object class="IBObjectRecord">
+						<int key="objectID">-1</int>
+						<reference key="object" ref="1015"/>
+						<reference key="parent" ref="1014"/>
+						<string key="objectName">First Responder</string>
+					</object>
+					<object class="IBObjectRecord">
+						<int key="objectID">-3</int>
+						<reference key="object" ref="1016"/>
+						<reference key="parent" ref="1014"/>
+						<string key="objectName">Application</string>
+					</object>
+					<object class="IBObjectRecord">
+						<int key="objectID">7</int>
+						<reference key="object" ref="1000"/>
+						<object class="NSMutableArray" key="children">
+							<bool key="EncodedWithXMLCoder">YES</bool>
+							<reference ref="1025445589"/>
+							<reference ref="71754860"/>
+							<reference ref="448392701"/>
+							<reference ref="374094120"/>
+						</object>
+						<reference key="parent" ref="1014"/>
+						<string key="objectName">Library Objects</string>
+					</object>
+					<object class="IBObjectRecord">
+						<int key="objectID">32</int>
+						<reference key="object" ref="1025445589"/>
+						<reference key="parent" ref="1000"/>
+					</object>
+					<object class="IBObjectRecord">
+						<int key="objectID">33</int>
+						<reference key="object" ref="71754860"/>
+						<object class="NSMutableArray" key="children">
+							<bool key="EncodedWithXMLCoder">YES</bool>
+							<reference ref="787386790"/>
+						</object>
+						<reference key="parent" ref="1000"/>
+					</object>
+					<object class="IBObjectRecord">
+						<int key="objectID">34</int>
+						<reference key="object" ref="787386790"/>
+						<reference key="parent" ref="71754860"/>
+					</object>
+					<object class="IBObjectRecord">
+						<int key="objectID">39</int>
+						<reference key="object" ref="448392701"/>
+						<object class="NSMutableArray" key="children">
+							<bool key="EncodedWithXMLCoder">YES</bool>
+							<reference ref="313792194"/>
+						</object>
+						<reference key="parent" ref="1000"/>
+					</object>
+					<object class="IBObjectRecord">
+						<int key="objectID">40</int>
+						<reference key="object" ref="313792194"/>
+						<reference key="parent" ref="448392701"/>
+					</object>
+					<object class="IBObjectRecord">
+						<int key="objectID">44</int>
+						<reference key="object" ref="730315722"/>
+						<reference key="parent" ref="1014"/>
+						<string key="objectName">Lisp Controller</string>
+					</object>
+					<object class="IBObjectRecord">
+						<int key="objectID">45</int>
+						<reference key="object" ref="374094120"/>
+						<object class="NSMutableArray" key="children">
+							<bool key="EncodedWithXMLCoder">YES</bool>
+							<reference ref="860527440"/>
+						</object>
+						<reference key="parent" ref="1000"/>
+					</object>
+					<object class="IBObjectRecord">
+						<int key="objectID">46</int>
+						<reference key="object" ref="860527440"/>
+						<object class="NSMutableArray" key="children">
+							<bool key="EncodedWithXMLCoder">YES</bool>
+							<reference ref="364918982"/>
+						</object>
+						<reference key="parent" ref="374094120"/>
+					</object>
+					<object class="IBObjectRecord">
+						<int key="objectID">47</int>
+						<reference key="object" ref="364918982"/>
+						<reference key="parent" ref="860527440"/>
+					</object>
+				</object>
+			</object>
+			<object class="NSMutableDictionary" key="flattenedProperties">
+				<bool key="EncodedWithXMLCoder">YES</bool>
+				<object class="NSMutableArray" key="dict.sortedKeys">
+					<bool key="EncodedWithXMLCoder">YES</bool>
+					<string>-1.IBPluginDependency</string>
+					<string>-2.IBPluginDependency</string>
+					<string>-3.IBPluginDependency</string>
+					<string>32.IBPluginDependency</string>
+					<string>33.IBPluginDependency</string>
+					<string>34.IBPluginDependency</string>
+					<string>39.IBPluginDependency</string>
+					<string>40.IBPluginDependency</string>
+					<string>44.IBPluginDependency</string>
+					<string>45.IBPluginDependency</string>
+					<string>46.IBPluginDependency</string>
+					<string>47.IBPluginDependency</string>
+					<string>7.IBEditorWindowLastContentRect</string>
+					<string>7.IBPluginDependency</string>
+					<string>7.IBUserGuides</string>
+					<string>7.WindowOrigin</string>
+					<string>7.editorWindowContentRectSynchronizationRect</string>
+				</object>
+				<object class="NSMutableArray" key="dict.values">
+					<bool key="EncodedWithXMLCoder">YES</bool>
+					<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
+					<string>com.apple.InterfaceBuilderKit</string>
+					<string>com.apple.InterfaceBuilderKit</string>
+					<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
+					<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
+					<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
+					<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
+					<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
+					<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
+					<string>com.apple.InterfaceBuilder.IBSDKPlugin</string>
+					<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
+					<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
+					<string>{{9, 529}, {264, 327}}</string>
+					<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
+					<object class="NSMutableArray">
+						<bool key="EncodedWithXMLCoder">YES</bool>
+					</object>
+					<string>{332, 343}</string>
+					<string>{{403, 401}, {264, 327}}</string>
+				</object>
+			</object>
+			<object class="NSMutableDictionary" key="unlocalizedProperties">
+				<bool key="EncodedWithXMLCoder">YES</bool>
+				<object class="NSArray" key="dict.sortedKeys">
+					<bool key="EncodedWithXMLCoder">YES</bool>
+				</object>
+				<object class="NSMutableArray" key="dict.values">
+					<bool key="EncodedWithXMLCoder">YES</bool>
+				</object>
+			</object>
+			<nil key="activeLocalization"/>
+			<object class="NSMutableDictionary" key="localizations">
+				<bool key="EncodedWithXMLCoder">YES</bool>
+				<object class="NSArray" key="dict.sortedKeys">
+					<bool key="EncodedWithXMLCoder">YES</bool>
+				</object>
+				<object class="NSMutableArray" key="dict.values">
+					<bool key="EncodedWithXMLCoder">YES</bool>
+				</object>
+			</object>
+			<nil key="sourceID"/>
+			<int key="maxID">55</int>
+		</object>
+		<object class="IBClassDescriber" key="IBDocument.Classes">
+			<object class="NSMutableArray" key="referencedPartialClassDescriptions">
+				<bool key="EncodedWithXMLCoder">YES</bool>
+				<object class="IBPartialClassDescription">
+					<string key="className">LispController</string>
+					<string key="superclassName">NSObject</string>
+					<object class="NSMutableDictionary" key="actions">
+						<bool key="EncodedWithXMLCoder">YES</bool>
+						<object class="NSMutableArray" key="dict.sortedKeys">
+							<bool key="EncodedWithXMLCoder">YES</bool>
+							<string>addChild:</string>
+							<string>insert:</string>
+							<string>remove:</string>
+						</object>
+						<object class="NSMutableArray" key="dict.values">
+							<bool key="EncodedWithXMLCoder">YES</bool>
+							<string>id</string>
+							<string>id</string>
+							<string>id</string>
+						</object>
+					</object>
+					<object class="IBClassDescriptionSource" key="sourceIdentifier">
+						<string key="majorKey">IBProjectSource</string>
+						<string key="minorKey">LispController.h</string>
+					</object>
+				</object>
+			</object>
+		</object>
+		<int key="IBDocument.localizationMode">0</int>
+		<string key="IBDocument.LastKnownRelativeProjectPath">../LispControllerPlugin.xcodeproj</string>
+		<int key="IBDocument.defaultPropertyAccessControl">3</int>
+	</data>
+</archive>
Index: /trunk/contrib/krueger/InterfaceProjects/Lisp IB Plugins/LispControllerPlugin/Info.plist
===================================================================
--- /trunk/contrib/krueger/InterfaceProjects/Lisp IB Plugins/LispControllerPlugin/Info.plist	(revision 13946)
+++ /trunk/contrib/krueger/InterfaceProjects/Lisp IB Plugins/LispControllerPlugin/Info.plist	(revision 13946)
@@ -0,0 +1,26 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
+<plist version="1.0">
+<dict>
+	<key>CFBundleDevelopmentRegion</key>
+	<string>English</string>
+	<key>CFBundleExecutable</key>
+	<string>${EXECUTABLE_NAME}</string>
+	<key>CFBundleIdentifier</key>
+	<string>com.clozure.ClozureCL.ibplugin</string>
+	<key>CFBundleInfoDictionaryVersion</key>
+	<string>6.0</string>
+	<key>CFBundleName</key>
+	<string>${PRODUCT_NAME}</string>
+	<key>CFBundlePackageType</key>
+	<string>BNDL</string>
+	<key>CFBundleShortVersionString</key>
+	<string>1.0</string>
+	<key>CFBundleSignature</key>
+	<string>OMCL</string>
+	<key>CFBundleVersion</key>
+	<string>1</string>
+	<key>NSPrincipalClass</key>
+	<string>LispControllerPlugin</string>
+</dict>
+</plist>
Index: /trunk/contrib/krueger/InterfaceProjects/Lisp IB Plugins/LispControllerPlugin/LispController.classdescription
===================================================================
--- /trunk/contrib/krueger/InterfaceProjects/Lisp IB Plugins/LispControllerPlugin/LispController.classdescription	(revision 13946)
+++ /trunk/contrib/krueger/InterfaceProjects/Lisp IB Plugins/LispControllerPlugin/LispController.classdescription	(revision 13946)
@@ -0,0 +1,17 @@
+{
+	Actions = {
+		// Define action descriptions here, for example
+		// "myAction:" = id;
+		"insert:" = id;
+		"addChild:" = id;
+		"remove:" = id;
+	};
+	Outlets = {
+		// Define outlet descriptions here, for example
+		// myOutlet = NSView;
+		view = NSView;
+		owner = id;
+	};
+    ClassName = LispController; 
+    SuperClass = NSObject;
+}
Index: /trunk/contrib/krueger/InterfaceProjects/Lisp IB Plugins/LispControllerPlugin/LispController.h
===================================================================
--- /trunk/contrib/krueger/InterfaceProjects/Lisp IB Plugins/LispControllerPlugin/LispController.h	(revision 13946)
+++ /trunk/contrib/krueger/InterfaceProjects/Lisp IB Plugins/LispControllerPlugin/LispController.h	(revision 13946)
@@ -0,0 +1,52 @@
+//
+//  LispController.h
+//  LispControllerPlugin
+//
+//  Created by Paul Krueger on 2/5/10.
+//  Copyright 2010. All rights reserved.
+//
+
+
+@interface LispController : NSObject {
+	NSMutableArray *typeInfo;
+	NSMutableArray *initforms;
+	NSMutableArray *sortInfo;
+	NSString *rootType;
+	NSString *readerFunc;
+	NSString *writerFunc;
+	NSString *countFunc;
+	NSString *selectFunc;
+	NSString *editedFunc;
+	NSString *addedFunc;
+	NSString *removedFunc;
+	NSString *deleteFunc;
+	NSString *addChildFunc;
+	NSString *childrenFunc;
+	BOOL genRoot;
+	IBOutlet NSView *view;
+	IBOutlet id *owner;
+}
+- (void)encodeWithCoder:(NSCoder *)encoder;
+- (id)initWithCoder:(NSCoder *)decoder;
+- (id)init;
+- (int)typeInfoCount;
+- (int)initformCount;
+- (int)sortInfoCount;
+- (void)addTypeRow;
+- (void)addInitformRow;
+- (void)addSortRow;
+- (void)typeTableRemoveRow: (int)row;
+- (void)initformTableRemoveRow: (int)row;
+- (void)sortTableRemoveRow: (int)row;
+- (id) emptyArrayOfSize: (int) sz;
+- (id) typeTableCellAtRow:(int)row col:(int)col;
+- (id) initformTableCellAtRow:(int)row col:(int)col;
+- (id) sortTableCellAtRow:(int)row col:(int)col;
+- (void) setValue:(id)newVal forTypeTableCellAtRow:(int)rowIndex col:(int)colIndex;
+- (void) setValue:(id)newVal forInitformTableCellAtRow:(int)rowIndex col:(int)colIndex;
+- (void) setValue:(id)newVal forSortTableCellAtRow:(int)rowIndex col:(int)colIndex;
+- (IBAction)insert: (id)sender;
+- (IBAction)addChild: (id)sender;
+- (IBAction)remove: (id)sender;
+
+@end
Index: /trunk/contrib/krueger/InterfaceProjects/Lisp IB Plugins/LispControllerPlugin/LispController.m
===================================================================
--- /trunk/contrib/krueger/InterfaceProjects/Lisp IB Plugins/LispControllerPlugin/LispController.m	(revision 13946)
+++ /trunk/contrib/krueger/InterfaceProjects/Lisp IB Plugins/LispControllerPlugin/LispController.m	(revision 13946)
@@ -0,0 +1,175 @@
+//
+//  LispController.m
+//  LispControllerPlugin
+//
+//  Created by Paul Krueger on 2/4/10.
+//  Copyright 2010. All rights reserved.
+//
+
+#import <LispController.h>
+
+@implementation LispController
+
+- (void)encodeWithCoder:(NSCoder *)encoder {
+	[encoder encodeObject:typeInfo forKey:@"typeInfo"];
+	[encoder encodeObject:initforms forKey:@"initforms"];
+	[encoder encodeObject:sortInfo forKey:@"sortInfo"];
+	[encoder encodeObject:rootType forKey:@"rootType"];
+	[encoder encodeObject:readerFunc forKey:@"readerFunc"];
+	[encoder encodeObject:writerFunc forKey:@"writerFunc"];
+	[encoder encodeObject:countFunc forKey:@"countFunc"];
+	[encoder encodeObject:selectFunc forKey:@"selectFunc"];
+	[encoder encodeObject:editedFunc forKey:@"editedFunc"];
+	[encoder encodeObject:addedFunc forKey:@"addedFunc"];
+	[encoder encodeObject:removedFunc forKey:@"removedFunc"];
+	[encoder encodeObject:deleteFunc forKey:@"deleteFunc"];
+	[encoder encodeObject:addChildFunc forKey:@"addChildFunc"];
+	[encoder encodeObject:childrenFunc forKey:@"childrenFunc"];
+	[encoder encodeBool:genRoot forKey:@"genRoot"];
+}
+
+- (id)init {
+	typeInfo = [[NSMutableArray alloc] initWithCapacity:5];
+	initforms = [[NSMutableArray alloc] initWithCapacity:5];
+	sortInfo = [[NSMutableArray alloc] initWithCapacity:5];
+	rootType = @"";
+	readerFunc = @"";
+	writerFunc = @"";
+	countFunc = @"";
+	selectFunc = @"";
+	editedFunc = @"";
+	deleteFunc = @"";
+	addChildFunc = @"";
+	childrenFunc = @"";
+	genRoot = YES;
+	
+	[self addTypeRow];
+	[self addInitformRow];
+	[self addSortRow];
+	return self;
+}
+
+- (id)initWithCoder:(NSCoder *)decoder {
+	typeInfo = [[decoder decodeObjectForKey:@"typeInfo"] retain];
+	initforms = [[decoder decodeObjectForKey:@"initforms"] retain];
+	sortInfo = [[decoder decodeObjectForKey:@"sortInfo"] retain];
+	rootType = [[decoder decodeObjectForKey:@"rootType"] retain];
+	readerFunc = [[decoder decodeObjectForKey:@"readerFunc"] retain];
+	writerFunc = [[decoder decodeObjectForKey:@"writerFunc"] retain];
+	countFunc = [[decoder decodeObjectForKey:@"countFunc"] retain];
+	selectFunc = [[decoder decodeObjectForKey:@"selectFunc"] retain];
+	editedFunc = [[decoder decodeObjectForKey:@"editedFunc"] retain];
+	addedFunc = [[decoder decodeObjectForKey:@"addedFunc"] retain];
+	removedFunc = [[decoder decodeObjectForKey:@"removedFunc"] retain];
+	deleteFunc = [[decoder decodeObjectForKey:@"deleteFunc"] retain];
+	addChildFunc = [[decoder decodeObjectForKey:@"addChildFunc"] retain];
+	childrenFunc = [[decoder decodeObjectForKey:@"childrenFunc"] retain];
+	genRoot = [decoder decodeBoolForKey:@"genRoot"];
+	return self;
+}
+
+- (int)typeInfoCount {
+	return [typeInfo count];
+}
+
+- (int)initformCount {
+	return [initforms count];
+}
+
+- (int)sortInfoCount {
+	return [sortInfo count];
+}
+
+
+- (void)addTypeRow {
+	int index = [typeInfo count];
+	NSMutableArray *firstTypeEntry = [self emptyArrayOfSize:3];
+	[typeInfo insertObject:firstTypeEntry atIndex: index];
+}
+
+- (void)addInitformRow {
+	int index = [initforms count];
+	NSMutableArray *firstInitformEntry = [self emptyArrayOfSize:2];
+	[initforms insertObject:firstInitformEntry atIndex: index];
+}
+
+- (void)addSortRow {
+	int index = [sortInfo count];
+	NSMutableArray *firstSortEntry = [self emptyArrayOfSize:3];
+	[sortInfo insertObject:firstSortEntry atIndex: index];
+}
+
+- (void)typeTableRemoveRow: (int)row {
+	[typeInfo removeObjectAtIndex: row];
+}
+
+- (void)initformTableRemoveRow: (int)row {
+	[initforms removeObjectAtIndex: row];
+}
+
+- (void)sortTableRemoveRow: (int)row {
+	[sortInfo removeObjectAtIndex: row];
+}
+
+- (id) emptyArrayOfSize: (int) sz {
+	NSMutableArray *newArray = [[NSMutableArray alloc] initWithCapacity: sz];
+	int i;
+	[newArray insertObject:@"<new type>" atIndex: 0];
+	for (i = 1; i < sz; i++) {
+		[newArray insertObject:@"" atIndex: i];
+	}
+	return newArray;
+}
+
+- (id) typeTableCellAtRow: (int)row
+					  col: (int)col {
+	NSMutableArray *rowArray = [typeInfo objectAtIndex:row];
+	return [rowArray objectAtIndex:col];
+}
+
+- (id) initformTableCellAtRow: (int)row
+						  col: (int)col {
+	NSMutableArray *rowArray = [initforms objectAtIndex:row];
+	return [rowArray objectAtIndex:col];
+}
+
+- (id) sortTableCellAtRow: (int)row
+					  col: (int)col {
+	NSMutableArray *rowArray = [sortInfo objectAtIndex:row];
+	return [rowArray objectAtIndex:col];
+}
+
+- (void) setValue: (id)newVal 
+	forTypeTableCellAtRow: (int)rowIndex
+			  col: (int)colIndex {
+	NSMutableArray *rowArray = [typeInfo objectAtIndex:rowIndex];
+	[rowArray replaceObjectAtIndex:	colIndex withObject: newVal];
+}
+
+- (void) setValue: (id)newVal 
+forInitformTableCellAtRow: (int)rowIndex
+			  col: (int)colIndex {
+	NSMutableArray *rowArray = [initforms objectAtIndex:rowIndex];
+	[rowArray replaceObjectAtIndex:	colIndex withObject: newVal];
+}
+
+- (void) setValue: (id)newVal 
+forSortTableCellAtRow: (int)rowIndex
+			  col: (int)colIndex {
+	NSMutableArray *rowArray = [sortInfo objectAtIndex:rowIndex];
+	[rowArray replaceObjectAtIndex:	colIndex withObject: newVal];
+}
+
+- (IBAction)insert: (id)sender {
+	// don't need to do anything here; implemented in Lisp
+}
+
+- (IBAction)addChild: (id)sender {
+	// don't need to do anything here; implemented in Lisp
+}
+
+- (IBAction)remove: (id)sender {
+	// don't need to do anything here; implemented in Lisp
+}
+
+@end
Index: /trunk/contrib/krueger/InterfaceProjects/Lisp IB Plugins/LispControllerPlugin/LispControllerInspector.h
===================================================================
--- /trunk/contrib/krueger/InterfaceProjects/Lisp IB Plugins/LispControllerPlugin/LispControllerInspector.h	(revision 13946)
+++ /trunk/contrib/krueger/InterfaceProjects/Lisp IB Plugins/LispControllerPlugin/LispControllerInspector.h	(revision 13946)
@@ -0,0 +1,19 @@
+//
+//  LispControllerInspector.h
+//  LispControllerPlugin
+//
+//  Created by Paul Krueger on 2/5/10.
+//  Copyright 2010. All rights reserved.
+//
+
+#import <InterfaceBuilderKit/InterfaceBuilderKit.h>
+#import <LispController.h>
+
+@interface LispControllerInspector : IBInspector {
+	IBOutlet NSTableView *typeTable;
+	IBOutlet NSTableView *initformTable;
+	IBOutlet NSTableView *sortTable;
+}
+
+
+@end
Index: /trunk/contrib/krueger/InterfaceProjects/Lisp IB Plugins/LispControllerPlugin/LispControllerInspector.m
===================================================================
--- /trunk/contrib/krueger/InterfaceProjects/Lisp IB Plugins/LispControllerPlugin/LispControllerInspector.m	(revision 13946)
+++ /trunk/contrib/krueger/InterfaceProjects/Lisp IB Plugins/LispControllerPlugin/LispControllerInspector.m	(revision 13946)
@@ -0,0 +1,122 @@
+//
+//  LispControllerInspector.m
+//  LispControllerPlugin
+//
+//  Created by Paul Krueger on 2/5/10.
+//  Copyright 2010. All rights reserved.
+//
+
+#import "LispControllerInspector.h"
+
+@implementation LispControllerInspector
+
+- (BOOL)supportsMultipleObjectInspection {
+	return NO;
+}
+
+- (NSString *)viewNibName {
+    return @"LispControllerInspector";
+}
+
+- (void)refresh {
+	// Synchronize your inspector's content view with the currently selected objects
+	[super refresh];
+	[typeTable reloadData];
+	[initformTable reloadData];
+	[sortTable reloadData];
+}
+
+- (int)numberOfRowsInTableView:(NSTableView *)tab {
+	NSArray* objects = [self inspectedObjects];
+	NSInteger numObjects = [objects count];
+	if (numObjects == 1) {
+		LispController *lc = [objects objectAtIndex:0];
+		if (tab == typeTable) {
+			return [lc typeInfoCount];
+		} else if (tab == initformTable) {
+			return [lc initformCount];
+		} else if (tab == sortTable) {
+			return [lc sortInfoCount];
+		}
+	}
+	return 0;
+}
+
+- (id) tableView: (NSTableView *)tab
+	objectValueForTableColumn: (NSTableColumn *)colObj
+			 row: (int)rowIndex {
+	NSArray* objects = [self inspectedObjects];
+	NSInteger numObjects = [objects count];
+	if (numObjects == 1) {
+		LispController *lc = [objects objectAtIndex:0];
+		int colIndex = [[colObj identifier] intValue];
+		if (tab == typeTable) {
+			return [lc typeTableCellAtRow:rowIndex col:colIndex];
+		} else if (tab == initformTable) {
+			return [lc initformTableCellAtRow:rowIndex col:colIndex];
+		} else if (tab == sortTable) {
+			return [lc sortTableCellAtRow:rowIndex col:colIndex];
+		}
+	}
+	return @"";
+}
+
+- (void) tableView: (NSTableView *) tab
+	setObjectValue: (id) newVal
+	forTableColumn: (NSTableColumn *) colObj
+			   row: (int) rowIndex {
+	NSArray* objects = [self inspectedObjects];
+	NSInteger numObjects = [objects count];
+	if (numObjects == 1) {
+		LispController *lc = [objects objectAtIndex:0];
+		int colIndex = [[colObj identifier] intValue];
+		int rowCount;
+		if (tab == typeTable) {
+			rowCount = [lc typeInfoCount];
+			[lc setValue:newVal forTypeTableCellAtRow:rowIndex col:colIndex];
+			if ((rowIndex == (rowCount - 1)) &&
+				![newVal isEqualToString:@""]) {
+				[lc addTypeRow];
+				[tab reloadData];
+			}
+			if ((rowIndex < (rowCount - 1)) &&
+				[[lc typeTableCellAtRow:rowIndex col:0] isEqualToString:@""] &&
+				[[lc typeTableCellAtRow:rowIndex col:1] isEqualToString:@""] &&
+				[[lc typeTableCellAtRow:rowIndex col:2] isEqualToString:@""]) {
+				[lc  typeTableRemoveRow: rowIndex];
+				[tab reloadData];
+			}
+		} else if (tab == initformTable) {
+			rowCount = [lc initformCount];
+			[lc setValue:newVal forInitformTableCellAtRow:rowIndex col:colIndex];
+			if ((rowIndex == (rowCount - 1)) &&
+				![newVal isEqualToString:@""]) {
+				[lc addInitformRow];
+				[tab reloadData];
+			}
+			if ((rowIndex < (rowCount - 1)) &&
+				[[lc initformTableCellAtRow:rowIndex col:0] isEqualToString:@""] &&
+				[[lc initformTableCellAtRow:rowIndex col:1] isEqualToString:@""]) {
+				[lc  initformTableRemoveRow: rowIndex];
+				[tab reloadData];
+			}					
+		} else if (tab == sortTable) {
+			rowCount = [lc sortInfoCount];
+			[lc setValue:newVal forSortTableCellAtRow:rowIndex col:colIndex];
+			if ((rowIndex == (rowCount - 1)) &&
+				![newVal isEqualToString:@""]) {
+				[lc addSortRow];
+				[tab reloadData];
+			}
+			if ((rowIndex < (rowCount - 1)) &&
+				[[lc sortTableCellAtRow:rowIndex col:0] isEqualToString:@""] &&
+				[[lc sortTableCellAtRow:rowIndex col:1] isEqualToString:@""] &&
+				[[lc sortTableCellAtRow:rowIndex col:2] isEqualToString:@""]) {
+				[lc  sortTableRemoveRow: rowIndex];
+				[tab reloadData];
+			}	
+		}
+	}
+}	
+
+@end
Index: /trunk/contrib/krueger/InterfaceProjects/Lisp IB Plugins/LispControllerPlugin/LispControllerPlugin-Info.plist
===================================================================
--- /trunk/contrib/krueger/InterfaceProjects/Lisp IB Plugins/LispControllerPlugin/LispControllerPlugin-Info.plist	(revision 13946)
+++ /trunk/contrib/krueger/InterfaceProjects/Lisp IB Plugins/LispControllerPlugin/LispControllerPlugin-Info.plist	(revision 13946)
@@ -0,0 +1,22 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
+<plist version="1.0">
+<dict>
+	<key>CFBundleDevelopmentRegion</key>
+	<string>English</string>
+	<key>CFBundleExecutable</key>
+	<string>${EXECUTABLE_NAME}</string>
+	<key>CFBundleIdentifier</key>
+	<string>com.yourcompany.${PRODUCT_NAME:identifier}</string>
+	<key>CFBundleInfoDictionaryVersion</key>
+	<string>6.0</string>
+	<key>CFBundlePackageType</key>
+	<string>FMWK</string>
+	<key>CFBundleSignature</key>
+	<string>????</string>
+	<key>CFBundleVersion</key>
+	<string>1.0</string>
+	<key>CFBundleName</key>
+	<string>${PRODUCT_NAME}</string>
+</dict>
+</plist>
Index: /trunk/contrib/krueger/InterfaceProjects/Lisp IB Plugins/LispControllerPlugin/LispControllerPlugin.h
===================================================================
--- /trunk/contrib/krueger/InterfaceProjects/Lisp IB Plugins/LispControllerPlugin/LispControllerPlugin.h	(revision 13946)
+++ /trunk/contrib/krueger/InterfaceProjects/Lisp IB Plugins/LispControllerPlugin/LispControllerPlugin.h	(revision 13946)
@@ -0,0 +1,15 @@
+//
+//  LispControllerPlugin.h
+//  LispControllerPlugin
+//
+//  Created by Paul Krueger on 2/3/10.
+//  Copyright. All rights reserved.
+//
+
+#import <InterfaceBuilderKit/InterfaceBuilderKit.h>
+
+@interface LispControllerPlugin : IBPlugin {
+
+}
+
+@end
Index: /trunk/contrib/krueger/InterfaceProjects/Lisp IB Plugins/LispControllerPlugin/LispControllerPlugin.m
===================================================================
--- /trunk/contrib/krueger/InterfaceProjects/Lisp IB Plugins/LispControllerPlugin/LispControllerPlugin.m	(revision 13946)
+++ /trunk/contrib/krueger/InterfaceProjects/Lisp IB Plugins/LispControllerPlugin/LispControllerPlugin.m	(revision 13946)
@@ -0,0 +1,20 @@
+//
+//  LispControllerPlugin.m
+//  LispControllerPlugin
+//
+//  Created by Paul Krueger on 2/3/10.
+//  Copyright. All rights reserved.
+//
+
+#import "LispControllerPlugin.h"
+
+@implementation LispControllerPlugin
+- (NSArray *)libraryNibNames {
+    return [NSArray arrayWithObject:@"LispControllerPluginLibrary"];
+}
+
+- (NSArray *)requiredFrameworks {
+    return [NSArray arrayWithObjects:[NSBundle bundleWithIdentifier:@"com.yourcompany.LispControllerPlugin"], nil];
+}
+
+@end
Index: /trunk/contrib/krueger/InterfaceProjects/Lisp IB Plugins/LispControllerPlugin/LispControllerPlugin.xcodeproj/default.pbxuser
===================================================================
--- /trunk/contrib/krueger/InterfaceProjects/Lisp IB Plugins/LispControllerPlugin/LispControllerPlugin.xcodeproj/default.pbxuser	(revision 13946)
+++ /trunk/contrib/krueger/InterfaceProjects/Lisp IB Plugins/LispControllerPlugin/LispControllerPlugin.xcodeproj/default.pbxuser	(revision 13946)
@@ -0,0 +1,147 @@
+// !$*UTF8*$!
+{
+	0259C573FE90428111CA0C5A /* Project object */ = {
+		activeBuildConfigurationName = Debug;
+		activeExecutable = C096A9340C03CEAB00263BB0 /* Interface Builder */;
+		activeTarget = 53DF6901067E5B8E0090B5B0 /* All */;
+		codeSenseManager = C096A9330C03CEA700263BB0 /* Code sense */;
+		executables = (
+			C096A9340C03CEAB00263BB0 /* Interface Builder */,
+		);
+		perUserDictionary = {
+			PBXConfiguration.PBXFileTableDataSource3.PBXExecutablesDataSource = {
+				PBXFileTableDataSourceColumnSortingDirectionKey = "-1";
+				PBXFileTableDataSourceColumnSortingKey = PBXExecutablesDataSource_NameID;
+				PBXFileTableDataSourceColumnWidthsKey = (
+					22,
+					300,
+					252,
+				);
+				PBXFileTableDataSourceColumnsKey = (
+					PBXExecutablesDataSource_ActiveFlagID,
+					PBXExecutablesDataSource_NameID,
+					PBXExecutablesDataSource_CommentsID,
+				);
+			};
+			PBXConfiguration.PBXFileTableDataSource3.PBXFileTableDataSource = {
+				PBXFileTableDataSourceColumnSortingDirectionKey = "-1";
+				PBXFileTableDataSourceColumnSortingKey = PBXFileDataSource_Filename_ColumnID;
+				PBXFileTableDataSourceColumnWidthsKey = (
+					20,
+					364,
+					20,
+					48,
+					43,
+					43,
+					20,
+				);
+				PBXFileTableDataSourceColumnsKey = (
+					PBXFileDataSource_FiletypeID,
+					PBXFileDataSource_Filename_ColumnID,
+					PBXFileDataSource_Built_ColumnID,
+					PBXFileDataSource_ObjectSize_ColumnID,
+					PBXFileDataSource_Errors_ColumnID,
+					PBXFileDataSource_Warnings_ColumnID,
+					PBXFileDataSource_Target_ColumnID,
+				);
+			};
+			PBXConfiguration.PBXTargetDataSource.PBXTargetDataSource = {
+				PBXFileTableDataSourceColumnSortingDirectionKey = "-1";
+				PBXFileTableDataSourceColumnSortingKey = PBXFileDataSource_Filename_ColumnID;
+				PBXFileTableDataSourceColumnWidthsKey = (
+					20,
+					324,
+					60,
+					20,
+					48.16259765625,
+					43,
+					43,
+				);
+				PBXFileTableDataSourceColumnsKey = (
+					PBXFileDataSource_FiletypeID,
+					PBXFileDataSource_Filename_ColumnID,
+					PBXTargetDataSource_PrimaryAttribute,
+					PBXFileDataSource_Built_ColumnID,
+					PBXFileDataSource_ObjectSize_ColumnID,
+					PBXFileDataSource_Errors_ColumnID,
+					PBXFileDataSource_Warnings_ColumnID,
+				);
+			};
+			PBXPerProjectTemplateStateSaveDate = 232924969;
+			PBXWorkspaceStateSaveDate = 232924969;
+		};
+		sourceControlManager = C096A9320C03CEA700263BB0 /* Source Control */;
+		userBuildSettings = {
+		};
+	};
+	53DF68FC067E5B5A0090B5B0 /* LispControllerPluginFramework */ = {
+		activeExec = 0;
+	};
+	53DF6901067E5B8E0090B5B0 /* All */ = {
+		activeExec = 0;
+	};
+	8D1AC9600486D14A00FE50C9 /* LispControllerPlugin */ = {
+		activeExec = 0;
+	};
+	C096A9320C03CEA700263BB0 /* Source Control */ = {
+		isa = PBXSourceControlManager;
+		fallbackIsa = XCSourceControlManager;
+		isSCMEnabled = 0;
+		scmConfiguration = {
+		};
+	};
+	C096A9330C03CEA700263BB0 /* Code sense */ = {
+		isa = PBXCodeSenseManager;
+		indexTemplatePath = "";
+	};
+	C096A9340C03CEAB00263BB0 /* Interface Builder */ = {
+		isa = PBXExecutable;
+		activeArgIndices = (
+			YES,
+		);
+		argumentStrings = (
+			"-NSOpen \"LispControllerPlugin.ibplugin\"",
+		);
+		autoAttachOnCrash = 1;
+		breakpointsEnabled = 1;
+		configStateDict = {
+			"PBXLSLaunchAction-0" = {
+				PBXLSLaunchAction = 0;
+				PBXLSLaunchStartAction = 1;
+				PBXLSLaunchStdioStyle = 2;
+				PBXLSLaunchStyle = 0;
+				class = PBXLSRunLaunchConfig;
+				commandLineArgs = (
+				);
+				displayName = "Executable Runner";
+				environment = {
+				};
+				identifier = com.apple.Xcode.launch.runConfig;
+				remoteHostInfo = "";
+				startActionInfo = "";
+			};
+		};
+		customDataFormattersEnabled = 1;
+		debuggerPlugin = GDBDebugging;
+		disassemblyDisplayState = 0;
+		dylibVariantSuffix = "";
+		enableDebugStr = 1;
+		environmentEntries = (
+		);
+		executableSystemSymbolLevel = 0;
+		executableUserSymbolLevel = 0;
+		launchableReference = C096A9350C03CEAB00263BB0 /* Interface Builder.app */;
+		libgmallocEnabled = 0;
+		name = "Interface Builder";
+		sourceDirectories = (
+		);
+		startupPath = "<<ProductDirectory>>";
+	};
+	C096A9350C03CEAB00263BB0 /* Interface Builder.app */ = {
+		isa = PBXFileReference;
+		lastKnownFileType = wrapper.application;
+		name = "Interface Builder.app";
+		path = "Applications/Interface Builder.app";
+		sourceTree = DEVELOPER_DIR;
+	};
+}
Index: /trunk/contrib/krueger/InterfaceProjects/Lisp IB Plugins/LispControllerPlugin/LispControllerPlugin.xcodeproj/paul.mode1v3
===================================================================
--- /trunk/contrib/krueger/InterfaceProjects/Lisp IB Plugins/LispControllerPlugin/LispControllerPlugin.xcodeproj/paul.mode1v3	(revision 13946)
+++ /trunk/contrib/krueger/InterfaceProjects/Lisp IB Plugins/LispControllerPlugin/LispControllerPlugin.xcodeproj/paul.mode1v3	(revision 13946)
@@ -0,0 +1,1430 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
+<plist version="1.0">
+<dict>
+	<key>ActivePerspectiveName</key>
+	<string>Project</string>
+	<key>AllowedModules</key>
+	<array>
+		<dict>
+			<key>BundleLoadPath</key>
+			<string></string>
+			<key>MaxInstances</key>
+			<string>n</string>
+			<key>Module</key>
+			<string>PBXSmartGroupTreeModule</string>
+			<key>Name</key>
+			<string>Groups and Files Outline View</string>
+		</dict>
+		<dict>
+			<key>BundleLoadPath</key>
+			<string></string>
+			<key>MaxInstances</key>
+			<string>n</string>
+			<key>Module</key>
+			<string>PBXNavigatorGroup</string>
+			<key>Name</key>
+			<string>Editor</string>
+		</dict>
+		<dict>
+			<key>BundleLoadPath</key>
+			<string></string>
+			<key>MaxInstances</key>
+			<string>n</string>
+			<key>Module</key>
+			<string>XCTaskListModule</string>
+			<key>Name</key>
+			<string>Task List</string>
+		</dict>
+		<dict>
+			<key>BundleLoadPath</key>
+			<string></string>
+			<key>MaxInstances</key>
+			<string>n</string>
+			<key>Module</key>
+			<string>XCDetailModule</string>
+			<key>Name</key>
+			<string>File and Smart Group Detail Viewer</string>
+		</dict>
+		<dict>
+			<key>BundleLoadPath</key>
+			<string></string>
+			<key>MaxInstances</key>
+			<string>1</string>
+			<key>Module</key>
+			<string>PBXBuildResultsModule</string>
+			<key>Name</key>
+			<string>Detailed Build Results Viewer</string>
+		</dict>
+		<dict>
+			<key>BundleLoadPath</key>
+			<string></string>
+			<key>MaxInstances</key>
+			<string>1</string>
+			<key>Module</key>
+			<string>PBXProjectFindModule</string>
+			<key>Name</key>
+			<string>Project Batch Find Tool</string>
+		</dict>
+		<dict>
+			<key>BundleLoadPath</key>
+			<string></string>
+			<key>MaxInstances</key>
+			<string>n</string>
+			<key>Module</key>
+			<string>XCProjectFormatConflictsModule</string>
+			<key>Name</key>
+			<string>Project Format Conflicts List</string>
+		</dict>
+		<dict>
+			<key>BundleLoadPath</key>
+			<string></string>
+			<key>MaxInstances</key>
+			<string>n</string>
+			<key>Module</key>
+			<string>PBXBookmarksModule</string>
+			<key>Name</key>
+			<string>Bookmarks Tool</string>
+		</dict>
+		<dict>
+			<key>BundleLoadPath</key>
+			<string></string>
+			<key>MaxInstances</key>
+			<string>n</string>
+			<key>Module</key>
+			<string>PBXClassBrowserModule</string>
+			<key>Name</key>
+			<string>Class Browser</string>
+		</dict>
+		<dict>
+			<key>BundleLoadPath</key>
+			<string></string>
+			<key>MaxInstances</key>
+			<string>n</string>
+			<key>Module</key>
+			<string>PBXCVSModule</string>
+			<key>Name</key>
+			<string>Source Code Control Tool</string>
+		</dict>
+		<dict>
+			<key>BundleLoadPath</key>
+			<string></string>
+			<key>MaxInstances</key>
+			<string>n</string>
+			<key>Module</key>
+			<string>PBXDebugBreakpointsModule</string>
+			<key>Name</key>
+			<string>Debug Breakpoints Tool</string>
+		</dict>
+		<dict>
+			<key>BundleLoadPath</key>
+			<string></string>
+			<key>MaxInstances</key>
+			<string>n</string>
+			<key>Module</key>
+			<string>XCDockableInspector</string>
+			<key>Name</key>
+			<string>Inspector</string>
+		</dict>
+		<dict>
+			<key>BundleLoadPath</key>
+			<string></string>
+			<key>MaxInstances</key>
+			<string>n</string>
+			<key>Module</key>
+			<string>PBXOpenQuicklyModule</string>
+			<key>Name</key>
+			<string>Open Quickly Tool</string>
+		</dict>
+		<dict>
+			<key>BundleLoadPath</key>
+			<string></string>
+			<key>MaxInstances</key>
+			<string>1</string>
+			<key>Module</key>
+			<string>PBXDebugSessionModule</string>
+			<key>Name</key>
+			<string>Debugger</string>
+		</dict>
+		<dict>
+			<key>BundleLoadPath</key>
+			<string></string>
+			<key>MaxInstances</key>
+			<string>1</string>
+			<key>Module</key>
+			<string>PBXDebugCLIModule</string>
+			<key>Name</key>
+			<string>Debug Console</string>
+		</dict>
+		<dict>
+			<key>BundleLoadPath</key>
+			<string></string>
+			<key>MaxInstances</key>
+			<string>n</string>
+			<key>Module</key>
+			<string>XCSnapshotModule</string>
+			<key>Name</key>
+			<string>Snapshots Tool</string>
+		</dict>
+	</array>
+	<key>BundlePath</key>
+	<string>/Developer/Library/PrivateFrameworks/DevToolsInterface.framework/Resources</string>
+	<key>Description</key>
+	<string>DefaultDescriptionKey</string>
+	<key>DockingSystemVisible</key>
+	<false/>
+	<key>Extension</key>
+	<string>mode1v3</string>
+	<key>FavBarConfig</key>
+	<dict>
+		<key>PBXProjectModuleGUID</key>
+		<string>DACE785C111A1CAE00886DC9</string>
+		<key>XCBarModuleItemNames</key>
+		<dict/>
+		<key>XCBarModuleItems</key>
+		<array/>
+	</dict>
+	<key>FirstTimeWindowDisplayed</key>
+	<false/>
+	<key>Identifier</key>
+	<string>com.apple.perspectives.project.mode1v3</string>
+	<key>MajorVersion</key>
+	<integer>33</integer>
+	<key>MinorVersion</key>
+	<integer>0</integer>
+	<key>Name</key>
+	<string>Default</string>
+	<key>Notifications</key>
+	<array/>
+	<key>OpenEditors</key>
+	<array/>
+	<key>PerspectiveWidths</key>
+	<array>
+		<integer>-1</integer>
+		<integer>-1</integer>
+	</array>
+	<key>Perspectives</key>
+	<array>
+		<dict>
+			<key>ChosenToolbarItems</key>
+			<array>
+				<string>active-combo-popup</string>
+				<string>action</string>
+				<string>NSToolbarFlexibleSpaceItem</string>
+				<string>build-and-go</string>
+				<string>com.apple.ide.PBXToolbarStopButton</string>
+				<string>get-info</string>
+				<string>NSToolbarFlexibleSpaceItem</string>
+				<string>com.apple.pbx.toolbar.searchfield</string>
+			</array>
+			<key>ControllerClassBaseName</key>
+			<string></string>
+			<key>IconName</key>
+			<string>WindowOfProjectWithEditor</string>
+			<key>Identifier</key>
+			<string>perspective.project</string>
+			<key>IsVertical</key>
+			<false/>
+			<key>Layout</key>
+			<array>
+				<dict>
+					<key>BecomeActive</key>
+					<true/>
+					<key>ContentConfiguration</key>
+					<dict>
+						<key>PBXBottomSmartGroupGIDs</key>
+						<array>
+							<string>1C37FBAC04509CD000000102</string>
+							<string>1C37FAAC04509CD000000102</string>
+							<string>1C08E77C0454961000C914BD</string>
+							<string>1C37FABC05509CD000000102</string>
+							<string>1C37FABC05539CD112110102</string>
+							<string>E2644B35053B69B200211256</string>
+							<string>1C37FABC04509CD000100104</string>
+							<string>1CC0EA4004350EF90044410B</string>
+							<string>1CC0EA4004350EF90041110B</string>
+						</array>
+						<key>PBXProjectModuleGUID</key>
+						<string>1CE0B1FE06471DED0097A5F4</string>
+						<key>PBXProjectModuleLabel</key>
+						<string>Files</string>
+						<key>PBXProjectStructureProvided</key>
+						<string>yes</string>
+						<key>PBXSmartGroupTreeModuleColumnData</key>
+						<dict>
+							<key>PBXSmartGroupTreeModuleColumnWidthsKey</key>
+							<array>
+								<real>334</real>
+							</array>
+							<key>PBXSmartGroupTreeModuleColumnsKey_v4</key>
+							<array>
+								<string>MainColumn</string>
+							</array>
+						</dict>
+						<key>PBXSmartGroupTreeModuleOutlineStateKey_v7</key>
+						<dict>
+							<key>PBXSmartGroupTreeModuleOutlineStateExpansionKey</key>
+							<array>
+								<string>0259C574FE90428111CA0C5A</string>
+								<string>32DBCF9E0370C38000C91783</string>
+								<string>54D33B2406778DD400C9C163</string>
+								<string>54D33B2506778DF000C9C163</string>
+								<string>32DBCF9F0370C38200C91783</string>
+								<string>131E8FE8067F80F40006E0CE</string>
+								<string>54D33B2C06778E4400C9C163</string>
+								<string>C0894DA40C32F4C100401507</string>
+								<string>0259C582FE90428111CA0C5A</string>
+								<string>1ED78706FE9D4A0611CA0C5A</string>
+								<string>8D1AC9740486D14A00FE50C9</string>
+								<string>53DF68FD067E5B5A0090B5B0</string>
+								<string>2E58F364FFB232C311CA0CBA</string>
+								<string>1C37FBAC04509CD000000102</string>
+								<string>1C37FAAC04509CD000000102</string>
+								<string>1C37FABC05509CD000000102</string>
+								<string>E2644B35053B69B200211256</string>
+								<string>1CC0EA4004350EF90041110B</string>
+							</array>
+							<key>PBXSmartGroupTreeModuleOutlineStateSelectionKey</key>
+							<array>
+								<array>
+									<integer>0</integer>
+								</array>
+							</array>
+							<key>PBXSmartGroupTreeModuleOutlineStateVisibleRectKey</key>
+							<string>{{0, 0}, {334, 560}}</string>
+						</dict>
+						<key>PBXTopSmartGroupGIDs</key>
+						<array/>
+						<key>XCIncludePerspectivesSwitch</key>
+						<true/>
+						<key>XCSharingToken</key>
+						<string>com.apple.Xcode.GFSharingToken</string>
+					</dict>
+					<key>GeometryConfiguration</key>
+					<dict>
+						<key>Frame</key>
+						<string>{{0, 0}, {351, 578}}</string>
+						<key>GroupTreeTableConfiguration</key>
+						<array>
+							<string>MainColumn</string>
+							<real>334</real>
+						</array>
+						<key>RubberWindowFrame</key>
+						<string>177 236 1193 619 0 0 1440 878 </string>
+					</dict>
+					<key>Module</key>
+					<string>PBXSmartGroupTreeModule</string>
+					<key>Proportion</key>
+					<string>351pt</string>
+				</dict>
+				<dict>
+					<key>Dock</key>
+					<array>
+						<dict>
+							<key>ContentConfiguration</key>
+							<dict>
+								<key>PBXProjectModuleGUID</key>
+								<string>1CE0B20306471E060097A5F4</string>
+								<key>PBXProjectModuleLabel</key>
+								<string>LispController.m</string>
+								<key>PBXSplitModuleInNavigatorKey</key>
+								<dict>
+									<key>Split0</key>
+									<dict>
+										<key>PBXProjectModuleGUID</key>
+										<string>1CE0B20406471E060097A5F4</string>
+										<key>PBXProjectModuleLabel</key>
+										<string>LispController.m</string>
+										<key>_historyCapacity</key>
+										<integer>0</integer>
+										<key>bookmark</key>
+										<string>DA194E7E11836D8F004F4DD5</string>
+										<key>history</key>
+										<array>
+											<string>DACE7888111B58AD00886DC9</string>
+											<string>DACE78E1111B6CE800886DC9</string>
+											<string>DACE79AB111CBA2700886DC9</string>
+											<string>DAA87B08113EB3CD00F079CB</string>
+											<string>DAA87B09113EB3CD00F079CB</string>
+											<string>DAA87C1A11405E0900F079CB</string>
+											<string>DAA87C8A1141C10E00F079CB</string>
+											<string>DA59442C114D3A2B0078AFE8</string>
+											<string>DA59444C115508DC0078AFE8</string>
+											<string>DA59444E115508DC0078AFE8</string>
+											<string>DA59444F115508DC0078AFE8</string>
+											<string>DA279E051173F1E1003793F6</string>
+											<string>DA00DBC31178125F00587AEB</string>
+										</array>
+										<key>prevStack</key>
+										<array>
+											<string>DACE788C111B58AD00886DC9</string>
+											<string>DACE788D111B58AD00886DC9</string>
+											<string>DACE788E111B58AD00886DC9</string>
+											<string>DACE788F111B58AD00886DC9</string>
+											<string>DACE7890111B58AD00886DC9</string>
+											<string>DACE789A111B58AD00886DC9</string>
+											<string>DACE78EC111B6CE800886DC9</string>
+											<string>DACE78EE111B6CE800886DC9</string>
+											<string>DACE795E111C8D6E00886DC9</string>
+											<string>DACE7978111C8D6E00886DC9</string>
+											<string>DACE7982111C8D6E00886DC9</string>
+											<string>DACE79C2111CBA2700886DC9</string>
+											<string>DA47DC531121B0B30028C558</string>
+										</array>
+									</dict>
+									<key>SplitCount</key>
+									<string>1</string>
+								</dict>
+								<key>StatusBarVisibility</key>
+								<true/>
+							</dict>
+							<key>GeometryConfiguration</key>
+							<dict>
+								<key>Frame</key>
+								<string>{{0, 0}, {837, 400}}</string>
+								<key>RubberWindowFrame</key>
+								<string>177 236 1193 619 0 0 1440 878 </string>
+							</dict>
+							<key>Module</key>
+							<string>PBXNavigatorGroup</string>
+							<key>Proportion</key>
+							<string>400pt</string>
+						</dict>
+						<dict>
+							<key>ContentConfiguration</key>
+							<dict>
+								<key>PBXProjectModuleGUID</key>
+								<string>1CE0B20506471E060097A5F4</string>
+								<key>PBXProjectModuleLabel</key>
+								<string>Detail</string>
+							</dict>
+							<key>GeometryConfiguration</key>
+							<dict>
+								<key>Frame</key>
+								<string>{{0, 405}, {837, 173}}</string>
+								<key>RubberWindowFrame</key>
+								<string>177 236 1193 619 0 0 1440 878 </string>
+							</dict>
+							<key>Module</key>
+							<string>XCDetailModule</string>
+							<key>Proportion</key>
+							<string>173pt</string>
+						</dict>
+					</array>
+					<key>Proportion</key>
+					<string>837pt</string>
+				</dict>
+			</array>
+			<key>Name</key>
+			<string>Project</string>
+			<key>ServiceClasses</key>
+			<array>
+				<string>XCModuleDock</string>
+				<string>PBXSmartGroupTreeModule</string>
+				<string>XCModuleDock</string>
+				<string>PBXNavigatorGroup</string>
+				<string>XCDetailModule</string>
+			</array>
+			<key>TableOfContents</key>
+			<array>
+				<string>DA194E7511836D8F004F4DD5</string>
+				<string>1CE0B1FE06471DED0097A5F4</string>
+				<string>DA194E7611836D8F004F4DD5</string>
+				<string>1CE0B20306471E060097A5F4</string>
+				<string>1CE0B20506471E060097A5F4</string>
+			</array>
+			<key>ToolbarConfiguration</key>
+			<string>xcode.toolbar.config.defaultV3</string>
+		</dict>
+		<dict>
+			<key>ControllerClassBaseName</key>
+			<string></string>
+			<key>IconName</key>
+			<string>WindowOfProject</string>
+			<key>Identifier</key>
+			<string>perspective.morph</string>
+			<key>IsVertical</key>
+			<integer>0</integer>
+			<key>Layout</key>
+			<array>
+				<dict>
+					<key>BecomeActive</key>
+					<integer>1</integer>
+					<key>ContentConfiguration</key>
+					<dict>
+						<key>PBXBottomSmartGroupGIDs</key>
+						<array>
+							<string>1C37FBAC04509CD000000102</string>
+							<string>1C37FAAC04509CD000000102</string>
+							<string>1C08E77C0454961000C914BD</string>
+							<string>1C37FABC05509CD000000102</string>
+							<string>1C37FABC05539CD112110102</string>
+							<string>E2644B35053B69B200211256</string>
+							<string>1C37FABC04509CD000100104</string>
+							<string>1CC0EA4004350EF90044410B</string>
+							<string>1CC0EA4004350EF90041110B</string>
+						</array>
+						<key>PBXProjectModuleGUID</key>
+						<string>11E0B1FE06471DED0097A5F4</string>
+						<key>PBXProjectModuleLabel</key>
+						<string>Files</string>
+						<key>PBXProjectStructureProvided</key>
+						<string>yes</string>
+						<key>PBXSmartGroupTreeModuleColumnData</key>
+						<dict>
+							<key>PBXSmartGroupTreeModuleColumnWidthsKey</key>
+							<array>
+								<real>186</real>
+							</array>
+							<key>PBXSmartGroupTreeModuleColumnsKey_v4</key>
+							<array>
+								<string>MainColumn</string>
+							</array>
+						</dict>
+						<key>PBXSmartGroupTreeModuleOutlineStateKey_v7</key>
+						<dict>
+							<key>PBXSmartGroupTreeModuleOutlineStateExpansionKey</key>
+							<array>
+								<string>29B97314FDCFA39411CA2CEA</string>
+								<string>1C37FABC05509CD000000102</string>
+							</array>
+							<key>PBXSmartGroupTreeModuleOutlineStateSelectionKey</key>
+							<array>
+								<array>
+									<integer>0</integer>
+								</array>
+							</array>
+							<key>PBXSmartGroupTreeModuleOutlineStateVisibleRectKey</key>
+							<string>{{0, 0}, {186, 337}}</string>
+						</dict>
+						<key>PBXTopSmartGroupGIDs</key>
+						<array/>
+						<key>XCIncludePerspectivesSwitch</key>
+						<integer>1</integer>
+						<key>XCSharingToken</key>
+						<string>com.apple.Xcode.GFSharingToken</string>
+					</dict>
+					<key>GeometryConfiguration</key>
+					<dict>
+						<key>Frame</key>
+						<string>{{0, 0}, {203, 355}}</string>
+						<key>GroupTreeTableConfiguration</key>
+						<array>
+							<string>MainColumn</string>
+							<real>186</real>
+						</array>
+						<key>RubberWindowFrame</key>
+						<string>373 269 690 397 0 0 1440 878 </string>
+					</dict>
+					<key>Module</key>
+					<string>PBXSmartGroupTreeModule</string>
+					<key>Proportion</key>
+					<string>100%</string>
+				</dict>
+			</array>
+			<key>Name</key>
+			<string>Morph</string>
+			<key>PreferredWidth</key>
+			<integer>300</integer>
+			<key>ServiceClasses</key>
+			<array>
+				<string>XCModuleDock</string>
+				<string>PBXSmartGroupTreeModule</string>
+			</array>
+			<key>TableOfContents</key>
+			<array>
+				<string>11E0B1FE06471DED0097A5F4</string>
+			</array>
+			<key>ToolbarConfiguration</key>
+			<string>xcode.toolbar.config.default.shortV3</string>
+		</dict>
+	</array>
+	<key>PerspectivesBarVisible</key>
+	<false/>
+	<key>ShelfIsVisible</key>
+	<false/>
+	<key>SourceDescription</key>
+	<string>file at '/Developer/Library/PrivateFrameworks/DevToolsInterface.framework/Resources/XCPerspectivesSpecificationMode1.xcperspec'</string>
+	<key>StatusbarIsVisible</key>
+	<true/>
+	<key>TimeStamp</key>
+	<real>0.0</real>
+	<key>ToolbarDisplayMode</key>
+	<integer>1</integer>
+	<key>ToolbarIsVisible</key>
+	<true/>
+	<key>ToolbarSizeMode</key>
+	<integer>1</integer>
+	<key>Type</key>
+	<string>Perspectives</string>
+	<key>UpdateMessage</key>
+	<string>The Default Workspace in this version of Xcode now includes support to hide and show the detail view (what has been referred to as the "Metro-Morph" feature).  You must discard your current Default Workspace settings and update to the latest Default Workspace in order to gain this feature.  Do you wish to update to the latest Workspace defaults for project '%@'?</string>
+	<key>WindowJustification</key>
+	<integer>5</integer>
+	<key>WindowOrderList</key>
+	<array>
+		<string>DACE789C111B58AD00886DC9</string>
+		<string>1CD10A99069EF8BA00B06720</string>
+		<string>/Applications/ccl/contrib/krueger/InterfaceProjects/Lisp IB Plugins/LispControllerPlugin/LispControllerPlugin.xcodeproj</string>
+	</array>
+	<key>WindowString</key>
+	<string>177 236 1193 619 0 0 1440 878 </string>
+	<key>WindowToolsV3</key>
+	<array>
+		<dict>
+			<key>FirstTimeWindowDisplayed</key>
+			<false/>
+			<key>Identifier</key>
+			<string>windowTool.build</string>
+			<key>IsVertical</key>
+			<true/>
+			<key>Layout</key>
+			<array>
+				<dict>
+					<key>Dock</key>
+					<array>
+						<dict>
+							<key>ContentConfiguration</key>
+							<dict>
+								<key>PBXProjectModuleGUID</key>
+								<string>1CD0528F0623707200166675</string>
+								<key>PBXProjectModuleLabel</key>
+								<string></string>
+								<key>StatusBarVisibility</key>
+								<true/>
+							</dict>
+							<key>GeometryConfiguration</key>
+							<dict>
+								<key>Frame</key>
+								<string>{{0, 0}, {875, 189}}</string>
+								<key>RubberWindowFrame</key>
+								<string>34 173 875 471 0 0 1440 878 </string>
+							</dict>
+							<key>Module</key>
+							<string>PBXNavigatorGroup</string>
+							<key>Proportion</key>
+							<string>189pt</string>
+						</dict>
+						<dict>
+							<key>ContentConfiguration</key>
+							<dict>
+								<key>PBXProjectModuleGUID</key>
+								<string>XCMainBuildResultsModuleGUID</string>
+								<key>PBXProjectModuleLabel</key>
+								<string>Build</string>
+								<key>XCBuildResultsTrigger_Collapse</key>
+								<integer>1021</integer>
+								<key>XCBuildResultsTrigger_Open</key>
+								<integer>1011</integer>
+							</dict>
+							<key>GeometryConfiguration</key>
+							<dict>
+								<key>Frame</key>
+								<string>{{0, 194}, {875, 236}}</string>
+								<key>RubberWindowFrame</key>
+								<string>34 173 875 471 0 0 1440 878 </string>
+							</dict>
+							<key>Module</key>
+							<string>PBXBuildResultsModule</string>
+							<key>Proportion</key>
+							<string>236pt</string>
+						</dict>
+					</array>
+					<key>Proportion</key>
+					<string>430pt</string>
+				</dict>
+			</array>
+			<key>Name</key>
+			<string>Build Results</string>
+			<key>ServiceClasses</key>
+			<array>
+				<string>PBXBuildResultsModule</string>
+			</array>
+			<key>StatusbarIsVisible</key>
+			<true/>
+			<key>TableOfContents</key>
+			<array>
+				<string>DACE789C111B58AD00886DC9</string>
+				<string>DA194E7711836D8F004F4DD5</string>
+				<string>1CD0528F0623707200166675</string>
+				<string>XCMainBuildResultsModuleGUID</string>
+			</array>
+			<key>ToolbarConfiguration</key>
+			<string>xcode.toolbar.config.buildV3</string>
+			<key>WindowString</key>
+			<string>34 173 875 471 0 0 1440 878 </string>
+			<key>WindowToolGUID</key>
+			<string>DACE789C111B58AD00886DC9</string>
+			<key>WindowToolIsVisible</key>
+			<false/>
+		</dict>
+		<dict>
+			<key>FirstTimeWindowDisplayed</key>
+			<false/>
+			<key>Identifier</key>
+			<string>windowTool.debugger</string>
+			<key>IsVertical</key>
+			<true/>
+			<key>Layout</key>
+			<array>
+				<dict>
+					<key>Dock</key>
+					<array>
+						<dict>
+							<key>ContentConfiguration</key>
+							<dict>
+								<key>Debugger</key>
+								<dict>
+									<key>HorizontalSplitView</key>
+									<dict>
+										<key>_collapsingFrameDimension</key>
+										<real>0.0</real>
+										<key>_indexOfCollapsedView</key>
+										<integer>0</integer>
+										<key>_percentageOfCollapsedView</key>
+										<real>0.0</real>
+										<key>isCollapsed</key>
+										<string>yes</string>
+										<key>sizes</key>
+										<array>
+											<string>{{0, 0}, {316, 203}}</string>
+											<string>{{316, 0}, {378, 203}}</string>
+										</array>
+									</dict>
+									<key>VerticalSplitView</key>
+									<dict>
+										<key>_collapsingFrameDimension</key>
+										<real>0.0</real>
+										<key>_indexOfCollapsedView</key>
+										<integer>0</integer>
+										<key>_percentageOfCollapsedView</key>
+										<real>0.0</real>
+										<key>isCollapsed</key>
+										<string>yes</string>
+										<key>sizes</key>
+										<array>
+											<string>{{0, 0}, {694, 203}}</string>
+											<string>{{0, 203}, {694, 178}}</string>
+										</array>
+									</dict>
+								</dict>
+								<key>LauncherConfigVersion</key>
+								<string>8</string>
+								<key>PBXProjectModuleGUID</key>
+								<string>1C162984064C10D400B95A72</string>
+								<key>PBXProjectModuleLabel</key>
+								<string>Debug - GLUTExamples (Underwater)</string>
+							</dict>
+							<key>GeometryConfiguration</key>
+							<dict>
+								<key>DebugConsoleVisible</key>
+								<string>None</string>
+								<key>DebugConsoleWindowFrame</key>
+								<string>{{200, 200}, {500, 300}}</string>
+								<key>DebugSTDIOWindowFrame</key>
+								<string>{{200, 200}, {500, 300}}</string>
+								<key>Frame</key>
+								<string>{{0, 0}, {694, 381}}</string>
+								<key>PBXDebugSessionStackFrameViewKey</key>
+								<dict>
+									<key>DebugVariablesTableConfiguration</key>
+									<array>
+										<string>Name</string>
+										<real>120</real>
+										<string>Value</string>
+										<real>85</real>
+										<string>Summary</string>
+										<real>148</real>
+									</array>
+									<key>Frame</key>
+									<string>{{316, 0}, {378, 203}}</string>
+									<key>RubberWindowFrame</key>
+									<string>347 365 694 422 0 0 1440 878 </string>
+								</dict>
+								<key>RubberWindowFrame</key>
+								<string>347 365 694 422 0 0 1440 878 </string>
+							</dict>
+							<key>Module</key>
+							<string>PBXDebugSessionModule</string>
+							<key>Proportion</key>
+							<string>381pt</string>
+						</dict>
+					</array>
+					<key>Proportion</key>
+					<string>381pt</string>
+				</dict>
+			</array>
+			<key>Name</key>
+			<string>Debugger</string>
+			<key>ServiceClasses</key>
+			<array>
+				<string>PBXDebugSessionModule</string>
+			</array>
+			<key>StatusbarIsVisible</key>
+			<true/>
+			<key>TableOfContents</key>
+			<array>
+				<string>1CD10A99069EF8BA00B06720</string>
+				<string>DA194E7811836D8F004F4DD5</string>
+				<string>1C162984064C10D400B95A72</string>
+				<string>DA194E7911836D8F004F4DD5</string>
+				<string>DA194E7A11836D8F004F4DD5</string>
+				<string>DA194E7B11836D8F004F4DD5</string>
+				<string>DA194E7C11836D8F004F4DD5</string>
+				<string>DA194E7D11836D8F004F4DD5</string>
+			</array>
+			<key>ToolbarConfiguration</key>
+			<string>xcode.toolbar.config.debugV3</string>
+			<key>WindowString</key>
+			<string>347 365 694 422 0 0 1440 878 </string>
+			<key>WindowToolGUID</key>
+			<string>1CD10A99069EF8BA00B06720</string>
+			<key>WindowToolIsVisible</key>
+			<false/>
+		</dict>
+		<dict>
+			<key>Identifier</key>
+			<string>windowTool.find</string>
+			<key>Layout</key>
+			<array>
+				<dict>
+					<key>Dock</key>
+					<array>
+						<dict>
+							<key>Dock</key>
+							<array>
+								<dict>
+									<key>ContentConfiguration</key>
+									<dict>
+										<key>PBXProjectModuleGUID</key>
+										<string>1CDD528C0622207200134675</string>
+										<key>PBXProjectModuleLabel</key>
+										<string>&lt;No Editor&gt;</string>
+										<key>PBXSplitModuleInNavigatorKey</key>
+										<dict>
+											<key>Split0</key>
+											<dict>
+												<key>PBXProjectModuleGUID</key>
+												<string>1CD0528D0623707200166675</string>
+											</dict>
+											<key>SplitCount</key>
+											<string>1</string>
+										</dict>
+										<key>StatusBarVisibility</key>
+										<integer>1</integer>
+									</dict>
+									<key>GeometryConfiguration</key>
+									<dict>
+										<key>Frame</key>
+										<string>{{0, 0}, {781, 167}}</string>
+										<key>RubberWindowFrame</key>
+										<string>62 385 781 470 0 0 1440 878 </string>
+									</dict>
+									<key>Module</key>
+									<string>PBXNavigatorGroup</string>
+									<key>Proportion</key>
+									<string>781pt</string>
+								</dict>
+							</array>
+							<key>Proportion</key>
+							<string>50%</string>
+						</dict>
+						<dict>
+							<key>BecomeActive</key>
+							<integer>1</integer>
+							<key>ContentConfiguration</key>
+							<dict>
+								<key>PBXProjectModuleGUID</key>
+								<string>1CD0528E0623707200166675</string>
+								<key>PBXProjectModuleLabel</key>
+								<string>Project Find</string>
+							</dict>
+							<key>GeometryConfiguration</key>
+							<dict>
+								<key>Frame</key>
+								<string>{{8, 0}, {773, 254}}</string>
+								<key>RubberWindowFrame</key>
+								<string>62 385 781 470 0 0 1440 878 </string>
+							</dict>
+							<key>Module</key>
+							<string>PBXProjectFindModule</string>
+							<key>Proportion</key>
+							<string>50%</string>
+						</dict>
+					</array>
+					<key>Proportion</key>
+					<string>428pt</string>
+				</dict>
+			</array>
+			<key>Name</key>
+			<string>Project Find</string>
+			<key>ServiceClasses</key>
+			<array>
+				<string>PBXProjectFindModule</string>
+			</array>
+			<key>StatusbarIsVisible</key>
+			<integer>1</integer>
+			<key>TableOfContents</key>
+			<array>
+				<string>1C530D57069F1CE1000CFCEE</string>
+				<string>1C530D58069F1CE1000CFCEE</string>
+				<string>1C530D59069F1CE1000CFCEE</string>
+				<string>1CDD528C0622207200134675</string>
+				<string>1C530D5A069F1CE1000CFCEE</string>
+				<string>1CE0B1FE06471DED0097A5F4</string>
+				<string>1CD0528E0623707200166675</string>
+			</array>
+			<key>WindowString</key>
+			<string>62 385 781 470 0 0 1440 878 </string>
+			<key>WindowToolGUID</key>
+			<string>1C530D57069F1CE1000CFCEE</string>
+			<key>WindowToolIsVisible</key>
+			<integer>0</integer>
+		</dict>
+		<dict>
+			<key>Identifier</key>
+			<string>MENUSEPARATOR</string>
+		</dict>
+		<dict>
+			<key>FirstTimeWindowDisplayed</key>
+			<false/>
+			<key>Identifier</key>
+			<string>windowTool.debuggerConsole</string>
+			<key>IsVertical</key>
+			<true/>
+			<key>Layout</key>
+			<array>
+				<dict>
+					<key>Dock</key>
+					<array>
+						<dict>
+							<key>BecomeActive</key>
+							<true/>
+							<key>ContentConfiguration</key>
+							<dict>
+								<key>PBXProjectModuleGUID</key>
+								<string>1C78EAAC065D492600B07095</string>
+								<key>PBXProjectModuleLabel</key>
+								<string>Debugger Console</string>
+							</dict>
+							<key>GeometryConfiguration</key>
+							<dict>
+								<key>Frame</key>
+								<string>{{0, 0}, {765, 512}}</string>
+								<key>RubberWindowFrame</key>
+								<string>35 120 765 553 0 0 1440 878 </string>
+							</dict>
+							<key>Module</key>
+							<string>PBXDebugCLIModule</string>
+							<key>Proportion</key>
+							<string>512pt</string>
+						</dict>
+					</array>
+					<key>Proportion</key>
+					<string>512pt</string>
+				</dict>
+			</array>
+			<key>Name</key>
+			<string>Debugger Console</string>
+			<key>ServiceClasses</key>
+			<array>
+				<string>PBXDebugCLIModule</string>
+			</array>
+			<key>StatusbarIsVisible</key>
+			<true/>
+			<key>TableOfContents</key>
+			<array>
+				<string>1C78EAAD065D492600B07095</string>
+				<string>DA59443E114D3A2B0078AFE8</string>
+				<string>1C78EAAC065D492600B07095</string>
+			</array>
+			<key>ToolbarConfiguration</key>
+			<string>xcode.toolbar.config.consoleV3</string>
+			<key>WindowString</key>
+			<string>35 120 765 553 0 0 1440 878 </string>
+			<key>WindowToolGUID</key>
+			<string>1C78EAAD065D492600B07095</string>
+			<key>WindowToolIsVisible</key>
+			<true/>
+		</dict>
+		<dict>
+			<key>Identifier</key>
+			<string>windowTool.snapshots</string>
+			<key>Layout</key>
+			<array>
+				<dict>
+					<key>Dock</key>
+					<array>
+						<dict>
+							<key>Module</key>
+							<string>XCSnapshotModule</string>
+							<key>Proportion</key>
+							<string>100%</string>
+						</dict>
+					</array>
+					<key>Proportion</key>
+					<string>100%</string>
+				</dict>
+			</array>
+			<key>Name</key>
+			<string>Snapshots</string>
+			<key>ServiceClasses</key>
+			<array>
+				<string>XCSnapshotModule</string>
+			</array>
+			<key>StatusbarIsVisible</key>
+			<string>Yes</string>
+			<key>ToolbarConfiguration</key>
+			<string>xcode.toolbar.config.snapshots</string>
+			<key>WindowString</key>
+			<string>315 824 300 550 0 0 1440 878 </string>
+			<key>WindowToolIsVisible</key>
+			<string>Yes</string>
+		</dict>
+		<dict>
+			<key>Identifier</key>
+			<string>windowTool.scm</string>
+			<key>Layout</key>
+			<array>
+				<dict>
+					<key>Dock</key>
+					<array>
+						<dict>
+							<key>ContentConfiguration</key>
+							<dict>
+								<key>PBXProjectModuleGUID</key>
+								<string>1C78EAB2065D492600B07095</string>
+								<key>PBXProjectModuleLabel</key>
+								<string>&lt;No Editor&gt;</string>
+								<key>PBXSplitModuleInNavigatorKey</key>
+								<dict>
+									<key>Split0</key>
+									<dict>
+										<key>PBXProjectModuleGUID</key>
+										<string>1C78EAB3065D492600B07095</string>
+									</dict>
+									<key>SplitCount</key>
+									<string>1</string>
+								</dict>
+								<key>StatusBarVisibility</key>
+								<integer>1</integer>
+							</dict>
+							<key>GeometryConfiguration</key>
+							<dict>
+								<key>Frame</key>
+								<string>{{0, 0}, {452, 0}}</string>
+								<key>RubberWindowFrame</key>
+								<string>743 379 452 308 0 0 1280 1002 </string>
+							</dict>
+							<key>Module</key>
+							<string>PBXNavigatorGroup</string>
+							<key>Proportion</key>
+							<string>0pt</string>
+						</dict>
+						<dict>
+							<key>BecomeActive</key>
+							<integer>1</integer>
+							<key>ContentConfiguration</key>
+							<dict>
+								<key>PBXProjectModuleGUID</key>
+								<string>1CD052920623707200166675</string>
+								<key>PBXProjectModuleLabel</key>
+								<string>SCM</string>
+							</dict>
+							<key>GeometryConfiguration</key>
+							<dict>
+								<key>ConsoleFrame</key>
+								<string>{{0, 259}, {452, 0}}</string>
+								<key>Frame</key>
+								<string>{{0, 7}, {452, 259}}</string>
+								<key>RubberWindowFrame</key>
+								<string>743 379 452 308 0 0 1280 1002 </string>
+								<key>TableConfiguration</key>
+								<array>
+									<string>Status</string>
+									<real>30</real>
+									<string>FileName</string>
+									<real>199</real>
+									<string>Path</string>
+									<real>197.0950012207031</real>
+								</array>
+								<key>TableFrame</key>
+								<string>{{0, 0}, {452, 250}}</string>
+							</dict>
+							<key>Module</key>
+							<string>PBXCVSModule</string>
+							<key>Proportion</key>
+							<string>262pt</string>
+						</dict>
+					</array>
+					<key>Proportion</key>
+					<string>266pt</string>
+				</dict>
+			</array>
+			<key>Name</key>
+			<string>SCM</string>
+			<key>ServiceClasses</key>
+			<array>
+				<string>PBXCVSModule</string>
+			</array>
+			<key>StatusbarIsVisible</key>
+			<integer>1</integer>
+			<key>TableOfContents</key>
+			<array>
+				<string>1C78EAB4065D492600B07095</string>
+				<string>1C78EAB5065D492600B07095</string>
+				<string>1C78EAB2065D492600B07095</string>
+				<string>1CD052920623707200166675</string>
+			</array>
+			<key>ToolbarConfiguration</key>
+			<string>xcode.toolbar.config.scm</string>
+			<key>WindowString</key>
+			<string>743 379 452 308 0 0 1280 1002 </string>
+		</dict>
+		<dict>
+			<key>Identifier</key>
+			<string>windowTool.breakpoints</string>
+			<key>IsVertical</key>
+			<integer>0</integer>
+			<key>Layout</key>
+			<array>
+				<dict>
+					<key>Dock</key>
+					<array>
+						<dict>
+							<key>BecomeActive</key>
+							<integer>1</integer>
+							<key>ContentConfiguration</key>
+							<dict>
+								<key>PBXBottomSmartGroupGIDs</key>
+								<array>
+									<string>1C77FABC04509CD000000102</string>
+								</array>
+								<key>PBXProjectModuleGUID</key>
+								<string>1CE0B1FE06471DED0097A5F4</string>
+								<key>PBXProjectModuleLabel</key>
+								<string>Files</string>
+								<key>PBXProjectStructureProvided</key>
+								<string>no</string>
+								<key>PBXSmartGroupTreeModuleColumnData</key>
+								<dict>
+									<key>PBXSmartGroupTreeModuleColumnWidthsKey</key>
+									<array>
+										<real>168</real>
+									</array>
+									<key>PBXSmartGroupTreeModuleColumnsKey_v4</key>
+									<array>
+										<string>MainColumn</string>
+									</array>
+								</dict>
+								<key>PBXSmartGroupTreeModuleOutlineStateKey_v7</key>
+								<dict>
+									<key>PBXSmartGroupTreeModuleOutlineStateExpansionKey</key>
+									<array>
+										<string>1C77FABC04509CD000000102</string>
+									</array>
+									<key>PBXSmartGroupTreeModuleOutlineStateSelectionKey</key>
+									<array>
+										<array>
+											<integer>0</integer>
+										</array>
+									</array>
+									<key>PBXSmartGroupTreeModuleOutlineStateVisibleRectKey</key>
+									<string>{{0, 0}, {168, 350}}</string>
+								</dict>
+								<key>PBXTopSmartGroupGIDs</key>
+								<array/>
+								<key>XCIncludePerspectivesSwitch</key>
+								<integer>0</integer>
+							</dict>
+							<key>GeometryConfiguration</key>
+							<dict>
+								<key>Frame</key>
+								<string>{{0, 0}, {185, 368}}</string>
+								<key>GroupTreeTableConfiguration</key>
+								<array>
+									<string>MainColumn</string>
+									<real>168</real>
+								</array>
+								<key>RubberWindowFrame</key>
+								<string>315 424 744 409 0 0 1440 878 </string>
+							</dict>
+							<key>Module</key>
+							<string>PBXSmartGroupTreeModule</string>
+							<key>Proportion</key>
+							<string>185pt</string>
+						</dict>
+						<dict>
+							<key>ContentConfiguration</key>
+							<dict>
+								<key>PBXProjectModuleGUID</key>
+								<string>1CA1AED706398EBD00589147</string>
+								<key>PBXProjectModuleLabel</key>
+								<string>Detail</string>
+							</dict>
+							<key>GeometryConfiguration</key>
+							<dict>
+								<key>Frame</key>
+								<string>{{190, 0}, {554, 368}}</string>
+								<key>RubberWindowFrame</key>
+								<string>315 424 744 409 0 0 1440 878 </string>
+							</dict>
+							<key>Module</key>
+							<string>XCDetailModule</string>
+							<key>Proportion</key>
+							<string>554pt</string>
+						</dict>
+					</array>
+					<key>Proportion</key>
+					<string>368pt</string>
+				</dict>
+			</array>
+			<key>MajorVersion</key>
+			<integer>3</integer>
+			<key>MinorVersion</key>
+			<integer>0</integer>
+			<key>Name</key>
+			<string>Breakpoints</string>
+			<key>ServiceClasses</key>
+			<array>
+				<string>PBXSmartGroupTreeModule</string>
+				<string>XCDetailModule</string>
+			</array>
+			<key>StatusbarIsVisible</key>
+			<integer>1</integer>
+			<key>TableOfContents</key>
+			<array>
+				<string>1CDDB66807F98D9800BB5817</string>
+				<string>1CDDB66907F98D9800BB5817</string>
+				<string>1CE0B1FE06471DED0097A5F4</string>
+				<string>1CA1AED706398EBD00589147</string>
+			</array>
+			<key>ToolbarConfiguration</key>
+			<string>xcode.toolbar.config.breakpointsV3</string>
+			<key>WindowString</key>
+			<string>315 424 744 409 0 0 1440 878 </string>
+			<key>WindowToolGUID</key>
+			<string>1CDDB66807F98D9800BB5817</string>
+			<key>WindowToolIsVisible</key>
+			<integer>1</integer>
+		</dict>
+		<dict>
+			<key>Identifier</key>
+			<string>windowTool.debugAnimator</string>
+			<key>Layout</key>
+			<array>
+				<dict>
+					<key>Dock</key>
+					<array>
+						<dict>
+							<key>Module</key>
+							<string>PBXNavigatorGroup</string>
+							<key>Proportion</key>
+							<string>100%</string>
+						</dict>
+					</array>
+					<key>Proportion</key>
+					<string>100%</string>
+				</dict>
+			</array>
+			<key>Name</key>
+			<string>Debug Visualizer</string>
+			<key>ServiceClasses</key>
+			<array>
+				<string>PBXNavigatorGroup</string>
+			</array>
+			<key>StatusbarIsVisible</key>
+			<integer>1</integer>
+			<key>ToolbarConfiguration</key>
+			<string>xcode.toolbar.config.debugAnimatorV3</string>
+			<key>WindowString</key>
+			<string>100 100 700 500 0 0 1280 1002 </string>
+		</dict>
+		<dict>
+			<key>Identifier</key>
+			<string>windowTool.bookmarks</string>
+			<key>Layout</key>
+			<array>
+				<dict>
+					<key>Dock</key>
+					<array>
+						<dict>
+							<key>Module</key>
+							<string>PBXBookmarksModule</string>
+							<key>Proportion</key>
+							<string>100%</string>
+						</dict>
+					</array>
+					<key>Proportion</key>
+					<string>100%</string>
+				</dict>
+			</array>
+			<key>Name</key>
+			<string>Bookmarks</string>
+			<key>ServiceClasses</key>
+			<array>
+				<string>PBXBookmarksModule</string>
+			</array>
+			<key>StatusbarIsVisible</key>
+			<integer>0</integer>
+			<key>WindowString</key>
+			<string>538 42 401 187 0 0 1280 1002 </string>
+		</dict>
+		<dict>
+			<key>Identifier</key>
+			<string>windowTool.projectFormatConflicts</string>
+			<key>Layout</key>
+			<array>
+				<dict>
+					<key>Dock</key>
+					<array>
+						<dict>
+							<key>Module</key>
+							<string>XCProjectFormatConflictsModule</string>
+							<key>Proportion</key>
+							<string>100%</string>
+						</dict>
+					</array>
+					<key>Proportion</key>
+					<string>100%</string>
+				</dict>
+			</array>
+			<key>Name</key>
+			<string>Project Format Conflicts</string>
+			<key>ServiceClasses</key>
+			<array>
+				<string>XCProjectFormatConflictsModule</string>
+			</array>
+			<key>StatusbarIsVisible</key>
+			<integer>0</integer>
+			<key>WindowContentMinSize</key>
+			<string>450 300</string>
+			<key>WindowString</key>
+			<string>50 850 472 307 0 0 1440 877</string>
+		</dict>
+		<dict>
+			<key>Identifier</key>
+			<string>windowTool.classBrowser</string>
+			<key>Layout</key>
+			<array>
+				<dict>
+					<key>Dock</key>
+					<array>
+						<dict>
+							<key>BecomeActive</key>
+							<integer>1</integer>
+							<key>ContentConfiguration</key>
+							<dict>
+								<key>OptionsSetName</key>
+								<string>Hierarchy, all classes</string>
+								<key>PBXProjectModuleGUID</key>
+								<string>1CA6456E063B45B4001379D8</string>
+								<key>PBXProjectModuleLabel</key>
+								<string>Class Browser - NSObject</string>
+							</dict>
+							<key>GeometryConfiguration</key>
+							<dict>
+								<key>ClassesFrame</key>
+								<string>{{0, 0}, {374, 96}}</string>
+								<key>ClassesTreeTableConfiguration</key>
+								<array>
+									<string>PBXClassNameColumnIdentifier</string>
+									<real>208</real>
+									<string>PBXClassBookColumnIdentifier</string>
+									<real>22</real>
+								</array>
+								<key>Frame</key>
+								<string>{{0, 0}, {630, 331}}</string>
+								<key>MembersFrame</key>
+								<string>{{0, 105}, {374, 395}}</string>
+								<key>MembersTreeTableConfiguration</key>
+								<array>
+									<string>PBXMemberTypeIconColumnIdentifier</string>
+									<real>22</real>
+									<string>PBXMemberNameColumnIdentifier</string>
+									<real>216</real>
+									<string>PBXMemberTypeColumnIdentifier</string>
+									<real>97</real>
+									<string>PBXMemberBookColumnIdentifier</string>
+									<real>22</real>
+								</array>
+								<key>PBXModuleWindowStatusBarHidden2</key>
+								<integer>1</integer>
+								<key>RubberWindowFrame</key>
+								<string>385 179 630 352 0 0 1440 878 </string>
+							</dict>
+							<key>Module</key>
+							<string>PBXClassBrowserModule</string>
+							<key>Proportion</key>
+							<string>332pt</string>
+						</dict>
+					</array>
+					<key>Proportion</key>
+					<string>332pt</string>
+				</dict>
+			</array>
+			<key>Name</key>
+			<string>Class Browser</string>
+			<key>ServiceClasses</key>
+			<array>
+				<string>PBXClassBrowserModule</string>
+			</array>
+			<key>StatusbarIsVisible</key>
+			<integer>0</integer>
+			<key>TableOfContents</key>
+			<array>
+				<string>1C0AD2AF069F1E9B00FABCE6</string>
+				<string>1C0AD2B0069F1E9B00FABCE6</string>
+				<string>1CA6456E063B45B4001379D8</string>
+			</array>
+			<key>ToolbarConfiguration</key>
+			<string>xcode.toolbar.config.classbrowser</string>
+			<key>WindowString</key>
+			<string>385 179 630 352 0 0 1440 878 </string>
+			<key>WindowToolGUID</key>
+			<string>1C0AD2AF069F1E9B00FABCE6</string>
+			<key>WindowToolIsVisible</key>
+			<integer>0</integer>
+		</dict>
+		<dict>
+			<key>Identifier</key>
+			<string>windowTool.refactoring</string>
+			<key>IncludeInToolsMenu</key>
+			<integer>0</integer>
+			<key>Layout</key>
+			<array>
+				<dict>
+					<key>Dock</key>
+					<array>
+						<dict>
+							<key>BecomeActive</key>
+							<integer>1</integer>
+							<key>GeometryConfiguration</key>
+							<dict>
+								<key>Frame</key>
+								<string>{0, 0}, {500, 335}</string>
+								<key>RubberWindowFrame</key>
+								<string>{0, 0}, {500, 335}</string>
+							</dict>
+							<key>Module</key>
+							<string>XCRefactoringModule</string>
+							<key>Proportion</key>
+							<string>100%</string>
+						</dict>
+					</array>
+					<key>Proportion</key>
+					<string>100%</string>
+				</dict>
+			</array>
+			<key>Name</key>
+			<string>Refactoring</string>
+			<key>ServiceClasses</key>
+			<array>
+				<string>XCRefactoringModule</string>
+			</array>
+			<key>WindowString</key>
+			<string>200 200 500 356 0 0 1920 1200 </string>
+		</dict>
+	</array>
+</dict>
+</plist>
Index: /trunk/contrib/krueger/InterfaceProjects/Lisp IB Plugins/LispControllerPlugin/LispControllerPlugin.xcodeproj/paul.pbxuser
===================================================================
--- /trunk/contrib/krueger/InterfaceProjects/Lisp IB Plugins/LispControllerPlugin/LispControllerPlugin.xcodeproj/paul.pbxuser	(revision 13946)
+++ /trunk/contrib/krueger/InterfaceProjects/Lisp IB Plugins/LispControllerPlugin/LispControllerPlugin.xcodeproj/paul.pbxuser	(revision 13946)
@@ -0,0 +1,573 @@
+// !$*UTF8*$!
+{
+	0259C573FE90428111CA0C5A /* Project object */ = {
+		activeBuildConfigurationName = Release;
+		activeExecutable = C096A9340C03CEAB00263BB0 /* Interface Builder */;
+		activeTarget = 53DF6901067E5B8E0090B5B0 /* All */;
+		addToTargets = (
+			8D1AC9600486D14A00FE50C9 /* LispControllerPlugin */,
+		);
+		codeSenseManager = C096A9330C03CEA700263BB0 /* Code sense */;
+		executables = (
+			C096A9340C03CEAB00263BB0 /* Interface Builder */,
+		);
+		perUserDictionary = {
+			PBXConfiguration.PBXFileTableDataSource3.PBXExecutablesDataSource = {
+				PBXFileTableDataSourceColumnSortingDirectionKey = "-1";
+				PBXFileTableDataSourceColumnSortingKey = PBXExecutablesDataSource_NameID;
+				PBXFileTableDataSourceColumnWidthsKey = (
+					22,
+					300,
+					252,
+				);
+				PBXFileTableDataSourceColumnsKey = (
+					PBXExecutablesDataSource_ActiveFlagID,
+					PBXExecutablesDataSource_NameID,
+					PBXExecutablesDataSource_CommentsID,
+				);
+			};
+			PBXConfiguration.PBXFileTableDataSource3.PBXFileTableDataSource = {
+				PBXFileTableDataSourceColumnSortingDirectionKey = "-1";
+				PBXFileTableDataSourceColumnSortingKey = PBXFileDataSource_Filename_ColumnID;
+				PBXFileTableDataSourceColumnWidthsKey = (
+					20,
+					598,
+					20,
+					48,
+					43,
+					43,
+					20,
+				);
+				PBXFileTableDataSourceColumnsKey = (
+					PBXFileDataSource_FiletypeID,
+					PBXFileDataSource_Filename_ColumnID,
+					PBXFileDataSource_Built_ColumnID,
+					PBXFileDataSource_ObjectSize_ColumnID,
+					PBXFileDataSource_Errors_ColumnID,
+					PBXFileDataSource_Warnings_ColumnID,
+					PBXFileDataSource_Target_ColumnID,
+				);
+			};
+			PBXConfiguration.PBXFileTableDataSource3.PBXFindDataSource = {
+				PBXFileTableDataSourceColumnSortingDirectionKey = "-1";
+				PBXFileTableDataSourceColumnSortingKey = PBXFindDataSource_LocationID;
+				PBXFileTableDataSourceColumnWidthsKey = (
+					200,
+					612.20849609375,
+				);
+				PBXFileTableDataSourceColumnsKey = (
+					PBXFindDataSource_MessageID,
+					PBXFindDataSource_LocationID,
+				);
+			};
+			PBXConfiguration.PBXFileTableDataSource3.PBXSymbolsDataSource = {
+				PBXFileTableDataSourceColumnSortingDirectionKey = "-1";
+				PBXFileTableDataSourceColumnSortingKey = PBXSymbolsDataSource_SymbolNameID;
+				PBXFileTableDataSourceColumnWidthsKey = (
+					16,
+					200,
+					50,
+					538,
+				);
+				PBXFileTableDataSourceColumnsKey = (
+					PBXSymbolsDataSource_SymbolTypeIconID,
+					PBXSymbolsDataSource_SymbolNameID,
+					PBXSymbolsDataSource_SymbolTypeID,
+					PBXSymbolsDataSource_ReferenceNameID,
+				);
+			};
+			PBXConfiguration.PBXFileTableDataSource3.XCSCMDataSource = {
+				PBXFileTableDataSourceColumnSortingDirectionKey = "-1";
+				PBXFileTableDataSourceColumnSortingKey = PBXFileDataSource_Filename_ColumnID;
+				PBXFileTableDataSourceColumnWidthsKey = (
+					20,
+					20,
+					574,
+					20,
+					48,
+					43,
+					43,
+					20,
+				);
+				PBXFileTableDataSourceColumnsKey = (
+					PBXFileDataSource_SCM_ColumnID,
+					PBXFileDataSource_FiletypeID,
+					PBXFileDataSource_Filename_ColumnID,
+					PBXFileDataSource_Built_ColumnID,
+					PBXFileDataSource_ObjectSize_ColumnID,
+					PBXFileDataSource_Errors_ColumnID,
+					PBXFileDataSource_Warnings_ColumnID,
+					PBXFileDataSource_Target_ColumnID,
+				);
+			};
+			PBXConfiguration.PBXTargetDataSource.PBXTargetDataSource = {
+				PBXFileTableDataSourceColumnSortingDirectionKey = "-1";
+				PBXFileTableDataSourceColumnSortingKey = PBXFileDataSource_Filename_ColumnID;
+				PBXFileTableDataSourceColumnWidthsKey = (
+					20,
+					558,
+					60,
+					20,
+					48,
+					43,
+					43,
+				);
+				PBXFileTableDataSourceColumnsKey = (
+					PBXFileDataSource_FiletypeID,
+					PBXFileDataSource_Filename_ColumnID,
+					PBXTargetDataSource_PrimaryAttribute,
+					PBXFileDataSource_Built_ColumnID,
+					PBXFileDataSource_ObjectSize_ColumnID,
+					PBXFileDataSource_Errors_ColumnID,
+					PBXFileDataSource_Warnings_ColumnID,
+				);
+			};
+			PBXPerProjectTemplateStateSaveDate = 293825908;
+			PBXWorkspaceStateSaveDate = 293825908;
+		};
+		perUserProjectItems = {
+			DA00DBC31178125F00587AEB /* PBXTextBookmark */ = DA00DBC31178125F00587AEB /* PBXTextBookmark */;
+			DA194E7E11836D8F004F4DD5 /* PBXTextBookmark */ = DA194E7E11836D8F004F4DD5 /* PBXTextBookmark */;
+			DA279E051173F1E1003793F6 /* PBXTextBookmark */ = DA279E051173F1E1003793F6 /* PBXTextBookmark */;
+			DA47DC531121B0B30028C558 /* PBXTextBookmark */ = DA47DC531121B0B30028C558 /* PBXTextBookmark */;
+			DA59442C114D3A2B0078AFE8 /* PBXTextBookmark */ = DA59442C114D3A2B0078AFE8 /* PBXTextBookmark */;
+			DA59444C115508DC0078AFE8 /* PBXTextBookmark */ = DA59444C115508DC0078AFE8 /* PBXTextBookmark */;
+			DA59444E115508DC0078AFE8 /* PBXTextBookmark */ = DA59444E115508DC0078AFE8 /* PBXTextBookmark */;
+			DA59444F115508DC0078AFE8 /* PBXTextBookmark */ = DA59444F115508DC0078AFE8 /* PBXTextBookmark */;
+			DAA87B08113EB3CD00F079CB /* PBXTextBookmark */ = DAA87B08113EB3CD00F079CB /* PBXTextBookmark */;
+			DAA87B09113EB3CD00F079CB /* PBXBookmark */ = DAA87B09113EB3CD00F079CB /* PBXBookmark */;
+			DAA87C1A11405E0900F079CB /* PBXTextBookmark */ = DAA87C1A11405E0900F079CB /* PBXTextBookmark */;
+			DAA87C8A1141C10E00F079CB /* PBXTextBookmark */ = DAA87C8A1141C10E00F079CB /* PBXTextBookmark */;
+			DACE7888111B58AD00886DC9 /* PlistBookmark */ = DACE7888111B58AD00886DC9 /* PlistBookmark */;
+			DACE788C111B58AD00886DC9 /* PlistBookmark */ = DACE788C111B58AD00886DC9 /* PlistBookmark */;
+			DACE788D111B58AD00886DC9 /* PlistBookmark */ = DACE788D111B58AD00886DC9 /* PlistBookmark */;
+			DACE788E111B58AD00886DC9 /* PBXTextBookmark */ = DACE788E111B58AD00886DC9 /* PBXTextBookmark */;
+			DACE788F111B58AD00886DC9 /* PBXTextBookmark */ = DACE788F111B58AD00886DC9 /* PBXTextBookmark */;
+			DACE7890111B58AD00886DC9 /* PBXTextBookmark */ = DACE7890111B58AD00886DC9 /* PBXTextBookmark */;
+			DACE789A111B58AD00886DC9 /* PBXTextBookmark */ = DACE789A111B58AD00886DC9 /* PBXTextBookmark */;
+			DACE78E1111B6CE800886DC9 /* PBXTextBookmark */ = DACE78E1111B6CE800886DC9 /* PBXTextBookmark */;
+			DACE78EC111B6CE800886DC9 /* PBXBookmark */ = DACE78EC111B6CE800886DC9 /* PBXBookmark */;
+			DACE78EE111B6CE800886DC9 /* PBXTextBookmark */ = DACE78EE111B6CE800886DC9 /* PBXTextBookmark */;
+			DACE795E111C8D6E00886DC9 /* PBXTextBookmark */ = DACE795E111C8D6E00886DC9 /* PBXTextBookmark */;
+			DACE7978111C8D6E00886DC9 /* PBXTextBookmark */ = DACE7978111C8D6E00886DC9 /* PBXTextBookmark */;
+			DACE7982111C8D6E00886DC9 /* PBXTextBookmark */ = DACE7982111C8D6E00886DC9 /* PBXTextBookmark */;
+			DACE79AB111CBA2700886DC9 /* PlistBookmark */ = DACE79AB111CBA2700886DC9 /* PlistBookmark */;
+			DACE79C2111CBA2700886DC9 /* PBXTextBookmark */ = DACE79C2111CBA2700886DC9 /* PBXTextBookmark */;
+		};
+		sourceControlManager = C096A9320C03CEA700263BB0 /* Source Control */;
+		userBuildSettings = {
+		};
+	};
+	0259C576FE90428111CA0C5A /* LispControllerPlugin.m */ = {
+		uiCtxt = {
+			sepNavIntBoundsRect = "{{0, 0}, {776, 368}}";
+			sepNavSelRange = "{110, 0}";
+			sepNavVisRange = "{0, 469}";
+		};
+	};
+	0259C57AFE90428111CA0C5A /* LispControllerPlugin.h */ = {
+		uiCtxt = {
+			sepNavIntBoundsRect = "{{0, 0}, {776, 368}}";
+			sepNavSelRange = "{110, 0}";
+			sepNavVisRange = "{0, 244}";
+		};
+	};
+	32DBCF980370C29C00C91783 /* LispControllerPlugin_Prefix.pch */ = {
+		uiCtxt = {
+			sepNavIntBoundsRect = "{{0, 0}, {776, 368}}";
+			sepNavSelRange = "{0, 0}";
+			sepNavVisRange = "{0, 228}";
+		};
+	};
+	53DF68FC067E5B5A0090B5B0 /* LispControllerPluginFramework */ = {
+		activeExec = 0;
+	};
+	53DF6901067E5B8E0090B5B0 /* All */ = {
+		activeExec = 0;
+	};
+	8D1AC9600486D14A00FE50C9 /* LispControllerPlugin */ = {
+		activeExec = 0;
+	};
+	8D1AC9730486D14A00FE50C9 /* Info.plist */ = {
+		uiCtxt = {
+			sepNavWindowFrame = "{{176, 152}, {1125, 658}}";
+		};
+	};
+	8D1AC97B0486D23100FE50C9 /* English */ = {
+		uiCtxt = {
+			sepNavIntBoundsRect = "{{0, 0}, {776, 368}}";
+			sepNavSelRange = "{0, 0}";
+			sepNavVisRange = "{0, 101}";
+		};
+	};
+	C096A9320C03CEA700263BB0 /* Source Control */ = {
+		isa = PBXSourceControlManager;
+		fallbackIsa = XCSourceControlManager;
+		isSCMEnabled = 0;
+		scmConfiguration = {
+		};
+	};
+	C096A9330C03CEA700263BB0 /* Code sense */ = {
+		isa = PBXCodeSenseManager;
+		indexTemplatePath = "";
+	};
+	C096A9340C03CEAB00263BB0 /* Interface Builder */ = {
+		isa = PBXExecutable;
+		activeArgIndices = (
+			YES,
+		);
+		argumentStrings = (
+			"-NSOpen \"LispControllerPlugin.ibplugin\"",
+		);
+		autoAttachOnCrash = 1;
+		breakpointsEnabled = 0;
+		configStateDict = {
+			"PBXLSLaunchAction-0" = {
+				PBXLSLaunchAction = 0;
+				PBXLSLaunchStartAction = 1;
+				PBXLSLaunchStdioStyle = 2;
+				PBXLSLaunchStyle = 0;
+				class = PBXLSRunLaunchConfig;
+				commandLineArgs = (
+				);
+				displayName = "Executable Runner";
+				environment = {
+				};
+				identifier = com.apple.Xcode.launch.runConfig;
+				remoteHostInfo = "";
+				startActionInfo = "";
+			};
+		};
+		customDataFormattersEnabled = 1;
+		debuggerPlugin = GDBDebugging;
+		disassemblyDisplayState = 0;
+		dylibVariantSuffix = "";
+		enableDebugStr = 1;
+		environmentEntries = (
+		);
+		executableSystemSymbolLevel = 0;
+		executableUserSymbolLevel = 0;
+		launchableReference = C096A9350C03CEAB00263BB0 /* Interface Builder.app */;
+		libgmallocEnabled = 0;
+		name = "Interface Builder";
+		savedGlobals = {
+		};
+		sourceDirectories = (
+		);
+		startupPath = "<<ProductDirectory>>";
+		variableFormatDictionary = {
+		};
+	};
+	C096A9350C03CEAB00263BB0 /* Interface Builder.app */ = {
+		isa = PBXFileReference;
+		lastKnownFileType = wrapper.application;
+		name = "Interface Builder.app";
+		path = "Applications/Interface Builder.app";
+		sourceTree = DEVELOPER_DIR;
+	};
+	DA00DBC31178125F00587AEB /* PBXTextBookmark */ = {
+		isa = PBXTextBookmark;
+		fRef = DACE7902111B6F4B00886DC9 /* LispController.m */;
+		name = "LispController.m: 13";
+		rLen = 16;
+		rLoc = 204;
+		rType = 0;
+		vrLen = 1133;
+		vrLoc = 135;
+	};
+	DA194E7E11836D8F004F4DD5 /* PBXTextBookmark */ = {
+		isa = PBXTextBookmark;
+		fRef = DACE7902111B6F4B00886DC9 /* LispController.m */;
+		name = "LispController.m: 13";
+		rLen = 16;
+		rLoc = 204;
+		rType = 0;
+		vrLen = 1133;
+		vrLoc = 135;
+	};
+	DA279E051173F1E1003793F6 /* PBXTextBookmark */ = {
+		isa = PBXTextBookmark;
+		fRef = DACE7918111C867D00886DC9 /* LispControllerInspector.m */;
+		name = "LispControllerInspector.m: 101";
+		rLen = 0;
+		rLoc = 3032;
+		rType = 0;
+		vrLen = 1057;
+		vrLoc = 2550;
+	};
+	DA47DBFD1120E5170028C558 /* LispIntegration.m */ = {
+		uiCtxt = {
+			sepNavIntBoundsRect = "{{0, 0}, {776, 714}}";
+			sepNavSelRange = "{998, 0}";
+			sepNavVisRange = "{669, 772}";
+		};
+	};
+	DA47DC531121B0B30028C558 /* PBXTextBookmark */ = {
+		isa = PBXTextBookmark;
+		fRef = DA47DBFD1120E5170028C558 /* LispIntegration.m */;
+		name = "LispListIntegration.m: 1";
+		rLen = 0;
+		rLoc = 0;
+		rType = 0;
+		vrLen = 912;
+		vrLoc = 0;
+	};
+	DA59442C114D3A2B0078AFE8 /* PBXTextBookmark */ = {
+		isa = PBXTextBookmark;
+		fRef = DA47DBFD1120E5170028C558 /* LispIntegration.m */;
+		name = "LispIntegration.m: 34";
+		rLen = 0;
+		rLoc = 998;
+		rType = 0;
+		vrLen = 772;
+		vrLoc = 669;
+	};
+	DA59444C115508DC0078AFE8 /* PBXTextBookmark */ = {
+		isa = PBXTextBookmark;
+		fRef = DACE78CA111B69C200886DC9 /* LispController.classdescription */;
+		name = "LispController.classdescription: 13";
+		rLen = 0;
+		rLoc = 264;
+		rType = 0;
+		vrLen = 332;
+		vrLoc = 0;
+	};
+	DA59444E115508DC0078AFE8 /* PBXTextBookmark */ = {
+		isa = PBXTextBookmark;
+		fRef = DACE7999111CB6ED00886DC9 /* LispController.h */;
+		name = "LispController.h: 21";
+		rLen = 11;
+		rLoc = 426;
+		rType = 0;
+		vrLen = 624;
+		vrLoc = 176;
+	};
+	DA59444F115508DC0078AFE8 /* PBXTextBookmark */ = {
+		isa = PBXTextBookmark;
+		fRef = 0259C576FE90428111CA0C5A /* LispControllerPlugin.m */;
+		name = "LispControllerPlugin.m: 6";
+		rLen = 0;
+		rLoc = 110;
+		rType = 0;
+		vrLen = 469;
+		vrLoc = 0;
+	};
+	DAA87B08113EB3CD00F079CB /* PBXTextBookmark */ = {
+		isa = PBXTextBookmark;
+		fRef = 32DBCF980370C29C00C91783 /* LispControllerPlugin_Prefix.pch */;
+		name = "LispControllerPlugin_Prefix.pch: 1";
+		rLen = 0;
+		rLoc = 0;
+		rType = 0;
+		vrLen = 228;
+		vrLoc = 0;
+	};
+	DAA87B09113EB3CD00F079CB /* PBXBookmark */ = {
+		isa = PBXBookmark;
+		fRef = DACE78C3111B5B8F00886DC9 /* LispList.icns */;
+	};
+	DAA87C1A11405E0900F079CB /* PBXTextBookmark */ = {
+		isa = PBXTextBookmark;
+		fRef = 0259C57AFE90428111CA0C5A /* LispControllerPlugin.h */;
+		name = "LispControllerPlugin.h: 6";
+		rLen = 0;
+		rLoc = 110;
+		rType = 0;
+		vrLen = 244;
+		vrLoc = 0;
+	};
+	DAA87C8A1141C10E00F079CB /* PBXTextBookmark */ = {
+		isa = PBXTextBookmark;
+		fRef = DACE7917111C867D00886DC9 /* LispControllerInspector.h */;
+		name = "LispControllerInspector.h: 13";
+		rLen = 82;
+		rLoc = 299;
+		rType = 0;
+		vrLen = 391;
+		vrLoc = 0;
+	};
+	DACE7888111B58AD00886DC9 /* PlistBookmark */ = {
+		isa = PlistBookmark;
+		fRef = 8D1AC9730486D14A00FE50C9 /* Info.plist */;
+		fallbackIsa = PBXBookmark;
+		isK = 0;
+		kPath = (
+		);
+		name = "/Applications/ccl/contrib/krueger/InterfaceProjects/Lisp IB Plugins/LispControllerPlugin/Info.plist";
+		rLen = 0;
+		rLoc = 2147483647;
+	};
+	DACE788C111B58AD00886DC9 /* PlistBookmark */ = {
+		isa = PlistBookmark;
+		fRef = 8D1AC9730486D14A00FE50C9 /* Info.plist */;
+		fallbackIsa = PBXBookmark;
+		isK = 0;
+		kPath = (
+		);
+		name = "/Applications/ccl/contrib/krueger/InterfaceProjects/Lisp IB Plugins/LispControllerPlugin/Info.plist";
+		rLen = 0;
+		rLoc = 2147483647;
+	};
+	DACE788D111B58AD00886DC9 /* PlistBookmark */ = {
+		isa = PlistBookmark;
+		fRef = 53DF68FE067E5B5A0090B5B0 /* LispControllerPlugin-Info.plist */;
+		fallbackIsa = PBXBookmark;
+		isK = 0;
+		kPath = (
+		);
+		name = "/Applications/ccl/contrib/krueger/InterfaceProjects/Lisp IB Plugins/LispControllerPlugin/LispControllerPlugin-Info.plist";
+		rLen = 0;
+		rLoc = 2147483647;
+	};
+	DACE788E111B58AD00886DC9 /* PBXTextBookmark */ = {
+		isa = PBXTextBookmark;
+		fRef = 0259C57AFE90428111CA0C5A /* LispControllerPlugin.h */;
+		name = "LispControllerPlugin.h: 1";
+		rLen = 0;
+		rLoc = 0;
+		rType = 0;
+		vrLen = 267;
+		vrLoc = 0;
+	};
+	DACE788F111B58AD00886DC9 /* PBXTextBookmark */ = {
+		isa = PBXTextBookmark;
+		fRef = 0259C576FE90428111CA0C5A /* LispControllerPlugin.m */;
+		name = "LispControllerPlugin.m: 1";
+		rLen = 0;
+		rLoc = 0;
+		rType = 0;
+		vrLen = 439;
+		vrLoc = 30;
+	};
+	DACE7890111B58AD00886DC9 /* PBXTextBookmark */ = {
+		isa = PBXTextBookmark;
+		fRef = 32DBCF980370C29C00C91783 /* LispControllerPlugin_Prefix.pch */;
+		name = "LispControllerPlugin_Prefix.pch: 1";
+		rLen = 0;
+		rLoc = 0;
+		rType = 0;
+		vrLen = 228;
+		vrLoc = 0;
+	};
+	DACE789A111B58AD00886DC9 /* PBXTextBookmark */ = {
+		isa = PBXTextBookmark;
+		fRef = 8D1AC97B0486D23100FE50C9 /* English */;
+		name = "InfoPlist.strings: 1";
+		rLen = 0;
+		rLoc = 0;
+		rType = 0;
+		vrLen = 101;
+		vrLoc = 0;
+	};
+	DACE78CA111B69C200886DC9 /* LispController.classdescription */ = {
+		uiCtxt = {
+			sepNavIntBoundsRect = "{{0, 0}, {776, 368}}";
+			sepNavSelRange = "{264, 0}";
+			sepNavVisRange = "{0, 332}";
+		};
+	};
+	DACE78E1111B6CE800886DC9 /* PBXTextBookmark */ = {
+		isa = PBXTextBookmark;
+		fRef = 8D1AC97B0486D23100FE50C9 /* English */;
+		name = "InfoPlist.strings: 1";
+		rLen = 0;
+		rLoc = 0;
+		rType = 0;
+		vrLen = 101;
+		vrLoc = 0;
+	};
+	DACE78EC111B6CE800886DC9 /* PBXBookmark */ = {
+		isa = PBXBookmark;
+		fRef = DACE78C3111B5B8F00886DC9 /* LispList.icns */;
+	};
+	DACE78EE111B6CE800886DC9 /* PBXTextBookmark */ = {
+		isa = PBXTextBookmark;
+		fRef = DACE78CA111B69C200886DC9 /* LispController.classdescription */;
+		name = "LispListController.classdescription: 14";
+		rLen = 0;
+		rLoc = 329;
+		rType = 0;
+		vrLen = 299;
+		vrLoc = 0;
+	};
+	DACE7902111B6F4B00886DC9 /* LispController.m */ = {
+		uiCtxt = {
+			sepNavIntBoundsRect = "{{0, 0}, {776, 2352}}";
+			sepNavSelRange = "{204, 16}";
+			sepNavVisRange = "{135, 1133}";
+			sepNavWindowFrame = "{{15, 215}, {1125, 658}}";
+		};
+	};
+	DACE7917111C867D00886DC9 /* LispControllerInspector.h */ = {
+		uiCtxt = {
+			sepNavIntBoundsRect = "{{0, 0}, {776, 368}}";
+			sepNavSelRange = "{299, 82}";
+			sepNavVisRange = "{0, 391}";
+		};
+	};
+	DACE7918111C867D00886DC9 /* LispControllerInspector.m */ = {
+		uiCtxt = {
+			sepNavIntBoundsRect = "{{0, 0}, {776, 1694}}";
+			sepNavSelRange = "{3032, 0}";
+			sepNavVisRange = "{2550, 1057}";
+		};
+	};
+	DACE795E111C8D6E00886DC9 /* PBXTextBookmark */ = {
+		isa = PBXTextBookmark;
+		fRef = DACE7902111B6F4B00886DC9 /* LispController.m */;
+		name = "LispListController.m: 1";
+		rLen = 0;
+		rLoc = 0;
+		rType = 0;
+		vrLen = 743;
+		vrLoc = 0;
+	};
+	DACE7978111C8D6E00886DC9 /* PBXTextBookmark */ = {
+		isa = PBXTextBookmark;
+		fRef = DACE7917111C867D00886DC9 /* LispControllerInspector.h */;
+		name = "LispListControllerInspector.h: 1";
+		rLen = 0;
+		rLoc = 0;
+		rType = 0;
+		vrLen = 282;
+		vrLoc = 0;
+	};
+	DACE7982111C8D6E00886DC9 /* PBXTextBookmark */ = {
+		isa = PBXTextBookmark;
+		fRef = DACE7918111C867D00886DC9 /* LispControllerInspector.m */;
+		name = "LispListControllerInspector.m: 1";
+		rLen = 0;
+		rLoc = 0;
+		rType = 0;
+		vrLen = 453;
+		vrLoc = 0;
+	};
+	DACE7999111CB6ED00886DC9 /* LispController.h */ = {
+		uiCtxt = {
+			sepNavIntBoundsRect = "{{0, 0}, {776, 854}}";
+			sepNavSelRange = "{426, 11}";
+			sepNavVisRange = "{176, 624}";
+		};
+	};
+	DACE79AB111CBA2700886DC9 /* PlistBookmark */ = {
+		isa = PlistBookmark;
+		fRef = 53DF68FE067E5B5A0090B5B0 /* LispControllerPlugin-Info.plist */;
+		fallbackIsa = PBXBookmark;
+		isK = 0;
+		kPath = (
+		);
+		name = "/Applications/ccl/contrib/krueger/InterfaceProjects/Lisp IB Plugins/LispControllerPlugin/LispControllerPlugin-Info.plist";
+		rLen = 0;
+		rLoc = 2147483647;
+	};
+	DACE79C2111CBA2700886DC9 /* PBXTextBookmark */ = {
+		isa = PBXTextBookmark;
+		fRef = DACE7999111CB6ED00886DC9 /* LispController.h */;
+		name = "LispListController.h: 11";
+		rLen = 0;
+		rLoc = 162;
+		rType = 0;
+		vrLen = 263;
+		vrLoc = 0;
+	};
+}
Index: /trunk/contrib/krueger/InterfaceProjects/Lisp IB Plugins/LispControllerPlugin/LispControllerPlugin.xcodeproj/project.pbxproj
===================================================================
--- /trunk/contrib/krueger/InterfaceProjects/Lisp IB Plugins/LispControllerPlugin/LispControllerPlugin.xcodeproj/project.pbxproj	(revision 13946)
+++ /trunk/contrib/krueger/InterfaceProjects/Lisp IB Plugins/LispControllerPlugin/LispControllerPlugin.xcodeproj/project.pbxproj	(revision 13946)
@@ -0,0 +1,558 @@
+// !$*UTF8*$!
+{
+	archiveVersion = 1;
+	classes = {
+	};
+	objectVersion = 45;
+	objects = {
+
+/* Begin PBXAggregateTarget section */
+		53DF6901067E5B8E0090B5B0 /* All */ = {
+			isa = PBXAggregateTarget;
+			buildConfigurationList = C056398708A954F8003078D8 /* Build configuration list for PBXAggregateTarget "All" */;
+			buildPhases = (
+			);
+			dependencies = (
+				53DF6903067E5B930090B5B0 /* PBXTargetDependency */,
+				53DF6905067E5B930090B5B0 /* PBXTargetDependency */,
+			);
+			name = All;
+			productName = All;
+		};
+/* End PBXAggregateTarget section */
+
+/* Begin PBXBuildFile section */
+		13F8B89007B43554008AE28D /* Cocoa.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = DD92D38A0106425D02CA0E72 /* Cocoa.framework */; };
+		546DEAF3067F632A0098DCC4 /* LispControllerPlugin.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 53DF68FD067E5B5A0090B5B0 /* LispControllerPlugin.framework */; };
+		8D1AC9700486D14A00FE50C9 /* Cocoa.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = DD92D38A0106425D02CA0E72 /* Cocoa.framework */; };
+		8D1AC9800486D23B00FE50C9 /* InfoPlist.strings in Resources */ = {isa = PBXBuildFile; fileRef = 8D1AC97F0486D23B00FE50C9 /* InfoPlist.strings */; };
+		C08787290A49DE9A00E9B151 /* LispControllerPlugin.m in Sources */ = {isa = PBXBuildFile; fileRef = 0259C576FE90428111CA0C5A /* LispControllerPlugin.m */; };
+		C0A47C500A523B730004BDC3 /* LispControllerInspector.xib in Resources */ = {isa = PBXBuildFile; fileRef = C05B20D80A48CB530099B9E5 /* LispControllerInspector.xib */; };
+		C0D069560A49DF9100C95564 /* InterfaceBuilderKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = C0D069550A49DF9100C95564 /* InterfaceBuilderKit.framework */; };
+		D1AEDE470A6C289C0010C343 /* LispControllerPluginLibrary.nib in Resources */ = {isa = PBXBuildFile; fileRef = D1AEDE460A6C289C0010C343 /* LispControllerPluginLibrary.nib */; };
+		DA47DBD01120DE590028C558 /* LispController.h in Headers */ = {isa = PBXBuildFile; fileRef = DACE7999111CB6ED00886DC9 /* LispController.h */; };
+		DA47DBD61120DEAE0028C558 /* LispController.m in Sources */ = {isa = PBXBuildFile; fileRef = DACE7902111B6F4B00886DC9 /* LispController.m */; };
+		DA47DBFE1120E5170028C558 /* LispIntegration.m in Sources */ = {isa = PBXBuildFile; fileRef = DA47DBFD1120E5170028C558 /* LispIntegration.m */; };
+		DACE78C4111B5B8F00886DC9 /* LispList.icns in Resources */ = {isa = PBXBuildFile; fileRef = DACE78C3111B5B8F00886DC9 /* LispList.icns */; };
+		DACE78D9111B6CD900886DC9 /* LispController.classdescription in Resources */ = {isa = PBXBuildFile; fileRef = DACE78CA111B69C200886DC9 /* LispController.classdescription */; };
+		DACE7919111C867D00886DC9 /* LispControllerInspector.m in Sources */ = {isa = PBXBuildFile; fileRef = DACE7918111C867D00886DC9 /* LispControllerInspector.m */; };
+/* End PBXBuildFile section */
+
+/* Begin PBXContainerItemProxy section */
+		53DF6902067E5B930090B5B0 /* PBXContainerItemProxy */ = {
+			isa = PBXContainerItemProxy;
+			containerPortal = 0259C573FE90428111CA0C5A /* Project object */;
+			proxyType = 1;
+			remoteGlobalIDString = 8D1AC9600486D14A00FE50C9;
+			remoteInfo = LispControllerPlugin;
+		};
+		53DF6904067E5B930090B5B0 /* PBXContainerItemProxy */ = {
+			isa = PBXContainerItemProxy;
+			containerPortal = 0259C573FE90428111CA0C5A /* Project object */;
+			proxyType = 1;
+			remoteGlobalIDString = 53DF68FC067E5B5A0090B5B0;
+			remoteInfo = LispControllerPluginFramework;
+		};
+		546DEAEF067F62F70098DCC4 /* PBXContainerItemProxy */ = {
+			isa = PBXContainerItemProxy;
+			containerPortal = 0259C573FE90428111CA0C5A /* Project object */;
+			proxyType = 1;
+			remoteGlobalIDString = 53DF68FC067E5B5A0090B5B0;
+			remoteInfo = LispControllerPluginFramework;
+		};
+/* End PBXContainerItemProxy section */
+
+/* Begin PBXFileReference section */
+		0259C576FE90428111CA0C5A /* LispControllerPlugin.m */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.objc; path = LispControllerPlugin.m; sourceTree = "<group>"; };
+		0259C57AFE90428111CA0C5A /* LispControllerPlugin.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = LispControllerPlugin.h; sourceTree = "<group>"; };
+		13F8B88807B434F6008AE28D /* AppKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = AppKit.framework; path = /System/Library/Frameworks/AppKit.framework; sourceTree = "<absolute>"; };
+		13F8B88907B434F6008AE28D /* CoreData.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CoreData.framework; path = /System/Library/Frameworks/CoreData.framework; sourceTree = "<absolute>"; };
+		13F8B88A07B434F6008AE28D /* Foundation.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Foundation.framework; path = /System/Library/Frameworks/Foundation.framework; sourceTree = "<absolute>"; };
+		32DBCF980370C29C00C91783 /* LispControllerPlugin_Prefix.pch */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = LispControllerPlugin_Prefix.pch; sourceTree = "<group>"; };
+		53DF68FD067E5B5A0090B5B0 /* LispControllerPlugin.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = LispControllerPlugin.framework; sourceTree = BUILT_PRODUCTS_DIR; };
+		53DF68FE067E5B5A0090B5B0 /* LispControllerPlugin-Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = "LispControllerPlugin-Info.plist"; sourceTree = "<group>"; };
+		8D1AC9730486D14A00FE50C9 /* Info.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist; path = Info.plist; sourceTree = "<group>"; };
+		8D1AC9740486D14A00FE50C9 /* LispControllerPlugin.ibplugin */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = LispControllerPlugin.ibplugin; sourceTree = BUILT_PRODUCTS_DIR; };
+		8D1AC97B0486D23100FE50C9 /* English */ = {isa = PBXFileReference; fileEncoding = 10; lastKnownFileType = text.plist.strings; name = English; path = English.lproj/InfoPlist.strings; sourceTree = "<group>"; };
+		C05B20D80A48CB530099B9E5 /* LispControllerInspector.xib */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = file.xib; name = LispControllerInspector.xib; path = English.lproj/LispControllerInspector.xib; sourceTree = "<group>"; };
+		C0D069550A49DF9100C95564 /* InterfaceBuilderKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = InterfaceBuilderKit.framework; path = /Developer/Library/Frameworks/InterfaceBuilderKit.framework; sourceTree = "<absolute>"; };
+		D1AEDE460A6C289C0010C343 /* LispControllerPluginLibrary.nib */ = {isa = PBXFileReference; lastKnownFileType = wrapper.nib; name = LispControllerPluginLibrary.nib; path = English.lproj/LispControllerPluginLibrary.nib; sourceTree = "<group>"; };
+		DA47DBFD1120E5170028C558 /* LispIntegration.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = LispIntegration.m; sourceTree = "<group>"; };
+		DACE78C3111B5B8F00886DC9 /* LispList.icns */ = {isa = PBXFileReference; lastKnownFileType = image.icns; path = LispList.icns; sourceTree = "<group>"; };
+		DACE78CA111B69C200886DC9 /* LispController.classdescription */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = LispController.classdescription; sourceTree = "<group>"; };
+		DACE7902111B6F4B00886DC9 /* LispController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = LispController.m; sourceTree = "<group>"; };
+		DACE7917111C867D00886DC9 /* LispControllerInspector.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = LispControllerInspector.h; sourceTree = "<group>"; };
+		DACE7918111C867D00886DC9 /* LispControllerInspector.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = LispControllerInspector.m; sourceTree = "<group>"; };
+		DACE7999111CB6ED00886DC9 /* LispController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = LispController.h; sourceTree = "<group>"; };
+		DD92D38A0106425D02CA0E72 /* Cocoa.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Cocoa.framework; path = /System/Library/Frameworks/Cocoa.framework; sourceTree = "<absolute>"; };
+/* End PBXFileReference section */
+
+/* Begin PBXFrameworksBuildPhase section */
+		53DF68FB067E5B5A0090B5B0 /* Frameworks */ = {
+			isa = PBXFrameworksBuildPhase;
+			buildActionMask = 2147483647;
+			files = (
+				13F8B89007B43554008AE28D /* Cocoa.framework in Frameworks */,
+			);
+			runOnlyForDeploymentPostprocessing = 0;
+		};
+		8D1AC96E0486D14A00FE50C9 /* Frameworks */ = {
+			isa = PBXFrameworksBuildPhase;
+			buildActionMask = 2147483647;
+			files = (
+				8D1AC9700486D14A00FE50C9 /* Cocoa.framework in Frameworks */,
+				546DEAF3067F632A0098DCC4 /* LispControllerPlugin.framework in Frameworks */,
+				C0D069560A49DF9100C95564 /* InterfaceBuilderKit.framework in Frameworks */,
+			);
+			runOnlyForDeploymentPostprocessing = 0;
+		};
+/* End PBXFrameworksBuildPhase section */
+
+/* Begin PBXGroup section */
+		0259C574FE90428111CA0C5A /* LispControllerPlugin */ = {
+			isa = PBXGroup;
+			children = (
+				32DBCF9E0370C38000C91783 /* Plugin */,
+				54D33B2C06778E4400C9C163 /* Framework */,
+				0259C582FE90428111CA0C5A /* Resources */,
+				1ED78706FE9D4A0611CA0C5A /* Products */,
+				2E58F364FFB232C311CA0CBA /* Frameworks */,
+			);
+			name = LispControllerPlugin;
+			sourceTree = "<group>";
+		};
+		0259C582FE90428111CA0C5A /* Resources */ = {
+			isa = PBXGroup;
+			children = (
+				8D1AC9730486D14A00FE50C9 /* Info.plist */,
+				53DF68FE067E5B5A0090B5B0 /* LispControllerPlugin-Info.plist */,
+				8D1AC97F0486D23B00FE50C9 /* InfoPlist.strings */,
+			);
+			name = Resources;
+			sourceTree = "<group>";
+		};
+		131E8FE8067F80F40006E0CE /* Resources */ = {
+			isa = PBXGroup;
+			children = (
+				DACE78C3111B5B8F00886DC9 /* LispList.icns */,
+				D1AEDE460A6C289C0010C343 /* LispControllerPluginLibrary.nib */,
+				C05B20D80A48CB530099B9E5 /* LispControllerInspector.xib */,
+			);
+			name = Resources;
+			sourceTree = "<group>";
+		};
+		13F8B6FD07B43410008AE28D /* Linked Frameworks */ = {
+			isa = PBXGroup;
+			children = (
+				DD92D38A0106425D02CA0E72 /* Cocoa.framework */,
+				C0D069550A49DF9100C95564 /* InterfaceBuilderKit.framework */,
+			);
+			name = "Linked Frameworks";
+			sourceTree = "<group>";
+		};
+		13F8B70407B43425008AE28D /* Other Frameworks */ = {
+			isa = PBXGroup;
+			children = (
+				13F8B88807B434F6008AE28D /* AppKit.framework */,
+				13F8B88907B434F6008AE28D /* CoreData.framework */,
+				13F8B88A07B434F6008AE28D /* Foundation.framework */,
+			);
+			name = "Other Frameworks";
+			sourceTree = "<group>";
+		};
+		1ED78706FE9D4A0611CA0C5A /* Products */ = {
+			isa = PBXGroup;
+			children = (
+				8D1AC9740486D14A00FE50C9 /* LispControllerPlugin.ibplugin */,
+				53DF68FD067E5B5A0090B5B0 /* LispControllerPlugin.framework */,
+			);
+			name = Products;
+			sourceTree = "<group>";
+		};
+		2E58F364FFB232C311CA0CBA /* Frameworks */ = {
+			isa = PBXGroup;
+			children = (
+				13F8B6FD07B43410008AE28D /* Linked Frameworks */,
+				13F8B70407B43425008AE28D /* Other Frameworks */,
+			);
+			name = Frameworks;
+			sourceTree = "<group>";
+		};
+		32DBCF9E0370C38000C91783 /* Plugin */ = {
+			isa = PBXGroup;
+			children = (
+				54D33B2406778DD400C9C163 /* Class Descriptions */,
+				54D33B2506778DF000C9C163 /* Classes */,
+				32DBCF9F0370C38200C91783 /* Other Sources */,
+				131E8FE8067F80F40006E0CE /* Resources */,
+			);
+			name = Plugin;
+			sourceTree = "<group>";
+		};
+		32DBCF9F0370C38200C91783 /* Other Sources */ = {
+			isa = PBXGroup;
+			children = (
+				32DBCF980370C29C00C91783 /* LispControllerPlugin_Prefix.pch */,
+			);
+			name = "Other Sources";
+			sourceTree = "<group>";
+		};
+		54D33B2406778DD400C9C163 /* Class Descriptions */ = {
+			isa = PBXGroup;
+			children = (
+				DACE78CA111B69C200886DC9 /* LispController.classdescription */,
+			);
+			name = "Class Descriptions";
+			sourceTree = "<group>";
+		};
+		54D33B2506778DF000C9C163 /* Classes */ = {
+			isa = PBXGroup;
+			children = (
+				0259C57AFE90428111CA0C5A /* LispControllerPlugin.h */,
+				0259C576FE90428111CA0C5A /* LispControllerPlugin.m */,
+				DACE7917111C867D00886DC9 /* LispControllerInspector.h */,
+				DACE7918111C867D00886DC9 /* LispControllerInspector.m */,
+			);
+			name = Classes;
+			sourceTree = "<group>";
+		};
+		54D33B2C06778E4400C9C163 /* Framework */ = {
+			isa = PBXGroup;
+			children = (
+				C0894DA40C32F4C100401507 /* Classes */,
+			);
+			name = Framework;
+			sourceTree = "<group>";
+		};
+		C0894DA40C32F4C100401507 /* Classes */ = {
+			isa = PBXGroup;
+			children = (
+				DACE7902111B6F4B00886DC9 /* LispController.m */,
+				DACE7999111CB6ED00886DC9 /* LispController.h */,
+				DA47DBFD1120E5170028C558 /* LispIntegration.m */,
+			);
+			name = Classes;
+			sourceTree = "<group>";
+		};
+/* End PBXGroup section */
+
+/* Begin PBXHeadersBuildPhase section */
+		53DF68F8067E5B5A0090B5B0 /* Headers */ = {
+			isa = PBXHeadersBuildPhase;
+			buildActionMask = 2147483647;
+			files = (
+				DA47DBD01120DE590028C558 /* LispController.h in Headers */,
+			);
+			runOnlyForDeploymentPostprocessing = 0;
+		};
+/* End PBXHeadersBuildPhase section */
+
+/* Begin PBXNativeTarget section */
+		53DF68FC067E5B5A0090B5B0 /* LispControllerPluginFramework */ = {
+			isa = PBXNativeTarget;
+			buildConfigurationList = C056397F08A954F8003078D8 /* Build configuration list for PBXNativeTarget "LispControllerPluginFramework" */;
+			buildPhases = (
+				53DF68F8067E5B5A0090B5B0 /* Headers */,
+				53DF68F9067E5B5A0090B5B0 /* Resources */,
+				53DF68FA067E5B5A0090B5B0 /* Sources */,
+				53DF68FB067E5B5A0090B5B0 /* Frameworks */,
+			);
+			buildRules = (
+			);
+			dependencies = (
+			);
+			name = LispControllerPluginFramework;
+			productName = LispControllerPluginFramework;
+			productReference = 53DF68FD067E5B5A0090B5B0 /* LispControllerPlugin.framework */;
+			productType = "com.apple.product-type.framework";
+		};
+		8D1AC9600486D14A00FE50C9 /* LispControllerPlugin */ = {
+			isa = PBXNativeTarget;
+			buildConfigurationList = C056398308A954F8003078D8 /* Build configuration list for PBXNativeTarget "LispControllerPlugin" */;
+			buildPhases = (
+				8D1AC9660486D14A00FE50C9 /* Resources */,
+				8D1AC96A0486D14A00FE50C9 /* Sources */,
+				8D1AC96E0486D14A00FE50C9 /* Frameworks */,
+			);
+			buildRules = (
+			);
+			dependencies = (
+				546DEAF0067F62F70098DCC4 /* PBXTargetDependency */,
+			);
+			name = LispControllerPlugin;
+			productInstallPath = "$(HOME)/Developer/Palettes";
+			productName = LispControllerPlugin;
+			productReference = 8D1AC9740486D14A00FE50C9 /* LispControllerPlugin.ibplugin */;
+			productType = "com.apple.product-type.bundle";
+		};
+/* End PBXNativeTarget section */
+
+/* Begin PBXProject section */
+		0259C573FE90428111CA0C5A /* Project object */ = {
+			isa = PBXProject;
+			buildConfigurationList = C056398B08A954F8003078D8 /* Build configuration list for PBXProject "LispControllerPlugin" */;
+			compatibilityVersion = "Xcode 3.1";
+			hasScannedForEncodings = 1;
+			mainGroup = 0259C574FE90428111CA0C5A /* LispControllerPlugin */;
+			projectDirPath = "";
+			projectRoot = "";
+			targets = (
+				53DF6901067E5B8E0090B5B0 /* All */,
+				8D1AC9600486D14A00FE50C9 /* LispControllerPlugin */,
+				53DF68FC067E5B5A0090B5B0 /* LispControllerPluginFramework */,
+			);
+		};
+/* End PBXProject section */
+
+/* Begin PBXResourcesBuildPhase section */
+		53DF68F9067E5B5A0090B5B0 /* Resources */ = {
+			isa = PBXResourcesBuildPhase;
+			buildActionMask = 2147483647;
+			files = (
+			);
+			runOnlyForDeploymentPostprocessing = 0;
+		};
+		8D1AC9660486D14A00FE50C9 /* Resources */ = {
+			isa = PBXResourcesBuildPhase;
+			buildActionMask = 2147483647;
+			files = (
+				DACE78D9111B6CD900886DC9 /* LispController.classdescription in Resources */,
+				8D1AC9800486D23B00FE50C9 /* InfoPlist.strings in Resources */,
+				C0A47C500A523B730004BDC3 /* LispControllerInspector.xib in Resources */,
+				D1AEDE470A6C289C0010C343 /* LispControllerPluginLibrary.nib in Resources */,
+				DACE78C4111B5B8F00886DC9 /* LispList.icns in Resources */,
+			);
+			runOnlyForDeploymentPostprocessing = 0;
+		};
+/* End PBXResourcesBuildPhase section */
+
+/* Begin PBXSourcesBuildPhase section */
+		53DF68FA067E5B5A0090B5B0 /* Sources */ = {
+			isa = PBXSourcesBuildPhase;
+			buildActionMask = 2147483647;
+			files = (
+				DA47DBD61120DEAE0028C558 /* LispController.m in Sources */,
+			);
+			runOnlyForDeploymentPostprocessing = 0;
+		};
+		8D1AC96A0486D14A00FE50C9 /* Sources */ = {
+			isa = PBXSourcesBuildPhase;
+			buildActionMask = 2147483647;
+			files = (
+				C08787290A49DE9A00E9B151 /* LispControllerPlugin.m in Sources */,
+				DACE7919111C867D00886DC9 /* LispControllerInspector.m in Sources */,
+				DA47DBFE1120E5170028C558 /* LispIntegration.m in Sources */,
+			);
+			runOnlyForDeploymentPostprocessing = 0;
+		};
+/* End PBXSourcesBuildPhase section */
+
+/* Begin PBXTargetDependency section */
+		53DF6903067E5B930090B5B0 /* PBXTargetDependency */ = {
+			isa = PBXTargetDependency;
+			target = 8D1AC9600486D14A00FE50C9 /* LispControllerPlugin */;
+			targetProxy = 53DF6902067E5B930090B5B0 /* PBXContainerItemProxy */;
+		};
+		53DF6905067E5B930090B5B0 /* PBXTargetDependency */ = {
+			isa = PBXTargetDependency;
+			target = 53DF68FC067E5B5A0090B5B0 /* LispControllerPluginFramework */;
+			targetProxy = 53DF6904067E5B930090B5B0 /* PBXContainerItemProxy */;
+		};
+		546DEAF0067F62F70098DCC4 /* PBXTargetDependency */ = {
+			isa = PBXTargetDependency;
+			target = 53DF68FC067E5B5A0090B5B0 /* LispControllerPluginFramework */;
+			targetProxy = 546DEAEF067F62F70098DCC4 /* PBXContainerItemProxy */;
+		};
+/* End PBXTargetDependency section */
+
+/* Begin PBXVariantGroup section */
+		8D1AC97F0486D23B00FE50C9 /* InfoPlist.strings */ = {
+			isa = PBXVariantGroup;
+			children = (
+				8D1AC97B0486D23100FE50C9 /* English */,
+			);
+			name = InfoPlist.strings;
+			sourceTree = "<group>";
+		};
+/* End PBXVariantGroup section */
+
+/* Begin XCBuildConfiguration section */
+		C056398008A954F8003078D8 /* Debug */ = {
+			isa = XCBuildConfiguration;
+			buildSettings = {
+				COPY_PHASE_STRIP = NO;
+				DYLIB_COMPATIBILITY_VERSION = 1;
+				DYLIB_CURRENT_VERSION = 1;
+				FRAMEWORK_VERSION = A;
+				GCC_DYNAMIC_NO_PIC = NO;
+				GCC_ENABLE_FIX_AND_CONTINUE = YES;
+				GCC_MODEL_TUNING = G5;
+				GCC_OPTIMIZATION_LEVEL = 0;
+				GCC_PRECOMPILE_PREFIX_HEADER = YES;
+				GCC_PREFIX_HEADER = "$(SYSTEM_LIBRARY_DIR)/Frameworks/AppKit.framework/Headers/AppKit.h";
+				INFOPLIST_FILE = "LispControllerPlugin-Info.plist";
+				PRODUCT_NAME = LispControllerPlugin;
+				SKIP_INSTALL = NO;
+			};
+			name = Debug;
+		};
+		C056398108A954F8003078D8 /* Release */ = {
+			isa = XCBuildConfiguration;
+			buildSettings = {
+				DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
+				DYLIB_COMPATIBILITY_VERSION = 1;
+				DYLIB_CURRENT_VERSION = 1;
+				FRAMEWORK_VERSION = A;
+				GCC_MODEL_TUNING = G5;
+				GCC_PRECOMPILE_PREFIX_HEADER = YES;
+				GCC_PREFIX_HEADER = "$(SYSTEM_LIBRARY_DIR)/Frameworks/AppKit.framework/Headers/AppKit.h";
+				INFOPLIST_FILE = "LispControllerPlugin-Info.plist";
+				INSTALL_MODE_FLAG = "go-w,a+rX";
+				PRODUCT_NAME = LispControllerPlugin;
+				SKIP_INSTALL = NO;
+			};
+			name = Release;
+		};
+		C056398408A954F8003078D8 /* Debug */ = {
+			isa = XCBuildConfiguration;
+			buildSettings = {
+				COPY_PHASE_STRIP = NO;
+				FRAMEWORK_SEARCH_PATHS = (
+					$inherited,
+					"$(FRAMEWORK_SEARCH_PATHS_QUOTED_FOR_TARGET_1)",
+				);
+				FRAMEWORK_SEARCH_PATHS_QUOTED_FOR_TARGET_1 = "\"$(DEVELOPER_DIR)/Library/Frameworks\"";
+				GCC_DYNAMIC_NO_PIC = NO;
+				GCC_ENABLE_FIX_AND_CONTINUE = YES;
+				GCC_MODEL_TUNING = G5;
+				GCC_OPTIMIZATION_LEVEL = 0;
+				GCC_PRECOMPILE_PREFIX_HEADER = YES;
+				GCC_PREFIX_HEADER = LispControllerPlugin_Prefix.pch;
+				INFOPLIST_FILE = Info.plist;
+				INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks/LispControllerPlugin.framework/Resources";
+				PRODUCT_NAME = LispControllerPlugin;
+				WRAPPER_EXTENSION = ibplugin;
+			};
+			name = Debug;
+		};
+		C056398508A954F8003078D8 /* Release */ = {
+			isa = XCBuildConfiguration;
+			buildSettings = {
+				COPY_PHASE_STRIP = NO;
+				DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
+				FRAMEWORK_SEARCH_PATHS = (
+					$inherited,
+					"$(FRAMEWORK_SEARCH_PATHS_QUOTED_FOR_TARGET_1)",
+				);
+				FRAMEWORK_SEARCH_PATHS_QUOTED_FOR_TARGET_1 = "\"$(DEVELOPER_DIR)/Library/Frameworks\"";
+				GCC_MODEL_TUNING = G5;
+				GCC_PRECOMPILE_PREFIX_HEADER = YES;
+				GCC_PREFIX_HEADER = LispControllerPlugin_Prefix.pch;
+				INFOPLIST_FILE = Info.plist;
+				INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks/LispControllerPlugin.framework/Resources";
+				PRODUCT_NAME = LispControllerPlugin;
+				WRAPPER_EXTENSION = ibplugin;
+			};
+			name = Release;
+		};
+		C056398808A954F8003078D8 /* Debug */ = {
+			isa = XCBuildConfiguration;
+			buildSettings = {
+				COPY_PHASE_STRIP = NO;
+				GCC_DYNAMIC_NO_PIC = NO;
+				GCC_ENABLE_FIX_AND_CONTINUE = YES;
+				GCC_MODEL_TUNING = G5;
+				GCC_OPTIMIZATION_LEVEL = 0;
+				PRODUCT_NAME = All;
+				WARNING_CFLAGS = (
+					"-Wmost",
+					"-Wno-four-char-constants",
+					"-Wno-unknown-pragmas",
+				);
+			};
+			name = Debug;
+		};
+		C056398908A954F8003078D8 /* Release */ = {
+			isa = XCBuildConfiguration;
+			buildSettings = {
+				DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
+				GCC_MODEL_TUNING = G5;
+				PRODUCT_NAME = All;
+				WARNING_CFLAGS = (
+					"-Wmost",
+					"-Wno-four-char-constants",
+					"-Wno-unknown-pragmas",
+				);
+			};
+			name = Release;
+		};
+		C056398C08A954F8003078D8 /* Debug */ = {
+			isa = XCBuildConfiguration;
+			buildSettings = {
+				ARCHS = "$(ARCHS_STANDARD_32_BIT)";
+				GCC_C_LANGUAGE_STANDARD = c99;
+				GCC_MODEL_TUNING = "";
+				GCC_WARN_ABOUT_RETURN_TYPE = YES;
+				GCC_WARN_UNUSED_VARIABLE = YES;
+				ONLY_ACTIVE_ARCH = YES;
+				PREBINDING = NO;
+				SDKROOT = macosx10.5;
+			};
+			name = Debug;
+		};
+		C056398D08A954F8003078D8 /* Release */ = {
+			isa = XCBuildConfiguration;
+			buildSettings = {
+				ARCHS = "$(ARCHS_STANDARD_32_BIT)";
+				GCC_C_LANGUAGE_STANDARD = c99;
+				GCC_MODEL_TUNING = "";
+				GCC_WARN_ABOUT_RETURN_TYPE = YES;
+				GCC_WARN_UNUSED_VARIABLE = YES;
+				PREBINDING = NO;
+				SDKROOT = macosx10.5;
+			};
+			name = Release;
+		};
+/* End XCBuildConfiguration section */
+
+/* Begin XCConfigurationList section */
+		C056397F08A954F8003078D8 /* Build configuration list for PBXNativeTarget "LispControllerPluginFramework" */ = {
+			isa = XCConfigurationList;
+			buildConfigurations = (
+				C056398008A954F8003078D8 /* Debug */,
+				C056398108A954F8003078D8 /* Release */,
+			);
+			defaultConfigurationIsVisible = 0;
+			defaultConfigurationName = Release;
+		};
+		C056398308A954F8003078D8 /* Build configuration list for PBXNativeTarget "LispControllerPlugin" */ = {
+			isa = XCConfigurationList;
+			buildConfigurations = (
+				C056398408A954F8003078D8 /* Debug */,
+				C056398508A954F8003078D8 /* Release */,
+			);
+			defaultConfigurationIsVisible = 0;
+			defaultConfigurationName = Release;
+		};
+		C056398708A954F8003078D8 /* Build configuration list for PBXAggregateTarget "All" */ = {
+			isa = XCConfigurationList;
+			buildConfigurations = (
+				C056398808A954F8003078D8 /* Debug */,
+				C056398908A954F8003078D8 /* Release */,
+			);
+			defaultConfigurationIsVisible = 0;
+			defaultConfigurationName = Release;
+		};
+		C056398B08A954F8003078D8 /* Build configuration list for PBXProject "LispControllerPlugin" */ = {
+			isa = XCConfigurationList;
+			buildConfigurations = (
+				C056398C08A954F8003078D8 /* Debug */,
+				C056398D08A954F8003078D8 /* Release */,
+			);
+			defaultConfigurationIsVisible = 0;
+			defaultConfigurationName = Release;
+		};
+/* End XCConfigurationList section */
+	};
+	rootObject = 0259C573FE90428111CA0C5A /* Project object */;
+}
Index: /trunk/contrib/krueger/InterfaceProjects/Lisp IB Plugins/LispControllerPlugin/LispControllerPlugin_Prefix.pch
===================================================================
--- /trunk/contrib/krueger/InterfaceProjects/Lisp IB Plugins/LispControllerPlugin/LispControllerPlugin_Prefix.pch	(revision 13946)
+++ /trunk/contrib/krueger/InterfaceProjects/Lisp IB Plugins/LispControllerPlugin/LispControllerPlugin_Prefix.pch	(revision 13946)
@@ -0,0 +1,8 @@
+//
+// Prefix header for all source files of the 'LispControllerPlugin' target in the 'LispControllerPlugin' project.
+//
+
+#ifdef __OBJC__
+    #import <Cocoa/Cocoa.h>
+    #import <InterfaceBuilderKit/InterfaceBuilderKit.h>
+#endif
Index: /trunk/contrib/krueger/InterfaceProjects/Lisp IB Plugins/LispControllerPlugin/LispIntegration.m
===================================================================
--- /trunk/contrib/krueger/InterfaceProjects/Lisp IB Plugins/LispControllerPlugin/LispIntegration.m	(revision 13946)
+++ /trunk/contrib/krueger/InterfaceProjects/Lisp IB Plugins/LispControllerPlugin/LispIntegration.m	(revision 13946)
@@ -0,0 +1,50 @@
+//
+//  LispIntegration.m
+//  LispControllerPlugin
+//
+//  Created by Paul Krueger on 2/8/10.
+//  Copyright 2010. All rights reserved.
+//
+
+#import <InterfaceBuilderKit/InterfaceBuilderKit.h>
+#import <LispControllerInspector.h>
+#import <LispController.h>
+
+
+@implementation LispController ( LispController )
+
+- (void)ibPopulateKeyPaths:(NSMutableDictionary *)keyPaths {
+    [super ibPopulateKeyPaths:keyPaths];
+	
+	//  KVC-compliant properties.
+    [[keyPaths objectForKey:IBAttributeKeyPaths] addObjectsFromArray:[NSArray arrayWithObjects:
+																	  @"rootType",
+																	  @"readerFunc",
+																	  @"writerFunc",
+																	  @"countFunc",
+																	  @"selectFunc",
+																	  @"editedFunc",
+																	  @"addedFunc",
+																	  @"insertFunc",
+																	  @"deleteFunc",
+																	  @"addChildFunc",
+																	  @"childrenFunc",
+																	  @"maxDepth",
+																	  @"genRoot",
+																	  nil]];
+/*
+	[[keyPaths objectForKey:IBToManyRelationshipKeyPaths] addObjectsFromArray:[NSArray arrayWithObjects:
+																			   @"typeInfo",
+																			   @"initforms",
+																			   @"sortInfo",
+																			   nil]];
+ */
+}
+
+- (void)ibPopulateAttributeInspectorClasses:(NSMutableArray *)classes {
+    [super ibPopulateAttributeInspectorClasses:classes];
+    [classes addObject:[LispControllerInspector class]];
+}
+
+
+@end
Index: /trunk/contrib/krueger/InterfaceProjects/Lisp IB Plugins/LispControllerPlugin/version.plist
===================================================================
--- /trunk/contrib/krueger/InterfaceProjects/Lisp IB Plugins/LispControllerPlugin/version.plist	(revision 13946)
+++ /trunk/contrib/krueger/InterfaceProjects/Lisp IB Plugins/LispControllerPlugin/version.plist	(revision 13946)
@@ -0,0 +1,16 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
+<plist version="1.0">
+<dict>
+	<key>BuildVersion</key>
+	<string>1</string>
+	<key>CFBundleShortVersionString</key>
+	<string>1.0</string>
+	<key>CFBundleVersion</key>
+	<string>1</string>
+	<key>ProjectName</key>
+	<string>IBXcodeIntegration</string>
+	<key>SourceVersion</key>
+	<string>380000</string>
+</dict>
+</plist>
Index: /trunk/contrib/krueger/InterfaceProjects/Loan Calc/loan-calc.lisp
===================================================================
--- /trunk/contrib/krueger/InterfaceProjects/Loan Calc/loan-calc.lisp	(revision 13946)
+++ /trunk/contrib/krueger/InterfaceProjects/Loan Calc/loan-calc.lisp	(revision 13946)
@@ -0,0 +1,454 @@
+;;; loan-calc.lisp
+
+#|
+The MIT license.
+
+Copyright (c) 2010 Paul L. Krueger
+
+Permission is hereby granted, free of charge, to any person obtaining a copy of this software 
+and associated documentation files (the "Software"), to deal in the Software without restriction, 
+including without limitation the rights to use, copy, modify, merge, publish, distribute, 
+sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is 
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all copies or substantial 
+portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT 
+LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. 
+IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, 
+WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE 
+SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+|#
+
+;;; Sample lisp/Cocoa interface that uses a NIB file defined with interface builder;
+;;; A definition is provided for the "SpeechController" class that was specified to interface builder
+;;; as the class of the NIB file owner.
+;;; We manually create an instance of SpeechController and specify it as the owner for the NIB file.
+
+(eval-when (:compile-toplevel :load-toplevel :execute)
+  (require :nib)
+  (require :date)
+  (require :decimal))
+
+(defpackage :loan-calc
+  (:nicknames :lnc)
+  (:use :iu :ccl :common-lisp)
+  (:export test-loan))
+
+(in-package :lnc)
+
+;; The loan-controller class
+
+(defclass loan-controller (ns:ns-window-controller)
+  ((loan :foreign-type :id :accessor loan)
+   (loan-text :foreign-type :id :accessor loan-text)
+   (int-text :foreign-type :id :accessor int-text)
+   (dur-text :foreign-type :id :accessor dur-text)
+   (pay-text :foreign-type :id :accessor pay-text)
+   (int-slider :foreign-type :id :accessor int-slider)
+   (dur-slider :foreign-type :id :accessor dur-slider)
+   (pay-slider :foreign-type :id :accessor pay-slider))
+  (:metaclass ns:+ns-object))
+
+(objc:defmethod (#/initWithLoan: :id)
+                ((self loan-controller) (ln :id))
+  (setf (loan self) ln)
+  (let* ((nib-name (ccl::%make-nsstring 
+                    (namestring (truename "ip:Loan Calc;loan.nib"))))
+         (init-self (#/initWithWindowNibPath:owner: self nib-name self)))
+    init-self))
+
+;; Action methods that are called when controls do something
+
+(objc:defmethod (#/buttonPushed: :void) 
+                ((self loan-controller) (button-matrix :id))
+  (with-slots (loan loan-text int-text dur-text pay-text int-slider 
+                    dur-slider pay-slider) self
+    (let ((cm (#/selectedRow button-matrix)))
+      (unless (eql cm (compute-mode loan))
+        (case (compute-mode loan)
+          (0 (#/setEnabled: loan-text #$YES))
+          (1 (#/setEnabled: int-text #$YES)
+             (#/setEnabled: int-slider #$YES))
+          (2 (#/setEnabled: dur-text #$YES)
+             (#/setEnabled: dur-slider #$YES))
+          (3 (#/setEnabled: pay-text #$YES)
+             (#/setEnabled: pay-slider #$YES)))
+        (setf (compute-mode loan) cm)
+        (case cm
+          (0 (#/setEnabled: loan-text #$NO))
+          (1 (#/setEnabled: int-text #$NO)
+             (#/setEnabled: int-slider #$NO))
+          (2 (#/setEnabled: dur-text #$NO)
+             (#/setEnabled: dur-slider #$NO))
+          (3 (#/setEnabled: pay-text #$NO)
+             (#/setEnabled: pay-slider #$NO)))
+        (compute-new-loan-values loan)))))
+
+(objc:defmethod (#/awakeFromNib :void) 
+                ((self loan-controller))
+  (#/setEnabled: (loan-text self) #$NO)
+  ;; set the sliders to update continuously so that the text boxes reflect the current value
+  ;; Note that we can set this in IB for text boxes, but not, apparently, for sliders
+  (#/setContinuous: (int-slider self) #$YES)
+  (#/setContinuous: (dur-slider self) #$YES)
+  (#/setContinuous: (pay-slider self) #$YES))
+
+(objc:defmethod (#/windowWillClose: :void) 
+                ((self loan-controller) (notif :id))
+  (declare (ignore notif))
+  (when (loan self)
+    ;; Tell the loan that the window is closing
+    ;; It will #/autorelease this window-controller)
+    (window-closed (loan self))))
+
+
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;;;; Everything below is related to the loan data model
+
+(defconstant $max-interest-rate$ .5)
+
+;; Some loan utility functions
+
+;; all equations are derived from a basic loan equation for an N month loan:
+;; LoanPrinciple = MonthlyPayment * ( (1 / (1 + MonthlyInterest)) + 
+;;                                    (1 / (1 + MonthlyInterest)^2) + ... + 
+;;                                    (1 / (1 + MonthlyInterest)^N) )
+;; which can be manipulated to derive:
+;; MonthlyPayment = LoanPrinciple * (MonthlyInterest + (MonthlyInterest / ((1 + MonthlyInterest)^LoanDuration - 1)))
+
+(defun pay-to-loan-ratio (mo-int loan-dur)
+  ;; Just computes the MonthlyPayment/Loan ratio from the basic loan equation given above
+  (if (zerop mo-int) 0 
+    (+ mo-int (/ mo-int (1- (expt (1+ mo-int) loan-dur))))))
+
+;; The loan class
+
+(defclass loan (ns:ns-object)
+  ((loan-amount :accessor loan-amount :initform 0)
+   (interest-rate :accessor interest-rate :initform 0)
+   (loan-duration :accessor loan-duration :initform 0)
+   (monthly-payment :accessor monthly-payment :initform 0)
+   (origination-date :accessor origination-date :initform (now))
+   (first-payment :accessor first-payment :initform (next-month (now)))
+   (pay-schedule :accessor pay-schedule :initform nil)
+   (window-controller :accessor window-controller :initform nil)
+   (compute-mode :accessor compute-mode :initform 0)
+   (max-dur :foreign-type #>BOOL :accessor max-dur)
+   (min-dur :foreign-type #>BOOL :accessor min-dur)
+   (min-pay :foreign-type #>BOOL :accessor min-pay))
+  (:metaclass ns:+ns-object))
+
+
+;; Normal lisp methods for our class
+
+(defmethod initialize-instance :after ((self loan) 
+                                       &key &allow-other-keys)
+  (setf (window-controller self)
+        (make-instance (find-class 'loan-controller)
+          :with-loan self))
+  (#/showWindow: (window-controller self) self))
+
+(defmethod window-closed ((self loan))
+  ;; called by the window-controller to tell us that the window closed
+  (when (window-controller self)
+    (#/autorelease (window-controller self))
+    (setf (window-controller self) nil)))
+
+(defmethod close-loan ((self loan))
+  ;; just tell the window to close
+  (when (window-controller self)
+    (let ((win (#/window (window-controller self))))
+      ;; for reasons mysterious to me, calling #/window seems to
+      ;; also #/retain the window, so we'll #/release it
+      (#/release win)
+      (#/performClose: win self))))
+
+(defmethod set-pay-schedule ((self loan))
+  ;; create a detailed payment schedule for the loan using daily compounding of interest 
+  ;; Payments are on the same date of each month, but the number of days between payments
+  ;; varies because the number of days in each month varies.
+  ;; We compute accurate interest compounded daily for the actual number of days.
+  (let ((monthly-interest (/ (interest-rate self) 12))
+        (payment (monthly-payment self))
+        (sched nil)
+        (display-min-pay-banner nil))
+    (prog1
+        (do* ((begin (loan-amount self) end)
+              (begin-date (first-payment self) end-date)
+              (end-date (next-month begin-date) (next-month begin-date))
+              (int (round (* begin monthly-interest))
+                   (round (* begin monthly-interest)))
+              (end (- (+ begin int) payment) (- (+ begin int) payment)))
+             ((not (plusp end)) 
+              (progn
+                (push (list (short-date-string begin-date) 
+                            (/ begin 100)
+                            (/ int 100)
+                            (/ payment 100)
+                            (short-date-string end-date) 
+                            (/ end 100)
+                            int) 
+                      sched)
+                (setf (pay-schedule self) (nreverse sched))))
+          (when (>= end begin)
+            ;; oops, with this combination of values the loan will never 
+            ;; be paid off, so let's set a minimum payment required
+            ;; Display a field that tells user the minimum payment was reached 
+            (setf display-min-pay-banner t)
+            (#/willChangeValueForKey: self #@"monthlyPayment")
+            (setf (monthly-payment self) (1+ int))
+            (#/didChangeValueForKey: self #@"monthlyPayment")
+            ;; now patch up our loop variables and keep going
+            (setf payment (monthly-payment self))
+            (setf end (1- begin)))
+          ;; put the last payment into the list
+          (push (list (short-date-string begin-date) 
+                      (/ begin 100)
+                      (/ int 100)
+                      (/ payment 100)
+                      (short-date-string end-date) 
+                      (/ end 100)
+                      int)
+                sched))
+      (#/willChangeValueForKey: self #@"totInterest")
+      ;; we'll make the total interest field call our accessor 
+      ;; to generate a new amount
+      (#/didChangeValueForKey: self #@"totInterest")
+      (if display-min-pay-banner
+        (progn
+          ;; Set a condition that says the minimum payment was reached 
+          (setf display-min-pay-banner t)
+          (#/willChangeValueForKey: self #@"minPay")
+          (setf (min-pay self) #$YES)
+          (#/didChangeValueForKey: self #@"minPay"))
+        (progn
+          ;; otherwise reset that condition
+          (#/willChangeValueForKey: self #@"minPay")
+          (setf (min-pay self) #$NO)
+          (#/didChangeValueForKey: self #@"minPay")))
+      ;; If we happen to be computing the interest rate, then 
+      ;; the combination of loan-amount and monthly payment will
+      ;; determine a maximum interest rate. This, in turn, 
+      ;; determines a maximum loan duration. If the duration was set
+      ;; longer than this by the user, we will reset the 
+      ;; lone duration value to the maximum needed.
+      ;; If, on the other hand, the monthly payment is set so low that
+      ;; the interest rate approaches 0, then we may have to adjust the
+      ;; loan duration up to the minimum needed to pay the loan.
+      ;; Let's start by resetting our two "duration" conditions and then we'll
+      ;; set them if conditions dictate.
+      ;; Reset a condition that indicates the max duration was reached 
+      (#/willChangeValueForKey: self #@"maxDur")
+      (setf (max-dur self) #$NO)
+      (#/didChangeValueForKey: self #@"maxDur")
+      ;; Reset a condition that indicates the min duration was reached 
+      (#/willChangeValueForKey: self #@"minDur")
+      (setf (min-dur self) #$NO)
+      (#/didChangeValueForKey: self #@"minDur"))
+      (let ((duration-diff (- (loan-duration self) (list-length (pay-schedule self)))))
+        (unless (or (eql (compute-mode self) 2) (zerop duration-diff))
+          ;; i.e. we're not calling this function just to determine the loan duration
+          ;; and we have to adjust the loan duration
+          (if (plusp duration-diff)
+            (progn
+              ;; change the loan-duration value to what it must be
+              (#/willChangeValueForKey: self #@"loanDuration")
+              (setf (loan-duration self) (list-length (pay-schedule self)))
+              (#/didChangeValueForKey: self #@"loanDuration")
+              (when (> duration-diff 2)
+                ;; If we're one-off just fix it and don't post a message
+                ;; This can occur almost anytime because of numerical issues
+                ;; Display a field that tells user the max duration was reached 
+                (#/willChangeValueForKey: self #@"maxDur")
+                (setf (max-dur self) #$YES)
+                (#/didChangeValueForKey: self #@"maxDur")))
+            (progn
+              ;; change the oan-duration value to what it must be
+              (#/willChangeValueForKey: self #@"loanDuration")
+              (setf (loan-duration self) (list-length (pay-schedule self)))
+              (#/didChangeValueForKey: self #@"loanDuration")
+              (when (< duration-diff -2)
+                ;; If we're one-off just fix it and don't post a message
+                ;; This can occur almost anytime because of numerical issues
+                ;; Display a field that tells user the min duration was reached 
+                (#/willChangeValueForKey: self #@"minDur")
+                (setf (min-dur self) #$YES)
+                (#/didChangeValueForKey: self #@"minDur"))))))))
+
+(defmethod print-pay-schedule ((self loan) &optional (strm t))
+  (format strm 
+          "~:{~%On ~a balance = $~$ + interest of $~$ - payment of $~$ = ~a balance of $~$~}"
+          (pay-schedule self)))
+
+(defmethod compute-int-rate ((self loan))
+  ;; Find a monthly interest rate that makes the rest of the values work.
+  ;; There isn't an algebraic solution for the interest rate, so let's search for it.
+  ;; Find a suitable search range and do a binary search for it. Even for large interest 
+  ;; rates the number of search iterations should be minimal.
+
+  (with-slots (loan-amount monthly-payment loan-duration interest-rate) self
+  
+    ;; First we'll check to see whether the monthly payment is great than the loan amount.
+    ;; If so we'll set the interest rate directly so that the loan is paid off in one month.
+    ;; This avoids some ugly arithmetic overflow things that can happen when interest rates
+    ;; go off the charts
+    (let ((max-monthly-rate (/ $max-interest-rate$ 12)))
+      (if (>= monthly-payment loan-amount)
+        (min max-monthly-rate (1- (/ monthly-payment loan-amount)))
+        (let ((imin (max 0 (min max-monthly-rate
+                                (/ (- (* monthly-payment loan-duration) loan-amount) 
+                                   (* loan-duration loan-amount)))))
+              ;; imin is basically a rate that would result in the first month's interest as 
+              ;; the average interest paid for all months. Since we know it must be greater 
+              ;; than this, we have a guaranteed lower bound. But we cap it at our allowed 
+              ;; monthly maximum interest.
+              (imax (min max-monthly-rate 
+                         (- (/ monthly-payment loan-amount) .000008333)))
+              ;; imax is a rate that would result in the first month's interest being 
+              ;; minimally smaller than the payment. Since we must pay off in a finite
+              ;; duration, this is a guaranteed maximum. We cap it the allowed maximum 
+              ;; monthly rate.
+              (target-p-l-ratio (/ monthly-payment loan-amount)))
+          (unless (>= imax imin)
+            (error "Max int = ~8,4f, Min int = ~8,4f" imax imin))
+          (do* ((i (/ (+ imin imax) 2) 
+                   (/ (+ imin imax) 2))
+                (p-l-ratio (pay-to-loan-ratio i loan-duration) 
+                           (pay-to-loan-ratio i loan-duration)))
+               ((<= (- imax imin) .000001) imax)
+            (if (>= target-p-l-ratio p-l-ratio)
+              (setf imin i)
+              (setf imax i))))))))
+
+(defmethod compute-new-loan-values ((self loan))
+  ;; For the sake of expediency we assume monthly componding
+  ;; The basic equation governing these computations is 
+  (with-slots (compute-mode interest-rate loan-duration monthly-payment 
+                            loan-amount pay-schedule) self
+    (case compute-mode
+      (0
+       ;; compute the loan amount
+       (unless (or (zerop interest-rate)
+                   (zerop loan-duration)
+                   (zerop monthly-payment))
+         (#/willChangeValueForKey: self #@"loanAmt")
+         (setf loan-amount 
+               (round (/ monthly-payment 
+                         (pay-to-loan-ratio (/ interest-rate 12)
+                                            loan-duration))))
+         (set-pay-schedule self)
+         (#/didChangeValueForKey: self #@"loanAmt")))
+      (1
+       ;; compute the interest rate
+       (unless (or (zerop loan-amount)
+                   (zerop loan-duration)
+                   (zerop monthly-payment))
+         (#/willChangeValueForKey: self #@"interestRate")
+         (setf interest-rate 
+               (* 12 (/ (floor (* 1000000 (compute-int-rate self)))
+                        1000000)))
+         (set-pay-schedule self)
+         (#/didChangeValueForKey: self #@"interestRate")))
+      (2
+       ;; compute the loan duration
+       (unless (or (zerop interest-rate)
+                   (zerop loan-amount)
+                   (zerop monthly-payment))
+         (#/willChangeValueForKey: self #@"loanDuration")
+         (set-pay-schedule self)
+         (setf loan-duration
+               (list-length pay-schedule))
+         (#/didChangeValueForKey: self #@"loanDuration")))
+      (3
+       ;; compute the monthly payment
+       (unless (or (zerop interest-rate)
+                   (zerop loan-amount)
+                   (zerop loan-duration))
+         (#/willChangeValueForKey: self #@"monthlyPayment")
+         (setf monthly-payment
+               (round (* loan-amount 
+                         (pay-to-loan-ratio (/ interest-rate 12) 
+                                            loan-duration))))
+         (set-pay-schedule self)
+         (#/didChangeValueForKey: self #@"monthlyPayment"))))))
+
+;; Accessor functions used by display objects to retrieve and set values as dictated
+;; by the bindings we set up in IB
+
+(objc:defmethod (#/loanAmt :id)
+                ((self loan))
+  (lisp-to-ns-decimal (loan-amount self)))
+
+(objc:defmethod (#/interestRate :id)
+                ((self loan))
+  (#/numberWithFloat: ns:ns-number (float (interest-rate self))))
+
+(objc:defmethod (#/loanDuration :id)
+                ((self loan))
+  (#/numberWithInt: ns:ns-number (loan-duration self)))
+
+(objc:defmethod (#/monthlyPayment :id)
+                ((self loan))
+  (lisp-to-ns-decimal (monthly-payment self)))
+
+(objc:defmethod (#/originationDate :id)
+                ((self loan))
+  (lisp-to-ns-date (origination-date self)))
+
+(objc:defmethod (#/firstPayment :id)
+                ((self loan))
+  (lisp-to-ns-date (first-payment self)))
+
+(objc:defmethod (#/totInterest :id)
+                ((self loan))
+  (lisp-to-ns-decimal (reduce #'+ (pay-schedule self) 
+                              :key #'seventh 
+                              :initial-value 0)))
+
+(objc:defmethod (#/setLoanAmt: :void)
+                ((self loan) (amt :id))
+  (setf (loan-amount self) (lisp-from-ns-decimal amt))
+  (compute-new-loan-values self))
+
+(objc:defmethod (#/setInterestRate: :void)
+                ((self loan) (rate :id))
+  (setf (interest-rate self) (#/floatValue rate))
+  (compute-new-loan-values self))
+
+(objc:defmethod (#/setLoanDuration: :void)
+                ((self loan) (dur :id))
+  (setf (loan-duration self) (#/longValue dur))
+  (compute-new-loan-values self))
+
+(objc:defmethod (#/setMonthlyPayment: :void)
+                ((self loan) (pay :id))
+  (setf (monthly-payment self) (lisp-from-ns-decimal pay))
+  (compute-new-loan-values self))
+
+(objc:defmethod (#/setOriginationDate: :void)
+                ((self loan) (dt :id))
+  (let ((new-dt (ns-to-lisp-date dt)))
+    (setf (origination-date self) new-dt)
+    (#/willChangeValueForKey: self #@"firstPayment")
+    (setf (first-payment self) (next-month new-dt))
+    (#/didChangeValueForKey: self #@"firstPayment"))
+  (compute-new-loan-values self))
+
+(objc:defmethod (#/setFirstPayment: :void) 
+                ((self loan) (pay :id))
+  (let ((new-pay (ns-to-lisp-date pay)))
+    (setf (first-payment self) new-pay))
+  (compute-new-loan-values self))
+
+
+
+;; test by
+(defun test-loan ()
+  ;; up to caller to #/release the returned loan instance
+  ;; but only after window is closed or crash will occur
+  (make-instance 'loan))
+
+(provide :loan-calc)
Index: /trunk/contrib/krueger/InterfaceProjects/Loan Calc/loan.nib/designable.nib
===================================================================
--- /trunk/contrib/krueger/InterfaceProjects/Loan Calc/loan.nib/designable.nib	(revision 13946)
+++ /trunk/contrib/krueger/InterfaceProjects/Loan Calc/loan.nib/designable.nib	(revision 13946)
@@ -0,0 +1,2129 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<archive type="com.apple.InterfaceBuilder3.Cocoa.XIB" version="7.03">
+	<data>
+		<int key="IBDocument.SystemTarget">1050</int>
+		<string key="IBDocument.SystemVersion">9L30</string>
+		<string key="IBDocument.InterfaceBuilderVersion">680</string>
+		<string key="IBDocument.AppKitVersion">949.54</string>
+		<string key="IBDocument.HIToolboxVersion">353.00</string>
+		<object class="NSMutableArray" key="IBDocument.EditedObjectIDs">
+			<bool key="EncodedWithXMLCoder">YES</bool>
+			<integer value="2" id="10"/>
+		</object>
+		<object class="NSArray" key="IBDocument.PluginDependencies">
+			<bool key="EncodedWithXMLCoder">YES</bool>
+			<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
+		</object>
+		<object class="NSMutableDictionary" key="IBDocument.Metadata">
+			<bool key="EncodedWithXMLCoder">YES</bool>
+			<object class="NSArray" key="dict.sortedKeys">
+				<bool key="EncodedWithXMLCoder">YES</bool>
+			</object>
+			<object class="NSMutableArray" key="dict.values">
+				<bool key="EncodedWithXMLCoder">YES</bool>
+			</object>
+		</object>
+		<object class="NSMutableArray" key="IBDocument.RootObjects" id="1000">
+			<bool key="EncodedWithXMLCoder">YES</bool>
+			<object class="NSCustomObject" id="1001">
+				<string key="NSClassName">LoanController</string>
+			</object>
+			<object class="NSCustomObject" id="1003">
+				<string key="NSClassName">FirstResponder</string>
+			</object>
+			<object class="NSCustomObject" id="1004">
+				<string key="NSClassName">NSApplication</string>
+			</object>
+			<object class="NSWindowTemplate" id="1005">
+				<int key="NSWindowStyleMask">7</int>
+				<int key="NSWindowBacking">2</int>
+				<string key="NSWindowRect">{{196, 12}, {527, 498}}</string>
+				<int key="NSWTFlags">536870912</int>
+				<string key="NSWindowTitle">Loan Calculator</string>
+				<string key="NSWindowClass">NSWindow</string>
+				<nil key="NSViewClass"/>
+				<string key="NSWindowContentMaxSize">{3.40282e+38, 3.40282e+38}</string>
+				<object class="NSView" key="NSWindowView" id="1006">
+					<reference key="NSNextResponder"/>
+					<int key="NSvFlags">256</int>
+					<object class="NSMutableArray" key="NSSubviews">
+						<bool key="EncodedWithXMLCoder">YES</bool>
+						<object class="NSSlider" id="502682855">
+							<reference key="NSNextResponder" ref="1006"/>
+							<int key="NSvFlags">268</int>
+							<string key="NSFrame">{{31, 360}, {284, 21}}</string>
+							<reference key="NSSuperview" ref="1006"/>
+							<bool key="NSEnabled">YES</bool>
+							<object class="NSSliderCell" key="NSCell" id="232181660">
+								<int key="NSCellFlags">-2080244224</int>
+								<int key="NSCellFlags2">0</int>
+								<string key="NSContents"/>
+								<object class="NSFont" key="NSSupport" id="2332340">
+									<string key="NSName">Helvetica</string>
+									<double key="NSSize">1.200000e+01</double>
+									<int key="NSfFlags">16</int>
+								</object>
+								<reference key="NSControlView" ref="502682855"/>
+								<double key="NSMaxValue">5.000000e-01</double>
+								<double key="NSMinValue">0.000000e+00</double>
+								<double key="NSValue">1.000000e-01</double>
+								<double key="NSAltIncValue">0.000000e+00</double>
+								<int key="NSNumberOfTickMarks">0</int>
+								<int key="NSTickMarkPosition">0</int>
+								<bool key="NSAllowsTickMarkValuesOnly">YES</bool>
+								<bool key="NSVertical">NO</bool>
+							</object>
+						</object>
+						<object class="NSSlider" id="857285538">
+							<reference key="NSNextResponder" ref="1006"/>
+							<int key="NSvFlags">268</int>
+							<string key="NSFrame">{{31, 280}, {284, 21}}</string>
+							<reference key="NSSuperview" ref="1006"/>
+							<bool key="NSEnabled">YES</bool>
+							<object class="NSSliderCell" key="NSCell" id="616540554">
+								<int key="NSCellFlags">-2080244224</int>
+								<int key="NSCellFlags2">0</int>
+								<string key="NSContents"/>
+								<reference key="NSSupport" ref="2332340"/>
+								<reference key="NSControlView" ref="857285538"/>
+								<double key="NSMaxValue">5.000000e+02</double>
+								<double key="NSMinValue">0.000000e+00</double>
+								<double key="NSValue">1.200000e+02</double>
+								<double key="NSAltIncValue">0.000000e+00</double>
+								<int key="NSNumberOfTickMarks">0</int>
+								<int key="NSTickMarkPosition">1</int>
+								<bool key="NSAllowsTickMarkValuesOnly">NO</bool>
+								<bool key="NSVertical">NO</bool>
+							</object>
+						</object>
+						<object class="NSSlider" id="82942187">
+							<reference key="NSNextResponder" ref="1006"/>
+							<int key="NSvFlags">268</int>
+							<string key="NSFrame">{{31, 192}, {284, 21}}</string>
+							<reference key="NSSuperview" ref="1006"/>
+							<bool key="NSEnabled">YES</bool>
+							<object class="NSSliderCell" key="NSCell" id="618853427">
+								<int key="NSCellFlags">-2080244224</int>
+								<int key="NSCellFlags2">0</int>
+								<string key="NSContents"/>
+								<reference key="NSSupport" ref="2332340"/>
+								<reference key="NSControlView" ref="82942187"/>
+								<double key="NSMaxValue">1.000000e+04</double>
+								<double key="NSMinValue">0.000000e+00</double>
+								<double key="NSValue">1.000000e+02</double>
+								<double key="NSAltIncValue">0.000000e+00</double>
+								<int key="NSNumberOfTickMarks">0</int>
+								<int key="NSTickMarkPosition">1</int>
+								<bool key="NSAllowsTickMarkValuesOnly">NO</bool>
+								<bool key="NSVertical">NO</bool>
+							</object>
+						</object>
+						<object class="NSTextField" id="1025071149">
+							<reference key="NSNextResponder" ref="1006"/>
+							<int key="NSvFlags">268</int>
+							<string key="NSFrame">{{107, 387}, {145, 17}}</string>
+							<reference key="NSSuperview" ref="1006"/>
+							<bool key="NSEnabled">YES</bool>
+							<object class="NSTextFieldCell" key="NSCell" id="311690344">
+								<int key="NSCellFlags">68288064</int>
+								<int key="NSCellFlags2">272630784</int>
+								<string key="NSContents">Annual Interest Rate %</string>
+								<object class="NSFont" key="NSSupport" id="227377946">
+									<string key="NSName">LucidaGrande</string>
+									<double key="NSSize">1.300000e+01</double>
+									<int key="NSfFlags">1044</int>
+								</object>
+								<reference key="NSControlView" ref="1025071149"/>
+								<object class="NSColor" key="NSBackgroundColor" id="344940583">
+									<int key="NSColorSpace">6</int>
+									<string key="NSCatalogName">System</string>
+									<string key="NSColorName">controlColor</string>
+									<object class="NSColor" key="NSColor">
+										<int key="NSColorSpace">3</int>
+										<bytes key="NSWhite">MC42NjY2NjY2OQA</bytes>
+									</object>
+								</object>
+								<object class="NSColor" key="NSTextColor" id="942182489">
+									<int key="NSColorSpace">6</int>
+									<string key="NSCatalogName">System</string>
+									<string key="NSColorName">controlTextColor</string>
+									<object class="NSColor" key="NSColor" id="752056265">
+										<int key="NSColorSpace">3</int>
+										<bytes key="NSWhite">MAA</bytes>
+									</object>
+								</object>
+							</object>
+						</object>
+						<object class="NSTextField" id="79509684">
+							<reference key="NSNextResponder" ref="1006"/>
+							<int key="NSvFlags">268</int>
+							<string key="NSFrame">{{95, 302}, {154, 17}}</string>
+							<reference key="NSSuperview" ref="1006"/>
+							<bool key="NSEnabled">YES</bool>
+							<object class="NSTextFieldCell" key="NSCell" id="961478139">
+								<int key="NSCellFlags">68288064</int>
+								<int key="NSCellFlags2">272630784</int>
+								<string key="NSContents">Loan Duration (months)</string>
+								<reference key="NSSupport" ref="227377946"/>
+								<reference key="NSControlView" ref="79509684"/>
+								<reference key="NSBackgroundColor" ref="344940583"/>
+								<reference key="NSTextColor" ref="942182489"/>
+							</object>
+						</object>
+						<object class="NSTextField" id="767489727">
+							<reference key="NSNextResponder" ref="1006"/>
+							<int key="NSvFlags">268</int>
+							<string key="NSFrame">{{116, 219}, {167, 17}}</string>
+							<reference key="NSSuperview" ref="1006"/>
+							<bool key="NSEnabled">YES</bool>
+							<object class="NSTextFieldCell" key="NSCell" id="487292094">
+								<int key="NSCellFlags">68288064</int>
+								<int key="NSCellFlags2">272630784</int>
+								<string key="NSContents">Monthly Payment</string>
+								<reference key="NSSupport" ref="227377946"/>
+								<reference key="NSControlView" ref="767489727"/>
+								<reference key="NSBackgroundColor" ref="344940583"/>
+								<reference key="NSTextColor" ref="942182489"/>
+							</object>
+						</object>
+						<object class="NSTextField" id="583982648">
+							<reference key="NSNextResponder" ref="1006"/>
+							<int key="NSvFlags">268</int>
+							<string key="NSFrame">{{365, 360}, {118, 22}}</string>
+							<reference key="NSSuperview" ref="1006"/>
+							<bool key="NSEnabled">YES</bool>
+							<object class="NSTextFieldCell" key="NSCell" id="5436249">
+								<int key="NSCellFlags">-1804468671</int>
+								<int key="NSCellFlags2">-2076179456</int>
+								<string key="NSContents"/>
+								<reference key="NSSupport" ref="227377946"/>
+								<object class="NSNumberFormatter" key="NSFormatter" id="801243361">
+									<object class="NSMutableDictionary" key="NS.attributes">
+										<bool key="EncodedWithXMLCoder">YES</bool>
+										<object class="NSMutableArray" key="dict.sortedKeys">
+											<bool key="EncodedWithXMLCoder">YES</bool>
+											<string>allowsFloats</string>
+											<string>formatterBehavior</string>
+											<string>maximumFractionDigits</string>
+											<string>maximumIntegerDigits</string>
+											<string>minimumIntegerDigits</string>
+											<string>multiplier</string>
+											<string>numberStyle</string>
+										</object>
+										<object class="NSMutableArray" key="dict.values">
+											<bool key="EncodedWithXMLCoder">YES</bool>
+											<integer value="1" id="9"/>
+											<integer value="1040"/>
+											<integer value="4"/>
+											<integer value="10"/>
+											<integer value="0" id="8"/>
+											<real value="1.000000e+02"/>
+											<integer value="3"/>
+										</object>
+									</object>
+									<string key="NS.positiveformat">#,###.####%</string>
+									<string key="NS.negativeformat">#,###.####%</string>
+									<nil key="NS.positiveattrs"/>
+									<nil key="NS.negativeattrs"/>
+									<object class="NSAttributedString" key="NS.zero">
+										<nil key="NSString"/>
+									</object>
+									<object class="NSAttributedString" key="NS.nil">
+										<nil key="NSString"/>
+									</object>
+									<object class="NSAttributedString" key="NS.nan">
+										<string key="NSString">NaN</string>
+										<object class="NSDictionary" key="NSAttributes" id="932461654">
+											<bool key="EncodedWithXMLCoder">YES</bool>
+											<object class="NSArray" key="dict.sortedKeys">
+												<bool key="EncodedWithXMLCoder">YES</bool>
+											</object>
+											<object class="NSMutableArray" key="dict.values">
+												<bool key="EncodedWithXMLCoder">YES</bool>
+											</object>
+										</object>
+									</object>
+									<object class="NSDecimalNumberPlaceholder" key="NS.min" id="325159587">
+										<int key="NS.exponent">0</int>
+										<int key="NS.length">0</int>
+										<bool key="NS.negative">YES</bool>
+										<bool key="NS.compact">NO</bool>
+										<int key="NS.mantissa.bo">1</int>
+										<bytes key="NS.mantissa">AAAAAAAAAAAAAAAAAAAAAA</bytes>
+									</object>
+									<reference key="NS.max" ref="325159587"/>
+									<object class="NSDecimalNumberHandler" key="NS.rounding">
+										<int key="NS.roundingmode">3</int>
+										<bool key="NS.raise.overflow">YES</bool>
+										<bool key="NS.raise.underflow">YES</bool>
+										<bool key="NS.raise.dividebyzero">YES</bool>
+									</object>
+									<string key="NS.decimal">.</string>
+									<string key="NS.thousand">,</string>
+									<bool key="NS.hasthousands">YES</bool>
+									<bool key="NS.localized">YES</bool>
+									<bool key="NS.allowsfloats">YES</bool>
+								</object>
+								<reference key="NSControlView" ref="583982648"/>
+								<bool key="NSDrawsBackground">YES</bool>
+								<object class="NSColor" key="NSBackgroundColor" id="627117864">
+									<int key="NSColorSpace">6</int>
+									<string key="NSCatalogName">System</string>
+									<string key="NSColorName">textBackgroundColor</string>
+									<object class="NSColor" key="NSColor" id="72801970">
+										<int key="NSColorSpace">3</int>
+										<bytes key="NSWhite">MQA</bytes>
+									</object>
+								</object>
+								<object class="NSColor" key="NSTextColor" id="394575910">
+									<int key="NSColorSpace">6</int>
+									<string key="NSCatalogName">System</string>
+									<string key="NSColorName">textColor</string>
+									<reference key="NSColor" ref="752056265"/>
+								</object>
+							</object>
+						</object>
+						<object class="NSTextField" id="125608385">
+							<reference key="NSNextResponder" ref="1006"/>
+							<int key="NSvFlags">268</int>
+							<string key="NSFrame">{{365, 277}, {118, 22}}</string>
+							<reference key="NSSuperview" ref="1006"/>
+							<bool key="NSEnabled">YES</bool>
+							<object class="NSTextFieldCell" key="NSCell" id="1071273742">
+								<int key="NSCellFlags">-1804468671</int>
+								<int key="NSCellFlags2">-2076179456</int>
+								<string key="NSContents"/>
+								<reference key="NSSupport" ref="227377946"/>
+								<object class="NSNumberFormatter" key="NSFormatter" id="757491514">
+									<object class="NSMutableDictionary" key="NS.attributes">
+										<bool key="EncodedWithXMLCoder">YES</bool>
+										<object class="NSMutableArray" key="dict.sortedKeys">
+											<bool key="EncodedWithXMLCoder">YES</bool>
+											<string>allowsFloats</string>
+											<string>formatterBehavior</string>
+											<string>numberStyle</string>
+										</object>
+										<object class="NSMutableArray" key="dict.values">
+											<bool key="EncodedWithXMLCoder">YES</bool>
+											<boolean value="NO" id="6"/>
+											<integer value="1040"/>
+											<reference ref="8"/>
+										</object>
+									</object>
+									<string key="NS.positiveformat">#</string>
+									<string key="NS.negativeformat">#</string>
+									<nil key="NS.positiveattrs"/>
+									<nil key="NS.negativeattrs"/>
+									<object class="NSAttributedString" key="NS.zero">
+										<nil key="NSString"/>
+									</object>
+									<object class="NSAttributedString" key="NS.nil">
+										<nil key="NSString"/>
+									</object>
+									<object class="NSAttributedString" key="NS.nan">
+										<string key="NSString">NaN</string>
+										<reference key="NSAttributes" ref="932461654"/>
+									</object>
+									<reference key="NS.min" ref="325159587"/>
+									<reference key="NS.max" ref="325159587"/>
+									<object class="NSDecimalNumberHandler" key="NS.rounding">
+										<int key="NS.roundingmode">3</int>
+										<bool key="NS.raise.overflow">YES</bool>
+										<bool key="NS.raise.underflow">YES</bool>
+										<bool key="NS.raise.dividebyzero">YES</bool>
+									</object>
+									<string key="NS.decimal">.</string>
+									<string key="NS.thousand">,</string>
+									<bool key="NS.hasthousands">NO</bool>
+									<bool key="NS.localized">YES</bool>
+									<bool key="NS.allowsfloats">NO</bool>
+								</object>
+								<reference key="NSControlView" ref="125608385"/>
+								<bool key="NSDrawsBackground">YES</bool>
+								<reference key="NSBackgroundColor" ref="627117864"/>
+								<reference key="NSTextColor" ref="394575910"/>
+							</object>
+						</object>
+						<object class="NSTextField" id="644051649">
+							<reference key="NSNextResponder" ref="1006"/>
+							<int key="NSvFlags">268</int>
+							<string key="NSFrame">{{365, 189}, {118, 22}}</string>
+							<reference key="NSSuperview" ref="1006"/>
+							<bool key="NSEnabled">YES</bool>
+							<object class="NSTextFieldCell" key="NSCell" id="111648228">
+								<int key="NSCellFlags">-1804468671</int>
+								<int key="NSCellFlags2">-2076179456</int>
+								<string key="NSContents"/>
+								<reference key="NSSupport" ref="227377946"/>
+								<object class="NSNumberFormatter" key="NSFormatter" id="123140303">
+									<object class="NSMutableDictionary" key="NS.attributes">
+										<bool key="EncodedWithXMLCoder">YES</bool>
+										<object class="NSMutableArray" key="dict.sortedKeys">
+											<bool key="EncodedWithXMLCoder">YES</bool>
+											<string>allowsFloats</string>
+											<string>alwaysShowsDecimalSeparator</string>
+											<string>formatterBehavior</string>
+											<string>generatesDecimalNumbers</string>
+											<string>numberStyle</string>
+										</object>
+										<object class="NSMutableArray" key="dict.values">
+											<bool key="EncodedWithXMLCoder">YES</bool>
+											<boolean value="YES" id="5"/>
+											<reference ref="5"/>
+											<integer value="1040"/>
+											<reference ref="5"/>
+											<reference ref="10"/>
+										</object>
+									</object>
+									<string type="base64-UTF8" key="NS.positiveformat">wqQjLCMjMC4wMA</string>
+									<string type="base64-UTF8" key="NS.negativeformat">KMKkIywjIzAuMDApA</string>
+									<nil key="NS.positiveattrs"/>
+									<nil key="NS.negativeattrs"/>
+									<object class="NSAttributedString" key="NS.zero">
+										<nil key="NSString"/>
+									</object>
+									<object class="NSAttributedString" key="NS.nil">
+										<nil key="NSString"/>
+									</object>
+									<object class="NSAttributedString" key="NS.nan">
+										<string key="NSString">NaN</string>
+										<reference key="NSAttributes" ref="932461654"/>
+									</object>
+									<reference key="NS.min" ref="325159587"/>
+									<reference key="NS.max" ref="325159587"/>
+									<object class="NSDecimalNumberHandler" key="NS.rounding">
+										<int key="NS.roundingmode">3</int>
+										<bool key="NS.raise.overflow">YES</bool>
+										<bool key="NS.raise.underflow">YES</bool>
+										<bool key="NS.raise.dividebyzero">YES</bool>
+									</object>
+									<string key="NS.decimal">.</string>
+									<string key="NS.thousand">,</string>
+									<bool key="NS.hasthousands">YES</bool>
+									<bool key="NS.localized">YES</bool>
+									<bool key="NS.allowsfloats">YES</bool>
+								</object>
+								<reference key="NSControlView" ref="644051649"/>
+								<bool key="NSDrawsBackground">YES</bool>
+								<reference key="NSBackgroundColor" ref="627117864"/>
+								<reference key="NSTextColor" ref="394575910"/>
+							</object>
+						</object>
+						<object class="NSTextField" id="809137054">
+							<reference key="NSNextResponder" ref="1006"/>
+							<int key="NSvFlags">268</int>
+							<string key="NSFrame">{{365, 441}, {118, 22}}</string>
+							<reference key="NSSuperview" ref="1006"/>
+							<bool key="NSEnabled">YES</bool>
+							<object class="NSTextFieldCell" key="NSCell" id="310865555">
+								<int key="NSCellFlags">-1804468671</int>
+								<int key="NSCellFlags2">-2076179456</int>
+								<string key="NSContents"/>
+								<reference key="NSSupport" ref="227377946"/>
+								<object class="NSNumberFormatter" key="NSFormatter" id="506223138">
+									<object class="NSMutableDictionary" key="NS.attributes">
+										<bool key="EncodedWithXMLCoder">YES</bool>
+										<object class="NSMutableArray" key="dict.sortedKeys">
+											<bool key="EncodedWithXMLCoder">YES</bool>
+											<string>allowsFloats</string>
+											<string>alwaysShowsDecimalSeparator</string>
+											<string>formatterBehavior</string>
+											<string>generatesDecimalNumbers</string>
+											<string>numberStyle</string>
+										</object>
+										<object class="NSMutableArray" key="dict.values">
+											<bool key="EncodedWithXMLCoder">YES</bool>
+											<reference ref="5"/>
+											<reference ref="5"/>
+											<integer value="1040"/>
+											<reference ref="5"/>
+											<reference ref="10"/>
+										</object>
+									</object>
+									<string type="base64-UTF8" key="NS.positiveformat">wqQjLCMjMC4wMA</string>
+									<string type="base64-UTF8" key="NS.negativeformat">KMKkIywjIzAuMDApA</string>
+									<nil key="NS.positiveattrs"/>
+									<nil key="NS.negativeattrs"/>
+									<object class="NSAttributedString" key="NS.zero">
+										<nil key="NSString"/>
+									</object>
+									<object class="NSAttributedString" key="NS.nil">
+										<nil key="NSString"/>
+									</object>
+									<object class="NSAttributedString" key="NS.nan">
+										<string key="NSString">NaN</string>
+										<reference key="NSAttributes" ref="932461654"/>
+									</object>
+									<reference key="NS.min" ref="325159587"/>
+									<reference key="NS.max" ref="325159587"/>
+									<object class="NSDecimalNumberHandler" key="NS.rounding">
+										<int key="NS.roundingmode">3</int>
+										<bool key="NS.raise.overflow">YES</bool>
+										<bool key="NS.raise.underflow">YES</bool>
+										<bool key="NS.raise.dividebyzero">YES</bool>
+									</object>
+									<string key="NS.decimal">.</string>
+									<string key="NS.thousand">,</string>
+									<bool key="NS.hasthousands">YES</bool>
+									<bool key="NS.localized">YES</bool>
+									<bool key="NS.allowsfloats">YES</bool>
+								</object>
+								<reference key="NSControlView" ref="809137054"/>
+								<bool key="NSDrawsBackground">YES</bool>
+								<reference key="NSBackgroundColor" ref="627117864"/>
+								<reference key="NSTextColor" ref="394575910"/>
+							</object>
+						</object>
+						<object class="NSTextField" id="229354320">
+							<reference key="NSNextResponder" ref="1006"/>
+							<int key="NSvFlags">268</int>
+							<string key="NSFrame">{{379, 471}, {89, 17}}</string>
+							<reference key="NSSuperview" ref="1006"/>
+							<bool key="NSEnabled">YES</bool>
+							<object class="NSTextFieldCell" key="NSCell" id="767188954">
+								<int key="NSCellFlags">68288064</int>
+								<int key="NSCellFlags2">272630784</int>
+								<string key="NSContents">Loan Amount</string>
+								<reference key="NSSupport" ref="227377946"/>
+								<reference key="NSControlView" ref="229354320"/>
+								<reference key="NSBackgroundColor" ref="344940583"/>
+								<reference key="NSTextColor" ref="942182489"/>
+							</object>
+						</object>
+						<object class="NSMatrix" id="628774051">
+							<reference key="NSNextResponder" ref="1006"/>
+							<int key="NSvFlags">268</int>
+							<string key="NSFrame">{{49, 37}, {137, 78}}</string>
+							<reference key="NSSuperview" ref="1006"/>
+							<bool key="NSEnabled">YES</bool>
+							<int key="NSNumRows">4</int>
+							<int key="NSNumCols">1</int>
+							<object class="NSMutableArray" key="NSCells">
+								<bool key="EncodedWithXMLCoder">YES</bool>
+								<object class="NSButtonCell" id="853217630">
+									<int key="NSCellFlags">-2080244224</int>
+									<int key="NSCellFlags2">0</int>
+									<string key="NSContents">Loan Amount</string>
+									<reference key="NSSupport" ref="227377946"/>
+									<reference key="NSControlView" ref="628774051"/>
+									<int key="NSButtonFlags">1211912703</int>
+									<int key="NSButtonFlags2">128</int>
+									<object class="NSButtonImageSource" key="NSAlternateImage" id="103585188">
+										<string key="NSImageName">NSRadioButton</string>
+									</object>
+									<string key="NSAlternateContents"/>
+									<string key="NSKeyEquivalent"/>
+									<int key="NSPeriodicDelay">200</int>
+									<int key="NSPeriodicInterval">25</int>
+								</object>
+								<object class="NSButtonCell" id="46258786">
+									<int key="NSCellFlags">67239424</int>
+									<int key="NSCellFlags2">0</int>
+									<string key="NSContents">Interest Rate</string>
+									<reference key="NSSupport" ref="227377946"/>
+									<reference key="NSControlView" ref="628774051"/>
+									<int key="NSButtonFlags">1211912703</int>
+									<int key="NSButtonFlags2">128</int>
+									<object class="NSImage" key="NSNormalImage">
+										<int key="NSImageFlags">549453824</int>
+										<string key="NSSize">{18, 18}</string>
+										<object class="NSMutableArray" key="NSReps">
+											<bool key="EncodedWithXMLCoder">YES</bool>
+											<object class="NSArray">
+												<bool key="EncodedWithXMLCoder">YES</bool>
+												<reference ref="8"/>
+												<object class="NSBitmapImageRep">
+													<object class="NSData" key="NSTIFFRepresentation">
+														<bytes key="NS.bytes">TU0AKgAABRgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAwAAAAMAAAADAAAAAwAAAAAAAAAA
+AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAwAAADwRERGLJycnySsrK/A1NTXw
+IyMjyRwcHIsJCQk8AAAAAwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFFRUVdVBQUOCoqKj/
+29vb//n5+f/6+vr/2tra/6qqqv9UVFTgHx8fdQAAAAUAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAUZGRl5
+dXV198PDw//8/Pz////////////////////////////U1NT/fHx89yUlJXkAAAAFAAAAAAAAAAAAAAAA
+AAAAAxEREUZqamrmtbW1/+3t7f/+/v7//v7+//7+/v/9/f3//f39//39/f/39/f/xMTE/3d3d+YZGRlG
+AAAAAwAAAAAAAAAAAAAACkJCQqGtra3/xsbG/+vr6//y8vL/9fX1//X19f/z8/P/9fX1//Ly8v/u7u7/
+0tLS/6+vr/9KSkqhAAAACgAAAAAAAAAAAAAAF3h4eN2/v7//z8/P/93d3f/q6ur/7+/v/+/v7//w8PD/
+7e3t/+3t7f/i4uL/zs7O/8XFxf98fHzdAAAAFwAAAAAAAAADAAAAJKSkpPjOzs7/2dnZ/+Dg4P/i4uL/
+5eXl/+bm5v/n5+f/5eXl/+Li4v/e3t7/2tra/9DQ0P+srKz4AAAAJAAAAAMAAAADAAAALrCwsPrW1tb/
+3t7e/+Tk5P/p6en/6+vr/+zs7P/p6en/6+vr/+fn5//k5OT/4ODg/9nZ2f+zs7P6AAAALgAAAAMAAAAD
+AAAALp2dnezg4OD/5eXl/+rq6v/u7u7/8PDw//Dw8P/x8fH/8PDw/+7u7v/q6ur/5ubm/+Hh4f+ZmZns
+AAAALgAAAAMAAAADAAAAJG5ubs/l5eX/6enp/+/v7//y8vL/9vb2//r6+v/5+fn/9/f3//b29v/x8fH/
+6+vr/+Tk5P9ra2vPAAAAJAAAAAMAAAAAAAAAFy4uLpPCwsL67Ozs//Pz8//5+fn//v7+//7+/v/+/v7/
+/v7+//v7+//19fX/8PDw/8LCwvosLCyTAAAAFwAAAAAAAAAAAAAACgAAAENfX1/S5OTk/vn5+f/+/v7/
+///////////////////////////8/Pz/5ubm/l9fX9IAAABDAAAACgAAAAAAAAAAAAAAAwAAABcAAABl
+YmJi3NLS0v3////////////////////////////////V1dX9ZGRk3AAAAGUAAAAXAAAAAwAAAAAAAAAA
+AAAAAAAAAAUAAAAfAAAAZTMzM8KAgIDwv7+//O3t7f/t7e3/v7+//ICAgPAzMzPCAAAAZQAAAB8AAAAF
+AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFAAAAFwAAAEMAAAB3AAAAnwAAALMAAACzAAAAnwAAAHcAAABD
+AAAAFwAAAAUAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAwAAAAoAAAAXAAAAJAAAAC4AAAAu
+AAAAJAAAABcAAAAKAAAAAwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+AAAAAwAAAAMAAAADAAAAAwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADgEAAAMAAAABABIAAAEB
+AAMAAAABABIAAAECAAMAAAAEAAAFxgEDAAMAAAABAAEAAAEGAAMAAAABAAIAAAERAAQAAAABAAAACAES
+AAMAAAABAAEAAAEVAAMAAAABAAQAAAEWAAMAAAABBxwAAAEXAAQAAAABAAAFEAEcAAMAAAABAAEAAAFS
+AAMAAAABAAEAAAFTAAMAAAAEAAAFzodzAAcAAAwYAAAF1gAAAAAACAAIAAgACAABAAEAAQABAAAMGGFw
+cGwCAAAAbW50clJHQiBYWVogB9YABAADABMALAASYWNzcEFQUEwAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+AAAAAPbWAAEAAAAA0y1hcHBs2U706y3Sst1fqit5+wYbUQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+AAAAAAAOclhZWgAAASwAAAAUZ1hZWgAAAUAAAAAUYlhZWgAAAVQAAAAUd3RwdAAAAWgAAAAUY2hhZAAA
+AXwAAAAsclRSQwAAAagAAAAOZ1RSQwAAAbgAAAAOYlRSQwAAAcgAAAAOdmNndAAAAdgAAAMSbmRpbgAA
+BOwAAAY+ZGVzYwAACywAAABkZHNjbQAAC5AAAAAubW1vZAAAC8AAAAAoY3BydAAAC+gAAAAtWFlaIAAA
+AAAAAF1KAAA0kQAACCVYWVogAAAAAAAAdCAAALRgAAAjPVhZWiAAAAAAAAAlbAAAFyoAAKfDWFlaIAAA
+AAAAAPNSAAEAAAABFs9zZjMyAAAAAAABDEIAAAXe///zJgAAB5IAAP2R///7ov///aMAAAPcAADAbGN1
+cnYAAAAAAAAAAQHNAABjdXJ2AAAAAAAAAAEBzQAAY3VydgAAAAAAAAABAc0AAHZjZ3QAAAAAAAAAAAAD
+AQAAAQACBAUGBwkKCw0ODxASExQWFxgaGxweHyAiIyQmJygpKywtLzAxMjM1Njc4OTs8PT5AQUJDREZH
+SElKS0xOT1BRUlNUVVZXWFlaW1xdXl9hYmNkZWZnaGlqa2xtbm9wcXJzdHV2d3h5ent8fX5/gIGCg4SF
+hoeIiYqLjI2Oj5CRkpOUlZaXmJmam5ydnZ6foKGio6SlpqanqKmqq6ytra6vsLGysrO0tba3uLi5uru8
+vL2+v8DBwcLDxMXGxsfIycrKy8zNzs7P0NHS0tPU1dbW19jZ2drb3Nzd3t/g4eLi4+Tl5ufo6enq6+zt
+7u/w8fHy8/T19vf4+fr7/P3+/v8AAgMEBQYHCAkKCwwNDg8QERITFBUWFxgZGhscHR8gISIjJCUnKCkq
+Ky0uLzAxMzQ1Njc4OTo7PD0/QEFCQ0RFRkdISUpLTE1OT1BRUlNUVVZXWFlaWltcXV5fYGFiY2RlZmdo
+aWprbG1ub3BxcnN0dXZ3d3h5ent8fH1+f4CBgoKDhIWGh4iIiYqLjI2Oj5CRkpOUlJWWl5iZmpucnZ2e
+n6ChoqOkpaamp6ipqqusra6vsLCxsrO0tba3uLm5uru8vb6/wMHCw8TFx8jJysvMzc7P0NDR0tPU1dbX
+2Nna29ze3+Dh4uPk5ebn6err7O3u7/Hy8/T19vf5+vv8/f7/AAIDAwQFBgcICQoKCwwNDg8QERITFBUW
+FxgZGhscHR4fICEiIyQlJicoKSorLC0uLzAxMjM0NTY3ODg5Ojs8PT4+P0BBQkNDREVGR0hJSUpLTE1O
+Tk9QUVJSU1RVVVZXWFhZWltbXF1eXl9gYWFiY2RkZWZnZ2hpaWprbGxtbm5vcHFxcnNzdHV1dnd4eHl6
+ent8fH1+fn+AgYGCg4SEhYaHiImJiouMjY6Oj5CRkpOTlJWWl5iZmZqbnJ2en6ChoqOkpaanqKmqq6yt
+rq+xsrO0tba3uLq7vL2+wMHDxMbHycrMzs/R0tTW19nb3d7g4uTm6Ors7vDy9Pb4+vz+/wAAbmRpbgAA
+AAAAAAY2AACXGgAAVjoAAFPKAACJ3gAAJ8IAABaoAABQDQAAVDkAAiuFAAIZmQABeFEAAwEAAAIAAAAA
+AAEABgANABcAIwAxAEAAUgBlAHsAkwCrAMUA4gD/AR8BPwFhAYUBqgHQAfgCIAJLAncCpQLSAwIDMwNl
+A5gDzgQFBD0EdQSvBOsFKQVnBacF6AYqBm4GtQb8B0UHkgfkCDkIkAjnCT4JmAn0ClAKrQsLC2sLygwq
+DIwM8Q1XDcAOKA6SDv4PbA/bEE0QxBE7EbQSMRKwEzITuRREFNAVYBXxFocXHhfAGGIZBBmsGlQa+RuU
+HC4czh1yHhQeux9jIA0gvCFoIhkizyOJJEEk+SW6JnknOygFKMspkypiKzIsASzXLawuhy9gMD4xGzH8
+MtszvzSgNYY2cjdcOEw5OTorOxs8CD0EPfU+6z/nQOFB2ELUQ9VE00XcRttH5EjxSgBLCUwdTTFOUE9v
+UI9Rt1LdVAVVNlZsV6VY4FohW21ct135X09goGH0Y0tkqGYFZ19oxGova5ptCG54b/BxbnLsdG119Xd/
+eQh6knwqfcV/W4D4gpSEO4Xih4CJKorYjIqOOY/jkZuTWJUOlsyYiZpSnB6d4Z+soX+jWqUvpxOo+6rj
+rMuuwLC4sra0rra0uL+60LzfvwDBHcLdxLXGhchYyi7MCs3lz7rRmtOA1WPXR9kq2xPc/97s4M/iveSn
+5o3obupT7ELuLPAM8fLz0PW396H5f/tZ/T3//wAAAAEAAwALABYAJQA3AE0AZQCBAJ8AwQDlAQsBNQFh
+AZABwQH1AisCZAKfAtwDHANfA6MD6gQ0BH8EzQT1BR0FcAXEBhsGdAbPBy0HXAeMB+4IUgi4CSAJVAmK
+CfYKZArVC0cLgQu8DDIMqw0mDaIOIQ6hDyQPqRAvELgQ/RFDEc8SXRLuE4AUFRSrFUMV3RZ5FxcXthhY
+GPwZoRpIGvEbnBxJHPgdqB5bHw8fxSB9ITch8iKwJDAk8yW3Jn4nRigQKNwpqSp5K0osHCzxLccuoC95
+MFUxMzISMvMz1TS5NaA2hzdxOFw5STo4Oyg8Gj4DPvs/9EDuQepD6ETpRexG8Uf3SP9LFEwhTTBOQE9S
+UGZSklOrVMVV4Vb/WB5ZP1phW4Vcq13SXvthUmJ/Y69k4GYSZ0dofGm0au1tZG6ib+FxInJlc6l073Y2
+d396FXtjfLJ+A39VgKmB/4NWhK+GCYjCiiGLgYzjjkePrJESknuT5Ja8mCuZm5sMnH+d9J9qoOGiWqPV
+pVGmz6eOqE6pzqtRrNSuWq/gsWmy8rR+tgu5Kbq6vE294b93wQ7Cp8RBxd3He8kZyrrLisxbzf/Po9FK
+0vHUm9ZF1/HZn9tO3Cbc/96x4GTiGePQ5YjnQegf6Pzquex27jbv9/G583z0X/VC9wj40Pqa/GX+Mf//
+AAAAAQADAAsAJQA3AE0AZQCBAJ8AwQELATUBYQGQAcEB9QIrAmQCnwLcAxwDXwOjA+oENAR/BM0FHQVw
+BcQGGwZ0Bs8HLQeMB+4IUgi4CSAJign2CmQK1QtHC7wMMgyrDSYNog4hDqEPJA+pEC8QuBFDEl0S7hOA
+FBUUqxVDFnkXFxe2GFgY/BpIGvEbnBxJHPgdqB8PH8UgfSE3IfIjbyQwJPMltydGKBAo3Cp5K0osHC3H
+LqAveTEzMhIy8zS5NaA2hzhcOUk6ODwaPQ4+Az/0QO5C6EPoROlG8Uf3SglLFEwhTkBPUlF7UpJUxVXh
+Vv9ZP1phXKtd0mAlYVJjr2TgZhJofGm0au1tZG6ib+FxInJldO92Nnd/eMl6FXyyfgN/VYCpgf+Er4YJ
+h2WIwoohi4GOR4+skRKSe5PklVCWvJgrmZubDJx/nfSfaqDholqj1aVRps+oTqnOq1Gs1K2Xrlqv4LFp
+svK0frYLt5m5Kbnxurq8Tb3hv3fBDsHawqfEQcUPxd3He8hKyRnKusuKzFvN/87Rz6PQdtFK0vHTxtSb
+1kXXG9fx2MjZn9tO3Cbc/93Y3rHfiuBk4hni9ePQ5KzliOZk50HoH+j86drqueuX7HbtVu427xbv9/DX
+8bnymvN89F/1QvYl9wj37PjQ+bX6mvt//GX9S/4x//8AAGRlc2MAAAAAAAAACkNvbG9yIExDRAAAAAAA
+AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+AAAAAAAAAAAAAAAAAABtbHVjAAAAAAAAAAEAAAAMZW5VUwAAABIAAAAcAEMAbwBsAG8AcgAgAEwAQwBE
+AABtbW9kAAAAAAAABhAAAJxOAAAAAL5zkQAAAAAAAAAAAAAAAAAAAAAAdGV4dAAAAABDb3B5cmlnaHQg
+QXBwbGUgQ29tcHV0ZXIsIEluYy4sIDIwMDUAAAAAA</bytes>
+													</object>
+												</object>
+											</object>
+										</object>
+										<object class="NSColor" key="NSColor" id="743532525">
+											<int key="NSColorSpace">3</int>
+											<bytes key="NSWhite">MCAwAA</bytes>
+										</object>
+									</object>
+									<reference key="NSAlternateImage" ref="103585188"/>
+									<int key="NSPeriodicDelay">400</int>
+									<int key="NSPeriodicInterval">75</int>
+								</object>
+								<object class="NSButtonCell" id="149842975">
+									<int key="NSCellFlags">67239424</int>
+									<int key="NSCellFlags2">0</int>
+									<string key="NSContents">Loan Duration</string>
+									<reference key="NSSupport" ref="227377946"/>
+									<reference key="NSControlView" ref="628774051"/>
+									<int key="NSButtonFlags">1211912703</int>
+									<int key="NSButtonFlags2">128</int>
+									<object class="NSImage" key="NSNormalImage" id="532858645">
+										<int key="NSImageFlags">549453824</int>
+										<string key="NSSize">{18, 18}</string>
+										<object class="NSMutableArray" key="NSReps">
+											<bool key="EncodedWithXMLCoder">YES</bool>
+											<object class="NSArray">
+												<bool key="EncodedWithXMLCoder">YES</bool>
+												<reference ref="8"/>
+												<object class="NSBitmapImageRep">
+													<object class="NSData" key="NSTIFFRepresentation">
+														<bytes key="NS.bytes">TU0AKgAABRgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAwAAAAMAAAADAAAAAwAAAAAAAAAA
+AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAwAAADwRERGLJycnySsrK/A1NTXw
+IyMjyRwcHIsJCQk8AAAAAwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFFRUVdVBQUOCoqKj/
+29vb//n5+f/6+vr/2tra/6qqqv9UVFTgHx8fdQAAAAUAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAUZGRl5
+dXV198PDw//8/Pz////////////////////////////U1NT/fHx89yUlJXkAAAAFAAAAAAAAAAAAAAAA
+AAAAAxEREUZqamrmtbW1/+3t7f/+/v7//v7+//7+/v/9/f3//f39//39/f/39/f/xMTE/3d3d+YZGRlG
+AAAAAwAAAAAAAAAAAAAACkJCQqGtra3/xsbG/+vr6//y8vL/9fX1//X19f/z8/P/9fX1//Ly8v/u7u7/
+0tLS/6+vr/9KSkqhAAAACgAAAAAAAAAAAAAAF3h4eN2/v7//z8/P/93d3f/q6ur/7+/v/+/v7//w8PD/
+7e3t/+3t7f/i4uL/zs7O/8XFxf98fHzdAAAAFwAAAAAAAAADAAAAJKSkpPjOzs7/2dnZ/+Dg4P/i4uL/
+5eXl/+bm5v/n5+f/5eXl/+Li4v/e3t7/2tra/9DQ0P+srKz4AAAAJAAAAAMAAAADAAAALrCwsPrW1tb/
+3t7e/+Tk5P/p6en/6+vr/+zs7P/p6en/6+vr/+fn5//k5OT/4ODg/9nZ2f+zs7P6AAAALgAAAAMAAAAD
+AAAALp2dnezg4OD/5eXl/+rq6v/u7u7/8PDw//Dw8P/x8fH/8PDw/+7u7v/q6ur/5ubm/+Hh4f+ZmZns
+AAAALgAAAAMAAAADAAAAJG5ubs/l5eX/6enp/+/v7//y8vL/9vb2//r6+v/5+fn/9/f3//b29v/x8fH/
+6+vr/+Tk5P9ra2vPAAAAJAAAAAMAAAAAAAAAFy4uLpPCwsL67Ozs//Pz8//5+fn//v7+//7+/v/+/v7/
+/v7+//v7+//19fX/8PDw/8LCwvosLCyTAAAAFwAAAAAAAAAAAAAACgAAAENfX1/S5OTk/vn5+f/+/v7/
+///////////////////////////8/Pz/5ubm/l9fX9IAAABDAAAACgAAAAAAAAAAAAAAAwAAABcAAABl
+YmJi3NLS0v3////////////////////////////////V1dX9ZGRk3AAAAGUAAAAXAAAAAwAAAAAAAAAA
+AAAAAAAAAAUAAAAfAAAAZTMzM8KAgIDwv7+//O3t7f/t7e3/v7+//ICAgPAzMzPCAAAAZQAAAB8AAAAF
+AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFAAAAFwAAAEMAAAB3AAAAnwAAALMAAACzAAAAnwAAAHcAAABD
+AAAAFwAAAAUAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAwAAAAoAAAAXAAAAJAAAAC4AAAAu
+AAAAJAAAABcAAAAKAAAAAwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+AAAAAwAAAAMAAAADAAAAAwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADgEAAAMAAAABABIAAAEB
+AAMAAAABABIAAAECAAMAAAAEAAAFxgEDAAMAAAABAAEAAAEGAAMAAAABAAIAAAERAAQAAAABAAAACAES
+AAMAAAABAAEAAAEVAAMAAAABAAQAAAEWAAMAAAABBxwAAAEXAAQAAAABAAAFEAEcAAMAAAABAAEAAAFS
+AAMAAAABAAEAAAFTAAMAAAAEAAAFzodzAAcAABEcAAAF1gAAAAAACAAIAAgACAABAAEAAQABAAARHGFw
+cGwCAAAAbW50clJHQiBYWVogB9kACAAIAAoAHwAdYWNzcEFQUEwAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+AAAAAPbWAAEAAAAA0y1hcHBsoS0Bh+QUuNDqzJl2rWVX8gAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+AAAAAAAOclhZWgAAASwAAAAUZ1hZWgAAAUAAAAAUYlhZWgAAAVQAAAAUd3RwdAAAAWgAAAAUY2hhZAAA
+AXwAAAAsclRSQwAAAagAAAAOZ1RSQwAAAbgAAAAOYlRSQwAAAcgAAAAOdmNndAAAAdgAAAYSbmRpbgAA
+B+wAAAY+ZGVzYwAADiwAAABkZHNjbQAADpAAAAI+bW1vZAAAENAAAAAoY3BydAAAEPgAAAAkWFlaIAAA
+AAAAAG6vAAA5TwAAAX1YWVogAAAAAAAAXt0AALO9AAAH11hZWiAAAAAAAAApSgAAEw8AAMnQWFlaIAAA
+AAAAAPNSAAEAAAABFs9zZjMyAAAAAAABDEIAAAXe///zJgAAB5IAAP2R///7ov///aMAAAPcAADAbGN1
+cnYAAAAAAAAAAQHNAABjdXJ2AAAAAAAAAAEBzQAAY3VydgAAAAAAAAABAc0AAHZjZ3QAAAAAAAAAAAAD
+AQAAAgAAADwA0gFbAe4CiQM6A/8E1gXDBsYH2Aj2CiYLXgyrDjYP1xF6Ex4UxRZyGCEZ3BuUHVEfFiDW
+Ip0kZCYuJ9UpeSsZLK4uQS/EMUMyszQaNXg2zDgXOVw6mzvUPQQ+MD9aQIhBtELhRA5FPEZnR5NIwEnr
+SxZMQE1qTohPplDEUd9S+VQTVSpWQFdSWGNZc1p/W4tcll2cXpZfjWCCYXViaGNZZEhlNGYgZwpn9Gjc
+acNqqmuQbHBtUW4wbw9v7nDMcapyh3NidD51GXXzds13qHiBeVd6LnsGe+F8wH2ifol/doBqgWSCZINq
+hHSFhIaXh7aI1on1ixSMM41Rjm2PiZCikbyS1JPslQOWGpcvmEGZU5pkm3WchZ2UnqOfsaC/ocyi2aPm
+pPKl/qcJqBOpHqorqzusUK1qroyvtbDpsiWzarS0tgi3YLi9udC647v0vQK+DL8SwBPBDcICwvDD2cS9
+xZzGd8dOyCfJBsnrys7Lq8yBzVDOF87Xz4rQN9Dg0YDSIdLB037UQNUB1cLWhNdG2AfYydmL2k3bD9vR
+3JPdVd4W3tbfluBX4Rnh2+Kg42bkLuT55cbmledn6DvpEOnn6qnra+wu7O/tsO5w7zDv7/Ct8WvyKfLm
+86L0X/Ub9df2k/dP+Av4x/mD+j/6+/u1/G79J/3e/pT/Sv//AAAANAC2ATsBuAJGAuQDlARXBSoGEQcL
+CAsJGwovC1wMwA41D6oRKBKkFCgVsBc4GMkaWRvuHYkfHyC9Ilcj2CVYJs8oRCmuKxUscC3CLw4wTTGG
+Mrcz5DULNi83OzhIOVM6XjtqPHQ9fT6GP45AlkGdQqVDq0SwRbRGtUeySLBJrUqpS6RMn02XTo9Ph1B/
+UXRSa1NgVFZVRFYzVyJYEFj9Wela1Fu+XKZdjl5zX1lgPWEgYf9i1mOqZH1lT2YhZvNnxGiUaWNqMmsA
+a81sm21pbjVu/m/HcI9xWHIgcuhzr3R3dT12A3bKd5B4VnkceeF6pntsfDV9AH3PfqJ/eoBZgT6CKYMa
+hA+FCYYHhwiIDYkTihiLHYwijSaOKo8ukDGRM5I1kzaUOJU4ljiXNpg0mTKaMZsxnDKdNp47n0SgT6Fc
+om2jgKSUpaumyKflqQOqH6s7rFetcq6Nr6iwwbHbsvS0DbUltj23VLhquX+6lLunvLi9xr7Qv9XA18HV
+ws7Dw8S2xaTGjMdzyFvJQsopyxDL98zezcTOq8+R0HfRXdJD0yjUDNTv1dPWtteZ2H3ZYdpG2yvcENz1
+3dzew9+q4JzhqOK548TkyeXG5r7nsOie6YjqcetY7D/tJ+4Q7vrv5vDf8gLzJvRJ9Wv2i/et+ND59fse
+/E79gv69//8AAAAiAHcA9gFXAccCQwLJA18EBgS4BXkGRQcVB+8I2gnyCxQMOw1nDpUPxBD6EjATahSo
+FekXLRh0GbsbAhw2HWoemx/JIPMiFiMzJEklVyZgJ2QoZClfKlcrSywvLQ8t8C7RL7EwjzFtMkszJzQB
+NNs1tDaNN2Y4PzkQOeI6szuEPFU9Jz34Psg/mUBqQTxCDkLgQ7NEhUVURiNG8kfBSI9JXUoqSvZLwUyM
+TVZOIE7pT7NQe1FBUgZSylOPVFNVFlXYVppXXFgcWN1ZnVpdWxxb2lyWXVFeC17EX31gNWDrYaJiWGMM
+Y8Bkc2UlZdhmiWc5Z+hol2lFafNqomtQa/xsqW1XbgNusG9ccAlwtHFfcghysXNbdAR0rHVVdfx2pHdL
+d/J4mXk/eeZ6jHsxe9h8gH0rfdt+jX9IgAiAz4GcgnCDS4QrhQ+F+Ibmh9eIx4m4iqeLl4yGjXWOY49R
+kD6RLJIZkwaT8pTalcGWp5eLmHCZVJo6myGcC5z4neie3J/ToM6h0KLxpBelPqZkp4qor6nUqvmsHa1B
+rmSviLCrsc6y8LQQtTC2ULdvuI+5sLrRu/K9FL43v1vAgMGmwszD9sUtxmvHsMkAylrLvM0tzqjQMNHB
+017VA9ay2GjaJNvm3a7fguGP4+TmWejj65DuVfEu9Bn3DfoE/QD//wAAbmRpbgAAAAAAAAY2AACl4wAA
+VqEAAFFbAACnKwAAJqUAABDlAABQDQAAVDkAAkKPAAHZmQABR64AAwEAAAIAAAANACcARgBmAIcAqADJ
+AOsBDgExAVUBegGdAbwB2wH8Ah0CPwJiAoYCqgLPAvQDGwNBA2gDkAO5A+IECwQ1BGAEjAS4BOQFEgU/
+BW4FoQXVBgoGQQZ4BrIG7AcoB2cHpwfpCC4IdQi/CQsJWgmsCgEKWAqyCw4LbgvSDDgMoA0IDXIN3g5K
+DrkPKA+aEA0QgRD3EW8R6BJjEt8TYhPnFG0U9hWBFg4WnRcvF8MYWxj1GZEaMRrTG3ccHRzQHYceQh8A
+H8EghSFNIhki6CO7JJElaiZGJyUoDCj1KeIq0ivELLotsy6wL68wsjG4MsAzyzTeNfE3BDgVOSM6LTsx
+PDA9Kj4gPxJAAkDvQdtCv0OiRIhFb0ZYR0JIL0keSg9LA0v4TPBN6k7lT+JQ4VHkUutT81T9VglXF1gn
+WTlaTVtjXHtdlV6wX85g7WIOYzNkWWV/ZqNnxWjjaf1rEmwhbSpuLm8tcClxInIWcwlz+nTpdhp3TXiE
+eb96/nxFfZN+64BNgbuDNIS5hkmH44mHiyGMro5Aj+CRkZNYlT2XSZl3m8WeG6AOogKj+aXyp+6p7Kvs
+re+v9bH9tAi2G7gvukS8Wb5pwHbCfsSAxn3IdspszGDOi9C40urVIddd2Z/b5t4x4IHi1eUr54jp5+xH
+7qrxEPN79e34Zvrn/XD//wAAAA8ALgBRAHUAmgC/AOQBCwEyAVsBhAGpAcsB7wIUAjoCYAKIArAC2QMD
+Ay0DWQOFA7ED3wQNBDwEawSbBM0E/gUxBWQFnAXVBg8GTAaJBsgHCgdNB5IH2gglCHIIwgkWCWwJxgoj
+CoIK5QtKC7oMKwyfDRUNjA4GDoIPAA+BEAMQiBEOEZcSIhKvE0AT1RRtFQYVohZBFuIXhhgtGNYZgRow
+GuAbkxxIHQQdwh6DH0YgDCDWIaIicyNGJB4k+CXWJrcnoCiXKZEqjiuOLJItmi6mL7UwyDHeMvc0FTU6
+NmM3jji9Oe87JTxfPZs+20AeQWRCr0P7RUVGi0fLSQVKN0tiTIZNpk7BT9pQ8FIEUxZUKlVAVllXc1iP
+Wa5azlvxXRZePV9mYJFhvmLuZCNlWGaPZ8Zo/Wo0a2lsnm3RbwJwMnFgco5zu3Todg93N3hgeYt6uHvn
+fRd+SX99gLKB6oMjhF2FmobYiBeJWYqei+SNLY54j8aRGJJvk8yVMJabmA6ZiZsMnJWeJ5/HoWmjDKSy
+plqoBKmwq1+tEK7DsHiyL7Potae3abktuvK8ur6CwEzCF8PjxbDHfMlKyxnM0M5Vz+PRetMe1M7Wi9hT
+2ibcAd3i38bhq+OP5XLnU+kb6p/sJ+2x7z7wzvJf8+/1gPcP+Jn6Hvuf/Rr+j///AAAAFwBBAHAAnwDP
+AP8BMgFmAZkBxQHzAiICUgKEArcC7AMhA1gDkAPJBAMEPgR6BLcE9QU1BXYFvQYFBk8GmwbqBzsHkAfo
+CEQIpAkICXAJ3ApMCsALNwu6DEIMzA1ZDeoOfg8VD7AQTxDxEZYSPhLpE50UUxUNFcoWiRdMGBIY2hml
+GnIbQRwTHOsdxh6kH4YgayFUIkEjMiQnJR8mGycaKCApKyo5K0ssYS18LpovvTDkMg4zPDRyNa427zg1
+OYE60jwoPYQ+5kBMQbdDK0SkRiFHo0kpSrVMRE3YT3BRDFKwVFtWCVe9WXZbNFz4XsBgjWJeZDZmDGfZ
+aZprSWzpbnlv/HF0cuV0UHWzdxF4cnnUezp8oX4Lf3iA54JYg8yFQoa6iDSJtos9jMmOWY/rkX6TEZSi
+li+XuZk+mr+cPJ22nwWgTKGVot+kKqV3psWoFalmqrqsDq1krrywFbFwssu0KLWKtu24Ubm3ux68hr3u
+v1fAwcIrw5XE/8Zqx9TJQMqrzBbNc87K0BvRaNKs0+rVI9ZX14LYqNnK2uXb/N0Q3h/fK+A14TriPuNA
+5EDlPuY65zfoMekq6iLrDuvp7Lntd+417uzvpfBZ8QrxvPJm8xDzuPRc9QD1ovZC9uL3f/gc+Ln5Vfnw
++oz7J/vC/F78+P2T/i/+yf9k//8AAGRlc2MAAAAAAAAACkNvbG9yIExDRAAAAAAAAAAAAAAAAAAAAAAA
+AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+AABtbHVjAAAAAAAAABIAAAAMbmJOTwAAABIAAADocHRQVAAAABYAAAD6c3ZTRQAAABAAAAEQZmlGSQAA
+ABAAAAEgZGFESwAAABwAAAEwemhDTgAAAAwAAAFMZnJGUgAAABIAAAFYamFKUAAAAA4AAAFqZW5VUwAA
+ABIAAAF4cGxQTAAAABIAAAGKcHRCUgAAABgAAAGcZXNFUwAAABIAAAG0emhUVwAAAA4AAAHGcnVSVQAA
+ACQAAAHUa29LUgAAAAwAAAH4ZGVERQAAABAAAAIEbmxOTAAAABYAAAIUaXRJVAAAABQAAAIqAEYAYQBy
+AGcAZQAtAEwAQwBEAEwAQwBEACAAYQAgAEMAbwByAGUAcwBGAOQAcgBnAC0ATABDAEQAVgDkAHIAaQAt
+AEwAQwBEAEwAQwBEAC0AZgBhAHIAdgBlAHMAawDmAHIAbV9pgnIAIABMAEMARADJAGMAcgBhAG4AIABM
+AEMARDCrMOkw/AAgAEwAQwBEAEMAbwBsAG8AcgAgAEwAQwBEAEsAbwBsAG8AcgAgAEwAQwBEAEwAQwBE
+ACAAQwBvAGwAbwByAGkAZABvAEwAQwBEACAAYwBvAGwAbwByX2mCcm2yZnaYb3k6VmgEJgQyBDUEQgQ9
+BD4EOQAgBBYEGgAtBDQEOARBBD8EOwQ1BDnO7LfsACAATABDAEQARgBhAHIAYgAtAEwAQwBEAEsAbABl
+AHUAcgBlAG4ALQBMAEMARABMAEMARAAgAGMAbwBsAG8AcgBpAABtbW9kAAAAAAAABhAAAJyjAAAAAMV4
+fYAAAAAAAAAAAAAAAAAAAAAAdGV4dAAAAABDb3B5cmlnaHQgQXBwbGUsIEluYy4sIDIwMDkAA</bytes>
+													</object>
+												</object>
+											</object>
+										</object>
+										<reference key="NSColor" ref="743532525"/>
+									</object>
+									<reference key="NSAlternateImage" ref="103585188"/>
+									<int key="NSPeriodicDelay">400</int>
+									<int key="NSPeriodicInterval">75</int>
+								</object>
+								<object class="NSButtonCell" id="322221180">
+									<int key="NSCellFlags">67239424</int>
+									<int key="NSCellFlags2">0</int>
+									<string key="NSContents">Monthly Payment</string>
+									<reference key="NSSupport" ref="227377946"/>
+									<int key="NSTag">1</int>
+									<reference key="NSControlView" ref="628774051"/>
+									<int key="NSButtonFlags">1211912703</int>
+									<int key="NSButtonFlags2">128</int>
+									<reference key="NSNormalImage" ref="532858645"/>
+									<reference key="NSAlternateImage" ref="103585188"/>
+									<int key="NSPeriodicDelay">400</int>
+									<int key="NSPeriodicInterval">75</int>
+								</object>
+							</object>
+							<string key="NSCellSize">{137, 18}</string>
+							<string key="NSIntercellSpacing">{4, 2}</string>
+							<int key="NSMatrixFlags">1151868928</int>
+							<string key="NSCellClass">NSActionCell</string>
+							<object class="NSButtonCell" key="NSProtoCell" id="735574461">
+								<int key="NSCellFlags">67239424</int>
+								<int key="NSCellFlags2">0</int>
+								<string key="NSContents">Radio</string>
+								<reference key="NSSupport" ref="227377946"/>
+								<int key="NSButtonFlags">1211912703</int>
+								<int key="NSButtonFlags2">128</int>
+								<object class="NSImage" key="NSNormalImage">
+									<int key="NSImageFlags">549453824</int>
+									<string key="NSSize">{18, 18}</string>
+									<object class="NSMutableArray" key="NSReps">
+										<bool key="EncodedWithXMLCoder">YES</bool>
+										<object class="NSArray">
+											<bool key="EncodedWithXMLCoder">YES</bool>
+											<reference ref="8"/>
+											<object class="NSBitmapImageRep">
+												<object class="NSData" key="NSTIFFRepresentation">
+													<bytes key="NS.bytes">TU0AKgAABRgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAwAAAAMAAAADAAAAAwAAAAAAAAAA
+AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAwAAADwRERGLJycnySsrK/A1NTXw
+IyMjyRwcHIsJCQk8AAAAAwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFFRUVdVBQUOCoqKj/
+29vb//n5+f/6+vr/2tra/6qqqv9UVFTgHx8fdQAAAAUAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAUZGRl5
+dXV198PDw//8/Pz////////////////////////////U1NT/fHx89yUlJXkAAAAFAAAAAAAAAAAAAAAA
+AAAAAxEREUZqamrmtbW1/+3t7f/+/v7//v7+//7+/v/9/f3//f39//39/f/39/f/xMTE/3d3d+YZGRlG
+AAAAAwAAAAAAAAAAAAAACkJCQqGtra3/xsbG/+vr6//y8vL/9fX1//X19f/z8/P/9fX1//Ly8v/u7u7/
+0tLS/6+vr/9KSkqhAAAACgAAAAAAAAAAAAAAF3h4eN2/v7//z8/P/93d3f/q6ur/7+/v/+/v7//w8PD/
+7e3t/+3t7f/i4uL/zs7O/8XFxf98fHzdAAAAFwAAAAAAAAADAAAAJKSkpPjOzs7/2dnZ/+Dg4P/i4uL/
+5eXl/+bm5v/n5+f/5eXl/+Li4v/e3t7/2tra/9DQ0P+srKz4AAAAJAAAAAMAAAADAAAALrCwsPrW1tb/
+3t7e/+Tk5P/p6en/6+vr/+zs7P/p6en/6+vr/+fn5//k5OT/4ODg/9nZ2f+zs7P6AAAALgAAAAMAAAAD
+AAAALp2dnezg4OD/5eXl/+rq6v/u7u7/8PDw//Dw8P/x8fH/8PDw/+7u7v/q6ur/5ubm/+Hh4f+ZmZns
+AAAALgAAAAMAAAADAAAAJG5ubs/l5eX/6enp/+/v7//y8vL/9vb2//r6+v/5+fn/9/f3//b29v/x8fH/
+6+vr/+Tk5P9ra2vPAAAAJAAAAAMAAAAAAAAAFy4uLpPCwsL67Ozs//Pz8//5+fn//v7+//7+/v/+/v7/
+/v7+//v7+//19fX/8PDw/8LCwvosLCyTAAAAFwAAAAAAAAAAAAAACgAAAENfX1/S5OTk/vn5+f/+/v7/
+///////////////////////////8/Pz/5ubm/l9fX9IAAABDAAAACgAAAAAAAAAAAAAAAwAAABcAAABl
+YmJi3NLS0v3////////////////////////////////V1dX9ZGRk3AAAAGUAAAAXAAAAAwAAAAAAAAAA
+AAAAAAAAAAUAAAAfAAAAZTMzM8KAgIDwv7+//O3t7f/t7e3/v7+//ICAgPAzMzPCAAAAZQAAAB8AAAAF
+AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFAAAAFwAAAEMAAAB3AAAAnwAAALMAAACzAAAAnwAAAHcAAABD
+AAAAFwAAAAUAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAwAAAAoAAAAXAAAAJAAAAC4AAAAu
+AAAAJAAAABcAAAAKAAAAAwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+AAAAAwAAAAMAAAADAAAAAwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADQEAAAMAAAABABIAAAEB
+AAMAAAABABIAAAECAAMAAAAEAAAFugEDAAMAAAABAAEAAAEGAAMAAAABAAIAAAERAAQAAAABAAAACAES
+AAMAAAABAAEAAAEVAAMAAAABAAQAAAEWAAMAAAABBxwAAAEXAAQAAAABAAAFEAEcAAMAAAABAAEAAAFS
+AAMAAAABAAEAAAFTAAMAAAAEAAAFwgAAAAAACAAIAAgACAABAAEAAQABA</bytes>
+												</object>
+											</object>
+										</object>
+									</object>
+									<reference key="NSColor" ref="743532525"/>
+								</object>
+								<reference key="NSAlternateImage" ref="103585188"/>
+								<int key="NSPeriodicDelay">400</int>
+								<int key="NSPeriodicInterval">75</int>
+							</object>
+							<reference key="NSSelectedCell" ref="853217630"/>
+							<reference key="NSBackgroundColor" ref="344940583"/>
+							<reference key="NSCellBackgroundColor" ref="72801970"/>
+							<reference key="NSFont" ref="227377946"/>
+						</object>
+						<object class="NSTextField" id="841149624">
+							<reference key="NSNextResponder" ref="1006"/>
+							<int key="NSvFlags">268</int>
+							<string key="NSFrame">{{76, 123}, {66, 17}}</string>
+							<reference key="NSSuperview" ref="1006"/>
+							<bool key="NSEnabled">YES</bool>
+							<object class="NSTextFieldCell" key="NSCell" id="405363163">
+								<int key="NSCellFlags">68288064</int>
+								<int key="NSCellFlags2">272630784</int>
+								<string key="NSContents">Compute:</string>
+								<reference key="NSSupport" ref="227377946"/>
+								<reference key="NSControlView" ref="841149624"/>
+								<reference key="NSBackgroundColor" ref="344940583"/>
+								<reference key="NSTextColor" ref="942182489"/>
+							</object>
+						</object>
+						<object class="NSTextField" id="543510533">
+							<reference key="NSNextResponder" ref="1006"/>
+							<int key="NSvFlags">268</int>
+							<string key="NSFrame">{{61, 441}, {78, 22}}</string>
+							<reference key="NSSuperview" ref="1006"/>
+							<bool key="NSEnabled">YES</bool>
+							<object class="NSTextFieldCell" key="NSCell" id="1003059605">
+								<int key="NSCellFlags">-1804468671</int>
+								<int key="NSCellFlags2">-1874852864</int>
+								<string key="NSContents"/>
+								<reference key="NSSupport" ref="227377946"/>
+								<object class="NSDateFormatter" key="NSFormatter" id="478164133">
+									<object class="NSMutableDictionary" key="NS.attributes">
+										<bool key="EncodedWithXMLCoder">YES</bool>
+										<object class="NSMutableArray" key="dict.sortedKeys">
+											<bool key="EncodedWithXMLCoder">YES</bool>
+											<string>dateFormat_10_0</string>
+											<string>dateStyle</string>
+											<string>formatterBehavior</string>
+											<string>timeStyle</string>
+										</object>
+										<object class="NSMutableArray" key="dict.values">
+											<bool key="EncodedWithXMLCoder">YES</bool>
+											<string>%m/%d/%y</string>
+											<reference ref="9"/>
+											<integer value="1040"/>
+											<reference ref="8"/>
+										</object>
+									</object>
+									<string key="NS.format">M/d/yy</string>
+									<bool key="NS.natural">NO</bool>
+								</object>
+								<reference key="NSControlView" ref="543510533"/>
+								<bool key="NSDrawsBackground">YES</bool>
+								<reference key="NSBackgroundColor" ref="627117864"/>
+								<reference key="NSTextColor" ref="394575910"/>
+							</object>
+						</object>
+						<object class="NSTextField" id="720301440">
+							<reference key="NSNextResponder" ref="1006"/>
+							<int key="NSvFlags">268</int>
+							<string key="NSFrame">{{213, 441}, {73, 22}}</string>
+							<reference key="NSSuperview" ref="1006"/>
+							<bool key="NSEnabled">YES</bool>
+							<object class="NSTextFieldCell" key="NSCell" id="622482629">
+								<int key="NSCellFlags">-2075001280</int>
+								<int key="NSCellFlags2">-1874852864</int>
+								<string key="NSContents"/>
+								<reference key="NSSupport" ref="227377946"/>
+								<object class="NSDateFormatter" key="NSFormatter" id="472826315">
+									<object class="NSMutableDictionary" key="NS.attributes">
+										<bool key="EncodedWithXMLCoder">YES</bool>
+										<object class="NSMutableArray" key="dict.sortedKeys">
+											<bool key="EncodedWithXMLCoder">YES</bool>
+											<string>dateFormat_10_0</string>
+											<string>dateStyle</string>
+											<string>formatterBehavior</string>
+											<string>timeStyle</string>
+										</object>
+										<object class="NSMutableArray" key="dict.values">
+											<bool key="EncodedWithXMLCoder">YES</bool>
+											<string>%m/%d/%y</string>
+											<reference ref="9"/>
+											<integer value="1040"/>
+											<reference ref="8"/>
+										</object>
+									</object>
+									<string key="NS.format">M/d/yy</string>
+									<bool key="NS.natural">NO</bool>
+								</object>
+								<reference key="NSControlView" ref="720301440"/>
+								<bool key="NSDrawsBackground">YES</bool>
+								<reference key="NSBackgroundColor" ref="627117864"/>
+								<reference key="NSTextColor" ref="394575910"/>
+							</object>
+						</object>
+						<object class="NSTextField" id="662881888">
+							<reference key="NSNextResponder" ref="1006"/>
+							<int key="NSvFlags">268</int>
+							<string key="NSFrame">{{46, 471}, {109, 17}}</string>
+							<reference key="NSSuperview" ref="1006"/>
+							<bool key="NSEnabled">YES</bool>
+							<object class="NSTextFieldCell" key="NSCell" id="124721751">
+								<int key="NSCellFlags">68288064</int>
+								<int key="NSCellFlags2">272630784</int>
+								<string key="NSContents">Origination Date</string>
+								<reference key="NSSupport" ref="227377946"/>
+								<reference key="NSControlView" ref="662881888"/>
+								<reference key="NSBackgroundColor" ref="344940583"/>
+								<reference key="NSTextColor" ref="942182489"/>
+							</object>
+						</object>
+						<object class="NSTextField" id="607934766">
+							<reference key="NSNextResponder" ref="1006"/>
+							<int key="NSvFlags">268</int>
+							<string key="NSFrame">{{205, 471}, {90, 17}}</string>
+							<reference key="NSSuperview" ref="1006"/>
+							<bool key="NSEnabled">YES</bool>
+							<object class="NSTextFieldCell" key="NSCell" id="211620694">
+								<int key="NSCellFlags">68288064</int>
+								<int key="NSCellFlags2">272630784</int>
+								<string key="NSContents">First Payment</string>
+								<reference key="NSSupport" ref="227377946"/>
+								<reference key="NSControlView" ref="607934766"/>
+								<reference key="NSBackgroundColor" ref="344940583"/>
+								<reference key="NSTextColor" ref="942182489"/>
+							</object>
+						</object>
+						<object class="NSTextField" id="149242470">
+							<reference key="NSNextResponder" ref="1006"/>
+							<int key="NSvFlags">268</int>
+							<string key="NSFrame">{{230, 110}, {123, 17}}</string>
+							<reference key="NSSuperview" ref="1006"/>
+							<bool key="NSEnabled">YES</bool>
+							<object class="NSTextFieldCell" key="NSCell" id="7019256">
+								<int key="NSCellFlags">68288064</int>
+								<int key="NSCellFlags2">272630784</int>
+								<string key="NSContents">Total Interest Paid:</string>
+								<reference key="NSSupport" ref="227377946"/>
+								<reference key="NSControlView" ref="149242470"/>
+								<reference key="NSBackgroundColor" ref="344940583"/>
+								<reference key="NSTextColor" ref="942182489"/>
+							</object>
+						</object>
+						<object class="NSTextField" id="665211230">
+							<reference key="NSNextResponder" ref="1006"/>
+							<int key="NSvFlags">268</int>
+							<string key="NSFrame">{{365, 108}, {118, 22}}</string>
+							<reference key="NSSuperview" ref="1006"/>
+							<bool key="NSEnabled">YES</bool>
+							<object class="NSTextFieldCell" key="NSCell" id="273963221">
+								<int key="NSCellFlags">-2075001280</int>
+								<int key="NSCellFlags2">-2076179456</int>
+								<string key="NSContents"/>
+								<reference key="NSSupport" ref="227377946"/>
+								<object class="NSNumberFormatter" key="NSFormatter" id="876830924">
+									<object class="NSMutableDictionary" key="NS.attributes">
+										<bool key="EncodedWithXMLCoder">YES</bool>
+										<object class="NSMutableArray" key="dict.sortedKeys">
+											<bool key="EncodedWithXMLCoder">YES</bool>
+											<string>allowsFloats</string>
+											<string>alwaysShowsDecimalSeparator</string>
+											<string>formatterBehavior</string>
+											<string>generatesDecimalNumbers</string>
+											<string>multiplier</string>
+											<string>numberStyle</string>
+										</object>
+										<object class="NSMutableArray" key="dict.values">
+											<bool key="EncodedWithXMLCoder">YES</bool>
+											<reference ref="6"/>
+											<reference ref="5"/>
+											<integer value="1040"/>
+											<reference ref="5"/>
+											<real value="1.000000e-02"/>
+											<reference ref="10"/>
+										</object>
+									</object>
+									<string type="base64-UTF8" key="NS.positiveformat">wqQjLCMjMC4wMA</string>
+									<string type="base64-UTF8" key="NS.negativeformat">KMKkIywjIzAuMDApA</string>
+									<nil key="NS.positiveattrs"/>
+									<nil key="NS.negativeattrs"/>
+									<object class="NSAttributedString" key="NS.zero">
+										<nil key="NSString"/>
+									</object>
+									<object class="NSAttributedString" key="NS.nil">
+										<nil key="NSString"/>
+									</object>
+									<object class="NSAttributedString" key="NS.nan">
+										<string key="NSString">NaN</string>
+										<reference key="NSAttributes" ref="932461654"/>
+									</object>
+									<reference key="NS.min" ref="325159587"/>
+									<reference key="NS.max" ref="325159587"/>
+									<object class="NSDecimalNumberHandler" key="NS.rounding">
+										<int key="NS.roundingmode">3</int>
+										<bool key="NS.raise.overflow">YES</bool>
+										<bool key="NS.raise.underflow">YES</bool>
+										<bool key="NS.raise.dividebyzero">YES</bool>
+									</object>
+									<string key="NS.decimal">.</string>
+									<string key="NS.thousand">,</string>
+									<bool key="NS.hasthousands">YES</bool>
+									<bool key="NS.localized">YES</bool>
+									<bool key="NS.allowsfloats">NO</bool>
+								</object>
+								<reference key="NSControlView" ref="665211230"/>
+								<bool key="NSDrawsBackground">YES</bool>
+								<reference key="NSBackgroundColor" ref="627117864"/>
+								<reference key="NSTextColor" ref="394575910"/>
+							</object>
+						</object>
+						<object class="NSTextField" id="1020002354">
+							<reference key="NSNextResponder" ref="1006"/>
+							<int key="NSvFlags">268</int>
+							<string key="NSFrame">{{253, 262}, {233, 14}}</string>
+							<reference key="NSSuperview" ref="1006"/>
+							<bool key="NSEnabled">YES</bool>
+							<object class="NSTextFieldCell" key="NSCell" id="1010722721">
+								<int key="NSCellFlags">68288064</int>
+								<int key="NSCellFlags2">272761856</int>
+								<string key="NSContents">Reached max duration needed to pay loan </string>
+								<object class="NSFont" key="NSSupport" id="26">
+									<string key="NSName">LucidaGrande</string>
+									<double key="NSSize">1.100000e+01</double>
+									<int key="NSfFlags">3100</int>
+								</object>
+								<reference key="NSControlView" ref="1020002354"/>
+								<reference key="NSBackgroundColor" ref="344940583"/>
+								<reference key="NSTextColor" ref="942182489"/>
+							</object>
+						</object>
+						<object class="NSTextField" id="848322395">
+							<reference key="NSNextResponder" ref="1006"/>
+							<int key="NSvFlags">268</int>
+							<string key="NSFrame">{{183, 174}, {332, 14}}</string>
+							<reference key="NSSuperview" ref="1006"/>
+							<bool key="NSEnabled">YES</bool>
+							<object class="NSTextFieldCell" key="NSCell" id="294160444">
+								<int key="NSCellFlags">68288064</int>
+								<int key="NSCellFlags2">272761856</int>
+								<string type="base64-UTF8" key="NSContents">UmVhY2hlZCBtaW4gcGF5bWVudCBuZWVkZWQgZm9yIGZpcnN0IG1vbnRoJ3MgaW50ZXJlc3Q</string>
+								<reference key="NSSupport" ref="26"/>
+								<reference key="NSControlView" ref="848322395"/>
+								<reference key="NSBackgroundColor" ref="344940583"/>
+								<reference key="NSTextColor" ref="942182489"/>
+							</object>
+						</object>
+						<object class="NSTextField" id="860928395">
+							<reference key="NSNextResponder" ref="1006"/>
+							<int key="NSvFlags">268</int>
+							<string key="NSFrame">{{253, 262}, {227, 14}}</string>
+							<reference key="NSSuperview" ref="1006"/>
+							<bool key="NSEnabled">YES</bool>
+							<object class="NSTextFieldCell" key="NSCell" id="571238653">
+								<int key="NSCellFlags">68288064</int>
+								<int key="NSCellFlags2">272761856</int>
+								<string key="NSContents">Reached min duration needed to pay loan</string>
+								<reference key="NSSupport" ref="26"/>
+								<reference key="NSControlView" ref="860928395"/>
+								<reference key="NSBackgroundColor" ref="344940583"/>
+								<reference key="NSTextColor" ref="942182489"/>
+							</object>
+						</object>
+					</object>
+					<string key="NSFrameSize">{527, 498}</string>
+					<reference key="NSSuperview"/>
+				</object>
+				<string key="NSScreenRect">{{0, 0}, {1680, 1028}}</string>
+				<string key="NSMaxSize">{3.40282e+38, 3.40282e+38}</string>
+			</object>
+		</object>
+		<object class="IBObjectContainer" key="IBDocument.Objects">
+			<object class="NSMutableArray" key="connectionRecords">
+				<bool key="EncodedWithXMLCoder">YES</bool>
+				<object class="IBConnectionRecord">
+					<object class="IBActionConnection" key="connection">
+						<string key="label">buttonPushed:</string>
+						<reference key="source" ref="1001"/>
+						<reference key="destination" ref="628774051"/>
+					</object>
+					<int key="connectionID">59</int>
+				</object>
+				<object class="IBConnectionRecord">
+					<object class="IBOutletConnection" key="connection">
+						<string key="label">loanText</string>
+						<reference key="source" ref="1001"/>
+						<reference key="destination" ref="809137054"/>
+					</object>
+					<int key="connectionID">76</int>
+				</object>
+				<object class="IBConnectionRecord">
+					<object class="IBOutletConnection" key="connection">
+						<string key="label">intText</string>
+						<reference key="source" ref="1001"/>
+						<reference key="destination" ref="583982648"/>
+					</object>
+					<int key="connectionID">77</int>
+				</object>
+				<object class="IBConnectionRecord">
+					<object class="IBOutletConnection" key="connection">
+						<string key="label">durText</string>
+						<reference key="source" ref="1001"/>
+						<reference key="destination" ref="125608385"/>
+					</object>
+					<int key="connectionID">78</int>
+				</object>
+				<object class="IBConnectionRecord">
+					<object class="IBOutletConnection" key="connection">
+						<string key="label">payText</string>
+						<reference key="source" ref="1001"/>
+						<reference key="destination" ref="644051649"/>
+					</object>
+					<int key="connectionID">79</int>
+				</object>
+				<object class="IBConnectionRecord">
+					<object class="IBOutletConnection" key="connection">
+						<string key="label">intSlider</string>
+						<reference key="source" ref="1001"/>
+						<reference key="destination" ref="502682855"/>
+					</object>
+					<int key="connectionID">80</int>
+				</object>
+				<object class="IBConnectionRecord">
+					<object class="IBOutletConnection" key="connection">
+						<string key="label">durSlider</string>
+						<reference key="source" ref="1001"/>
+						<reference key="destination" ref="857285538"/>
+					</object>
+					<int key="connectionID">81</int>
+				</object>
+				<object class="IBConnectionRecord">
+					<object class="IBOutletConnection" key="connection">
+						<string key="label">paySlider</string>
+						<reference key="source" ref="1001"/>
+						<reference key="destination" ref="82942187"/>
+					</object>
+					<int key="connectionID">82</int>
+				</object>
+				<object class="IBConnectionRecord">
+					<object class="IBBindingConnection" key="connection">
+						<string key="label">value: loan.originationDate</string>
+						<reference key="source" ref="543510533"/>
+						<reference key="destination" ref="1001"/>
+						<object class="NSNibBindingConnector" key="connector">
+							<reference key="NSSource" ref="543510533"/>
+							<reference key="NSDestination" ref="1001"/>
+							<string key="NSLabel">value: loan.originationDate</string>
+							<string key="NSBinding">value</string>
+							<string key="NSKeyPath">loan.originationDate</string>
+							<object class="NSDictionary" key="NSOptions">
+								<string key="NS.key.0">NSContinuouslyUpdatesValue</string>
+								<reference key="NS.object.0" ref="5"/>
+							</object>
+							<int key="NSNibBindingConnectorVersion">2</int>
+						</object>
+					</object>
+					<int key="connectionID">151</int>
+				</object>
+				<object class="IBConnectionRecord">
+					<object class="IBBindingConnection" key="connection">
+						<string key="label">value: loan.firstPayment</string>
+						<reference key="source" ref="720301440"/>
+						<reference key="destination" ref="1001"/>
+						<object class="NSNibBindingConnector" key="connector">
+							<reference key="NSSource" ref="720301440"/>
+							<reference key="NSDestination" ref="1001"/>
+							<string key="NSLabel">value: loan.firstPayment</string>
+							<string key="NSBinding">value</string>
+							<string key="NSKeyPath">loan.firstPayment</string>
+							<object class="NSDictionary" key="NSOptions">
+								<string key="NS.key.0">NSContinuouslyUpdatesValue</string>
+								<reference key="NS.object.0" ref="5"/>
+							</object>
+							<int key="NSNibBindingConnectorVersion">2</int>
+						</object>
+					</object>
+					<int key="connectionID">152</int>
+				</object>
+				<object class="IBConnectionRecord">
+					<object class="IBBindingConnection" key="connection">
+						<string key="label">value: loan.interestRate</string>
+						<reference key="source" ref="583982648"/>
+						<reference key="destination" ref="1001"/>
+						<object class="NSNibBindingConnector" key="connector">
+							<reference key="NSSource" ref="583982648"/>
+							<reference key="NSDestination" ref="1001"/>
+							<string key="NSLabel">value: loan.interestRate</string>
+							<string key="NSBinding">value</string>
+							<string key="NSKeyPath">loan.interestRate</string>
+							<object class="NSDictionary" key="NSOptions">
+								<string key="NS.key.0">NSContinuouslyUpdatesValue</string>
+								<reference key="NS.object.0" ref="5"/>
+							</object>
+							<int key="NSNibBindingConnectorVersion">2</int>
+						</object>
+					</object>
+					<int key="connectionID">154</int>
+				</object>
+				<object class="IBConnectionRecord">
+					<object class="IBBindingConnection" key="connection">
+						<string key="label">value: loan.loanDuration</string>
+						<reference key="source" ref="125608385"/>
+						<reference key="destination" ref="1001"/>
+						<object class="NSNibBindingConnector" key="connector">
+							<reference key="NSSource" ref="125608385"/>
+							<reference key="NSDestination" ref="1001"/>
+							<string key="NSLabel">value: loan.loanDuration</string>
+							<string key="NSBinding">value</string>
+							<string key="NSKeyPath">loan.loanDuration</string>
+							<object class="NSDictionary" key="NSOptions">
+								<string key="NS.key.0">NSContinuouslyUpdatesValue</string>
+								<reference key="NS.object.0" ref="5"/>
+							</object>
+							<int key="NSNibBindingConnectorVersion">2</int>
+						</object>
+					</object>
+					<int key="connectionID">155</int>
+				</object>
+				<object class="IBConnectionRecord">
+					<object class="IBBindingConnection" key="connection">
+						<string key="label">value: loan.monthlyPayment</string>
+						<reference key="source" ref="644051649"/>
+						<reference key="destination" ref="1001"/>
+						<object class="NSNibBindingConnector" key="connector">
+							<reference key="NSSource" ref="644051649"/>
+							<reference key="NSDestination" ref="1001"/>
+							<string key="NSLabel">value: loan.monthlyPayment</string>
+							<string key="NSBinding">value</string>
+							<string key="NSKeyPath">loan.monthlyPayment</string>
+							<object class="NSDictionary" key="NSOptions">
+								<string key="NS.key.0">NSContinuouslyUpdatesValue</string>
+								<reference key="NS.object.0" ref="5"/>
+							</object>
+							<int key="NSNibBindingConnectorVersion">2</int>
+						</object>
+					</object>
+					<int key="connectionID">156</int>
+				</object>
+				<object class="IBConnectionRecord">
+					<object class="IBBindingConnection" key="connection">
+						<string key="label">value: loan.totInterest</string>
+						<reference key="source" ref="665211230"/>
+						<reference key="destination" ref="1001"/>
+						<object class="NSNibBindingConnector" key="connector">
+							<reference key="NSSource" ref="665211230"/>
+							<reference key="NSDestination" ref="1001"/>
+							<string key="NSLabel">value: loan.totInterest</string>
+							<string key="NSBinding">value</string>
+							<string key="NSKeyPath">loan.totInterest</string>
+							<int key="NSNibBindingConnectorVersion">2</int>
+						</object>
+					</object>
+					<int key="connectionID">157</int>
+				</object>
+				<object class="IBConnectionRecord">
+					<object class="IBBindingConnection" key="connection">
+						<string key="label">value: loan.monthlyPayment</string>
+						<reference key="source" ref="82942187"/>
+						<reference key="destination" ref="1001"/>
+						<object class="NSNibBindingConnector" key="connector">
+							<reference key="NSSource" ref="82942187"/>
+							<reference key="NSDestination" ref="1001"/>
+							<string key="NSLabel">value: loan.monthlyPayment</string>
+							<string key="NSBinding">value</string>
+							<string key="NSKeyPath">loan.monthlyPayment</string>
+							<int key="NSNibBindingConnectorVersion">2</int>
+						</object>
+					</object>
+					<int key="connectionID">161</int>
+				</object>
+				<object class="IBConnectionRecord">
+					<object class="IBBindingConnection" key="connection">
+						<string key="label">value: loan.loanDuration</string>
+						<reference key="source" ref="857285538"/>
+						<reference key="destination" ref="1001"/>
+						<object class="NSNibBindingConnector" key="connector">
+							<reference key="NSSource" ref="857285538"/>
+							<reference key="NSDestination" ref="1001"/>
+							<string key="NSLabel">value: loan.loanDuration</string>
+							<string key="NSBinding">value</string>
+							<string key="NSKeyPath">loan.loanDuration</string>
+							<int key="NSNibBindingConnectorVersion">2</int>
+						</object>
+					</object>
+					<int key="connectionID">162</int>
+				</object>
+				<object class="IBConnectionRecord">
+					<object class="IBBindingConnection" key="connection">
+						<string key="label">value: loan.interestRate</string>
+						<reference key="source" ref="502682855"/>
+						<reference key="destination" ref="1001"/>
+						<object class="NSNibBindingConnector" key="connector">
+							<reference key="NSSource" ref="502682855"/>
+							<reference key="NSDestination" ref="1001"/>
+							<string key="NSLabel">value: loan.interestRate</string>
+							<string key="NSBinding">value</string>
+							<string key="NSKeyPath">loan.interestRate</string>
+							<int key="NSNibBindingConnectorVersion">2</int>
+						</object>
+					</object>
+					<int key="connectionID">163</int>
+				</object>
+				<object class="IBConnectionRecord">
+					<object class="IBOutletConnection" key="connection">
+						<string key="label">window</string>
+						<reference key="source" ref="1001"/>
+						<reference key="destination" ref="1005"/>
+					</object>
+					<int key="connectionID">164</int>
+				</object>
+				<object class="IBConnectionRecord">
+					<object class="IBOutletConnection" key="connection">
+						<string key="label">delegate</string>
+						<reference key="source" ref="1005"/>
+						<reference key="destination" ref="1001"/>
+					</object>
+					<int key="connectionID">165</int>
+				</object>
+				<object class="IBConnectionRecord">
+					<object class="IBBindingConnection" key="connection">
+						<string key="label">hidden: loan.minPay</string>
+						<reference key="source" ref="848322395"/>
+						<reference key="destination" ref="1001"/>
+						<object class="NSNibBindingConnector" key="connector">
+							<reference key="NSSource" ref="848322395"/>
+							<reference key="NSDestination" ref="1001"/>
+							<string key="NSLabel">hidden: loan.minPay</string>
+							<string key="NSBinding">hidden</string>
+							<string key="NSKeyPath">loan.minPay</string>
+							<object class="NSDictionary" key="NSOptions">
+								<bool key="EncodedWithXMLCoder">YES</bool>
+								<object class="NSMutableArray" key="dict.sortedKeys">
+									<bool key="EncodedWithXMLCoder">YES</bool>
+									<string>NSNullPlaceholder</string>
+									<string>NSValueTransformerName</string>
+								</object>
+								<object class="NSMutableArray" key="dict.values">
+									<bool key="EncodedWithXMLCoder">YES</bool>
+									<reference ref="9"/>
+									<string>NSNegateBoolean</string>
+								</object>
+							</object>
+							<int key="NSNibBindingConnectorVersion">2</int>
+						</object>
+					</object>
+					<int key="connectionID">169</int>
+				</object>
+				<object class="IBConnectionRecord">
+					<object class="IBBindingConnection" key="connection">
+						<string key="label">hidden: loan.minDur</string>
+						<reference key="source" ref="860928395"/>
+						<reference key="destination" ref="1001"/>
+						<object class="NSNibBindingConnector" key="connector">
+							<reference key="NSSource" ref="860928395"/>
+							<reference key="NSDestination" ref="1001"/>
+							<string key="NSLabel">hidden: loan.minDur</string>
+							<string key="NSBinding">hidden</string>
+							<string key="NSKeyPath">loan.minDur</string>
+							<object class="NSDictionary" key="NSOptions">
+								<bool key="EncodedWithXMLCoder">YES</bool>
+								<object class="NSMutableArray" key="dict.sortedKeys">
+									<bool key="EncodedWithXMLCoder">YES</bool>
+									<string>NSNullPlaceholder</string>
+									<string>NSValueTransformerName</string>
+								</object>
+								<object class="NSMutableArray" key="dict.values">
+									<bool key="EncodedWithXMLCoder">YES</bool>
+									<reference ref="9"/>
+									<string>NSNegateBoolean</string>
+								</object>
+							</object>
+							<int key="NSNibBindingConnectorVersion">2</int>
+						</object>
+					</object>
+					<int key="connectionID">170</int>
+				</object>
+				<object class="IBConnectionRecord">
+					<object class="IBBindingConnection" key="connection">
+						<string key="label">hidden: loan.maxDur</string>
+						<reference key="source" ref="1020002354"/>
+						<reference key="destination" ref="1001"/>
+						<object class="NSNibBindingConnector" key="connector">
+							<reference key="NSSource" ref="1020002354"/>
+							<reference key="NSDestination" ref="1001"/>
+							<string key="NSLabel">hidden: loan.maxDur</string>
+							<string key="NSBinding">hidden</string>
+							<string key="NSKeyPath">loan.maxDur</string>
+							<object class="NSDictionary" key="NSOptions">
+								<bool key="EncodedWithXMLCoder">YES</bool>
+								<object class="NSMutableArray" key="dict.sortedKeys">
+									<bool key="EncodedWithXMLCoder">YES</bool>
+									<string>NSNullPlaceholder</string>
+									<string>NSValueTransformerName</string>
+								</object>
+								<object class="NSMutableArray" key="dict.values">
+									<bool key="EncodedWithXMLCoder">YES</bool>
+									<reference ref="9"/>
+									<string>NSNegateBoolean</string>
+								</object>
+							</object>
+							<int key="NSNibBindingConnectorVersion">2</int>
+						</object>
+					</object>
+					<int key="connectionID">171</int>
+				</object>
+				<object class="IBConnectionRecord">
+					<object class="IBBindingConnection" key="connection">
+						<string key="label">value: loan.loanAmt</string>
+						<reference key="source" ref="809137054"/>
+						<reference key="destination" ref="1001"/>
+						<object class="NSNibBindingConnector" key="connector">
+							<reference key="NSSource" ref="809137054"/>
+							<reference key="NSDestination" ref="1001"/>
+							<string key="NSLabel">value: loan.loanAmt</string>
+							<string key="NSBinding">value</string>
+							<string key="NSKeyPath">loan.loanAmt</string>
+							<object class="NSDictionary" key="NSOptions">
+								<string key="NS.key.0">NSContinuouslyUpdatesValue</string>
+								<reference key="NS.object.0" ref="5"/>
+							</object>
+							<int key="NSNibBindingConnectorVersion">2</int>
+						</object>
+					</object>
+					<int key="connectionID">174</int>
+				</object>
+			</object>
+			<object class="IBMutableOrderedSet" key="objectRecords">
+				<object class="NSArray" key="orderedObjects">
+					<bool key="EncodedWithXMLCoder">YES</bool>
+					<object class="IBObjectRecord">
+						<int key="objectID">0</int>
+						<object class="NSArray" key="object" id="1002">
+							<bool key="EncodedWithXMLCoder">YES</bool>
+						</object>
+						<reference key="children" ref="1000"/>
+						<nil key="parent"/>
+					</object>
+					<object class="IBObjectRecord">
+						<int key="objectID">-2</int>
+						<reference key="object" ref="1001"/>
+						<reference key="parent" ref="1002"/>
+						<string type="base64-UTF8" key="objectName">RmlsZSdzIE93bmVyA</string>
+					</object>
+					<object class="IBObjectRecord">
+						<int key="objectID">-1</int>
+						<reference key="object" ref="1003"/>
+						<reference key="parent" ref="1002"/>
+						<string key="objectName">First Responder</string>
+					</object>
+					<object class="IBObjectRecord">
+						<int key="objectID">-3</int>
+						<reference key="object" ref="1004"/>
+						<reference key="parent" ref="1002"/>
+						<string key="objectName">Application</string>
+					</object>
+					<object class="IBObjectRecord">
+						<int key="objectID">1</int>
+						<reference key="object" ref="1005"/>
+						<object class="NSMutableArray" key="children">
+							<bool key="EncodedWithXMLCoder">YES</bool>
+							<reference ref="1006"/>
+						</object>
+						<reference key="parent" ref="1002"/>
+					</object>
+					<object class="IBObjectRecord">
+						<int key="objectID">2</int>
+						<reference key="object" ref="1006"/>
+						<object class="NSMutableArray" key="children">
+							<bool key="EncodedWithXMLCoder">YES</bool>
+							<reference ref="857285538"/>
+							<reference ref="82942187"/>
+							<reference ref="583982648"/>
+							<reference ref="125608385"/>
+							<reference ref="644051649"/>
+							<reference ref="809137054"/>
+							<reference ref="1025071149"/>
+							<reference ref="767489727"/>
+							<reference ref="79509684"/>
+							<reference ref="229354320"/>
+							<reference ref="662881888"/>
+							<reference ref="607934766"/>
+							<reference ref="543510533"/>
+							<reference ref="720301440"/>
+							<reference ref="628774051"/>
+							<reference ref="841149624"/>
+							<reference ref="665211230"/>
+							<reference ref="149242470"/>
+							<reference ref="502682855"/>
+							<reference ref="1020002354"/>
+							<reference ref="848322395"/>
+							<reference ref="860928395"/>
+						</object>
+						<reference key="parent" ref="1005"/>
+					</object>
+					<object class="IBObjectRecord">
+						<int key="objectID">3</int>
+						<reference key="object" ref="502682855"/>
+						<object class="NSMutableArray" key="children">
+							<bool key="EncodedWithXMLCoder">YES</bool>
+							<reference ref="232181660"/>
+						</object>
+						<reference key="parent" ref="1006"/>
+					</object>
+					<object class="IBObjectRecord">
+						<int key="objectID">4</int>
+						<reference key="object" ref="232181660"/>
+						<reference key="parent" ref="502682855"/>
+					</object>
+					<object class="IBObjectRecord">
+						<int key="objectID">5</int>
+						<reference key="object" ref="857285538"/>
+						<object class="NSMutableArray" key="children">
+							<bool key="EncodedWithXMLCoder">YES</bool>
+							<reference ref="616540554"/>
+						</object>
+						<reference key="parent" ref="1006"/>
+					</object>
+					<object class="IBObjectRecord">
+						<int key="objectID">6</int>
+						<reference key="object" ref="616540554"/>
+						<reference key="parent" ref="857285538"/>
+					</object>
+					<object class="IBObjectRecord">
+						<int key="objectID">7</int>
+						<reference key="object" ref="82942187"/>
+						<object class="NSMutableArray" key="children">
+							<bool key="EncodedWithXMLCoder">YES</bool>
+							<reference ref="618853427"/>
+						</object>
+						<reference key="parent" ref="1006"/>
+					</object>
+					<object class="IBObjectRecord">
+						<int key="objectID">8</int>
+						<reference key="object" ref="618853427"/>
+						<object class="NSMutableArray" key="children">
+							<bool key="EncodedWithXMLCoder">YES</bool>
+						</object>
+						<reference key="parent" ref="82942187"/>
+					</object>
+					<object class="IBObjectRecord">
+						<int key="objectID">9</int>
+						<reference key="object" ref="1025071149"/>
+						<object class="NSMutableArray" key="children">
+							<bool key="EncodedWithXMLCoder">YES</bool>
+							<reference ref="311690344"/>
+						</object>
+						<reference key="parent" ref="1006"/>
+					</object>
+					<object class="IBObjectRecord">
+						<int key="objectID">10</int>
+						<reference key="object" ref="311690344"/>
+						<reference key="parent" ref="1025071149"/>
+					</object>
+					<object class="IBObjectRecord">
+						<int key="objectID">11</int>
+						<reference key="object" ref="79509684"/>
+						<object class="NSMutableArray" key="children">
+							<bool key="EncodedWithXMLCoder">YES</bool>
+							<reference ref="961478139"/>
+						</object>
+						<reference key="parent" ref="1006"/>
+					</object>
+					<object class="IBObjectRecord">
+						<int key="objectID">12</int>
+						<reference key="object" ref="961478139"/>
+						<reference key="parent" ref="79509684"/>
+					</object>
+					<object class="IBObjectRecord">
+						<int key="objectID">13</int>
+						<reference key="object" ref="767489727"/>
+						<object class="NSMutableArray" key="children">
+							<bool key="EncodedWithXMLCoder">YES</bool>
+							<reference ref="487292094"/>
+						</object>
+						<reference key="parent" ref="1006"/>
+					</object>
+					<object class="IBObjectRecord">
+						<int key="objectID">14</int>
+						<reference key="object" ref="487292094"/>
+						<reference key="parent" ref="767489727"/>
+					</object>
+					<object class="IBObjectRecord">
+						<int key="objectID">15</int>
+						<reference key="object" ref="583982648"/>
+						<object class="NSMutableArray" key="children">
+							<bool key="EncodedWithXMLCoder">YES</bool>
+							<reference ref="5436249"/>
+						</object>
+						<reference key="parent" ref="1006"/>
+					</object>
+					<object class="IBObjectRecord">
+						<int key="objectID">16</int>
+						<reference key="object" ref="5436249"/>
+						<object class="NSMutableArray" key="children">
+							<bool key="EncodedWithXMLCoder">YES</bool>
+							<reference ref="801243361"/>
+						</object>
+						<reference key="parent" ref="583982648"/>
+					</object>
+					<object class="IBObjectRecord">
+						<int key="objectID">17</int>
+						<reference key="object" ref="125608385"/>
+						<object class="NSMutableArray" key="children">
+							<bool key="EncodedWithXMLCoder">YES</bool>
+							<reference ref="1071273742"/>
+						</object>
+						<reference key="parent" ref="1006"/>
+					</object>
+					<object class="IBObjectRecord">
+						<int key="objectID">18</int>
+						<reference key="object" ref="1071273742"/>
+						<object class="NSMutableArray" key="children">
+							<bool key="EncodedWithXMLCoder">YES</bool>
+							<reference ref="757491514"/>
+						</object>
+						<reference key="parent" ref="125608385"/>
+					</object>
+					<object class="IBObjectRecord">
+						<int key="objectID">19</int>
+						<reference key="object" ref="644051649"/>
+						<object class="NSMutableArray" key="children">
+							<bool key="EncodedWithXMLCoder">YES</bool>
+							<reference ref="111648228"/>
+						</object>
+						<reference key="parent" ref="1006"/>
+					</object>
+					<object class="IBObjectRecord">
+						<int key="objectID">20</int>
+						<reference key="object" ref="111648228"/>
+						<object class="NSMutableArray" key="children">
+							<bool key="EncodedWithXMLCoder">YES</bool>
+							<reference ref="123140303"/>
+						</object>
+						<reference key="parent" ref="644051649"/>
+					</object>
+					<object class="IBObjectRecord">
+						<int key="objectID">21</int>
+						<reference key="object" ref="801243361"/>
+						<reference key="parent" ref="5436249"/>
+					</object>
+					<object class="IBObjectRecord">
+						<int key="objectID">22</int>
+						<reference key="object" ref="757491514"/>
+						<reference key="parent" ref="1071273742"/>
+					</object>
+					<object class="IBObjectRecord">
+						<int key="objectID">24</int>
+						<reference key="object" ref="809137054"/>
+						<object class="NSMutableArray" key="children">
+							<bool key="EncodedWithXMLCoder">YES</bool>
+							<reference ref="310865555"/>
+						</object>
+						<reference key="parent" ref="1006"/>
+					</object>
+					<object class="IBObjectRecord">
+						<int key="objectID">25</int>
+						<reference key="object" ref="310865555"/>
+						<object class="NSMutableArray" key="children">
+							<bool key="EncodedWithXMLCoder">YES</bool>
+							<reference ref="506223138"/>
+						</object>
+						<reference key="parent" ref="809137054"/>
+					</object>
+					<object class="IBObjectRecord">
+						<int key="objectID">27</int>
+						<reference key="object" ref="229354320"/>
+						<object class="NSMutableArray" key="children">
+							<bool key="EncodedWithXMLCoder">YES</bool>
+							<reference ref="767188954"/>
+						</object>
+						<reference key="parent" ref="1006"/>
+					</object>
+					<object class="IBObjectRecord">
+						<int key="objectID">28</int>
+						<reference key="object" ref="767188954"/>
+						<reference key="parent" ref="229354320"/>
+					</object>
+					<object class="IBObjectRecord">
+						<int key="objectID">29</int>
+						<reference key="object" ref="628774051"/>
+						<object class="NSMutableArray" key="children">
+							<bool key="EncodedWithXMLCoder">YES</bool>
+							<reference ref="853217630"/>
+							<reference ref="46258786"/>
+							<reference ref="735574461"/>
+							<reference ref="322221180"/>
+							<reference ref="149842975"/>
+						</object>
+						<reference key="parent" ref="1006"/>
+					</object>
+					<object class="IBObjectRecord">
+						<int key="objectID">30</int>
+						<reference key="object" ref="853217630"/>
+						<reference key="parent" ref="628774051"/>
+					</object>
+					<object class="IBObjectRecord">
+						<int key="objectID">31</int>
+						<reference key="object" ref="46258786"/>
+						<reference key="parent" ref="628774051"/>
+					</object>
+					<object class="IBObjectRecord">
+						<int key="objectID">32</int>
+						<reference key="object" ref="735574461"/>
+						<reference key="parent" ref="628774051"/>
+					</object>
+					<object class="IBObjectRecord">
+						<int key="objectID">33</int>
+						<reference key="object" ref="322221180"/>
+						<reference key="parent" ref="628774051"/>
+					</object>
+					<object class="IBObjectRecord">
+						<int key="objectID">34</int>
+						<reference key="object" ref="149842975"/>
+						<reference key="parent" ref="628774051"/>
+					</object>
+					<object class="IBObjectRecord">
+						<int key="objectID">35</int>
+						<reference key="object" ref="841149624"/>
+						<object class="NSMutableArray" key="children">
+							<bool key="EncodedWithXMLCoder">YES</bool>
+							<reference ref="405363163"/>
+						</object>
+						<reference key="parent" ref="1006"/>
+					</object>
+					<object class="IBObjectRecord">
+						<int key="objectID">36</int>
+						<reference key="object" ref="405363163"/>
+						<reference key="parent" ref="841149624"/>
+					</object>
+					<object class="IBObjectRecord">
+						<int key="objectID">60</int>
+						<reference key="object" ref="543510533"/>
+						<object class="NSMutableArray" key="children">
+							<bool key="EncodedWithXMLCoder">YES</bool>
+							<reference ref="1003059605"/>
+						</object>
+						<reference key="parent" ref="1006"/>
+					</object>
+					<object class="IBObjectRecord">
+						<int key="objectID">61</int>
+						<reference key="object" ref="1003059605"/>
+						<object class="NSMutableArray" key="children">
+							<bool key="EncodedWithXMLCoder">YES</bool>
+							<reference ref="478164133"/>
+						</object>
+						<reference key="parent" ref="543510533"/>
+					</object>
+					<object class="IBObjectRecord">
+						<int key="objectID">62</int>
+						<reference key="object" ref="720301440"/>
+						<object class="NSMutableArray" key="children">
+							<bool key="EncodedWithXMLCoder">YES</bool>
+							<reference ref="622482629"/>
+						</object>
+						<reference key="parent" ref="1006"/>
+					</object>
+					<object class="IBObjectRecord">
+						<int key="objectID">63</int>
+						<reference key="object" ref="622482629"/>
+						<object class="NSMutableArray" key="children">
+							<bool key="EncodedWithXMLCoder">YES</bool>
+							<reference ref="472826315"/>
+						</object>
+						<reference key="parent" ref="720301440"/>
+					</object>
+					<object class="IBObjectRecord">
+						<int key="objectID">64</int>
+						<reference key="object" ref="662881888"/>
+						<object class="NSMutableArray" key="children">
+							<bool key="EncodedWithXMLCoder">YES</bool>
+							<reference ref="124721751"/>
+						</object>
+						<reference key="parent" ref="1006"/>
+					</object>
+					<object class="IBObjectRecord">
+						<int key="objectID">65</int>
+						<reference key="object" ref="124721751"/>
+						<reference key="parent" ref="662881888"/>
+					</object>
+					<object class="IBObjectRecord">
+						<int key="objectID">66</int>
+						<reference key="object" ref="607934766"/>
+						<object class="NSMutableArray" key="children">
+							<bool key="EncodedWithXMLCoder">YES</bool>
+							<reference ref="211620694"/>
+						</object>
+						<reference key="parent" ref="1006"/>
+					</object>
+					<object class="IBObjectRecord">
+						<int key="objectID">67</int>
+						<reference key="object" ref="211620694"/>
+						<reference key="parent" ref="607934766"/>
+					</object>
+					<object class="IBObjectRecord">
+						<int key="objectID">68</int>
+						<reference key="object" ref="478164133"/>
+						<reference key="parent" ref="1003059605"/>
+					</object>
+					<object class="IBObjectRecord">
+						<int key="objectID">69</int>
+						<reference key="object" ref="472826315"/>
+						<reference key="parent" ref="622482629"/>
+					</object>
+					<object class="IBObjectRecord">
+						<int key="objectID">83</int>
+						<reference key="object" ref="149242470"/>
+						<object class="NSMutableArray" key="children">
+							<bool key="EncodedWithXMLCoder">YES</bool>
+							<reference ref="7019256"/>
+						</object>
+						<reference key="parent" ref="1006"/>
+					</object>
+					<object class="IBObjectRecord">
+						<int key="objectID">84</int>
+						<reference key="object" ref="7019256"/>
+						<reference key="parent" ref="149242470"/>
+					</object>
+					<object class="IBObjectRecord">
+						<int key="objectID">85</int>
+						<reference key="object" ref="665211230"/>
+						<object class="NSMutableArray" key="children">
+							<bool key="EncodedWithXMLCoder">YES</bool>
+							<reference ref="273963221"/>
+						</object>
+						<reference key="parent" ref="1006"/>
+					</object>
+					<object class="IBObjectRecord">
+						<int key="objectID">86</int>
+						<reference key="object" ref="273963221"/>
+						<object class="NSMutableArray" key="children">
+							<bool key="EncodedWithXMLCoder">YES</bool>
+							<reference ref="876830924"/>
+						</object>
+						<reference key="parent" ref="665211230"/>
+					</object>
+					<object class="IBObjectRecord">
+						<int key="objectID">87</int>
+						<reference key="object" ref="876830924"/>
+						<reference key="parent" ref="273963221"/>
+					</object>
+					<object class="IBObjectRecord">
+						<int key="objectID">130</int>
+						<reference key="object" ref="1020002354"/>
+						<object class="NSMutableArray" key="children">
+							<bool key="EncodedWithXMLCoder">YES</bool>
+							<reference ref="1010722721"/>
+						</object>
+						<reference key="parent" ref="1006"/>
+					</object>
+					<object class="IBObjectRecord">
+						<int key="objectID">131</int>
+						<reference key="object" ref="1010722721"/>
+						<reference key="parent" ref="1020002354"/>
+					</object>
+					<object class="IBObjectRecord">
+						<int key="objectID">136</int>
+						<reference key="object" ref="848322395"/>
+						<object class="NSMutableArray" key="children">
+							<bool key="EncodedWithXMLCoder">YES</bool>
+							<reference ref="294160444"/>
+						</object>
+						<reference key="parent" ref="1006"/>
+					</object>
+					<object class="IBObjectRecord">
+						<int key="objectID">137</int>
+						<reference key="object" ref="294160444"/>
+						<reference key="parent" ref="848322395"/>
+					</object>
+					<object class="IBObjectRecord">
+						<int key="objectID">142</int>
+						<reference key="object" ref="860928395"/>
+						<object class="NSMutableArray" key="children">
+							<bool key="EncodedWithXMLCoder">YES</bool>
+							<reference ref="571238653"/>
+						</object>
+						<reference key="parent" ref="1006"/>
+					</object>
+					<object class="IBObjectRecord">
+						<int key="objectID">143</int>
+						<reference key="object" ref="571238653"/>
+						<reference key="parent" ref="860928395"/>
+					</object>
+					<object class="IBObjectRecord">
+						<int key="objectID">148</int>
+						<reference key="object" ref="123140303"/>
+						<reference key="parent" ref="111648228"/>
+					</object>
+					<object class="IBObjectRecord">
+						<int key="objectID">149</int>
+						<reference key="object" ref="506223138"/>
+						<reference key="parent" ref="310865555"/>
+					</object>
+				</object>
+			</object>
+			<object class="NSMutableDictionary" key="flattenedProperties">
+				<bool key="EncodedWithXMLCoder">YES</bool>
+				<object class="NSMutableArray" key="dict.sortedKeys">
+					<bool key="EncodedWithXMLCoder">YES</bool>
+					<string>-1.IBPluginDependency</string>
+					<string>-2.IBPluginDependency</string>
+					<string>-3.IBPluginDependency</string>
+					<string>1.IBEditorWindowLastContentRect</string>
+					<string>1.IBPluginDependency</string>
+					<string>1.IBWindowTemplateEditedContentRect</string>
+					<string>1.NSWindowTemplate.visibleAtLaunch</string>
+					<string>1.WindowOrigin</string>
+					<string>1.editorWindowContentRectSynchronizationRect</string>
+					<string>10.IBPluginDependency</string>
+					<string>11.IBPluginDependency</string>
+					<string>12.IBPluginDependency</string>
+					<string>13.IBPluginDependency</string>
+					<string>130.IBPluginDependency</string>
+					<string>131.IBPluginDependency</string>
+					<string>136.IBPluginDependency</string>
+					<string>137.IBPluginDependency</string>
+					<string>14.IBPluginDependency</string>
+					<string>142.IBPluginDependency</string>
+					<string>143.IBPluginDependency</string>
+					<string>148.IBPluginDependency</string>
+					<string>149.IBPluginDependency</string>
+					<string>15.IBPluginDependency</string>
+					<string>16.IBPluginDependency</string>
+					<string>17.IBPluginDependency</string>
+					<string>18.IBPluginDependency</string>
+					<string>19.IBPluginDependency</string>
+					<string>2.IBPluginDependency</string>
+					<string>20.IBPluginDependency</string>
+					<string>21.IBPluginDependency</string>
+					<string>22.IBPluginDependency</string>
+					<string>24.IBPluginDependency</string>
+					<string>25.IBPluginDependency</string>
+					<string>27.IBPluginDependency</string>
+					<string>28.IBPluginDependency</string>
+					<string>29.IBPluginDependency</string>
+					<string>3.IBPluginDependency</string>
+					<string>30.IBPluginDependency</string>
+					<string>31.IBPluginDependency</string>
+					<string>32.IBPluginDependency</string>
+					<string>35.IBPluginDependency</string>
+					<string>36.IBPluginDependency</string>
+					<string>4.IBPluginDependency</string>
+					<string>5.IBPluginDependency</string>
+					<string>6.IBPluginDependency</string>
+					<string>60.IBPluginDependency</string>
+					<string>61.IBPluginDependency</string>
+					<string>62.IBPluginDependency</string>
+					<string>63.IBPluginDependency</string>
+					<string>64.IBPluginDependency</string>
+					<string>65.IBPluginDependency</string>
+					<string>66.IBPluginDependency</string>
+					<string>67.IBPluginDependency</string>
+					<string>68.IBPluginDependency</string>
+					<string>69.IBPluginDependency</string>
+					<string>7.IBPluginDependency</string>
+					<string>8.IBPluginDependency</string>
+					<string>83.IBPluginDependency</string>
+					<string>84.IBPluginDependency</string>
+					<string>85.IBPluginDependency</string>
+					<string>86.IBPluginDependency</string>
+					<string>87.IBPluginDependency</string>
+					<string>9.IBPluginDependency</string>
+				</object>
+				<object class="NSMutableArray" key="dict.values">
+					<bool key="EncodedWithXMLCoder">YES</bool>
+					<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
+					<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
+					<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
+					<string>{{103, 262}, {527, 498}}</string>
+					<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
+					<string>{{103, 262}, {527, 498}}</string>
+					<reference ref="9"/>
+					<string>{196, 240}</string>
+					<string>{{357, 418}, {480, 270}}</string>
+					<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
+					<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
+					<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
+					<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
+					<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
+					<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
+					<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
+					<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
+					<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
+					<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
+					<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
+					<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
+					<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
+					<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
+					<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
+					<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
+					<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
+					<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
+					<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
+					<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
+					<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
+					<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
+					<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
+					<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
+					<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
+					<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
+					<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
+					<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
+					<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
+					<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
+					<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
+					<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
+					<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
+					<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
+					<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
+					<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
+					<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
+					<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
+					<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
+					<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
+					<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
+					<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
+					<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
+					<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
+					<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
+					<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
+					<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
+					<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
+					<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
+					<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
+					<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
+					<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
+					<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
+					<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
+				</object>
+			</object>
+			<object class="NSMutableDictionary" key="unlocalizedProperties">
+				<bool key="EncodedWithXMLCoder">YES</bool>
+				<object class="NSArray" key="dict.sortedKeys">
+					<bool key="EncodedWithXMLCoder">YES</bool>
+				</object>
+				<object class="NSMutableArray" key="dict.values">
+					<bool key="EncodedWithXMLCoder">YES</bool>
+				</object>
+			</object>
+			<nil key="activeLocalization"/>
+			<object class="NSMutableDictionary" key="localizations">
+				<bool key="EncodedWithXMLCoder">YES</bool>
+				<object class="NSArray" key="dict.sortedKeys">
+					<bool key="EncodedWithXMLCoder">YES</bool>
+				</object>
+				<object class="NSMutableArray" key="dict.values">
+					<bool key="EncodedWithXMLCoder">YES</bool>
+				</object>
+			</object>
+			<nil key="sourceID"/>
+			<int key="maxID">174</int>
+		</object>
+		<object class="IBClassDescriber" key="IBDocument.Classes">
+			<object class="NSMutableArray" key="referencedPartialClassDescriptions">
+				<bool key="EncodedWithXMLCoder">YES</bool>
+				<object class="IBPartialClassDescription">
+					<string key="className">LoanController</string>
+					<object class="NSMutableDictionary" key="actions">
+						<string key="NS.key.0">buttonPushed:</string>
+						<string key="NS.object.0">id</string>
+					</object>
+					<object class="NSMutableDictionary" key="outlets">
+						<bool key="EncodedWithXMLCoder">YES</bool>
+						<object class="NSMutableArray" key="dict.sortedKeys">
+							<bool key="EncodedWithXMLCoder">YES</bool>
+							<string>durSlider</string>
+							<string>durText</string>
+							<string>intSlider</string>
+							<string>intText</string>
+							<string>loanText</string>
+							<string>paySlider</string>
+							<string>payText</string>
+							<string>window</string>
+						</object>
+						<object class="NSMutableArray" key="dict.values">
+							<bool key="EncodedWithXMLCoder">YES</bool>
+							<string>id</string>
+							<string>id</string>
+							<string>id</string>
+							<string>id</string>
+							<string>id</string>
+							<string>id</string>
+							<string>id</string>
+							<string>id</string>
+						</object>
+					</object>
+					<object class="IBClassDescriptionSource" key="sourceIdentifier">
+						<string key="majorKey">IBUserSource</string>
+						<string key="minorKey"/>
+					</object>
+				</object>
+				<object class="IBPartialClassDescription">
+					<string key="className">NSMatrix</string>
+					<string key="superclassName">NSControl</string>
+					<object class="IBClassDescriptionSource" key="sourceIdentifier">
+						<string key="majorKey">IBUserSource</string>
+						<string key="minorKey"/>
+					</object>
+				</object>
+			</object>
+		</object>
+		<int key="IBDocument.localizationMode">0</int>
+		<nil key="IBDocument.LastKnownRelativeProjectPath"/>
+		<int key="IBDocument.defaultPropertyAccessControl">3</int>
+	</data>
+</archive>
Index: /trunk/contrib/krueger/InterfaceProjects/Loan Document/loan-doc.lisp
===================================================================
--- /trunk/contrib/krueger/InterfaceProjects/Loan Document/loan-doc.lisp	(revision 13946)
+++ /trunk/contrib/krueger/InterfaceProjects/Loan Document/loan-doc.lisp	(revision 13946)
@@ -0,0 +1,483 @@
+;; loan-doc.lisp
+
+#|
+The MIT license.
+
+Copyright (c) 2010 Paul L. Krueger
+
+Permission is hereby granted, free of charge, to any person obtaining a copy of this software 
+and associated documentation files (the "Software"), to deal in the Software without restriction, 
+including without limitation the rights to use, copy, modify, merge, publish, distribute, 
+sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is 
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all copies or substantial 
+portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT 
+LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. 
+IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, 
+WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE 
+SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+|#
+
+(eval-when (:compile-toplevel :load-toplevel :execute)
+  (require :menu-utils)
+  (require :decimal)
+  (require :date)
+  (require :lisp-doc-controller)
+  (require :loan-win-cntrl)
+  (require :loan-pr-view)
+  (require :ns-string-utils))
+
+(defpackage :loan-document
+  (:nicknames :lnd)
+  (:use :iu :ccl :common-lisp))
+
+(in-package :lnd)
+
+;; demonstration code for creating a Cocoa document class in lisp that can be required
+;; and loaded into a standard running CCL IDE (i.e. does not require a stand-alone program).
+
+(defconstant $max-interest-rate$ .5)
+
+;; Some loan utility functions
+
+;; all equations are derived from a basic loan equation for an N month loan:
+;; LoanPrinciple = MonthlyPayment * ( (1 / (1 + MonthlyInterest)) + 
+;;                                    (1 / (1 + MonthlyInterest)^2) + ... + 
+;;                                    (1 / (1 + MonthlyInterest)^N) )
+;; which can be manipulated to derive:
+;; MonthlyPayment = LoanPrinciple * (MonthlyInterest + (MonthlyInterest / ((1 + MonthlyInterest)^LoanDuration - 1)))
+
+(defun pay-to-loan-ratio (mo-int loan-dur)
+  ;; Just computes the MonthlyPayment/Loan ratio from the basic loan equation given above
+  (if (zerop mo-int) 0 
+    (+ mo-int (/ mo-int (1- (expt (1+ mo-int) loan-dur))))))
+
+;; The loan class
+
+(defclass loan-doc (ns:ns-document)
+  ((loan-amount :accessor loan-amount :initform 0)
+   (interest-rate :accessor interest-rate :initform 0)
+   (loan-duration :accessor loan-duration :initform 0)
+   (monthly-payment :accessor monthly-payment :initform 0)
+   (origination-date :accessor origination-date :initform (now))
+   (first-payment :accessor first-payment :initform (next-month (now)))
+   (pay-schedule :accessor pay-schedule :initform nil)
+   (compute-mode :accessor compute-mode :initform 0)
+   (last-set-param :accessor last-set-param :initform nil)
+   (max-dur :foreign-type #>BOOL :accessor max-dur)
+   (min-dur :foreign-type #>BOOL :accessor min-dur)
+   (min-pay :foreign-type #>BOOL :accessor min-pay))
+  (:default-initargs 
+    :doc-class nil
+    :menu-name nil
+    :file-ext nil)
+  (:metaclass ns:+ns-object))
+
+(defvar *loan-doc-controller* (make-instance 'lisp-doc-controller
+                                :doc-class (find-class 'loan-doc)
+                                :menu-class "Loan"
+                                :file-ext "loan"))
+
+;; Normal lisp methods for our class
+
+(defmethod get-loan-state ((self loan-doc))
+  ;; returns a list of loan state values suitable for use by set-loan-state
+  (list (loan-amount self)
+        (interest-rate self)
+        (loan-duration self)
+        (monthly-payment self)
+        (origination-date self)
+        (first-payment self)
+        (max-dur self)
+        (min-dur self)
+        (min-pay self)))
+
+(defmethod set-loan-state ((self loan-doc) state-list)
+  (setf (last-set-param self) nil)
+  (#/willChangeValueForKey: self #@"loanAmt")
+  (setf (loan-amount self) (pop state-list))
+  (#/didChangeValueForKey: self #@"loanAmt")
+  (#/willChangeValueForKey: self #@"interestRate")
+  (setf (interest-rate self) (pop state-list))
+  (#/didChangeValueForKey: self #@"interestRate")
+  (#/willChangeValueForKey: self #@"loanDuration")
+  (setf  (loan-duration self) (pop state-list))
+  (#/didChangeValueForKey: self #@"loanDuration")
+  (#/willChangeValueForKey: self #@"monthlyPayment")
+  (setf   (monthly-payment self) (pop state-list))
+  (#/didChangeValueForKey: self #@"monthlyPayment")
+  (#/willChangeValueForKey: self #@"originationDate")
+  (setf  (origination-date self) (pop state-list))
+  (#/didChangeValueForKey: self #@"originationDate")
+  (#/willChangeValueForKey: self #@"firstPayment")
+  (setf  (first-payment self) (pop state-list))
+  (#/didChangeValueForKey: self #@"firstPayment")
+  (#/willChangeValueForKey: self #@"maxDur")
+  (setf   (max-dur self) (pop state-list))
+  (#/didChangeValueForKey: self #@"maxDur")
+  (#/willChangeValueForKey: self #@"minDur")
+  (setf   (min-dur self) (pop state-list))
+  (#/didChangeValueForKey: self #@"minDur")
+  (#/willChangeValueForKey: self #@"minPay")
+  (setf   (min-pay self) (pop state-list))
+  (#/didChangeValueForKey: self #@"minPay")
+  (#/willChangeValueForKey: self #@"totInterest")
+  (setf   (pay-schedule self) nil)
+  (#/didChangeValueForKey: self #@"totInterest")
+  (compute-new-loan-values self))
+
+(defmethod create-undo ((self loan-doc) undo-name &optional (always-undo nil))
+  (when (or always-undo (not (eq (last-set-param self) undo-name)))
+    (let ((undo (#/undoManager self))
+          (st (lisp-object-to-ns-data (get-loan-state self))))
+      (#/setLoanState: (#/prepareWithInvocationTarget: undo self)
+                       st)
+      (unless (#/isUndoing undo)
+        (#/setActionName: undo undo-name))
+      (setf (last-set-param self) undo-name))))
+
+(defmethod set-pay-schedule ((self loan-doc))
+  ;; create a detailed payment schedule for the loan using daily compounding of interest 
+  ;; Payments are on the same date of each month, but the number of days between payments
+  ;; varies because the number of days in each month varies.
+  ;; We compute accurate interest compounded daily for the actual number of days.
+  (let ((monthly-interest (/ (interest-rate self) 12))
+        (payment (monthly-payment self))
+        (sched nil)
+        (display-min-pay-banner nil))
+    (prog1
+        (do* ((begin (loan-amount self) end)
+              (begin-date (first-payment self) end-date)
+              (end-date (next-month begin-date) (next-month begin-date))
+              (int (round (* begin monthly-interest))
+                   (round (* begin monthly-interest)))
+              (end (- (+ begin int) payment) (- (+ begin int) payment)))
+             ((not (plusp end)) 
+              (progn
+                (push (list (short-date-string begin-date) 
+                            (/ begin 100)
+                            (/ int 100)
+                            (/ payment 100)
+                            (short-date-string end-date) 
+                            (/ end 100)
+                            int) 
+                      sched)
+                (setf (pay-schedule self) (nreverse sched))))
+          (when (>= end begin)
+            ;; oops, with this combination of values the loan will never 
+            ;; be paid off, so let's set a minimum payment required
+            ;; Display a field that tells user the minimum payment was reached 
+            (setf display-min-pay-banner t)
+            (#/willChangeValueForKey: self #@"monthlyPayment")
+            (setf (monthly-payment self) (1+ int))
+            (#/didChangeValueForKey: self #@"monthlyPayment")
+            ;; now patch up our loop variables and keep going
+            (setf payment (monthly-payment self))
+            (setf end (1- begin)))
+          ;; put the last payment into the list
+          (push (list (short-date-string begin-date) 
+                      (/ begin 100)
+                      (/ int 100)
+                      (/ payment 100)
+                      (short-date-string end-date) 
+                      (/ end 100)
+                      int)
+                sched))
+      (#/willChangeValueForKey: self #@"totInterest")
+      ;; we'll make the total interest field call our accessor 
+      ;; to generate a new amount
+      (#/didChangeValueForKey: self #@"totInterest")
+      (if display-min-pay-banner
+        (progn
+          ;; Set a condition that says the minimum payment was reached 
+          (setf display-min-pay-banner t)
+          (#/willChangeValueForKey: self #@"minPay")
+          (setf (min-pay self) #$YES)
+          (#/didChangeValueForKey: self #@"minPay"))
+        (progn
+          ;; otherwise reset that condition
+          (#/willChangeValueForKey: self #@"minPay")
+          (setf (min-pay self) #$NO)
+          (#/didChangeValueForKey: self #@"minPay")))
+      ;; If we happen to be computing the interest rate, then 
+      ;; the combination of loan-amount and monthly payment will
+      ;; determine a maximum interest rate. This, in turn, 
+      ;; determines a maximum loan duration. If the duration was set
+      ;; longer than this by the user, we will reset the 
+      ;; lone duration value to the maximum needed.
+      ;; If, on the other hand, the monthly payment is set so low that
+      ;; the interest rate approaches 0, then we may have to adjust the
+      ;; loan duration up to the minimum needed to pay the loan.
+      ;; Let's start by resetting our two "duration" conditions and then we'll
+      ;; set them if conditions dictate.
+      ;; Reset a condition that indicates the max duration was reached 
+      (#/willChangeValueForKey: self #@"maxDur")
+      (setf (max-dur self) #$NO)
+      (#/didChangeValueForKey: self #@"maxDur")
+      ;; Reset a condition that indicates the min duration was reached 
+      (#/willChangeValueForKey: self #@"minDur")
+      (setf (min-dur self) #$NO)
+      (#/didChangeValueForKey: self #@"minDur"))
+      (let ((duration-diff (- (loan-duration self) (list-length (pay-schedule self)))))
+        (unless (or (eql (compute-mode self) 2) (zerop duration-diff))
+          ;; i.e. we're not calling this function just to determine the loan duration
+          ;; and we have to adjust the loan duration
+          (if (plusp duration-diff)
+            (progn
+              ;; change the loan-duration value to what it must be
+              (#/willChangeValueForKey: self #@"loanDuration")
+              (setf (loan-duration self) (list-length (pay-schedule self)))
+              (#/didChangeValueForKey: self #@"loanDuration")
+              (when (> duration-diff 2)
+                ;; If we're one-off just fix it and don't post a message
+                ;; This can occur almost anytime because of numerical issues
+                ;; Display a field that tells user the max duration was reached 
+                (#/willChangeValueForKey: self #@"maxDur")
+                (setf (max-dur self) #$YES)
+                (#/didChangeValueForKey: self #@"maxDur")))
+            (progn
+              ;; change the oan-duration value to what it must be
+              (#/willChangeValueForKey: self #@"loanDuration")
+              (setf (loan-duration self) (list-length (pay-schedule self)))
+              (#/didChangeValueForKey: self #@"loanDuration")
+              (when (< duration-diff -2)
+                ;; If we're one-off just fix it and don't post a message
+                ;; This can occur almost anytime because of numerical issues
+                ;; Display a field that tells user the min duration was reached 
+                (#/willChangeValueForKey: self #@"minDur")
+                (setf (min-dur self) #$YES)
+                (#/didChangeValueForKey: self #@"minDur"))))))))
+
+(defmethod print-pay-schedule ((self loan-doc) &optional (strm t))
+  (format strm 
+          "~:{~%On ~a balance = $~$ + interest of $~$ - payment of $~$ = ~a balance of $~$~}"
+          (pay-schedule self)))
+
+(defmethod compute-int-rate ((self loan-doc))
+  ;; Find a monthly interest rate that makes the rest of the values work.
+  ;; There isn't an algebraic solution for the interest rate, so let's search for it.
+  ;; Find a suitable search range and do a binary search for it. Even for large interest 
+  ;; rates the number of search iterations should be minimal.
+
+  (with-slots (loan-amount monthly-payment loan-duration interest-rate) self
+  
+    ;; First we'll check to see whether the monthly payment is great than the loan amount.
+    ;; If so we'll set the interest rate directly so that the loan is paid off in one month.
+    ;; This avoids some ugly arithmetic overflow things that can happen when interest rates
+    ;; go off the charts
+    (let ((max-monthly-rate (/ $max-interest-rate$ 12)))
+      (if (>= monthly-payment loan-amount)
+        (min max-monthly-rate (1- (/ monthly-payment loan-amount)))
+        (let ((imin (max 0 (min max-monthly-rate
+                                (/ (- (* monthly-payment loan-duration) loan-amount) 
+                                   (* loan-duration loan-amount)))))
+              ;; imin is basically a rate that would result in the first month's interest as 
+              ;; the average interest paid for all months. Since we know it must be greater 
+              ;; than this, we have a guaranteed lower bound. But we cap it at our allowed 
+              ;; monthly maximum interest.
+              (imax (min max-monthly-rate 
+                         (- (/ monthly-payment loan-amount) .000008333)))
+              ;; imax is a rate that would result in the first month's interest being 
+              ;; minimally smaller than the payment. Since we must pay off in a finite
+              ;; duration, this is a guaranteed maximum. We cap it the allowed maximum 
+              ;; monthly rate.
+              (target-p-l-ratio (/ monthly-payment loan-amount)))
+          (unless (>= imax imin)
+            (error "Max int = ~8,4f, Min int = ~8,4f" imax imin))
+          (do* ((i (/ (+ imin imax) 2) 
+                   (/ (+ imin imax) 2))
+                (p-l-ratio (pay-to-loan-ratio i loan-duration) 
+                           (pay-to-loan-ratio i loan-duration)))
+               ((<= (- imax imin) .000001) imax)
+            (if (>= target-p-l-ratio p-l-ratio)
+              (setf imin i)
+              (setf imax i))))))))
+
+(defmethod compute-new-loan-values ((self loan-doc))
+  ;; For the sake of expediency we assume monthly componding
+  ;; The basic equation governing these computations is 
+  (with-slots (compute-mode interest-rate loan-duration monthly-payment 
+                            loan-amount pay-schedule) self
+    (case compute-mode
+      (0
+       ;; compute the loan amount
+       (unless (or (zerop interest-rate)
+                   (zerop loan-duration)
+                   (zerop monthly-payment))
+         (#/willChangeValueForKey: self #@"loanAmt")
+         (setf loan-amount 
+               (round (/ monthly-payment 
+                         (pay-to-loan-ratio (/ interest-rate 12)
+                                            loan-duration))))
+         (set-pay-schedule self)
+         (#/didChangeValueForKey: self #@"loanAmt")))
+      (1
+       ;; compute the interest rate
+       (unless (or (zerop loan-amount)
+                   (zerop loan-duration)
+                   (zerop monthly-payment))
+         (#/willChangeValueForKey: self #@"interestRate")
+         (setf interest-rate 
+               (* 12 (/ (floor (* 1000000 (compute-int-rate self)))
+                        1000000)))
+         (set-pay-schedule self)
+         (#/didChangeValueForKey: self #@"interestRate")))
+      (2
+       ;; compute the loan duration
+       (unless (or (zerop interest-rate)
+                   (zerop loan-amount)
+                   (zerop monthly-payment))
+         (#/willChangeValueForKey: self #@"loanDuration")
+         (set-pay-schedule self)
+         (setf loan-duration
+               (list-length pay-schedule))
+         (#/didChangeValueForKey: self #@"loanDuration")))
+      (3
+       ;; compute the monthly payment
+       (unless (or (zerop interest-rate)
+                   (zerop loan-amount)
+                   (zerop loan-duration))
+         (#/willChangeValueForKey: self #@"monthlyPayment")
+         (setf monthly-payment
+               (round (* loan-amount 
+                         (pay-to-loan-ratio (/ interest-rate 12) 
+                                            loan-duration))))
+         (set-pay-schedule self)
+         (#/didChangeValueForKey: self #@"monthlyPayment"))))))
+
+;; Accessor functions used by display objects to retrieve and set values as dictated
+;; by the bindings we set up in IB
+
+(objc:defmethod (#/loanAmt :id)
+                ((self loan-doc))
+  (lisp-to-ns-decimal (loan-amount self)))
+
+(objc:defmethod (#/interestRate :id)
+                ((self loan-doc))
+  (#/numberWithFloat: ns:ns-number (float (interest-rate self))))
+
+(objc:defmethod (#/loanDuration :id)
+                ((self loan-doc))
+  (#/numberWithInt: ns:ns-number (loan-duration self)))
+
+(objc:defmethod (#/monthlyPayment :id)
+                ((self loan-doc))
+  (lisp-to-ns-decimal (monthly-payment self)))
+
+(objc:defmethod (#/originationDate :id)
+                ((self loan-doc))
+  (lisp-to-ns-date (origination-date self)))
+
+(objc:defmethod (#/firstPayment :id)
+                ((self loan-doc))
+  (lisp-to-ns-date (first-payment self)))
+
+(objc:defmethod (#/totInterest :id)
+                ((self loan-doc))
+  (lisp-to-ns-decimal (reduce #'+ (pay-schedule self) 
+                              :key #'seventh 
+                              :initial-value 0)))
+
+(objc:defmethod (#/setLoanAmt: :void)
+                ((self loan-doc) (amt :id))
+  (create-undo self #@"set loan amount")
+  (setf (loan-amount self) (lisp-from-ns-decimal amt))
+  (compute-new-loan-values self))
+
+(objc:defmethod (#/setInterestRate: :void)
+                ((self loan-doc) (rate :id))
+  (create-undo self #@"set interest rate")
+  (setf (interest-rate self) (#/floatValue rate))
+  (compute-new-loan-values self))
+
+(objc:defmethod (#/setLoanDuration: :void)
+                ((self loan-doc) (dur :id))
+  (create-undo self #@"set loan duration")
+  (setf (loan-duration self) (#/longValue dur))
+  (compute-new-loan-values self))
+
+(objc:defmethod (#/setMonthlyPayment: :void)
+                ((self loan-doc) (pay :id))
+  (create-undo self #@"set monthly payment")
+  (setf (monthly-payment self) (lisp-from-ns-decimal pay))
+  (compute-new-loan-values self))
+
+(objc:defmethod (#/setOriginationDate: :void)
+                ((self loan-doc) (dt :id))
+  (create-undo self #@"set origination date")
+  (let ((new-dt (ns-to-lisp-date dt)))
+    (setf (origination-date self) new-dt)
+    (#/willChangeValueForKey: self #@"firstPayment")
+    (setf (first-payment self) (next-month new-dt))
+    (#/didChangeValueForKey: self #@"firstPayment"))
+  (compute-new-loan-values self))
+
+(objc:defmethod (#/setFirstPayment: :void) 
+                ((self loan-doc) (pay :id))
+  (create-undo self #@"set first payment date")
+  (let ((new-pay (ns-to-lisp-date pay)))
+    (setf (first-payment self) new-pay))
+  (compute-new-loan-values self))
+
+;; Necessary overrides of NSDocument methods
+;; Methods called to read data from and write data to external files
+
+(objc:defmethod (#/readFromData:ofType:error: #>BOOL) 
+                ((self loan-doc) (data :id) (dtype :id) (err (:* :id)))
+  (declare (ignore err dtype))
+  (set-loan-state self (ns-data-to-lisp-object data))
+  #$YES)
+
+(objc:defmethod (#/dataOfType:error: :id) 
+                ((self loan-doc) (dtype :id) (err (:* :id)))
+  (declare (ignore dtype err))
+  (lisp-object-to-ns-data (get-loan-state self)))
+
+(objc:defmethod (#/setLoanState: :void)
+                ((self loan-doc) (st :id))
+  (create-undo self nil t)
+  ;; called when user does an "undo" 
+  (set-loan-state self (ns-data-to-lisp-object st)))
+
+;; Methods to manage windows
+
+(objc:defmethod (#/makeWindowControllers :void) 
+                ((self loan-doc))
+  (let ((lwc (make-instance 'loan-win-controller
+               :with-loan self)))
+    (#/setShouldCloseDocument: lwc #$YES)
+    (#/addWindowController: self lwc)))
+
+(objc:defmethod (#/validateMenuItem: #>BOOL) 
+                ((self loan-doc) (item :id))
+  (let* ((action (#/action item)))
+    (cond ((eql action (ccl::@selector #/saveDocument:))
+           (#/isDocumentEdited self))
+          (t (call-next-method item)))))
+
+(objc:defmethod (#/prepareSavePanel: #>BOOL) 
+                ((self loan-doc) (panel :id))
+  (#/setRequiredFileType: panel #@"loan")
+  #$YES)
+
+;; Printing Support
+
+(objc:defmethod (#/printLoan: :void)
+                ((self loan-doc) (sender :id))
+  (declare (ignore sender))
+  (#/printDocument: self self))
+
+(objc:defmethod (#/printOperationWithSettings:error: :id)
+                ((self loan-doc) (settings :id) (err (:* :id)))
+  (declare (ignore err settings))
+  (let ((pr-view (make-instance 'loan-print-view
+                   :loan self)))
+    (#/printOperationWithView:printInfo: ns:ns-print-operation 
+                                         pr-view 
+                                         (#/printInfo self))))
+    
+(provide :loan-doc)
Index: /trunk/contrib/krueger/InterfaceProjects/Loan Document/loan-pr-view.lisp
===================================================================
--- /trunk/contrib/krueger/InterfaceProjects/Loan Document/loan-pr-view.lisp	(revision 13946)
+++ /trunk/contrib/krueger/InterfaceProjects/Loan Document/loan-pr-view.lisp	(revision 13946)
@@ -0,0 +1,139 @@
+;; loan-pr-view.lisp
+
+(eval-when (:compile-toplevel :load-toplevel :execute)
+  (require :date)
+  (require :nslog-utils))
+
+(defpackage :loan-document
+  (:nicknames :lnd)
+  (:use :iu :ccl :common-lisp))
+
+(in-package :lnd)
+
+;; provides a view class used to print loan information
+
+(defclass loan-print-view (ns:ns-view)
+  ((loan :accessor loan 
+         :initarg :loan)
+   (attributes :accessor attributes 
+               :initform (make-instance ns:ns-mutable-dictionary))
+   (page-line-count :accessor page-line-count
+                    :initform 0)
+   (line-height :accessor line-height)
+   (page-num :accessor page-num
+             :initform 0)
+   (page-rect :accessor page-rect))
+  (:metaclass ns:+ns-object))
+
+(defmethod initialize-instance :after ((self loan-print-view)
+                                       &key &allow-other-keys)
+  ;; assure loan still exists if user closes the window while we are printing
+  (#/retain (loan self))
+  (ccl:terminate-when-unreachable self)
+  (let* ((font (#/fontWithName:size: ns:ns-font #@"Courier" 8.0)))
+    (setf (line-height self) (* (+ (#/ascender font) (abs (#/descender font))) 1.5))
+    (#/setObject:forKey: (attributes self) font #$NSFontAttributeName)))
+
+(defmethod ccl:terminate ((self loan-print-view))
+  (#/release (loan self))
+  (#/release (attributes self)))
+
+(objc:defmethod (#/knowsPageRange: :<BOOL>) 
+                ((self loan-print-view) (range (:* #>NSRange)))
+  ;; compute printing parameters and set the range
+  (let* ((pr-op (#/currentOperation ns:ns-print-operation))
+         (pr-info (#/printInfo pr-op))
+         ;; (pg-size (#/paperSize pr-info))
+         ;; (left-margin (#/leftMargin pr-info))
+         ;; (right-margin (#/rightMargin pr-info))
+         ;; (top-margin (#/topMargin pr-info))
+         ;; (bottom-margin (#/bottomMargin pr-info))
+         (image-rect (#/imageablePageBounds pr-info))
+         (pg-rect (ns:make-ns-rect 0 
+                                   0 
+                                   (ns:ns-rect-width image-rect)
+                                   (ns:ns-rect-height image-rect))))
+    ;; (log-size pg-size "pg-size: ")
+    ;; (log-4floats left-margin right-margin top-margin bottom-margin 
+    ;;              (list "Margins: left = " " right = " " top = " " bottom = "))
+    ;; (log-rect image-rect "imageable rect: ")
+    (setf (page-rect self) pg-rect)
+    ;; (log-rect pg-rect "my page rect: ")
+    (#/setFrame: self pg-rect)
+    ;; (log-float (line-height self) "Line Height: ")
+    (setf (page-line-count self) (floor (ns:ns-rect-height pg-rect) 
+                                        (line-height self)))
+    ;; start on page 1
+    (setf (ns:ns-range-location range) 1)
+    ;; compute the number of pages for 9 header lines on page 1 and 2 header
+    ;; lines on subsequet pages plus a line per payment
+    (let* ((pay-lines-on-p-1 (- (page-line-count self) 7))
+           (other-pages-needed (ceiling (max 0 (- (list-length (pay-schedule (loan self)))
+                                                  pay-lines-on-p-1))
+                                        (page-line-count self))))
+      (setf (ns:ns-range-length range)
+            (1+ other-pages-needed))))
+  #$YES)
+
+(objc:defmethod (#/rectForPage: #>NSRect)
+                ((self loan-print-view) (pg #>NSInteger))
+  (setf (page-num self) (1- pg))
+  (page-rect self))
+
+(objc:defmethod (#/isFlipped #>BOOL)
+                ((self loan-print-view))
+  ;; we compute coords from upper left
+  #$YES)
+
+(objc:defmethod (#/drawRect: :void)
+                ((self loan-print-view) (r #>NSRect))
+  (with-slots (loan attributes page-line-count line-height page-num page-rect) self
+    (ns:with-ns-rect (line-rect (ns:ns-rect-x r) 
+                                (- (ns:ns-rect-y r) line-height)
+                                (ns:ns-rect-width r) 
+                                line-height)
+      
+      ;; (log-rect r "draw rect: ")
+      (labels ((draw-next-line (str)
+                 (incf (ns:ns-rect-y line-rect) line-height)
+                 (#/drawInRect:withAttributes: 
+                  (lisp-to-temp-nsstring str)
+                  line-rect
+                  attributes))
+               (draw-next-payment (sched-line)
+                 (draw-next-line 
+                  (format nil
+     "~1{On ~a balance = $~$ + interest of $~$ - payment of $~$ = ~a balance of $~$~}"
+                          sched-line))))
+        (when (zerop page-num)
+          ;; print all the basic loan info
+          (draw-next-line (format nil 
+                                  "Loan ID: ~a" 
+                                  (ns-to-lisp-string (#/displayName loan))))
+          (draw-next-line (format nil 
+                                  "Amount: $~$"
+                                  (/ (loan-amount loan) 100)))
+          (draw-next-line (format nil 
+                                  "Origination Date: ~a"
+                                  (date-string (origination-date loan))))
+          (draw-next-line (format nil 
+                                  "Annual Interest Rate: ~7,4F%"
+                                  (* 100 (interest-rate loan))))
+          (draw-next-line (format nil 
+                                  "Loan Duration: ~D month~:P"
+                                  (loan-duration loan)))
+          (draw-next-line (format nil 
+                                  "Monthly Payment: $~$"
+                                  (/ (monthly-payment loan) 100)))
+          ;; draw spacer line
+          (incf (ns:ns-rect-y line-rect) line-height))
+        ;; print the appropriate schedule lines for this page
+        (let* ((lines-per-page (- page-line-count (if (zerop page-num) 7 0)))
+               (start-indx (if (zerop page-num) 0 (+ (- page-line-count 7) 
+                                                     (* lines-per-page (1- page-num)))))
+               (end-indx (min (length (pay-schedule loan)) 
+                              (+ start-indx lines-per-page 1))))
+          (dolist (sched-line (subseq (pay-schedule loan) start-indx end-indx))
+            (draw-next-payment sched-line)))))))
+
+(provide :loan-pr-view)
Index: /trunk/contrib/krueger/InterfaceProjects/Loan Document/loan-win-cntrl.lisp
===================================================================
--- /trunk/contrib/krueger/InterfaceProjects/Loan Document/loan-win-cntrl.lisp	(revision 13946)
+++ /trunk/contrib/krueger/InterfaceProjects/Loan Document/loan-win-cntrl.lisp	(revision 13946)
@@ -0,0 +1,100 @@
+;;; loan-win-cntrl.lisp
+
+#|
+The MIT license.
+
+Copyright (c) 2010 Paul L. Krueger
+
+Permission is hereby granted, free of charge, to any person obtaining a copy of this software 
+and associated documentation files (the "Software"), to deal in the Software without restriction, 
+including without limitation the rights to use, copy, modify, merge, publish, distribute, 
+sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is 
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all copies or substantial 
+portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT 
+LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. 
+IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, 
+WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE 
+SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+|#
+
+;;; Sample lisp/Cocoa interface that uses a NIB file defined with interface builder;
+;;; A definition is provided for the "SpeechController" class that was specified to interface builder
+;;; as the class of the NIB file owner.
+;;; We manually create an instance of SpeechController and specify it as the owner for the NIB file.
+
+(defpackage :loan-document
+  (:nicknames :lnd)
+  (:use :iu :ccl :common-lisp))
+
+(in-package :lnd)
+
+;; The loan-win-controller class
+
+(defclass loan-win-controller (ns:ns-window-controller)
+  ((loan :foreign-type :id :accessor loan)
+   (orig-date-text :foreign-type :id :accessor orig-date-text)
+   (loan-text :foreign-type :id :accessor loan-text)
+   (int-text :foreign-type :id :accessor int-text)
+   (dur-text :foreign-type :id :accessor dur-text)
+   (pay-text :foreign-type :id :accessor pay-text)
+   (int-slider :foreign-type :id :accessor int-slider)
+   (dur-slider :foreign-type :id :accessor dur-slider)
+   (pay-slider :foreign-type :id :accessor pay-slider))
+  (:metaclass ns:+ns-object))
+
+(objc:defmethod (#/initWithLoan: :id)
+                ((self loan-win-controller) (ln :id))
+  (setf (loan self) ln)
+  (let* ((nib-name (ccl::%make-nsstring 
+                    (namestring (truename "ip:Loan Document;loandoc.nib"))))
+         (init-self (#/initWithWindowNibPath:owner: self nib-name self)))
+    init-self))
+
+;; Action methods that are called when controls do something
+
+(objc:defmethod (#/buttonPushed: :void) 
+                ((self loan-win-controller) (button-matrix :id))
+  (with-slots (loan loan-text int-text dur-text pay-text int-slider 
+                    dur-slider pay-slider) self
+    (let ((cm (#/selectedRow button-matrix)))
+      (unless (eql cm (compute-mode loan))
+        (case (compute-mode loan)
+          (0 (#/setEnabled: loan-text #$YES))
+          (1 (#/setEnabled: int-text #$YES)
+             (#/setEnabled: int-slider #$YES))
+          (2 (#/setEnabled: dur-text #$YES)
+             (#/setEnabled: dur-slider #$YES))
+          (3 (#/setEnabled: pay-text #$YES)
+             (#/setEnabled: pay-slider #$YES)))
+        (setf (compute-mode loan) cm)
+        (case cm
+          (0 (#/setEnabled: loan-text #$NO))
+          (1 (#/setEnabled: int-text #$NO)
+             (#/setEnabled: int-slider #$NO))
+          (2 (#/setEnabled: dur-text #$NO)
+             (#/setEnabled: dur-slider #$NO))
+          (3 (#/setEnabled: pay-text #$NO)
+             (#/setEnabled: pay-slider #$NO)))
+        (compute-new-loan-values loan)))))
+
+(objc:defmethod (#/awakeFromNib :void) 
+                ((self loan-win-controller))
+  (#/setEnabled: (loan-text self) #$NO)
+  ;; set the sliders to update continuously so that the text boxes reflect the current value
+  ;; Note that we can set this in IB for text boxes, but not, apparently, for sliders
+  (#/setContinuous: (int-slider self) #$YES)
+  (#/setContinuous: (dur-slider self) #$YES)
+  (#/setContinuous: (pay-slider self) #$YES)
+  ;; tell the text cells not to handle undo
+  (#/setAllowsUndo: (#/cell (loan-text self)) #$NO)
+  (#/setAllowsUndo: (#/cell (int-text self)) #$NO)
+  (#/setAllowsUndo: (#/cell (dur-text self)) #$NO)
+  (#/setAllowsUndo: (#/cell (pay-text self)) #$NO)
+  (#/setAllowsUndo: (#/cell (orig-date-text self)) #$NO))
+
+(provide :loan-win-cntrl)
Index: /trunk/contrib/krueger/InterfaceProjects/Loan Document/loandoc.nib/designable.nib
===================================================================
--- /trunk/contrib/krueger/InterfaceProjects/Loan Document/loandoc.nib/designable.nib	(revision 13946)
+++ /trunk/contrib/krueger/InterfaceProjects/Loan Document/loandoc.nib/designable.nib	(revision 13946)
@@ -0,0 +1,2137 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<archive type="com.apple.InterfaceBuilder3.Cocoa.XIB" version="7.03">
+	<data>
+		<int key="IBDocument.SystemTarget">1050</int>
+		<string key="IBDocument.SystemVersion">9L30</string>
+		<string key="IBDocument.InterfaceBuilderVersion">680</string>
+		<string key="IBDocument.AppKitVersion">949.54</string>
+		<string key="IBDocument.HIToolboxVersion">353.00</string>
+		<object class="NSMutableArray" key="IBDocument.EditedObjectIDs">
+			<bool key="EncodedWithXMLCoder">YES</bool>
+		</object>
+		<object class="NSArray" key="IBDocument.PluginDependencies">
+			<bool key="EncodedWithXMLCoder">YES</bool>
+			<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
+		</object>
+		<object class="NSMutableDictionary" key="IBDocument.Metadata">
+			<bool key="EncodedWithXMLCoder">YES</bool>
+			<object class="NSArray" key="dict.sortedKeys">
+				<bool key="EncodedWithXMLCoder">YES</bool>
+			</object>
+			<object class="NSMutableArray" key="dict.values">
+				<bool key="EncodedWithXMLCoder">YES</bool>
+			</object>
+		</object>
+		<object class="NSMutableArray" key="IBDocument.RootObjects" id="1000">
+			<bool key="EncodedWithXMLCoder">YES</bool>
+			<object class="NSCustomObject" id="1001">
+				<string key="NSClassName">LoanController</string>
+			</object>
+			<object class="NSCustomObject" id="1003">
+				<string key="NSClassName">FirstResponder</string>
+			</object>
+			<object class="NSCustomObject" id="1004">
+				<string key="NSClassName">NSApplication</string>
+			</object>
+			<object class="NSWindowTemplate" id="1005">
+				<int key="NSWindowStyleMask">7</int>
+				<int key="NSWindowBacking">2</int>
+				<string key="NSWindowRect">{{196, 12}, {527, 498}}</string>
+				<int key="NSWTFlags">536870912</int>
+				<string key="NSWindowTitle">Loan Calculator</string>
+				<string key="NSWindowClass">NSWindow</string>
+				<nil key="NSViewClass"/>
+				<string key="NSWindowContentMaxSize">{3.40282e+38, 3.40282e+38}</string>
+				<object class="NSView" key="NSWindowView" id="1006">
+					<nil key="NSNextResponder"/>
+					<int key="NSvFlags">256</int>
+					<object class="NSMutableArray" key="NSSubviews">
+						<bool key="EncodedWithXMLCoder">YES</bool>
+						<object class="NSSlider" id="502682855">
+							<reference key="NSNextResponder" ref="1006"/>
+							<int key="NSvFlags">268</int>
+							<string key="NSFrame">{{31, 360}, {284, 21}}</string>
+							<reference key="NSSuperview" ref="1006"/>
+							<bool key="NSEnabled">YES</bool>
+							<object class="NSSliderCell" key="NSCell" id="232181660">
+								<int key="NSCellFlags">-2080244224</int>
+								<int key="NSCellFlags2">0</int>
+								<string key="NSContents"/>
+								<object class="NSFont" key="NSSupport" id="2332340">
+									<string key="NSName">Helvetica</string>
+									<double key="NSSize">1.200000e+01</double>
+									<int key="NSfFlags">16</int>
+								</object>
+								<reference key="NSControlView" ref="502682855"/>
+								<double key="NSMaxValue">5.000000e-01</double>
+								<double key="NSMinValue">0.000000e+00</double>
+								<double key="NSValue">1.000000e-01</double>
+								<double key="NSAltIncValue">0.000000e+00</double>
+								<int key="NSNumberOfTickMarks">0</int>
+								<int key="NSTickMarkPosition">0</int>
+								<bool key="NSAllowsTickMarkValuesOnly">YES</bool>
+								<bool key="NSVertical">NO</bool>
+							</object>
+						</object>
+						<object class="NSSlider" id="857285538">
+							<reference key="NSNextResponder" ref="1006"/>
+							<int key="NSvFlags">268</int>
+							<string key="NSFrame">{{31, 280}, {284, 21}}</string>
+							<reference key="NSSuperview" ref="1006"/>
+							<bool key="NSEnabled">YES</bool>
+							<object class="NSSliderCell" key="NSCell" id="616540554">
+								<int key="NSCellFlags">-2080244224</int>
+								<int key="NSCellFlags2">0</int>
+								<string key="NSContents"/>
+								<reference key="NSSupport" ref="2332340"/>
+								<reference key="NSControlView" ref="857285538"/>
+								<double key="NSMaxValue">5.000000e+02</double>
+								<double key="NSMinValue">0.000000e+00</double>
+								<double key="NSValue">1.200000e+02</double>
+								<double key="NSAltIncValue">0.000000e+00</double>
+								<int key="NSNumberOfTickMarks">0</int>
+								<int key="NSTickMarkPosition">1</int>
+								<bool key="NSAllowsTickMarkValuesOnly">NO</bool>
+								<bool key="NSVertical">NO</bool>
+							</object>
+						</object>
+						<object class="NSSlider" id="82942187">
+							<reference key="NSNextResponder" ref="1006"/>
+							<int key="NSvFlags">268</int>
+							<string key="NSFrame">{{31, 192}, {284, 21}}</string>
+							<reference key="NSSuperview" ref="1006"/>
+							<bool key="NSEnabled">YES</bool>
+							<object class="NSSliderCell" key="NSCell" id="618853427">
+								<int key="NSCellFlags">-2080244224</int>
+								<int key="NSCellFlags2">0</int>
+								<string key="NSContents"/>
+								<reference key="NSSupport" ref="2332340"/>
+								<reference key="NSControlView" ref="82942187"/>
+								<double key="NSMaxValue">1.000000e+04</double>
+								<double key="NSMinValue">0.000000e+00</double>
+								<double key="NSValue">1.000000e+02</double>
+								<double key="NSAltIncValue">0.000000e+00</double>
+								<int key="NSNumberOfTickMarks">0</int>
+								<int key="NSTickMarkPosition">1</int>
+								<bool key="NSAllowsTickMarkValuesOnly">NO</bool>
+								<bool key="NSVertical">NO</bool>
+							</object>
+						</object>
+						<object class="NSTextField" id="1025071149">
+							<reference key="NSNextResponder" ref="1006"/>
+							<int key="NSvFlags">268</int>
+							<string key="NSFrame">{{107, 387}, {145, 17}}</string>
+							<reference key="NSSuperview" ref="1006"/>
+							<bool key="NSEnabled">YES</bool>
+							<object class="NSTextFieldCell" key="NSCell" id="311690344">
+								<int key="NSCellFlags">68288064</int>
+								<int key="NSCellFlags2">272630784</int>
+								<string key="NSContents">Annual Interest Rate %</string>
+								<object class="NSFont" key="NSSupport" id="227377946">
+									<string key="NSName">LucidaGrande</string>
+									<double key="NSSize">1.300000e+01</double>
+									<int key="NSfFlags">1044</int>
+								</object>
+								<reference key="NSControlView" ref="1025071149"/>
+								<object class="NSColor" key="NSBackgroundColor" id="344940583">
+									<int key="NSColorSpace">6</int>
+									<string key="NSCatalogName">System</string>
+									<string key="NSColorName">controlColor</string>
+									<object class="NSColor" key="NSColor">
+										<int key="NSColorSpace">3</int>
+										<bytes key="NSWhite">MC42NjY2NjY2OQA</bytes>
+									</object>
+								</object>
+								<object class="NSColor" key="NSTextColor" id="942182489">
+									<int key="NSColorSpace">6</int>
+									<string key="NSCatalogName">System</string>
+									<string key="NSColorName">controlTextColor</string>
+									<object class="NSColor" key="NSColor" id="752056265">
+										<int key="NSColorSpace">3</int>
+										<bytes key="NSWhite">MAA</bytes>
+									</object>
+								</object>
+							</object>
+						</object>
+						<object class="NSTextField" id="79509684">
+							<reference key="NSNextResponder" ref="1006"/>
+							<int key="NSvFlags">268</int>
+							<string key="NSFrame">{{95, 302}, {154, 17}}</string>
+							<reference key="NSSuperview" ref="1006"/>
+							<bool key="NSEnabled">YES</bool>
+							<object class="NSTextFieldCell" key="NSCell" id="961478139">
+								<int key="NSCellFlags">68288064</int>
+								<int key="NSCellFlags2">272630784</int>
+								<string key="NSContents">Loan Duration (months)</string>
+								<reference key="NSSupport" ref="227377946"/>
+								<reference key="NSControlView" ref="79509684"/>
+								<reference key="NSBackgroundColor" ref="344940583"/>
+								<reference key="NSTextColor" ref="942182489"/>
+							</object>
+						</object>
+						<object class="NSTextField" id="767489727">
+							<reference key="NSNextResponder" ref="1006"/>
+							<int key="NSvFlags">268</int>
+							<string key="NSFrame">{{116, 219}, {167, 17}}</string>
+							<reference key="NSSuperview" ref="1006"/>
+							<bool key="NSEnabled">YES</bool>
+							<object class="NSTextFieldCell" key="NSCell" id="487292094">
+								<int key="NSCellFlags">68288064</int>
+								<int key="NSCellFlags2">272630784</int>
+								<string key="NSContents">Monthly Payment</string>
+								<reference key="NSSupport" ref="227377946"/>
+								<reference key="NSControlView" ref="767489727"/>
+								<reference key="NSBackgroundColor" ref="344940583"/>
+								<reference key="NSTextColor" ref="942182489"/>
+							</object>
+						</object>
+						<object class="NSTextField" id="583982648">
+							<reference key="NSNextResponder" ref="1006"/>
+							<int key="NSvFlags">268</int>
+							<string key="NSFrame">{{365, 360}, {118, 22}}</string>
+							<reference key="NSSuperview" ref="1006"/>
+							<bool key="NSEnabled">YES</bool>
+							<object class="NSTextFieldCell" key="NSCell" id="5436249">
+								<int key="NSCellFlags">-1804468671</int>
+								<int key="NSCellFlags2">-2076179456</int>
+								<string key="NSContents"/>
+								<reference key="NSSupport" ref="227377946"/>
+								<object class="NSNumberFormatter" key="NSFormatter" id="801243361">
+									<object class="NSMutableDictionary" key="NS.attributes">
+										<bool key="EncodedWithXMLCoder">YES</bool>
+										<object class="NSMutableArray" key="dict.sortedKeys">
+											<bool key="EncodedWithXMLCoder">YES</bool>
+											<string>allowsFloats</string>
+											<string>formatterBehavior</string>
+											<string>maximumFractionDigits</string>
+											<string>maximumIntegerDigits</string>
+											<string>minimumIntegerDigits</string>
+											<string>multiplier</string>
+											<string>numberStyle</string>
+										</object>
+										<object class="NSMutableArray" key="dict.values">
+											<bool key="EncodedWithXMLCoder">YES</bool>
+											<integer value="1" id="9"/>
+											<integer value="1040"/>
+											<integer value="4"/>
+											<integer value="10"/>
+											<integer value="0" id="8"/>
+											<real value="1.000000e+02"/>
+											<integer value="3"/>
+										</object>
+									</object>
+									<string key="NS.positiveformat">#,###.####%</string>
+									<string key="NS.negativeformat">#,###.####%</string>
+									<nil key="NS.positiveattrs"/>
+									<nil key="NS.negativeattrs"/>
+									<object class="NSAttributedString" key="NS.zero">
+										<nil key="NSString"/>
+									</object>
+									<object class="NSAttributedString" key="NS.nil">
+										<nil key="NSString"/>
+									</object>
+									<object class="NSAttributedString" key="NS.nan">
+										<string key="NSString">NaN</string>
+										<object class="NSDictionary" key="NSAttributes" id="932461654">
+											<bool key="EncodedWithXMLCoder">YES</bool>
+											<object class="NSArray" key="dict.sortedKeys">
+												<bool key="EncodedWithXMLCoder">YES</bool>
+											</object>
+											<object class="NSMutableArray" key="dict.values">
+												<bool key="EncodedWithXMLCoder">YES</bool>
+											</object>
+										</object>
+									</object>
+									<object class="NSDecimalNumberPlaceholder" key="NS.min" id="325159587">
+										<int key="NS.exponent">0</int>
+										<int key="NS.length">0</int>
+										<bool key="NS.negative">YES</bool>
+										<bool key="NS.compact">NO</bool>
+										<int key="NS.mantissa.bo">1</int>
+										<bytes key="NS.mantissa">AAAAAAAAAAAAAAAAAAAAAA</bytes>
+									</object>
+									<reference key="NS.max" ref="325159587"/>
+									<object class="NSDecimalNumberHandler" key="NS.rounding">
+										<int key="NS.roundingmode">3</int>
+										<bool key="NS.raise.overflow">YES</bool>
+										<bool key="NS.raise.underflow">YES</bool>
+										<bool key="NS.raise.dividebyzero">YES</bool>
+									</object>
+									<string key="NS.decimal">.</string>
+									<string key="NS.thousand">,</string>
+									<bool key="NS.hasthousands">YES</bool>
+									<bool key="NS.localized">YES</bool>
+									<bool key="NS.allowsfloats">YES</bool>
+								</object>
+								<reference key="NSControlView" ref="583982648"/>
+								<bool key="NSDrawsBackground">YES</bool>
+								<object class="NSColor" key="NSBackgroundColor" id="627117864">
+									<int key="NSColorSpace">6</int>
+									<string key="NSCatalogName">System</string>
+									<string key="NSColorName">textBackgroundColor</string>
+									<object class="NSColor" key="NSColor" id="72801970">
+										<int key="NSColorSpace">3</int>
+										<bytes key="NSWhite">MQA</bytes>
+									</object>
+								</object>
+								<object class="NSColor" key="NSTextColor" id="394575910">
+									<int key="NSColorSpace">6</int>
+									<string key="NSCatalogName">System</string>
+									<string key="NSColorName">textColor</string>
+									<reference key="NSColor" ref="752056265"/>
+								</object>
+							</object>
+						</object>
+						<object class="NSTextField" id="125608385">
+							<reference key="NSNextResponder" ref="1006"/>
+							<int key="NSvFlags">268</int>
+							<string key="NSFrame">{{365, 277}, {118, 22}}</string>
+							<reference key="NSSuperview" ref="1006"/>
+							<bool key="NSEnabled">YES</bool>
+							<object class="NSTextFieldCell" key="NSCell" id="1071273742">
+								<int key="NSCellFlags">-1804468671</int>
+								<int key="NSCellFlags2">-2076179456</int>
+								<string key="NSContents"/>
+								<reference key="NSSupport" ref="227377946"/>
+								<object class="NSNumberFormatter" key="NSFormatter" id="757491514">
+									<object class="NSMutableDictionary" key="NS.attributes">
+										<bool key="EncodedWithXMLCoder">YES</bool>
+										<object class="NSMutableArray" key="dict.sortedKeys">
+											<bool key="EncodedWithXMLCoder">YES</bool>
+											<string>allowsFloats</string>
+											<string>formatterBehavior</string>
+											<string>numberStyle</string>
+										</object>
+										<object class="NSMutableArray" key="dict.values">
+											<bool key="EncodedWithXMLCoder">YES</bool>
+											<boolean value="NO" id="6"/>
+											<integer value="1040"/>
+											<reference ref="8"/>
+										</object>
+									</object>
+									<string key="NS.positiveformat">#</string>
+									<string key="NS.negativeformat">#</string>
+									<nil key="NS.positiveattrs"/>
+									<nil key="NS.negativeattrs"/>
+									<object class="NSAttributedString" key="NS.zero">
+										<nil key="NSString"/>
+									</object>
+									<object class="NSAttributedString" key="NS.nil">
+										<nil key="NSString"/>
+									</object>
+									<object class="NSAttributedString" key="NS.nan">
+										<string key="NSString">NaN</string>
+										<reference key="NSAttributes" ref="932461654"/>
+									</object>
+									<reference key="NS.min" ref="325159587"/>
+									<reference key="NS.max" ref="325159587"/>
+									<object class="NSDecimalNumberHandler" key="NS.rounding">
+										<int key="NS.roundingmode">3</int>
+										<bool key="NS.raise.overflow">YES</bool>
+										<bool key="NS.raise.underflow">YES</bool>
+										<bool key="NS.raise.dividebyzero">YES</bool>
+									</object>
+									<string key="NS.decimal">.</string>
+									<string key="NS.thousand">,</string>
+									<bool key="NS.hasthousands">NO</bool>
+									<bool key="NS.localized">YES</bool>
+									<bool key="NS.allowsfloats">NO</bool>
+								</object>
+								<reference key="NSControlView" ref="125608385"/>
+								<bool key="NSDrawsBackground">YES</bool>
+								<reference key="NSBackgroundColor" ref="627117864"/>
+								<reference key="NSTextColor" ref="394575910"/>
+							</object>
+						</object>
+						<object class="NSTextField" id="644051649">
+							<reference key="NSNextResponder" ref="1006"/>
+							<int key="NSvFlags">268</int>
+							<string key="NSFrame">{{365, 189}, {118, 22}}</string>
+							<reference key="NSSuperview" ref="1006"/>
+							<bool key="NSEnabled">YES</bool>
+							<object class="NSTextFieldCell" key="NSCell" id="111648228">
+								<int key="NSCellFlags">-1804468671</int>
+								<int key="NSCellFlags2">-2076179456</int>
+								<string key="NSContents"/>
+								<reference key="NSSupport" ref="227377946"/>
+								<object class="NSNumberFormatter" key="NSFormatter" id="123140303">
+									<object class="NSMutableDictionary" key="NS.attributes">
+										<bool key="EncodedWithXMLCoder">YES</bool>
+										<object class="NSMutableArray" key="dict.sortedKeys">
+											<bool key="EncodedWithXMLCoder">YES</bool>
+											<string>allowsFloats</string>
+											<string>alwaysShowsDecimalSeparator</string>
+											<string>formatterBehavior</string>
+											<string>generatesDecimalNumbers</string>
+											<string>numberStyle</string>
+										</object>
+										<object class="NSMutableArray" key="dict.values">
+											<bool key="EncodedWithXMLCoder">YES</bool>
+											<boolean value="YES" id="5"/>
+											<reference ref="5"/>
+											<integer value="1040"/>
+											<reference ref="5"/>
+											<integer value="2" id="10"/>
+										</object>
+									</object>
+									<string type="base64-UTF8" key="NS.positiveformat">wqQjLCMjMC4wMA</string>
+									<string type="base64-UTF8" key="NS.negativeformat">KMKkIywjIzAuMDApA</string>
+									<nil key="NS.positiveattrs"/>
+									<nil key="NS.negativeattrs"/>
+									<object class="NSAttributedString" key="NS.zero">
+										<nil key="NSString"/>
+									</object>
+									<object class="NSAttributedString" key="NS.nil">
+										<nil key="NSString"/>
+									</object>
+									<object class="NSAttributedString" key="NS.nan">
+										<string key="NSString">NaN</string>
+										<reference key="NSAttributes" ref="932461654"/>
+									</object>
+									<reference key="NS.min" ref="325159587"/>
+									<reference key="NS.max" ref="325159587"/>
+									<object class="NSDecimalNumberHandler" key="NS.rounding">
+										<int key="NS.roundingmode">3</int>
+										<bool key="NS.raise.overflow">YES</bool>
+										<bool key="NS.raise.underflow">YES</bool>
+										<bool key="NS.raise.dividebyzero">YES</bool>
+									</object>
+									<string key="NS.decimal">.</string>
+									<string key="NS.thousand">,</string>
+									<bool key="NS.hasthousands">YES</bool>
+									<bool key="NS.localized">YES</bool>
+									<bool key="NS.allowsfloats">YES</bool>
+								</object>
+								<reference key="NSControlView" ref="644051649"/>
+								<bool key="NSDrawsBackground">YES</bool>
+								<reference key="NSBackgroundColor" ref="627117864"/>
+								<reference key="NSTextColor" ref="394575910"/>
+							</object>
+						</object>
+						<object class="NSTextField" id="809137054">
+							<reference key="NSNextResponder" ref="1006"/>
+							<int key="NSvFlags">268</int>
+							<string key="NSFrame">{{365, 441}, {118, 22}}</string>
+							<reference key="NSSuperview" ref="1006"/>
+							<bool key="NSEnabled">YES</bool>
+							<object class="NSTextFieldCell" key="NSCell" id="310865555">
+								<int key="NSCellFlags">-1804468671</int>
+								<int key="NSCellFlags2">-2076179456</int>
+								<string key="NSContents"/>
+								<reference key="NSSupport" ref="227377946"/>
+								<object class="NSNumberFormatter" key="NSFormatter" id="506223138">
+									<object class="NSMutableDictionary" key="NS.attributes">
+										<bool key="EncodedWithXMLCoder">YES</bool>
+										<object class="NSMutableArray" key="dict.sortedKeys">
+											<bool key="EncodedWithXMLCoder">YES</bool>
+											<string>allowsFloats</string>
+											<string>alwaysShowsDecimalSeparator</string>
+											<string>formatterBehavior</string>
+											<string>generatesDecimalNumbers</string>
+											<string>numberStyle</string>
+										</object>
+										<object class="NSMutableArray" key="dict.values">
+											<bool key="EncodedWithXMLCoder">YES</bool>
+											<reference ref="5"/>
+											<reference ref="5"/>
+											<integer value="1040"/>
+											<reference ref="5"/>
+											<reference ref="10"/>
+										</object>
+									</object>
+									<string type="base64-UTF8" key="NS.positiveformat">wqQjLCMjMC4wMA</string>
+									<string type="base64-UTF8" key="NS.negativeformat">KMKkIywjIzAuMDApA</string>
+									<nil key="NS.positiveattrs"/>
+									<nil key="NS.negativeattrs"/>
+									<object class="NSAttributedString" key="NS.zero">
+										<nil key="NSString"/>
+									</object>
+									<object class="NSAttributedString" key="NS.nil">
+										<nil key="NSString"/>
+									</object>
+									<object class="NSAttributedString" key="NS.nan">
+										<string key="NSString">NaN</string>
+										<reference key="NSAttributes" ref="932461654"/>
+									</object>
+									<reference key="NS.min" ref="325159587"/>
+									<reference key="NS.max" ref="325159587"/>
+									<object class="NSDecimalNumberHandler" key="NS.rounding">
+										<int key="NS.roundingmode">3</int>
+										<bool key="NS.raise.overflow">YES</bool>
+										<bool key="NS.raise.underflow">YES</bool>
+										<bool key="NS.raise.dividebyzero">YES</bool>
+									</object>
+									<string key="NS.decimal">.</string>
+									<string key="NS.thousand">,</string>
+									<bool key="NS.hasthousands">YES</bool>
+									<bool key="NS.localized">YES</bool>
+									<bool key="NS.allowsfloats">YES</bool>
+								</object>
+								<reference key="NSControlView" ref="809137054"/>
+								<bool key="NSDrawsBackground">YES</bool>
+								<reference key="NSBackgroundColor" ref="627117864"/>
+								<reference key="NSTextColor" ref="394575910"/>
+							</object>
+						</object>
+						<object class="NSTextField" id="229354320">
+							<reference key="NSNextResponder" ref="1006"/>
+							<int key="NSvFlags">268</int>
+							<string key="NSFrame">{{379, 471}, {89, 17}}</string>
+							<reference key="NSSuperview" ref="1006"/>
+							<bool key="NSEnabled">YES</bool>
+							<object class="NSTextFieldCell" key="NSCell" id="767188954">
+								<int key="NSCellFlags">68288064</int>
+								<int key="NSCellFlags2">272630784</int>
+								<string key="NSContents">Loan Amount</string>
+								<reference key="NSSupport" ref="227377946"/>
+								<reference key="NSControlView" ref="229354320"/>
+								<reference key="NSBackgroundColor" ref="344940583"/>
+								<reference key="NSTextColor" ref="942182489"/>
+							</object>
+						</object>
+						<object class="NSMatrix" id="628774051">
+							<reference key="NSNextResponder" ref="1006"/>
+							<int key="NSvFlags">268</int>
+							<string key="NSFrame">{{49, 37}, {137, 78}}</string>
+							<reference key="NSSuperview" ref="1006"/>
+							<bool key="NSEnabled">YES</bool>
+							<int key="NSNumRows">4</int>
+							<int key="NSNumCols">1</int>
+							<object class="NSMutableArray" key="NSCells">
+								<bool key="EncodedWithXMLCoder">YES</bool>
+								<object class="NSButtonCell" id="853217630">
+									<int key="NSCellFlags">-2080244224</int>
+									<int key="NSCellFlags2">0</int>
+									<string key="NSContents">Loan Amount</string>
+									<reference key="NSSupport" ref="227377946"/>
+									<reference key="NSControlView" ref="628774051"/>
+									<int key="NSButtonFlags">1211912703</int>
+									<int key="NSButtonFlags2">128</int>
+									<object class="NSButtonImageSource" key="NSAlternateImage" id="103585188">
+										<string key="NSImageName">NSRadioButton</string>
+									</object>
+									<string key="NSAlternateContents"/>
+									<string key="NSKeyEquivalent"/>
+									<int key="NSPeriodicDelay">200</int>
+									<int key="NSPeriodicInterval">25</int>
+								</object>
+								<object class="NSButtonCell" id="46258786">
+									<int key="NSCellFlags">67239424</int>
+									<int key="NSCellFlags2">0</int>
+									<string key="NSContents">Interest Rate</string>
+									<reference key="NSSupport" ref="227377946"/>
+									<reference key="NSControlView" ref="628774051"/>
+									<int key="NSButtonFlags">1211912703</int>
+									<int key="NSButtonFlags2">128</int>
+									<object class="NSImage" key="NSNormalImage">
+										<int key="NSImageFlags">549453824</int>
+										<string key="NSSize">{18, 18}</string>
+										<object class="NSMutableArray" key="NSReps">
+											<bool key="EncodedWithXMLCoder">YES</bool>
+											<object class="NSArray">
+												<bool key="EncodedWithXMLCoder">YES</bool>
+												<reference ref="8"/>
+												<object class="NSBitmapImageRep">
+													<object class="NSData" key="NSTIFFRepresentation">
+														<bytes key="NS.bytes">TU0AKgAABRgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAwAAAAMAAAADAAAAAwAAAAAAAAAA
+AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAwAAADwRERGLJycnySsrK/A1NTXw
+IyMjyRwcHIsJCQk8AAAAAwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFFRUVdVBQUOCoqKj/
+29vb//n5+f/6+vr/2tra/6qqqv9UVFTgHx8fdQAAAAUAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAUZGRl5
+dXV198PDw//8/Pz////////////////////////////U1NT/fHx89yUlJXkAAAAFAAAAAAAAAAAAAAAA
+AAAAAxEREUZqamrmtbW1/+3t7f/+/v7//v7+//7+/v/9/f3//f39//39/f/39/f/xMTE/3d3d+YZGRlG
+AAAAAwAAAAAAAAAAAAAACkJCQqGtra3/xsbG/+vr6//y8vL/9fX1//X19f/z8/P/9fX1//Ly8v/u7u7/
+0tLS/6+vr/9KSkqhAAAACgAAAAAAAAAAAAAAF3h4eN2/v7//z8/P/93d3f/q6ur/7+/v/+/v7//w8PD/
+7e3t/+3t7f/i4uL/zs7O/8XFxf98fHzdAAAAFwAAAAAAAAADAAAAJKSkpPjOzs7/2dnZ/+Dg4P/i4uL/
+5eXl/+bm5v/n5+f/5eXl/+Li4v/e3t7/2tra/9DQ0P+srKz4AAAAJAAAAAMAAAADAAAALrCwsPrW1tb/
+3t7e/+Tk5P/p6en/6+vr/+zs7P/p6en/6+vr/+fn5//k5OT/4ODg/9nZ2f+zs7P6AAAALgAAAAMAAAAD
+AAAALp2dnezg4OD/5eXl/+rq6v/u7u7/8PDw//Dw8P/x8fH/8PDw/+7u7v/q6ur/5ubm/+Hh4f+ZmZns
+AAAALgAAAAMAAAADAAAAJG5ubs/l5eX/6enp/+/v7//y8vL/9vb2//r6+v/5+fn/9/f3//b29v/x8fH/
+6+vr/+Tk5P9ra2vPAAAAJAAAAAMAAAAAAAAAFy4uLpPCwsL67Ozs//Pz8//5+fn//v7+//7+/v/+/v7/
+/v7+//v7+//19fX/8PDw/8LCwvosLCyTAAAAFwAAAAAAAAAAAAAACgAAAENfX1/S5OTk/vn5+f/+/v7/
+///////////////////////////8/Pz/5ubm/l9fX9IAAABDAAAACgAAAAAAAAAAAAAAAwAAABcAAABl
+YmJi3NLS0v3////////////////////////////////V1dX9ZGRk3AAAAGUAAAAXAAAAAwAAAAAAAAAA
+AAAAAAAAAAUAAAAfAAAAZTMzM8KAgIDwv7+//O3t7f/t7e3/v7+//ICAgPAzMzPCAAAAZQAAAB8AAAAF
+AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFAAAAFwAAAEMAAAB3AAAAnwAAALMAAACzAAAAnwAAAHcAAABD
+AAAAFwAAAAUAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAwAAAAoAAAAXAAAAJAAAAC4AAAAu
+AAAAJAAAABcAAAAKAAAAAwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+AAAAAwAAAAMAAAADAAAAAwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADgEAAAMAAAABABIAAAEB
+AAMAAAABABIAAAECAAMAAAAEAAAFxgEDAAMAAAABAAEAAAEGAAMAAAABAAIAAAERAAQAAAABAAAACAES
+AAMAAAABAAEAAAEVAAMAAAABAAQAAAEWAAMAAAABBxwAAAEXAAQAAAABAAAFEAEcAAMAAAABAAEAAAFS
+AAMAAAABAAEAAAFTAAMAAAAEAAAFzodzAAcAAAwYAAAF1gAAAAAACAAIAAgACAABAAEAAQABAAAMGGFw
+cGwCAAAAbW50clJHQiBYWVogB9YABAADABMALAASYWNzcEFQUEwAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+AAAAAPbWAAEAAAAA0y1hcHBs2U706y3Sst1fqit5+wYbUQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+AAAAAAAOclhZWgAAASwAAAAUZ1hZWgAAAUAAAAAUYlhZWgAAAVQAAAAUd3RwdAAAAWgAAAAUY2hhZAAA
+AXwAAAAsclRSQwAAAagAAAAOZ1RSQwAAAbgAAAAOYlRSQwAAAcgAAAAOdmNndAAAAdgAAAMSbmRpbgAA
+BOwAAAY+ZGVzYwAACywAAABkZHNjbQAAC5AAAAAubW1vZAAAC8AAAAAoY3BydAAAC+gAAAAtWFlaIAAA
+AAAAAF1KAAA0kQAACCVYWVogAAAAAAAAdCAAALRgAAAjPVhZWiAAAAAAAAAlbAAAFyoAAKfDWFlaIAAA
+AAAAAPNSAAEAAAABFs9zZjMyAAAAAAABDEIAAAXe///zJgAAB5IAAP2R///7ov///aMAAAPcAADAbGN1
+cnYAAAAAAAAAAQHNAABjdXJ2AAAAAAAAAAEBzQAAY3VydgAAAAAAAAABAc0AAHZjZ3QAAAAAAAAAAAAD
+AQAAAQACBAUGBwkKCw0ODxASExQWFxgaGxweHyAiIyQmJygpKywtLzAxMjM1Njc4OTs8PT5AQUJDREZH
+SElKS0xOT1BRUlNUVVZXWFlaW1xdXl9hYmNkZWZnaGlqa2xtbm9wcXJzdHV2d3h5ent8fX5/gIGCg4SF
+hoeIiYqLjI2Oj5CRkpOUlZaXmJmam5ydnZ6foKGio6SlpqanqKmqq6ytra6vsLGysrO0tba3uLi5uru8
+vL2+v8DBwcLDxMXGxsfIycrKy8zNzs7P0NHS0tPU1dbW19jZ2drb3Nzd3t/g4eLi4+Tl5ufo6enq6+zt
+7u/w8fHy8/T19vf4+fr7/P3+/v8AAgMEBQYHCAkKCwwNDg8QERITFBUWFxgZGhscHR8gISIjJCUnKCkq
+Ky0uLzAxMzQ1Njc4OTo7PD0/QEFCQ0RFRkdISUpLTE1OT1BRUlNUVVZXWFlaWltcXV5fYGFiY2RlZmdo
+aWprbG1ub3BxcnN0dXZ3d3h5ent8fH1+f4CBgoKDhIWGh4iIiYqLjI2Oj5CRkpOUlJWWl5iZmpucnZ2e
+n6ChoqOkpaamp6ipqqusra6vsLCxsrO0tba3uLm5uru8vb6/wMHCw8TFx8jJysvMzc7P0NDR0tPU1dbX
+2Nna29ze3+Dh4uPk5ebn6err7O3u7/Hy8/T19vf5+vv8/f7/AAIDAwQFBgcICQoKCwwNDg8QERITFBUW
+FxgZGhscHR4fICEiIyQlJicoKSorLC0uLzAxMjM0NTY3ODg5Ojs8PT4+P0BBQkNDREVGR0hJSUpLTE1O
+Tk9QUVJSU1RVVVZXWFhZWltbXF1eXl9gYWFiY2RkZWZnZ2hpaWprbGxtbm5vcHFxcnNzdHV1dnd4eHl6
+ent8fH1+fn+AgYGCg4SEhYaHiImJiouMjY6Oj5CRkpOTlJWWl5iZmZqbnJ2en6ChoqOkpaanqKmqq6yt
+rq+xsrO0tba3uLq7vL2+wMHDxMbHycrMzs/R0tTW19nb3d7g4uTm6Ors7vDy9Pb4+vz+/wAAbmRpbgAA
+AAAAAAY2AACXGgAAVjoAAFPKAACJ3gAAJ8IAABaoAABQDQAAVDkAAiuFAAIZmQABeFEAAwEAAAIAAAAA
+AAEABgANABcAIwAxAEAAUgBlAHsAkwCrAMUA4gD/AR8BPwFhAYUBqgHQAfgCIAJLAncCpQLSAwIDMwNl
+A5gDzgQFBD0EdQSvBOsFKQVnBacF6AYqBm4GtQb8B0UHkgfkCDkIkAjnCT4JmAn0ClAKrQsLC2sLygwq
+DIwM8Q1XDcAOKA6SDv4PbA/bEE0QxBE7EbQSMRKwEzITuRREFNAVYBXxFocXHhfAGGIZBBmsGlQa+RuU
+HC4czh1yHhQeux9jIA0gvCFoIhkizyOJJEEk+SW6JnknOygFKMspkypiKzIsASzXLawuhy9gMD4xGzH8
+MtszvzSgNYY2cjdcOEw5OTorOxs8CD0EPfU+6z/nQOFB2ELUQ9VE00XcRttH5EjxSgBLCUwdTTFOUE9v
+UI9Rt1LdVAVVNlZsV6VY4FohW21ct135X09goGH0Y0tkqGYFZ19oxGova5ptCG54b/BxbnLsdG119Xd/
+eQh6knwqfcV/W4D4gpSEO4Xih4CJKorYjIqOOY/jkZuTWJUOlsyYiZpSnB6d4Z+soX+jWqUvpxOo+6rj
+rMuuwLC4sra0rra0uL+60LzfvwDBHcLdxLXGhchYyi7MCs3lz7rRmtOA1WPXR9kq2xPc/97s4M/iveSn
+5o3obupT7ELuLPAM8fLz0PW396H5f/tZ/T3//wAAAAEAAwALABYAJQA3AE0AZQCBAJ8AwQDlAQsBNQFh
+AZABwQH1AisCZAKfAtwDHANfA6MD6gQ0BH8EzQT1BR0FcAXEBhsGdAbPBy0HXAeMB+4IUgi4CSAJVAmK
+CfYKZArVC0cLgQu8DDIMqw0mDaIOIQ6hDyQPqRAvELgQ/RFDEc8SXRLuE4AUFRSrFUMV3RZ5FxcXthhY
+GPwZoRpIGvEbnBxJHPgdqB5bHw8fxSB9ITch8iKwJDAk8yW3Jn4nRigQKNwpqSp5K0osHCzxLccuoC95
+MFUxMzISMvMz1TS5NaA2hzdxOFw5STo4Oyg8Gj4DPvs/9EDuQepD6ETpRexG8Uf3SP9LFEwhTTBOQE9S
+UGZSklOrVMVV4Vb/WB5ZP1phW4Vcq13SXvthUmJ/Y69k4GYSZ0dofGm0au1tZG6ib+FxInJlc6l073Y2
+d396FXtjfLJ+A39VgKmB/4NWhK+GCYjCiiGLgYzjjkePrJESknuT5Ja8mCuZm5sMnH+d9J9qoOGiWqPV
+pVGmz6eOqE6pzqtRrNSuWq/gsWmy8rR+tgu5Kbq6vE294b93wQ7Cp8RBxd3He8kZyrrLisxbzf/Po9FK
+0vHUm9ZF1/HZn9tO3Cbc/96x4GTiGePQ5YjnQegf6Pzquex27jbv9/G583z0X/VC9wj40Pqa/GX+Mf//
+AAAAAQADAAsAJQA3AE0AZQCBAJ8AwQELATUBYQGQAcEB9QIrAmQCnwLcAxwDXwOjA+oENAR/BM0FHQVw
+BcQGGwZ0Bs8HLQeMB+4IUgi4CSAJign2CmQK1QtHC7wMMgyrDSYNog4hDqEPJA+pEC8QuBFDEl0S7hOA
+FBUUqxVDFnkXFxe2GFgY/BpIGvEbnBxJHPgdqB8PH8UgfSE3IfIjbyQwJPMltydGKBAo3Cp5K0osHC3H
+LqAveTEzMhIy8zS5NaA2hzhcOUk6ODwaPQ4+Az/0QO5C6EPoROlG8Uf3SglLFEwhTkBPUlF7UpJUxVXh
+Vv9ZP1phXKtd0mAlYVJjr2TgZhJofGm0au1tZG6ib+FxInJldO92Nnd/eMl6FXyyfgN/VYCpgf+Er4YJ
+h2WIwoohi4GOR4+skRKSe5PklVCWvJgrmZubDJx/nfSfaqDholqj1aVRps+oTqnOq1Gs1K2Xrlqv4LFp
+svK0frYLt5m5Kbnxurq8Tb3hv3fBDsHawqfEQcUPxd3He8hKyRnKusuKzFvN/87Rz6PQdtFK0vHTxtSb
+1kXXG9fx2MjZn9tO3Cbc/93Y3rHfiuBk4hni9ePQ5KzliOZk50HoH+j86drqueuX7HbtVu427xbv9/DX
+8bnymvN89F/1QvYl9wj37PjQ+bX6mvt//GX9S/4x//8AAGRlc2MAAAAAAAAACkNvbG9yIExDRAAAAAAA
+AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+AAAAAAAAAAAAAAAAAABtbHVjAAAAAAAAAAEAAAAMZW5VUwAAABIAAAAcAEMAbwBsAG8AcgAgAEwAQwBE
+AABtbW9kAAAAAAAABhAAAJxOAAAAAL5zkQAAAAAAAAAAAAAAAAAAAAAAdGV4dAAAAABDb3B5cmlnaHQg
+QXBwbGUgQ29tcHV0ZXIsIEluYy4sIDIwMDUAAAAAA</bytes>
+													</object>
+												</object>
+											</object>
+										</object>
+										<object class="NSColor" key="NSColor" id="743532525">
+											<int key="NSColorSpace">3</int>
+											<bytes key="NSWhite">MCAwAA</bytes>
+										</object>
+									</object>
+									<reference key="NSAlternateImage" ref="103585188"/>
+									<int key="NSPeriodicDelay">400</int>
+									<int key="NSPeriodicInterval">75</int>
+								</object>
+								<object class="NSButtonCell" id="149842975">
+									<int key="NSCellFlags">67239424</int>
+									<int key="NSCellFlags2">0</int>
+									<string key="NSContents">Loan Duration</string>
+									<reference key="NSSupport" ref="227377946"/>
+									<reference key="NSControlView" ref="628774051"/>
+									<int key="NSButtonFlags">1211912703</int>
+									<int key="NSButtonFlags2">128</int>
+									<object class="NSImage" key="NSNormalImage" id="532858645">
+										<int key="NSImageFlags">549453824</int>
+										<string key="NSSize">{18, 18}</string>
+										<object class="NSMutableArray" key="NSReps">
+											<bool key="EncodedWithXMLCoder">YES</bool>
+											<object class="NSArray">
+												<bool key="EncodedWithXMLCoder">YES</bool>
+												<reference ref="8"/>
+												<object class="NSBitmapImageRep">
+													<object class="NSData" key="NSTIFFRepresentation">
+														<bytes key="NS.bytes">TU0AKgAABRgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAwAAAAMAAAADAAAAAwAAAAAAAAAA
+AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAwAAADwRERGLJycnySsrK/A1NTXw
+IyMjyRwcHIsJCQk8AAAAAwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFFRUVdVBQUOCoqKj/
+29vb//n5+f/6+vr/2tra/6qqqv9UVFTgHx8fdQAAAAUAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAUZGRl5
+dXV198PDw//8/Pz////////////////////////////U1NT/fHx89yUlJXkAAAAFAAAAAAAAAAAAAAAA
+AAAAAxEREUZqamrmtbW1/+3t7f/+/v7//v7+//7+/v/9/f3//f39//39/f/39/f/xMTE/3d3d+YZGRlG
+AAAAAwAAAAAAAAAAAAAACkJCQqGtra3/xsbG/+vr6//y8vL/9fX1//X19f/z8/P/9fX1//Ly8v/u7u7/
+0tLS/6+vr/9KSkqhAAAACgAAAAAAAAAAAAAAF3h4eN2/v7//z8/P/93d3f/q6ur/7+/v/+/v7//w8PD/
+7e3t/+3t7f/i4uL/zs7O/8XFxf98fHzdAAAAFwAAAAAAAAADAAAAJKSkpPjOzs7/2dnZ/+Dg4P/i4uL/
+5eXl/+bm5v/n5+f/5eXl/+Li4v/e3t7/2tra/9DQ0P+srKz4AAAAJAAAAAMAAAADAAAALrCwsPrW1tb/
+3t7e/+Tk5P/p6en/6+vr/+zs7P/p6en/6+vr/+fn5//k5OT/4ODg/9nZ2f+zs7P6AAAALgAAAAMAAAAD
+AAAALp2dnezg4OD/5eXl/+rq6v/u7u7/8PDw//Dw8P/x8fH/8PDw/+7u7v/q6ur/5ubm/+Hh4f+ZmZns
+AAAALgAAAAMAAAADAAAAJG5ubs/l5eX/6enp/+/v7//y8vL/9vb2//r6+v/5+fn/9/f3//b29v/x8fH/
+6+vr/+Tk5P9ra2vPAAAAJAAAAAMAAAAAAAAAFy4uLpPCwsL67Ozs//Pz8//5+fn//v7+//7+/v/+/v7/
+/v7+//v7+//19fX/8PDw/8LCwvosLCyTAAAAFwAAAAAAAAAAAAAACgAAAENfX1/S5OTk/vn5+f/+/v7/
+///////////////////////////8/Pz/5ubm/l9fX9IAAABDAAAACgAAAAAAAAAAAAAAAwAAABcAAABl
+YmJi3NLS0v3////////////////////////////////V1dX9ZGRk3AAAAGUAAAAXAAAAAwAAAAAAAAAA
+AAAAAAAAAAUAAAAfAAAAZTMzM8KAgIDwv7+//O3t7f/t7e3/v7+//ICAgPAzMzPCAAAAZQAAAB8AAAAF
+AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFAAAAFwAAAEMAAAB3AAAAnwAAALMAAACzAAAAnwAAAHcAAABD
+AAAAFwAAAAUAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAwAAAAoAAAAXAAAAJAAAAC4AAAAu
+AAAAJAAAABcAAAAKAAAAAwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+AAAAAwAAAAMAAAADAAAAAwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADgEAAAMAAAABABIAAAEB
+AAMAAAABABIAAAECAAMAAAAEAAAFxgEDAAMAAAABAAEAAAEGAAMAAAABAAIAAAERAAQAAAABAAAACAES
+AAMAAAABAAEAAAEVAAMAAAABAAQAAAEWAAMAAAABBxwAAAEXAAQAAAABAAAFEAEcAAMAAAABAAEAAAFS
+AAMAAAABAAEAAAFTAAMAAAAEAAAFzodzAAcAABEcAAAF1gAAAAAACAAIAAgACAABAAEAAQABAAARHGFw
+cGwCAAAAbW50clJHQiBYWVogB9kACAAIAAoAHwAdYWNzcEFQUEwAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+AAAAAPbWAAEAAAAA0y1hcHBsoS0Bh+QUuNDqzJl2rWVX8gAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+AAAAAAAOclhZWgAAASwAAAAUZ1hZWgAAAUAAAAAUYlhZWgAAAVQAAAAUd3RwdAAAAWgAAAAUY2hhZAAA
+AXwAAAAsclRSQwAAAagAAAAOZ1RSQwAAAbgAAAAOYlRSQwAAAcgAAAAOdmNndAAAAdgAAAYSbmRpbgAA
+B+wAAAY+ZGVzYwAADiwAAABkZHNjbQAADpAAAAI+bW1vZAAAENAAAAAoY3BydAAAEPgAAAAkWFlaIAAA
+AAAAAG6vAAA5TwAAAX1YWVogAAAAAAAAXt0AALO9AAAH11hZWiAAAAAAAAApSgAAEw8AAMnQWFlaIAAA
+AAAAAPNSAAEAAAABFs9zZjMyAAAAAAABDEIAAAXe///zJgAAB5IAAP2R///7ov///aMAAAPcAADAbGN1
+cnYAAAAAAAAAAQHNAABjdXJ2AAAAAAAAAAEBzQAAY3VydgAAAAAAAAABAc0AAHZjZ3QAAAAAAAAAAAAD
+AQAAAgAAADwA0gFbAe4CiQM6A/8E1gXDBsYH2Aj2CiYLXgyrDjYP1xF6Ex4UxRZyGCEZ3BuUHVEfFiDW
+Ip0kZCYuJ9UpeSsZLK4uQS/EMUMyszQaNXg2zDgXOVw6mzvUPQQ+MD9aQIhBtELhRA5FPEZnR5NIwEnr
+SxZMQE1qTohPplDEUd9S+VQTVSpWQFdSWGNZc1p/W4tcll2cXpZfjWCCYXViaGNZZEhlNGYgZwpn9Gjc
+acNqqmuQbHBtUW4wbw9v7nDMcapyh3NidD51GXXzds13qHiBeVd6LnsGe+F8wH2ifol/doBqgWSCZINq
+hHSFhIaXh7aI1on1ixSMM41Rjm2PiZCikbyS1JPslQOWGpcvmEGZU5pkm3WchZ2UnqOfsaC/ocyi2aPm
+pPKl/qcJqBOpHqorqzusUK1qroyvtbDpsiWzarS0tgi3YLi9udC647v0vQK+DL8SwBPBDcICwvDD2cS9
+xZzGd8dOyCfJBsnrys7Lq8yBzVDOF87Xz4rQN9Dg0YDSIdLB037UQNUB1cLWhNdG2AfYydmL2k3bD9vR
+3JPdVd4W3tbfluBX4Rnh2+Kg42bkLuT55cbmledn6DvpEOnn6qnra+wu7O/tsO5w7zDv7/Ct8WvyKfLm
+86L0X/Ub9df2k/dP+Av4x/mD+j/6+/u1/G79J/3e/pT/Sv//AAAANAC2ATsBuAJGAuQDlARXBSoGEQcL
+CAsJGwovC1wMwA41D6oRKBKkFCgVsBc4GMkaWRvuHYkfHyC9Ilcj2CVYJs8oRCmuKxUscC3CLw4wTTGG
+Mrcz5DULNi83OzhIOVM6XjtqPHQ9fT6GP45AlkGdQqVDq0SwRbRGtUeySLBJrUqpS6RMn02XTo9Ph1B/
+UXRSa1NgVFZVRFYzVyJYEFj9Wela1Fu+XKZdjl5zX1lgPWEgYf9i1mOqZH1lT2YhZvNnxGiUaWNqMmsA
+a81sm21pbjVu/m/HcI9xWHIgcuhzr3R3dT12A3bKd5B4VnkceeF6pntsfDV9AH3PfqJ/eoBZgT6CKYMa
+hA+FCYYHhwiIDYkTihiLHYwijSaOKo8ukDGRM5I1kzaUOJU4ljiXNpg0mTKaMZsxnDKdNp47n0SgT6Fc
+om2jgKSUpaumyKflqQOqH6s7rFetcq6Nr6iwwbHbsvS0DbUltj23VLhquX+6lLunvLi9xr7Qv9XA18HV
+ws7Dw8S2xaTGjMdzyFvJQsopyxDL98zezcTOq8+R0HfRXdJD0yjUDNTv1dPWtteZ2H3ZYdpG2yvcENz1
+3dzew9+q4JzhqOK548TkyeXG5r7nsOie6YjqcetY7D/tJ+4Q7vrv5vDf8gLzJvRJ9Wv2i/et+ND59fse
+/E79gv69//8AAAAiAHcA9gFXAccCQwLJA18EBgS4BXkGRQcVB+8I2gnyCxQMOw1nDpUPxBD6EjATahSo
+FekXLRh0GbsbAhw2HWoemx/JIPMiFiMzJEklVyZgJ2QoZClfKlcrSywvLQ8t8C7RL7EwjzFtMkszJzQB
+NNs1tDaNN2Y4PzkQOeI6szuEPFU9Jz34Psg/mUBqQTxCDkLgQ7NEhUVURiNG8kfBSI9JXUoqSvZLwUyM
+TVZOIE7pT7NQe1FBUgZSylOPVFNVFlXYVppXXFgcWN1ZnVpdWxxb2lyWXVFeC17EX31gNWDrYaJiWGMM
+Y8Bkc2UlZdhmiWc5Z+hol2lFafNqomtQa/xsqW1XbgNusG9ccAlwtHFfcghysXNbdAR0rHVVdfx2pHdL
+d/J4mXk/eeZ6jHsxe9h8gH0rfdt+jX9IgAiAz4GcgnCDS4QrhQ+F+Ibmh9eIx4m4iqeLl4yGjXWOY49R
+kD6RLJIZkwaT8pTalcGWp5eLmHCZVJo6myGcC5z4neie3J/ToM6h0KLxpBelPqZkp4qor6nUqvmsHa1B
+rmSviLCrsc6y8LQQtTC2ULdvuI+5sLrRu/K9FL43v1vAgMGmwszD9sUtxmvHsMkAylrLvM0tzqjQMNHB
+017VA9ay2GjaJNvm3a7fguGP4+TmWejj65DuVfEu9Bn3DfoE/QD//wAAbmRpbgAAAAAAAAY2AACl4wAA
+VqEAAFFbAACnKwAAJqUAABDlAABQDQAAVDkAAkKPAAHZmQABR64AAwEAAAIAAAANACcARgBmAIcAqADJ
+AOsBDgExAVUBegGdAbwB2wH8Ah0CPwJiAoYCqgLPAvQDGwNBA2gDkAO5A+IECwQ1BGAEjAS4BOQFEgU/
+BW4FoQXVBgoGQQZ4BrIG7AcoB2cHpwfpCC4IdQi/CQsJWgmsCgEKWAqyCw4LbgvSDDgMoA0IDXIN3g5K
+DrkPKA+aEA0QgRD3EW8R6BJjEt8TYhPnFG0U9hWBFg4WnRcvF8MYWxj1GZEaMRrTG3ccHRzQHYceQh8A
+H8EghSFNIhki6CO7JJElaiZGJyUoDCj1KeIq0ivELLotsy6wL68wsjG4MsAzyzTeNfE3BDgVOSM6LTsx
+PDA9Kj4gPxJAAkDvQdtCv0OiRIhFb0ZYR0JIL0keSg9LA0v4TPBN6k7lT+JQ4VHkUutT81T9VglXF1gn
+WTlaTVtjXHtdlV6wX85g7WIOYzNkWWV/ZqNnxWjjaf1rEmwhbSpuLm8tcClxInIWcwlz+nTpdhp3TXiE
+eb96/nxFfZN+64BNgbuDNIS5hkmH44mHiyGMro5Aj+CRkZNYlT2XSZl3m8WeG6AOogKj+aXyp+6p7Kvs
+re+v9bH9tAi2G7gvukS8Wb5pwHbCfsSAxn3IdspszGDOi9C40urVIddd2Z/b5t4x4IHi1eUr54jp5+xH
+7qrxEPN79e34Zvrn/XD//wAAAA8ALgBRAHUAmgC/AOQBCwEyAVsBhAGpAcsB7wIUAjoCYAKIArAC2QMD
+Ay0DWQOFA7ED3wQNBDwEawSbBM0E/gUxBWQFnAXVBg8GTAaJBsgHCgdNB5IH2gglCHIIwgkWCWwJxgoj
+CoIK5QtKC7oMKwyfDRUNjA4GDoIPAA+BEAMQiBEOEZcSIhKvE0AT1RRtFQYVohZBFuIXhhgtGNYZgRow
+GuAbkxxIHQQdwh6DH0YgDCDWIaIicyNGJB4k+CXWJrcnoCiXKZEqjiuOLJItmi6mL7UwyDHeMvc0FTU6
+NmM3jji9Oe87JTxfPZs+20AeQWRCr0P7RUVGi0fLSQVKN0tiTIZNpk7BT9pQ8FIEUxZUKlVAVllXc1iP
+Wa5azlvxXRZePV9mYJFhvmLuZCNlWGaPZ8Zo/Wo0a2lsnm3RbwJwMnFgco5zu3Todg93N3hgeYt6uHvn
+fRd+SX99gLKB6oMjhF2FmobYiBeJWYqei+SNLY54j8aRGJJvk8yVMJabmA6ZiZsMnJWeJ5/HoWmjDKSy
+plqoBKmwq1+tEK7DsHiyL7Potae3abktuvK8ur6CwEzCF8PjxbDHfMlKyxnM0M5Vz+PRetMe1M7Wi9hT
+2ibcAd3i38bhq+OP5XLnU+kb6p/sJ+2x7z7wzvJf8+/1gPcP+Jn6Hvuf/Rr+j///AAAAFwBBAHAAnwDP
+AP8BMgFmAZkBxQHzAiICUgKEArcC7AMhA1gDkAPJBAMEPgR6BLcE9QU1BXYFvQYFBk8GmwbqBzsHkAfo
+CEQIpAkICXAJ3ApMCsALNwu6DEIMzA1ZDeoOfg8VD7AQTxDxEZYSPhLpE50UUxUNFcoWiRdMGBIY2hml
+GnIbQRwTHOsdxh6kH4YgayFUIkEjMiQnJR8mGycaKCApKyo5K0ssYS18LpovvTDkMg4zPDRyNa427zg1
+OYE60jwoPYQ+5kBMQbdDK0SkRiFHo0kpSrVMRE3YT3BRDFKwVFtWCVe9WXZbNFz4XsBgjWJeZDZmDGfZ
+aZprSWzpbnlv/HF0cuV0UHWzdxF4cnnUezp8oX4Lf3iA54JYg8yFQoa6iDSJtos9jMmOWY/rkX6TEZSi
+li+XuZk+mr+cPJ22nwWgTKGVot+kKqV3psWoFalmqrqsDq1krrywFbFwssu0KLWKtu24Ubm3ux68hr3u
+v1fAwcIrw5XE/8Zqx9TJQMqrzBbNc87K0BvRaNKs0+rVI9ZX14LYqNnK2uXb/N0Q3h/fK+A14TriPuNA
+5EDlPuY65zfoMekq6iLrDuvp7Lntd+417uzvpfBZ8QrxvPJm8xDzuPRc9QD1ovZC9uL3f/gc+Ln5Vfnw
++oz7J/vC/F78+P2T/i/+yf9k//8AAGRlc2MAAAAAAAAACkNvbG9yIExDRAAAAAAAAAAAAAAAAAAAAAAA
+AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+AABtbHVjAAAAAAAAABIAAAAMbmJOTwAAABIAAADocHRQVAAAABYAAAD6c3ZTRQAAABAAAAEQZmlGSQAA
+ABAAAAEgZGFESwAAABwAAAEwemhDTgAAAAwAAAFMZnJGUgAAABIAAAFYamFKUAAAAA4AAAFqZW5VUwAA
+ABIAAAF4cGxQTAAAABIAAAGKcHRCUgAAABgAAAGcZXNFUwAAABIAAAG0emhUVwAAAA4AAAHGcnVSVQAA
+ACQAAAHUa29LUgAAAAwAAAH4ZGVERQAAABAAAAIEbmxOTAAAABYAAAIUaXRJVAAAABQAAAIqAEYAYQBy
+AGcAZQAtAEwAQwBEAEwAQwBEACAAYQAgAEMAbwByAGUAcwBGAOQAcgBnAC0ATABDAEQAVgDkAHIAaQAt
+AEwAQwBEAEwAQwBEAC0AZgBhAHIAdgBlAHMAawDmAHIAbV9pgnIAIABMAEMARADJAGMAcgBhAG4AIABM
+AEMARDCrMOkw/AAgAEwAQwBEAEMAbwBsAG8AcgAgAEwAQwBEAEsAbwBsAG8AcgAgAEwAQwBEAEwAQwBE
+ACAAQwBvAGwAbwByAGkAZABvAEwAQwBEACAAYwBvAGwAbwByX2mCcm2yZnaYb3k6VmgEJgQyBDUEQgQ9
+BD4EOQAgBBYEGgAtBDQEOARBBD8EOwQ1BDnO7LfsACAATABDAEQARgBhAHIAYgAtAEwAQwBEAEsAbABl
+AHUAcgBlAG4ALQBMAEMARABMAEMARAAgAGMAbwBsAG8AcgBpAABtbW9kAAAAAAAABhAAAJyjAAAAAMV4
+fYAAAAAAAAAAAAAAAAAAAAAAdGV4dAAAAABDb3B5cmlnaHQgQXBwbGUsIEluYy4sIDIwMDkAA</bytes>
+													</object>
+												</object>
+											</object>
+										</object>
+										<reference key="NSColor" ref="743532525"/>
+									</object>
+									<reference key="NSAlternateImage" ref="103585188"/>
+									<int key="NSPeriodicDelay">400</int>
+									<int key="NSPeriodicInterval">75</int>
+								</object>
+								<object class="NSButtonCell" id="322221180">
+									<int key="NSCellFlags">67239424</int>
+									<int key="NSCellFlags2">0</int>
+									<string key="NSContents">Monthly Payment</string>
+									<reference key="NSSupport" ref="227377946"/>
+									<int key="NSTag">1</int>
+									<reference key="NSControlView" ref="628774051"/>
+									<int key="NSButtonFlags">1211912703</int>
+									<int key="NSButtonFlags2">128</int>
+									<reference key="NSNormalImage" ref="532858645"/>
+									<reference key="NSAlternateImage" ref="103585188"/>
+									<int key="NSPeriodicDelay">400</int>
+									<int key="NSPeriodicInterval">75</int>
+								</object>
+							</object>
+							<string key="NSCellSize">{137, 18}</string>
+							<string key="NSIntercellSpacing">{4, 2}</string>
+							<int key="NSMatrixFlags">1151868928</int>
+							<string key="NSCellClass">NSActionCell</string>
+							<object class="NSButtonCell" key="NSProtoCell" id="735574461">
+								<int key="NSCellFlags">67239424</int>
+								<int key="NSCellFlags2">0</int>
+								<string key="NSContents">Radio</string>
+								<reference key="NSSupport" ref="227377946"/>
+								<int key="NSButtonFlags">1211912703</int>
+								<int key="NSButtonFlags2">128</int>
+								<object class="NSImage" key="NSNormalImage">
+									<int key="NSImageFlags">549453824</int>
+									<string key="NSSize">{18, 18}</string>
+									<object class="NSMutableArray" key="NSReps">
+										<bool key="EncodedWithXMLCoder">YES</bool>
+										<object class="NSArray">
+											<bool key="EncodedWithXMLCoder">YES</bool>
+											<reference ref="8"/>
+											<object class="NSBitmapImageRep">
+												<object class="NSData" key="NSTIFFRepresentation">
+													<bytes key="NS.bytes">TU0AKgAABRgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAwAAAAMAAAADAAAAAwAAAAAAAAAA
+AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAwAAADwRERGLJycnySsrK/A1NTXw
+IyMjyRwcHIsJCQk8AAAAAwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFFRUVdVBQUOCoqKj/
+29vb//n5+f/6+vr/2tra/6qqqv9UVFTgHx8fdQAAAAUAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAUZGRl5
+dXV198PDw//8/Pz////////////////////////////U1NT/fHx89yUlJXkAAAAFAAAAAAAAAAAAAAAA
+AAAAAxEREUZqamrmtbW1/+3t7f/+/v7//v7+//7+/v/9/f3//f39//39/f/39/f/xMTE/3d3d+YZGRlG
+AAAAAwAAAAAAAAAAAAAACkJCQqGtra3/xsbG/+vr6//y8vL/9fX1//X19f/z8/P/9fX1//Ly8v/u7u7/
+0tLS/6+vr/9KSkqhAAAACgAAAAAAAAAAAAAAF3h4eN2/v7//z8/P/93d3f/q6ur/7+/v/+/v7//w8PD/
+7e3t/+3t7f/i4uL/zs7O/8XFxf98fHzdAAAAFwAAAAAAAAADAAAAJKSkpPjOzs7/2dnZ/+Dg4P/i4uL/
+5eXl/+bm5v/n5+f/5eXl/+Li4v/e3t7/2tra/9DQ0P+srKz4AAAAJAAAAAMAAAADAAAALrCwsPrW1tb/
+3t7e/+Tk5P/p6en/6+vr/+zs7P/p6en/6+vr/+fn5//k5OT/4ODg/9nZ2f+zs7P6AAAALgAAAAMAAAAD
+AAAALp2dnezg4OD/5eXl/+rq6v/u7u7/8PDw//Dw8P/x8fH/8PDw/+7u7v/q6ur/5ubm/+Hh4f+ZmZns
+AAAALgAAAAMAAAADAAAAJG5ubs/l5eX/6enp/+/v7//y8vL/9vb2//r6+v/5+fn/9/f3//b29v/x8fH/
+6+vr/+Tk5P9ra2vPAAAAJAAAAAMAAAAAAAAAFy4uLpPCwsL67Ozs//Pz8//5+fn//v7+//7+/v/+/v7/
+/v7+//v7+//19fX/8PDw/8LCwvosLCyTAAAAFwAAAAAAAAAAAAAACgAAAENfX1/S5OTk/vn5+f/+/v7/
+///////////////////////////8/Pz/5ubm/l9fX9IAAABDAAAACgAAAAAAAAAAAAAAAwAAABcAAABl
+YmJi3NLS0v3////////////////////////////////V1dX9ZGRk3AAAAGUAAAAXAAAAAwAAAAAAAAAA
+AAAAAAAAAAUAAAAfAAAAZTMzM8KAgIDwv7+//O3t7f/t7e3/v7+//ICAgPAzMzPCAAAAZQAAAB8AAAAF
+AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFAAAAFwAAAEMAAAB3AAAAnwAAALMAAACzAAAAnwAAAHcAAABD
+AAAAFwAAAAUAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAwAAAAoAAAAXAAAAJAAAAC4AAAAu
+AAAAJAAAABcAAAAKAAAAAwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+AAAAAwAAAAMAAAADAAAAAwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADQEAAAMAAAABABIAAAEB
+AAMAAAABABIAAAECAAMAAAAEAAAFugEDAAMAAAABAAEAAAEGAAMAAAABAAIAAAERAAQAAAABAAAACAES
+AAMAAAABAAEAAAEVAAMAAAABAAQAAAEWAAMAAAABBxwAAAEXAAQAAAABAAAFEAEcAAMAAAABAAEAAAFS
+AAMAAAABAAEAAAFTAAMAAAAEAAAFwgAAAAAACAAIAAgACAABAAEAAQABA</bytes>
+												</object>
+											</object>
+										</object>
+									</object>
+									<reference key="NSColor" ref="743532525"/>
+								</object>
+								<reference key="NSAlternateImage" ref="103585188"/>
+								<int key="NSPeriodicDelay">400</int>
+								<int key="NSPeriodicInterval">75</int>
+							</object>
+							<reference key="NSSelectedCell" ref="853217630"/>
+							<reference key="NSBackgroundColor" ref="344940583"/>
+							<reference key="NSCellBackgroundColor" ref="72801970"/>
+							<reference key="NSFont" ref="227377946"/>
+						</object>
+						<object class="NSTextField" id="841149624">
+							<reference key="NSNextResponder" ref="1006"/>
+							<int key="NSvFlags">268</int>
+							<string key="NSFrame">{{76, 123}, {66, 17}}</string>
+							<reference key="NSSuperview" ref="1006"/>
+							<bool key="NSEnabled">YES</bool>
+							<object class="NSTextFieldCell" key="NSCell" id="405363163">
+								<int key="NSCellFlags">68288064</int>
+								<int key="NSCellFlags2">272630784</int>
+								<string key="NSContents">Compute:</string>
+								<reference key="NSSupport" ref="227377946"/>
+								<reference key="NSControlView" ref="841149624"/>
+								<reference key="NSBackgroundColor" ref="344940583"/>
+								<reference key="NSTextColor" ref="942182489"/>
+							</object>
+						</object>
+						<object class="NSTextField" id="543510533">
+							<reference key="NSNextResponder" ref="1006"/>
+							<int key="NSvFlags">268</int>
+							<string key="NSFrame">{{61, 441}, {78, 22}}</string>
+							<reference key="NSSuperview" ref="1006"/>
+							<bool key="NSEnabled">YES</bool>
+							<object class="NSTextFieldCell" key="NSCell" id="1003059605">
+								<int key="NSCellFlags">-1804468671</int>
+								<int key="NSCellFlags2">-1874852864</int>
+								<string key="NSContents"/>
+								<reference key="NSSupport" ref="227377946"/>
+								<object class="NSDateFormatter" key="NSFormatter" id="478164133">
+									<object class="NSMutableDictionary" key="NS.attributes">
+										<bool key="EncodedWithXMLCoder">YES</bool>
+										<object class="NSMutableArray" key="dict.sortedKeys">
+											<bool key="EncodedWithXMLCoder">YES</bool>
+											<string>dateFormat_10_0</string>
+											<string>dateStyle</string>
+											<string>formatterBehavior</string>
+											<string>timeStyle</string>
+										</object>
+										<object class="NSMutableArray" key="dict.values">
+											<bool key="EncodedWithXMLCoder">YES</bool>
+											<string>%m/%d/%y</string>
+											<reference ref="9"/>
+											<integer value="1040"/>
+											<reference ref="8"/>
+										</object>
+									</object>
+									<string key="NS.format">M/d/yy</string>
+									<bool key="NS.natural">NO</bool>
+								</object>
+								<reference key="NSControlView" ref="543510533"/>
+								<bool key="NSDrawsBackground">YES</bool>
+								<reference key="NSBackgroundColor" ref="627117864"/>
+								<reference key="NSTextColor" ref="394575910"/>
+							</object>
+						</object>
+						<object class="NSTextField" id="720301440">
+							<reference key="NSNextResponder" ref="1006"/>
+							<int key="NSvFlags">268</int>
+							<string key="NSFrame">{{213, 441}, {73, 22}}</string>
+							<reference key="NSSuperview" ref="1006"/>
+							<bool key="NSEnabled">YES</bool>
+							<object class="NSTextFieldCell" key="NSCell" id="622482629">
+								<int key="NSCellFlags">-2075001280</int>
+								<int key="NSCellFlags2">-1874852864</int>
+								<string key="NSContents"/>
+								<reference key="NSSupport" ref="227377946"/>
+								<object class="NSDateFormatter" key="NSFormatter" id="472826315">
+									<object class="NSMutableDictionary" key="NS.attributes">
+										<bool key="EncodedWithXMLCoder">YES</bool>
+										<object class="NSMutableArray" key="dict.sortedKeys">
+											<bool key="EncodedWithXMLCoder">YES</bool>
+											<string>dateFormat_10_0</string>
+											<string>dateStyle</string>
+											<string>formatterBehavior</string>
+											<string>timeStyle</string>
+										</object>
+										<object class="NSMutableArray" key="dict.values">
+											<bool key="EncodedWithXMLCoder">YES</bool>
+											<string>%m/%d/%y</string>
+											<reference ref="9"/>
+											<integer value="1040"/>
+											<reference ref="8"/>
+										</object>
+									</object>
+									<string key="NS.format">M/d/yy</string>
+									<bool key="NS.natural">NO</bool>
+								</object>
+								<reference key="NSControlView" ref="720301440"/>
+								<bool key="NSDrawsBackground">YES</bool>
+								<reference key="NSBackgroundColor" ref="627117864"/>
+								<reference key="NSTextColor" ref="394575910"/>
+							</object>
+						</object>
+						<object class="NSTextField" id="662881888">
+							<reference key="NSNextResponder" ref="1006"/>
+							<int key="NSvFlags">268</int>
+							<string key="NSFrame">{{46, 471}, {109, 17}}</string>
+							<reference key="NSSuperview" ref="1006"/>
+							<bool key="NSEnabled">YES</bool>
+							<object class="NSTextFieldCell" key="NSCell" id="124721751">
+								<int key="NSCellFlags">68288064</int>
+								<int key="NSCellFlags2">272630784</int>
+								<string key="NSContents">Origination Date</string>
+								<reference key="NSSupport" ref="227377946"/>
+								<reference key="NSControlView" ref="662881888"/>
+								<reference key="NSBackgroundColor" ref="344940583"/>
+								<reference key="NSTextColor" ref="942182489"/>
+							</object>
+						</object>
+						<object class="NSTextField" id="607934766">
+							<reference key="NSNextResponder" ref="1006"/>
+							<int key="NSvFlags">268</int>
+							<string key="NSFrame">{{205, 471}, {90, 17}}</string>
+							<reference key="NSSuperview" ref="1006"/>
+							<bool key="NSEnabled">YES</bool>
+							<object class="NSTextFieldCell" key="NSCell" id="211620694">
+								<int key="NSCellFlags">68288064</int>
+								<int key="NSCellFlags2">272630784</int>
+								<string key="NSContents">First Payment</string>
+								<reference key="NSSupport" ref="227377946"/>
+								<reference key="NSControlView" ref="607934766"/>
+								<reference key="NSBackgroundColor" ref="344940583"/>
+								<reference key="NSTextColor" ref="942182489"/>
+							</object>
+						</object>
+						<object class="NSTextField" id="149242470">
+							<reference key="NSNextResponder" ref="1006"/>
+							<int key="NSvFlags">268</int>
+							<string key="NSFrame">{{230, 110}, {123, 17}}</string>
+							<reference key="NSSuperview" ref="1006"/>
+							<bool key="NSEnabled">YES</bool>
+							<object class="NSTextFieldCell" key="NSCell" id="7019256">
+								<int key="NSCellFlags">68288064</int>
+								<int key="NSCellFlags2">272630784</int>
+								<string key="NSContents">Total Interest Paid:</string>
+								<reference key="NSSupport" ref="227377946"/>
+								<reference key="NSControlView" ref="149242470"/>
+								<reference key="NSBackgroundColor" ref="344940583"/>
+								<reference key="NSTextColor" ref="942182489"/>
+							</object>
+						</object>
+						<object class="NSTextField" id="665211230">
+							<reference key="NSNextResponder" ref="1006"/>
+							<int key="NSvFlags">268</int>
+							<string key="NSFrame">{{365, 108}, {118, 22}}</string>
+							<reference key="NSSuperview" ref="1006"/>
+							<bool key="NSEnabled">YES</bool>
+							<object class="NSTextFieldCell" key="NSCell" id="273963221">
+								<int key="NSCellFlags">-2075001280</int>
+								<int key="NSCellFlags2">-2076179456</int>
+								<string key="NSContents"/>
+								<reference key="NSSupport" ref="227377946"/>
+								<object class="NSNumberFormatter" key="NSFormatter" id="876830924">
+									<object class="NSMutableDictionary" key="NS.attributes">
+										<bool key="EncodedWithXMLCoder">YES</bool>
+										<object class="NSMutableArray" key="dict.sortedKeys">
+											<bool key="EncodedWithXMLCoder">YES</bool>
+											<string>allowsFloats</string>
+											<string>alwaysShowsDecimalSeparator</string>
+											<string>formatterBehavior</string>
+											<string>generatesDecimalNumbers</string>
+											<string>multiplier</string>
+											<string>numberStyle</string>
+										</object>
+										<object class="NSMutableArray" key="dict.values">
+											<bool key="EncodedWithXMLCoder">YES</bool>
+											<reference ref="6"/>
+											<reference ref="5"/>
+											<integer value="1040"/>
+											<reference ref="5"/>
+											<real value="1.000000e-02"/>
+											<reference ref="10"/>
+										</object>
+									</object>
+									<string type="base64-UTF8" key="NS.positiveformat">wqQjLCMjMC4wMA</string>
+									<string type="base64-UTF8" key="NS.negativeformat">KMKkIywjIzAuMDApA</string>
+									<nil key="NS.positiveattrs"/>
+									<nil key="NS.negativeattrs"/>
+									<object class="NSAttributedString" key="NS.zero">
+										<nil key="NSString"/>
+									</object>
+									<object class="NSAttributedString" key="NS.nil">
+										<nil key="NSString"/>
+									</object>
+									<object class="NSAttributedString" key="NS.nan">
+										<string key="NSString">NaN</string>
+										<reference key="NSAttributes" ref="932461654"/>
+									</object>
+									<reference key="NS.min" ref="325159587"/>
+									<reference key="NS.max" ref="325159587"/>
+									<object class="NSDecimalNumberHandler" key="NS.rounding">
+										<int key="NS.roundingmode">3</int>
+										<bool key="NS.raise.overflow">YES</bool>
+										<bool key="NS.raise.underflow">YES</bool>
+										<bool key="NS.raise.dividebyzero">YES</bool>
+									</object>
+									<string key="NS.decimal">.</string>
+									<string key="NS.thousand">,</string>
+									<bool key="NS.hasthousands">YES</bool>
+									<bool key="NS.localized">YES</bool>
+									<bool key="NS.allowsfloats">NO</bool>
+								</object>
+								<reference key="NSControlView" ref="665211230"/>
+								<bool key="NSDrawsBackground">YES</bool>
+								<reference key="NSBackgroundColor" ref="627117864"/>
+								<reference key="NSTextColor" ref="394575910"/>
+							</object>
+						</object>
+						<object class="NSTextField" id="1020002354">
+							<reference key="NSNextResponder" ref="1006"/>
+							<int key="NSvFlags">268</int>
+							<string key="NSFrame">{{253, 262}, {233, 14}}</string>
+							<reference key="NSSuperview" ref="1006"/>
+							<bool key="NSEnabled">YES</bool>
+							<object class="NSTextFieldCell" key="NSCell" id="1010722721">
+								<int key="NSCellFlags">68288064</int>
+								<int key="NSCellFlags2">272761856</int>
+								<string key="NSContents">Reached max duration needed to pay loan </string>
+								<object class="NSFont" key="NSSupport" id="26">
+									<string key="NSName">LucidaGrande</string>
+									<double key="NSSize">1.100000e+01</double>
+									<int key="NSfFlags">3100</int>
+								</object>
+								<reference key="NSControlView" ref="1020002354"/>
+								<reference key="NSBackgroundColor" ref="344940583"/>
+								<reference key="NSTextColor" ref="942182489"/>
+							</object>
+						</object>
+						<object class="NSTextField" id="848322395">
+							<reference key="NSNextResponder" ref="1006"/>
+							<int key="NSvFlags">268</int>
+							<string key="NSFrame">{{183, 174}, {332, 14}}</string>
+							<reference key="NSSuperview" ref="1006"/>
+							<bool key="NSEnabled">YES</bool>
+							<object class="NSTextFieldCell" key="NSCell" id="294160444">
+								<int key="NSCellFlags">68288064</int>
+								<int key="NSCellFlags2">272761856</int>
+								<string type="base64-UTF8" key="NSContents">UmVhY2hlZCBtaW4gcGF5bWVudCBuZWVkZWQgZm9yIGZpcnN0IG1vbnRoJ3MgaW50ZXJlc3Q</string>
+								<reference key="NSSupport" ref="26"/>
+								<reference key="NSControlView" ref="848322395"/>
+								<reference key="NSBackgroundColor" ref="344940583"/>
+								<reference key="NSTextColor" ref="942182489"/>
+							</object>
+						</object>
+						<object class="NSTextField" id="860928395">
+							<reference key="NSNextResponder" ref="1006"/>
+							<int key="NSvFlags">268</int>
+							<string key="NSFrame">{{253, 262}, {227, 14}}</string>
+							<reference key="NSSuperview" ref="1006"/>
+							<bool key="NSEnabled">YES</bool>
+							<object class="NSTextFieldCell" key="NSCell" id="571238653">
+								<int key="NSCellFlags">68288064</int>
+								<int key="NSCellFlags2">272761856</int>
+								<string key="NSContents">Reached min duration needed to pay loan</string>
+								<reference key="NSSupport" ref="26"/>
+								<reference key="NSControlView" ref="860928395"/>
+								<reference key="NSBackgroundColor" ref="344940583"/>
+								<reference key="NSTextColor" ref="942182489"/>
+							</object>
+						</object>
+					</object>
+					<string key="NSFrameSize">{527, 498}</string>
+				</object>
+				<string key="NSScreenRect">{{0, 0}, {1680, 1028}}</string>
+				<string key="NSMaxSize">{3.40282e+38, 3.40282e+38}</string>
+			</object>
+		</object>
+		<object class="IBObjectContainer" key="IBDocument.Objects">
+			<object class="NSMutableArray" key="connectionRecords">
+				<bool key="EncodedWithXMLCoder">YES</bool>
+				<object class="IBConnectionRecord">
+					<object class="IBActionConnection" key="connection">
+						<string key="label">buttonPushed:</string>
+						<reference key="source" ref="1001"/>
+						<reference key="destination" ref="628774051"/>
+					</object>
+					<int key="connectionID">59</int>
+				</object>
+				<object class="IBConnectionRecord">
+					<object class="IBOutletConnection" key="connection">
+						<string key="label">loanText</string>
+						<reference key="source" ref="1001"/>
+						<reference key="destination" ref="809137054"/>
+					</object>
+					<int key="connectionID">76</int>
+				</object>
+				<object class="IBConnectionRecord">
+					<object class="IBOutletConnection" key="connection">
+						<string key="label">intText</string>
+						<reference key="source" ref="1001"/>
+						<reference key="destination" ref="583982648"/>
+					</object>
+					<int key="connectionID">77</int>
+				</object>
+				<object class="IBConnectionRecord">
+					<object class="IBOutletConnection" key="connection">
+						<string key="label">durText</string>
+						<reference key="source" ref="1001"/>
+						<reference key="destination" ref="125608385"/>
+					</object>
+					<int key="connectionID">78</int>
+				</object>
+				<object class="IBConnectionRecord">
+					<object class="IBOutletConnection" key="connection">
+						<string key="label">payText</string>
+						<reference key="source" ref="1001"/>
+						<reference key="destination" ref="644051649"/>
+					</object>
+					<int key="connectionID">79</int>
+				</object>
+				<object class="IBConnectionRecord">
+					<object class="IBOutletConnection" key="connection">
+						<string key="label">intSlider</string>
+						<reference key="source" ref="1001"/>
+						<reference key="destination" ref="502682855"/>
+					</object>
+					<int key="connectionID">80</int>
+				</object>
+				<object class="IBConnectionRecord">
+					<object class="IBOutletConnection" key="connection">
+						<string key="label">durSlider</string>
+						<reference key="source" ref="1001"/>
+						<reference key="destination" ref="857285538"/>
+					</object>
+					<int key="connectionID">81</int>
+				</object>
+				<object class="IBConnectionRecord">
+					<object class="IBOutletConnection" key="connection">
+						<string key="label">paySlider</string>
+						<reference key="source" ref="1001"/>
+						<reference key="destination" ref="82942187"/>
+					</object>
+					<int key="connectionID">82</int>
+				</object>
+				<object class="IBConnectionRecord">
+					<object class="IBBindingConnection" key="connection">
+						<string key="label">value: loan.originationDate</string>
+						<reference key="source" ref="543510533"/>
+						<reference key="destination" ref="1001"/>
+						<object class="NSNibBindingConnector" key="connector">
+							<reference key="NSSource" ref="543510533"/>
+							<reference key="NSDestination" ref="1001"/>
+							<string key="NSLabel">value: loan.originationDate</string>
+							<string key="NSBinding">value</string>
+							<string key="NSKeyPath">loan.originationDate</string>
+							<object class="NSDictionary" key="NSOptions">
+								<string key="NS.key.0">NSContinuouslyUpdatesValue</string>
+								<reference key="NS.object.0" ref="5"/>
+							</object>
+							<int key="NSNibBindingConnectorVersion">2</int>
+						</object>
+					</object>
+					<int key="connectionID">151</int>
+				</object>
+				<object class="IBConnectionRecord">
+					<object class="IBBindingConnection" key="connection">
+						<string key="label">value: loan.firstPayment</string>
+						<reference key="source" ref="720301440"/>
+						<reference key="destination" ref="1001"/>
+						<object class="NSNibBindingConnector" key="connector">
+							<reference key="NSSource" ref="720301440"/>
+							<reference key="NSDestination" ref="1001"/>
+							<string key="NSLabel">value: loan.firstPayment</string>
+							<string key="NSBinding">value</string>
+							<string key="NSKeyPath">loan.firstPayment</string>
+							<object class="NSDictionary" key="NSOptions">
+								<string key="NS.key.0">NSContinuouslyUpdatesValue</string>
+								<reference key="NS.object.0" ref="5"/>
+							</object>
+							<int key="NSNibBindingConnectorVersion">2</int>
+						</object>
+					</object>
+					<int key="connectionID">152</int>
+				</object>
+				<object class="IBConnectionRecord">
+					<object class="IBBindingConnection" key="connection">
+						<string key="label">value: loan.loanAmt</string>
+						<reference key="source" ref="809137054"/>
+						<reference key="destination" ref="1001"/>
+						<object class="NSNibBindingConnector" key="connector">
+							<reference key="NSSource" ref="809137054"/>
+							<reference key="NSDestination" ref="1001"/>
+							<string key="NSLabel">value: loan.loanAmt</string>
+							<string key="NSBinding">value</string>
+							<string key="NSKeyPath">loan.loanAmt</string>
+							<object class="NSDictionary" key="NSOptions">
+								<string key="NS.key.0">NSContinuouslyUpdatesValue</string>
+								<reference key="NS.object.0" ref="5"/>
+							</object>
+							<int key="NSNibBindingConnectorVersion">2</int>
+						</object>
+					</object>
+					<int key="connectionID">153</int>
+				</object>
+				<object class="IBConnectionRecord">
+					<object class="IBBindingConnection" key="connection">
+						<string key="label">value: loan.interestRate</string>
+						<reference key="source" ref="583982648"/>
+						<reference key="destination" ref="1001"/>
+						<object class="NSNibBindingConnector" key="connector">
+							<reference key="NSSource" ref="583982648"/>
+							<reference key="NSDestination" ref="1001"/>
+							<string key="NSLabel">value: loan.interestRate</string>
+							<string key="NSBinding">value</string>
+							<string key="NSKeyPath">loan.interestRate</string>
+							<object class="NSDictionary" key="NSOptions">
+								<string key="NS.key.0">NSContinuouslyUpdatesValue</string>
+								<reference key="NS.object.0" ref="5"/>
+							</object>
+							<int key="NSNibBindingConnectorVersion">2</int>
+						</object>
+					</object>
+					<int key="connectionID">154</int>
+				</object>
+				<object class="IBConnectionRecord">
+					<object class="IBBindingConnection" key="connection">
+						<string key="label">value: loan.loanDuration</string>
+						<reference key="source" ref="125608385"/>
+						<reference key="destination" ref="1001"/>
+						<object class="NSNibBindingConnector" key="connector">
+							<reference key="NSSource" ref="125608385"/>
+							<reference key="NSDestination" ref="1001"/>
+							<string key="NSLabel">value: loan.loanDuration</string>
+							<string key="NSBinding">value</string>
+							<string key="NSKeyPath">loan.loanDuration</string>
+							<object class="NSDictionary" key="NSOptions">
+								<string key="NS.key.0">NSContinuouslyUpdatesValue</string>
+								<reference key="NS.object.0" ref="5"/>
+							</object>
+							<int key="NSNibBindingConnectorVersion">2</int>
+						</object>
+					</object>
+					<int key="connectionID">155</int>
+				</object>
+				<object class="IBConnectionRecord">
+					<object class="IBBindingConnection" key="connection">
+						<string key="label">value: loan.monthlyPayment</string>
+						<reference key="source" ref="644051649"/>
+						<reference key="destination" ref="1001"/>
+						<object class="NSNibBindingConnector" key="connector">
+							<reference key="NSSource" ref="644051649"/>
+							<reference key="NSDestination" ref="1001"/>
+							<string key="NSLabel">value: loan.monthlyPayment</string>
+							<string key="NSBinding">value</string>
+							<string key="NSKeyPath">loan.monthlyPayment</string>
+							<object class="NSDictionary" key="NSOptions">
+								<string key="NS.key.0">NSContinuouslyUpdatesValue</string>
+								<reference key="NS.object.0" ref="5"/>
+							</object>
+							<int key="NSNibBindingConnectorVersion">2</int>
+						</object>
+					</object>
+					<int key="connectionID">156</int>
+				</object>
+				<object class="IBConnectionRecord">
+					<object class="IBBindingConnection" key="connection">
+						<string key="label">value: loan.totInterest</string>
+						<reference key="source" ref="665211230"/>
+						<reference key="destination" ref="1001"/>
+						<object class="NSNibBindingConnector" key="connector">
+							<reference key="NSSource" ref="665211230"/>
+							<reference key="NSDestination" ref="1001"/>
+							<string key="NSLabel">value: loan.totInterest</string>
+							<string key="NSBinding">value</string>
+							<string key="NSKeyPath">loan.totInterest</string>
+							<int key="NSNibBindingConnectorVersion">2</int>
+						</object>
+					</object>
+					<int key="connectionID">157</int>
+				</object>
+				<object class="IBConnectionRecord">
+					<object class="IBBindingConnection" key="connection">
+						<string key="label">value: loan.monthlyPayment</string>
+						<reference key="source" ref="82942187"/>
+						<reference key="destination" ref="1001"/>
+						<object class="NSNibBindingConnector" key="connector">
+							<reference key="NSSource" ref="82942187"/>
+							<reference key="NSDestination" ref="1001"/>
+							<string key="NSLabel">value: loan.monthlyPayment</string>
+							<string key="NSBinding">value</string>
+							<string key="NSKeyPath">loan.monthlyPayment</string>
+							<int key="NSNibBindingConnectorVersion">2</int>
+						</object>
+					</object>
+					<int key="connectionID">161</int>
+				</object>
+				<object class="IBConnectionRecord">
+					<object class="IBBindingConnection" key="connection">
+						<string key="label">value: loan.loanDuration</string>
+						<reference key="source" ref="857285538"/>
+						<reference key="destination" ref="1001"/>
+						<object class="NSNibBindingConnector" key="connector">
+							<reference key="NSSource" ref="857285538"/>
+							<reference key="NSDestination" ref="1001"/>
+							<string key="NSLabel">value: loan.loanDuration</string>
+							<string key="NSBinding">value</string>
+							<string key="NSKeyPath">loan.loanDuration</string>
+							<int key="NSNibBindingConnectorVersion">2</int>
+						</object>
+					</object>
+					<int key="connectionID">162</int>
+				</object>
+				<object class="IBConnectionRecord">
+					<object class="IBBindingConnection" key="connection">
+						<string key="label">value: loan.interestRate</string>
+						<reference key="source" ref="502682855"/>
+						<reference key="destination" ref="1001"/>
+						<object class="NSNibBindingConnector" key="connector">
+							<reference key="NSSource" ref="502682855"/>
+							<reference key="NSDestination" ref="1001"/>
+							<string key="NSLabel">value: loan.interestRate</string>
+							<string key="NSBinding">value</string>
+							<string key="NSKeyPath">loan.interestRate</string>
+							<int key="NSNibBindingConnectorVersion">2</int>
+						</object>
+					</object>
+					<int key="connectionID">163</int>
+				</object>
+				<object class="IBConnectionRecord">
+					<object class="IBOutletConnection" key="connection">
+						<string key="label">window</string>
+						<reference key="source" ref="1001"/>
+						<reference key="destination" ref="1005"/>
+					</object>
+					<int key="connectionID">164</int>
+				</object>
+				<object class="IBConnectionRecord">
+					<object class="IBOutletConnection" key="connection">
+						<string key="label">delegate</string>
+						<reference key="source" ref="1005"/>
+						<reference key="destination" ref="1001"/>
+					</object>
+					<int key="connectionID">165</int>
+				</object>
+				<object class="IBConnectionRecord">
+					<object class="IBBindingConnection" key="connection">
+						<string key="label">hidden: loan.minPay</string>
+						<reference key="source" ref="848322395"/>
+						<reference key="destination" ref="1001"/>
+						<object class="NSNibBindingConnector" key="connector">
+							<reference key="NSSource" ref="848322395"/>
+							<reference key="NSDestination" ref="1001"/>
+							<string key="NSLabel">hidden: loan.minPay</string>
+							<string key="NSBinding">hidden</string>
+							<string key="NSKeyPath">loan.minPay</string>
+							<object class="NSDictionary" key="NSOptions">
+								<bool key="EncodedWithXMLCoder">YES</bool>
+								<object class="NSMutableArray" key="dict.sortedKeys">
+									<bool key="EncodedWithXMLCoder">YES</bool>
+									<string>NSNullPlaceholder</string>
+									<string>NSValueTransformerName</string>
+								</object>
+								<object class="NSMutableArray" key="dict.values">
+									<bool key="EncodedWithXMLCoder">YES</bool>
+									<reference ref="9"/>
+									<string>NSNegateBoolean</string>
+								</object>
+							</object>
+							<int key="NSNibBindingConnectorVersion">2</int>
+						</object>
+					</object>
+					<int key="connectionID">169</int>
+				</object>
+				<object class="IBConnectionRecord">
+					<object class="IBBindingConnection" key="connection">
+						<string key="label">hidden: loan.minDur</string>
+						<reference key="source" ref="860928395"/>
+						<reference key="destination" ref="1001"/>
+						<object class="NSNibBindingConnector" key="connector">
+							<reference key="NSSource" ref="860928395"/>
+							<reference key="NSDestination" ref="1001"/>
+							<string key="NSLabel">hidden: loan.minDur</string>
+							<string key="NSBinding">hidden</string>
+							<string key="NSKeyPath">loan.minDur</string>
+							<object class="NSDictionary" key="NSOptions">
+								<bool key="EncodedWithXMLCoder">YES</bool>
+								<object class="NSMutableArray" key="dict.sortedKeys">
+									<bool key="EncodedWithXMLCoder">YES</bool>
+									<string>NSNullPlaceholder</string>
+									<string>NSValueTransformerName</string>
+								</object>
+								<object class="NSMutableArray" key="dict.values">
+									<bool key="EncodedWithXMLCoder">YES</bool>
+									<reference ref="9"/>
+									<string>NSNegateBoolean</string>
+								</object>
+							</object>
+							<int key="NSNibBindingConnectorVersion">2</int>
+						</object>
+					</object>
+					<int key="connectionID">170</int>
+				</object>
+				<object class="IBConnectionRecord">
+					<object class="IBBindingConnection" key="connection">
+						<string key="label">hidden: loan.maxDur</string>
+						<reference key="source" ref="1020002354"/>
+						<reference key="destination" ref="1001"/>
+						<object class="NSNibBindingConnector" key="connector">
+							<reference key="NSSource" ref="1020002354"/>
+							<reference key="NSDestination" ref="1001"/>
+							<string key="NSLabel">hidden: loan.maxDur</string>
+							<string key="NSBinding">hidden</string>
+							<string key="NSKeyPath">loan.maxDur</string>
+							<object class="NSDictionary" key="NSOptions">
+								<bool key="EncodedWithXMLCoder">YES</bool>
+								<object class="NSMutableArray" key="dict.sortedKeys">
+									<bool key="EncodedWithXMLCoder">YES</bool>
+									<string>NSNullPlaceholder</string>
+									<string>NSValueTransformerName</string>
+								</object>
+								<object class="NSMutableArray" key="dict.values">
+									<bool key="EncodedWithXMLCoder">YES</bool>
+									<reference ref="9"/>
+									<string>NSNegateBoolean</string>
+								</object>
+							</object>
+							<int key="NSNibBindingConnectorVersion">2</int>
+						</object>
+					</object>
+					<int key="connectionID">171</int>
+				</object>
+				<object class="IBConnectionRecord">
+					<object class="IBOutletConnection" key="connection">
+						<string key="label">origDateText</string>
+						<reference key="source" ref="1001"/>
+						<reference key="destination" ref="543510533"/>
+					</object>
+					<int key="connectionID">172</int>
+				</object>
+			</object>
+			<object class="IBMutableOrderedSet" key="objectRecords">
+				<object class="NSArray" key="orderedObjects">
+					<bool key="EncodedWithXMLCoder">YES</bool>
+					<object class="IBObjectRecord">
+						<int key="objectID">0</int>
+						<object class="NSArray" key="object" id="1002">
+							<bool key="EncodedWithXMLCoder">YES</bool>
+						</object>
+						<reference key="children" ref="1000"/>
+						<nil key="parent"/>
+					</object>
+					<object class="IBObjectRecord">
+						<int key="objectID">-2</int>
+						<reference key="object" ref="1001"/>
+						<reference key="parent" ref="1002"/>
+						<string type="base64-UTF8" key="objectName">RmlsZSdzIE93bmVyA</string>
+					</object>
+					<object class="IBObjectRecord">
+						<int key="objectID">-1</int>
+						<reference key="object" ref="1003"/>
+						<reference key="parent" ref="1002"/>
+						<string key="objectName">First Responder</string>
+					</object>
+					<object class="IBObjectRecord">
+						<int key="objectID">-3</int>
+						<reference key="object" ref="1004"/>
+						<reference key="parent" ref="1002"/>
+						<string key="objectName">Application</string>
+					</object>
+					<object class="IBObjectRecord">
+						<int key="objectID">1</int>
+						<reference key="object" ref="1005"/>
+						<object class="NSMutableArray" key="children">
+							<bool key="EncodedWithXMLCoder">YES</bool>
+							<reference ref="1006"/>
+						</object>
+						<reference key="parent" ref="1002"/>
+					</object>
+					<object class="IBObjectRecord">
+						<int key="objectID">2</int>
+						<reference key="object" ref="1006"/>
+						<object class="NSMutableArray" key="children">
+							<bool key="EncodedWithXMLCoder">YES</bool>
+							<reference ref="857285538"/>
+							<reference ref="82942187"/>
+							<reference ref="583982648"/>
+							<reference ref="125608385"/>
+							<reference ref="644051649"/>
+							<reference ref="809137054"/>
+							<reference ref="1025071149"/>
+							<reference ref="767489727"/>
+							<reference ref="79509684"/>
+							<reference ref="229354320"/>
+							<reference ref="662881888"/>
+							<reference ref="607934766"/>
+							<reference ref="543510533"/>
+							<reference ref="720301440"/>
+							<reference ref="628774051"/>
+							<reference ref="841149624"/>
+							<reference ref="665211230"/>
+							<reference ref="149242470"/>
+							<reference ref="502682855"/>
+							<reference ref="1020002354"/>
+							<reference ref="848322395"/>
+							<reference ref="860928395"/>
+						</object>
+						<reference key="parent" ref="1005"/>
+					</object>
+					<object class="IBObjectRecord">
+						<int key="objectID">3</int>
+						<reference key="object" ref="502682855"/>
+						<object class="NSMutableArray" key="children">
+							<bool key="EncodedWithXMLCoder">YES</bool>
+							<reference ref="232181660"/>
+						</object>
+						<reference key="parent" ref="1006"/>
+					</object>
+					<object class="IBObjectRecord">
+						<int key="objectID">4</int>
+						<reference key="object" ref="232181660"/>
+						<reference key="parent" ref="502682855"/>
+					</object>
+					<object class="IBObjectRecord">
+						<int key="objectID">5</int>
+						<reference key="object" ref="857285538"/>
+						<object class="NSMutableArray" key="children">
+							<bool key="EncodedWithXMLCoder">YES</bool>
+							<reference ref="616540554"/>
+						</object>
+						<reference key="parent" ref="1006"/>
+					</object>
+					<object class="IBObjectRecord">
+						<int key="objectID">6</int>
+						<reference key="object" ref="616540554"/>
+						<reference key="parent" ref="857285538"/>
+					</object>
+					<object class="IBObjectRecord">
+						<int key="objectID">7</int>
+						<reference key="object" ref="82942187"/>
+						<object class="NSMutableArray" key="children">
+							<bool key="EncodedWithXMLCoder">YES</bool>
+							<reference ref="618853427"/>
+						</object>
+						<reference key="parent" ref="1006"/>
+					</object>
+					<object class="IBObjectRecord">
+						<int key="objectID">8</int>
+						<reference key="object" ref="618853427"/>
+						<object class="NSMutableArray" key="children">
+							<bool key="EncodedWithXMLCoder">YES</bool>
+						</object>
+						<reference key="parent" ref="82942187"/>
+					</object>
+					<object class="IBObjectRecord">
+						<int key="objectID">9</int>
+						<reference key="object" ref="1025071149"/>
+						<object class="NSMutableArray" key="children">
+							<bool key="EncodedWithXMLCoder">YES</bool>
+							<reference ref="311690344"/>
+						</object>
+						<reference key="parent" ref="1006"/>
+					</object>
+					<object class="IBObjectRecord">
+						<int key="objectID">10</int>
+						<reference key="object" ref="311690344"/>
+						<reference key="parent" ref="1025071149"/>
+					</object>
+					<object class="IBObjectRecord">
+						<int key="objectID">11</int>
+						<reference key="object" ref="79509684"/>
+						<object class="NSMutableArray" key="children">
+							<bool key="EncodedWithXMLCoder">YES</bool>
+							<reference ref="961478139"/>
+						</object>
+						<reference key="parent" ref="1006"/>
+					</object>
+					<object class="IBObjectRecord">
+						<int key="objectID">12</int>
+						<reference key="object" ref="961478139"/>
+						<reference key="parent" ref="79509684"/>
+					</object>
+					<object class="IBObjectRecord">
+						<int key="objectID">13</int>
+						<reference key="object" ref="767489727"/>
+						<object class="NSMutableArray" key="children">
+							<bool key="EncodedWithXMLCoder">YES</bool>
+							<reference ref="487292094"/>
+						</object>
+						<reference key="parent" ref="1006"/>
+					</object>
+					<object class="IBObjectRecord">
+						<int key="objectID">14</int>
+						<reference key="object" ref="487292094"/>
+						<reference key="parent" ref="767489727"/>
+					</object>
+					<object class="IBObjectRecord">
+						<int key="objectID">15</int>
+						<reference key="object" ref="583982648"/>
+						<object class="NSMutableArray" key="children">
+							<bool key="EncodedWithXMLCoder">YES</bool>
+							<reference ref="5436249"/>
+						</object>
+						<reference key="parent" ref="1006"/>
+					</object>
+					<object class="IBObjectRecord">
+						<int key="objectID">16</int>
+						<reference key="object" ref="5436249"/>
+						<object class="NSMutableArray" key="children">
+							<bool key="EncodedWithXMLCoder">YES</bool>
+							<reference ref="801243361"/>
+						</object>
+						<reference key="parent" ref="583982648"/>
+					</object>
+					<object class="IBObjectRecord">
+						<int key="objectID">17</int>
+						<reference key="object" ref="125608385"/>
+						<object class="NSMutableArray" key="children">
+							<bool key="EncodedWithXMLCoder">YES</bool>
+							<reference ref="1071273742"/>
+						</object>
+						<reference key="parent" ref="1006"/>
+					</object>
+					<object class="IBObjectRecord">
+						<int key="objectID">18</int>
+						<reference key="object" ref="1071273742"/>
+						<object class="NSMutableArray" key="children">
+							<bool key="EncodedWithXMLCoder">YES</bool>
+							<reference ref="757491514"/>
+						</object>
+						<reference key="parent" ref="125608385"/>
+					</object>
+					<object class="IBObjectRecord">
+						<int key="objectID">19</int>
+						<reference key="object" ref="644051649"/>
+						<object class="NSMutableArray" key="children">
+							<bool key="EncodedWithXMLCoder">YES</bool>
+							<reference ref="111648228"/>
+						</object>
+						<reference key="parent" ref="1006"/>
+					</object>
+					<object class="IBObjectRecord">
+						<int key="objectID">20</int>
+						<reference key="object" ref="111648228"/>
+						<object class="NSMutableArray" key="children">
+							<bool key="EncodedWithXMLCoder">YES</bool>
+							<reference ref="123140303"/>
+						</object>
+						<reference key="parent" ref="644051649"/>
+					</object>
+					<object class="IBObjectRecord">
+						<int key="objectID">21</int>
+						<reference key="object" ref="801243361"/>
+						<reference key="parent" ref="5436249"/>
+					</object>
+					<object class="IBObjectRecord">
+						<int key="objectID">22</int>
+						<reference key="object" ref="757491514"/>
+						<reference key="parent" ref="1071273742"/>
+					</object>
+					<object class="IBObjectRecord">
+						<int key="objectID">24</int>
+						<reference key="object" ref="809137054"/>
+						<object class="NSMutableArray" key="children">
+							<bool key="EncodedWithXMLCoder">YES</bool>
+							<reference ref="310865555"/>
+						</object>
+						<reference key="parent" ref="1006"/>
+					</object>
+					<object class="IBObjectRecord">
+						<int key="objectID">25</int>
+						<reference key="object" ref="310865555"/>
+						<object class="NSMutableArray" key="children">
+							<bool key="EncodedWithXMLCoder">YES</bool>
+							<reference ref="506223138"/>
+						</object>
+						<reference key="parent" ref="809137054"/>
+					</object>
+					<object class="IBObjectRecord">
+						<int key="objectID">27</int>
+						<reference key="object" ref="229354320"/>
+						<object class="NSMutableArray" key="children">
+							<bool key="EncodedWithXMLCoder">YES</bool>
+							<reference ref="767188954"/>
+						</object>
+						<reference key="parent" ref="1006"/>
+					</object>
+					<object class="IBObjectRecord">
+						<int key="objectID">28</int>
+						<reference key="object" ref="767188954"/>
+						<reference key="parent" ref="229354320"/>
+					</object>
+					<object class="IBObjectRecord">
+						<int key="objectID">29</int>
+						<reference key="object" ref="628774051"/>
+						<object class="NSMutableArray" key="children">
+							<bool key="EncodedWithXMLCoder">YES</bool>
+							<reference ref="853217630"/>
+							<reference ref="46258786"/>
+							<reference ref="735574461"/>
+							<reference ref="322221180"/>
+							<reference ref="149842975"/>
+						</object>
+						<reference key="parent" ref="1006"/>
+					</object>
+					<object class="IBObjectRecord">
+						<int key="objectID">30</int>
+						<reference key="object" ref="853217630"/>
+						<reference key="parent" ref="628774051"/>
+					</object>
+					<object class="IBObjectRecord">
+						<int key="objectID">31</int>
+						<reference key="object" ref="46258786"/>
+						<reference key="parent" ref="628774051"/>
+					</object>
+					<object class="IBObjectRecord">
+						<int key="objectID">32</int>
+						<reference key="object" ref="735574461"/>
+						<reference key="parent" ref="628774051"/>
+					</object>
+					<object class="IBObjectRecord">
+						<int key="objectID">33</int>
+						<reference key="object" ref="322221180"/>
+						<reference key="parent" ref="628774051"/>
+					</object>
+					<object class="IBObjectRecord">
+						<int key="objectID">34</int>
+						<reference key="object" ref="149842975"/>
+						<reference key="parent" ref="628774051"/>
+					</object>
+					<object class="IBObjectRecord">
+						<int key="objectID">35</int>
+						<reference key="object" ref="841149624"/>
+						<object class="NSMutableArray" key="children">
+							<bool key="EncodedWithXMLCoder">YES</bool>
+							<reference ref="405363163"/>
+						</object>
+						<reference key="parent" ref="1006"/>
+					</object>
+					<object class="IBObjectRecord">
+						<int key="objectID">36</int>
+						<reference key="object" ref="405363163"/>
+						<reference key="parent" ref="841149624"/>
+					</object>
+					<object class="IBObjectRecord">
+						<int key="objectID">60</int>
+						<reference key="object" ref="543510533"/>
+						<object class="NSMutableArray" key="children">
+							<bool key="EncodedWithXMLCoder">YES</bool>
+							<reference ref="1003059605"/>
+						</object>
+						<reference key="parent" ref="1006"/>
+					</object>
+					<object class="IBObjectRecord">
+						<int key="objectID">61</int>
+						<reference key="object" ref="1003059605"/>
+						<object class="NSMutableArray" key="children">
+							<bool key="EncodedWithXMLCoder">YES</bool>
+							<reference ref="478164133"/>
+						</object>
+						<reference key="parent" ref="543510533"/>
+					</object>
+					<object class="IBObjectRecord">
+						<int key="objectID">62</int>
+						<reference key="object" ref="720301440"/>
+						<object class="NSMutableArray" key="children">
+							<bool key="EncodedWithXMLCoder">YES</bool>
+							<reference ref="622482629"/>
+						</object>
+						<reference key="parent" ref="1006"/>
+					</object>
+					<object class="IBObjectRecord">
+						<int key="objectID">63</int>
+						<reference key="object" ref="622482629"/>
+						<object class="NSMutableArray" key="children">
+							<bool key="EncodedWithXMLCoder">YES</bool>
+							<reference ref="472826315"/>
+						</object>
+						<reference key="parent" ref="720301440"/>
+					</object>
+					<object class="IBObjectRecord">
+						<int key="objectID">64</int>
+						<reference key="object" ref="662881888"/>
+						<object class="NSMutableArray" key="children">
+							<bool key="EncodedWithXMLCoder">YES</bool>
+							<reference ref="124721751"/>
+						</object>
+						<reference key="parent" ref="1006"/>
+					</object>
+					<object class="IBObjectRecord">
+						<int key="objectID">65</int>
+						<reference key="object" ref="124721751"/>
+						<reference key="parent" ref="662881888"/>
+					</object>
+					<object class="IBObjectRecord">
+						<int key="objectID">66</int>
+						<reference key="object" ref="607934766"/>
+						<object class="NSMutableArray" key="children">
+							<bool key="EncodedWithXMLCoder">YES</bool>
+							<reference ref="211620694"/>
+						</object>
+						<reference key="parent" ref="1006"/>
+					</object>
+					<object class="IBObjectRecord">
+						<int key="objectID">67</int>
+						<reference key="object" ref="211620694"/>
+						<reference key="parent" ref="607934766"/>
+					</object>
+					<object class="IBObjectRecord">
+						<int key="objectID">68</int>
+						<reference key="object" ref="478164133"/>
+						<reference key="parent" ref="1003059605"/>
+					</object>
+					<object class="IBObjectRecord">
+						<int key="objectID">69</int>
+						<reference key="object" ref="472826315"/>
+						<reference key="parent" ref="622482629"/>
+					</object>
+					<object class="IBObjectRecord">
+						<int key="objectID">83</int>
+						<reference key="object" ref="149242470"/>
+						<object class="NSMutableArray" key="children">
+							<bool key="EncodedWithXMLCoder">YES</bool>
+							<reference ref="7019256"/>
+						</object>
+						<reference key="parent" ref="1006"/>
+					</object>
+					<object class="IBObjectRecord">
+						<int key="objectID">84</int>
+						<reference key="object" ref="7019256"/>
+						<reference key="parent" ref="149242470"/>
+					</object>
+					<object class="IBObjectRecord">
+						<int key="objectID">85</int>
+						<reference key="object" ref="665211230"/>
+						<object class="NSMutableArray" key="children">
+							<bool key="EncodedWithXMLCoder">YES</bool>
+							<reference ref="273963221"/>
+						</object>
+						<reference key="parent" ref="1006"/>
+					</object>
+					<object class="IBObjectRecord">
+						<int key="objectID">86</int>
+						<reference key="object" ref="273963221"/>
+						<object class="NSMutableArray" key="children">
+							<bool key="EncodedWithXMLCoder">YES</bool>
+							<reference ref="876830924"/>
+						</object>
+						<reference key="parent" ref="665211230"/>
+					</object>
+					<object class="IBObjectRecord">
+						<int key="objectID">87</int>
+						<reference key="object" ref="876830924"/>
+						<reference key="parent" ref="273963221"/>
+					</object>
+					<object class="IBObjectRecord">
+						<int key="objectID">130</int>
+						<reference key="object" ref="1020002354"/>
+						<object class="NSMutableArray" key="children">
+							<bool key="EncodedWithXMLCoder">YES</bool>
+							<reference ref="1010722721"/>
+						</object>
+						<reference key="parent" ref="1006"/>
+					</object>
+					<object class="IBObjectRecord">
+						<int key="objectID">131</int>
+						<reference key="object" ref="1010722721"/>
+						<reference key="parent" ref="1020002354"/>
+					</object>
+					<object class="IBObjectRecord">
+						<int key="objectID">136</int>
+						<reference key="object" ref="848322395"/>
+						<object class="NSMutableArray" key="children">
+							<bool key="EncodedWithXMLCoder">YES</bool>
+							<reference ref="294160444"/>
+						</object>
+						<reference key="parent" ref="1006"/>
+					</object>
+					<object class="IBObjectRecord">
+						<int key="objectID">137</int>
+						<reference key="object" ref="294160444"/>
+						<reference key="parent" ref="848322395"/>
+					</object>
+					<object class="IBObjectRecord">
+						<int key="objectID">142</int>
+						<reference key="object" ref="860928395"/>
+						<object class="NSMutableArray" key="children">
+							<bool key="EncodedWithXMLCoder">YES</bool>
+							<reference ref="571238653"/>
+						</object>
+						<reference key="parent" ref="1006"/>
+					</object>
+					<object class="IBObjectRecord">
+						<int key="objectID">143</int>
+						<reference key="object" ref="571238653"/>
+						<reference key="parent" ref="860928395"/>
+					</object>
+					<object class="IBObjectRecord">
+						<int key="objectID">148</int>
+						<reference key="object" ref="123140303"/>
+						<reference key="parent" ref="111648228"/>
+					</object>
+					<object class="IBObjectRecord">
+						<int key="objectID">149</int>
+						<reference key="object" ref="506223138"/>
+						<reference key="parent" ref="310865555"/>
+					</object>
+				</object>
+			</object>
+			<object class="NSMutableDictionary" key="flattenedProperties">
+				<bool key="EncodedWithXMLCoder">YES</bool>
+				<object class="NSMutableArray" key="dict.sortedKeys">
+					<bool key="EncodedWithXMLCoder">YES</bool>
+					<string>-1.IBPluginDependency</string>
+					<string>-2.IBPluginDependency</string>
+					<string>-3.IBPluginDependency</string>
+					<string>1.IBEditorWindowLastContentRect</string>
+					<string>1.IBPluginDependency</string>
+					<string>1.IBWindowTemplateEditedContentRect</string>
+					<string>1.NSWindowTemplate.visibleAtLaunch</string>
+					<string>1.WindowOrigin</string>
+					<string>1.editorWindowContentRectSynchronizationRect</string>
+					<string>10.IBPluginDependency</string>
+					<string>11.IBPluginDependency</string>
+					<string>12.IBPluginDependency</string>
+					<string>13.IBPluginDependency</string>
+					<string>130.IBPluginDependency</string>
+					<string>131.IBPluginDependency</string>
+					<string>136.IBPluginDependency</string>
+					<string>137.IBPluginDependency</string>
+					<string>14.IBPluginDependency</string>
+					<string>142.IBPluginDependency</string>
+					<string>143.IBPluginDependency</string>
+					<string>148.IBPluginDependency</string>
+					<string>149.IBPluginDependency</string>
+					<string>15.IBPluginDependency</string>
+					<string>16.IBPluginDependency</string>
+					<string>17.IBPluginDependency</string>
+					<string>18.IBPluginDependency</string>
+					<string>19.IBPluginDependency</string>
+					<string>2.IBPluginDependency</string>
+					<string>20.IBPluginDependency</string>
+					<string>21.IBPluginDependency</string>
+					<string>22.IBPluginDependency</string>
+					<string>24.IBPluginDependency</string>
+					<string>25.IBPluginDependency</string>
+					<string>27.IBPluginDependency</string>
+					<string>28.IBPluginDependency</string>
+					<string>29.IBPluginDependency</string>
+					<string>3.IBPluginDependency</string>
+					<string>30.IBPluginDependency</string>
+					<string>31.IBPluginDependency</string>
+					<string>32.IBPluginDependency</string>
+					<string>35.IBPluginDependency</string>
+					<string>36.IBPluginDependency</string>
+					<string>4.IBPluginDependency</string>
+					<string>5.IBPluginDependency</string>
+					<string>6.IBPluginDependency</string>
+					<string>60.IBPluginDependency</string>
+					<string>61.IBPluginDependency</string>
+					<string>62.IBPluginDependency</string>
+					<string>63.IBPluginDependency</string>
+					<string>64.IBPluginDependency</string>
+					<string>65.IBPluginDependency</string>
+					<string>66.IBPluginDependency</string>
+					<string>67.IBPluginDependency</string>
+					<string>68.IBPluginDependency</string>
+					<string>69.IBPluginDependency</string>
+					<string>7.IBPluginDependency</string>
+					<string>8.IBPluginDependency</string>
+					<string>83.IBPluginDependency</string>
+					<string>84.IBPluginDependency</string>
+					<string>85.IBPluginDependency</string>
+					<string>86.IBPluginDependency</string>
+					<string>87.IBPluginDependency</string>
+					<string>9.IBPluginDependency</string>
+				</object>
+				<object class="NSMutableArray" key="dict.values">
+					<bool key="EncodedWithXMLCoder">YES</bool>
+					<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
+					<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
+					<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
+					<string>{{78, 307}, {527, 498}}</string>
+					<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
+					<string>{{78, 307}, {527, 498}}</string>
+					<reference ref="9"/>
+					<string>{196, 240}</string>
+					<string>{{357, 418}, {480, 270}}</string>
+					<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
+					<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
+					<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
+					<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
+					<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
+					<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
+					<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
+					<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
+					<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
+					<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
+					<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
+					<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
+					<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
+					<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
+					<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
+					<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
+					<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
+					<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
+					<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
+					<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
+					<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
+					<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
+					<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
+					<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
+					<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
+					<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
+					<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
+					<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
+					<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
+					<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
+					<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
+					<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
+					<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
+					<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
+					<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
+					<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
+					<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
+					<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
+					<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
+					<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
+					<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
+					<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
+					<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
+					<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
+					<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
+					<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
+					<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
+					<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
+					<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
+					<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
+					<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
+					<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
+					<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
+					<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
+				</object>
+			</object>
+			<object class="NSMutableDictionary" key="unlocalizedProperties">
+				<bool key="EncodedWithXMLCoder">YES</bool>
+				<object class="NSArray" key="dict.sortedKeys">
+					<bool key="EncodedWithXMLCoder">YES</bool>
+				</object>
+				<object class="NSMutableArray" key="dict.values">
+					<bool key="EncodedWithXMLCoder">YES</bool>
+				</object>
+			</object>
+			<nil key="activeLocalization"/>
+			<object class="NSMutableDictionary" key="localizations">
+				<bool key="EncodedWithXMLCoder">YES</bool>
+				<object class="NSArray" key="dict.sortedKeys">
+					<bool key="EncodedWithXMLCoder">YES</bool>
+				</object>
+				<object class="NSMutableArray" key="dict.values">
+					<bool key="EncodedWithXMLCoder">YES</bool>
+				</object>
+			</object>
+			<nil key="sourceID"/>
+			<int key="maxID">172</int>
+		</object>
+		<object class="IBClassDescriber" key="IBDocument.Classes">
+			<object class="NSMutableArray" key="referencedPartialClassDescriptions">
+				<bool key="EncodedWithXMLCoder">YES</bool>
+				<object class="IBPartialClassDescription">
+					<string key="className">LoanController</string>
+					<object class="NSMutableDictionary" key="actions">
+						<string key="NS.key.0">buttonPushed:</string>
+						<string key="NS.object.0">id</string>
+					</object>
+					<object class="NSMutableDictionary" key="outlets">
+						<bool key="EncodedWithXMLCoder">YES</bool>
+						<object class="NSMutableArray" key="dict.sortedKeys">
+							<bool key="EncodedWithXMLCoder">YES</bool>
+							<string>durSlider</string>
+							<string>durText</string>
+							<string>intSlider</string>
+							<string>intText</string>
+							<string>loanText</string>
+							<string>origDateText</string>
+							<string>paySlider</string>
+							<string>payText</string>
+							<string>window</string>
+						</object>
+						<object class="NSMutableArray" key="dict.values">
+							<bool key="EncodedWithXMLCoder">YES</bool>
+							<string>id</string>
+							<string>id</string>
+							<string>id</string>
+							<string>id</string>
+							<string>id</string>
+							<string>id</string>
+							<string>id</string>
+							<string>id</string>
+							<string>id</string>
+						</object>
+					</object>
+					<object class="IBClassDescriptionSource" key="sourceIdentifier">
+						<string key="majorKey">IBUserSource</string>
+						<string key="minorKey"/>
+					</object>
+				</object>
+				<object class="IBPartialClassDescription">
+					<string key="className">NSMatrix</string>
+					<string key="superclassName">NSControl</string>
+					<object class="IBClassDescriptionSource" key="sourceIdentifier">
+						<string key="majorKey">IBUserSource</string>
+						<string key="minorKey"/>
+					</object>
+				</object>
+			</object>
+		</object>
+		<int key="IBDocument.localizationMode">0</int>
+		<nil key="IBDocument.LastKnownRelativeProjectPath"/>
+		<int key="IBDocument.defaultPropertyAccessControl">3</int>
+	</data>
+</archive>
Index: /trunk/contrib/krueger/InterfaceProjects/Menu/menu-utils.lisp
===================================================================
--- /trunk/contrib/krueger/InterfaceProjects/Menu/menu-utils.lisp	(revision 13946)
+++ /trunk/contrib/krueger/InterfaceProjects/Menu/menu-utils.lisp	(revision 13946)
@@ -0,0 +1,165 @@
+;; menu-uitls.lisp
+
+#|
+The MIT license.
+
+Copyright (c) 2010 Paul L. Krueger
+
+Permission is hereby granted, free of charge, to any person obtaining a copy of this software 
+and associated documentation files (the "Software"), to deal in the Software without restriction, 
+including without limitation the rights to use, copy, modify, merge, publish, distribute, 
+sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is 
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all copies or substantial 
+portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT 
+LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. 
+IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, 
+WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE 
+SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+|#
+
+(eval-when (:compile-toplevel :load-toplevel :execute)
+  (require :selector-utils))
+
+(defpackage :interface-utilities
+  (:nicknames :iu)
+  (:export make-and-install-menu make-and-install-menuitems-after 
+           test-menu test2-menu))
+
+(in-package :iu)
+
+;; Utility functions that allow lisp programs to add menus to the existing menubar
+
+#|
+(defun make-menu-item (title-str action-str &key (key-equiv ""))
+  (let* ((ns-title (ccl::%make-nsstring name-str))
+         (action-selector (get-selector action-str))
+         (ns-key (ccl::%make-nsstring key-equiv))
+         (mi (#/initWithTitle:action:keyEquivalent: 
+              (#/alloc ns:ns-menu-item) 
+              ns-title 
+              action-selector
+              ns-key)))
+    (#/autorelease ns-title)
+    (#/autorelease ns-key)
+    (#/autorelease mi)
+    mi))
+
+|#
+
+;; For the following function menu-item-specs should be a list where each
+;; element of the list is itself a list of the form:
+;;  (menu-item-name menu-item-action menu-item-key-equivalent menu-item-target)
+;; where each of these except the menu-item-target must be acceptable as an 
+;; argument to the function "string". Menu-item-target must be an Ojbective-C object,
+;; but can be nil to signify no target (the default)
+;; Used "menumadness" sample code from Apple Developer website to know what to do ...
+;;    NSMenu *newMenu;
+;;    NSMenuItem *newItem;
+;;
+;;    // Add the submenu
+;;    newItem = [[NSMenuItem allocWithZone:[NSMenu menuZone]] initWithTitle:@"Flashy" action:NULL keyEquivalent:@""];
+;;    newMenu = [[NSMenu allocWithZone:[NSMenu menuZone]] initWithTitle:@"Flashy"];
+;;    [newItem setSubmenu:newMenu];
+;;    [newMenu release];
+;;    [[NSApp mainMenu] addItem:newItem];
+;;    [newItem release];
+;;  Basically you need to create both a menuitem and a menu for any menu displayed in the menubar
+;;  and link them together. Then add the menuitem to the main menu (i.e. menubar)
+
+(defun make-and-install-menu (menu-name &rest menu-item-specs)
+  (let* ((ns-menu-name (ccl::%make-nsstring menu-name))
+         (menuitem (#/initWithTitle:action:keyEquivalent: 
+                    (#/allocWithZone: ns:ns-menu-item 
+                                      (#/menuZone ns:ns-menu))
+                    ns-menu-name
+                    (%null-ptr)
+                    #@""))
+         (menu (#/initWithTitle: (#/allocWithZone: 
+                                  ns:ns-menu (#/menuZone ns:ns-menu))
+                                 ns-menu-name))
+         (main-menu (#/mainMenu #&NSApp)))
+    (dolist (mi menu-item-specs)
+      (destructuring-bind (mi-title mi-selector &optional (mi-key "") mi-target) mi
+        (let* ((ns-title (ccl::%make-nsstring (string mi-title)))
+               (action-selector (get-selector (string mi-selector)))
+               (ns-key (ccl::%make-nsstring (string mi-key)))
+               (men-item (#/addItemWithTitle:action:keyEquivalent: menu 
+                                                                   ns-title 
+                                                                   action-selector
+                                                                   ns-key)))
+          (when mi-target
+            (#/setTarget: men-item mi-target))
+          (#/release ns-title)
+          (#/release ns-key))))
+    ;; Link up the new menuitem and new menu
+    (#/setSubmenu: menuitem menu)
+    (#/release menu)
+    ;; Now tell the main menu to make this a sub-menu
+    (#/addItem: main-menu menuitem)
+    (#/release ns-menu-name)
+    (#/release menuitem)
+    menu))
+
+;; The following function inserts one or more new menu-items immediately 
+;; following a specified menu-item.
+;; If the menu-item-name is "" the insertion will be after the first divider
+;; (which has a blank name). If the menu-item-name does not exist in the menu,
+;;  the items will be placed at the beginning of the menu.
+;; menu-item-specs are as defined above for the make-and-install-menu function.
+;; menu-name and menu-item-name arguments must be acceptable as argument to the 
+;; "string" function.
+(defun make-and-install-menuitems-after (menu-name menu-item-name &rest menu-item-specs)
+  (let* ((ns-menu-name (ccl::%make-nsstring menu-name))
+         (main-menu (#/mainMenu #&NSApp))
+         (menuitem (or (#/itemWithTitle: main-menu ns-menu-name) 
+                       (error "~s is not a valid menu title" menu-name)))
+         (sub-menu (#/submenu menuitem))
+         (ns-menu-item-name (ccl::%make-nsstring menu-item-name))
+         (insert-index (#/indexOfItemWithTitle: sub-menu ns-menu-item-name)))
+    (dolist (mi menu-item-specs)
+      (destructuring-bind (mi-title mi-selector &optional (mi-key "") mi-target) mi
+        (let* ((ns-title (ccl::%make-nsstring (string mi-title)))
+               (action-selector (get-selector (string mi-selector)))
+               (ns-key (ccl::%make-nsstring (string mi-key)))
+               (men-item (#/insertItemWithTitle:action:keyEquivalent:atIndex: 
+                          sub-menu 
+                          ns-title 
+                          action-selector
+                          ns-key
+                          (incf insert-index))))
+          (when mi-target
+            (#/setTarget: men-item mi-target))
+          (#/release ns-title)
+          (#/release ns-key))))
+    (#/release ns-menu-item-name)
+    (#/release ns-menu-name)))
+
+(defun menu-item-action-selector (menu-name menu-item-name)
+  (let* ((ns-menu-name (ccl::%make-nsstring menu-name))
+         (main-menu (#/mainMenu #&NSApp))
+         (menuitem (or (#/itemWithTitle: main-menu ns-menu-name) 
+                       (error "~s is not a valid menu title" menu-name)))
+         (sub-menu (#/submenu menuitem))
+         (ns-menu-item-name (ccl::%make-nsstring menu-item-name))
+         (target-mi (#/itemWithTitle: sub-menu ns-menu-item-name)))
+    (#/release ns-menu-item-name)
+    (#/release ns-menu-name)
+    (#/action target-mi)))
+
+
+(defun test-menu ()
+  (make-and-install-menu "New App Menu" 
+                         '("Menu Item1" "doFirstThing")
+                         '("Menu Item2" "doSecondThing")))
+
+(defun test2-menu ()
+  (make-and-install-menuitems-after "File" "New"
+                                    '("New myDoc" "newMyDoc")))
+                                         
+
+(provide :menu-utils)
Index: /trunk/contrib/krueger/InterfaceProjects/PackageView/package-view.lisp
===================================================================
--- /trunk/contrib/krueger/InterfaceProjects/PackageView/package-view.lisp	(revision 13946)
+++ /trunk/contrib/krueger/InterfaceProjects/PackageView/package-view.lisp	(revision 13946)
@@ -0,0 +1,176 @@
+;;; package-view.lisp
+
+#|
+The MIT license.
+
+Copyright (c) 2010 Paul L. Krueger
+
+Permission is hereby granted, free of charge, to any person obtaining a copy of this software 
+and associated documentation files (the "Software"), to deal in the Software without restriction, 
+including without limitation the rights to use, copy, modify, merge, publish, distribute, 
+sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is 
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all copies or substantial 
+portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT 
+LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. 
+IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, 
+WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE 
+SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+|#
+
+(eval-when (:compile-toplevel :load-toplevel :execute)
+  (require :nib))
+
+(defpackage :package-view
+  (:nicknames :pv)
+  (:use :ccl :common-lisp)
+  (:export test-package))
+
+(in-package :pv)
+
+;;; Sample lisp/Cocoa interface that uses a NIB file defined with interface builder;
+;;; A definition is provided for the "SpeechController" class that was specified to interface builder
+;;; as the class of the NIB file owner.
+;;; We manually create an instance of SpeechController and specify it as the owner for the NIB file.
+
+(defclass package-view-controller (ns:ns-object)
+  ((package-table :foreign-type :id :accessor package-table)
+   (use-table :foreign-type :id :accessor use-table)
+   (used-by-table :foreign-type :id :accessor used-by-table)
+   (current-package :accessor current-package :initform nil)
+   (current-nicknames :accessor current-nicknames :initform nil)
+   (all-packages :accessor all-packages :initform nil)
+   (current-package-use-list :accessor current-package-use-list :initform nil)
+   (current-package-used-by-list :accessor current-package-used-by-list :initform nil)
+   (window-controller :accessor window-controller :initform nil))
+  (:metaclass ns:+ns-object))
+
+(defmethod initialize-instance :after ((self package-view-controller) 
+                                       &key &allow-other-keys)
+  (let ((pkgs (list-all-packages)))
+    (setf (all-packages self) (make-array (list (list-length pkgs)) 
+                                          :initial-contents pkgs)))
+  (let ((nib-name (ccl::%make-nsstring 
+                   (namestring (truename "ip:PackageView;packageview.nib")))))
+    (setf (window-controller self)
+          (make-instance ns:ns-window-controller
+            :with-window-nib-path nib-name
+            :owner self))
+    ;; Now make the controller load the nib file and make the window visible
+    (#/window (window-controller self))
+    (#/release nib-name))
+  ;; we do the following so that ccl:terminate will be called before we are garbage
+  ;; collected and we can release the window-controller that we created
+  (ccl:terminate-when-unreachable self))
+
+(defmethod ccl:terminate ((self package-view-controller))
+  (#/release (window-controller self)))
+
+;; Initialization methods called when the nib file is loaded
+;; These initialize links from this package-view-controller to the text-views we defined 
+;; to display things. Names correspond to the outlet names we defined for the 
+;; PackageViewController class as file-owner in IB.
+
+(objc:defmethod (#/setPackageTable: :void) 
+                ((self package-view-controller) (tab :id))
+  (setf (package-table self) tab)
+  ;; Table may already have initialized before this link was set. Tell it to reload 
+  ;; just in case.
+  (#/reloadData tab))
+
+(objc:defmethod (#/setUseTable: :void) 
+                ((self package-view-controller) (tab :id))
+  (setf (use-table self) tab)
+  ;; Table may already have initialized before this link was set. Tell it to reload 
+  ;; just in case
+  (#/reloadData tab))
+
+(objc:defmethod (#/setUseByTable: :void) 
+                ((self package-view-controller) (tab :id))
+  (setf (used-by-table self) tab)
+  ;; Table may already have initialized before this link was set. Tell it to reload just in case
+  (#/reloadData tab))
+
+;; Methods called because we linked this class (as file owner) via the data-source outlet for 
+;; our text views in IB
+
+(objc:defmethod (#/numberOfRowsInTableView: #>NSInteger) 
+                ((self package-view-controller) (tab :id))
+  (cond ((eql tab (package-table self))
+         (array-dimension (all-packages self) 0))
+        ((eql tab (use-table self))
+         (if (current-package-use-list self)
+           (array-dimension (current-package-use-list self) 0)
+           0))
+        ((eql tab (used-by-table self))
+         (if (current-package-used-by-list self)
+           (array-dimension (current-package-used-by-list self) 0)
+           0))
+        (t
+         ;; We can get called before the links are initialized. If so, return 0
+         0)))
+  
+(objc:defmethod (#/tableView:objectValueForTableColumn:row: :id) 
+                ((self package-view-controller) 
+                 (tab :id)
+                 (col :id)
+                 (row #>NSInteger))
+  (let ((ret-str nil))
+    (cond ((eql tab (package-table self))
+           (let ((col-id (ccl::lisp-string-from-nsstring (#/identifier col))))
+             (setf ret-str (ccl::%make-nsstring 
+                            (if (string= col-id "1") 
+                              (package-name (svref (all-packages self) row))
+                              (format nil 
+                                      "~{~a~^,~}" 
+                                      (package-nicknames 
+                                       (svref (all-packages self) row))))))))
+          ((eql tab (use-table self))
+           (setf ret-str (ccl::%make-nsstring 
+                          (if (current-package-use-list self)
+                            (package-name (svref (current-package-use-list self) row))
+                            ""))))
+          ((eql tab (used-by-table self))
+           (setf ret-str (ccl::%make-nsstring 
+                          (if (current-package-used-by-list self)
+                            (package-name (svref (current-package-used-by-list self) row))
+                            ""))))
+          (t
+           (error "~s is not a linked view (~s, ~s, or ~s)" 
+                  tab
+                  (package-table self)
+                  (use-table self)
+                  (used-by-table self))))
+    (#/autorelease ret-str)
+    ret-str))
+
+;; Methods called because we linked this class (as file owner) via the text-view delegate outlets in IB
+
+
+(objc:defmethod (#/tableViewSelectionDidChange: :void) 
+                ((self package-view-controller) (notif :id))
+  (let ((tab (#/object notif)))
+    (when (eql tab (package-table self))
+      ;; change the other two tables to reflect the package selected
+      (let* ((pkg (svref (all-packages self) (#/selectedRow (package-table self))))
+             (pkgs-used (package-use-list pkg))
+             (pkgs-using (package-used-by-list pkg)))
+        (setf (current-package-use-list self)
+              (make-array (list (list-length pkgs-used)) :initial-contents pkgs-used))
+        (setf (current-package-used-by-list self)
+              (make-array (list (list-length pkgs-using)) :initial-contents pkgs-using))
+        (#/reloadData (use-table self))
+        (#/reloadData (used-by-table self))))))
+  
+
+;; Methods called because we linked this class (as file owner) via the Window delegate outlet in IB
+
+;; test by
+(defun test-package ()
+  (make-instance 'package-view-controller))
+
+(provide :package-view)
Index: /trunk/contrib/krueger/InterfaceProjects/PackageView/packageview.nib/designable.nib
===================================================================
--- /trunk/contrib/krueger/InterfaceProjects/PackageView/packageview.nib/designable.nib	(revision 13946)
+++ /trunk/contrib/krueger/InterfaceProjects/PackageView/packageview.nib/designable.nib	(revision 13946)
@@ -0,0 +1,934 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<archive type="com.apple.InterfaceBuilder3.Cocoa.XIB" version="7.03">
+	<data>
+		<int key="IBDocument.SystemTarget">1050</int>
+		<string key="IBDocument.SystemVersion">9L30</string>
+		<string key="IBDocument.InterfaceBuilderVersion">680</string>
+		<string key="IBDocument.AppKitVersion">949.54</string>
+		<string key="IBDocument.HIToolboxVersion">353.00</string>
+		<object class="NSMutableArray" key="IBDocument.EditedObjectIDs">
+			<bool key="EncodedWithXMLCoder">YES</bool>
+			<integer value="22"/>
+		</object>
+		<object class="NSArray" key="IBDocument.PluginDependencies">
+			<bool key="EncodedWithXMLCoder">YES</bool>
+			<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
+		</object>
+		<object class="NSMutableDictionary" key="IBDocument.Metadata">
+			<bool key="EncodedWithXMLCoder">YES</bool>
+			<object class="NSArray" key="dict.sortedKeys">
+				<bool key="EncodedWithXMLCoder">YES</bool>
+			</object>
+			<object class="NSMutableArray" key="dict.values">
+				<bool key="EncodedWithXMLCoder">YES</bool>
+			</object>
+		</object>
+		<object class="NSMutableArray" key="IBDocument.RootObjects" id="1000">
+			<bool key="EncodedWithXMLCoder">YES</bool>
+			<object class="NSCustomObject" id="1001">
+				<string key="NSClassName">PackageViewController</string>
+			</object>
+			<object class="NSCustomObject" id="1003">
+				<string key="NSClassName">FirstResponder</string>
+			</object>
+			<object class="NSCustomObject" id="1004">
+				<string key="NSClassName">NSApplication</string>
+			</object>
+			<object class="NSWindowTemplate" id="1005">
+				<int key="NSWindowStyleMask">15</int>
+				<int key="NSWindowBacking">2</int>
+				<string key="NSWindowRect">{{196, -10}, {555, 520}}</string>
+				<int key="NSWTFlags">536870912</int>
+				<string key="NSWindowTitle">Lisp Packages</string>
+				<string key="NSWindowClass">NSWindow</string>
+				<nil key="NSViewClass"/>
+				<string key="NSWindowContentMaxSize">{3.40282e+38, 3.40282e+38}</string>
+				<object class="NSView" key="NSWindowView" id="1006">
+					<reference key="NSNextResponder"/>
+					<int key="NSvFlags">256</int>
+					<object class="NSMutableArray" key="NSSubviews">
+						<bool key="EncodedWithXMLCoder">YES</bool>
+						<object class="NSScrollView" id="846347810">
+							<reference key="NSNextResponder" ref="1006"/>
+							<int key="NSvFlags">286</int>
+							<object class="NSMutableArray" key="NSSubviews">
+								<bool key="EncodedWithXMLCoder">YES</bool>
+								<object class="NSClipView" id="815089046">
+									<reference key="NSNextResponder" ref="846347810"/>
+									<int key="NSvFlags">2304</int>
+									<object class="NSMutableArray" key="NSSubviews">
+										<bool key="EncodedWithXMLCoder">YES</bool>
+										<object class="NSTableView" id="605849626">
+											<reference key="NSNextResponder" ref="815089046"/>
+											<int key="NSvFlags">256</int>
+											<string key="NSFrameSize">{482, 179}</string>
+											<reference key="NSSuperview" ref="815089046"/>
+											<bool key="NSEnabled">YES</bool>
+											<object class="NSTableHeaderView" key="NSHeaderView" id="504164402">
+												<reference key="NSNextResponder" ref="133322094"/>
+												<int key="NSvFlags">256</int>
+												<string key="NSFrameSize">{482, 17}</string>
+												<reference key="NSSuperview" ref="133322094"/>
+												<reference key="NSTableView" ref="605849626"/>
+											</object>
+											<object class="_NSCornerView" key="NSCornerView" id="900301141">
+												<reference key="NSNextResponder" ref="846347810"/>
+												<int key="NSvFlags">256</int>
+												<string key="NSFrame">{{483, 0}, {16, 17}}</string>
+												<reference key="NSSuperview" ref="846347810"/>
+											</object>
+											<object class="NSMutableArray" key="NSTableColumns">
+												<bool key="EncodedWithXMLCoder">YES</bool>
+												<object class="NSTableColumn" id="997458089">
+													<string key="NSIdentifier">1</string>
+													<double key="NSWidth">1.680000e+02</double>
+													<double key="NSMinWidth">4.000000e+01</double>
+													<double key="NSMaxWidth">1.000000e+03</double>
+													<object class="NSTableHeaderCell" key="NSHeaderCell">
+														<int key="NSCellFlags">75628032</int>
+														<int key="NSCellFlags2">0</int>
+														<string key="NSContents">Package</string>
+														<object class="NSFont" key="NSSupport" id="26">
+															<string key="NSName">LucidaGrande</string>
+															<double key="NSSize">1.100000e+01</double>
+															<int key="NSfFlags">3100</int>
+														</object>
+														<object class="NSColor" key="NSBackgroundColor" id="733068830">
+															<int key="NSColorSpace">3</int>
+															<bytes key="NSWhite">MC4zMzMzMzI5OQA</bytes>
+														</object>
+														<object class="NSColor" key="NSTextColor" id="245962408">
+															<int key="NSColorSpace">6</int>
+															<string key="NSCatalogName">System</string>
+															<string key="NSColorName">headerTextColor</string>
+															<object class="NSColor" key="NSColor" id="385811266">
+																<int key="NSColorSpace">3</int>
+																<bytes key="NSWhite">MAA</bytes>
+															</object>
+														</object>
+													</object>
+													<object class="NSTextFieldCell" key="NSDataCell" id="542099181">
+														<int key="NSCellFlags">69336641</int>
+														<int key="NSCellFlags2">2048</int>
+														<string key="NSContents">Text Cell</string>
+														<object class="NSFont" key="NSSupport" id="111849803">
+															<string key="NSName">LucidaGrande</string>
+															<double key="NSSize">1.300000e+01</double>
+															<int key="NSfFlags">1044</int>
+														</object>
+														<reference key="NSControlView" ref="605849626"/>
+														<object class="NSColor" key="NSBackgroundColor" id="292773639">
+															<int key="NSColorSpace">6</int>
+															<string key="NSCatalogName">System</string>
+															<string key="NSColorName">controlBackgroundColor</string>
+															<object class="NSColor" key="NSColor">
+																<int key="NSColorSpace">3</int>
+																<bytes key="NSWhite">MC42NjY2NjY2OQA</bytes>
+															</object>
+														</object>
+														<object class="NSColor" key="NSTextColor" id="750309214">
+															<int key="NSColorSpace">6</int>
+															<string key="NSCatalogName">System</string>
+															<string key="NSColorName">controlTextColor</string>
+															<reference key="NSColor" ref="385811266"/>
+														</object>
+													</object>
+													<int key="NSResizingMask">3</int>
+													<bool key="NSIsResizeable">YES</bool>
+													<bool key="NSIsEditable">YES</bool>
+													<reference key="NSTableView" ref="605849626"/>
+												</object>
+												<object class="NSTableColumn" id="461325047">
+													<string key="NSIdentifier">2</string>
+													<double key="NSWidth">3.080000e+02</double>
+													<double key="NSMinWidth">4.000000e+01</double>
+													<double key="NSMaxWidth">1.000000e+03</double>
+													<object class="NSTableHeaderCell" key="NSHeaderCell">
+														<int key="NSCellFlags">75628032</int>
+														<int key="NSCellFlags2">0</int>
+														<string key="NSContents">Nicknames</string>
+														<reference key="NSSupport" ref="26"/>
+														<reference key="NSBackgroundColor" ref="733068830"/>
+														<reference key="NSTextColor" ref="245962408"/>
+													</object>
+													<object class="NSTextFieldCell" key="NSDataCell" id="309525533">
+														<int key="NSCellFlags">67239488</int>
+														<int key="NSCellFlags2">2048</int>
+														<string key="NSContents">Text Cell</string>
+														<reference key="NSSupport" ref="111849803"/>
+														<reference key="NSControlView" ref="605849626"/>
+														<reference key="NSBackgroundColor" ref="292773639"/>
+														<reference key="NSTextColor" ref="750309214"/>
+													</object>
+													<int key="NSResizingMask">3</int>
+													<bool key="NSIsResizeable">YES</bool>
+													<bool key="NSIsEditable">YES</bool>
+													<reference key="NSTableView" ref="605849626"/>
+												</object>
+											</object>
+											<double key="NSIntercellSpacingWidth">3.000000e+00</double>
+											<double key="NSIntercellSpacingHeight">2.000000e+00</double>
+											<object class="NSColor" key="NSBackgroundColor" id="907658559">
+												<int key="NSColorSpace">3</int>
+												<bytes key="NSWhite">MQA</bytes>
+											</object>
+											<object class="NSColor" key="NSGridColor" id="678234468">
+												<int key="NSColorSpace">6</int>
+												<string key="NSCatalogName">System</string>
+												<string key="NSColorName">gridColor</string>
+												<object class="NSColor" key="NSColor">
+													<int key="NSColorSpace">3</int>
+													<bytes key="NSWhite">MC41AA</bytes>
+												</object>
+											</object>
+											<double key="NSRowHeight">1.700000e+01</double>
+											<int key="NSTvFlags">-700448768</int>
+											<int key="NSColumnAutoresizingStyle">4</int>
+											<int key="NSDraggingSourceMaskForLocal">15</int>
+											<int key="NSDraggingSourceMaskForNonLocal">0</int>
+											<bool key="NSAllowsTypeSelect">YES</bool>
+										</object>
+									</object>
+									<string key="NSFrame">{{1, 17}, {482, 179}}</string>
+									<reference key="NSSuperview" ref="846347810"/>
+									<reference key="NSNextKeyView" ref="605849626"/>
+									<reference key="NSDocView" ref="605849626"/>
+									<reference key="NSBGColor" ref="292773639"/>
+									<int key="NScvFlags">4</int>
+								</object>
+								<object class="NSScroller" id="423958127">
+									<reference key="NSNextResponder" ref="846347810"/>
+									<int key="NSvFlags">256</int>
+									<string key="NSFrame">{{483, 17}, {15, 179}}</string>
+									<reference key="NSSuperview" ref="846347810"/>
+									<reference key="NSTarget" ref="846347810"/>
+									<string key="NSAction">_doScroller:</string>
+									<double key="NSCurValue">3.700000e+01</double>
+									<double key="NSPercent">1.947368e-01</double>
+								</object>
+								<object class="NSScroller" id="162292652">
+									<reference key="NSNextResponder" ref="846347810"/>
+									<int key="NSvFlags">256</int>
+									<string key="NSFrame">{{1, 196}, {482, 15}}</string>
+									<reference key="NSSuperview" ref="846347810"/>
+									<int key="NSsFlags">1</int>
+									<reference key="NSTarget" ref="846347810"/>
+									<string key="NSAction">_doScroller:</string>
+									<double key="NSPercent">9.979716e-01</double>
+								</object>
+								<object class="NSClipView" id="133322094">
+									<reference key="NSNextResponder" ref="846347810"/>
+									<int key="NSvFlags">2304</int>
+									<object class="NSMutableArray" key="NSSubviews">
+										<bool key="EncodedWithXMLCoder">YES</bool>
+										<reference ref="504164402"/>
+									</object>
+									<string key="NSFrame">{{1, 0}, {482, 17}}</string>
+									<reference key="NSSuperview" ref="846347810"/>
+									<reference key="NSNextKeyView" ref="504164402"/>
+									<reference key="NSDocView" ref="504164402"/>
+									<reference key="NSBGColor" ref="292773639"/>
+									<int key="NScvFlags">4</int>
+								</object>
+								<reference ref="900301141"/>
+							</object>
+							<string key="NSFrame">{{26, 288}, {499, 212}}</string>
+							<reference key="NSSuperview" ref="1006"/>
+							<reference key="NSNextKeyView" ref="815089046"/>
+							<int key="NSsFlags">50</int>
+							<reference key="NSVScroller" ref="423958127"/>
+							<reference key="NSHScroller" ref="162292652"/>
+							<reference key="NSContentView" ref="815089046"/>
+							<reference key="NSHeaderClipView" ref="133322094"/>
+							<reference key="NSCornerView" ref="900301141"/>
+							<bytes key="NSScrollAmts">QSAAAEEgAABBmAAAQZgAAA</bytes>
+						</object>
+						<object class="NSScrollView" id="873949528">
+							<reference key="NSNextResponder" ref="1006"/>
+							<int key="NSvFlags">310</int>
+							<object class="NSMutableArray" key="NSSubviews">
+								<bool key="EncodedWithXMLCoder">YES</bool>
+								<object class="NSClipView" id="816190321">
+									<reference key="NSNextResponder" ref="873949528"/>
+									<int key="NSvFlags">2304</int>
+									<object class="NSMutableArray" key="NSSubviews">
+										<bool key="EncodedWithXMLCoder">YES</bool>
+										<object class="NSTableView" id="1039136029">
+											<reference key="NSNextResponder" ref="816190321"/>
+											<int key="NSvFlags">256</int>
+											<string key="NSFrameSize">{217, 222}</string>
+											<reference key="NSSuperview" ref="816190321"/>
+											<bool key="NSEnabled">YES</bool>
+											<object class="NSTableHeaderView" key="NSHeaderView" id="534528862">
+												<reference key="NSNextResponder" ref="66694854"/>
+												<int key="NSvFlags">256</int>
+												<string key="NSFrameSize">{217, 17}</string>
+												<reference key="NSSuperview" ref="66694854"/>
+												<reference key="NSTableView" ref="1039136029"/>
+											</object>
+											<object class="_NSCornerView" key="NSCornerView" id="201674147">
+												<reference key="NSNextResponder" ref="873949528"/>
+												<int key="NSvFlags">256</int>
+												<string key="NSFrame">{{218, 0}, {16, 17}}</string>
+												<reference key="NSSuperview" ref="873949528"/>
+											</object>
+											<object class="NSMutableArray" key="NSTableColumns">
+												<bool key="EncodedWithXMLCoder">YES</bool>
+												<object class="NSTableColumn" id="120650054">
+													<double key="NSWidth">2.140000e+02</double>
+													<double key="NSMinWidth">4.000000e+01</double>
+													<double key="NSMaxWidth">1.000000e+03</double>
+													<object class="NSTableHeaderCell" key="NSHeaderCell">
+														<int key="NSCellFlags">75628032</int>
+														<int key="NSCellFlags2">0</int>
+														<string key="NSContents">Package Use List</string>
+														<reference key="NSSupport" ref="26"/>
+														<object class="NSColor" key="NSBackgroundColor">
+															<int key="NSColorSpace">3</int>
+															<bytes key="NSWhite">MC4zMzMzMzI5OQA</bytes>
+														</object>
+														<reference key="NSTextColor" ref="245962408"/>
+													</object>
+													<object class="NSTextFieldCell" key="NSDataCell" id="788058591">
+														<int key="NSCellFlags">67239488</int>
+														<int key="NSCellFlags2">2048</int>
+														<string key="NSContents">Text Cell</string>
+														<reference key="NSSupport" ref="111849803"/>
+														<reference key="NSControlView" ref="1039136029"/>
+														<reference key="NSBackgroundColor" ref="292773639"/>
+														<reference key="NSTextColor" ref="750309214"/>
+													</object>
+													<int key="NSResizingMask">3</int>
+													<bool key="NSIsResizeable">YES</bool>
+													<reference key="NSTableView" ref="1039136029"/>
+												</object>
+											</object>
+											<double key="NSIntercellSpacingWidth">3.000000e+00</double>
+											<double key="NSIntercellSpacingHeight">2.000000e+00</double>
+											<reference key="NSBackgroundColor" ref="907658559"/>
+											<reference key="NSGridColor" ref="678234468"/>
+											<double key="NSRowHeight">1.700000e+01</double>
+											<int key="NSTvFlags">-767557632</int>
+											<int key="NSColumnAutoresizingStyle">4</int>
+											<int key="NSDraggingSourceMaskForLocal">15</int>
+											<int key="NSDraggingSourceMaskForNonLocal">0</int>
+											<bool key="NSAllowsTypeSelect">NO</bool>
+										</object>
+									</object>
+									<string key="NSFrame">{{1, 17}, {217, 222}}</string>
+									<reference key="NSSuperview" ref="873949528"/>
+									<reference key="NSNextKeyView" ref="1039136029"/>
+									<reference key="NSDocView" ref="1039136029"/>
+									<reference key="NSBGColor" ref="292773639"/>
+									<int key="NScvFlags">4</int>
+								</object>
+								<object class="NSScroller" id="599981709">
+									<reference key="NSNextResponder" ref="873949528"/>
+									<int key="NSvFlags">256</int>
+									<string key="NSFrame">{{218, 17}, {15, 222}}</string>
+									<reference key="NSSuperview" ref="873949528"/>
+									<reference key="NSTarget" ref="873949528"/>
+									<string key="NSAction">_doScroller:</string>
+									<double key="NSCurValue">3.700000e+01</double>
+									<double key="NSPercent">1.947368e-01</double>
+								</object>
+								<object class="NSScroller" id="961510052">
+									<reference key="NSNextResponder" ref="873949528"/>
+									<int key="NSvFlags">256</int>
+									<string key="NSFrame">{{1, 239}, {217, 15}}</string>
+									<reference key="NSSuperview" ref="873949528"/>
+									<int key="NSsFlags">1</int>
+									<reference key="NSTarget" ref="873949528"/>
+									<string key="NSAction">_doScroller:</string>
+									<double key="NSPercent">9.115646e-01</double>
+								</object>
+								<object class="NSClipView" id="66694854">
+									<reference key="NSNextResponder" ref="873949528"/>
+									<int key="NSvFlags">2304</int>
+									<object class="NSMutableArray" key="NSSubviews">
+										<bool key="EncodedWithXMLCoder">YES</bool>
+										<reference ref="534528862"/>
+									</object>
+									<string key="NSFrame">{{1, 0}, {217, 17}}</string>
+									<reference key="NSSuperview" ref="873949528"/>
+									<reference key="NSNextKeyView" ref="534528862"/>
+									<reference key="NSDocView" ref="534528862"/>
+									<reference key="NSBGColor" ref="292773639"/>
+									<int key="NScvFlags">4</int>
+								</object>
+								<reference ref="201674147"/>
+							</object>
+							<string key="NSFrame">{{26, 25}, {234, 255}}</string>
+							<reference key="NSSuperview" ref="1006"/>
+							<reference key="NSNextKeyView" ref="816190321"/>
+							<int key="NSsFlags">50</int>
+							<reference key="NSVScroller" ref="599981709"/>
+							<reference key="NSHScroller" ref="961510052"/>
+							<reference key="NSContentView" ref="816190321"/>
+							<reference key="NSHeaderClipView" ref="66694854"/>
+							<reference key="NSCornerView" ref="201674147"/>
+							<bytes key="NSScrollAmts">QSAAAEEgAABBmAAAQZgAAA</bytes>
+						</object>
+						<object class="NSScrollView" id="882692977">
+							<reference key="NSNextResponder" ref="1006"/>
+							<int key="NSvFlags">307</int>
+							<object class="NSMutableArray" key="NSSubviews">
+								<bool key="EncodedWithXMLCoder">YES</bool>
+								<object class="NSClipView" id="940621517">
+									<reference key="NSNextResponder" ref="882692977"/>
+									<int key="NSvFlags">2304</int>
+									<object class="NSMutableArray" key="NSSubviews">
+										<bool key="EncodedWithXMLCoder">YES</bool>
+										<object class="NSTableView" id="529258400">
+											<reference key="NSNextResponder" ref="940621517"/>
+											<int key="NSvFlags">256</int>
+											<string key="NSFrameSize">{223, 222}</string>
+											<reference key="NSSuperview" ref="940621517"/>
+											<bool key="NSEnabled">YES</bool>
+											<object class="NSTableHeaderView" key="NSHeaderView" id="123096532">
+												<reference key="NSNextResponder" ref="796045454"/>
+												<int key="NSvFlags">256</int>
+												<string key="NSFrameSize">{223, 17}</string>
+												<reference key="NSSuperview" ref="796045454"/>
+												<reference key="NSTableView" ref="529258400"/>
+											</object>
+											<object class="_NSCornerView" key="NSCornerView" id="163646568">
+												<reference key="NSNextResponder" ref="882692977"/>
+												<int key="NSvFlags">256</int>
+												<string key="NSFrame">{{224, 0}, {16, 17}}</string>
+												<reference key="NSSuperview" ref="882692977"/>
+											</object>
+											<object class="NSMutableArray" key="NSTableColumns">
+												<bool key="EncodedWithXMLCoder">YES</bool>
+												<object class="NSTableColumn" id="602298172">
+													<double key="NSWidth">2.200000e+02</double>
+													<double key="NSMinWidth">4.000000e+01</double>
+													<double key="NSMaxWidth">1.000000e+03</double>
+													<object class="NSTableHeaderCell" key="NSHeaderCell">
+														<int key="NSCellFlags">75628032</int>
+														<int key="NSCellFlags2">0</int>
+														<string key="NSContents">Package Used By List</string>
+														<reference key="NSSupport" ref="26"/>
+														<object class="NSColor" key="NSBackgroundColor">
+															<int key="NSColorSpace">3</int>
+															<bytes key="NSWhite">MC4zMzMzMzI5OQA</bytes>
+														</object>
+														<reference key="NSTextColor" ref="245962408"/>
+													</object>
+													<object class="NSTextFieldCell" key="NSDataCell" id="870958269">
+														<int key="NSCellFlags">67239488</int>
+														<int key="NSCellFlags2">2048</int>
+														<string key="NSContents">Text Cell</string>
+														<reference key="NSSupport" ref="111849803"/>
+														<reference key="NSControlView" ref="529258400"/>
+														<reference key="NSBackgroundColor" ref="292773639"/>
+														<reference key="NSTextColor" ref="750309214"/>
+													</object>
+													<int key="NSResizingMask">3</int>
+													<bool key="NSIsResizeable">YES</bool>
+													<reference key="NSTableView" ref="529258400"/>
+												</object>
+											</object>
+											<double key="NSIntercellSpacingWidth">3.000000e+00</double>
+											<double key="NSIntercellSpacingHeight">2.000000e+00</double>
+											<reference key="NSBackgroundColor" ref="907658559"/>
+											<reference key="NSGridColor" ref="678234468"/>
+											<double key="NSRowHeight">1.700000e+01</double>
+											<int key="NSTvFlags">-700448768</int>
+											<int key="NSColumnAutoresizingStyle">4</int>
+											<int key="NSDraggingSourceMaskForLocal">15</int>
+											<int key="NSDraggingSourceMaskForNonLocal">0</int>
+											<bool key="NSAllowsTypeSelect">YES</bool>
+										</object>
+									</object>
+									<string key="NSFrame">{{1, 17}, {223, 222}}</string>
+									<reference key="NSSuperview" ref="882692977"/>
+									<reference key="NSNextKeyView" ref="529258400"/>
+									<reference key="NSDocView" ref="529258400"/>
+									<reference key="NSBGColor" ref="292773639"/>
+									<int key="NScvFlags">4</int>
+								</object>
+								<object class="NSScroller" id="182370043">
+									<reference key="NSNextResponder" ref="882692977"/>
+									<int key="NSvFlags">256</int>
+									<string key="NSFrame">{{224, 17}, {15, 222}}</string>
+									<reference key="NSSuperview" ref="882692977"/>
+									<reference key="NSTarget" ref="882692977"/>
+									<string key="NSAction">_doScroller:</string>
+									<double key="NSCurValue">3.700000e+01</double>
+									<double key="NSPercent">1.947368e-01</double>
+								</object>
+								<object class="NSScroller" id="328005951">
+									<reference key="NSNextResponder" ref="882692977"/>
+									<int key="NSvFlags">256</int>
+									<string key="NSFrame">{{1, 239}, {223, 15}}</string>
+									<reference key="NSSuperview" ref="882692977"/>
+									<int key="NSsFlags">1</int>
+									<reference key="NSTarget" ref="882692977"/>
+									<string key="NSAction">_doScroller:</string>
+									<double key="NSPercent">9.455782e-01</double>
+								</object>
+								<object class="NSClipView" id="796045454">
+									<reference key="NSNextResponder" ref="882692977"/>
+									<int key="NSvFlags">2304</int>
+									<object class="NSMutableArray" key="NSSubviews">
+										<bool key="EncodedWithXMLCoder">YES</bool>
+										<reference ref="123096532"/>
+									</object>
+									<string key="NSFrame">{{1, 0}, {223, 17}}</string>
+									<reference key="NSSuperview" ref="882692977"/>
+									<reference key="NSNextKeyView" ref="123096532"/>
+									<reference key="NSDocView" ref="123096532"/>
+									<reference key="NSBGColor" ref="292773639"/>
+									<int key="NScvFlags">4</int>
+								</object>
+								<reference ref="163646568"/>
+							</object>
+							<string key="NSFrame">{{285, 25}, {240, 255}}</string>
+							<reference key="NSSuperview" ref="1006"/>
+							<reference key="NSNextKeyView" ref="940621517"/>
+							<int key="NSsFlags">50</int>
+							<reference key="NSVScroller" ref="182370043"/>
+							<reference key="NSHScroller" ref="328005951"/>
+							<reference key="NSContentView" ref="940621517"/>
+							<reference key="NSHeaderClipView" ref="796045454"/>
+							<reference key="NSCornerView" ref="163646568"/>
+							<bytes key="NSScrollAmts">QSAAAEEgAABBmAAAQZgAAA</bytes>
+						</object>
+					</object>
+					<string key="NSFrameSize">{555, 520}</string>
+					<reference key="NSSuperview"/>
+				</object>
+				<string key="NSScreenRect">{{0, 0}, {1680, 1028}}</string>
+				<string key="NSMaxSize">{3.40282e+38, 3.40282e+38}</string>
+			</object>
+		</object>
+		<object class="IBObjectContainer" key="IBDocument.Objects">
+			<object class="NSMutableArray" key="connectionRecords">
+				<bool key="EncodedWithXMLCoder">YES</bool>
+				<object class="IBConnectionRecord">
+					<object class="IBOutletConnection" key="connection">
+						<string key="label">packageTable</string>
+						<reference key="source" ref="1001"/>
+						<reference key="destination" ref="605849626"/>
+					</object>
+					<int key="connectionID">49</int>
+				</object>
+				<object class="IBConnectionRecord">
+					<object class="IBOutletConnection" key="connection">
+						<string key="label">useTable</string>
+						<reference key="source" ref="1001"/>
+						<reference key="destination" ref="1039136029"/>
+					</object>
+					<int key="connectionID">50</int>
+				</object>
+				<object class="IBConnectionRecord">
+					<object class="IBOutletConnection" key="connection">
+						<string key="label">usedByTable</string>
+						<reference key="source" ref="1001"/>
+						<reference key="destination" ref="529258400"/>
+					</object>
+					<int key="connectionID">51</int>
+				</object>
+				<object class="IBConnectionRecord">
+					<object class="IBOutletConnection" key="connection">
+						<string key="label">dataSource</string>
+						<reference key="source" ref="605849626"/>
+						<reference key="destination" ref="1001"/>
+					</object>
+					<int key="connectionID">52</int>
+				</object>
+				<object class="IBConnectionRecord">
+					<object class="IBOutletConnection" key="connection">
+						<string key="label">delegate</string>
+						<reference key="source" ref="605849626"/>
+						<reference key="destination" ref="1001"/>
+					</object>
+					<int key="connectionID">53</int>
+				</object>
+				<object class="IBConnectionRecord">
+					<object class="IBOutletConnection" key="connection">
+						<string key="label">dataSource</string>
+						<reference key="source" ref="1039136029"/>
+						<reference key="destination" ref="1001"/>
+					</object>
+					<int key="connectionID">54</int>
+				</object>
+				<object class="IBConnectionRecord">
+					<object class="IBOutletConnection" key="connection">
+						<string key="label">delegate</string>
+						<reference key="source" ref="1039136029"/>
+						<reference key="destination" ref="1001"/>
+					</object>
+					<int key="connectionID">55</int>
+				</object>
+				<object class="IBConnectionRecord">
+					<object class="IBOutletConnection" key="connection">
+						<string key="label">dataSource</string>
+						<reference key="source" ref="529258400"/>
+						<reference key="destination" ref="1001"/>
+					</object>
+					<int key="connectionID">56</int>
+				</object>
+				<object class="IBConnectionRecord">
+					<object class="IBOutletConnection" key="connection">
+						<string key="label">delegate</string>
+						<reference key="source" ref="529258400"/>
+						<reference key="destination" ref="1001"/>
+					</object>
+					<int key="connectionID">57</int>
+				</object>
+				<object class="IBConnectionRecord">
+					<object class="IBOutletConnection" key="connection">
+						<string key="label">delegate</string>
+						<reference key="source" ref="1005"/>
+						<reference key="destination" ref="1001"/>
+					</object>
+					<int key="connectionID">59</int>
+				</object>
+			</object>
+			<object class="IBMutableOrderedSet" key="objectRecords">
+				<object class="NSArray" key="orderedObjects">
+					<bool key="EncodedWithXMLCoder">YES</bool>
+					<object class="IBObjectRecord">
+						<int key="objectID">0</int>
+						<object class="NSArray" key="object" id="1002">
+							<bool key="EncodedWithXMLCoder">YES</bool>
+						</object>
+						<reference key="children" ref="1000"/>
+						<nil key="parent"/>
+					</object>
+					<object class="IBObjectRecord">
+						<int key="objectID">-2</int>
+						<reference key="object" ref="1001"/>
+						<reference key="parent" ref="1002"/>
+						<string type="base64-UTF8" key="objectName">RmlsZSdzIE93bmVyA</string>
+					</object>
+					<object class="IBObjectRecord">
+						<int key="objectID">-1</int>
+						<reference key="object" ref="1003"/>
+						<reference key="parent" ref="1002"/>
+						<string key="objectName">First Responder</string>
+					</object>
+					<object class="IBObjectRecord">
+						<int key="objectID">-3</int>
+						<reference key="object" ref="1004"/>
+						<reference key="parent" ref="1002"/>
+						<string key="objectName">Application</string>
+					</object>
+					<object class="IBObjectRecord">
+						<int key="objectID">1</int>
+						<reference key="object" ref="1005"/>
+						<object class="NSMutableArray" key="children">
+							<bool key="EncodedWithXMLCoder">YES</bool>
+							<reference ref="1006"/>
+						</object>
+						<reference key="parent" ref="1002"/>
+					</object>
+					<object class="IBObjectRecord">
+						<int key="objectID">2</int>
+						<reference key="object" ref="1006"/>
+						<object class="NSMutableArray" key="children">
+							<bool key="EncodedWithXMLCoder">YES</bool>
+							<reference ref="873949528"/>
+							<reference ref="882692977"/>
+							<reference ref="846347810"/>
+						</object>
+						<reference key="parent" ref="1005"/>
+					</object>
+					<object class="IBObjectRecord">
+						<int key="objectID">22</int>
+						<reference key="object" ref="846347810"/>
+						<object class="NSMutableArray" key="children">
+							<bool key="EncodedWithXMLCoder">YES</bool>
+							<reference ref="423958127"/>
+							<reference ref="162292652"/>
+							<reference ref="605849626"/>
+							<reference ref="504164402"/>
+						</object>
+						<reference key="parent" ref="1006"/>
+					</object>
+					<object class="IBObjectRecord">
+						<int key="objectID">23</int>
+						<reference key="object" ref="423958127"/>
+						<reference key="parent" ref="846347810"/>
+					</object>
+					<object class="IBObjectRecord">
+						<int key="objectID">24</int>
+						<reference key="object" ref="162292652"/>
+						<reference key="parent" ref="846347810"/>
+					</object>
+					<object class="IBObjectRecord">
+						<int key="objectID">25</int>
+						<reference key="object" ref="605849626"/>
+						<object class="NSMutableArray" key="children">
+							<bool key="EncodedWithXMLCoder">YES</bool>
+							<reference ref="997458089"/>
+							<reference ref="461325047"/>
+						</object>
+						<reference key="parent" ref="846347810"/>
+					</object>
+					<object class="IBObjectRecord">
+						<int key="objectID">26</int>
+						<reference key="object" ref="504164402"/>
+						<reference key="parent" ref="846347810"/>
+					</object>
+					<object class="IBObjectRecord">
+						<int key="objectID">27</int>
+						<reference key="object" ref="997458089"/>
+						<object class="NSMutableArray" key="children">
+							<bool key="EncodedWithXMLCoder">YES</bool>
+							<reference ref="542099181"/>
+						</object>
+						<reference key="parent" ref="605849626"/>
+					</object>
+					<object class="IBObjectRecord">
+						<int key="objectID">28</int>
+						<reference key="object" ref="461325047"/>
+						<object class="NSMutableArray" key="children">
+							<bool key="EncodedWithXMLCoder">YES</bool>
+							<reference ref="309525533"/>
+						</object>
+						<reference key="parent" ref="605849626"/>
+					</object>
+					<object class="IBObjectRecord">
+						<int key="objectID">29</int>
+						<reference key="object" ref="309525533"/>
+						<reference key="parent" ref="461325047"/>
+					</object>
+					<object class="IBObjectRecord">
+						<int key="objectID">30</int>
+						<reference key="object" ref="542099181"/>
+						<reference key="parent" ref="997458089"/>
+					</object>
+					<object class="IBObjectRecord">
+						<int key="objectID">31</int>
+						<reference key="object" ref="873949528"/>
+						<object class="NSMutableArray" key="children">
+							<bool key="EncodedWithXMLCoder">YES</bool>
+							<reference ref="599981709"/>
+							<reference ref="961510052"/>
+							<reference ref="1039136029"/>
+							<reference ref="534528862"/>
+						</object>
+						<reference key="parent" ref="1006"/>
+					</object>
+					<object class="IBObjectRecord">
+						<int key="objectID">32</int>
+						<reference key="object" ref="599981709"/>
+						<reference key="parent" ref="873949528"/>
+					</object>
+					<object class="IBObjectRecord">
+						<int key="objectID">33</int>
+						<reference key="object" ref="961510052"/>
+						<reference key="parent" ref="873949528"/>
+					</object>
+					<object class="IBObjectRecord">
+						<int key="objectID">34</int>
+						<reference key="object" ref="1039136029"/>
+						<object class="NSMutableArray" key="children">
+							<bool key="EncodedWithXMLCoder">YES</bool>
+							<reference ref="120650054"/>
+						</object>
+						<reference key="parent" ref="873949528"/>
+					</object>
+					<object class="IBObjectRecord">
+						<int key="objectID">35</int>
+						<reference key="object" ref="534528862"/>
+						<reference key="parent" ref="873949528"/>
+					</object>
+					<object class="IBObjectRecord">
+						<int key="objectID">36</int>
+						<reference key="object" ref="120650054"/>
+						<object class="NSMutableArray" key="children">
+							<bool key="EncodedWithXMLCoder">YES</bool>
+							<reference ref="788058591"/>
+						</object>
+						<reference key="parent" ref="1039136029"/>
+					</object>
+					<object class="IBObjectRecord">
+						<int key="objectID">39</int>
+						<reference key="object" ref="788058591"/>
+						<reference key="parent" ref="120650054"/>
+					</object>
+					<object class="IBObjectRecord">
+						<int key="objectID">40</int>
+						<reference key="object" ref="882692977"/>
+						<object class="NSMutableArray" key="children">
+							<bool key="EncodedWithXMLCoder">YES</bool>
+							<reference ref="182370043"/>
+							<reference ref="328005951"/>
+							<reference ref="529258400"/>
+							<reference ref="123096532"/>
+						</object>
+						<reference key="parent" ref="1006"/>
+					</object>
+					<object class="IBObjectRecord">
+						<int key="objectID">41</int>
+						<reference key="object" ref="182370043"/>
+						<reference key="parent" ref="882692977"/>
+					</object>
+					<object class="IBObjectRecord">
+						<int key="objectID">42</int>
+						<reference key="object" ref="328005951"/>
+						<reference key="parent" ref="882692977"/>
+					</object>
+					<object class="IBObjectRecord">
+						<int key="objectID">43</int>
+						<reference key="object" ref="529258400"/>
+						<object class="NSMutableArray" key="children">
+							<bool key="EncodedWithXMLCoder">YES</bool>
+							<reference ref="602298172"/>
+						</object>
+						<reference key="parent" ref="882692977"/>
+					</object>
+					<object class="IBObjectRecord">
+						<int key="objectID">44</int>
+						<reference key="object" ref="123096532"/>
+						<reference key="parent" ref="882692977"/>
+					</object>
+					<object class="IBObjectRecord">
+						<int key="objectID">45</int>
+						<reference key="object" ref="602298172"/>
+						<object class="NSMutableArray" key="children">
+							<bool key="EncodedWithXMLCoder">YES</bool>
+							<reference ref="870958269"/>
+						</object>
+						<reference key="parent" ref="529258400"/>
+					</object>
+					<object class="IBObjectRecord">
+						<int key="objectID">48</int>
+						<reference key="object" ref="870958269"/>
+						<reference key="parent" ref="602298172"/>
+					</object>
+				</object>
+			</object>
+			<object class="NSMutableDictionary" key="flattenedProperties">
+				<bool key="EncodedWithXMLCoder">YES</bool>
+				<object class="NSMutableArray" key="dict.sortedKeys">
+					<bool key="EncodedWithXMLCoder">YES</bool>
+					<string>-1.IBPluginDependency</string>
+					<string>-2.IBPluginDependency</string>
+					<string>-3.IBPluginDependency</string>
+					<string>1.IBEditorWindowLastContentRect</string>
+					<string>1.IBPluginDependency</string>
+					<string>1.IBWindowTemplateEditedContentRect</string>
+					<string>1.NSWindowTemplate.visibleAtLaunch</string>
+					<string>1.WindowOrigin</string>
+					<string>1.editorWindowContentRectSynchronizationRect</string>
+					<string>2.IBPluginDependency</string>
+					<string>22.IBPluginDependency</string>
+					<string>23.IBPluginDependency</string>
+					<string>24.IBPluginDependency</string>
+					<string>25.IBPluginDependency</string>
+					<string>26.IBPluginDependency</string>
+					<string>27.IBPluginDependency</string>
+					<string>28.IBPluginDependency</string>
+					<string>29.IBPluginDependency</string>
+					<string>30.IBPluginDependency</string>
+					<string>31.IBPluginDependency</string>
+					<string>32.IBPluginDependency</string>
+					<string>33.IBPluginDependency</string>
+					<string>34.IBPluginDependency</string>
+					<string>35.IBPluginDependency</string>
+					<string>36.IBPluginDependency</string>
+					<string>39.IBPluginDependency</string>
+					<string>40.IBPluginDependency</string>
+					<string>41.IBPluginDependency</string>
+					<string>42.IBPluginDependency</string>
+					<string>43.IBPluginDependency</string>
+					<string>44.IBPluginDependency</string>
+					<string>45.IBPluginDependency</string>
+					<string>48.IBPluginDependency</string>
+				</object>
+				<object class="NSMutableArray" key="dict.values">
+					<bool key="EncodedWithXMLCoder">YES</bool>
+					<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
+					<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
+					<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
+					<string>{{48, 320}, {555, 520}}</string>
+					<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
+					<string>{{48, 320}, {555, 520}}</string>
+					<integer value="1"/>
+					<string>{196, 240}</string>
+					<string>{{357, 418}, {480, 270}}</string>
+					<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
+					<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
+					<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
+					<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
+					<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
+					<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
+					<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
+					<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
+					<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
+					<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
+					<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
+					<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
+					<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
+					<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
+					<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
+					<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
+					<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
+					<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
+					<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
+					<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
+					<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
+					<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
+					<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
+					<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
+				</object>
+			</object>
+			<object class="NSMutableDictionary" key="unlocalizedProperties">
+				<bool key="EncodedWithXMLCoder">YES</bool>
+				<object class="NSArray" key="dict.sortedKeys">
+					<bool key="EncodedWithXMLCoder">YES</bool>
+				</object>
+				<object class="NSMutableArray" key="dict.values">
+					<bool key="EncodedWithXMLCoder">YES</bool>
+				</object>
+			</object>
+			<nil key="activeLocalization"/>
+			<object class="NSMutableDictionary" key="localizations">
+				<bool key="EncodedWithXMLCoder">YES</bool>
+				<object class="NSArray" key="dict.sortedKeys">
+					<bool key="EncodedWithXMLCoder">YES</bool>
+				</object>
+				<object class="NSMutableArray" key="dict.values">
+					<bool key="EncodedWithXMLCoder">YES</bool>
+				</object>
+			</object>
+			<nil key="sourceID"/>
+			<int key="maxID">59</int>
+		</object>
+		<object class="IBClassDescriber" key="IBDocument.Classes">
+			<object class="NSMutableArray" key="referencedPartialClassDescriptions">
+				<bool key="EncodedWithXMLCoder">YES</bool>
+				<object class="IBPartialClassDescription">
+					<string key="className">PackageViewController</string>
+					<object class="NSMutableDictionary" key="outlets">
+						<bool key="EncodedWithXMLCoder">YES</bool>
+						<object class="NSMutableArray" key="dict.sortedKeys">
+							<bool key="EncodedWithXMLCoder">YES</bool>
+							<string>packageTable</string>
+							<string>useTable</string>
+							<string>usedByTable</string>
+						</object>
+						<object class="NSMutableArray" key="dict.values">
+							<bool key="EncodedWithXMLCoder">YES</bool>
+							<string>id</string>
+							<string>id</string>
+							<string>id</string>
+						</object>
+					</object>
+					<object class="IBClassDescriptionSource" key="sourceIdentifier">
+						<string key="majorKey">IBUserSource</string>
+						<string key="minorKey"/>
+					</object>
+				</object>
+			</object>
+		</object>
+		<int key="IBDocument.localizationMode">0</int>
+		<nil key="IBDocument.LastKnownRelativeProjectPath"/>
+		<int key="IBDocument.defaultPropertyAccessControl">3</int>
+	</data>
+</archive>
Index: /trunk/contrib/krueger/InterfaceProjects/Simple Sum/simplesum.lisp
===================================================================
--- /trunk/contrib/krueger/InterfaceProjects/Simple Sum/simplesum.lisp	(revision 13946)
+++ /trunk/contrib/krueger/InterfaceProjects/Simple Sum/simplesum.lisp	(revision 13946)
@@ -0,0 +1,89 @@
+;;; simplesum.lisp
+
+#|
+The MIT license.
+
+Copyright (c) 2009 Paul L. Krueger
+
+Permission is hereby granted, free of charge, to any person obtaining a copy of this software 
+and associated documentation files (the "Software"), to deal in the Software without restriction, 
+including without limitation the rights to use, copy, modify, merge, publish, distribute, 
+sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is 
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all copies or substantial 
+portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT 
+LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. 
+IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, 
+WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE 
+SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+|#
+
+;;; Sample lisp/Cocoa interface that uses a NIB file defined with interface builder;
+;;; A definition is provided for the "Foo" class that was specified to interface builder
+;;; so that when the NIB file is loaded an instance of that class will be created and
+;;; linked appropriately to the input fields, output sum text field, and Sum button.
+;;; When the Sum button is pushed the sum will be computed and placed into the sum 
+;;; field in the window.
+
+(eval-when (:compile-toplevel :load-toplevel :execute)
+  (require :nib))
+
+(defpackage :simplesum 
+  (:nicknames :ss)
+  (:use :iu :ccl :common-lisp)
+  (:export test-sum))
+
+(in-package :simplesum)
+
+(defvar *debug-sum* nil)
+
+(defclass sum-window-owner (ns:ns-object)
+  ((input1 :foreign-type :id
+           :accessor input1)
+   (input2 :foreign-type :id
+           :accessor input2)
+   (sum :foreign-type :id
+        :accessor sum)
+   (nib-objects :accessor nib-objects :initform nil))
+  (:metaclass ns:+ns-object))
+
+(defmethod initialize-instance :after ((self sum-window-owner) 
+                                       &key &allow-other-keys)
+  (setf (nib-objects self)
+        (load-nibfile 
+         (truename "ip:Simple Sum;sumLisp.nib") 
+         :nib-owner self
+         :retain-top-objs t))
+  ;; we do the following so that ccl:terminate will be called before we are garbage 
+  ;; collected and we can release the top-level objects from the NIB that we retained
+  ;; when loaded
+  (ccl:terminate-when-unreachable self))
+
+(defmethod ccl:terminate ((self sum-window-owner))
+  (dolist (top-obj (nib-objects self))
+    (unless (eql top-obj (%null-ptr))
+      (#/release top-obj))))
+
+;; methods called as a result of button actions
+
+(objc:defmethod (#/doSum: :void) 
+                ((self sum-window-owner) (s :id))
+  (declare (ignore s))
+  (with-slots (input1 input2 sum) self
+    (#/setIntValue: sum (+ (#/intValue input1) (#/intValue input2)))))
+
+(objc:defmethod (#/doFirstThing :void) 
+                ((self sum-window-owner) (s :id))
+  (declare (ignore s))
+  ;;; test function for menu tests
+  (#/doSum: self (%null-ptr)))
+
+;; test by
+(defun test-sum ()
+  (make-instance 'sum-window-owner))
+
+(provide :simplesum)
Index: /trunk/contrib/krueger/InterfaceProjects/Simple Sum/sumLisp.nib/designable.nib
===================================================================
--- /trunk/contrib/krueger/InterfaceProjects/Simple Sum/sumLisp.nib/designable.nib	(revision 13946)
+++ /trunk/contrib/krueger/InterfaceProjects/Simple Sum/sumLisp.nib/designable.nib	(revision 13946)
@@ -0,0 +1,429 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<archive type="com.apple.InterfaceBuilder3.Cocoa.XIB" version="7.03">
+	<data>
+		<int key="IBDocument.SystemTarget">1050</int>
+		<string key="IBDocument.SystemVersion">9L30</string>
+		<string key="IBDocument.InterfaceBuilderVersion">680</string>
+		<string key="IBDocument.AppKitVersion">949.54</string>
+		<string key="IBDocument.HIToolboxVersion">353.00</string>
+		<object class="NSMutableArray" key="IBDocument.EditedObjectIDs">
+			<bool key="EncodedWithXMLCoder">YES</bool>
+			<integer value="1" id="9"/>
+		</object>
+		<object class="NSArray" key="IBDocument.PluginDependencies">
+			<bool key="EncodedWithXMLCoder">YES</bool>
+			<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
+		</object>
+		<object class="NSMutableDictionary" key="IBDocument.Metadata">
+			<bool key="EncodedWithXMLCoder">YES</bool>
+			<object class="NSArray" key="dict.sortedKeys">
+				<bool key="EncodedWithXMLCoder">YES</bool>
+			</object>
+			<object class="NSMutableArray" key="dict.values">
+				<bool key="EncodedWithXMLCoder">YES</bool>
+			</object>
+		</object>
+		<object class="NSMutableArray" key="IBDocument.RootObjects" id="1000">
+			<bool key="EncodedWithXMLCoder">YES</bool>
+			<object class="NSCustomObject" id="1001">
+				<string key="NSClassName">SumWindowOwn</string>
+			</object>
+			<object class="NSCustomObject" id="1003">
+				<string key="NSClassName">FirstResponder</string>
+			</object>
+			<object class="NSCustomObject" id="1004">
+				<string key="NSClassName">NSApplication</string>
+			</object>
+			<object class="NSWindowTemplate" id="1005">
+				<int key="NSWindowStyleMask">15</int>
+				<int key="NSWindowBacking">2</int>
+				<string key="NSWindowRect">{{196, 240}, {480, 270}}</string>
+				<int key="NSWTFlags">536870912</int>
+				<string key="NSWindowTitle">Sum Window</string>
+				<string key="NSWindowClass">NSWindow</string>
+				<nil key="NSViewClass"/>
+				<string key="NSWindowContentMaxSize">{3.40282e+38, 3.40282e+38}</string>
+				<object class="NSView" key="NSWindowView" id="1006">
+					<reference key="NSNextResponder"/>
+					<int key="NSvFlags">256</int>
+					<object class="NSMutableArray" key="NSSubviews">
+						<bool key="EncodedWithXMLCoder">YES</bool>
+						<object class="NSTextField" id="1038637517">
+							<reference key="NSNextResponder" ref="1006"/>
+							<int key="NSvFlags">268</int>
+							<string key="NSFrame">{{69, 212}, {96, 22}}</string>
+							<reference key="NSSuperview" ref="1006"/>
+							<bool key="NSEnabled">YES</bool>
+							<object class="NSTextFieldCell" key="NSCell" id="774035685">
+								<int key="NSCellFlags">-1804468671</int>
+								<int key="NSCellFlags2">272630784</int>
+								<string key="NSContents"/>
+								<object class="NSFont" key="NSSupport" id="430743036">
+									<string key="NSName">LucidaGrande</string>
+									<double key="NSSize">1.300000e+01</double>
+									<int key="NSfFlags">1044</int>
+								</object>
+								<reference key="NSControlView" ref="1038637517"/>
+								<bool key="NSDrawsBackground">YES</bool>
+								<object class="NSColor" key="NSBackgroundColor" id="281062866">
+									<int key="NSColorSpace">6</int>
+									<string key="NSCatalogName">System</string>
+									<string key="NSColorName">textBackgroundColor</string>
+									<object class="NSColor" key="NSColor">
+										<int key="NSColorSpace">3</int>
+										<bytes key="NSWhite">MQA</bytes>
+									</object>
+								</object>
+								<object class="NSColor" key="NSTextColor" id="814966717">
+									<int key="NSColorSpace">6</int>
+									<string key="NSCatalogName">System</string>
+									<string key="NSColorName">textColor</string>
+									<object class="NSColor" key="NSColor">
+										<int key="NSColorSpace">3</int>
+										<bytes key="NSWhite">MAA</bytes>
+									</object>
+								</object>
+							</object>
+						</object>
+						<object class="NSTextField" id="939473490">
+							<reference key="NSNextResponder" ref="1006"/>
+							<int key="NSvFlags">268</int>
+							<string key="NSFrame">{{230, 212}, {96, 22}}</string>
+							<reference key="NSSuperview" ref="1006"/>
+							<bool key="NSEnabled">YES</bool>
+							<object class="NSTextFieldCell" key="NSCell" id="475105469">
+								<int key="NSCellFlags">-1804468671</int>
+								<int key="NSCellFlags2">272630784</int>
+								<string key="NSContents"/>
+								<reference key="NSSupport" ref="430743036"/>
+								<reference key="NSControlView" ref="939473490"/>
+								<bool key="NSDrawsBackground">YES</bool>
+								<reference key="NSBackgroundColor" ref="281062866"/>
+								<reference key="NSTextColor" ref="814966717"/>
+							</object>
+						</object>
+						<object class="NSTextField" id="566943346">
+							<reference key="NSNextResponder" ref="1006"/>
+							<int key="NSvFlags">268</int>
+							<string key="NSFrame">{{151, 81}, {96, 22}}</string>
+							<reference key="NSSuperview" ref="1006"/>
+							<bool key="NSEnabled">YES</bool>
+							<object class="NSTextFieldCell" key="NSCell" id="993638017">
+								<int key="NSCellFlags">-2079195584</int>
+								<int key="NSCellFlags2">272630784</int>
+								<string key="NSContents"/>
+								<reference key="NSSupport" ref="430743036"/>
+								<reference key="NSControlView" ref="566943346"/>
+								<reference key="NSBackgroundColor" ref="281062866"/>
+								<reference key="NSTextColor" ref="814966717"/>
+							</object>
+						</object>
+						<object class="NSButton" id="481302721">
+							<reference key="NSNextResponder" ref="1006"/>
+							<int key="NSvFlags">268</int>
+							<string key="NSFrame">{{151, 147}, {96, 32}}</string>
+							<reference key="NSSuperview" ref="1006"/>
+							<bool key="NSEnabled">YES</bool>
+							<object class="NSButtonCell" key="NSCell" id="540763753">
+								<int key="NSCellFlags">67239424</int>
+								<int key="NSCellFlags2">134217728</int>
+								<string key="NSContents">Sum</string>
+								<reference key="NSSupport" ref="430743036"/>
+								<reference key="NSControlView" ref="481302721"/>
+								<int key="NSButtonFlags">-2038284033</int>
+								<int key="NSButtonFlags2">129</int>
+								<string key="NSAlternateContents"/>
+								<string key="NSKeyEquivalent"/>
+								<int key="NSPeriodicDelay">200</int>
+								<int key="NSPeriodicInterval">25</int>
+							</object>
+						</object>
+					</object>
+					<string key="NSFrameSize">{480, 270}</string>
+					<reference key="NSSuperview"/>
+				</object>
+				<string key="NSScreenRect">{{0, 0}, {1680, 1028}}</string>
+				<string key="NSMaxSize">{3.40282e+38, 3.40282e+38}</string>
+			</object>
+		</object>
+		<object class="IBObjectContainer" key="IBDocument.Objects">
+			<object class="NSMutableArray" key="connectionRecords">
+				<bool key="EncodedWithXMLCoder">YES</bool>
+				<object class="IBConnectionRecord">
+					<object class="IBActionConnection" key="connection">
+						<string key="label">doSum:</string>
+						<reference key="source" ref="1001"/>
+						<reference key="destination" ref="481302721"/>
+					</object>
+					<int key="connectionID">19</int>
+				</object>
+				<object class="IBConnectionRecord">
+					<object class="IBOutletConnection" key="connection">
+						<string key="label">input1</string>
+						<reference key="source" ref="1001"/>
+						<reference key="destination" ref="1038637517"/>
+					</object>
+					<int key="connectionID">23</int>
+				</object>
+				<object class="IBConnectionRecord">
+					<object class="IBOutletConnection" key="connection">
+						<string key="label">input2</string>
+						<reference key="source" ref="1001"/>
+						<reference key="destination" ref="939473490"/>
+					</object>
+					<int key="connectionID">24</int>
+				</object>
+				<object class="IBConnectionRecord">
+					<object class="IBOutletConnection" key="connection">
+						<string key="label">sum</string>
+						<reference key="source" ref="1001"/>
+						<reference key="destination" ref="566943346"/>
+					</object>
+					<int key="connectionID">25</int>
+				</object>
+				<object class="IBConnectionRecord">
+					<object class="IBOutletConnection" key="connection">
+						<string key="label">delegate</string>
+						<reference key="source" ref="1005"/>
+						<reference key="destination" ref="1001"/>
+					</object>
+					<int key="connectionID">26</int>
+				</object>
+			</object>
+			<object class="IBMutableOrderedSet" key="objectRecords">
+				<object class="NSArray" key="orderedObjects">
+					<bool key="EncodedWithXMLCoder">YES</bool>
+					<object class="IBObjectRecord">
+						<int key="objectID">0</int>
+						<object class="NSArray" key="object" id="1002">
+							<bool key="EncodedWithXMLCoder">YES</bool>
+						</object>
+						<reference key="children" ref="1000"/>
+						<nil key="parent"/>
+					</object>
+					<object class="IBObjectRecord">
+						<int key="objectID">-2</int>
+						<reference key="object" ref="1001"/>
+						<reference key="parent" ref="1002"/>
+						<string type="base64-UTF8" key="objectName">RmlsZSdzIE93bmVyA</string>
+					</object>
+					<object class="IBObjectRecord">
+						<int key="objectID">-1</int>
+						<reference key="object" ref="1003"/>
+						<reference key="parent" ref="1002"/>
+						<string key="objectName">First Responder</string>
+					</object>
+					<object class="IBObjectRecord">
+						<int key="objectID">-3</int>
+						<reference key="object" ref="1004"/>
+						<reference key="parent" ref="1002"/>
+						<string key="objectName">Application</string>
+					</object>
+					<object class="IBObjectRecord">
+						<int key="objectID">1</int>
+						<reference key="object" ref="1005"/>
+						<object class="NSMutableArray" key="children">
+							<bool key="EncodedWithXMLCoder">YES</bool>
+							<reference ref="1006"/>
+						</object>
+						<reference key="parent" ref="1002"/>
+					</object>
+					<object class="IBObjectRecord">
+						<int key="objectID">2</int>
+						<reference key="object" ref="1006"/>
+						<object class="NSMutableArray" key="children">
+							<bool key="EncodedWithXMLCoder">YES</bool>
+							<reference ref="1038637517"/>
+							<reference ref="939473490"/>
+							<reference ref="566943346"/>
+							<reference ref="481302721"/>
+						</object>
+						<reference key="parent" ref="1005"/>
+					</object>
+					<object class="IBObjectRecord">
+						<int key="objectID">4</int>
+						<reference key="object" ref="1038637517"/>
+						<object class="NSMutableArray" key="children">
+							<bool key="EncodedWithXMLCoder">YES</bool>
+							<reference ref="774035685"/>
+						</object>
+						<reference key="parent" ref="1006"/>
+					</object>
+					<object class="IBObjectRecord">
+						<int key="objectID">5</int>
+						<reference key="object" ref="774035685"/>
+						<reference key="parent" ref="1038637517"/>
+					</object>
+					<object class="IBObjectRecord">
+						<int key="objectID">6</int>
+						<reference key="object" ref="939473490"/>
+						<object class="NSMutableArray" key="children">
+							<bool key="EncodedWithXMLCoder">YES</bool>
+							<reference ref="475105469"/>
+						</object>
+						<reference key="parent" ref="1006"/>
+					</object>
+					<object class="IBObjectRecord">
+						<int key="objectID">7</int>
+						<reference key="object" ref="475105469"/>
+						<reference key="parent" ref="939473490"/>
+					</object>
+					<object class="IBObjectRecord">
+						<int key="objectID">8</int>
+						<reference key="object" ref="566943346"/>
+						<object class="NSMutableArray" key="children">
+							<bool key="EncodedWithXMLCoder">YES</bool>
+							<reference ref="993638017"/>
+						</object>
+						<reference key="parent" ref="1006"/>
+					</object>
+					<object class="IBObjectRecord">
+						<int key="objectID">9</int>
+						<reference key="object" ref="993638017"/>
+						<reference key="parent" ref="566943346"/>
+					</object>
+					<object class="IBObjectRecord">
+						<int key="objectID">10</int>
+						<reference key="object" ref="481302721"/>
+						<object class="NSMutableArray" key="children">
+							<bool key="EncodedWithXMLCoder">YES</bool>
+							<reference ref="540763753"/>
+						</object>
+						<reference key="parent" ref="1006"/>
+					</object>
+					<object class="IBObjectRecord">
+						<int key="objectID">11</int>
+						<reference key="object" ref="540763753"/>
+						<reference key="parent" ref="481302721"/>
+					</object>
+				</object>
+			</object>
+			<object class="NSMutableDictionary" key="flattenedProperties">
+				<bool key="EncodedWithXMLCoder">YES</bool>
+				<object class="NSMutableArray" key="dict.sortedKeys">
+					<bool key="EncodedWithXMLCoder">YES</bool>
+					<string>-1.IBPluginDependency</string>
+					<string>-2.IBPluginDependency</string>
+					<string>-3.IBPluginDependency</string>
+					<string>1.IBEditorWindowLastContentRect</string>
+					<string>1.IBPluginDependency</string>
+					<string>1.IBWindowTemplateEditedContentRect</string>
+					<string>1.NSWindowTemplate.visibleAtLaunch</string>
+					<string>1.WindowOrigin</string>
+					<string>1.editorWindowContentRectSynchronizationRect</string>
+					<string>10.IBPluginDependency</string>
+					<string>11.IBPluginDependency</string>
+					<string>2.IBPluginDependency</string>
+					<string>4.IBPluginDependency</string>
+					<string>5.IBPluginDependency</string>
+					<string>6.IBPluginDependency</string>
+					<string>7.IBPluginDependency</string>
+					<string>8.IBPluginDependency</string>
+					<string>9.IBPluginDependency</string>
+				</object>
+				<object class="NSMutableArray" key="dict.values">
+					<bool key="EncodedWithXMLCoder">YES</bool>
+					<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
+					<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
+					<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
+					<string>{{34, 124}, {480, 270}}</string>
+					<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
+					<string>{{34, 124}, {480, 270}}</string>
+					<reference ref="9"/>
+					<string>{196, 240}</string>
+					<string>{{357, 418}, {480, 270}}</string>
+					<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
+					<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
+					<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
+					<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
+					<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
+					<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
+					<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
+					<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
+					<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
+				</object>
+			</object>
+			<object class="NSMutableDictionary" key="unlocalizedProperties">
+				<bool key="EncodedWithXMLCoder">YES</bool>
+				<object class="NSArray" key="dict.sortedKeys">
+					<bool key="EncodedWithXMLCoder">YES</bool>
+				</object>
+				<object class="NSMutableArray" key="dict.values">
+					<bool key="EncodedWithXMLCoder">YES</bool>
+				</object>
+			</object>
+			<nil key="activeLocalization"/>
+			<object class="NSMutableDictionary" key="localizations">
+				<bool key="EncodedWithXMLCoder">YES</bool>
+				<object class="NSArray" key="dict.sortedKeys">
+					<bool key="EncodedWithXMLCoder">YES</bool>
+				</object>
+				<object class="NSMutableArray" key="dict.values">
+					<bool key="EncodedWithXMLCoder">YES</bool>
+				</object>
+			</object>
+			<nil key="sourceID"/>
+			<int key="maxID">26</int>
+		</object>
+		<object class="IBClassDescriber" key="IBDocument.Classes">
+			<object class="NSMutableArray" key="referencedPartialClassDescriptions">
+				<bool key="EncodedWithXMLCoder">YES</bool>
+				<object class="IBPartialClassDescription">
+					<string key="className">NSObject</string>
+					<object class="NSMutableDictionary" key="actions">
+						<string key="NS.key.0">doSum:</string>
+						<string key="NS.object.0">id</string>
+					</object>
+					<object class="NSMutableDictionary" key="outlets">
+						<bool key="EncodedWithXMLCoder">YES</bool>
+						<object class="NSMutableArray" key="dict.sortedKeys">
+							<bool key="EncodedWithXMLCoder">YES</bool>
+							<string>input1</string>
+							<string>input2</string>
+							<string>sum</string>
+						</object>
+						<object class="NSMutableArray" key="dict.values">
+							<bool key="EncodedWithXMLCoder">YES</bool>
+							<string>NSTextField</string>
+							<string>NSTextField</string>
+							<string>NSTextField</string>
+						</object>
+					</object>
+					<object class="IBClassDescriptionSource" key="sourceIdentifier">
+						<string key="majorKey">IBUserSource</string>
+						<string key="minorKey"/>
+					</object>
+				</object>
+				<object class="IBPartialClassDescription">
+					<string key="className">SumWindowOwn</string>
+					<object class="NSMutableDictionary" key="actions">
+						<string key="NS.key.0">doSum:</string>
+						<string key="NS.object.0">id</string>
+					</object>
+					<object class="NSMutableDictionary" key="outlets">
+						<bool key="EncodedWithXMLCoder">YES</bool>
+						<object class="NSMutableArray" key="dict.sortedKeys">
+							<bool key="EncodedWithXMLCoder">YES</bool>
+							<string>input1</string>
+							<string>input2</string>
+							<string>sum</string>
+						</object>
+						<object class="NSMutableArray" key="dict.values">
+							<bool key="EncodedWithXMLCoder">YES</bool>
+							<string>NSTextField</string>
+							<string>NSTextField</string>
+							<string>NSTextField</string>
+						</object>
+					</object>
+					<object class="IBClassDescriptionSource" key="sourceIdentifier">
+						<string key="majorKey">IBUserSource</string>
+						<string key="minorKey"/>
+					</object>
+				</object>
+			</object>
+		</object>
+		<int key="IBDocument.localizationMode">0</int>
+		<nil key="IBDocument.LastKnownRelativeProjectPath"/>
+		<int key="IBDocument.defaultPropertyAccessControl">3</int>
+	</data>
+</archive>
Index: /trunk/contrib/krueger/InterfaceProjects/Speech/SpeechView.nib/designable.nib
===================================================================
--- /trunk/contrib/krueger/InterfaceProjects/Speech/SpeechView.nib/designable.nib	(revision 13946)
+++ /trunk/contrib/krueger/InterfaceProjects/Speech/SpeechView.nib/designable.nib	(revision 13946)
@@ -0,0 +1,1191 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<archive type="com.apple.InterfaceBuilder3.Cocoa.XIB" version="7.03">
+	<data>
+		<int key="IBDocument.SystemTarget">1050</int>
+		<string key="IBDocument.SystemVersion">9L30</string>
+		<string key="IBDocument.InterfaceBuilderVersion">680</string>
+		<string key="IBDocument.AppKitVersion">949.54</string>
+		<string key="IBDocument.HIToolboxVersion">353.00</string>
+		<object class="NSMutableArray" key="IBDocument.EditedObjectIDs">
+			<bool key="EncodedWithXMLCoder">YES</bool>
+			<integer value="2"/>
+		</object>
+		<object class="NSArray" key="IBDocument.PluginDependencies">
+			<bool key="EncodedWithXMLCoder">YES</bool>
+			<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
+		</object>
+		<object class="NSMutableDictionary" key="IBDocument.Metadata">
+			<bool key="EncodedWithXMLCoder">YES</bool>
+			<object class="NSArray" key="dict.sortedKeys">
+				<bool key="EncodedWithXMLCoder">YES</bool>
+			</object>
+			<object class="NSMutableArray" key="dict.values">
+				<bool key="EncodedWithXMLCoder">YES</bool>
+			</object>
+		</object>
+		<object class="NSMutableArray" key="IBDocument.RootObjects" id="1000">
+			<bool key="EncodedWithXMLCoder">YES</bool>
+			<object class="NSCustomObject" id="1001">
+				<string key="NSClassName">SpeechController</string>
+			</object>
+			<object class="NSCustomObject" id="1003">
+				<string key="NSClassName">FirstResponder</string>
+			</object>
+			<object class="NSCustomObject" id="1004">
+				<string key="NSClassName">NSApplication</string>
+			</object>
+			<object class="NSWindowTemplate" id="1005">
+				<int key="NSWindowStyleMask">15</int>
+				<int key="NSWindowBacking">2</int>
+				<string key="NSWindowRect">{{196, 81}, {475, 429}}</string>
+				<int key="NSWTFlags">536870912</int>
+				<string key="NSWindowTitle">Talk to me ...</string>
+				<string key="NSWindowClass">NSWindow</string>
+				<nil key="NSViewClass"/>
+				<string key="NSWindowContentMaxSize">{3.40282e+38, 3.40282e+38}</string>
+				<object class="NSView" key="NSWindowView" id="1006">
+					<reference key="NSNextResponder"/>
+					<int key="NSvFlags">256</int>
+					<object class="NSMutableArray" key="NSSubviews">
+						<bool key="EncodedWithXMLCoder">YES</bool>
+						<object class="NSButton" id="760939504">
+							<reference key="NSNextResponder" ref="1006"/>
+							<int key="NSvFlags">268</int>
+							<string key="NSFrame">{{55, 290}, {174, 32}}</string>
+							<reference key="NSSuperview" ref="1006"/>
+							<bool key="NSEnabled">YES</bool>
+							<object class="NSButtonCell" key="NSCell" id="1058338364">
+								<int key="NSCellFlags">67239424</int>
+								<int key="NSCellFlags2">134217728</int>
+								<string key="NSContents">Start Speaking</string>
+								<object class="NSFont" key="NSSupport" id="111849803">
+									<string key="NSName">LucidaGrande</string>
+									<double key="NSSize">1.300000e+01</double>
+									<int key="NSfFlags">1044</int>
+								</object>
+								<reference key="NSControlView" ref="760939504"/>
+								<int key="NSButtonFlags">-2038284033</int>
+								<int key="NSButtonFlags2">129</int>
+								<string key="NSAlternateContents"/>
+								<string key="NSKeyEquivalent"/>
+								<int key="NSPeriodicDelay">200</int>
+								<int key="NSPeriodicInterval">25</int>
+							</object>
+						</object>
+						<object class="NSButton" id="577036643">
+							<reference key="NSNextResponder" ref="1006"/>
+							<int key="NSvFlags">268</int>
+							<string key="NSFrame">{{237, 290}, {179, 32}}</string>
+							<reference key="NSSuperview" ref="1006"/>
+							<bool key="NSEnabled">YES</bool>
+							<object class="NSButtonCell" key="NSCell" id="70435651">
+								<int key="NSCellFlags">67239424</int>
+								<int key="NSCellFlags2">134217728</int>
+								<string key="NSContents">Stop Speaking</string>
+								<reference key="NSSupport" ref="111849803"/>
+								<reference key="NSControlView" ref="577036643"/>
+								<int key="NSButtonFlags">-2038284033</int>
+								<int key="NSButtonFlags2">129</int>
+								<string key="NSAlternateContents"/>
+								<string key="NSKeyEquivalent"/>
+								<int key="NSPeriodicDelay">200</int>
+								<int key="NSPeriodicInterval">25</int>
+							</object>
+						</object>
+						<object class="NSTextField" id="502162398">
+							<reference key="NSNextResponder" ref="1006"/>
+							<int key="NSvFlags">268</int>
+							<string key="NSFrame">{{45, 361}, {393, 22}}</string>
+							<reference key="NSSuperview" ref="1006"/>
+							<bool key="NSEnabled">YES</bool>
+							<object class="NSTextFieldCell" key="NSCell" id="379084012">
+								<int key="NSCellFlags">-1804468671</int>
+								<int key="NSCellFlags2">272630784</int>
+								<string key="NSContents"/>
+								<reference key="NSSupport" ref="111849803"/>
+								<reference key="NSControlView" ref="502162398"/>
+								<bool key="NSDrawsBackground">YES</bool>
+								<object class="NSColor" key="NSBackgroundColor">
+									<int key="NSColorSpace">6</int>
+									<string key="NSCatalogName">System</string>
+									<string key="NSColorName">textBackgroundColor</string>
+									<object class="NSColor" key="NSColor" id="484440858">
+										<int key="NSColorSpace">3</int>
+										<bytes key="NSWhite">MQA</bytes>
+									</object>
+								</object>
+								<object class="NSColor" key="NSTextColor">
+									<int key="NSColorSpace">6</int>
+									<string key="NSCatalogName">System</string>
+									<string key="NSColorName">textColor</string>
+									<object class="NSColor" key="NSColor" id="733504598">
+										<int key="NSColorSpace">3</int>
+										<bytes key="NSWhite">MAA</bytes>
+									</object>
+								</object>
+							</object>
+						</object>
+						<object class="NSMatrix" id="767130651">
+							<reference key="NSNextResponder" ref="1006"/>
+							<int key="NSvFlags">268</int>
+							<string key="NSFrame">{{31, 44}, {432, 190}}</string>
+							<reference key="NSSuperview" ref="1006"/>
+							<bool key="NSEnabled">YES</bool>
+							<int key="NSNumRows">6</int>
+							<int key="NSNumCols">4</int>
+							<object class="NSMutableArray" key="NSCells">
+								<bool key="EncodedWithXMLCoder">YES</bool>
+								<object class="NSButtonCell" id="374109759">
+									<int key="NSCellFlags">-2080244224</int>
+									<int key="NSCellFlags2">0</int>
+									<string key="NSContents">Radio</string>
+									<reference key="NSSupport" ref="111849803"/>
+									<int key="NSTag">1</int>
+									<reference key="NSControlView" ref="767130651"/>
+									<int key="NSButtonFlags">1211912703</int>
+									<int key="NSButtonFlags2">128</int>
+									<object class="NSButtonImageSource" key="NSAlternateImage" id="504559315">
+										<string key="NSImageName">NSRadioButton</string>
+									</object>
+									<string key="NSAlternateContents"/>
+									<string key="NSKeyEquivalent"/>
+									<int key="NSPeriodicDelay">200</int>
+									<int key="NSPeriodicInterval">25</int>
+								</object>
+								<object class="NSButtonCell" id="740026460">
+									<int key="NSCellFlags">67239424</int>
+									<int key="NSCellFlags2">0</int>
+									<string key="NSContents">Radio</string>
+									<reference key="NSSupport" ref="111849803"/>
+									<reference key="NSControlView" ref="767130651"/>
+									<int key="NSButtonFlags">1211912703</int>
+									<int key="NSButtonFlags2">128</int>
+									<object class="NSImage" key="NSNormalImage" id="360097870">
+										<int key="NSImageFlags">549453824</int>
+										<string key="NSSize">{18, 18}</string>
+										<object class="NSMutableArray" key="NSReps">
+											<bool key="EncodedWithXMLCoder">YES</bool>
+											<object class="NSArray">
+												<bool key="EncodedWithXMLCoder">YES</bool>
+												<integer value="0" id="8"/>
+												<object class="NSBitmapImageRep">
+													<object class="NSData" key="NSTIFFRepresentation">
+														<bytes key="NS.bytes">TU0AKgAABRgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAwAAAAMAAAADAAAAAwAAAAAAAAAA
+AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAwAAADwRERGLJycnySsrK/A1NTXw
+IyMjyRwcHIsJCQk8AAAAAwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFFRUVdVBQUOCoqKj/
+29vb//n5+f/6+vr/2tra/6qqqv9UVFTgHx8fdQAAAAUAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAUZGRl5
+dXV198PDw//8/Pz////////////////////////////U1NT/fHx89yUlJXkAAAAFAAAAAAAAAAAAAAAA
+AAAAAxEREUZqamrmtbW1/+3t7f/+/v7//v7+//7+/v/9/f3//f39//39/f/39/f/xMTE/3d3d+YZGRlG
+AAAAAwAAAAAAAAAAAAAACkJCQqGtra3/xsbG/+vr6//y8vL/9fX1//X19f/z8/P/9fX1//Ly8v/u7u7/
+0tLS/6+vr/9KSkqhAAAACgAAAAAAAAAAAAAAF3h4eN2/v7//z8/P/93d3f/q6ur/7+/v/+/v7//w8PD/
+7e3t/+3t7f/i4uL/zs7O/8XFxf98fHzdAAAAFwAAAAAAAAADAAAAJKSkpPjOzs7/2dnZ/+Dg4P/i4uL/
+5eXl/+bm5v/n5+f/5eXl/+Li4v/e3t7/2tra/9DQ0P+srKz4AAAAJAAAAAMAAAADAAAALrCwsPrW1tb/
+3t7e/+Tk5P/p6en/6+vr/+zs7P/p6en/6+vr/+fn5//k5OT/4ODg/9nZ2f+zs7P6AAAALgAAAAMAAAAD
+AAAALp2dnezg4OD/5eXl/+rq6v/u7u7/8PDw//Dw8P/x8fH/8PDw/+7u7v/q6ur/5ubm/+Hh4f+ZmZns
+AAAALgAAAAMAAAADAAAAJG5ubs/l5eX/6enp/+/v7//y8vL/9vb2//r6+v/5+fn/9/f3//b29v/x8fH/
+6+vr/+Tk5P9ra2vPAAAAJAAAAAMAAAAAAAAAFy4uLpPCwsL67Ozs//Pz8//5+fn//v7+//7+/v/+/v7/
+/v7+//v7+//19fX/8PDw/8LCwvosLCyTAAAAFwAAAAAAAAAAAAAACgAAAENfX1/S5OTk/vn5+f/+/v7/
+///////////////////////////8/Pz/5ubm/l9fX9IAAABDAAAACgAAAAAAAAAAAAAAAwAAABcAAABl
+YmJi3NLS0v3////////////////////////////////V1dX9ZGRk3AAAAGUAAAAXAAAAAwAAAAAAAAAA
+AAAAAAAAAAUAAAAfAAAAZTMzM8KAgIDwv7+//O3t7f/t7e3/v7+//ICAgPAzMzPCAAAAZQAAAB8AAAAF
+AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFAAAAFwAAAEMAAAB3AAAAnwAAALMAAACzAAAAnwAAAHcAAABD
+AAAAFwAAAAUAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAwAAAAoAAAAXAAAAJAAAAC4AAAAu
+AAAAJAAAABcAAAAKAAAAAwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+AAAAAwAAAAMAAAADAAAAAwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADgEAAAMAAAABABIAAAEB
+AAMAAAABABIAAAECAAMAAAAEAAAFxgEDAAMAAAABAAEAAAEGAAMAAAABAAIAAAERAAQAAAABAAAACAES
+AAMAAAABAAEAAAEVAAMAAAABAAQAAAEWAAMAAAABBxwAAAEXAAQAAAABAAAFEAEcAAMAAAABAAEAAAFS
+AAMAAAABAAEAAAFTAAMAAAAEAAAFzodzAAcAABEcAAAF1gAAAAAACAAIAAgACAABAAEAAQABAAARHGFw
+cGwCAAAAbW50clJHQiBYWVogB9kACAAIAAoAHwAdYWNzcEFQUEwAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+AAAAAPbWAAEAAAAA0y1hcHBsoS0Bh+QUuNDqzJl2rWVX8gAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+AAAAAAAOclhZWgAAASwAAAAUZ1hZWgAAAUAAAAAUYlhZWgAAAVQAAAAUd3RwdAAAAWgAAAAUY2hhZAAA
+AXwAAAAsclRSQwAAAagAAAAOZ1RSQwAAAbgAAAAOYlRSQwAAAcgAAAAOdmNndAAAAdgAAAYSbmRpbgAA
+B+wAAAY+ZGVzYwAADiwAAABkZHNjbQAADpAAAAI+bW1vZAAAENAAAAAoY3BydAAAEPgAAAAkWFlaIAAA
+AAAAAG6vAAA5TwAAAX1YWVogAAAAAAAAXt0AALO9AAAH11hZWiAAAAAAAAApSgAAEw8AAMnQWFlaIAAA
+AAAAAPNSAAEAAAABFs9zZjMyAAAAAAABDEIAAAXe///zJgAAB5IAAP2R///7ov///aMAAAPcAADAbGN1
+cnYAAAAAAAAAAQHNAABjdXJ2AAAAAAAAAAEBzQAAY3VydgAAAAAAAAABAc0AAHZjZ3QAAAAAAAAAAAAD
+AQAAAgAAADwA0gFbAe4CiQM6A/8E1gXDBsYH2Aj2CiYLXgyrDjYP1xF6Ex4UxRZyGCEZ3BuUHVEfFiDW
+Ip0kZCYuJ9UpeSsZLK4uQS/EMUMyszQaNXg2zDgXOVw6mzvUPQQ+MD9aQIhBtELhRA5FPEZnR5NIwEnr
+SxZMQE1qTohPplDEUd9S+VQTVSpWQFdSWGNZc1p/W4tcll2cXpZfjWCCYXViaGNZZEhlNGYgZwpn9Gjc
+acNqqmuQbHBtUW4wbw9v7nDMcapyh3NidD51GXXzds13qHiBeVd6LnsGe+F8wH2ifol/doBqgWSCZINq
+hHSFhIaXh7aI1on1ixSMM41Rjm2PiZCikbyS1JPslQOWGpcvmEGZU5pkm3WchZ2UnqOfsaC/ocyi2aPm
+pPKl/qcJqBOpHqorqzusUK1qroyvtbDpsiWzarS0tgi3YLi9udC647v0vQK+DL8SwBPBDcICwvDD2cS9
+xZzGd8dOyCfJBsnrys7Lq8yBzVDOF87Xz4rQN9Dg0YDSIdLB037UQNUB1cLWhNdG2AfYydmL2k3bD9vR
+3JPdVd4W3tbfluBX4Rnh2+Kg42bkLuT55cbmledn6DvpEOnn6qnra+wu7O/tsO5w7zDv7/Ct8WvyKfLm
+86L0X/Ub9df2k/dP+Av4x/mD+j/6+/u1/G79J/3e/pT/Sv//AAAANAC2ATsBuAJGAuQDlARXBSoGEQcL
+CAsJGwovC1wMwA41D6oRKBKkFCgVsBc4GMkaWRvuHYkfHyC9Ilcj2CVYJs8oRCmuKxUscC3CLw4wTTGG
+Mrcz5DULNi83OzhIOVM6XjtqPHQ9fT6GP45AlkGdQqVDq0SwRbRGtUeySLBJrUqpS6RMn02XTo9Ph1B/
+UXRSa1NgVFZVRFYzVyJYEFj9Wela1Fu+XKZdjl5zX1lgPWEgYf9i1mOqZH1lT2YhZvNnxGiUaWNqMmsA
+a81sm21pbjVu/m/HcI9xWHIgcuhzr3R3dT12A3bKd5B4VnkceeF6pntsfDV9AH3PfqJ/eoBZgT6CKYMa
+hA+FCYYHhwiIDYkTihiLHYwijSaOKo8ukDGRM5I1kzaUOJU4ljiXNpg0mTKaMZsxnDKdNp47n0SgT6Fc
+om2jgKSUpaumyKflqQOqH6s7rFetcq6Nr6iwwbHbsvS0DbUltj23VLhquX+6lLunvLi9xr7Qv9XA18HV
+ws7Dw8S2xaTGjMdzyFvJQsopyxDL98zezcTOq8+R0HfRXdJD0yjUDNTv1dPWtteZ2H3ZYdpG2yvcENz1
+3dzew9+q4JzhqOK548TkyeXG5r7nsOie6YjqcetY7D/tJ+4Q7vrv5vDf8gLzJvRJ9Wv2i/et+ND59fse
+/E79gv69//8AAAAiAHcA9gFXAccCQwLJA18EBgS4BXkGRQcVB+8I2gnyCxQMOw1nDpUPxBD6EjATahSo
+FekXLRh0GbsbAhw2HWoemx/JIPMiFiMzJEklVyZgJ2QoZClfKlcrSywvLQ8t8C7RL7EwjzFtMkszJzQB
+NNs1tDaNN2Y4PzkQOeI6szuEPFU9Jz34Psg/mUBqQTxCDkLgQ7NEhUVURiNG8kfBSI9JXUoqSvZLwUyM
+TVZOIE7pT7NQe1FBUgZSylOPVFNVFlXYVppXXFgcWN1ZnVpdWxxb2lyWXVFeC17EX31gNWDrYaJiWGMM
+Y8Bkc2UlZdhmiWc5Z+hol2lFafNqomtQa/xsqW1XbgNusG9ccAlwtHFfcghysXNbdAR0rHVVdfx2pHdL
+d/J4mXk/eeZ6jHsxe9h8gH0rfdt+jX9IgAiAz4GcgnCDS4QrhQ+F+Ibmh9eIx4m4iqeLl4yGjXWOY49R
+kD6RLJIZkwaT8pTalcGWp5eLmHCZVJo6myGcC5z4neie3J/ToM6h0KLxpBelPqZkp4qor6nUqvmsHa1B
+rmSviLCrsc6y8LQQtTC2ULdvuI+5sLrRu/K9FL43v1vAgMGmwszD9sUtxmvHsMkAylrLvM0tzqjQMNHB
+017VA9ay2GjaJNvm3a7fguGP4+TmWejj65DuVfEu9Bn3DfoE/QD//wAAbmRpbgAAAAAAAAY2AACl4wAA
+VqEAAFFbAACnKwAAJqUAABDlAABQDQAAVDkAAkKPAAHZmQABR64AAwEAAAIAAAANACcARgBmAIcAqADJ
+AOsBDgExAVUBegGdAbwB2wH8Ah0CPwJiAoYCqgLPAvQDGwNBA2gDkAO5A+IECwQ1BGAEjAS4BOQFEgU/
+BW4FoQXVBgoGQQZ4BrIG7AcoB2cHpwfpCC4IdQi/CQsJWgmsCgEKWAqyCw4LbgvSDDgMoA0IDXIN3g5K
+DrkPKA+aEA0QgRD3EW8R6BJjEt8TYhPnFG0U9hWBFg4WnRcvF8MYWxj1GZEaMRrTG3ccHRzQHYceQh8A
+H8EghSFNIhki6CO7JJElaiZGJyUoDCj1KeIq0ivELLotsy6wL68wsjG4MsAzyzTeNfE3BDgVOSM6LTsx
+PDA9Kj4gPxJAAkDvQdtCv0OiRIhFb0ZYR0JIL0keSg9LA0v4TPBN6k7lT+JQ4VHkUutT81T9VglXF1gn
+WTlaTVtjXHtdlV6wX85g7WIOYzNkWWV/ZqNnxWjjaf1rEmwhbSpuLm8tcClxInIWcwlz+nTpdhp3TXiE
+eb96/nxFfZN+64BNgbuDNIS5hkmH44mHiyGMro5Aj+CRkZNYlT2XSZl3m8WeG6AOogKj+aXyp+6p7Kvs
+re+v9bH9tAi2G7gvukS8Wb5pwHbCfsSAxn3IdspszGDOi9C40urVIddd2Z/b5t4x4IHi1eUr54jp5+xH
+7qrxEPN79e34Zvrn/XD//wAAAA8ALgBRAHUAmgC/AOQBCwEyAVsBhAGpAcsB7wIUAjoCYAKIArAC2QMD
+Ay0DWQOFA7ED3wQNBDwEawSbBM0E/gUxBWQFnAXVBg8GTAaJBsgHCgdNB5IH2gglCHIIwgkWCWwJxgoj
+CoIK5QtKC7oMKwyfDRUNjA4GDoIPAA+BEAMQiBEOEZcSIhKvE0AT1RRtFQYVohZBFuIXhhgtGNYZgRow
+GuAbkxxIHQQdwh6DH0YgDCDWIaIicyNGJB4k+CXWJrcnoCiXKZEqjiuOLJItmi6mL7UwyDHeMvc0FTU6
+NmM3jji9Oe87JTxfPZs+20AeQWRCr0P7RUVGi0fLSQVKN0tiTIZNpk7BT9pQ8FIEUxZUKlVAVllXc1iP
+Wa5azlvxXRZePV9mYJFhvmLuZCNlWGaPZ8Zo/Wo0a2lsnm3RbwJwMnFgco5zu3Todg93N3hgeYt6uHvn
+fRd+SX99gLKB6oMjhF2FmobYiBeJWYqei+SNLY54j8aRGJJvk8yVMJabmA6ZiZsMnJWeJ5/HoWmjDKSy
+plqoBKmwq1+tEK7DsHiyL7Potae3abktuvK8ur6CwEzCF8PjxbDHfMlKyxnM0M5Vz+PRetMe1M7Wi9hT
+2ibcAd3i38bhq+OP5XLnU+kb6p/sJ+2x7z7wzvJf8+/1gPcP+Jn6Hvuf/Rr+j///AAAAFwBBAHAAnwDP
+AP8BMgFmAZkBxQHzAiICUgKEArcC7AMhA1gDkAPJBAMEPgR6BLcE9QU1BXYFvQYFBk8GmwbqBzsHkAfo
+CEQIpAkICXAJ3ApMCsALNwu6DEIMzA1ZDeoOfg8VD7AQTxDxEZYSPhLpE50UUxUNFcoWiRdMGBIY2hml
+GnIbQRwTHOsdxh6kH4YgayFUIkEjMiQnJR8mGycaKCApKyo5K0ssYS18LpovvTDkMg4zPDRyNa427zg1
+OYE60jwoPYQ+5kBMQbdDK0SkRiFHo0kpSrVMRE3YT3BRDFKwVFtWCVe9WXZbNFz4XsBgjWJeZDZmDGfZ
+aZprSWzpbnlv/HF0cuV0UHWzdxF4cnnUezp8oX4Lf3iA54JYg8yFQoa6iDSJtos9jMmOWY/rkX6TEZSi
+li+XuZk+mr+cPJ22nwWgTKGVot+kKqV3psWoFalmqrqsDq1krrywFbFwssu0KLWKtu24Ubm3ux68hr3u
+v1fAwcIrw5XE/8Zqx9TJQMqrzBbNc87K0BvRaNKs0+rVI9ZX14LYqNnK2uXb/N0Q3h/fK+A14TriPuNA
+5EDlPuY65zfoMekq6iLrDuvp7Lntd+417uzvpfBZ8QrxvPJm8xDzuPRc9QD1ovZC9uL3f/gc+Ln5Vfnw
++oz7J/vC/F78+P2T/i/+yf9k//8AAGRlc2MAAAAAAAAACkNvbG9yIExDRAAAAAAAAAAAAAAAAAAAAAAA
+AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+AABtbHVjAAAAAAAAABIAAAAMbmJOTwAAABIAAADocHRQVAAAABYAAAD6c3ZTRQAAABAAAAEQZmlGSQAA
+ABAAAAEgZGFESwAAABwAAAEwemhDTgAAAAwAAAFMZnJGUgAAABIAAAFYamFKUAAAAA4AAAFqZW5VUwAA
+ABIAAAF4cGxQTAAAABIAAAGKcHRCUgAAABgAAAGcZXNFUwAAABIAAAG0emhUVwAAAA4AAAHGcnVSVQAA
+ACQAAAHUa29LUgAAAAwAAAH4ZGVERQAAABAAAAIEbmxOTAAAABYAAAIUaXRJVAAAABQAAAIqAEYAYQBy
+AGcAZQAtAEwAQwBEAEwAQwBEACAAYQAgAEMAbwByAGUAcwBGAOQAcgBnAC0ATABDAEQAVgDkAHIAaQAt
+AEwAQwBEAEwAQwBEAC0AZgBhAHIAdgBlAHMAawDmAHIAbV9pgnIAIABMAEMARADJAGMAcgBhAG4AIABM
+AEMARDCrMOkw/AAgAEwAQwBEAEMAbwBsAG8AcgAgAEwAQwBEAEsAbwBsAG8AcgAgAEwAQwBEAEwAQwBE
+ACAAQwBvAGwAbwByAGkAZABvAEwAQwBEACAAYwBvAGwAbwByX2mCcm2yZnaYb3k6VmgEJgQyBDUEQgQ9
+BD4EOQAgBBYEGgAtBDQEOARBBD8EOwQ1BDnO7LfsACAATABDAEQARgBhAHIAYgAtAEwAQwBEAEsAbABl
+AHUAcgBlAG4ALQBMAEMARABMAEMARAAgAGMAbwBsAG8AcgBpAABtbW9kAAAAAAAABhAAAJyjAAAAAMV4
+fYAAAAAAAAAAAAAAAAAAAAAAdGV4dAAAAABDb3B5cmlnaHQgQXBwbGUsIEluYy4sIDIwMDkAA</bytes>
+													</object>
+												</object>
+											</object>
+										</object>
+										<object class="NSColor" key="NSColor" id="41951801">
+											<int key="NSColorSpace">3</int>
+											<bytes key="NSWhite">MCAwAA</bytes>
+										</object>
+									</object>
+									<reference key="NSAlternateImage" ref="504559315"/>
+									<int key="NSPeriodicDelay">400</int>
+									<int key="NSPeriodicInterval">75</int>
+								</object>
+								<object class="NSButtonCell" id="138213755">
+									<int key="NSCellFlags">67239424</int>
+									<int key="NSCellFlags2">0</int>
+									<string key="NSContents">Radio</string>
+									<reference key="NSSupport" ref="111849803"/>
+									<reference key="NSControlView" ref="767130651"/>
+									<int key="NSButtonFlags">1211912703</int>
+									<int key="NSButtonFlags2">128</int>
+									<reference key="NSNormalImage" ref="360097870"/>
+									<reference key="NSAlternateImage" ref="504559315"/>
+									<int key="NSPeriodicDelay">400</int>
+									<int key="NSPeriodicInterval">75</int>
+								</object>
+								<object class="NSButtonCell" id="1038275073">
+									<int key="NSCellFlags">67239424</int>
+									<int key="NSCellFlags2">0</int>
+									<string key="NSContents">Radio</string>
+									<reference key="NSSupport" ref="111849803"/>
+									<reference key="NSControlView" ref="767130651"/>
+									<int key="NSButtonFlags">1211912703</int>
+									<int key="NSButtonFlags2">128</int>
+									<reference key="NSNormalImage" ref="360097870"/>
+									<reference key="NSAlternateImage" ref="504559315"/>
+									<int key="NSPeriodicDelay">400</int>
+									<int key="NSPeriodicInterval">75</int>
+								</object>
+								<object class="NSButtonCell" id="1065881531">
+									<int key="NSCellFlags">67239424</int>
+									<int key="NSCellFlags2">0</int>
+									<string key="NSContents">Radio</string>
+									<reference key="NSSupport" ref="111849803"/>
+									<reference key="NSControlView" ref="767130651"/>
+									<int key="NSButtonFlags">1211912703</int>
+									<int key="NSButtonFlags2">128</int>
+									<object class="NSImage" key="NSNormalImage">
+										<int key="NSImageFlags">549453824</int>
+										<string key="NSSize">{18, 18}</string>
+										<object class="NSMutableArray" key="NSReps">
+											<bool key="EncodedWithXMLCoder">YES</bool>
+											<object class="NSArray">
+												<bool key="EncodedWithXMLCoder">YES</bool>
+												<reference ref="8"/>
+												<object class="NSBitmapImageRep">
+													<object class="NSData" key="NSTIFFRepresentation">
+														<bytes key="NS.bytes">TU0AKgAABRgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAwAAAAMAAAADAAAAAwAAAAAAAAAA
+AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAwAAADwRERGLJycnySsrK/A1NTXw
+IyMjyRwcHIsJCQk8AAAAAwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFFRUVdVBQUOCoqKj/
+29vb//n5+f/6+vr/2tra/6qqqv9UVFTgHx8fdQAAAAUAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAUZGRl5
+dXV198PDw//8/Pz////////////////////////////U1NT/fHx89yUlJXkAAAAFAAAAAAAAAAAAAAAA
+AAAAAxEREUZqamrmtbW1/+3t7f/+/v7//v7+//7+/v/9/f3//f39//39/f/39/f/xMTE/3d3d+YZGRlG
+AAAAAwAAAAAAAAAAAAAACkJCQqGtra3/xsbG/+vr6//y8vL/9fX1//X19f/z8/P/9fX1//Ly8v/u7u7/
+0tLS/6+vr/9KSkqhAAAACgAAAAAAAAAAAAAAF3h4eN2/v7//z8/P/93d3f/q6ur/7+/v/+/v7//w8PD/
+7e3t/+3t7f/i4uL/zs7O/8XFxf98fHzdAAAAFwAAAAAAAAADAAAAJKSkpPjOzs7/2dnZ/+Dg4P/i4uL/
+5eXl/+bm5v/n5+f/5eXl/+Li4v/e3t7/2tra/9DQ0P+srKz4AAAAJAAAAAMAAAADAAAALrCwsPrW1tb/
+3t7e/+Tk5P/p6en/6+vr/+zs7P/p6en/6+vr/+fn5//k5OT/4ODg/9nZ2f+zs7P6AAAALgAAAAMAAAAD
+AAAALp2dnezg4OD/5eXl/+rq6v/u7u7/8PDw//Dw8P/x8fH/8PDw/+7u7v/q6ur/5ubm/+Hh4f+ZmZns
+AAAALgAAAAMAAAADAAAAJG5ubs/l5eX/6enp/+/v7//y8vL/9vb2//r6+v/5+fn/9/f3//b29v/x8fH/
+6+vr/+Tk5P9ra2vPAAAAJAAAAAMAAAAAAAAAFy4uLpPCwsL67Ozs//Pz8//5+fn//v7+//7+/v/+/v7/
+/v7+//v7+//19fX/8PDw/8LCwvosLCyTAAAAFwAAAAAAAAAAAAAACgAAAENfX1/S5OTk/vn5+f/+/v7/
+///////////////////////////8/Pz/5ubm/l9fX9IAAABDAAAACgAAAAAAAAAAAAAAAwAAABcAAABl
+YmJi3NLS0v3////////////////////////////////V1dX9ZGRk3AAAAGUAAAAXAAAAAwAAAAAAAAAA
+AAAAAAAAAAUAAAAfAAAAZTMzM8KAgIDwv7+//O3t7f/t7e3/v7+//ICAgPAzMzPCAAAAZQAAAB8AAAAF
+AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFAAAAFwAAAEMAAAB3AAAAnwAAALMAAACzAAAAnwAAAHcAAABD
+AAAAFwAAAAUAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAwAAAAoAAAAXAAAAJAAAAC4AAAAu
+AAAAJAAAABcAAAAKAAAAAwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+AAAAAwAAAAMAAAADAAAAAwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADgEAAAMAAAABABIAAAEB
+AAMAAAABABIAAAECAAMAAAAEAAAFxgEDAAMAAAABAAEAAAEGAAMAAAABAAIAAAERAAQAAAABAAAACAES
+AAMAAAABAAEAAAEVAAMAAAABAAQAAAEWAAMAAAABBxwAAAEXAAQAAAABAAAFEAEcAAMAAAABAAEAAAFS
+AAMAAAABAAEAAAFTAAMAAAAEAAAFzodzAAcAAAwYAAAF1gAAAAAACAAIAAgACAABAAEAAQABAAAMGGFw
+cGwCAAAAbW50clJHQiBYWVogB9YABAADABMALAASYWNzcEFQUEwAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+AAAAAPbWAAEAAAAA0y1hcHBs2U706y3Sst1fqit5+wYbUQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+AAAAAAAOclhZWgAAASwAAAAUZ1hZWgAAAUAAAAAUYlhZWgAAAVQAAAAUd3RwdAAAAWgAAAAUY2hhZAAA
+AXwAAAAsclRSQwAAAagAAAAOZ1RSQwAAAbgAAAAOYlRSQwAAAcgAAAAOdmNndAAAAdgAAAMSbmRpbgAA
+BOwAAAY+ZGVzYwAACywAAABkZHNjbQAAC5AAAAAubW1vZAAAC8AAAAAoY3BydAAAC+gAAAAtWFlaIAAA
+AAAAAF1KAAA0kQAACCVYWVogAAAAAAAAdCAAALRgAAAjPVhZWiAAAAAAAAAlbAAAFyoAAKfDWFlaIAAA
+AAAAAPNSAAEAAAABFs9zZjMyAAAAAAABDEIAAAXe///zJgAAB5IAAP2R///7ov///aMAAAPcAADAbGN1
+cnYAAAAAAAAAAQHNAABjdXJ2AAAAAAAAAAEBzQAAY3VydgAAAAAAAAABAc0AAHZjZ3QAAAAAAAAAAAAD
+AQAAAQACBAUGBwkKCw0ODxASExQWFxgaGxweHyAiIyQmJygpKywtLzAxMjM1Njc4OTs8PT5AQUJDREZH
+SElKS0xOT1BRUlNUVVZXWFlaW1xdXl9hYmNkZWZnaGlqa2xtbm9wcXJzdHV2d3h5ent8fX5/gIGCg4SF
+hoeIiYqLjI2Oj5CRkpOUlZaXmJmam5ydnZ6foKGio6SlpqanqKmqq6ytra6vsLGysrO0tba3uLi5uru8
+vL2+v8DBwcLDxMXGxsfIycrKy8zNzs7P0NHS0tPU1dbW19jZ2drb3Nzd3t/g4eLi4+Tl5ufo6enq6+zt
+7u/w8fHy8/T19vf4+fr7/P3+/v8AAgMEBQYHCAkKCwwNDg8QERITFBUWFxgZGhscHR8gISIjJCUnKCkq
+Ky0uLzAxMzQ1Njc4OTo7PD0/QEFCQ0RFRkdISUpLTE1OT1BRUlNUVVZXWFlaWltcXV5fYGFiY2RlZmdo
+aWprbG1ub3BxcnN0dXZ3d3h5ent8fH1+f4CBgoKDhIWGh4iIiYqLjI2Oj5CRkpOUlJWWl5iZmpucnZ2e
+n6ChoqOkpaamp6ipqqusra6vsLCxsrO0tba3uLm5uru8vb6/wMHCw8TFx8jJysvMzc7P0NDR0tPU1dbX
+2Nna29ze3+Dh4uPk5ebn6err7O3u7/Hy8/T19vf5+vv8/f7/AAIDAwQFBgcICQoKCwwNDg8QERITFBUW
+FxgZGhscHR4fICEiIyQlJicoKSorLC0uLzAxMjM0NTY3ODg5Ojs8PT4+P0BBQkNDREVGR0hJSUpLTE1O
+Tk9QUVJSU1RVVVZXWFhZWltbXF1eXl9gYWFiY2RkZWZnZ2hpaWprbGxtbm5vcHFxcnNzdHV1dnd4eHl6
+ent8fH1+fn+AgYGCg4SEhYaHiImJiouMjY6Oj5CRkpOTlJWWl5iZmZqbnJ2en6ChoqOkpaanqKmqq6yt
+rq+xsrO0tba3uLq7vL2+wMHDxMbHycrMzs/R0tTW19nb3d7g4uTm6Ors7vDy9Pb4+vz+/wAAbmRpbgAA
+AAAAAAY2AACXGgAAVjoAAFPKAACJ3gAAJ8IAABaoAABQDQAAVDkAAiuFAAIZmQABeFEAAwEAAAIAAAAA
+AAEABgANABcAIwAxAEAAUgBlAHsAkwCrAMUA4gD/AR8BPwFhAYUBqgHQAfgCIAJLAncCpQLSAwIDMwNl
+A5gDzgQFBD0EdQSvBOsFKQVnBacF6AYqBm4GtQb8B0UHkgfkCDkIkAjnCT4JmAn0ClAKrQsLC2sLygwq
+DIwM8Q1XDcAOKA6SDv4PbA/bEE0QxBE7EbQSMRKwEzITuRREFNAVYBXxFocXHhfAGGIZBBmsGlQa+RuU
+HC4czh1yHhQeux9jIA0gvCFoIhkizyOJJEEk+SW6JnknOygFKMspkypiKzIsASzXLawuhy9gMD4xGzH8
+MtszvzSgNYY2cjdcOEw5OTorOxs8CD0EPfU+6z/nQOFB2ELUQ9VE00XcRttH5EjxSgBLCUwdTTFOUE9v
+UI9Rt1LdVAVVNlZsV6VY4FohW21ct135X09goGH0Y0tkqGYFZ19oxGova5ptCG54b/BxbnLsdG119Xd/
+eQh6knwqfcV/W4D4gpSEO4Xih4CJKorYjIqOOY/jkZuTWJUOlsyYiZpSnB6d4Z+soX+jWqUvpxOo+6rj
+rMuuwLC4sra0rra0uL+60LzfvwDBHcLdxLXGhchYyi7MCs3lz7rRmtOA1WPXR9kq2xPc/97s4M/iveSn
+5o3obupT7ELuLPAM8fLz0PW396H5f/tZ/T3//wAAAAEAAwALABYAJQA3AE0AZQCBAJ8AwQDlAQsBNQFh
+AZABwQH1AisCZAKfAtwDHANfA6MD6gQ0BH8EzQT1BR0FcAXEBhsGdAbPBy0HXAeMB+4IUgi4CSAJVAmK
+CfYKZArVC0cLgQu8DDIMqw0mDaIOIQ6hDyQPqRAvELgQ/RFDEc8SXRLuE4AUFRSrFUMV3RZ5FxcXthhY
+GPwZoRpIGvEbnBxJHPgdqB5bHw8fxSB9ITch8iKwJDAk8yW3Jn4nRigQKNwpqSp5K0osHCzxLccuoC95
+MFUxMzISMvMz1TS5NaA2hzdxOFw5STo4Oyg8Gj4DPvs/9EDuQepD6ETpRexG8Uf3SP9LFEwhTTBOQE9S
+UGZSklOrVMVV4Vb/WB5ZP1phW4Vcq13SXvthUmJ/Y69k4GYSZ0dofGm0au1tZG6ib+FxInJlc6l073Y2
+d396FXtjfLJ+A39VgKmB/4NWhK+GCYjCiiGLgYzjjkePrJESknuT5Ja8mCuZm5sMnH+d9J9qoOGiWqPV
+pVGmz6eOqE6pzqtRrNSuWq/gsWmy8rR+tgu5Kbq6vE294b93wQ7Cp8RBxd3He8kZyrrLisxbzf/Po9FK
+0vHUm9ZF1/HZn9tO3Cbc/96x4GTiGePQ5YjnQegf6Pzquex27jbv9/G583z0X/VC9wj40Pqa/GX+Mf//
+AAAAAQADAAsAJQA3AE0AZQCBAJ8AwQELATUBYQGQAcEB9QIrAmQCnwLcAxwDXwOjA+oENAR/BM0FHQVw
+BcQGGwZ0Bs8HLQeMB+4IUgi4CSAJign2CmQK1QtHC7wMMgyrDSYNog4hDqEPJA+pEC8QuBFDEl0S7hOA
+FBUUqxVDFnkXFxe2GFgY/BpIGvEbnBxJHPgdqB8PH8UgfSE3IfIjbyQwJPMltydGKBAo3Cp5K0osHC3H
+LqAveTEzMhIy8zS5NaA2hzhcOUk6ODwaPQ4+Az/0QO5C6EPoROlG8Uf3SglLFEwhTkBPUlF7UpJUxVXh
+Vv9ZP1phXKtd0mAlYVJjr2TgZhJofGm0au1tZG6ib+FxInJldO92Nnd/eMl6FXyyfgN/VYCpgf+Er4YJ
+h2WIwoohi4GOR4+skRKSe5PklVCWvJgrmZubDJx/nfSfaqDholqj1aVRps+oTqnOq1Gs1K2Xrlqv4LFp
+svK0frYLt5m5Kbnxurq8Tb3hv3fBDsHawqfEQcUPxd3He8hKyRnKusuKzFvN/87Rz6PQdtFK0vHTxtSb
+1kXXG9fx2MjZn9tO3Cbc/93Y3rHfiuBk4hni9ePQ5KzliOZk50HoH+j86drqueuX7HbtVu427xbv9/DX
+8bnymvN89F/1QvYl9wj37PjQ+bX6mvt//GX9S/4x//8AAGRlc2MAAAAAAAAACkNvbG9yIExDRAAAAAAA
+AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+AAAAAAAAAAAAAAAAAABtbHVjAAAAAAAAAAEAAAAMZW5VUwAAABIAAAAcAEMAbwBsAG8AcgAgAEwAQwBE
+AABtbW9kAAAAAAAABhAAAJxOAAAAAL5zkQAAAAAAAAAAAAAAAAAAAAAAdGV4dAAAAABDb3B5cmlnaHQg
+QXBwbGUgQ29tcHV0ZXIsIEluYy4sIDIwMDUAAAAAA</bytes>
+													</object>
+												</object>
+											</object>
+										</object>
+										<reference key="NSColor" ref="41951801"/>
+									</object>
+									<reference key="NSAlternateImage" ref="504559315"/>
+									<int key="NSPeriodicDelay">400</int>
+									<int key="NSPeriodicInterval">75</int>
+								</object>
+								<object class="NSButtonCell" id="1033929450">
+									<int key="NSCellFlags">67239424</int>
+									<int key="NSCellFlags2">0</int>
+									<string key="NSContents">Radio</string>
+									<reference key="NSSupport" ref="111849803"/>
+									<reference key="NSControlView" ref="767130651"/>
+									<int key="NSButtonFlags">1211912703</int>
+									<int key="NSButtonFlags2">128</int>
+									<reference key="NSNormalImage" ref="360097870"/>
+									<reference key="NSAlternateImage" ref="504559315"/>
+									<int key="NSPeriodicDelay">400</int>
+									<int key="NSPeriodicInterval">75</int>
+								</object>
+								<object class="NSButtonCell" id="291824855">
+									<int key="NSCellFlags">67239424</int>
+									<int key="NSCellFlags2">0</int>
+									<string key="NSContents">Radio</string>
+									<reference key="NSSupport" ref="111849803"/>
+									<reference key="NSControlView" ref="767130651"/>
+									<int key="NSButtonFlags">1211912703</int>
+									<int key="NSButtonFlags2">128</int>
+									<reference key="NSNormalImage" ref="360097870"/>
+									<reference key="NSAlternateImage" ref="504559315"/>
+									<int key="NSPeriodicDelay">400</int>
+									<int key="NSPeriodicInterval">75</int>
+								</object>
+								<object class="NSButtonCell" id="16741473">
+									<int key="NSCellFlags">67239424</int>
+									<int key="NSCellFlags2">0</int>
+									<string key="NSContents">Radio</string>
+									<reference key="NSSupport" ref="111849803"/>
+									<reference key="NSControlView" ref="767130651"/>
+									<int key="NSButtonFlags">1211912703</int>
+									<int key="NSButtonFlags2">128</int>
+									<reference key="NSNormalImage" ref="360097870"/>
+									<reference key="NSAlternateImage" ref="504559315"/>
+									<int key="NSPeriodicDelay">400</int>
+									<int key="NSPeriodicInterval">75</int>
+								</object>
+								<object class="NSButtonCell" id="360506081">
+									<int key="NSCellFlags">67239424</int>
+									<int key="NSCellFlags2">0</int>
+									<string key="NSContents">Radio</string>
+									<reference key="NSSupport" ref="111849803"/>
+									<reference key="NSControlView" ref="767130651"/>
+									<int key="NSButtonFlags">1211912703</int>
+									<int key="NSButtonFlags2">128</int>
+									<reference key="NSNormalImage" ref="360097870"/>
+									<reference key="NSAlternateImage" ref="504559315"/>
+									<int key="NSPeriodicDelay">400</int>
+									<int key="NSPeriodicInterval">75</int>
+								</object>
+								<object class="NSButtonCell" id="930824054">
+									<int key="NSCellFlags">67239424</int>
+									<int key="NSCellFlags2">0</int>
+									<string key="NSContents">Radio</string>
+									<reference key="NSSupport" ref="111849803"/>
+									<reference key="NSControlView" ref="767130651"/>
+									<int key="NSButtonFlags">1211912703</int>
+									<int key="NSButtonFlags2">128</int>
+									<reference key="NSNormalImage" ref="360097870"/>
+									<reference key="NSAlternateImage" ref="504559315"/>
+									<int key="NSPeriodicDelay">400</int>
+									<int key="NSPeriodicInterval">75</int>
+								</object>
+								<object class="NSButtonCell" id="530942939">
+									<int key="NSCellFlags">67239424</int>
+									<int key="NSCellFlags2">0</int>
+									<string key="NSContents">Radio</string>
+									<reference key="NSSupport" ref="111849803"/>
+									<reference key="NSControlView" ref="767130651"/>
+									<int key="NSButtonFlags">1211912703</int>
+									<int key="NSButtonFlags2">128</int>
+									<reference key="NSNormalImage" ref="360097870"/>
+									<reference key="NSAlternateImage" ref="504559315"/>
+									<int key="NSPeriodicDelay">400</int>
+									<int key="NSPeriodicInterval">75</int>
+								</object>
+								<object class="NSButtonCell" id="581063128">
+									<int key="NSCellFlags">67239424</int>
+									<int key="NSCellFlags2">0</int>
+									<string key="NSContents">Radio</string>
+									<reference key="NSSupport" ref="111849803"/>
+									<reference key="NSControlView" ref="767130651"/>
+									<int key="NSButtonFlags">1211912703</int>
+									<int key="NSButtonFlags2">128</int>
+									<reference key="NSNormalImage" ref="360097870"/>
+									<reference key="NSAlternateImage" ref="504559315"/>
+									<int key="NSPeriodicDelay">400</int>
+									<int key="NSPeriodicInterval">75</int>
+								</object>
+								<object class="NSButtonCell" id="277569562">
+									<int key="NSCellFlags">67239424</int>
+									<int key="NSCellFlags2">0</int>
+									<string key="NSContents">Radio</string>
+									<reference key="NSSupport" ref="111849803"/>
+									<reference key="NSControlView" ref="767130651"/>
+									<int key="NSButtonFlags">1211912703</int>
+									<int key="NSButtonFlags2">128</int>
+									<reference key="NSNormalImage" ref="360097870"/>
+									<reference key="NSAlternateImage" ref="504559315"/>
+									<int key="NSPeriodicDelay">400</int>
+									<int key="NSPeriodicInterval">75</int>
+								</object>
+								<object class="NSButtonCell" id="357774730">
+									<int key="NSCellFlags">67239424</int>
+									<int key="NSCellFlags2">0</int>
+									<string key="NSContents">Radio</string>
+									<reference key="NSSupport" ref="111849803"/>
+									<reference key="NSControlView" ref="767130651"/>
+									<int key="NSButtonFlags">1211912703</int>
+									<int key="NSButtonFlags2">128</int>
+									<reference key="NSNormalImage" ref="360097870"/>
+									<reference key="NSAlternateImage" ref="504559315"/>
+									<int key="NSPeriodicDelay">400</int>
+									<int key="NSPeriodicInterval">75</int>
+								</object>
+								<object class="NSButtonCell" id="406417436">
+									<int key="NSCellFlags">67239424</int>
+									<int key="NSCellFlags2">0</int>
+									<string key="NSContents">Radio</string>
+									<reference key="NSSupport" ref="111849803"/>
+									<reference key="NSControlView" ref="767130651"/>
+									<int key="NSButtonFlags">1211912703</int>
+									<int key="NSButtonFlags2">128</int>
+									<reference key="NSNormalImage" ref="360097870"/>
+									<reference key="NSAlternateImage" ref="504559315"/>
+									<int key="NSPeriodicDelay">400</int>
+									<int key="NSPeriodicInterval">75</int>
+								</object>
+								<object class="NSButtonCell" id="676924064">
+									<int key="NSCellFlags">67239424</int>
+									<int key="NSCellFlags2">0</int>
+									<string key="NSContents">Radio</string>
+									<reference key="NSSupport" ref="111849803"/>
+									<reference key="NSControlView" ref="767130651"/>
+									<int key="NSButtonFlags">1211912703</int>
+									<int key="NSButtonFlags2">128</int>
+									<reference key="NSNormalImage" ref="360097870"/>
+									<reference key="NSAlternateImage" ref="504559315"/>
+									<int key="NSPeriodicDelay">400</int>
+									<int key="NSPeriodicInterval">75</int>
+								</object>
+								<object class="NSButtonCell" id="911468005">
+									<int key="NSCellFlags">67239424</int>
+									<int key="NSCellFlags2">0</int>
+									<string key="NSContents">Radio</string>
+									<reference key="NSSupport" ref="111849803"/>
+									<reference key="NSControlView" ref="767130651"/>
+									<int key="NSButtonFlags">1211912703</int>
+									<int key="NSButtonFlags2">128</int>
+									<reference key="NSNormalImage" ref="360097870"/>
+									<reference key="NSAlternateImage" ref="504559315"/>
+									<int key="NSPeriodicDelay">400</int>
+									<int key="NSPeriodicInterval">75</int>
+								</object>
+								<object class="NSButtonCell" id="883484497">
+									<int key="NSCellFlags">67239424</int>
+									<int key="NSCellFlags2">0</int>
+									<string key="NSContents">Radio</string>
+									<reference key="NSSupport" ref="111849803"/>
+									<reference key="NSControlView" ref="767130651"/>
+									<int key="NSButtonFlags">1211912703</int>
+									<int key="NSButtonFlags2">128</int>
+									<reference key="NSNormalImage" ref="360097870"/>
+									<reference key="NSAlternateImage" ref="504559315"/>
+									<int key="NSPeriodicDelay">400</int>
+									<int key="NSPeriodicInterval">75</int>
+								</object>
+								<object class="NSButtonCell" id="316555328">
+									<int key="NSCellFlags">67239424</int>
+									<int key="NSCellFlags2">0</int>
+									<string key="NSContents">Radio</string>
+									<reference key="NSSupport" ref="111849803"/>
+									<reference key="NSControlView" ref="767130651"/>
+									<int key="NSButtonFlags">1211912703</int>
+									<int key="NSButtonFlags2">128</int>
+									<reference key="NSNormalImage" ref="360097870"/>
+									<reference key="NSAlternateImage" ref="504559315"/>
+									<int key="NSPeriodicDelay">400</int>
+									<int key="NSPeriodicInterval">75</int>
+								</object>
+								<object class="NSButtonCell" id="838374391">
+									<int key="NSCellFlags">67239424</int>
+									<int key="NSCellFlags2">0</int>
+									<string key="NSContents">Radio</string>
+									<reference key="NSSupport" ref="111849803"/>
+									<reference key="NSControlView" ref="767130651"/>
+									<int key="NSButtonFlags">1211912703</int>
+									<int key="NSButtonFlags2">128</int>
+									<reference key="NSNormalImage" ref="360097870"/>
+									<reference key="NSAlternateImage" ref="504559315"/>
+									<int key="NSPeriodicDelay">400</int>
+									<int key="NSPeriodicInterval">75</int>
+								</object>
+								<object class="NSButtonCell" id="731661901">
+									<int key="NSCellFlags">67239424</int>
+									<int key="NSCellFlags2">0</int>
+									<string key="NSContents">Radio</string>
+									<reference key="NSSupport" ref="111849803"/>
+									<reference key="NSControlView" ref="767130651"/>
+									<int key="NSButtonFlags">1211912703</int>
+									<int key="NSButtonFlags2">128</int>
+									<reference key="NSNormalImage" ref="360097870"/>
+									<reference key="NSAlternateImage" ref="504559315"/>
+									<int key="NSPeriodicDelay">400</int>
+									<int key="NSPeriodicInterval">75</int>
+								</object>
+								<object class="NSButtonCell" id="11878620">
+									<int key="NSCellFlags">67239424</int>
+									<int key="NSCellFlags2">0</int>
+									<string key="NSContents">Radio</string>
+									<reference key="NSSupport" ref="111849803"/>
+									<reference key="NSControlView" ref="767130651"/>
+									<int key="NSButtonFlags">1211912703</int>
+									<int key="NSButtonFlags2">128</int>
+									<reference key="NSNormalImage" ref="360097870"/>
+									<reference key="NSAlternateImage" ref="504559315"/>
+									<int key="NSPeriodicDelay">400</int>
+									<int key="NSPeriodicInterval">75</int>
+								</object>
+								<object class="NSButtonCell" id="677195126">
+									<int key="NSCellFlags">67239424</int>
+									<int key="NSCellFlags2">0</int>
+									<string key="NSContents">Radio</string>
+									<reference key="NSSupport" ref="111849803"/>
+									<reference key="NSControlView" ref="767130651"/>
+									<int key="NSButtonFlags">1211912703</int>
+									<int key="NSButtonFlags2">128</int>
+									<reference key="NSNormalImage" ref="360097870"/>
+									<reference key="NSAlternateImage" ref="504559315"/>
+									<int key="NSPeriodicDelay">400</int>
+									<int key="NSPeriodicInterval">75</int>
+								</object>
+								<object class="NSButtonCell" id="317098256">
+									<int key="NSCellFlags">67239424</int>
+									<int key="NSCellFlags2">0</int>
+									<string key="NSContents">Radio</string>
+									<reference key="NSSupport" ref="111849803"/>
+									<reference key="NSControlView" ref="767130651"/>
+									<int key="NSButtonFlags">1211912703</int>
+									<int key="NSButtonFlags2">128</int>
+									<reference key="NSNormalImage" ref="360097870"/>
+									<reference key="NSAlternateImage" ref="504559315"/>
+									<int key="NSPeriodicDelay">400</int>
+									<int key="NSPeriodicInterval">75</int>
+								</object>
+							</object>
+							<string key="NSCellSize">{105, 30}</string>
+							<string key="NSIntercellSpacing">{4, 2}</string>
+							<int key="NSMatrixFlags">1151868928</int>
+							<string key="NSCellClass">NSActionCell</string>
+							<object class="NSButtonCell" key="NSProtoCell" id="182787736">
+								<int key="NSCellFlags">67239424</int>
+								<int key="NSCellFlags2">0</int>
+								<string key="NSContents">Radio</string>
+								<reference key="NSSupport" ref="111849803"/>
+								<int key="NSButtonFlags">1211912703</int>
+								<int key="NSButtonFlags2">128</int>
+								<object class="NSImage" key="NSNormalImage">
+									<int key="NSImageFlags">549453824</int>
+									<string key="NSSize">{18, 18}</string>
+									<object class="NSMutableArray" key="NSReps">
+										<bool key="EncodedWithXMLCoder">YES</bool>
+										<object class="NSArray">
+											<bool key="EncodedWithXMLCoder">YES</bool>
+											<reference ref="8"/>
+											<object class="NSBitmapImageRep">
+												<object class="NSData" key="NSTIFFRepresentation">
+													<bytes key="NS.bytes">TU0AKgAABRgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAwAAAAMAAAADAAAAAwAAAAAAAAAA
+AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAwAAADwRERGLJycnySsrK/A1NTXw
+IyMjyRwcHIsJCQk8AAAAAwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFFRUVdVBQUOCoqKj/
+29vb//n5+f/6+vr/2tra/6qqqv9UVFTgHx8fdQAAAAUAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAUZGRl5
+dXV198PDw//8/Pz////////////////////////////U1NT/fHx89yUlJXkAAAAFAAAAAAAAAAAAAAAA
+AAAAAxEREUZqamrmtbW1/+3t7f/+/v7//v7+//7+/v/9/f3//f39//39/f/39/f/xMTE/3d3d+YZGRlG
+AAAAAwAAAAAAAAAAAAAACkJCQqGtra3/xsbG/+vr6//y8vL/9fX1//X19f/z8/P/9fX1//Ly8v/u7u7/
+0tLS/6+vr/9KSkqhAAAACgAAAAAAAAAAAAAAF3h4eN2/v7//z8/P/93d3f/q6ur/7+/v/+/v7//w8PD/
+7e3t/+3t7f/i4uL/zs7O/8XFxf98fHzdAAAAFwAAAAAAAAADAAAAJKSkpPjOzs7/2dnZ/+Dg4P/i4uL/
+5eXl/+bm5v/n5+f/5eXl/+Li4v/e3t7/2tra/9DQ0P+srKz4AAAAJAAAAAMAAAADAAAALrCwsPrW1tb/
+3t7e/+Tk5P/p6en/6+vr/+zs7P/p6en/6+vr/+fn5//k5OT/4ODg/9nZ2f+zs7P6AAAALgAAAAMAAAAD
+AAAALp2dnezg4OD/5eXl/+rq6v/u7u7/8PDw//Dw8P/x8fH/8PDw/+7u7v/q6ur/5ubm/+Hh4f+ZmZns
+AAAALgAAAAMAAAADAAAAJG5ubs/l5eX/6enp/+/v7//y8vL/9vb2//r6+v/5+fn/9/f3//b29v/x8fH/
+6+vr/+Tk5P9ra2vPAAAAJAAAAAMAAAAAAAAAFy4uLpPCwsL67Ozs//Pz8//5+fn//v7+//7+/v/+/v7/
+/v7+//v7+//19fX/8PDw/8LCwvosLCyTAAAAFwAAAAAAAAAAAAAACgAAAENfX1/S5OTk/vn5+f/+/v7/
+///////////////////////////8/Pz/5ubm/l9fX9IAAABDAAAACgAAAAAAAAAAAAAAAwAAABcAAABl
+YmJi3NLS0v3////////////////////////////////V1dX9ZGRk3AAAAGUAAAAXAAAAAwAAAAAAAAAA
+AAAAAAAAAAUAAAAfAAAAZTMzM8KAgIDwv7+//O3t7f/t7e3/v7+//ICAgPAzMzPCAAAAZQAAAB8AAAAF
+AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFAAAAFwAAAEMAAAB3AAAAnwAAALMAAACzAAAAnwAAAHcAAABD
+AAAAFwAAAAUAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAwAAAAoAAAAXAAAAJAAAAC4AAAAu
+AAAAJAAAABcAAAAKAAAAAwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+AAAAAwAAAAMAAAADAAAAAwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADQEAAAMAAAABABIAAAEB
+AAMAAAABABIAAAECAAMAAAAEAAAFugEDAAMAAAABAAEAAAEGAAMAAAABAAIAAAERAAQAAAABAAAACAES
+AAMAAAABAAEAAAEVAAMAAAABAAQAAAEWAAMAAAABBxwAAAEXAAQAAAABAAAFEAEcAAMAAAABAAEAAAFS
+AAMAAAABAAEAAAFTAAMAAAAEAAAFwgAAAAAACAAIAAgACAABAAEAAQABA</bytes>
+												</object>
+											</object>
+										</object>
+									</object>
+									<reference key="NSColor" ref="41951801"/>
+								</object>
+								<reference key="NSAlternateImage" ref="504559315"/>
+								<int key="NSPeriodicDelay">400</int>
+								<int key="NSPeriodicInterval">75</int>
+							</object>
+							<reference key="NSSelectedCell" ref="374109759"/>
+							<object class="NSColor" key="NSBackgroundColor" id="716487516">
+								<int key="NSColorSpace">6</int>
+								<string key="NSCatalogName">System</string>
+								<string key="NSColorName">controlColor</string>
+								<object class="NSColor" key="NSColor">
+									<int key="NSColorSpace">3</int>
+									<bytes key="NSWhite">MC42NjY2NjY2OQA</bytes>
+								</object>
+							</object>
+							<reference key="NSCellBackgroundColor" ref="484440858"/>
+							<reference key="NSFont" ref="111849803"/>
+						</object>
+						<object class="NSTextField" id="1012995405">
+							<reference key="NSNextResponder" ref="1006"/>
+							<int key="NSvFlags">268</int>
+							<string key="NSFrame">{{204, 242}, {39, 17}}</string>
+							<reference key="NSSuperview" ref="1006"/>
+							<bool key="NSEnabled">YES</bool>
+							<object class="NSTextFieldCell" key="NSCell" id="773610705">
+								<int key="NSCellFlags">68288064</int>
+								<int key="NSCellFlags2">272630784</int>
+								<string key="NSContents">Voice</string>
+								<reference key="NSSupport" ref="111849803"/>
+								<reference key="NSControlView" ref="1012995405"/>
+								<reference key="NSBackgroundColor" ref="716487516"/>
+								<object class="NSColor" key="NSTextColor">
+									<int key="NSColorSpace">6</int>
+									<string key="NSCatalogName">System</string>
+									<string key="NSColorName">controlTextColor</string>
+									<reference key="NSColor" ref="733504598"/>
+								</object>
+							</object>
+						</object>
+					</object>
+					<string key="NSFrameSize">{475, 429}</string>
+					<reference key="NSSuperview"/>
+				</object>
+				<string key="NSScreenRect">{{0, 0}, {1680, 1028}}</string>
+				<string key="NSMaxSize">{3.40282e+38, 3.40282e+38}</string>
+			</object>
+		</object>
+		<object class="IBObjectContainer" key="IBDocument.Objects">
+			<object class="NSMutableArray" key="connectionRecords">
+				<bool key="EncodedWithXMLCoder">YES</bool>
+				<object class="IBConnectionRecord">
+					<object class="IBOutletConnection" key="connection">
+						<string key="label">speechText</string>
+						<reference key="source" ref="1001"/>
+						<reference key="destination" ref="502162398"/>
+					</object>
+					<int key="connectionID">9</int>
+				</object>
+				<object class="IBConnectionRecord">
+					<object class="IBActionConnection" key="connection">
+						<string key="label">startSpeaking:</string>
+						<reference key="source" ref="1001"/>
+						<reference key="destination" ref="1058338364"/>
+					</object>
+					<int key="connectionID">11</int>
+				</object>
+				<object class="IBConnectionRecord">
+					<object class="IBActionConnection" key="connection">
+						<string key="label">stopSpeaking:</string>
+						<reference key="source" ref="1001"/>
+						<reference key="destination" ref="70435651"/>
+					</object>
+					<int key="connectionID">12</int>
+				</object>
+				<object class="IBConnectionRecord">
+					<object class="IBActionConnection" key="connection">
+						<string key="label">buttonPushed:</string>
+						<reference key="source" ref="1001"/>
+						<reference key="destination" ref="767130651"/>
+					</object>
+					<int key="connectionID">32</int>
+				</object>
+				<object class="IBConnectionRecord">
+					<object class="IBOutletConnection" key="connection">
+						<string key="label">buttonMatrix</string>
+						<reference key="source" ref="1001"/>
+						<reference key="destination" ref="767130651"/>
+					</object>
+					<int key="connectionID">33</int>
+				</object>
+			</object>
+			<object class="IBMutableOrderedSet" key="objectRecords">
+				<object class="NSArray" key="orderedObjects">
+					<bool key="EncodedWithXMLCoder">YES</bool>
+					<object class="IBObjectRecord">
+						<int key="objectID">0</int>
+						<object class="NSArray" key="object" id="1002">
+							<bool key="EncodedWithXMLCoder">YES</bool>
+						</object>
+						<reference key="children" ref="1000"/>
+						<nil key="parent"/>
+					</object>
+					<object class="IBObjectRecord">
+						<int key="objectID">-2</int>
+						<reference key="object" ref="1001"/>
+						<reference key="parent" ref="1002"/>
+						<string type="base64-UTF8" key="objectName">RmlsZSdzIE93bmVyA</string>
+					</object>
+					<object class="IBObjectRecord">
+						<int key="objectID">-1</int>
+						<reference key="object" ref="1003"/>
+						<reference key="parent" ref="1002"/>
+						<string key="objectName">First Responder</string>
+					</object>
+					<object class="IBObjectRecord">
+						<int key="objectID">-3</int>
+						<reference key="object" ref="1004"/>
+						<reference key="parent" ref="1002"/>
+						<string key="objectName">Application</string>
+					</object>
+					<object class="IBObjectRecord">
+						<int key="objectID">1</int>
+						<reference key="object" ref="1005"/>
+						<object class="NSMutableArray" key="children">
+							<bool key="EncodedWithXMLCoder">YES</bool>
+							<reference ref="1006"/>
+						</object>
+						<reference key="parent" ref="1002"/>
+					</object>
+					<object class="IBObjectRecord">
+						<int key="objectID">2</int>
+						<reference key="object" ref="1006"/>
+						<object class="NSMutableArray" key="children">
+							<bool key="EncodedWithXMLCoder">YES</bool>
+							<reference ref="577036643"/>
+							<reference ref="502162398"/>
+							<reference ref="760939504"/>
+							<reference ref="1012995405"/>
+							<reference ref="767130651"/>
+						</object>
+						<reference key="parent" ref="1005"/>
+					</object>
+					<object class="IBObjectRecord">
+						<int key="objectID">3</int>
+						<reference key="object" ref="760939504"/>
+						<object class="NSMutableArray" key="children">
+							<bool key="EncodedWithXMLCoder">YES</bool>
+							<reference ref="1058338364"/>
+						</object>
+						<reference key="parent" ref="1006"/>
+					</object>
+					<object class="IBObjectRecord">
+						<int key="objectID">4</int>
+						<reference key="object" ref="1058338364"/>
+						<reference key="parent" ref="760939504"/>
+					</object>
+					<object class="IBObjectRecord">
+						<int key="objectID">5</int>
+						<reference key="object" ref="577036643"/>
+						<object class="NSMutableArray" key="children">
+							<bool key="EncodedWithXMLCoder">YES</bool>
+							<reference ref="70435651"/>
+						</object>
+						<reference key="parent" ref="1006"/>
+					</object>
+					<object class="IBObjectRecord">
+						<int key="objectID">6</int>
+						<reference key="object" ref="70435651"/>
+						<reference key="parent" ref="577036643"/>
+					</object>
+					<object class="IBObjectRecord">
+						<int key="objectID">7</int>
+						<reference key="object" ref="502162398"/>
+						<object class="NSMutableArray" key="children">
+							<bool key="EncodedWithXMLCoder">YES</bool>
+							<reference ref="379084012"/>
+						</object>
+						<reference key="parent" ref="1006"/>
+					</object>
+					<object class="IBObjectRecord">
+						<int key="objectID">8</int>
+						<reference key="object" ref="379084012"/>
+						<reference key="parent" ref="502162398"/>
+					</object>
+					<object class="IBObjectRecord">
+						<int key="objectID">13</int>
+						<reference key="object" ref="767130651"/>
+						<object class="NSMutableArray" key="children">
+							<bool key="EncodedWithXMLCoder">YES</bool>
+							<reference ref="374109759"/>
+							<reference ref="1065881531"/>
+							<reference ref="182787736"/>
+							<reference ref="1033929450"/>
+							<reference ref="740026460"/>
+							<reference ref="138213755"/>
+							<reference ref="291824855"/>
+							<reference ref="357774730"/>
+							<reference ref="911468005"/>
+							<reference ref="930824054"/>
+							<reference ref="406417436"/>
+							<reference ref="360506081"/>
+							<reference ref="530942939"/>
+							<reference ref="883484497"/>
+							<reference ref="316555328"/>
+							<reference ref="277569562"/>
+							<reference ref="838374391"/>
+							<reference ref="16741473"/>
+							<reference ref="676924064"/>
+							<reference ref="1038275073"/>
+							<reference ref="581063128"/>
+							<reference ref="317098256"/>
+							<reference ref="731661901"/>
+							<reference ref="11878620"/>
+							<reference ref="677195126"/>
+						</object>
+						<reference key="parent" ref="1006"/>
+					</object>
+					<object class="IBObjectRecord">
+						<int key="objectID">14</int>
+						<reference key="object" ref="374109759"/>
+						<reference key="parent" ref="767130651"/>
+					</object>
+					<object class="IBObjectRecord">
+						<int key="objectID">15</int>
+						<reference key="object" ref="1065881531"/>
+						<reference key="parent" ref="767130651"/>
+					</object>
+					<object class="IBObjectRecord">
+						<int key="objectID">16</int>
+						<reference key="object" ref="182787736"/>
+						<reference key="parent" ref="767130651"/>
+					</object>
+					<object class="IBObjectRecord">
+						<int key="objectID">17</int>
+						<reference key="object" ref="1033929450"/>
+						<reference key="parent" ref="767130651"/>
+					</object>
+					<object class="IBObjectRecord">
+						<int key="objectID">18</int>
+						<reference key="object" ref="740026460"/>
+						<reference key="parent" ref="767130651"/>
+					</object>
+					<object class="IBObjectRecord">
+						<int key="objectID">19</int>
+						<reference key="object" ref="138213755"/>
+						<reference key="parent" ref="767130651"/>
+					</object>
+					<object class="IBObjectRecord">
+						<int key="objectID">20</int>
+						<reference key="object" ref="291824855"/>
+						<reference key="parent" ref="767130651"/>
+					</object>
+					<object class="IBObjectRecord">
+						<int key="objectID">21</int>
+						<reference key="object" ref="357774730"/>
+						<reference key="parent" ref="767130651"/>
+					</object>
+					<object class="IBObjectRecord">
+						<int key="objectID">22</int>
+						<reference key="object" ref="911468005"/>
+						<reference key="parent" ref="767130651"/>
+					</object>
+					<object class="IBObjectRecord">
+						<int key="objectID">23</int>
+						<reference key="object" ref="930824054"/>
+						<reference key="parent" ref="767130651"/>
+					</object>
+					<object class="IBObjectRecord">
+						<int key="objectID">24</int>
+						<reference key="object" ref="406417436"/>
+						<reference key="parent" ref="767130651"/>
+					</object>
+					<object class="IBObjectRecord">
+						<int key="objectID">25</int>
+						<reference key="object" ref="360506081"/>
+						<reference key="parent" ref="767130651"/>
+					</object>
+					<object class="IBObjectRecord">
+						<int key="objectID">26</int>
+						<reference key="object" ref="530942939"/>
+						<reference key="parent" ref="767130651"/>
+					</object>
+					<object class="IBObjectRecord">
+						<int key="objectID">27</int>
+						<reference key="object" ref="883484497"/>
+						<reference key="parent" ref="767130651"/>
+					</object>
+					<object class="IBObjectRecord">
+						<int key="objectID">28</int>
+						<reference key="object" ref="316555328"/>
+						<reference key="parent" ref="767130651"/>
+					</object>
+					<object class="IBObjectRecord">
+						<int key="objectID">29</int>
+						<reference key="object" ref="277569562"/>
+						<reference key="parent" ref="767130651"/>
+					</object>
+					<object class="IBObjectRecord">
+						<int key="objectID">30</int>
+						<reference key="object" ref="1012995405"/>
+						<object class="NSMutableArray" key="children">
+							<bool key="EncodedWithXMLCoder">YES</bool>
+							<reference ref="773610705"/>
+						</object>
+						<reference key="parent" ref="1006"/>
+					</object>
+					<object class="IBObjectRecord">
+						<int key="objectID">31</int>
+						<reference key="object" ref="773610705"/>
+						<reference key="parent" ref="1012995405"/>
+					</object>
+					<object class="IBObjectRecord">
+						<int key="objectID">34</int>
+						<reference key="object" ref="838374391"/>
+						<reference key="parent" ref="767130651"/>
+					</object>
+					<object class="IBObjectRecord">
+						<int key="objectID">35</int>
+						<reference key="object" ref="16741473"/>
+						<reference key="parent" ref="767130651"/>
+					</object>
+					<object class="IBObjectRecord">
+						<int key="objectID">36</int>
+						<reference key="object" ref="676924064"/>
+						<reference key="parent" ref="767130651"/>
+					</object>
+					<object class="IBObjectRecord">
+						<int key="objectID">37</int>
+						<reference key="object" ref="1038275073"/>
+						<reference key="parent" ref="767130651"/>
+					</object>
+					<object class="IBObjectRecord">
+						<int key="objectID">38</int>
+						<reference key="object" ref="581063128"/>
+						<reference key="parent" ref="767130651"/>
+					</object>
+					<object class="IBObjectRecord">
+						<int key="objectID">44</int>
+						<reference key="object" ref="317098256"/>
+						<reference key="parent" ref="767130651"/>
+					</object>
+					<object class="IBObjectRecord">
+						<int key="objectID">45</int>
+						<reference key="object" ref="731661901"/>
+						<reference key="parent" ref="767130651"/>
+					</object>
+					<object class="IBObjectRecord">
+						<int key="objectID">46</int>
+						<reference key="object" ref="11878620"/>
+						<reference key="parent" ref="767130651"/>
+					</object>
+					<object class="IBObjectRecord">
+						<int key="objectID">47</int>
+						<reference key="object" ref="677195126"/>
+						<reference key="parent" ref="767130651"/>
+					</object>
+				</object>
+			</object>
+			<object class="NSMutableDictionary" key="flattenedProperties">
+				<bool key="EncodedWithXMLCoder">YES</bool>
+				<object class="NSMutableArray" key="dict.sortedKeys">
+					<bool key="EncodedWithXMLCoder">YES</bool>
+					<string>-1.IBPluginDependency</string>
+					<string>-2.IBPluginDependency</string>
+					<string>-3.IBPluginDependency</string>
+					<string>1.IBEditorWindowLastContentRect</string>
+					<string>1.IBPluginDependency</string>
+					<string>1.IBWindowTemplateEditedContentRect</string>
+					<string>1.NSWindowTemplate.visibleAtLaunch</string>
+					<string>1.WindowOrigin</string>
+					<string>1.editorWindowContentRectSynchronizationRect</string>
+					<string>13.IBPluginDependency</string>
+					<string>14.IBPluginDependency</string>
+					<string>15.IBPluginDependency</string>
+					<string>16.IBPluginDependency</string>
+					<string>2.IBPluginDependency</string>
+					<string>3.IBPluginDependency</string>
+					<string>30.IBPluginDependency</string>
+					<string>31.IBPluginDependency</string>
+					<string>4.IBPluginDependency</string>
+					<string>5.IBPluginDependency</string>
+					<string>6.IBPluginDependency</string>
+					<string>7.IBPluginDependency</string>
+					<string>8.IBPluginDependency</string>
+				</object>
+				<object class="NSMutableArray" key="dict.values">
+					<bool key="EncodedWithXMLCoder">YES</bool>
+					<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
+					<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
+					<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
+					<string>{{71, 344}, {475, 429}}</string>
+					<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
+					<string>{{71, 344}, {475, 429}}</string>
+					<integer value="1"/>
+					<string>{196, 240}</string>
+					<string>{{357, 418}, {480, 270}}</string>
+					<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
+					<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
+					<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
+					<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
+					<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
+					<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
+					<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
+					<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
+					<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
+					<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
+					<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
+					<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
+					<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
+				</object>
+			</object>
+			<object class="NSMutableDictionary" key="unlocalizedProperties">
+				<bool key="EncodedWithXMLCoder">YES</bool>
+				<object class="NSArray" key="dict.sortedKeys">
+					<bool key="EncodedWithXMLCoder">YES</bool>
+				</object>
+				<object class="NSMutableArray" key="dict.values">
+					<bool key="EncodedWithXMLCoder">YES</bool>
+				</object>
+			</object>
+			<nil key="activeLocalization"/>
+			<object class="NSMutableDictionary" key="localizations">
+				<bool key="EncodedWithXMLCoder">YES</bool>
+				<object class="NSArray" key="dict.sortedKeys">
+					<bool key="EncodedWithXMLCoder">YES</bool>
+				</object>
+				<object class="NSMutableArray" key="dict.values">
+					<bool key="EncodedWithXMLCoder">YES</bool>
+				</object>
+			</object>
+			<nil key="sourceID"/>
+			<int key="maxID">48</int>
+		</object>
+		<object class="IBClassDescriber" key="IBDocument.Classes">
+			<object class="NSMutableArray" key="referencedPartialClassDescriptions">
+				<bool key="EncodedWithXMLCoder">YES</bool>
+				<object class="IBPartialClassDescription">
+					<string key="className">SpeechController</string>
+					<object class="NSMutableDictionary" key="actions">
+						<bool key="EncodedWithXMLCoder">YES</bool>
+						<object class="NSMutableArray" key="dict.sortedKeys">
+							<bool key="EncodedWithXMLCoder">YES</bool>
+							<string>buttonPushed:</string>
+							<string>startSpeaking:</string>
+							<string>stopSpeaking:</string>
+						</object>
+						<object class="NSMutableArray" key="dict.values">
+							<bool key="EncodedWithXMLCoder">YES</bool>
+							<string>id</string>
+							<string>id</string>
+							<string>id</string>
+						</object>
+					</object>
+					<object class="NSMutableDictionary" key="outlets">
+						<bool key="EncodedWithXMLCoder">YES</bool>
+						<object class="NSMutableArray" key="dict.sortedKeys">
+							<bool key="EncodedWithXMLCoder">YES</bool>
+							<string>buttonMatrix</string>
+							<string>speechText</string>
+						</object>
+						<object class="NSMutableArray" key="dict.values">
+							<bool key="EncodedWithXMLCoder">YES</bool>
+							<string>NSMatrix</string>
+							<string>NSTextField</string>
+						</object>
+					</object>
+					<object class="IBClassDescriptionSource" key="sourceIdentifier">
+						<string key="majorKey">IBUserSource</string>
+						<string key="minorKey"/>
+					</object>
+				</object>
+			</object>
+		</object>
+		<int key="IBDocument.localizationMode">0</int>
+		<nil key="IBDocument.LastKnownRelativeProjectPath"/>
+		<int key="IBDocument.defaultPropertyAccessControl">3</int>
+	</data>
+</archive>
Index: /trunk/contrib/krueger/InterfaceProjects/Speech/speech-controller.lisp
===================================================================
--- /trunk/contrib/krueger/InterfaceProjects/Speech/speech-controller.lisp	(revision 13946)
+++ /trunk/contrib/krueger/InterfaceProjects/Speech/speech-controller.lisp	(revision 13946)
@@ -0,0 +1,112 @@
+;;; speech-controller.lisp
+
+#|
+The MIT license.
+
+Copyright (c) 2009 Paul L. Krueger
+
+Permission is hereby granted, free of charge, to any person obtaining a copy of this software 
+and associated documentation files (the "Software"), to deal in the Software without restriction, 
+including without limitation the rights to use, copy, modify, merge, publish, distribute, 
+sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is 
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all copies or substantial 
+portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT 
+LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. 
+IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, 
+WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE 
+SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+|#
+
+;;; Sample lisp/Cocoa interface that uses a NIB file defined with interface builder;
+;;; A definition is provided for the "SpeechController" class that was specified to interface builder
+;;; as the class of the NIB file owner.
+;;; We manually create an instance of SpeechController and specify it as the owner for the NIB file.
+
+(eval-when (:compile-toplevel :load-toplevel :execute)
+  (require :nib))
+
+(defpackage :speech-controller 
+  (:nicknames :spc)
+  (:use :iu :ccl :common-lisp)
+  (:export test-speech))
+
+(in-package :spc)
+
+(defclass speech-controller (ns:ns-object)
+  ((speech-text :foreign-type :id :accessor speech-text)
+   (button-matrix :foreign-type :id :accessor button-matrix)
+   (speech-synth :accessor speech-synth 
+                 :initform (make-instance ns:ns-speech-synthesizer))
+   (voices :accessor voices 
+           :initform (#/retain (#/availableVoices ns:ns-speech-synthesizer)))
+   (nib-objects :accessor nib-objects :initform nil))
+  (:metaclass ns:+ns-object))
+
+(defmethod initialize-instance :after ((self speech-controller) 
+                                       &key &allow-other-keys)
+  (setf (nib-objects self)
+        (load-nibfile 
+         (truename "ip:Speech;SpeechView.nib") 
+         :nib-owner self
+         :retain-top-objs t))
+  ;; get all of the voice strings and set the names of the radio buttons
+  (dotimes (i (#/count (voices self)))
+    (multiple-value-bind (col row) (floor i 6)
+      (#/setTitle: (#/cellAtRow:column: (button-matrix self) row col)
+                   (#/objectForKey: 
+                    (#/attributesForVoice: ns:ns-speech-synthesizer 
+                                           (#/objectAtIndex: (voices self) i)) 
+                    #&NSVoiceName))))
+  ;; Make sure that the initial voice selected for the speech syntesizer matches 
+  ;; the radio button that is selected at startup. To do that we'll just call our
+  ;; own buttonPushed: method.
+  (#/buttonPushed: self (button-matrix self))
+  ;; we do the following so that ccl:terminate will be called before we are
+  ;; garbage collected and we can release the top-level objects from the NIB 
+  ;; that we retained when loaded
+  (ccl:terminate-when-unreachable self))
+
+(defmethod ccl:terminate ((self speech-controller))
+  (when (speech-synth self)
+    (#/release (speech-synth self)))
+  (when (voices self)
+    (#/release (voices self)))
+  (dolist (top-obj (nib-objects self))
+    (unless (eql top-obj (%null-ptr))
+      (#/release top-obj))))
+
+;; Action methods called as a result of pushing some button
+
+(objc:defmethod (#/startSpeaking: :void) 
+                ((self speech-controller) (s :id))
+  (declare (ignore s))
+  (with-slots (speech-text speech-synth) self
+    (let ((stxt (#/stringValue speech-text)))
+      (when (zerop (#/length stxt))
+        (setf stxt #@"I have nothing to say"))
+      (#/startSpeakingString: speech-synth stxt))))
+
+(objc:defmethod (#/stopSpeaking: :void) 
+                ((self speech-controller) (s :id))
+  (declare (ignore s))
+  (with-slots (speech-synth) self
+    (#/stopSpeaking speech-synth)))
+
+(objc:defmethod (#/buttonPushed: :void) 
+                ((self speech-controller) (button-matrix :id))
+  (let ((row (#/selectedRow button-matrix))
+        (col (#/selectedColumn button-matrix)))
+    (#/setVoice: (speech-synth self) 
+                 (#/objectAtIndex: (voices self) (+ row (* col 6))))))
+  
+;; test funtion
+
+(defun test-speech ()
+  (make-instance 'speech-controller))
+
+(provide :speech-controller)
Index: /trunk/contrib/krueger/InterfaceProjects/Utilities/assoc-array.lisp
===================================================================
--- /trunk/contrib/krueger/InterfaceProjects/Utilities/assoc-array.lisp	(revision 13946)
+++ /trunk/contrib/krueger/InterfaceProjects/Utilities/assoc-array.lisp	(revision 13946)
@@ -0,0 +1,147 @@
+;;; assoc-array.lisp
+
+;; Implements an N-dimensional "array" where indices are arbitrary objects
+;; Implementation creates nested hash-tables
+
+#|
+The MIT license.
+
+Copyright (c) 2010 Paul L. Krueger
+
+Permission is hereby granted, free of charge, to any person obtaining a copy of this software 
+and associated documentation files (the "Software"), to deal in the Software without restriction, 
+including without limitation the rights to use, copy, modify, merge, publish, distribute, 
+sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is 
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all copies or substantial 
+portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT 
+LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. 
+IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, 
+WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE 
+SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+|#
+
+
+(defpackage :interface-utilities
+  (:nicknames :iu)
+  (:export assoc-array
+           assoc-aref
+           mapcar-assoc-array
+           mapcar-hash-keys))
+
+(in-package :iu)
+
+(defclass assoc-array ()
+  ((arr-rank :accessor arr-rank :initarg :rank)
+   (index1-ht :accessor index1-ht)
+   (index-tests :accessor index-tests :initarg :tests)
+   (default-value :accessor default-value :initarg :default))
+  (:default-initargs
+    :rank 2
+    :tests nil
+    :default nil))
+
+(defmethod initialize-instance :after ((self assoc-array) &key tests &allow-other-keys)
+  (setf (index1-ht self) 
+        (make-hash-table :test (or (first tests) #'eql))))
+
+(defmethod assoc-aref ((self assoc-array) &rest indices)
+  (unless (eql (list-length indices) (arr-rank self))
+    (error "Access to ~s requires ~s indices" self (arr-rank self)))
+  (do* ((res (index1-ht self))
+        (index-list indices (rest index-list))
+        (indx (first index-list) (first index-list))
+        (found-next t))
+       ((null index-list) (if found-next
+                            (values res t)
+                            (values (default-value self) nil)))
+    (if found-next
+      (multiple-value-setq (res found-next) (gethash indx res))
+      (return-from assoc-aref (values (default-value self) nil)))))
+
+(defmethod (setf assoc-aref) (new-val (self assoc-array) &rest indices)
+  (unless (eql (list-length indices) (arr-rank self))
+    (error "Access to ~s requires ~s indices" self (arr-rank self)))
+  (let* ((ht (index1-ht self))
+         (last-indx (do* ((dim 1 (1+ dim))
+                          (index-list indices (rest index-list))
+                          (indx (first index-list) (first index-list))
+                          (tests (rest (index-tests self)) (rest tests))
+                          (test (first tests) (first tests)))
+                         ((>= dim (arr-rank self)) indx)
+                      (multiple-value-bind (next-ht found-next) (gethash indx ht)
+                        (unless found-next
+                          (setf next-ht (make-hash-table :test (or test #'eql)))
+                          (setf (gethash indx ht) next-ht))
+                        (setf ht next-ht)))))
+    (setf (gethash last-indx ht) new-val)))
+
+(defmethod mapcar-assoc-array ((func function) (self assoc-array) &rest indices)
+  ;; collects list of results of applying func to each bound index at
+  ;; the next level after the indices provided.
+  (unless (<= (list-length indices) (arr-rank self))
+    (error "Access to ~s requires ~s or fewer indices" self (arr-rank self)))
+  (do* ((res (index1-ht self))
+        (index-list indices (rest index-list))
+        (indx (first index-list) (first index-list))
+        (found-next t))
+       ((null index-list) (when found-next
+                            ;; apply map function to res
+                            (typecase res
+                              (hash-table (mapcar-hash-keys func res))
+                              (cons (mapcar func res))
+                              (sequence (map 'list func res)))))
+    (if found-next
+      (multiple-value-setq (res found-next) (gethash indx res))
+      (return-from mapcar-assoc-array nil))))
+
+(defmethod map-assoc-array ((func function) (self assoc-array) &rest indices)
+  ;; collects list of results of applying func of two arguments to 
+  ;; a bound index at the next level after the indices provided and to
+  ;; the value resulting from indexing the array by appending that index
+  ;; to those provided as initial arguments. This would typically be used
+  ;; to get a list of all keys and values at the lowest level of an
+  ;; assoc-array.
+  (unless (<= (list-length indices) (arr-rank self))
+    (error "Access to ~s requires ~s or fewer indices" self (arr-rank self)))
+  (do* ((res (index1-ht self))
+        (index-list indices (rest index-list))
+        (indx (first index-list) (first index-list))
+        (found-next t))
+       ((null index-list) (when found-next
+                            ;; apply map function to res
+                            (typecase res
+                              (hash-table (map-hash-keys func res))
+                              (cons (mapcar func res nil))
+                              (sequence (map 'list func res nil)))))
+    (if found-next
+      (multiple-value-setq (res found-next) (gethash indx res))
+      (return-from map-assoc-array nil))))
+
+(defun print-last-level (key val)
+  (format t "~%Key = ~s   Value = ~s" key val))
+
+(defmethod last-level ((self assoc-array) &rest indices)
+  (apply #'map-assoc-array #'print-last-level self indices))
+
+(defmethod map-hash-keys ((func function) (self hash-table))
+  (let ((res nil))
+    (maphash #'(lambda (key val)
+                 (push (funcall func key val) res))
+             self)
+    (nreverse res)))
+
+(defmethod mapcar-hash-keys ((func function) (self hash-table))
+  (let ((res nil))
+    (maphash #'(lambda (key val)
+                 (declare (ignore val))
+                 (push (funcall func key) res))
+             self)
+    (nreverse res)))
+
+(provide :assoc-array)
+      
Index: /trunk/contrib/krueger/InterfaceProjects/Utilities/date.lisp
===================================================================
--- /trunk/contrib/krueger/InterfaceProjects/Utilities/date.lisp	(revision 13946)
+++ /trunk/contrib/krueger/InterfaceProjects/Utilities/date.lisp	(revision 13946)
@@ -0,0 +1,290 @@
+;; date.lisp
+
+#|
+The MIT license.
+
+Copyright (c) 2010 Paul L. Krueger
+
+Permission is hereby granted, free of charge, to any person obtaining a copy of this software 
+and associated documentation files (the "Software"), to deal in the Software without restriction, 
+including without limitation the rights to use, copy, modify, merge, publish, distribute, 
+sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is 
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all copies or substantial 
+portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT 
+LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. 
+IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, 
+WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE 
+SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+|#
+
+(defpackage :interface-utilities
+  (:nicknames :iu)
+  (:export now dt dt-diff day-of-wk abbrev-day-of-wk day-char
+           next-day prev-day inc-months next-month prev-month
+           inc-years next-year  prev-year same-day-p days-to-sec
+           do-dates do-interval-dates do-months days-between 
+           days-from +days date-string short-date-string 
+           mmdd-string mmddyy-list dt-yr date-list day-set-bit
+           add-day remove-day has-day-p in-dayset-p day-set
+           num-days-in-dayset random-date intl-string-dt
+           lisp-to-ns-date ns-to-lisp-date))
+
+(in-package :iu)
+
+;;; some general date utility routines
+
+(defun now ()
+  (get-universal-time))
+
+(defun dt (mm dd yy &optional (hour 12) (min 0) (sec 0) (zone nil))
+  ;; yy can be 2 or 4 digit year
+  (if zone
+    (encode-universal-time sec min hour dd mm yy zone)
+    (encode-universal-time sec min hour dd mm yy)))
+
+(defun dt-diff (dt1 dt2)
+  ;; computes the number of days between the two dates
+  (round (abs (- dt1 dt2)) 86400))
+
+(defun day-of-wk (dt)
+  (multiple-value-bind (sec min hr dd mm yr day dst zone)
+                       (decode-universal-time dt)
+    (declare (ignore sec min hr dd mm yr dst zone))
+    (nth day '(monday tuesday wednesday thursday friday saturday sunday))))
+
+(defun abbrev-day-of-wk (dt)
+  (multiple-value-bind (sec min hr dd mm yr day dst zone)
+                       (decode-universal-time dt)
+    (declare (ignore sec min hr dd mm yr dst zone))
+    (nth day '(mon tue wed thu fri sat sun))))
+
+(defun day-char (dt)
+  (multiple-value-bind (sec min hr dd mm yr day dst zone)
+                       (decode-universal-time dt)
+    (declare (ignore sec min hr dd mm yr dst zone))
+    (nth day '(m t w t f s s))))
+
+(defun next-day (dt)
+  (+ 86400 dt))
+
+(defun prev-day (dt)
+  (- dt 86400))
+
+(defun inc-months (dt num-mm)
+  (multiple-value-bind (sec min hr dd mm yr day dst zone)
+                       (decode-universal-time dt)
+    (declare (ignore day dst))
+    (multiple-value-bind (yy-inc new-mm)
+                         (floor (+ num-mm mm -1) 12)
+      (encode-universal-time sec 
+                             min 
+                             hr 
+                             dd 
+                             (1+ new-mm)
+                             (+ yr yy-inc)
+                             zone))))
+(defun next-month (dt)
+  (inc-months dt 1))
+                           
+(defun prev-month (dt)
+  (inc-months dt -1))
+
+(defun inc-years (dt num-yy)
+  (multiple-value-bind (sec min hr dd mm yr day dst zone)
+                       (decode-universal-time dt)
+    (declare (ignore day dst))
+    (encode-universal-time sec 
+                           min 
+                           hr 
+                           dd 
+                           mm
+                           (+ yr num-yy)
+                           zone)))
+
+(defun next-year (dt)
+  (inc-years dt 1))
+
+(defun prev-year (dt)
+  (inc-years dt -1))
+
+(defun same-day-p (dt1 dt2)
+  (multiple-value-bind (sec min hr dd1 mm1 yr1 day dst zone)
+                       (decode-universal-time dt1)
+    (declare (ignore sec min hr day dst zone))
+    (multiple-value-bind (sec min hr dd2 mm2 yr2 day dst zone)
+                       (decode-universal-time dt2)
+      (declare (ignore sec min hr day dst zone))
+      (and (eql dd1 dd2) (eql mm1 mm2) (eql yr1 yr2)))))
+
+(defun days-to-sec (num-days)
+  ;; convert a number of days to seconds, which can be added/subtracted
+  ;; from a date to get a new date
+  (* num-days 86400))
+
+(defmacro do-dates ((dt start end &optional (return-form nil ret-p)) &rest forms)
+  `(do* ((,dt ,start (+ ,dt 86400)))
+        ((> ,dt ,end) (if ,ret-p ,return-form (values)))
+     ,@forms))
+
+(defmacro do-interval-dates ((dt start end interval &optional (return-form nil ret-p)) &rest forms)
+  `(do* ((,dt ,start (+ ,dt (days-to-sec ,interval))))
+        ((> ,dt ,end) (if ,ret-p ,return-form (values)))
+     ,@forms))
+
+(defmacro do-months ((dt start end mm-interval &optional (return-form nil ret-p)) &rest forms)
+  `(do* ((,dt ,start (inc-months ,dt ,mm-interval)))
+        ((> ,dt ,end) (if ,ret-p ,return-form (values)))
+     ,@forms))
+
+(defun days-between (dt1 dt2)
+  (round (abs (- dt2 dt1)) 86400))
+
+(defmethod days-from ((dt1 integer) (dt2 integer))
+  (days-between dt1 dt2))
+
+(defmethod days-from ((dt integer) (day symbol))
+  (let* ((abbrev-days '(sun mon tue wed thu fri sat))
+         (days '(sunday monday tuesday wednesday thursday friday saturday))
+         (dow (abbrev-day-of-wk dt))
+         (today (position dow abbrev-days))
+         (day-pos (or (position day days)
+                      (position day abbrev-days))))
+    (if (<= today day-pos)
+      (- day-pos today)
+      (- 7 (- today day-pos)))))
+
+(defmethod days-from ((day symbol) (dt integer))
+  (let* ((abbrev-days '(sun mon tue wed thu fri sat))
+         (days '(sunday monday tuesday wednesday thursday friday saturday))
+         (dow (abbrev-day-of-wk dt))
+         (day-pos (position dow abbrev-days))
+         (today (or (position day days)
+                    (position day abbrev-days))))
+    (if (<= today day-pos)
+      (- day-pos today)
+      (- 7 (- today day-pos)))))
+
+(defmethod days-from ((day1 symbol) (day2 symbol))
+  (let* ((abbrev-days '(sun mon tue wed thu fri sat))
+         (days '(sunday monday tuesday wednesday thursday friday saturday))
+         (today (or (position day1 days)
+                    (position day1 abbrev-days)))
+         (day-pos (or (position day2 days)
+                      (position day2 abbrev-days))))
+    (if (<= today day-pos)
+      (- day-pos today)
+      (- 7 (- today day-pos)))))
+
+(defun +days (dt days)
+  (+ dt (days-to-sec days)))
+
+(defun date-string (dt)
+  (multiple-value-bind (sec min hr dd mm yr day dst zone)
+                       (decode-universal-time dt)
+    (declare (ignore sec min hr dst zone))
+    (format nil 
+            "~9s ~2,'0d/~2,'0d/~2,'0d" 
+            (nth day '(monday tuesday wednesday thursday friday saturday sunday))
+            mm dd (mod yr 100))))
+
+(defun short-date-string (dt)
+  (multiple-value-bind (sec min hr dd mm yr day dst zone)
+                       (decode-universal-time dt)
+    (declare (ignore sec min hr day dst zone))
+    (format nil 
+            "~2,'0d/~2,'0d/~2,'0d" mm dd (mod yr 100))))
+
+(defun mmdd-string (dt)
+  (multiple-value-bind (sec min hr dd mm yr day dst zone)
+                       (decode-universal-time dt)
+    (declare (ignore sec min hr yr day dst zone))
+    (format nil 
+            "~2,'0d/~2,'0d" mm dd)))
+
+(defun mmddyy-list (dt)
+  (multiple-value-bind (sec min hr dd mm yr day dst zone)
+                       (decode-universal-time dt)
+    (declare (ignore sec min hr day dst zone))
+    (list mm dd yr)))
+
+(defun dt-yr (dt)
+    (multiple-value-bind (sec min hr dd mm yr day dst zone)
+                       (decode-universal-time dt)
+    (declare (ignore sec min hr dd mm day dst zone))
+    yr))
+
+(defun date-list (strt end)
+  (do* ((res (list strt) (cons next res))
+        (next (next-day strt) (next-day next)))
+       ((> next end) (nreverse res))))
+
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+
+;; utility functions supporting the use of an integer as a set days of
+;; the week. The low-order 7 bits of the integer represent sun thru sat
+;; Bit 0 = sun ... Bit 6 = sat.
+
+(defun day-set-bit (day)
+  (or (position day '(sun mon tue wed thu fri sat))
+      (position day '(sunday monday tuesday wednesday thursday friday saturday))))
+
+(defun add-day (day day-set)
+  (dpb 1 (byte 1 (day-set-bit day)) day-set))
+
+(defun remove-day (day day-set)
+  (dpb 0 (byte 1 (day-set-bit day)) day-set))
+
+(defun has-day-p (day-set day)
+  (logbitp (day-set-bit day) day-set))
+
+(defun in-dayset-p (dt day-set)
+  (has-day-p day-set (abbrev-day-of-wk dt)))
+
+(defun day-set (&rest days)
+  (let ((ds 0))
+    (dolist (day days ds)
+      (setf ds (dpb 1 (byte 1 (day-set-bit day)) ds)))))
+
+(defun num-days-in-dayset (dayset strt end)
+  (count-if #'(lambda (dt)
+                (in-dayset-p dt dayset))
+            (date-list strt end)))
+
+(defun random-date (begin-dt end-dt)
+  (+ begin-dt (random (- end-dt begin-dt))))
+
+(defun intl-string-dt (dt)
+  ;; A string that specifies a date and time value in the international string representation formatâ
+  ;; YYYY-MM-DD HH:MM:SS Â±HHMM, where Â±HHMM is a time zone offset in hours and minutes from GMT
+  ;; (for example, â2001-03-24 10:45:32 +0600â).
+  (multiple-value-bind (sec min hr dd mm yr day dst zone)
+                       (decode-universal-time dt)
+    (declare (ignore dst day))
+    (format nil "~4d-~2,'0d-~2,'0d ~2,'0d:~2,'0d:~2,'0d ~a~4,'0d"
+            yr
+            mm
+            dd
+            hr
+            min
+            sec
+            (if (plusp zone) "+" "-")
+            (* zone 100))))
+
+;; The reference used for NSDate objects is 01/01/2001
+;; This represents the difference between lisp's reference date and NSDate's
+(defconstant $ns-lisp-ref-date-diff$ (dt 01 01 2001 0 0 0 0))
+
+(defun lisp-to-ns-date (dt)
+  (#/dateWithTimeIntervalSinceReferenceDate:
+   ns:ns-date
+   (coerce (- dt $ns-lisp-ref-date-diff$) 'double-float)))
+
+(defun ns-to-lisp-date (ns-date)
+  (+ (round (#/timeIntervalSinceReferenceDate ns-date)) $ns-lisp-ref-date-diff$))
+
+(provide :date)
Index: /trunk/contrib/krueger/InterfaceProjects/Utilities/decimal.lisp
===================================================================
--- /trunk/contrib/krueger/InterfaceProjects/Utilities/decimal.lisp	(revision 13946)
+++ /trunk/contrib/krueger/InterfaceProjects/Utilities/decimal.lisp	(revision 13946)
@@ -0,0 +1,92 @@
+;; decimal.lisp
+
+#|
+The MIT license.
+
+Copyright (c) 2010 Paul L. Krueger
+
+Permission is hereby granted, free of charge, to any person obtaining a copy of this software 
+and associated documentation files (the "Software"), to deal in the Software without restriction, 
+including without limitation the rights to use, copy, modify, merge, publish, distribute, 
+sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is 
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all copies or substantial 
+portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT 
+LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. 
+IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, 
+WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE 
+SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+|#
+
+(eval-when (:compile-toplevel :load-toplevel :execute)
+  (require :ns-string-utils))
+
+(defpackage :interface-utilities
+  (:nicknames :iu)
+  (:export lisp-to-ns-decimal lisp-from-ns-decimal))
+
+(in-package :iu)
+
+;; This contains a set of utility functions for converting back and forth between 
+;; NSDecimalNumber objects and lisp integers.
+;; Lisp does a good job representing large integers, so in general we can do things
+;; like manipulate dollar amounts just by using integers to represent the total
+;; cents value and doing something like:
+;;       (floor lisp-value 100) 
+;; to retrieve dollars and cents values.
+
+;; Using float values for dollars and cents is problematic. Rounding errors will get
+;; you anytime you convert to or from float-values and input or display strings. Apple
+;; has created a special class NSDecimalNumber to represent long decimal numbers. They
+;; defined an array of arithmetic functions to manipulate instance of this class. While
+;; we could probably just use those functions in lisp and manipulate NSDecimalNumber
+;; objects directly, it seems preferable to convert back and forth to lisp integers and
+;; use normal arithmetic operations when in Lisp. Of course it will be up to the Lisp
+;; programmer to understand how many decimal digits are being represented whereas this
+;; value is represented within NSDecimalNumberObjects.
+
+(defun lisp-to-ns-decimal (int-val &key (decimals 2))
+  ;; construct an NSDecimalNumber object with the given int-val and number of decimals
+  ;; For example if you have a dollar amount 123.45 represented by the fixnum 12345
+  ;; you would call (make-ns-decimal 12345 :decimals 2) to get a corresponding
+  ;; NSDecimalNumber object. This object is the responsibility of the caller and a 
+  ;; call to #/release must be made when the caller is done with it.
+  (unless (typep int-val 'fixnum)
+    (error "Input must be a fixnum"))
+  (#/decimalNumberWithMantissa:exponent:isNegative:
+   ns:ns-decimal-number
+   (abs int-val)
+   (- decimals)
+   (if (minusp int-val) #$YES #$NO)))
+
+(defun lisp-from-ns-decimal (ns-dec-obj &key (decimals 2))
+  ;; This function returns a fixnum that corresponds to the NSDecimalNumber 
+  ;; or NSNumber that is passed in as the first argument. 
+  ;; The result will be scaled and rounded to represent the desired
+  ;; number of decimal digits as specified by the :decimals keyword argument.
+  ;; For example, if an NSNumber is passed in which is something like 123.45678
+  ;; and you ask for 2 decimal digits, the returned value will be the integer 12346.
+  (let* ((loc (#/currentLocale ns:ns-locale))
+         (lisp-str (ccl::lisp-string-from-nsstring 
+                    (#/descriptionWithLocale: ns-dec-obj loc)))
+         (str-len-1 (1- (length lisp-str)))
+         (dec-pos (or (position #\. lisp-str) str-len-1))
+         (dec-digits (- str-len-1 dec-pos))
+         (dec-diff (- decimals dec-digits))
+         (mantissa-str (delete #\. lisp-str)))
+    (cond ((zerop dec-diff)
+           (read-from-string mantissa-str))
+          ((plusp dec-diff)
+           (read-from-string (concatenate 'string 
+                                          mantissa-str
+                                          (make-string dec-diff :initial-element #\0))))
+          (t ;; minusp dec-diff
+           (let ((first-dropped (+ (length mantissa-str) dec-diff)))
+             (+ (if (> (char-code (elt mantissa-str first-dropped)) (char-code #\4)) 1 0)
+                (read-from-string (subseq mantissa-str 0 first-dropped))))))))
+    
+
Index: /trunk/contrib/krueger/InterfaceProjects/Utilities/lisp-controller.lisp
===================================================================
--- /trunk/contrib/krueger/InterfaceProjects/Utilities/lisp-controller.lisp	(revision 13946)
+++ /trunk/contrib/krueger/InterfaceProjects/Utilities/lisp-controller.lisp	(revision 13946)
@@ -0,0 +1,1214 @@
+;; lisp-controller.lisp
+#|
+The MIT license.
+
+Copyright (c) 2010 Paul L. Krueger
+
+Permission is hereby granted, free of charge, to any person obtaining a copy of this software 
+and associated documentation files (the "Software"), to deal in the Software without restriction, 
+including without limitation the rights to use, copy, modify, merge, publish, distribute, 
+sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is 
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all copies or substantial 
+portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT 
+LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. 
+IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, 
+WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE 
+SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+|#
+
+;; Implements a class that can be used within IB as a content object
+;; for various standard view types
+
+(eval-when (:compile-toplevel :load-toplevel :execute)
+  (require :ns-string-utils)
+  (require :ns-object-utils)
+  (require :nslog-utils)
+  (require :assoc-array)
+  (require :list-utils))
+
+(defpackage :lisp-controller
+  (:nicknames :lc)
+  (:use :ccl :common-lisp :iu)
+  (:export 
+   added-func
+   add-child-func
+   children-func
+   content-class
+   count-func
+   delete-func
+   edited-func
+   gen-root
+   lisp-controller 
+   lisp-controller-changed
+   objects
+   reader-func
+   removed-func
+   root
+   root-type
+   select-func
+   writer-func))
+
+(in-package :lc)
+
+;; lisp-controller functionality
+;; Class and methods used to view a lisp object using a NSTableView
+;; or NSOutlineView or NSBrowser.
+;; The objects slot should initialized as an object to be represented
+;; in an associated view table. Unless user-specified reader/writer
+;; functions are also specified (as described later), that object 
+;; must be a sequence of objects (e.g. a list or vector) or a
+;; hast-table which is treated as a sequence of (key . value) pairs.
+;; For use with non-hierarchical display views (NSTableView)
+;; the objects will be displayed one per row in the table.
+;; For use with hierarchical display views (NSOutlineView or 
+;; NSBrowser) the objects comprise the set of root objects; each
+;; of which may contain children that will be displayed. Children
+;; may themselves have children, etc.
+;; Objects can be an arbitrary lisp object (e.g. a list,
+;; vector, structure, hash-table, or class instance).
+
+;; In the View specification, table column identifiers can be
+;; set to provide information about how to access the data to be
+;; displayed in that column from the object that represents a
+;; given row. 
+
+;; The user has three options for how to convert column identifiers
+;; into accessor functions (reader and also writer if the table is
+;; editable). The choice is determined by what is found in the column
+;; identifier at initialization time and by whether reader/writer
+;; functions have been specified.
+
+;; Option 1: Use the column identifier as an index
+;; If the column identifier is a number, then it is treated as
+;; a numerical index that will be used to access the row-object as
+;; a sequence (i.e. as a list or vector)
+;; with elements that correspond to numerical values set as
+;; column identifiers in IB. For example, a table-column with
+;; identifier set to "1" would access the second element of
+;; the row. This is the equivalent of:
+;;   (elt row-object identifier-value)
+;; Also the writer function for such a table identifier
+;; is assumed to result in the equivalent of:
+;;   (setf (elt row-object identifier-value) new-value)
+;; where as before the identifier-value is derived from the
+;; identifier-string which is a number.
+
+;; Option 2: Use the column identifier as a key specifier
+;; If the column identifier consists of a single symbol,
+;; it is treated as a key to use in accessing a value from
+;; the row-object. This is the equivalent of:
+;;   (funcall (symbol-function identifier-value) row-object)
+;; The identifier value should not BE a key (e.g. #'key-function)
+;; but rather should be the symbol-name for which symbol-function
+;; exists (e.g. key-function).
+;; The identifier-value may contain package specifiers for the
+;; symbol in the normal way (e.g. my-package::my-symbol).
+;; If that column permits editing, then the lisp-controller
+;; will execute the equivalent of:
+;;  (setf (identifier-value row-object) new-value)
+;; So, for example, if the row-object happens to be a list, 
+;; the user could specify a key of "first" (quotes not included),
+;; since both (first row-object) and (setf (first row-object) new-value)
+;; are well-specified for lists. Note that this would, however, be 
+;; equivalent to using 0.
+;; If editing of a column is permitted, but no appropriate setf
+;; method exists for the key specifier, then although the user
+;; will apparently be able to change the value of that column in
+;; the table, no actual change will be made and the value will 
+;; instantly revert back to its former value.
+;; Note that a key specifier of "identity" could be used to select
+;; the row-object itself for printing. This might be suitable for 
+;; single-column tables or multi-column tables where other columns
+;; display some transformation of the row-object.
+
+;; Option 3: Use the column-identifier as a symbol or number supplied
+;; as a parameter to a separately provided accessor function. 
+;; If the user explicitly provides a reader function by setting the
+;; reader-function field for a lisp-controller in IB, then
+;; that function will be used for all table accesses. It will be passed
+;; three arguments: the content of the "objects" slot for the lisp-controller,
+;; the requested row number and the value of the column-identifier
+;; field for the column. If that is a number, then a numerical
+;; value is passed, if it is anything else then whatever lisp object
+;; results from doing a (read-from-string column-identifier) is passed
+;; as the second parameter. For example, this would permit the user
+;; to provide a two-dimensional array as the "objects" to be displayed,
+;; provide appropriate numerical indices as the value of various column-
+;; identifiers, and to specify "aref" as the reader function.
+;; Similarly, if a writer function is specified by the user in IB, then
+;; it will be called with four arguments: the new value, the content of
+;; the objects slot, the row-number, and the column-identifier as either
+;; a number or symbol. Using the same example, this would result in
+;; calling (setf (aref contents row-num col-identifier) new-value).
+;; Note that if a reader function is specified, then a count function
+;; should also be provided. If editing is permitted, then an "edited" 
+;; function should also be provided. If row insertion and/or deletion are
+;; permitted, then appropriate "added" and "deleted" functions
+;; must also be provided.
+
+;; In addition to reader and writer functions, the user may specify
+;; functions that are called when a table entry is selected or edited.
+;; These should be functions that take 3 arguments: the content of 
+;; the lisp-controller's "objects" slot, the row number, 
+;; and the column-identifier-string for the affected table entry. 
+;; The select function will be invoked whenever a list item is 
+;; selected and the edited function will be invoked after an item
+;; in the list has been modified.
+
+;; The user may also specify functions to be called when a new row is
+;; added or deleted. These will take two arguments, the content of the
+;; "objects" slot and the row number of the new object. Note that if 
+;; the user has specified their own reader and writer functions that 
+;; the lisp-controller will have no way of adding or deleting objects.
+;; In this case only, the user supplied "added" and "deleted" functions
+;; should actually make the necessary changes to the first argument (i.e.
+;; add or delete as appropriate). The table will be re-displayed after
+;; this has been done.
+
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;;; Global variables
+
+(defvar *lisp-controller-debug* nil)
+
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;; class and methods specific to hash-tables
+
+(defclass ht-entry ()
+  ((ht-key :reader ht-key :initarg :key)
+   (ht-value :reader ht-value :initarg :value)
+   (ht :accessor ht :initarg :ht))
+  (:default-initargs
+    :key (gensym "KEY")
+    :value nil
+    :ht nil))
+
+(defmethod (setf ht-key) (new-key (self ht-entry))
+  (block set-it
+    (let ((new-key-exists (not (eq :not-found (gethash new-key (ht self) :not-found)))))
+      (when new-key-exists
+        ;; They are redefining a key to be one that already exists in the hash-table
+        ;; first verify they want to do this
+        (let* ((alert-str  (lisp-to-temp-nsstring 
+                            (format nil 
+                                    "Continuing will reset value for existing key: ~s"
+                                    new-key)))
+               (res (#_NSRunAlertPanel #@"ALERT" 
+                                       alert-str
+                                       #@"Cancel key change"  
+                                       #@"Continue and change key"
+                                       (%null-ptr))))
+          (unless (eql res #$NSAlertAlternateReturn)
+            ;; they don't want to continue
+            (return-from set-it))))
+      ;; change the value for the existing key
+      (setf (gethash new-key (ht self))
+            (gethash (ht-key self) (ht self)))
+      ;; and then remove the old key that was changed both from the hash table
+      ;; and from the list of keys
+      ;; new keys are always put at the end of the list unless a sort predicate
+      ;; has been specified.
+      (remhash (ht-key self) (ht self))
+      (setf (slot-value self 'ht-key) new-key))))
+
+(defmethod (setf ht-value) (new-val (self ht-entry))
+  (setf (gethash (ht-key self) (ht self)) new-val)
+  (setf (slot-value self 'ht-value) new-val))
+
+(let ((ht-hash (make-hash-table)))
+  ;; in order to treat hash-tables as containers like lists and vectors we
+  ;; need to define a few functions which use a cache of the "children" of
+  ;; a hash-table so that we don't need to recreate the whole list every time
+  ;; a new child is added
+
+  (defmethod children ((parent hash-table))
+    (or (gethash parent ht-hash)
+        (setf (gethash parent ht-hash)
+              (let ((ht-list nil))
+                (maphash #'(lambda (key val)
+                             (push (make-instance 'ht-entry
+                                     :key key
+                                     :value val
+                                     :ht parent)
+                                   ht-list))
+                         parent)
+                ht-list))))
+
+  (defmethod (setf children) (new-value (parent hash-table))
+    (setf (gethash parent ht-hash) new-value))
+
+  (defmethod add-to-child-seq (parent (seq list) (thing ht-entry))
+    (with-slots (ht ht-key ht-value) thing
+      (setf (gethash ht-hash parent) (cons thing seq))
+      (setf ht parent)
+      (setf (gethash parent ht-key) ht-value)))
+
+  (defmethod delete-from-child-seq ((seq list) (thing ht-entry))
+    (with-slots (ht ht-key) thing
+      (remhash ht-key ht)
+      (delete-from-list seq thing)))
+
+) ;; end of hash-table functions within let
+
+;;; Functions to access children for other common types
+
+(defmethod children ((parent sequence))
+  ;; root objects that are lists or vectors are
+  ;; also the sequence of children
+  parent)
+
+(defmethod (setf children) (new-children (parent vector))
+  ;; root objects that are lists or vectors are
+  ;; also the sequence of children
+  (or parent new-children))
+
+(defmethod (setf children) (new-children (parent list))
+  ;; root objects that are lists or vectors are
+  ;; also the sequence of children
+  new-children)
+
+(defmethod children (parent)
+  (declare (ignore parent))
+  ;; any other unknown type of parent
+  nil)
+
+;;; Functions to add/delete items from sequences
+;;; See also corresponding methods for sequences of ht-entry items
+;;; in section of hash-table methods above
+
+(defmethod add-to-child-seq (parent (seq list) thing)
+  (declare (ignore parent))
+  (nconc seq (list thing)))
+
+(defmethod add-to-child-seq (parent (seq vector) thing)
+  (declare (ignore parent))
+  (when (array-has-fill-pointer-p seq)
+    (vector-push-extend thing seq)))
+
+(defmethod delete-from-child-seq ((seq vector) thing)
+  (let ((pos (position thing seq)))
+    (dotimes (i (- (fill-pointer seq) pos 1))
+      (setf (aref seq (+ pos i))
+            (aref seq (+ pos i 1)))))
+  (vector-pop seq))
+
+(defmethod delete-from-child-seq ((seq list) thing)
+  (delete-from-list seq thing))
+
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;; Some utility functions used later
+
+         
+(defun valid-setf-for (read-form)
+  (multiple-value-bind (a b c func-form d) (get-setf-expansion read-form)
+    (declare (ignore a b c d))
+    (or (not (eq (first func-form) 'funcall))
+        ;; this must be a built-in function, so assume setf works
+        ;; otherwise make sure the function name specified is fboundp
+        (let ((func-name (second (second func-form))))
+          (and (typep func-name 'function-name) (fboundp func-name))))))
+
+(defun eval-without-errors (form)
+  (when *lisp-controller-debug*
+    (ns-log (format nil "evaling form: ~s" form)))
+  (handler-case (eval form)
+    (condition (c)
+      (when *lisp-controller-debug*
+        (format t "~%condition: ~s" c)))))
+
+(defun reader-writer-pair (typ col-val)
+  (let* ((reader-form nil)
+         (writer-form nil))
+    (cond ((null col-val)
+           ;; reader justs return the object itself
+           ;; leave the writer-form null
+           (setf reader-form 'row))
+          ((and (eq col-val :key) (eq typ 'ht-entry))
+           ;; used for the key value in a hash table
+           (setf reader-form '(ht-key row))
+           (setf writer-form '(setf (ht-key row) new-val)))
+          ((and (eq col-val :value) (eq typ 'ht-entry))
+           ;; used for the value in a hash table
+           (setf reader-form '(ht-value row))
+           (setf writer-form '(setf (ht-value row) new-val)))
+          ((eq col-val :row)
+           (setf reader-form 'row)
+           (setf writer-form '(setf row new-val)))
+          ((numberp col-val)
+           (cond ((subtypep typ 'vector)
+                  (setf reader-form `(aref row ,col-val))
+                  (setf writer-form `(setf (aref row ,col-val) new-val)))
+                 ((subtypep typ 'list)
+                  (setf reader-form `(nth ,col-val row))
+                  (setf writer-form `(setf (nth ,col-val row) new-val)))
+                 ((eq typ 'ht-entry)
+                  ;; Index if the value is a sequence
+                  (setf reader-form `(when (typep (ht-value row) 'sequence)
+                                       (elt (ht-value row) ,col-val)))
+                  (setf writer-form `(when (typep (ht-value row) 'sequence)
+                                       (setf (elt (ht-value row) ,col-val) new-val))))
+                 ((subtypep typ 'hash-table)
+                  ;; use the number as a key into the hash table and return the value
+                  (setf reader-form `(gethash ,col-val row))
+                  (setf writer-form `(setf (gethash ,col-val row) new-val)))
+                 (t
+                  ;; index if row is any other type of sequence
+                  (setf reader-form `(when (typep row 'sequence)
+                                       (elt row ,col-val)))
+                  (setf writer-form `(when (typep row 'sequence)
+                                       (setf (elt row ,col-val) new-val))))))
+          ((and (symbolp col-val) (fboundp col-val))
+           (cond ((eq typ 'ht-entry)
+                  ;; Assume the function applies to the value
+                  (setf reader-form `(,col-val (ht-value row)))
+                  (when (valid-setf-for reader-form)
+                    (setf writer-form `(setf (,col-val (ht-value row)) new-val))))
+                 (t
+                  (setf reader-form `(,col-val row))
+                  (when (valid-setf-for reader-form)
+                    (setf writer-form `(setf (,col-val row) new-val))))))
+          ((symbolp col-val)
+           (cond ((subtypep typ 'hash-table)
+                  ;; use the symbol as a key into the hash table and return the value
+                  (setf reader-form `(gethash ,col-val row))
+                  (setf writer-form `(setf (gethash ,col-val row) new-val)))))
+          ((and (consp col-val) (eq (first col-val) 'function))
+           (let ((col-val (second col-val)))
+             (when (and (symbolp col-val) (fboundp col-val))
+               (cond ((eq typ 'ht-entry)
+                      ;; Assume the function applies to the value
+                      (setf reader-form `(,col-val (ht-value row)))
+                      (when (valid-setf-for reader-form)
+                        (setf writer-form `(setf (,col-val (ht-value row)) new-val))))
+                     (t
+                      (setf reader-form `(,col-val row))
+                      (when (valid-setf-for reader-form)
+                        (setf writer-form `(setf (,col-val row) new-val))))))))
+          ((consp col-val)
+           ;; accessors are lisp forms possibly using keywords :row, :key, and :value
+           ;; which are replaced appropriately
+           (setf reader-form (nsubst 'row ':row 
+                                     (nsubst '(ht-key row) :key
+                                             (nsubst '(ht-value row) :value
+                                                     col-val))))
+           (when (valid-setf-for reader-form)
+             (setf writer-form `(setf ,col-val new-val)))))
+    (when *lisp-controller-debug*
+      (ns-log (format nil "Reader-form: ~s~%Writer-form: ~s" reader-form writer-form)))
+    (cons (and reader-form 
+               (eval-without-errors `(function (lambda (row) ,reader-form))))
+          (and writer-form 
+               (eval-without-errors `(function (lambda (new-val row) ,writer-form)))))))
+
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;; lisp-controller class
+
+(defclass lisp-controller (ns:ns-object)
+  ((root :accessor root)
+   (root-type :accessor root-type)
+   (gen-root :accessor gen-root)
+   (objects :accessor objects)
+   (types :reader types)
+   (reader-func :accessor reader-func)
+   (writer-func :accessor writer-func)
+   (count-func :accessor count-func)
+   (select-func :accessor select-func)
+   (edited-func :accessor edited-func)
+   (added-func :accessor added-func)
+   (removed-func :accessor removed-func)
+   (delete-func :accessor delete-func)
+   (add-child-func :accessor add-child-func)
+   (children-func :accessor children-func)
+   (type-info :accessor type-info)
+   (column-info :accessor column-info)
+   (nib-initialized :accessor nib-initialized)
+   (view-class :accessor view-class)
+   (can-remove :foreign-type #>BOOL :accessor can-remove)
+   (can-insert :foreign-type #>BOOL :accessor can-insert)
+   (can-add-child :foreign-type #>BOOL :accessor can-add-child)
+   (owner :foreign-type :id :accessor owner)
+   (view :foreign-type :id :accessor view))
+  (:metaclass ns:+ns-object))
+
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;; instance initialization methods
+
+(objc:defmethod (#/initWithCoder: :id)
+                ((self lisp-controller) (decoder :id))
+  ;; This method is called when the Nib is loaded and provides values defined
+  ;; when the NIB was created
+  (#/init self)
+  (with-slots (reader-func writer-func count-func select-func edited-func
+               add-child-func root-type gen-root added-func removed-func
+               children-func type-info delete-func) self
+    (let ((type-info-array (#/decodeObjectForKey: decoder #@"typeInfo")))
+      (dotimes (i (#/count type-info-array))
+        ;; for each type specified in IB by the user
+        (let* ((row-array (#/objectAtIndex: type-info-array i))
+               (ns-str-type-name (#/objectAtIndex: row-array 0))
+               (type-name (nsstring-to-sym ns-str-type-name))
+               (child-type (nsstring-to-sym (#/objectAtIndex: row-array 1)))
+               (child-func-str (ns-to-lisp-string (#/objectAtIndex: row-array 2)))
+               (child-func (find-func child-func-str))
+               (reader-sym (and child-func (function-name child-func)))
+               (writer-form `(setf (,reader-sym thing) new-val))
+               (child-writer-func (and child-func
+                                       (valid-setf-for writer-form)
+                                       (eval `(function (lambda (new-val thing)
+                                                          ,writer-form))))))
+          (when child-type
+              (setf (assoc-aref type-info type-name :child-type) child-type))
+          (when child-func
+            (setf (assoc-aref type-info type-name :child-key) child-func))
+          (when child-writer-func
+              (setf (assoc-aref type-info type-name :child-setf-key) child-writer-func)))))
+    (let ((initform-array (#/decodeObjectForKey: decoder #@"initforms")))
+      (dotimes (i (#/count initform-array))
+        ;; for each initform specified in IB by the user
+        (let* ((row-array (#/objectAtIndex: initform-array i))
+               (ns-str-type-name (#/objectAtIndex: row-array 0))
+               (type-name (nsstring-to-sym ns-str-type-name))
+               (initform (ns-to-lisp-object t (#/objectAtIndex: row-array 1))))
+          (when initform
+              (setf (assoc-aref type-info type-name :initform) initform)))))
+    (let ((sort-info-array (#/decodeObjectForKey: decoder #@"sortInfo")))
+      (dotimes (i (#/count sort-info-array))
+        ;; for each sort predicate and key specified in IB by the user
+        (let* ((row-array (#/objectAtIndex: sort-info-array i))
+               (ns-str-type-name (#/objectAtIndex: row-array 0))
+               (type-name (nsstring-to-sym ns-str-type-name))
+               (sort-key (nsstring-to-func (#/objectAtIndex: row-array 1)))
+               (sort-pred (nsstring-to-func (#/objectAtIndex: row-array 2))))
+          (when sort-pred
+            (setf (assoc-aref type-info type-name :sort-pred) sort-pred))
+          (when sort-key
+            (setf (assoc-aref type-info type-name :sort-key) sort-key)))))
+    (setf root-type (nsstring-to-sym (#/decodeObjectForKey: decoder #@"rootType")))
+    (setf (types self) (delete-duplicates (list* root-type 
+                                                 'ht-entry
+                                                 (mapcar-assoc-array #'identity type-info))))
+    (setf reader-func (nsstring-to-func (#/decodeObjectForKey: decoder #@"readerFunc")))
+    (setf writer-func (nsstring-to-func (#/decodeObjectForKey: decoder #@"writerFunc")))
+    (setf count-func (nsstring-to-func (#/decodeObjectForKey: decoder #@"countFunc")))
+    (setf select-func (nsstring-to-func (#/decodeObjectForKey: decoder #@"selectFunc")))
+    (setf edited-func (nsstring-to-func (#/decodeObjectForKey: decoder #@"editedFunc")))
+    (setf added-func (nsstring-to-func (#/decodeObjectForKey: decoder #@"addedFunc")))
+    (setf removed-func (nsstring-to-func (#/decodeObjectForKey: decoder #@"removedFunc")))
+    (setf delete-func (nsstring-to-func (#/decodeObjectForKey: decoder #@"deleteFunc")))
+    (setf add-child-func (nsstring-to-func (#/decodeObjectForKey: decoder #@"addChildFunc")))
+    (setf children-func (nsstring-to-func (#/decodeObjectForKey: decoder #@"childrenFunc")))
+    (setf gen-root (#/decodeBoolForKey: decoder #@"genRoot")))
+  self)
+
+(objc:defmethod (#/init :id)
+                ((self lisp-controller))
+  ;; need to do this to initialize default values that are needed when
+  ;; this object is instantiated from Objective-C runtime
+  (unless (slot-boundp self 'nib-initialized)
+    (setf (nib-initialized self) nil))
+  (unless (slot-boundp self 'select-func)
+    (setf (select-func self) nil))
+  (unless (slot-boundp self 'edited-func)
+    (setf (edited-func self) nil))
+  (unless (slot-boundp self 'added-func)
+    (setf (added-func self) nil))
+  (unless (slot-boundp self 'removed-func)
+    (setf (removed-func self) nil))
+  (unless (slot-boundp self 'add-child-func)
+    (setf (add-child-func self) nil))
+  (unless (slot-boundp self 'delete-func)
+    (setf (delete-func self) nil))
+  (unless (slot-boundp self 'reader-func)
+    (setf (reader-func self) nil))
+  (unless (slot-boundp self 'writer-func)
+    (setf (writer-func self) nil))
+  (unless (slot-boundp self 'count-func)
+    (setf (count-func self) nil))
+  (unless (slot-boundp self 'objects)
+    (setf (objects self) nil))
+  (unless (slot-boundp self 'root)
+    ;; note that we have to set root slot to avoid
+    ;; calling accessor functions. This is a 
+    ;; special case and the only place where we
+    ;; want to set the root to something that 
+    ;; doesn't match the root-type specified in IB
+    (setf (slot-value self 'root) nil))
+  (unless (slot-boundp self 'root-type)
+    (setf (root-type self) t))
+  (unless (slot-boundp self 'types)
+    (setf (types self) nil))
+  (unless (slot-boundp self 'type-info)
+    (setf (type-info self) (make-instance 'assoc-array :rank 2)))
+  ;; Now set up some default type info for standard types
+  ;; These can be overridden in the lisp-controller setup
+  ;; within Interface Builder.
+  ;; Typically users would define their own types and
+  ;; specify values for them rather than overriding these
+  ;; but it is permissable to do so.
+  (setf (assoc-aref (type-info self) 'hash-table :child-key) #'children)
+  (setf (assoc-aref (type-info self) 'list :child-key) #'children)
+  (setf (assoc-aref (type-info self) 'vector :child-key) #'children)
+  (setf (assoc-aref (type-info self) 'hash-table :child-setf-key) #'(setf children))
+  (setf (assoc-aref (type-info self) 'list :child-setf-key) #'(setf children))
+  (setf (assoc-aref (type-info self) 'vector :child-setf-key) #'(setf children))
+  (setf (assoc-aref (type-info self) 'hash-table :child-type) 'ht-entry)
+  (setf (assoc-aref (type-info self) 'list :child-type) 'list)
+  (setf (assoc-aref (type-info self) 'vector :child-type) 'vector)
+  (setf (assoc-aref (type-info self) 'hash-table :initform)
+        '(make-hash-table))
+  (setf (assoc-aref (type-info self) 'list :initform)
+        nil)
+  (setf (assoc-aref (type-info self) 'vector :initform) 
+        '(make-array '(10) :adjustable t :fill-pointer 0 :initial-element nil))
+  self)
+
+(objc:defmethod (#/awakeFromNib :void)
+                ((self lisp-controller))
+  (setf (nib-initialized self) t)
+  (let ((has-valid-view (and (slot-boundp self 'view)
+                             (not (eql (view self) (%null-ptr))))))
+    (when has-valid-view
+      (setf (view-class self) (#/class (view self)))
+      (init-column-info self (view self)))
+    (when (gen-root self)
+      ;; create the root object
+      (setf (root self) (new-object-of-type self (root-type self))))
+    (when (and has-valid-view (objects self))
+      (setup-accessors self))))
+
+(defmethod setup-accessors ((self lisp-controller))
+  ;; This method must be called to initialize the column value
+  ;; accessor functions for a lisp-controller.
+  ;; It is called after NIB loading has been done.
+  (with-slots (reader-func column-info type-info types) self
+    (unless reader-func
+      (dolist (col (mapcar-assoc-array #'identity column-info))
+        (let ((col-id (assoc-aref column-info col :col-val)))
+          (dolist (typ types)
+            (setf (assoc-aref type-info typ col) 
+                  (reader-writer-pair typ col-id))))))))
+
+(defmethod set-can-add-child ((self lisp-controller) row-selected)
+  ;; indicates whether new children objects can be placed within
+  ;; the object represented in the row specified.
+  ;; If we have been given an explict add-child function then we can or
+  ;; if we know the child type for the root type and have a valid
+  ;; child key for which there is an associated setf function
+  ;; then we can also insert a new object.
+  (#/willChangeValueForKey: self #@"canAddChild")
+  (let* ((obj (object-at-row self row-selected))
+         (obj-type (controller-type-of self obj))
+         (child-setf-key (assoc-aref (type-info self) obj-type :child-setf-key)))
+    (if child-setf-key
+      (setf (can-add-child self)  #$YES)
+      (setf (can-add-child self) #$NO)))
+  (#/didChangeValueForKey: self #@"canAddChild"))
+
+(defmethod set-can-insert :around ((self lisp-controller) new-obj)
+  (declare (ignore new-obj))
+  (#/willChangeValueForKey: self #@"canInsert")
+  (call-next-method)
+  (#/didChangeValueForKey: self #@"canInsert"))
+
+(defmethod set-can-insert ((self lisp-controller) new-obj)
+  (declare (ignore new-obj))
+  ;; indicates whether new children objects can be placed within
+  ;; the root object.
+  ;; If we have been given an explict insert function then we can or
+  ;; if we know the child type for the root type and have a valid
+  ;; child key for which there is an associated setf function
+  ;; then we can also insert a new object.
+  (if (or (add-child-func self)
+          (assoc-aref (type-info self) (root-type self) :child-setf-key))
+    (setf (can-insert self) #$YES)
+    (setf (can-insert self) #$NO)))
+
+(defmethod set-can-insert ((self lisp-controller) (new-obj vector))
+  (setf (can-insert self) 
+        (if (or (add-child-func self)
+                (and (assoc-aref (type-info self) (controller-type-of self new-obj) :child-setf-key)
+                     (array-has-fill-pointer-p (objects self))
+                     (or (adjustable-array-p (objects self))
+                         (< (fill-pointer (objects self)) 
+                            (first (array-dimensions (objects self)))))))
+          #$YES
+          #$NO)))
+
+(defmethod (setf types) (new-types (self lisp-controller))
+  ;; sort the types making most specific first
+  ;; when we look for a type match using the function controller-type-of
+  ;; we'll find the most specific type that matches the given object
+  ;; Unfortunately we can't just call sort using #'subtypep as a predicate
+  ;; because it may not create a list where it is guaranteed that a appears
+  ;; before b whenever a is a subtype of b. So we do our own manual insertion
+  ;; sort.
+  (let ((res-list nil)
+        (pos nil))
+    (dolist (typ new-types)
+      (setf pos (position-if #'(lambda (check-type)
+                                 (subtypep typ check-type))
+                             res-list))
+      (if pos
+        ;; splice type into the res-list at pos
+        (setf res-list (add-to-list-at res-list pos typ))
+        (setf res-list (nconc res-list (list typ)))))
+    (setf (slot-value self 'types) res-list)))
+
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;; View-specific methods
+
+(defmethod init-column-info ((self lisp-controller) (view ns:ns-table-view))
+  (with-slots (column-info) self
+    (let* ((tc-arr (#/tableColumns view))
+           (col-obj nil)
+           (idc nil)
+           (col-count (#/count tc-arr)))
+      (unless tc-arr
+        (ns-log "#/tableColumns returned nil for view")
+        (return-from init-column-info))
+      (setf column-info (make-instance 'assoc-array :rank 2))
+      (dotimes (i col-count)
+        (setf col-obj (#/objectAtIndex: tc-arr i))
+        (setf (assoc-aref column-info col-obj :col-indx) i)
+        (setf (assoc-aref column-info i :col-obj) col-obj)
+        (setf idc (ns-to-lisp-string (#/identifier col-obj)))
+        (setf (assoc-aref column-info col-obj :col-string) idc)
+        (setf (assoc-aref column-info col-obj :col-val) 
+              (read-from-string idc nil nil))
+        (setf (assoc-aref column-info col-obj :col-title)
+              (ns-to-lisp-string (#/title (#/headerCell col-obj))))
+        ;; find any formatter attached to the data cell for this column and 
+        ;; use info from it to help us translate to and from lisp objects
+        ;; appropriately
+        (let ((formatter-object (#/formatter (#/dataCell col-obj))))
+          (unless (eql formatter-object (%null-ptr))
+            (cond ((typep formatter-object 'ns:ns-date-formatter)
+                   (setf (assoc-aref column-info col-obj :col-format) :date))
+                  ((typep formatter-object 'ns:ns-number-formatter)
+                   (cond ((#/generatesDecimalNumbers formatter-object)
+                          (let ((dec-digits (#/maximumFractionDigits formatter-object)))
+                            (setf (assoc-aref column-info col-obj :col-format)
+                                  (list :decimal dec-digits))))
+                         (t
+                          (setf (assoc-aref column-info col-obj :col-format)
+                                :number)))))))))))
+                   
+
+(defmethod object-at-row ((self lisp-controller) row-selected)
+  ;; returns two objects: the lisp object represented by the specified 
+  ;; row and the parent of that object
+  (unless (eql row-selected -1)
+    (cond ((eql (view-class self) ns:ns-outline-view)
+           (let ((ptr-wrapper (#/itemAtRow: (view self) row-selected)))
+             (values (lpw-lisp-ptr ptr-wrapper)
+                     (lpw-parent ptr-wrapper))))
+          ((eql (view-class self) ns:ns-table-view)
+           (values (elt (objects self) row-selected) (root self))))))
+
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;; Utility methods for the lisp-controller class
+
+(defmethod controller-type-of ((self lisp-controller) thing)
+  ;; find which of the declared types (if any) matches thing
+  ;; if none do, just return its lisp type
+  (if (eq thing (root self))
+    (root-type self)
+    (or (find-if #'(lambda (typ)
+                     (typep thing typ))
+                 (types self))
+        (type-of thing))))
+
+(defmethod controller-types-of ((self lisp-controller) thing)
+  ;; finds all of the declared types (if any) that match thing
+  ;; in an order from most specific to least specific including
+  ;; its lisp type
+  (nconc (remove-if-not #'(lambda (typ)
+                            (typep thing typ))
+                        (types self))
+         (list (type-of thing))))
+
+(defmethod most-specific-type-info ((self lisp-controller) type-list info-key)
+  (some #'(lambda (typ)
+            (assoc-aref (type-info self) typ info-key))
+        type-list))
+
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;; methods callable by outside functions within a lisp program
+
+(defmethod lisp-controller-changed ((self lisp-controller))
+  ;; program should call this if it changes the contents of the
+  ;; list object (but not the pointer to the list itself). In
+  ;; the latter case set-lisp-list-controller should be called.
+  (#/reloadData (view self)))
+
+(defmethod (setf root) :before (new-obj (self lisp-controller))
+  (let ((typ (controller-type-of self new-obj))
+        (rt (root-type self)))
+    (when (not (subtypep typ rt))
+      ;; trying to set root to something other than what was specified in IB
+      (error "Type of ~s (~s) is not a subtype of ~s" new-obj typ rt)))
+  (#/willChangeValueForKey: self #@"root"))
+
+(defmethod (setf root) :after (new-obj (self lisp-controller))
+  ;; cache the children of the root object because they are used so frequently
+  (setf (objects self) (children-of-object self new-obj))
+  (#/didChangeValueForKey: self #@"root")
+  (when (and (nib-initialized self) (not (eql (view self) (%null-ptr))))
+    (setup-accessors self)
+    (set-can-insert self new-obj)
+    (sort-sequence self (objects self))
+    (#/reloadData (view self)))
+  new-obj)
+
+(defmethod (setf view) :after (new-view (self lisp-controller))
+  ;; only used if lisp-list-controller object is not created via a nib load
+  ;; and view is set from somewhere else
+  (when new-view
+    (init-column-info self (view self))))
+
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;; miscellaneous methods for accessing and transforming objects
+
+(defmethod new-child-initform ((self lisp-controller) parent-type)
+  ;; get the initform for the child type of the parent-type parameter
+  (let ((child-type (assoc-aref (type-info self) parent-type :child-type)))
+    (when child-type
+      ;; child-type cannot be nil unless there are no children
+      (assoc-aref (type-info self) child-type :initform))))
+
+(defmethod new-object-of-type ((self lisp-controller) typ)
+  ;; Create & initialize a new instance of some type
+  (eval (assoc-aref (type-info self) typ :initform)))
+
+(defmethod children-of-object ((self lisp-controller) (obj ht-entry))
+  ;; We want to handle the children of ht-entry objects a bit differently
+  ;; Basically we would like to return the children of the value of the entry
+  (children-of-object self (ht-value obj)))
+
+(defmethod children-of-object ((self lisp-controller) obj)
+  ;; Get the children of an instance of some type
+  (let* ((obj-type (controller-type-of self obj))
+         (child-key (assoc-aref (type-info self) obj-type :child-key))
+         (children-object nil))
+    (if (children-func self)
+      (setf children-object (funcall (children-func self) (owner self) self obj))
+      (if child-key
+        (setf children-object (funcall child-key obj))))
+    ;; if the children object is a hash-table, expand it into an ht-entry list
+    (when (typep children-object 'hash-table)
+      (setf children-object (children children-object)))
+    (sort-sequence self children-object)))
+
+(defmethod add-child-to ((self lisp-controller) (parent ht-entry))
+  ;; We want to handle the children of ht-entry objects a bit differently
+  ;; Basically we would like to add a child to the children of the value of the entry
+  (add-child-to self (ht-value parent)))
+
+(defmethod add-child-to ((self lisp-controller) parent)
+  (let* ((parent-type (controller-type-of self parent))
+         (child-type (assoc-aref (type-info self) parent-type :child-type))
+         (child-key (assoc-aref (type-info self) parent-type :child-key))
+         (child-initform (and child-type (assoc-aref (type-info self) child-type :initform)))
+         (set-child-func (assoc-aref (type-info self) parent-type :child-setf-key))
+         (new-children nil)
+         (new-child nil))
+    (if (and child-type child-key child-initform set-child-func)
+      ;; we've got everything we need to set the child ourselves
+      (let ((children (children-of-object self parent)))
+        (setf new-child (eval child-initform))
+        (setf new-children 
+              (funcall set-child-func 
+                       (add-to-child-seq parent children new-child) 
+                       parent))
+        (when (subtypep (controller-type-of self parent) 'hash-table)
+          (setf (ht new-child) parent)
+          (setf (gethash (ht-key new-child) parent) (ht-value new-child))))
+      ;; else see if there is a user-specified function to add a child
+      (when (add-child-func self)
+        (multiple-value-setq (new-children new-child)
+          (funcall (add-child-func self) parent))))
+    (when (added-func self)
+      ;; notify by calling the function specified in IB
+      (let ((last-child (if (typep new-child 'ht-entry)
+                          (list (ht-key new-child) (ht-value new-child))
+                          new-child)))
+        (when last-child
+          (funcall (added-func self) 
+                   (owner self)
+                   self
+                   (root self)
+                   parent last-child))))
+    (sort-sequence self new-children)))
+
+(defmethod child-type-of ((self lisp-controller) obj)
+  ;; Get the type of child objects for an instance of some type
+  (let ((obj-type (controller-type-of self obj)))
+    (assoc-aref (type-info self) obj-type :child-type)))
+
+(defmethod col-value ((self lisp-controller) obj col-obj)
+  ;; Get the lisp value for some column for an object
+  ;; return "" if there isn't one so the display doesn't
+  ;; have "nil" for columns without values.
+  (let* ((obj-type (controller-type-of self obj))
+         (override-reader (reader-func self))
+         (reader-func (car (assoc-aref (type-info self) obj-type col-obj))))
+    (if override-reader
+      (funcall override-reader obj (assoc-aref (column-info self) col-obj :col-val))
+      (if reader-func
+        (funcall reader-func obj)
+        ""))))
+
+(defmethod set-col-value ((self lisp-controller) obj col-obj new-value)
+  ;; set the lisp value for some column for an object
+  (let* ((obj-type (controller-type-of self obj))
+         (override-writer (writer-func self))
+         (writer-func (cdr (assoc-aref (type-info self) obj-type col-obj))))
+    (if override-writer
+      (funcall override-writer new-value obj (assoc-aref (column-info self) col-obj :col-val))
+      (if writer-func
+        (funcall writer-func new-value obj)))))
+
+(defmethod remove-child-from ((self lisp-controller) parent child)
+  (let* ((parent-type (controller-type-of self parent))
+         (child-key (assoc-aref (type-info self) parent-type :child-key))
+         (set-child-func (assoc-aref (type-info self) parent-type :child-setf-key))
+         (parent-is-root (eq parent (root self)))
+         (new-children nil))
+    (if (delete-func self)
+      (setf new-children (funcall (delete-func self) parent child))
+      (when (and child-key set-child-func)
+        (let ((children (funcall child-key parent)))
+          (setf new-children 
+                (funcall set-child-func
+                         (delete-from-child-seq children child)
+                         parent)))))
+    (when (and parent-is-root (null new-children))
+      ;; The only time this actually does something is when the 
+      ;; objects were a list and we just deleted the last child.
+      (if (listp parent) (setf (root self) nil))
+      (setf (objects self) nil))
+    (when (removed-func self)
+      (funcall (removed-func self) (owner self) self (root self) parent child))
+    (sort-sequence self new-children)))
+
+(defmethod sort-sequence ((self lisp-controller) (seq sequence))
+  ;; sort a sequence of objects
+  (if (plusp (length seq))
+    (let* ((seq-elt-type (controller-type-of self (elt seq 0)))
+           (seq-elt-sort-pred (assoc-aref (type-info self) seq-elt-type :sort-pred))
+           (seq-elt-sort-key (assoc-aref (type-info self) seq-elt-type :sort-key)))
+      (if seq-elt-sort-pred
+        (typecase seq
+          (cons 
+           (sort-list-in-place seq seq-elt-sort-pred seq-elt-sort-key))
+          (vector 
+           (if seq-elt-sort-key
+             (sort seq seq-elt-sort-pred :key seq-elt-sort-key)
+             (sort seq seq-elt-sort-pred))))
+        seq))
+    seq))
+
+(defmethod sort-sequence ((self lisp-controller) thing)
+  ;; trying to sort something that isn't a sequence
+  ;; just do nothing
+  thing)
+
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;; Methods invoked by NSTableView objects at runtime.
+;; Needed to be a data source for NSTableView
+
+(objc:defmethod (#/tableView:objectValueForTableColumn:row: :id) 
+                ((self lisp-controller) 
+                 (tab :id)
+                 (col :id)
+                 (row #>NSInteger))
+  (declare (ignore tab))
+  (let ((ns-format (assoc-aref (column-info self) col :col-format)))
+    (lisp-to-ns-object (col-value self (elt (objects self) row) col) ns-format)))
+
+(objc:defmethod (#/numberOfRowsInTableView: #>NSInteger) 
+                ((self lisp-controller) (tab :id))
+  ;; Assumes that objects is some type of sequence
+  ;; Subclass should override this method if that is not true.
+  (declare (ignore tab))
+  (with-slots (root objects count-func owner) self
+    (if root
+      (if count-func
+        (funcall count-func owner self root)
+        (typecase objects
+          (array (if (array-has-fill-pointer-p objects)
+                   (fill-pointer objects)
+                   (first (array-dimensions objects))))
+          (t
+           (length objects))))
+      0)))
+  
+(objc:defmethod (#/tableView:setObjectValue:forTableColumn:row: :void)
+                ((self lisp-controller) 
+                 (tab :id)
+                 (val :id)
+                 (col :id)
+                 (row #>NSInteger))
+  ;; We let the user edit the table and something was changed
+  ;; try to convert it to the same type as what is already in that
+  ;; position in the objects.
+  (declare (ignore tab))
+  (let* ((row-obj (elt (objects self) row))
+         (old-obj (col-value self row-obj col))
+         (ns-format (assoc-aref (column-info self) col :col-format))
+         (new-val (ns-to-lisp-object old-obj val ns-format)))
+    (if (writer-func self)
+      (funcall (writer-func self)
+               new-val
+               (root self) 
+               row
+               (assoc-aref (column-info self) col :col-val))
+      (set-col-value self row-obj col new-val))
+    (when (edited-func self)
+      (let* ((row-obj (object-at-row self row))
+             (edited-obj (if (typep row-obj 'ht-entry)
+                           (list (ht-key row-obj) (ht-value row-obj))
+                           row-obj)))
+        (funcall (edited-func self)
+                 (owner self)
+                 self
+                 (root self)
+                 row
+                 (assoc-aref (column-info self) col :col-indx)
+                 edited-obj
+                 old-obj
+                 new-val)))
+    ;; re-sort and reload the table
+    ;; unfortunately we probably have to do this for every change since
+    ;; we don't know what affects the sort order
+    (sort-sequence self (objects self))
+    (#/reloadData (view self))))
+
+(objc:defmethod (#/tableView:shouldEditTableColumn:row: #>BOOL)
+                ((self lisp-controller) 
+                 (tab :id)
+                 (col :id)
+                 (row #>NSInteger))
+  (declare (ignore tab))
+  ;; allow editing if there is a function available to setf a new value
+  (if (or (writer-func self)
+           (let ((obj-type (controller-type-of self (elt (objects self) row))))
+             (cdr (assoc-aref (type-info self) obj-type col))))
+    #$YES
+    #$NO))
+
+(objc:defmethod (#/tableViewSelectionDidChange: :void) 
+                ((self lisp-controller) (notif :id))
+  (let* ((tab (#/object notif))
+         (row-indx (#/selectedRow tab))
+         (col-indx (#/selectedColumn tab)))
+    ;; enable/disable buttons that remove current selection
+    (#/willChangeValueForKey: self #@"canRemove")
+    (if (minusp row-indx)
+      (setf (can-remove self) #$NO)
+      (setf (can-remove self) #$YES))
+    (#/didChangeValueForKey: self #@"canRemove")
+    ;; enable/disable buttons that want to add a child to
+    ;; the current selection
+    (set-can-add-child self row-indx)
+    ;; User code to do something when a cell is selected
+    (when (select-func self)
+      (let* ((row-obj (and (not (eql row-indx -1)) (object-at-row self row-indx)))
+             (col (assoc-aref (column-info self) col-indx :col-obj))
+             (selected-obj (cond ((and (minusp col-indx) (minusp row-indx))
+                                  nil)
+                                 ((minusp col-indx)
+                                  row-obj)
+                                 ((minusp row-indx)
+                                  (assoc-aref (column-info self) col :col-title))
+                                 (t
+                                  (col-value self row-obj col)))))
+        (funcall (select-func self)
+                 (owner self)
+                 self
+                 (root self)
+                 row-indx
+                 col-indx
+                 selected-obj)))))
+
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;; Methods invoked by NSOutlineView objects at runtime.
+;; Needed to be a data source for NSOutlineView.
+
+(objc:defmethod (#/outlineView:child:ofItem: :id)
+                ((self lisp-controller) 
+                 (olview :id)
+                 (child #>NSInteger)
+                 (item :id))
+  (declare (ignore olview))
+  (with-slots (objects) self
+    (cond ((typep item 'lisp-ptr-wrapper)
+           (let* ((parent (lpw-lisp-ptr item))
+                  (parent-depth (lpw-depth item))
+                  (children (children-of-object self parent))
+                  (child-ptr (elt children child)))
+             (wrapper-for self child-ptr :depth (1+ parent-depth) :parent parent)))
+          ((eql item (%null-ptr))
+           (let ((child-ptr (elt objects child)))
+             (wrapper-for self child-ptr :depth 1)))
+          (t
+           (%null-ptr)))))
+
+(objc:defmethod (#/outlineView:isItemExpandable: #>BOOL)
+                ((self lisp-controller) 
+                 (olview :id)
+                 (item :id))
+  (declare (ignore olview))
+  (cond ((eql item (%null-ptr))
+         ;; root object
+         #$YES)
+        ((typep item 'lisp-ptr-wrapper)
+         (if (children-of-object self (lpw-lisp-ptr item))
+           #$YES
+           #$NO))
+         (t
+          #$NO)))
+
+(objc:defmethod (#/outlineView:numberOfChildrenOfItem: #>NSInteger)
+                ((self lisp-controller) 
+                 (olview :id)
+                 (item :id))
+  (declare (ignore olview))
+  (cond ((typep item 'lisp-ptr-wrapper)
+         (length (children-of-object self (lpw-lisp-ptr item))))
+        ((eql item (%null-ptr))
+         (length (objects self)))
+        (t
+         0)))
+
+(objc:defmethod (#/outlineView:objectValueForTableColumn:byItem: :id)
+                ((self lisp-controller) 
+                 (olview :id)
+                 (col :id)
+                 (item :id))
+  (declare (ignore olview))
+  (let ((ns-format (assoc-aref (column-info self) col :col-format)))
+    (lisp-to-ns-object (col-value self (lpw-lisp-ptr item) col) ns-format)))
+
+(objc:defmethod (#/outlineView:setObjectValue:forTableColumn:byItem: :void)
+                ((self lisp-controller) 
+                 (olview :id)
+                 (val :id)
+                 (col :id)
+                 (item :id))
+  (let* ((row-obj (lpw-lisp-ptr item))
+         (old-obj (col-value self row-obj col))
+         (ns-format (assoc-aref (column-info self) col :col-format))
+         (new-val (ns-to-lisp-object old-obj val ns-format)))
+    (if (writer-func self)
+      (funcall (writer-func self)
+               new-val
+               (root self) 
+               row-obj
+               (assoc-aref (column-info self) col :col-val))
+      (set-col-value self row-obj col new-val))
+    (when (edited-func self)
+      (let* ((row (#/rowForItem: olview item))
+             (edited-obj (if (typep row-obj 'ht-entry)
+                           (list (ht-key row-obj) (ht-value row-obj))
+                           row-obj)))
+        (funcall (edited-func self)
+                 (owner self)
+                 self
+                 (root self)
+                 row
+                 (assoc-aref (column-info self) col :col-val)
+                 edited-obj
+                 old-obj
+                 new-val)))))
+
+(objc:defmethod (#/outlineView:shouldEditTableColumn:item: #>BOOL)
+                ((self lisp-controller) 
+                 (olview :id)
+                 (col :id)
+                 (item :id))
+  (declare (ignore olview))
+  ;; allow editing if there is a function available to setf a new value
+  (if (or (writer-func self)
+           (let ((obj-type (controller-type-of self (lpw-lisp-ptr item))))
+             (cdr (assoc-aref (type-info self) obj-type col))))
+    #$YES
+    #$NO))
+
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;; Methods for inserting and removing rows. User interface can trigger these
+;; (for example) by setting action methods on buttons 
+
+(objc:defmethod (#/insert: :void)
+                ((self lisp-controller) (button :id))
+  (declare (ignore button))
+  ;; insert a new object into the root object
+  (unless (root self)
+    ;; need to create a root object
+    ;; may still be null if root type is 'list
+    (setf (root self)
+          (new-object-of-type self (root-type self))))
+  (let ((new-children (add-child-to self (root self))))
+    (when (null (root self))
+      ;; special hack for root objects that are lists and may be null
+      (setf (root self) new-children)
+      (setf (objects self) new-children)))
+  (#/reloadData (view self)))
+
+(objc:defmethod (#/addChild: :void)
+                ((self lisp-controller) (button :id))
+  (declare (ignore button))
+  ;; add a new child to the currently selected item
+  (let* ((row-num (#/selectedRow (view self)))
+         (parent (object-at-row self row-num)))
+    (add-child-to self parent))
+  (#/reloadData (view self)))
+
+(objc:defmethod (#/remove: :void)
+                ((self lisp-controller) (button :id))
+  (declare (ignore button))
+  (let ((row-num (#/selectedRow (view self))))
+    (multiple-value-bind (child parent) (object-at-row self row-num)
+      (when parent
+        (remove-child-from self parent child)
+        (#/reloadData (view self))))))
+
+
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;; Methods for using a lisp-controller as an initial binding target
+;; Binding paths must start with "root" or "selected" and can use
+;; lisp accessors from that point to other lisp targets.
+;; Any atomic value found by following the path is converted to an 
+;; Objective-C value and returned. If a non-atomic value is found by 
+;; following the path it is encapsulated within a lisp-ptr-wrapper object
+;; and returned. When that path is subsequently followed the lisp-ptr-wrapper
+;; will handle the path reference in the same way.
+
+(objc:defmethod (#/root :id)
+                ((self lisp-controller))
+  (cond ((typep (root self) 'objc:objc-object)
+             (root self))
+        ((null (root self))
+         (%null-ptr))
+        ((typep (root self) 'objc-displayable)
+         (lisp-to-ns-object (root self)))
+        (t
+         (wrapper-for self (root self)))))
+
+(objc:defmethod (#/selection :id)
+                ((self lisp-controller))
+  (let* ((row-num (#/selectedRow (view self)))
+         (obj (object-at-row self row-num)))
+    (cond ((typep obj 'objc:objc-object)
+           obj)
+          ((typep obj 'objc-displayable)
+           (lisp-to-ns-object obj))
+          (t
+           (wrapper-for self obj)))))
+
+(provide :lisp-controller)
+      
Index: /trunk/contrib/krueger/InterfaceProjects/Utilities/lisp-doc-controller.lisp
===================================================================
--- /trunk/contrib/krueger/InterfaceProjects/Utilities/lisp-doc-controller.lisp	(revision 13946)
+++ /trunk/contrib/krueger/InterfaceProjects/Utilities/lisp-doc-controller.lisp	(revision 13946)
@@ -0,0 +1,131 @@
+;; lisp-doc-controller.lisp
+
+#|
+The MIT license.
+
+Copyright (c) 2010 Paul L. Krueger
+
+Permission is hereby granted, free of charge, to any person obtaining a copy of this software 
+and associated documentation files (the "Software"), to deal in the Software without restriction, 
+including without limitation the rights to use, copy, modify, merge, publish, distribute, 
+sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is 
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all copies or substantial 
+portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT 
+LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. 
+IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, 
+WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE 
+SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+|#
+
+(eval-when (:compile-toplevel :load-toplevel :execute)
+  (require :menu-utils))
+
+(defpackage :interface-utilities
+  (:nicknames :iu)
+  (:export lisp-doc-controller))
+
+(in-package :iu)
+
+;; demonstration code for creating a Cocoa document class in lisp that can be required
+;; and loaded into a standard running CCL IDE (i.e. does not require a stand-alone program).
+
+;; lisp-doc-controller class
+;; This class does some of the same things that the shared NSDocumentController instance
+;; does for stand-alone application programs. We use it so that we don't have to mess
+;; with CCL's existing interfaces to or its NSApplication delegate objects et. We will
+;; create specific menu-items that target an instance of this class to create new documents
+;; of a specified type that the CCL IDE knows nothing about. We will tell the shared
+;; NSDocumentController about our documents so that it can manage things like saving and
+;; closing them. This class will also handle opening files of a specified type.
+;; The creator of one of these objects can also specify a name to use for inserting
+;; "New <menu-class>" and "Open <menu-class>" menuitems which will target this instance.
+
+(defclass lisp-doc-controller (ns:ns-object)
+  ((document-class :accessor document-class :initarg :doc-class)
+   (menu-class-name :accessor menu-class-name :initarg :menu-class)
+   (file-ext :accessor file-ext :initarg :file-ext)
+   (doc-ctrlr :accessor doc-ctrlr)
+   (open-panel :accessor open-panel)
+   (type-ns-str :accessor type-ns-str)
+   (ext-ns-str :accessor ext-ns-str)
+   (type-array :accessor type-array)
+   (documents :accessor documents :initform nil))
+  (:default-initargs 
+    :doc-class nil
+    :menu-class nil
+    :file-ext nil)
+  (:metaclass ns:+ns-object))
+
+(defmethod initialize-instance :after ((self lisp-doc-controller) 
+                                       &key menu-class file-ext &allow-other-keys)
+  (ccl:terminate-when-unreachable self)
+  (when menu-class
+    (setf (type-ns-str self) (ccl::%make-nsstring menu-class))
+    (setf (ext-ns-str self) (ccl::%make-nsstring file-ext))
+    (setf (doc-ctrlr self) (#/sharedDocumentController ns:ns-document-controller))
+    (setf (open-panel self) (make-instance ns:ns-open-panel))
+    (#/retain (open-panel self))
+    (setf (type-array self)
+          (#/arrayByAddingObject: (make-instance ns:ns-array) (ext-ns-str self)))
+    (make-and-install-menuitems-after "File" "New"
+                                      (list (concatenate 'string "New " menu-class) 
+                                            "newDoc"
+                                            nil
+                                            self))
+    (make-and-install-menuitems-after "File" "Open..."
+                                      (list (concatenate 'string "Open " menu-class "...") 
+                                            "openDoc"
+                                            nil
+                                            self))
+    (make-and-install-menuitems-after "File" "Print..."
+                                      (list (concatenate 'string "Print " menu-class "...") 
+                                            (concatenate 'string "print" menu-class ":")
+                                            nil
+                                            nil))))
+
+(defmethod ccl:terminate ((self lisp-doc-controller))
+  (#/release (type-ns-str self))
+  (#/release (ext-ns-str self))
+  (#/release (type-array self))
+  (#/release (open-panel self)))
+
+(objc:defmethod (#/newDoc :void)
+                ((self lisp-doc-controller))
+  (let ((new-doc (make-instance (document-class self))))
+    (push new-doc (documents self))
+    ;; register the document with the shared controller so that things like
+    ;; "save" and "close" will work properly
+    (#/addDocument: (doc-ctrlr self) new-doc)
+    (#/makeWindowControllers new-doc)
+    (#/showWindows new-doc)))
+
+(objc:defmethod (#/openDoc :void)
+                ((self lisp-doc-controller))
+  (let ((result (#/runModalForTypes: (open-panel self) (type-array self))))
+    (when (eql result 1)
+      (let ((urls (#/URLs (open-panel self))))
+        (dotimes (i (#/count urls))
+          (let ((doc (make-instance (document-class self))))
+            (setf doc (#/initWithContentsOfURL:ofType:error: 
+                       doc
+                       (#/objectAtIndex: urls i)
+                       (type-ns-str self)
+                       (%null-ptr)))
+            (if doc
+              (progn
+                (pushnew doc (documents self))
+                (#/addDocument: (doc-ctrlr self) doc)
+                (#/makeWindowControllers doc)
+                (#/showWindows doc))
+              (#_NSRunAlertPanel #@"ALERT" 
+                                 #@"Could not open specified file ... ignoring it."
+                                 #@"OK"  
+                                 (%null-ptr)
+                                 (%null-ptr)))))))))
+
+(provide :lisp-doc-controller)
Index: /trunk/contrib/krueger/InterfaceProjects/Utilities/list-utils.lisp
===================================================================
--- /trunk/contrib/krueger/InterfaceProjects/Utilities/list-utils.lisp	(revision 13946)
+++ /trunk/contrib/krueger/InterfaceProjects/Utilities/list-utils.lisp	(revision 13946)
@@ -0,0 +1,97 @@
+;; list-utils.lisp
+
+#|
+The MIT license.
+
+Copyright (c) 2010 Paul L. Krueger
+
+Permission is hereby granted, free of charge, to any person obtaining a copy of this software 
+and associated documentation files (the "Software"), to deal in the Software without restriction, 
+including without limitation the rights to use, copy, modify, merge, publish, distribute, 
+sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is 
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all copies or substantial 
+portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT 
+LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. 
+IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, 
+WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE 
+SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+|#
+
+(defpackage :interface-utilities
+  (:nicknames :iu)
+  (:export add-to-list-at
+           delete-from-list
+           find-cdr
+           sort-list-in-place))
+
+(in-package :iu)
+
+(defun add-to-list-at (lst indx value)
+  ;; splices value into lst at the designated indx
+  ;; if indx = 0 we make sure that the lst pointer remains
+  ;; valid.
+  (cond ((null lst)
+         (setf lst (list value)))
+        ((>= indx (list-length lst))
+         (nconc lst (list value)))
+        (t
+         (let* ((nth-ptr (nthcdr indx lst))
+                (new-cons (cons (car nth-ptr) (cdr nth-ptr))))
+           ;; splice in the new value at the position of the specified indx
+           (setf (car nth-ptr) value)
+           (setf (cdr nth-ptr) new-cons))))
+  lst)
+
+(defun delete-from-list (lst thing)
+  (cond ((eql 1 (list-length lst))
+         nil)
+        ((eq thing (first lst))
+         (setf (car lst) (cadr lst))
+         (setf (cdr lst) (cddr lst))
+         (if (and (null (car lst)) (null (cdr lst)))
+           nil
+           lst))
+        (t 
+         (delete thing lst))))
+
+(defun find-cdr (lst cdr-thing)
+  ;; return the cons cell with a cdr eq to cdr-thing
+  (do* ((cons-cell lst (cdr cons-cell)))
+       ((or (null cons-cell) (eq (cdr cons-cell) cdr-thing)) cons-cell)))
+
+(defun sort-list-in-place (lst sort-pred &optional (sort-key nil))
+  ;; Sorting a list normally results in a reordering of the cons
+  ;; cells. We swap the contents of cons cells around after sorting 
+  ;; so that previous references to the list are still valid.
+  ;; That way we can sort "in place" without having to copy the whole list.
+  (let ((old-first-cons lst)
+        (new-first-cons nil))
+    (if sort-key
+      (setf new-first-cons (sort lst sort-pred :key sort-key))
+      (setf new-first-cons (sort lst sort-pred)))
+    (let* ((prev-cons (find-cdr new-first-cons old-first-cons))
+           (new-first-car (car new-first-cons))
+           (new-first-cdr (cdr new-first-cons)))
+      (when prev-cons
+        ;; exchange the two cons cells: the one that used to 
+        ;; be the first (called the old-first-cons) with the 
+        ;; first in the sorted list (called the new-first-cons)
+        ;; first exchange cars
+        (setf (car new-first-cons) (car old-first-cons))
+        (setf (car old-first-cons) new-first-car)
+        ;; always set cdr of new-first-cons to the cdr of the old-first-cons 
+        (setf (cdr new-first-cons) (cdr old-first-cons))  
+        ;; have to be more careful about other cdr pointers
+        (if (eq prev-cons new-first-cons)
+          (setf (cdr old-first-cons) new-first-cons)
+          (progn
+            (setf (cdr prev-cons) new-first-cons)
+            (setf (cdr old-first-cons) new-first-cdr)))))
+    lst))
+
+(provide :list-utils)
Index: /trunk/contrib/krueger/InterfaceProjects/Utilities/nib.lisp
===================================================================
--- /trunk/contrib/krueger/InterfaceProjects/Utilities/nib.lisp	(revision 13946)
+++ /trunk/contrib/krueger/InterfaceProjects/Utilities/nib.lisp	(revision 13946)
@@ -0,0 +1,39 @@
+;; nib.lisp
+;; Start with some corrected functions from .../ccl/examples/cocoa/nib-loading/HOWTO.html
+
+(defpackage :interface-utilities
+  (:nicknames :iu)
+  (:export load-nibfile))
+
+(in-package :iu)
+
+;; Note that callers of this function are responsible for retaining top-level objects if
+;; they're going to be around for a while and them releasing them when no longer needed.
+
+(defun load-nibfile (nib-path &key (nib-owner #&NSApp) (retain-top-objs nil))
+  (let* ((app-zone (#/zone nib-owner))
+         (nib-name (ccl::%make-nsstring (namestring nib-path)))
+         (objects-array (#/arrayWithCapacity: ns:ns-mutable-array 16))
+         (toplevel-objects (list))
+         (dict (#/dictionaryWithObjectsAndKeys: ns:ns-mutable-dictionary
+                nib-owner #&NSNibOwner
+                objects-array #&NSNibTopLevelObjects
+                (%null-ptr)))
+         (result (#/loadNibFile:externalNameTable:withZone: ns:ns-bundle
+                                                            nib-name
+                                                            dict
+                                                            app-zone)))
+    (when result
+      (dotimes (i (#/count objects-array))
+        (setf toplevel-objects 
+              (cons (#/objectAtIndex: objects-array i)
+                    toplevel-objects)))
+      (when retain-top-objs
+        (dolist (obj toplevel-objects)
+          (#/retain obj))))
+    (#/release nib-name)
+    ;; Note that both dict and objects-array are temporary (i.e. autoreleased objects)
+    ;; so don't need to be released by us
+    (values toplevel-objects result)))
+
+(provide :NIB)
Index: /trunk/contrib/krueger/InterfaceProjects/Utilities/ns-binding-utils.lisp
===================================================================
--- /trunk/contrib/krueger/InterfaceProjects/Utilities/ns-binding-utils.lisp	(revision 13946)
+++ /trunk/contrib/krueger/InterfaceProjects/Utilities/ns-binding-utils.lisp	(revision 13946)
@@ -0,0 +1,125 @@
+;; ns-binding-utils.lisp
+
+#|
+The MIT license.
+
+Copyright (c) 2010 Paul L. Krueger
+
+Permission is hereby granted, free of charge, to any person obtaining a copy of this software 
+and associated documentation files (the "Software"), to deal in the Software without restriction, 
+including without limitation the rights to use, copy, modify, merge, publish, distribute, 
+sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is 
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all copies or substantial 
+portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT 
+LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. 
+IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, 
+WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE 
+SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+|#
+
+(eval-when (:compile-toplevel :load-toplevel :execute)
+  (require :ns-object-utils)
+  (require :assoc-array))
+
+(defpackage :interface-utilities
+  (:nicknames :iu)
+  (:export bound-to linking-views link-path-components lisp-to-objc-keypathname objc-to-lisp-keypathname))
+
+(in-package :iu)
+
+;; Given a window and another object, find all the subviews of the window that link to that object
+;; for their value and the key paths that they use (returned as a string).
+
+(defmethod linking-views ((win ns:ns-window) (obj ns:ns-object))
+  (let* ((cview (#/contentView win))
+         (subviews (ns-to-lisp-list (#/subviews cview) :no-convert t)))
+    (mapcan #'(lambda (v)
+                (multiple-value-bind (bound-p path) (bound-to v obj #@"value")
+                  (when bound-p
+                    (list (cons v path)))))
+            subviews)))
+
+(defmethod bound-to ((view ns::ns-view) (bound-to-obj ns::ns-object) binding-ns-string)
+  (let* ((objc-info (#/infoForBinding: view binding-ns-string))
+         (info (and (not (eql objc-info (%null-ptr))) (ns-to-lisp-assoc objc-info :no-convert t)))
+         (proxy (cdr (assoc 'CL-USER::NSOBSERVEDOBJECT info)))
+         (proxy-desc (and proxy (ns-to-lisp-string (#/description proxy))))
+         (bound-to-desc (ns-to-lisp-string (#/description bound-to-obj)))
+         (path (and info (ns-to-lisp-string (cdr (assoc 'CL-USER::NSOBSERVEDKEYPATH info))))))
+    (if (and info (find-substring bound-to-desc proxy-desc))
+      (values t path)
+      (values nil nil))))
+
+(defun link-path-components (path-str)
+  (if (zerop (length path-str))
+    nil
+    (do* ((begin 0
+                 (1+ end))
+          (end (or (position #\. path-str :start (1+ begin))
+                   (length path-str))
+               (or (position #\. path-str :start (1+ begin))
+                   (length path-str)))
+          (words (list (subseq path-str begin end))
+                 (push (subseq path-str begin end) words)))
+         ((>= end (length path-str))
+          (mapcar #'objc-to-lisp-keypathname (nreverse words))))))
+
+(let ((path-trans (make-instance 'assoc-array :rank 2)))
+
+  (defun objc-to-lisp-keypathname (name-str)
+    ;; translate a name from Objective-C to Lisp
+    ;; Use standard translation for function/slot names except the use of 
+    ;; underscore (#\_) is used initially to delimit a package specifier
+    (let* ((package-end (if (char= (elt name-str 0) #\_)
+                          (position #\_ name-str :start 1)))
+           (pkg-string (string-upcase (subseq name-str 1 package-end)))
+           (path-string (if package-end 
+                          (subseq name-str (1+ package-end))
+                          name-str))
+           (pkg (or (and package-end
+                         (find-package pkg-string))
+                    (find-package :cl-user))))
+      ;; cache the string we are translating so that we can reverse
+      ;; translate to exactly the same string used by the developer.
+      (setf (assoc-aref path-trans pkg path-string) name-str)
+      (ccl::compute-lisp-name path-string pkg)))
+  
+  (defun lisp-to-objc-keypathname (name)
+    ;; translate name (symbol or string) from Lisp to Objective-C
+    ;; If we previously cached a string that came from Objective-C and
+    ;; was translated to this name, then translate back to it. This
+    ;; prevents problems caused by alternative package names/nicknames
+    ;; that the developer might have used in Interface Builder.
+    ;; Use standard translation for function/slot names except prefix
+    ;; package name and underscore if package is not cl-user
+   
+    (let ((pkg (if (symbolp name)
+                 (symbol-package name)
+                 (find-package :cl-user)))
+          (name-str (string name))
+          (name-segments nil))
+      (or (assoc-aref path-trans pkg name-str)
+          (progn
+            (do* ((start 0 (1+ pos))
+                  (pos (position #\- name-str)
+                       (position #\- name-str :start start)))
+                 ((null pos) (setf name-segments (nreverse (cons (subseq name-str start) name-segments))))
+              (setf name-segments (cons (subseq name-str start pos) name-segments)))
+            (setf name-segments (cons (string-downcase (first name-segments))
+                                      (mapcar #'string-capitalize (rest name-segments))))
+            (unless (eq pkg (find-package :cl-user))
+              (setf name-segments (cons (concatenate 'string
+                                                     "_"
+                                                     (lisp-to-objc-keypathname (or (first (package-nicknames pkg))
+                                                                                   (package-name pkg)))
+                                                     "_")
+                                        name-segments)))
+            (apply #'concatenate 'string name-segments)))))
+
+) ;; end of definitions using path-trans assoc-array
+            
Index: /trunk/contrib/krueger/InterfaceProjects/Utilities/ns-object-utils.lisp
===================================================================
--- /trunk/contrib/krueger/InterfaceProjects/Utilities/ns-object-utils.lisp	(revision 13946)
+++ /trunk/contrib/krueger/InterfaceProjects/Utilities/ns-object-utils.lisp	(revision 13946)
@@ -0,0 +1,346 @@
+;; ns-object-utils.lisp
+#|
+The MIT license.
+
+Copyright (c) 2010 Paul L. Krueger
+
+Permission is hereby granted, free of charge, to any person obtaining a copy of this software 
+and associated documentation files (the "Software"), to deal in the Software without restriction, 
+including without limitation the rights to use, copy, modify, merge, publish, distribute, 
+sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is 
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all copies or substantial 
+portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT 
+LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. 
+IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, 
+WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE 
+SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+|#
+
+
+;; These are useful for manipulating various types of NSObjects using lisp
+
+(eval-when (:compile-toplevel :load-toplevel :execute)
+  (require :ns-string-utils)
+  (require :ns-binding-utils)
+  (require :nslog-utils)
+  (require :date)
+  (require :decimal)
+  (require :assoc-array))
+
+
+(defpackage :interface-utilities
+  (:nicknames :iu)
+  (:export 
+   did-change-value-for-key
+   lisp-to-ns-array
+   lisp-to-ns-dict
+   lisp-to-ns-object
+   lisp-ptr-wrapper
+   lpw-lisp-ptr
+   lpw-depth
+   lpw-parent
+   make-ptr-wrapper
+   ns-to-lisp-array
+   ns-to-lisp-assoc
+   ns-to-lisp-hash-table
+   ns-to-lisp-list
+   ns-to-lisp-object
+   objc-displayable
+   print-ns-object
+   will-change-value-for-key
+   wrapper-for))
+
+(in-package :iu)
+
+(defun print-ns-object (ns-obj)
+  ;; default print methods for objects truncate strings at 1024 characters for some reason
+  ;; this function doesn't
+  (if (ccl::objc-object-p ns-obj)
+    (format t "~a" (ns-to-lisp-string (#/description ns-obj)))
+    (format t "~s" ns-obj)))
+
+(defun ns-to-lisp-object (old-lisp-obj ns-obj &optional (ns-format nil))
+  ;; convert an arbitrary NSObject object to an appropriate lisp object.
+  ;; Often done so that it can replace the old-lisp-obj when edited
+  ;; An empty string @"" returns nil if old-lisp-obj is not a string
+  (cond ((ccl::objc-object-p old-lisp-obj)
+         ;; the old value was an NSObject so just return the new value
+         ns-obj)
+        ((typep ns-obj 'lisp-ptr-wrapper)
+         ;; just strip the wrapper and return the original object
+         (lpw-lisp-ptr ns-obj))
+        ((typep ns-obj 'ns:ns-decimal)
+         (if (or (floatp old-lisp-obj) (eq :float old-lisp-obj))
+           ;; convert the decimal to a float
+           (#/doubleValue ns-obj)
+           ;; otherwise convert it to an appropriate lisp integer with assumed
+           ;; decimals (see ip;Utilities;decimal.lisp)
+           (if (eq (first ns-format) :decimal)
+             (lisp-from-ns-decimal ns-obj :decimals (second ns-format))
+             (lisp-from-ns-decimal ns-obj))))
+        ((typep ns-obj 'ns:ns-number)
+         (read-from-string (ns-to-lisp-string (#/descriptionWithLocale: ns-obj (%null-ptr)))
+                           nil nil))
+        ((typep ns-obj 'ns:ns-date)
+         (ns-to-lisp-date ns-obj))
+        ((typep ns-obj 'ns:ns-dictionary)
+         (if (or (consp old-lisp-obj) (eq old-lisp-obj :cons))
+           (ns-to-lisp-assoc ns-obj)
+           (ns-to-lisp-hash-table ns-obj)))
+        ((typep ns-obj 'ns:ns-array)
+         (if (or (consp old-lisp-obj) (eq old-lisp-obj :cons))
+           (ns-to-lisp-list ns-obj)
+           (ns-to-lisp-array ns-obj)))
+        ((typep ns-obj 'ns:ns-string)
+         (let ((str (ns-to-lisp-string ns-obj)))
+           (if (or (stringp old-lisp-obj) (eq old-lisp-obj :string))
+             str
+             (read-from-string str nil nil))))
+        ((typep ns-obj 'ns:ns-null)
+         nil)
+        (t
+         ;; can't convert so just return ns-obj
+         ns-obj)))
+
+(defun lisp-to-ns-object (lisp-obj &optional (ns-format nil))
+  ;; convert an arbitrary lisp object to an appropriate NSObject so
+  ;; that it can be displayed someplace
+  (cond ((ccl::objc-object-p lisp-obj)
+         ;; it's already an NSObject so just return it
+         lisp-obj)
+        ((eq ns-format :date)
+         ;; assume lisp-obj is an integer representing a lisp date
+         (lisp-to-ns-date lisp-obj))
+        ((and (consp ns-format) (eq (first ns-format) :decimal))
+         (cond ((typep lisp-obj 'fixnum)
+                (lisp-to-ns-decimal lisp-obj :decimals (second ns-format)))
+               ((typep lisp-obj 'number)
+                (lisp-to-ns-decimal (round (* (expt 10 (second ns-format)) lisp-obj))
+                                    :decimals (second ns-format)))
+               (t
+                (lisp-to-ns-decimal 0 :decimals (second ns-format)))))
+        ((integerp lisp-obj)
+         (#/numberWithInt: ns:ns-number lisp-obj))
+        ((typep lisp-obj 'double-float)
+         (#/numberWithDouble: ns:ns-number lisp-obj))
+        ((floatp lisp-obj)
+         (#/numberWithFloat: ns:ns-number lisp-obj))
+        ((stringp lisp-obj)
+         (lisp-to-temp-nsstring lisp-obj))
+        ((hash-table-p lisp-obj)
+         (lisp-to-ns-dict lisp-obj))
+        ((vectorp lisp-obj)
+         (lisp-to-ns-array lisp-obj))
+        ((null lisp-obj)
+         #@"")
+        (t
+         (lisp-to-temp-nsstring (format nil "~s" lisp-obj)))))
+
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;; Methods dealing with NSArray objects
+
+(defmethod ns-to-lisp-array ((ns-arr ns:ns-array) &key (no-convert nil))
+  (let* ((count (#/count ns-arr))
+         (new-arr (make-array (list count))))
+    (dotimes (i count new-arr)
+        (setf (aref new-arr i) 
+              (if no-convert
+                (#/objectAtIndex: ns-arr i)
+                (ns-to-lisp-object nil (#/objectAtIndex: ns-arr i)))))))
+
+(defmethod ns-to-lisp-list ((ns-arr ns:ns-array) &key (no-convert nil))
+  (let* ((count (#/count ns-arr))
+         (new-list nil))
+    (dotimes (i count (nreverse new-list))
+        (setf new-list 
+              (cons (if no-convert
+                      (#/objectAtIndex: ns-arr i)
+                      (ns-to-lisp-object nil (#/objectAtIndex: ns-arr i)))
+                    new-list)))))
+
+(defmethod lisp-to-ns-array ((lst list))
+  (let ((new-arr (#/arrayWithCapacity: ns:ns-mutable-array (list-length lst)))
+        (count -1))
+    (dolist (item lst new-arr)
+      (#/insertObject:atIndex: new-arr
+                               (lisp-to-ns-object item)
+                               (incf count)))))
+
+(defmethod lisp-to-ns-array ((arr array))
+  (let* ((max-count (if (array-has-fill-pointer-p arr)
+                     (fill-pointer arr)
+                     (length arr)))
+         (new-arr (#/arrayWithCapacity: ns:ns-mutable-array max-count)))
+    (do* ((count 0 (1+ count)))
+         ((>= count max-count) new-arr)
+      (#/insertObject:atIndex: new-arr
+                               (lisp-to-ns-object (aref arr count))
+                               count))))
+
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;; Methods dealing with NSDictionary objects
+
+(defmethod ns-to-lisp-hash-table ((dict ns:ns-dictionary) &key (no-convert nil))
+  (let ((ht (make-hash-table))
+        (dict-keys (ns-to-lisp-list (#/allKeys dict) :no-convert t)))
+    (dolist (key dict-keys ht)
+      (setf (gethash (ns-to-lisp-object nil key) ht)
+            (if no-convert
+              (#/objectForKey: dict key)
+              (ns-to-lisp-object nil (#/objectForKey: dict key)))))))
+
+(defmethod ns-to-lisp-assoc ((dict ns:ns-dictionary) &key (no-convert nil))
+  (let ((assoc-lst nil)
+        (dict-keys (ns-to-lisp-list (#/allKeys dict) :no-convert t)))
+    (dolist (key dict-keys assoc-lst)
+      (setf assoc-lst
+            (acons (ns-to-lisp-object nil key)
+                   (if no-convert
+                     (#/objectForKey: dict key)
+                     (ns-to-lisp-object nil (#/objectForKey: dict key)))
+                   assoc-lst)))))
+
+(defmethod lisp-to-ns-dict ((alist list))
+  ;; alist must be in the form of an association list
+  (let* ((count (list-length alist))
+         (new-dict (#/dictionaryWithCapacity: ns:ns-mutable-dictionary count)))
+    (dolist (pair alist new-dict)
+      (#/setObject:forKey: new-dict 
+                           (lisp-to-ns-object nil (cdr pair))
+                           (lisp-to-ns-object nil (car pair))))))
+
+(defmethod lisp-to-ns-dict ((ht hash-table))
+  (let* ((count (hash-table-count ht))
+         (new-dict (#/dictionaryWithCapacity: ns:ns-mutable-dictionary count)))
+    (maphash #'(lambda (key val)
+                 (#/setObject:forKey: new-dict 
+                                      (lisp-to-ns-object nil val)
+                                      (lisp-to-ns-object nil key)))
+             ht)
+    new-dict))
+
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;; lisp-ptr-wrapper
+;;
+;; This is a simple class that encapsulates a pointer to a lisp object so we can pass this
+;; off to an Objective-C view and know what it points to when we get it back later.
+;; Added is the ability to handle bindings 
+
+(deftype objc-displayable () 
+  '(and atom 
+       (not sequence)
+       (not hash-table)
+       (not package) 
+       (not pathname)
+       (not random-state)
+       (not readtable)
+       (not array)
+       (not stream)
+       (not class)
+       (not structure-object)
+       (not standard-object)
+       (not macptr)))
+
+(defclass lisp-ptr-wrapper (ns:ns-object)
+  ((lpw-lisp-ptr :accessor lpw-lisp-ptr)
+   (lpw-controller :accessor lpw-controller)
+   (lpw-depth :accessor lpw-depth)
+   (lpw-parent :accessor lpw-parent))
+  (:metaclass ns:+ns-object))
+
+(objc:defmethod (#/copyWithZone: :id)
+                ((self lisp-ptr-wrapper) (zone (* #>NSZone)))
+  ;; (ns-log (format nil "Copying wrapper for ~s" (lpw-lisp-ptr self)))
+  self)
+
+(let ((kvc-observed (make-instance 'assoc-array :rank 2))
+      (obj-wrappers (make-instance 'assoc-array :rank 2)))
+  ;; this assoc-array keeps track of paths that are being observed and the
+  ;; corresponding lisp-ptr-wrapper object that is ostensibly being observed.
+
+  (defun make-ptr-wrapper (ptr &key (depth 1) (parent nil) (controller nil))
+    ;; (ns-log (format nil "Making wrapper for ~s" ptr))
+    (let ((lpw (make-instance 'lisp-ptr-wrapper)))
+      (setf (lpw-lisp-ptr lpw) ptr)
+      (setf (lpw-depth lpw) depth)
+      (setf (lpw-parent lpw) parent)
+      (setf (lpw-controller lpw) controller)
+      (setf (assoc-aref obj-wrappers controller ptr) lpw)
+      lpw))
+
+  (defmethod wrapper-for (controller lisp-obj &key (depth 0) (parent nil))
+    (or (assoc-aref obj-wrappers controller lisp-obj)
+        (setf (assoc-aref obj-wrappers controller lisp-obj)
+              (make-ptr-wrapper lisp-obj 
+                                :depth depth
+                                :parent parent
+                                :controller controller))))
+
+  (defmethod note-kvc-observed ((self lisp-ptr-wrapper) lisp-obj path-sym)
+    ;; (ns-log (format nil "Observing ~s for ~s" path-sym lisp-obj))
+    (pushnew self (assoc-aref kvc-observed lisp-obj path-sym)))
+
+  (defmethod will-change-value-for-key (owner key)
+    ;; called from a lisp object to tell us that a value will be changed.
+    ;; We find the lisp-ptr-wrapper instances that have been used to access
+    ;; the owner via the specified key and call the appropriate
+    ;; method to lets KVC know what is going on.
+    ;; (ns-log (format nil "Will change ~s for ~s" key owner))
+    (let ((owner-lpws (assoc-aref kvc-observed owner key))
+          (objc-key (lisp-to-temp-nsstring (lisp-to-objc-keypathname key))))
+      (dolist (lpw owner-lpws)
+        ;; (ns-log (format nil "#/willChangeValueForKey: ~s ~s" lpw objc-key))
+        (#/willChangeValueForKey: lpw objc-key))))
+
+  (defmethod did-change-value-for-key (owner key)
+    ;; called from a lisp object to tell us that a value changed.
+    ;; We find the lisp-ptr-wrapper instances that have been used to access
+    ;; the owner via the specified key and call the appropriate
+    ;; method to lets KVC know what is going on.
+    ;; (ns-log (format nil "Did change ~s for ~s" key owner))
+    (let ((owner-lpws (assoc-aref kvc-observed owner key))
+          (objc-key (lisp-to-temp-nsstring (lisp-to-objc-keypathname key))))
+      (dolist (lpw owner-lpws)
+        ;; (ns-log (format nil "#/didChangeValueForKey: ~s ~s" lpw objc-key))
+        (#/didChangeValueForKey: lpw objc-key))))
+
+  (defun kvc-observed ()
+    kvc-observed)
+)
+;; end of definitions with access to kvc-observed assoc-array
+
+(objc:defmethod (#/valueForKey: :id)
+                ((self lisp-ptr-wrapper) (path :id))
+  (let* ((lisp-path (objc-to-lisp-keypathname (ns-to-lisp-string path)))
+         (next-obj (when (and (typep lisp-path 'function-name) (fboundp lisp-path))
+                     (funcall lisp-path (lpw-lisp-ptr self)))))
+    ;; First track that the path is being observed by somebody
+    (note-kvc-observed self (lpw-lisp-ptr self) lisp-path)
+    ;; (ns-log (format nil "(~s ~s) returned ~s" lisp-path (lpw-lisp-ptr self) next-obj))
+    (cond ((typep next-obj 'objc:objc-object)
+           next-obj)
+          ((null next-obj)
+           (%null-ptr))
+          ((typep next-obj 'objc-displayable)
+           (lisp-to-ns-object next-obj))
+          (t
+           (wrapper-for (lpw-controller self) next-obj :parent (lpw-lisp-ptr self))))))
+
+(objc:defmethod (#/setValue:forKey: :void)
+                ((self lisp-ptr-wrapper) (new-value :id) (path :id))
+  (let* ((lisp-path (objc-to-lisp-keypathname (ns-to-lisp-string path)))
+         (prev-obj (when (and (typep lisp-path 'function-name) (fboundp lisp-path))
+                     (funcall lisp-path (lpw-lisp-ptr self))))
+         (new-lisp-obj (ns-to-lisp-object prev-obj new-value))
+         (setf-form `(setf (,lisp-path ,(lpw-lisp-ptr self)) ,new-lisp-obj)))
+    ;; (ns-log (format nil "Evaling ~s" setf-form))
+    (handler-case (eval setf-form)
+      (condition (c)
+                 (ns-log (format nil "condition: ~s evaling ~s" c setf-form))))))
+
+(provide :ns-object-utils)
Index: /trunk/contrib/krueger/InterfaceProjects/Utilities/ns-string-utils.lisp
===================================================================
--- /trunk/contrib/krueger/InterfaceProjects/Utilities/ns-string-utils.lisp	(revision 13946)
+++ /trunk/contrib/krueger/InterfaceProjects/Utilities/ns-string-utils.lisp	(revision 13946)
@@ -0,0 +1,91 @@
+;; ns-string-utils.lisp
+#|
+The MIT license.
+
+Copyright (c) 2010 Paul L. Krueger
+
+Permission is hereby granted, free of charge, to any person obtaining a copy of this software 
+and associated documentation files (the "Software"), to deal in the Software without restriction, 
+including without limitation the rights to use, copy, modify, merge, publish, distribute, 
+sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is 
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all copies or substantial 
+portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT 
+LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. 
+IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, 
+WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE 
+SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+|#
+
+(defpackage :interface-utilities
+  (:nicknames :iu)
+  (:export ns-to-lisp-string lisp-str-to-ns-data ns-data-to-lisp-str 
+           lisp-object-to-ns-data ns-data-to-lisp-object lisp-to-temp-nsstring
+           nsstring-to-class nsstring-to-func nsstring-to-sym find-func find-substring))
+
+(in-package :iu)
+
+(defun ns-to-lisp-string (ns-str)
+  (if (and (not (eql (%null-ptr) ns-str)) (plusp (#/length ns-str)))
+    (%get-cstring (#/cStringUsingEncoding: ns-str #$NSUTF8StringEncoding))
+    ""))
+
+(defun lisp-str-to-ns-data (lisp-str)
+  (with-cstrs ((str lisp-str))
+    (#/dataWithBytes:length: ns:ns-data str (1+ (length lisp-str)))))
+
+(defun ns-data-to-lisp-str (nsdata)
+  (%get-cstring (#/bytes nsdata)))
+
+(defun lisp-object-to-ns-data (obj)
+  (lisp-str-to-ns-data (format nil "~s" obj)))
+
+(defun ns-data-to-lisp-object (nsdata)
+  (read-from-string (ns-data-to-lisp-str nsdata)))
+
+(defun lisp-to-temp-nsstring (string)
+  ;; creates a string that is not owned by caller
+  ;; so no release is necessary
+  (with-encoded-cstrs :utf-8 ((s string))
+    (#/stringWithUTF8String: ns:ns-string s)))
+
+(defun nsstring-to-class (ns-str)
+  (let ((lisp-obj (read-from-string (ns-to-lisp-string ns-str) nil nil))
+        (classes nil))
+    (if (consp lisp-obj)
+      (dolist (obj lisp-obj (nreverse classes))
+        (push (find-class obj nil) classes))
+      (find-class lisp-obj nil))))
+
+(defun find-func (func-str)
+  (let* ((sym (read-from-string func-str nil nil)))
+    (cond ((and (typep sym 'function-name) (fboundp sym))
+           (symbol-function sym))
+          ((and (consp sym) (eq (first sym) 'function))
+           (let ((fsym (second sym)))
+             (and (typep fsym 'function-name) 
+                  (fboundp fsym)
+                  (symbol-function fsym)))))))
+
+(defun nsstring-to-func (ns-str)
+  (find-func (ns-to-lisp-string ns-str)))
+
+(defun nsstring-to-sym (ns-str)
+  (let ((sym (read-from-string (ns-to-lisp-string ns-str) nil nil)))
+    (if (symbolp sym) sym nil)))
+
+(defun find-substring (substr str &key (test #'string=))
+  (let* ((first-char (elt substr 0))
+         (count (length substr))
+         (search-end (1+ (- (length str) count))))
+    (do* ((begin (position first-char str :end search-end)
+                 (position first-char str :start (1+ begin) :end search-end)))
+         ((null begin) nil)
+      (if (funcall test substr (subseq str begin (+ begin count)))
+        (return-from find-substring t)))))
+
+(provide :ns-string-utils)
Index: /trunk/contrib/krueger/InterfaceProjects/Utilities/nslog-utils.lisp
===================================================================
--- /trunk/contrib/krueger/InterfaceProjects/Utilities/nslog-utils.lisp	(revision 13946)
+++ /trunk/contrib/krueger/InterfaceProjects/Utilities/nslog-utils.lisp	(revision 13946)
@@ -0,0 +1,60 @@
+;; nslog-utils.lisp
+
+(eval-when (:compile-toplevel :load-toplevel :execute)
+  (require :ns-string-utils))
+
+(defpackage :interface-utilities
+  (:nicknames :iu)
+  (:export ns-log ns-error log-rect log-size log-float interleave log-4floats))
+
+(in-package :iu)
+
+(defun ns-log (lisp-str)
+  (#_NSLog (lisp-to-temp-nsstring lisp-str)))
+
+(defmacro ns-error (format-string &rest args)
+  `(progn
+     (ns-log (format nil ,format-string ,@args))
+     (error "See console log for information")))
+
+(defun log-rect (r &optional (log-string ""))
+  (#_NSLog (lisp-to-temp-nsstring (concatenate 'string 
+                                               log-string 
+                                               "x = %F y = %F width = %F height = %F"))
+           #>CGFloat (ns:ns-rect-x r)
+           #>CGFloat (ns:ns-rect-y r)
+           #>CGFloat (ns:ns-rect-width r)
+           #>CGFloat (ns:ns-rect-height r)))
+           
+(defun log-size (s &optional (log-string ""))
+  (#_NSLog (lisp-to-temp-nsstring (concatenate 'string 
+                                               log-string 
+                                               "width = %F height = %F"))
+           #>CGFloat (ns:ns-size-width s)
+           #>CGFloat (ns:ns-size-height s)))
+
+(defun log-float (f &optional (log-string ""))
+  (#_NSLog (lisp-to-temp-nsstring (concatenate 'string 
+                                               log-string 
+                                               "%F"))
+           #>CGFloat f))
+
+(defun interleave (l1 l2)
+  (let ((lst1 (if (listp l1) l1 (list l1)))
+        (lst2 (if (listp l2) l2 (list l2))))
+    (if (atom l1)
+      (setf (cdr lst1) lst1)
+      (if (atom l2)
+        (setf (cdr lst2) lst2)))
+    (mapcan #'(lambda (el1 el2)
+                (list el1 el2))
+            lst1
+            lst2)))
+
+(defun log-4floats (f1 f2 f3 f4 &optional (log-strings '("" "" "" "")))
+  (#_NSLog (lisp-to-temp-nsstring (apply #'concatenate 'string 
+                                         (interleave log-strings "%F ")))
+           #>CGFloat f1
+           #>CGFloat f2
+           #>CGFloat f3
+           #>CGFloat f4))
Index: /trunk/contrib/krueger/InterfaceProjects/Utilities/selector-utils.lisp
===================================================================
--- /trunk/contrib/krueger/InterfaceProjects/Utilities/selector-utils.lisp	(revision 13946)
+++ /trunk/contrib/krueger/InterfaceProjects/Utilities/selector-utils.lisp	(revision 13946)
@@ -0,0 +1,23 @@
+;; selector-utils.lisp
+
+(defpackage :interface-utilities
+  (:nicknames :iu)
+  (:export get-selector find-selector-match))
+
+(in-package :iu)
+
+(defun get-selector (name)
+  ;; we can't use the @selector macro for some uses because it requires a literal name
+  ;; argument and sometimes we want to take a name passed in as a parameter and cause it
+  ;; to be registered as an objective C selector name. We could do this directly with
+  ;; a call to the C function #_sel_get_uid and let lisp figure it out for itself later
+  ;; but we'll play nice with the objective C bridge instead which hashes these things.
+  (ccl::%get-selector (ccl::ensure-objc-selector name)))
+
+(defun find-selector-match (sel)
+  (maphash #'(lambda (key val)
+               (when (eql (ccl::objc-selector-%sel val) sel) 
+                 (return-from find-selector-match key)))
+           ccl::*objc-selectors*))
+
+(provide :selector-utils)
Index: /trunk/contrib/montuori/trivial-ldap/LICENSE.txt
===================================================================
--- /trunk/contrib/montuori/trivial-ldap/LICENSE.txt	(revision 13946)
+++ /trunk/contrib/montuori/trivial-ldap/LICENSE.txt	(revision 13946)
@@ -0,0 +1,136 @@
+                     The Clarified Artistic License
+
+                                Preamble
+
+The intent of this document is to state the conditions under which a
+Package may be copied, such that the Copyright Holder maintains some
+semblance of artistic control over the development of the package,
+while giving the users of the package the right to use and distribute
+the Package in a more-or-less customary fashion, plus the right to make
+reasonable modifications.
+
+Definitions:
+
+        "Package" refers to the collection of files distributed by the
+        Copyright Holder, and derivatives of that collection of files
+        created through textual modification.
+
+        "Standard Version" refers to such a Package if it has not been
+        modified, or has been modified in accordance with the wishes
+        of the Copyright Holder as specified below.
+
+        "Copyright Holder" is whoever is named in the copyright or
+        copyrights for the package.
+
+        "You" is you, if you're thinking about copying or distributing
+        this Package.
+
+        "Distribution fee" is a fee you charge for providing a copy
+        of this Package to another party.
+
+        "Freely Available" means that no fee is charged for the right to
+        use the item, though there may be fees involved in handling the
+        item.  It also means that recipients of the item may redistribute
+        it under the same conditions they received it.
+
+1. You may make and give away verbatim copies of the source form of the
+Standard Version of this Package without restriction, provided that you
+duplicate all of the original copyright notices and associated disclaimers.
+
+2. You may apply bug fixes, portability fixes and other modifications
+derived from the Public Domain, or those made Freely Available, or from
+the Copyright Holder.  A Package modified in such a way shall still be
+considered the Standard Version.
+
+3. You may otherwise modify your copy of this Package in any way, provided
+that you insert a prominent notice in each changed file stating how and
+when you changed that file, and provided that you do at least ONE of the
+following:
+
+    a) place your modifications in the Public Domain or otherwise make them
+    Freely Available, such as by posting said modifications to Usenet or an
+    equivalent medium, or placing the modifications on a major network
+    archive site allowing unrestricted access to them, or by allowing the
+    Copyright Holder to include your modifications in the Standard Version
+    of the Package.
+
+    b) use the modified Package only within your corporation or organization.
+
+    c) rename any non-standard executables so the names do not conflict
+    with standard executables, which must also be provided, and provide
+    a separate manual page for each non-standard executable that clearly
+    documents how it differs from the Standard Version.
+
+    d) make other distribution arrangements with the Copyright Holder.
+
+    e) permit and encourge anyone who receives a copy of the modified Package
+       permission to make your modifications Freely Available
+       in some specific way.
+
+
+4. You may distribute the programs of this Package in object code or
+executable form, provided that you do at least ONE of the following:
+
+    a) distribute a Standard Version of the executables and library files,
+    together with instructions (in the manual page or equivalent) on where
+    to get the Standard Version.
+
+    b) accompany the distribution with the machine-readable source of
+    the Package with your modifications.
+
+    c) give non-standard executables non-standard names, and clearly
+    document the differences in manual pages (or equivalent), together
+    with instructions on where to get the Standard Version.
+
+    d) make other distribution arrangements with the Copyright Holder.
+
+    e) offer the machine-readable source of the Package, with your
+       modifications, by mail order.
+
+5. You may charge a distribution fee for any distribution of this Package.
+If you offer support for this Package, you may charge any fee you choose
+for that support.  You may not charge a license fee for the right to use
+this Package itself.  You may distribute this Package in aggregate with
+other (possibly commercial and possibly nonfree) programs as part of a
+larger (possibly commercial and possibly nonfree) software distribution,
+and charge license fees for other parts of that software distribution,
+provided that you do not advertise this Package as a product of your own.
+If the Package includes an interpreter, You may embed this Package's
+interpreter within an executable of yours (by linking); this shall be
+construed as a mere form of aggregation, provided that the complete
+Standard Version of the interpreter is so embedded.
+
+6. The scripts and library files supplied as input to or produced as
+output from the programs of this Package do not automatically fall
+under the copyright of this Package, but belong to whoever generated
+them, and may be sold commercially, and may be aggregated with this
+Package.  If such scripts or library files are aggregated with this
+Package via the so-called "undump" or "unexec" methods of producing a
+binary executable image, then distribution of such an image shall
+neither be construed as a distribution of this Package nor shall it
+fall under the restrictions of Paragraphs 3 and 4, provided that you do
+not represent such an executable image as a Standard Version of this
+Package.
+
+7. C subroutines (or comparably compiled subroutines in other
+languages) supplied by you and linked into this Package in order to
+emulate subroutines and variables of the language defined by this
+Package shall not be considered part of this Package, but are the
+equivalent of input as in Paragraph 6, provided these subroutines do
+not change the language in any way that would cause it to fail the
+regression tests for the language.
+
+8. Aggregation of the Standard Version of the Package with a commercial
+distribution is always permitted provided that the use of this Package
+is embedded; that is, when no overt attempt is made to make this Package's
+interfaces visible to the end user of the commercial distribution.
+Such use shall not be construed as a distribution of this Package.
+
+9. The name of the Copyright Holder may not be used to endorse or promote
+products derived from this software without specific prior written permission.
+
+10. THIS PACKAGE IS PROVIDED "AS IS" AND WITHOUT ANY EXPRESS OR
+IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
+WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+
+                                The End
Index: /trunk/contrib/montuori/trivial-ldap/example.lisp
===================================================================
--- /trunk/contrib/montuori/trivial-ldap/example.lisp	(revision 13946)
+++ /trunk/contrib/montuori/trivial-ldap/example.lisp	(revision 13946)
@@ -0,0 +1,131 @@
+(require 'trivial-ldap)
+
+; see http://www.openldap.org/doc/admin23/quickstart.html for some
+; openldap quickstart documentation.  
+
+;; create a new ldap object.  the port number is the default 389 here.
+(defparameter l
+  (ldap:new-ldap :host "redbaron.local" 
+		 :user "cn=directory manager, dc=example, dc=com"
+		 :sslflag t
+		 :debug t
+		 :pass "secret"
+		 :base "dc=example,dc=com"
+		 :reuse-connection 'ldap:rebind))
+
+
+;; create some entry objects.  
+(defparameter entry-one
+  (ldap:new-entry "dc=example,dc=com" 
+		  :attrs '((objectclass . (dcobject organization))
+			   (o . "example organization"))))
+
+(defparameter entry-two
+  (ldap:new-entry "cn=manager,dc=example,dc=com" 
+		  :attrs '((objectclass . organizationalrole))))
+
+(defparameter entry-three
+  (ldap:new-entry "cn=test user,dc=example,dc=com" 
+		  :attrs '((objectclass . organizationalrole))))
+
+(defparameter entry-four
+  (ldap:new-entry "cn=quuxor,dc=example,dc=com" 
+		  :attrs '((objectclass . (organizationalrole))
+			   (description . "another test entry")
+			   (l . ("Boston" "Cambridge" "Jamaica Plain"))
+			   (st . "Massachusetts")
+			   (postalcode . "02115")
+			   (street . "Commonwealth Avenue"))))
+
+
+; a printed representation:
+(format t "~A" (ldap:ldif entry-four))
+
+; turn on debugging.
+(setf (ldap:debugflag l) t)
+
+; bind to the server.
+(when (ldap:bind l)
+  (write-line "bound to ldap."))
+
+; turn off debugging.
+(setf (ldap:debugflag l) nil)
+
+; add a couple entries.
+(ldap:add entry-one l)
+
+; or use the lower-level add specified on ldap first:
+(multiple-value-bind (res code msg) (ldap:add l entry-two)
+  (format t "res: ~A~%code: ~A~%msg: ~A" res code msg))
+
+; search (and print results in ldif) 
+(ldap:ldif-search l "(cn=*)")
+
+; add another entry.
+(ldap:add entry-three l)
+
+; search for that.
+(if (ldap:search l (ldap:rdn entry-three))
+    (describe (ldap:next-search-result l))
+    (format t "Search Failed."))
+
+; delete an entry.  
+(ldap:delete entry-three l)
+
+; ldap:search will return nil.
+(ldap:search l (ldap:rdn entry-three))
+
+; a fourth entry.
+(ldap:add entry-four l)
+
+; this should be true.
+(ldap:compare entry-four l 'st "Massachusetts")
+
+; as should this, because the st attribute 
+; compares case insensitively.
+(ldap:compare entry-four l 'st 'massachusetts)
+
+; this is false, so it returns nil.
+(ldap:compare entry-four l 'st 'foobarbaz)
+
+; compare (and delete) take strings as well as entry objects.
+(ldap:compare (ldap:dn entry-four) l 'l 'boston)
+(ldap:delete (ldap:dn entry-four) l)
+
+; put entry four back:
+(ldap:add entry-four l)
+
+(ldap:attr-value entry-four 'st)
+(ldap:attr-list entry-four)
+(ldap:attrs entry-four)
+
+(ldap:modify entry-four l '((ldap:delete l "Boston")
+			    (ldap:replace st "Vermont")
+			    (ldap:add st "New Hampshire")
+			    (ldap:add street ("Massachusetts Avenue"
+					      "Newbury Street"
+					      "Boylston Street"))))
+
+(format t "~A~%" (ldap:ldif entry-four))
+
+
+(ldap:moddn entry-four l "cn=buzzer")
+
+; simple ldap filters work more or less as expected.  extended filters
+; however have not been implemented yet.
+(ldap:search l "(cn=buzz*)")
+(ldap:search l "(| (cn=baz*) (cn=*ager))")
+
+; the outside parens are optional:
+(ldap:search l "| (cn=baz*) (cn=*ager)")
+
+; clean up.  with one ldap object fetching the results of the search,
+; a second LDAP object is required for the delete.
+
+(defparameter j (ldap:new-ldap :host "great-pumpkin.local"
+			       :base "dc=example,dc=com"))
+
+; (ldap:dosearch (ent (ldap:search j "cn=*"))
+;   (ldap:delete ent l))
+;  
+; (ldap:delete entry-one l)
Index: /trunk/contrib/montuori/trivial-ldap/trivial-ldap.asd
===================================================================
--- /trunk/contrib/montuori/trivial-ldap/trivial-ldap.asd	(revision 13946)
+++ /trunk/contrib/montuori/trivial-ldap/trivial-ldap.asd	(revision 13946)
@@ -0,0 +1,8 @@
+(defpackage :trivial-ldap-system (:use #:cl #:asdf))
+(in-package :trivial-ldap-system)
+
+
+(defsystem :trivial-ldap
+  :version "0.91"
+  :components ((:file "trivial-ldap"))
+  :depends-on (usocket cl+ssl))
Index: /trunk/contrib/montuori/trivial-ldap/trivial-ldap.html
===================================================================
--- /trunk/contrib/montuori/trivial-ldap/trivial-ldap.html	(revision 13946)
+++ /trunk/contrib/montuori/trivial-ldap/trivial-ldap.html	(revision 13946)
@@ -0,0 +1,554 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
+<!-- 
+(defun add-api-entry ()
+  (interactive)
+  (let ((function (read-string "Function/Method name: "))
+	(args (read-string "Argument list: "))
+	(type (read-string "Function, Method, or Macro? ")))
+    (insert (format "
+    <dt>
+      <span class=\"term\"><b>%s</b> <i>%s</i></span>
+      <span class=\"type\">[%s]</span>
+    </dt>
+    <br class=\"both\" />
+    <dd>
+    </dd>" function args type))
+    (previous-line 1)))
+-->
+
+
+<html>
+  <head>
+    <title>TRIVIAL-LDAP v0.91</title>
+
+    <style type="text/css">
+      .leftcontent {float: left; width: 75%; padding-left: 12px;}
+      div.head {background-color: #aeffee;}
+      span.term {float: left; text-align: left;}
+      span.type {float: right; text-align: right; font-weight: bold;}
+      br.both {clear: both;}
+      dd {font-style: normal; padding-bottom: 8px;}
+      
+    </style>
+  </head>
+
+  <body class="leftcontent">
+    <h3>TRIVIAL-LDAP v0.91</h3>
+
+    TRIVIAL-LDAP is a one file, all Common Lisp client implementation of
+    parts of RFC 2261.
+
+    <h4>WARNING:</h4> This is beta software.  While I believe the API
+    documented below is correct it is subject to change.  Also, <b>do
+    not run execute the example.lisp program against a production LDAP
+    directory, it will delete your entries.</b>  
+
+    <h4>Introduction</h4> This LDAP client came about as a result of
+    some functionality I required for a different project altogether.
+    As a result it provides functionality that is general enough but
+    probably not in typical low-level API fashion.  (For instance, a
+    "real" LDAP library would probably tackle the BER encoding
+    separately.)  However, as there is a lack of Common Lisp LDAP
+    clients out there I thought I'd share.  <p/>
+
+    I am open to both requests for features and suggestions for
+    improving my Lisp code.  There are features I will be implementing
+    in the short term but for the sake of not creating false
+    expectations neither a comprehensive list nor timeframe is
+    available. <p />
+
+    You can reach me at montuori@gmail.com.  
+
+  <h4>Changes</h4>
+    <dl>
+      <dt>2009-08-16 (v0.91)</dt>
+      <dd>Applied a patch supplied by Nick Dannenberg to fix UTF-8
+      handling for SBCL and CCL.  My sincerest appreciation for taking
+      the time to generate and send the patch along!</dd>
+
+      <dt>2009-03-12 (v0.90)</dt>
+      <dd>Applied patches kindly provided by Slawek Zak.
+	<ul>
+	  <li>Enable UTF-8 encoding for Allegro.</li>
+	  <li>Fixed a compilation failure on Allegro where a number
+	    of constants were not properly defined.</li>
+	  <li>Fixed the dosearch macro for cases where the LDAP 
+	    variable is lexical.</li>
+	</ul>
+	Thanks to Slawek for taking the time to send the patches!
+      </dd>
+
+
+      <dt>2007-01-12 (v0.80)</dt>
+      <dd><ul>
+	  
+	  <li>Converted from trivial-socket to usocket: indications
+	    were that trivial-socket has been deprecated.</li>
+
+	  <li>Added support for SSL with CL+SSL.  Setting the ldap
+	  object slot <code>sslflag</code> to T or
+	  the <code>port</code> slot to 636 will force an encrypted
+	  connection.  Do note that this is not TLS, just ldaps://
+	  ... I don't require TLS; if you do, drop me a line.</li>
+
+	  <li>Added functionality to ease the pain of short slapd
+	  idletimeouts.  The ldap object
+	  slot <code>reuse-connection</code> may be set to NIL (the
+	  default) to not attempt reopening connections, T to reopen
+	  the connection before each request, or TRIVIAL-LDAP:REBIND
+	  if the connection should be opened and a bind message sent
+	  before each request (except, of course, the bind request
+	    itself).  </li>
+
+	  <li>A couple of documentation and logic bugs were corrected</li>
+	</ul></dd>
+
+    </dl>
+<p>
+    
+  <h4>Acknowledgments</h4> I would like to thank Zach Beane for his
+  many helpful comments and suggestions.  Thanks also to Ed Symanzik
+  for pointing out a number inconsistencies in the code and
+  documentation.  
+<p>
+  Also, a nod to my client, Brandeis University, for not fretting too
+  much when I break out emacs + slime to administrate their LDAP
+  directories.
+<p>
+    <h4>License</h4> TRIVIAL-LDAP is distributed under the Clarified
+    Artistic License, a copy of which is included in the downloadable
+    package.  
+
+    <h4>Requirements</h4> TRIVIAL-LDAP has been tested under OpenMCL 1.0
+    (OS X/PPC), SBCL 0.9.7 (OS X/PPC), and SBCL 1.0 (OS X/Intel).
+<p>
+    I would assume any CL that is supported by usockets and CL+SSL
+    would have no issues with this code.  If you encounter problems
+    let me know.
+
+    <p/>Two external packages, usocket and CL+SSL, are required.
+    CL+SSL itself requires trivial-gray-streams, flexi-streams, and
+    cffi.  These may be downloaded from:
+
+   <ul>
+     <li><a href="http://common-lisp.net/project/usocket/">
+	 http://common-lisp.net/project/usocket/</a></li>
+
+     <li><a href="http://common-lisp.net/project/cl-plus-ssl/">
+	 http://common-lisp.net/project/cl-plus-ssl/</a></li>
+
+     <li><a href="http://common-lisp.net/project/cffi/">
+	 http://common-lisp.net/project/cffi/</a></li>
+
+     <li><a href="http://weitz.de/flexi-streams/">
+	 http://weitz.de/flexi-streams/</a></li>
+   </ul>
+
+   The trivial-gray-streams project is part of the CL+SSL project.
+   (Note: to get CL+SSL working on OS X/Intel it was necessary to
+   re-compile openssl with the -m64 flag.)
+
+<p>
+
+    <h4>Limitations</h4>
+    
+    Missing functionality, as specified by RFC 2251,  includes:
+    
+    <ul>
+      <li>UTF-8 is not implemented for all CL implementations</li>
+      <li>SASL authentication is not implemented</li>
+      <li>controls are not implemented</li>
+      <li>extended DN searches are not implemented</li>
+      <li>referrals are not followed</li>
+      <li>extended request/response is not implemented</li>
+    </ul>
+    
+    I do not require this functionality myself, but if there was
+    interest I would consider augmenting TRIVIAL-LDAP with some of
+    this missing functionality.
+
+    <p/>
+      
+    <h4>API</h4>
+    <dl>
+<p><b>LDAP object and associated methods.</b></p>
+
+      <dt>
+	<span class="term"><b>new-ldap</b> <i>&key (host "localhost")
+	(port 389) user pass base debug</i></span> <span
+	class="type">[function]</span>
+      </dt>
+    <br class="both" />
+    <dd>Return an LDAP object.</dd>
+    
+    <dt>
+      <span class="term"><b>host</b> <i>ldap-object</i></span>
+      <span class="type">[method]</span>
+    </dt>
+    <br class="both" /> <dd>Get/set the host slot value of
+    ldap-object.  Slot value will be a string.</dd>
+
+    <dt>
+      <span class="term"><b>port</b> <i>ldap-object</i></span> <span
+      class="type">[method]</span>
+    </dt>
+    <br class="both" /> <dd>Get/set the port slot value of
+    ldap-object.  Slot value will be an integer.  If the sslflag slot
+    is NIL, defaults to 389; if sslflag slot is T, defaults to 636.
+    If the port parameter is manually set to 636 an SSL connection is
+    used unless the sslflag is explicitly set to nil.
+    </dd>
+
+
+    <dt>
+      <span class="term"><b>user</b> <i>ldap-object</i></span> <span
+      class="type">[method]</span>
+    </dt>
+    <br class="both" /> <dd>Get/set the user DN to bind as.  Slot
+    value will be a string.
+    </dd>
+  
+
+    <dt>
+      <span class="term"><b>pass</b> <i>ldap-object</i></span> <span
+      class="type">[method]</span>
+    </dt>
+    <br class="both" /> <dd>Get/set the simple password to bind with.
+    Slot value will be a string.
+    </dd>
+
+
+    <dt>
+      <span class="term"><b>base</b> <i>ldap-object</i></span> <span
+      class="type">[method]</span>
+    </dt>
+    <br class="both" /> <dd>Get/set the default base DN for searches.
+    Slot value will be a string.
+    </dd>
+
+
+    <dt>
+      <span class="term"><b>debug</b> <i>ldap-object</i></span>
+      <span class="type">[method]</span>
+    </dt>
+    <br class="both" /> 
+
+    <dd>Get/set the debug flag.  Slot value will be T or NIL.  When
+    value is T debug output will be written to *debug-io*.
+    </dd>
+
+
+    <dt>
+      <span class="term"><b>sslflag</b> <i>ldap-object</i></span>
+      <span class="type">[method]</span>
+    </dt>
+    <br class="both" />
+    <dd>Get/set the SSL flag.  When T the default port is 636 and a
+    CL+SSL stream is used.  Defaults to nil.  Note that if the port
+    slot is explicitly set to 636 an SSL connection is used unless the
+    sslflag slot is set to nil explicitly.
+    </dd>
+
+
+    <dt>
+      <span class="term"><b>reuse-connection</b> <i>ldap-object</i></span>
+      <span class="type">[method]</span>
+    </dt>
+    <br class="both" />
+    <dd>Get/set the reuse-connection slot parameter.  When T re-open
+    the stream before each reqest; when LDAP:REBIND open the stream
+    and send an (ldap:bind ldap-object) message; when nil, don't do
+    anything special.  Set to NIL by default.
+    </dd>
+
+<p><b>Entry object and associated methods</b></p>
+
+    <dt>
+      <span class="term"><b>new-entry</b> <i>dn &key (attrs ())
+      (infer-rdn t)</i></span> <span class="type">[function]</span>
+    </dt>
+    <br class="both" /> 
+
+    <dd>Return a new entry object with the DN specified.
+    <code>attrs</code>, if specified, will be an alist of
+    attribute/value pairs.  If <code>infer-rdn</code> is T the RDN
+    attribute and value will be appended to the attribute list.
+    </dd>
+
+    
+    <dt>
+      <span class="term"><b>dn</b> <i>entry-object</i></span>
+      <span class="type">[method]</span>
+    </dt>
+    <br class="both" />
+    <dd>Return the DN value for entry-object.  
+    </dd>
+
+
+    <dt>
+      <span class="term"><b>rdn</b> <i>entry-object</i></span>
+      <span class="type">[method]</span>
+    </dt>
+    <br class="both" />
+    <dd>Return the RDN value for entry-object
+    </dd>    
+
+    <dt>
+      <span class="term"><b>change-rdn</b> <i>entry-object
+      new-rdn</i></span> <span class="type">[method]</span>
+    </dt>
+    <br class="both" /> <dd>Change the RDN (and therefore DN) of an
+    entry-object.  The RDN attribute and value will be updated in the
+    attribute list.  No LDAP directory transactions will take place.
+    </dd>
+
+
+    <dt>
+      <span class="term"><b>attr-list</b> <i>entry-object</i></span>
+      <span class="type">[method]</span>
+    </dt>
+    <br class="both" /> <dd>Return the list of attribute symbols
+    belonging to entry-object
+    </dd>
+
+
+    <dt>
+      <span class="term"><b>attr-value</b> <i>entry-object
+      attr</i></span> <span class="type">[method]</span>
+     <br class="both" />
+     <span class="term"><b>attr-value</b> <i>entry-object
+      attr-list</i></span> <span class="type">[method]</span>
+   
+    </dt>
+    <br class="both" /> <dd>Return a list of values associated with
+    the attribute <code>attr</code>.  Return NIL if the attribute does
+    not exist.  If a list of attributes is passed, return a list of
+    lists of values.
+    </dd>
+
+
+    <dt>
+      <span class="term"><b>add-attr</b> <i>entry-object attr
+      values</i></span> <span class="type">[method]</span>
+    </dt>
+    <br class="both" /> <dd>Add the specified attribute with the value
+    or values specified to the entry object's attribute list.  Returns
+    the entire list of attributes/values.  No LDAP directory transactions
+    will take place.
+    </dd>
+
+    
+    <dt>
+      <span class="term"><b>del-attr</b> <i>entry-object attr
+      &optional values</i></span> <span class="type">[method]</span>
+    </dt>
+    <br class="both" /> <dd>Delete the specified attribute (or values
+    for attribute) from the entry object's attribute list.  Returns
+    the entire list of attributes/values.  No LDAP directory
+    transactions will take place.
+    </dd>
+
+
+    <dt>
+      <span class="term"><b>replace-attr</b> <i>entry-object attribute
+      values</i></span> <span class="type">[method]</span>
+    </dt>
+    <br class="both" /> <dd>Replace current attribute values with
+    values specified.  Returns the entire list of attributes/values.
+    No LDAP directory transactions will take place.
+    </dd>
+
+
+
+    <dt>
+      <span class="term"><b>ldif</b> <i>entry-object</i></span>
+      <span class="type">[method]</span>
+    </dt>
+    <br class="both" />
+    <dd>Return an LDIF representation of entry (as a string).
+    </dd>
+
+
+
+<p><b>LDAP Commands</b></p>
+<p>
+<b>NB:</b> Methods below that are specialized first on ldap-object will
+return three values: T/NIL indicating success or failure, the LDAP
+response code (these are exported from the TRIVIAL-LDAP package as
+symbols), and third, any response message received from the LDAP
+directory server (as a string).
+</p>
+<p>
+Methods specialized first on entry-object will return T (or T/NIL
+in the case of compare) and will throw an ldap-response-error if a
+response from the LDAP directory server is other than succesful.
+</p>
+<p>
+<i>dn-or-entry</i> can be either an entry-object or a DN string.
+<i>dn</i> is a string.  Generally if the method only requires the DN
+either the entry or the DN will be acceptable arguments.
+</p>
+
+
+
+    <dt>
+      <span class="term"><b>bind</b> <i>ldap-object</i></span>
+      <span class="type">[method]</span>
+    </dt>
+    <br class="both" />
+    <dd>Send a bind request to the LDAP directory server.
+    </dd>
+
+
+    <dt>
+      <span class="term"><b>unbind</b> <i>ldap-object</i></span>
+      <span class="type">[method]</span>
+    </dt>
+    <br class="both" /> <dd>Send an unbind request to the LDAP
+    directory server and close the stream.
+    </dd>
+
+<dt>
+      <span class="term"><b>abandon</b> <i>ldap-object</i></span>
+      <span class="type">[method]</span>
+    </dt>
+    <br class="both" /> <dd>Send an abandon request to the LDAP
+    directory server and purge any data on the stream waiting to be
+    read.  </dd>
+
+
+    <dt>
+      <span class="term"><b>add</b> <i>ldap-object entry-object</i></span>
+      <span class="type">[method]</span>
+    <br class="both" /> 
+      <span class="term"><b>add</b> <i>entry-object ldap-object</i></span>
+    </dt>
+    <br class="both" /> <dd>Add an entry described by entry-object to
+    the directory specified by ldap-object.
+    </dd>
+
+
+
+    <dt>
+      <span class="term"><b>delete</b> <i>ldap-object
+      dn-or-entry</i></span> <span class="type">[method]</span>
+     <br class="both" />
+      <span class="term"><b>delete</b> <i>entry-object
+      ldap-object</i></span> 
+     <br class="both" />
+      <span class="term"><b>delete</b> <i>dn ldap-object</i></span>
+
+    </dt>
+    <br class="both" /> <dd>Delete entry from directory specified by
+    ldap-object.  <code>dn-or-entry</code> may be an entry object or a
+    DN string.  
+    </dd>
+
+    <dt>
+      <span class="term"><b>moddn</b> <i>ldap-object dn-or-entry
+      new-rdn &key delete-old new-sup</i></span> <span
+      class="type">[method]</span>
+    <br class="both" />
+      <span class="term"><b>moddn</b> <i>entry-object ldap-object
+      new-rdn &key delete-old new-sup</i></span> 
+    <br class="both" />
+      <span class="term"><b>moddn</b> <i>dn ldap-object new-rdn &key
+      delete-old new-sup</i></span> 
+    </dt>
+    <br class="both" /> <dd>Modify the RDN specified by
+    <code>dn-or-entry</code> to the replacement RDN
+    <code>new-rdn</code>.  <code>dn-or-entry</code> may be either an
+    entry object or DN string.  If an object is specified, the DN and
+    attribute associated with the RDN slot values are modified as well
+    as the directory specified by ldap-object.
+    </dd>
+ 
+    <dt>
+      <span class="term"><b>compare</b> <i>ldap-object dn-or-entry
+      attribute value</i></span> <span class="type">[method]</span>
+      <br class="both" /> <span class="term"><b>compare</b>
+      <i>entry-object ldap-object attribute value</i>
+    </dt>
+    <br class="both" /> <dd>Send a compare message to the directory
+    server asserting that entry-obj (or DN) has an attribute
+    <code>attribute</code> with a value <code>value</code>.  Returns
+    either T or NIL (as the only argument or as the first argument)
+    indicating a return code of compareTrue or compareFalse.  
+    </dd>
+
+
+
+    <dt>
+      <span class="term"><b>modify</b> <i>ldap-object dn-or-entry
+      list-of-mods</i></span> <span class="type">[method]</span>
+    <br class="both" />
+      <span class="term"><b>modify</b> <i>entry-object ldap-object
+      list-of-mods</i></span> 
+    </dt>
+    <br class="both" /> <dd>Modify the entry specified by
+    <code>dn-or-entry</code> or <code>entry-object</code>.
+    <code>list-of-mods</code> is a list of (type attribute value)
+    triples.  Type will be one of ldap:add, ldap:delete, or
+    ldap:replace.
+    </dd>
+
+
+    <dt>
+      <span class="term"><b>search</b> <i>ldap-object filter &key base
+      (scope 'sub) (deref 'never) (size-limit 0) (time-limit 0)
+      types-only attributes</i></span> <span
+      class="type">[method]</span>
+    </dt>
+    <br class="both" /> <dd>Search the directory specified by
+    ldap-object.  <code>filter</code> is an LDAP filter (as a string).
+    The outer parens on the filter are optional.  The search base
+    defaults to the base slot-value of the ldap-object.  This method
+    returns T or NIL, indicating results pending or not, respectively.
+    </dd>
+
+
+    <dt>
+      <span class="term"><b>next-search-result</b> <i>ldap-object</i></span>
+      <span class="type">[method]</span>
+    </dt>
+    <br class="both" /> <dd>After an ldap:search is executed, this
+    method can be used to return each of the entry objects that search
+    resulted in.  next-search-result will return NIL if no more
+    results are available.
+    </dd>
+
+
+    <dt>
+      <span class="term"><b>dosearch</b> <i>var search-form &body
+      body</i></span> <span class="type">[macro]</span>
+    </dt>
+    <br class="both" /> <dd>Execute the ldap:search provided as
+    <code>search-form</code> and iterate through the results binding
+    each resulting entry object to <code>var</code> before evaluating
+    <code>body.</code> Returns the number of entries processed.
+    <b>NB: </b>If the body of the loop involves LDAP transactions it
+    is probably best that a difference LDAP instance be employed.
+
+    </dd>
+
+    <dt>
+      <span class="term"><b>ldif-search</b> <i>&rest
+      ldap-search-args</i></span> <span class="type">[macro]</span>
+    </dt>
+    <br class="both" /> <dd>Prints the results of a search in LDIF.
+    This macro is probably most useful in an interactive setting.
+    <code>ldap-search-args</code> are passed directly to the search
+    method described above.
+    </dd>
+
+</dl>
+
+
+    <hr>
+    <address><a href="mailto:montuori@gmail.com">kevin montuori</a></address>
+<!-- Created: Sun Jan 22 14:36:42 EST 2006 -->
+<!-- hhmts start -->
+Last modified: Sat Jan 13 09:01:44 EST 2007
+<!-- hhmts end -->
+  </body>
+</html>
Index: /trunk/contrib/montuori/trivial-ldap/trivial-ldap.lisp
===================================================================
--- /trunk/contrib/montuori/trivial-ldap/trivial-ldap.lisp	(revision 13946)
+++ /trunk/contrib/montuori/trivial-ldap/trivial-ldap.lisp	(revision 13946)
@@ -0,0 +1,1281 @@
+;;;; TRIVIAL-LDAP v0.91 -- a one file, all lisp client implementation of
+;;;; parts of RFC 2261.  
+
+;;;; Please see the trivial-ldap.html file for documentation and limitations.
+
+;;;; Updates are available at:
+;;;;    http://homepage.mac.com/ignavusinfo/trivial-ldap/
+
+;;;; TRIVIAL-LDAP is Copyright 2005-2009 Kevin Montuori and is 
+;;;; distributed under The Clarified Artistic License, a copy of which
+;;;; should have accompanied this file.
+
+;;;; Kevin Montuori <montuori@gmail.com>
+
+(defpackage :trivial-ldap
+    (:use :cl-user :common-lisp :usocket)
+  (:nicknames :ldap)
+  (:shadow :delete :search)
+  (:export
+   ; mod types.
+   delete replace add 
+   ; search option symbols
+   base sub one never search find always
+   ; objects.
+   entry ldap
+   ; methods.
+   #:user #:pass #:base #:debugflag #:host #:port #:rdn #:dn #:attrs #:compare
+   #:sslflag #:reuse-connection #:rebind
+   #:bind #:unbind #:abandon #:add #:delete #:moddn #:search 
+   #:new-entry-from-list #:replace-attr #:del-attr #:add-attr #:modify
+   #:attr-list #:attr-value #:new-entry #:new-ldap #:ldif #:change-rdn
+   #:response #:results-pending-p #:next-search-result
+   ; convenience macros
+   #:dosearch #:ldif-search))
+	   
+(in-package :trivial-ldap)
+
+;;;;
+;;;; error conditions
+;;;;
+
+(define-condition ldap-error ()
+  ((note :initarg :mesg
+	 :reader mesg
+	 :initform "LDAP transaction resulted in an error."))
+  (:report (lambda (c stream)
+	     (format stream "~A~%" (mesg c)))))
+
+(define-condition ldap-filter-error (ldap-error)
+  ((filter :initarg :filter
+	   :reader filter
+	   :initform "Not Supplied"))
+  (:report (lambda (c stream)
+	     (format stream "Filter Error: ~A~%Supplied Filter: ~A~%" 
+		     (mesg c) (filter c)))))
+
+(define-condition ldap-connection-error (ldap-error)
+  ((host :initarg :host
+	 :reader  host)
+   (port :initarg :port
+	 :reader port))
+  (:report (lambda (c stream)
+	     (format stream "LDAP Connection Error: ~A~%Host:Port: ~A:~A~%"
+		     (mesg c) (host c) (port c)))))
+
+(define-condition ldap-response-error (ldap-error)
+    ((dn   :initarg :dn
+	   :reader dn
+	   :initform "DN not available.")
+     (code :initarg :code
+	   :reader code
+	   :initform "Result code not available")
+     (msg  :initarg :msg
+	   :reader msg
+	   :initform "N/A"))
+    (:report (lambda (c stream)
+	       (format stream "~A~%DN: ~A~%Code: ~A~%Message: ~A~%"
+		       (mesg c) (dn c) (code c) (msg c)))))
+
+;;;;
+;;;; utility functions
+;;;;
+
+
+;; to appease sbcl (see http://tinyurl.com/auqmr):
+(defmacro define-constant (name value &optional doc)
+  `(defconstant ,name (if (boundp ',name) (symbol-value ',name) ,value)
+    ,@(when doc (list doc))))
+
+(defparameter *hex-print* "~A~%~{~<~%~1,76:;~2,'0,,X~> ~}~%"
+  "Format directive to print a list of line wrapped hex numbers.")
+
+(defun base10->base256 (int)
+  "Return representation of an integer as a list of base 256 'digits'."
+  (assert (and (integerp int) (>= int 0)))
+  (or 
+   (do ((i 0 (+ i 8))
+	(j int (ash j -8))
+	(result nil (cons (logand #xFF j) result)))
+       ((> i (1- (integer-length int))) result))
+   (list 0)))
+
+(defun base256->base10 (list)
+  "Given a list of base 256 'digits' return an integer."
+  (assert (consp list))
+  (let ((len (length list)))
+    (do ((i 0 (1+ i))
+	 (j (- len 1) (1- j))
+	 (int 0 (dpb (pop list) (byte 8 (* 8 j)) int)))
+	((= i len) int))))
+
+(defun int->octet-list (int)
+  "Return 2s comp. representation of INT."
+   (assert (integerp int))
+   (do ((i 0 (+ i 8))
+	(j int (ash j -8))
+	(result nil (cons (logand #xFF j) result)))
+       ((> i (integer-length int)) result)))
+
+(defun octet-list->int (octet-list)
+  "Convert sequence of twos-complement octets into an integer."
+  (assert (consp octet-list))
+  (let ((int 0))
+    (dolist (value octet-list int) (setq int (+ (ash int 8) value)))))
+
+(defun string->char-code-list (string)
+  "Convert a string into a list of bytes."
+   (let ((string (etypecase string 
+ 		  (string string)
+ 		  (symbol (symbol-name string)))))
+     #-(or allegro ccl sbcl)
+     (map 'list #'char-code string)
+     #+ccl
+     (coerce 
+      (ccl::encode-string-to-octets string :external-format :utf-8) 'list)
+     #+sbcl
+     (coerce (sb-ext:string-to-octets string :external-format :utf-8) 'list)
+     #+allegro
+     (coerce (excl:string-to-octets string :null-terminate nil) 'list)))
+
+(defun char-code-list->string (char-code-list)
+  "Convert a list of bytes into a string."
+  (assert (or (null char-code-list) (consp char-code-list)))
+  #-(or allegro ccl sbcl)
+  (map 'string #'code-char char-code-list)
+  #+ccl
+  (ccl::decode-string-from-octets (make-array (list (length char-code-list))
+					      :element-type '(unsigned-byte 8)
+					      :initial-contents char-code-list)
+				  :external-format :utf-8)
+  #+sbcl
+  (sb-ext:octets-to-string (make-array (list (length char-code-list))
+				       :element-type '(unsigned-byte 8)
+				       :initial-contents char-code-list)
+			   :external-format :utf-8)
+  #+allegro
+  (excl:octets-to-string (make-array (list (length char-code-list))
+				     :element-type '(unsigned-byte 8)
+				     :initial-contents char-code-list)
+			 :external-format :utf8))
+
+(defun filter-string->sexp (filter)
+  "Convert a filter-string into a sexp."
+  (unless (and (char= #\( (char filter 0))
+ 	       (char= #\) (char filter (1- (length filter)))))
+    (setf filter (format nil "(~A)" filter)))
+  (unless (balanced-parentheses-p filter)
+    (error 'ldap-filter-error :mesg "unbalanced parentheses" :filter filter))
+  (let ((*package* (find-package :ldap)))
+    (read-from-string (rearrange-filter (quote-verticals filter)) nil nil)))
+
+(defun quote-verticals (string)
+  "Backslash quote the character | (for filter strings)"
+  (with-output-to-string (stream)
+			 (loop for char across string do
+			       (when (char= char #\|) (write-char #\\ stream))
+			       (write-char char stream))))
+
+(defun balanced-parentheses-p (string)
+  (let ((level 0))
+    (dotimes (i (length string) (zerop level))
+      (case (char string i)
+	(#\( (incf level))
+	(#\) (if (zerop level) (return nil) (decf level)))))))
+  
+(defun rearrange-filter (string &optional (beg 0))
+  "Prepare a filter to be (read)."
+  (let ((pos (position #\= string :start beg)))
+    (if pos
+	(flet ((trim (x) (string-trim '(#\Space) x)))
+	  (let* ((opening-paren (position #\( string :from-end t :end pos))
+		 (closing-paren (position #\) string :start pos))
+		 (prev (char string (1- pos)))
+		 (next (char string (1+ pos)))
+		 (op-bounds 
+		  (cond
+		    ((or (eql #\~ prev) (eql #\< prev) (eql #\> prev)) 
+		     (list (1- pos) (1+ pos)))
+		    ((eql #\* next) (list pos (+ 2 pos)))
+		    (t (list pos (1+ pos)))))
+		 (op  (subseq string (first op-bounds) (second op-bounds)))
+		 (att (trim (subseq string (1+ opening-paren) 
+				    (first op-bounds))))
+		 (val (trim (subseq string (second op-bounds) closing-paren)))
+		 (pre-part (subseq string 0 (1+ opening-paren)))
+		 (post-part (subseq string closing-paren)))
+	    (unless (attribute-p att)
+	      (error 'ldap-filter-error
+		     :mesg (format nil "invalid attribute in filter: '~A'" att)
+		     :filter string))
+	    (when (and (string= op "=*") (not (string= val "")))
+	      (setf op "=" val (format nil "*~A" val)))
+	    (let ((this-part (format nil "~A ~A |~A|" op att val)))
+	      (rearrange-filter 
+	       (format nil "~A~A~A" pre-part this-part post-part)
+	       (+ (length pre-part) (length this-part))))))
+	string)))
+
+(defun split-substring (string &optional list)
+  "Split a substring filter value into a list, retaining the * separators."
+  (let ((pos (position #\* string)))
+    (if pos
+	(let* ((capture (subseq string 0 pos))
+	       (vals (if (string= capture "") (list "*") (list "*" capture))))
+	  (split-substring (subseq string (1+ pos))(append vals list)))
+	(nreverse (if (string= string "") list (push string list))))))
+
+;;;;
+;;;; BER encoding constants and constructors.
+;;;;
+
+(eval-when (:compile-toplevel :load-toplevel :execute)
+  (define-constant +max-int+ (- (expt 2 31) 1)
+    "As defined by the LDAP RFC.")
+  
+  (define-constant +ber-class-id+
+      '((universal   . #b00000000) (application . #b01000000)
+	(context     . #b10000000) (private     . #b11000000)))
+  
+  (define-constant +ber-p/c-bit+
+      '((primitive   . #b00000000) (constructed . #b00100000)))
+  
+  (define-constant +ber-multibyte-tag-number+ #b00011111
+    "Flag indicating tag number requires > 1 byte")
+  
+  (define-constant +ber-long-length-marker+   #b10000000
+    "Flag indicating more tag number bytes follow")
+  
+  (defun ber-class-id (class)
+    "Return the bits to construct a BER tag of type class."
+    (or (cdr (assoc class +ber-class-id+))
+	(error "Attempted to retrieve a non-existent BER class.")))
+
+  (defun ber-p/c-bit (p/c)
+    "Return the bit to construct a BER tag of class primitive or constructed."
+    (or (cdr (assoc p/c +ber-p/c-bit+))
+	(error "Attempted to retrieve a non-existent p/c bit.")))
+
+  (defun ber-tag-type (class p/c)
+    "Construct the bits that kicks off a BER tag byte."
+    (+ (ber-class-id class) (ber-p/c-bit p/c)))
+
+  (defun ber-tag (class p/c number-or-command)
+    "Construct the list of bytes that constitute a BER tag number 0-127.
+CLASS should be the symbol universal, applicaiton, context, or private.
+P/C should be the symbol primitive or constructed.
+NUMBER should be either an integer or LDAP application name as symbol."
+    (let ((byte (ber-tag-type class p/c))
+	  (number (etypecase number-or-command 
+		    (integer number-or-command)
+		    (symbol (ldap-command number-or-command)))))
+      (cond 
+	((< number 31)  (list (+ byte number)))
+	((< number 128) (list (+ byte +ber-multibyte-tag-number+) number))
+	(t (error "Length of tag exceeds maximum bounds (0-127).")))))
+
+  (defun ber-length (it)
+    "Given a sequence or integer, return a BER length."
+    (let ((length (etypecase it
+		    (sequence (length it))
+		    (integer it))))
+      (cond
+	((< length 128) (list length))
+	((< length +max-int+)
+	 (let ((output (base10->base256 length)))
+	   (append (list (+ (length output) +ber-long-length-marker+)) 
+		   output)))
+	(t (error "Length exceeds maximum bounds")))))
+
+  (defun ber-msg (tag data)
+    "Given a BER tag and a sequence of data, return a message"
+    (let ((len (ber-length data)))
+      (append tag len data))))
+
+
+;;;;
+;;;; LDAP constants and accessors
+;;;;
+
+(define-constant +ldap-version+     #x03 "LDAP version 3.")
+(define-constant +ldap-port-no-ssl+ 389  "Default LDAP Port.")
+(define-constant +ldap-port-ssl+    636  "Default LDAPS Port.")
+
+(define-constant +ldap-disconnection-response+ "1.3.6.1.4.1.1466.20036"
+  "OID of the unsolicited disconnection reponse.")
+  
+(eval-when (:compile-toplevel :load-toplevel :execute)
+  (define-constant +ldap-application-names+
+    '((BindRequest           . 0)
+      (BindResponse          . 1)
+      (UnbindRequest         . 2)
+      (SearchRequest	     . 3)
+      (SearchResultEntry     . 4)
+      (SearchResultReference . 19)
+      (SearchResultDone      . 5)
+      (ModifyRequest         . 6)
+      (ModifyResponse        . 7)
+      (AddRequest            . 8)
+      (AddResponse           . 9)
+      (DelRequest            . 10)
+      (DelResponse           . 11)
+      (ModifyDNRequest       . 12)
+      (ModifyDNResponse      . 13)
+      (CompareRequest        . 14)
+      (CompareResponse       . 15)
+      (AbandonRequest        . 16)
+      (ExtendedRequest       . 23)
+      (ExtendedResponse      . 24)))
+  
+  (defun ldap-command (command)
+    "Given a symbol naming an ldap command, return the command number."
+    (cdr (assoc command +ldap-application-names+)))
+  
+  (defun ldap-command-sym (number)
+    "Given an application number, return the command name as symbol."
+    (car (rassoc number +ldap-application-names+)))
+  
+  (define-constant +ldap-result-codes+
+      '((0  . (success			 "Success"))
+	(1  . (operationsError		 "Operations Error"))
+	(2  . (protocolError		 "Protocol Error"))
+	(3  . (timeLimitExceeded	 "Time Limit Exceeded"))
+	(4  . (sizeLimitExceeded	 "Size Limit Exceeded"))
+	(5  . (compareFalse		 "Compare False"))
+	(6  . (compareTrue		 "Compare True"))
+	(7  . (authMethodNotSupported	 "Auth Method Not Supported"))
+	(8  . (strongAuthRequired	 "Strong Auth Required"))
+	(10 . (referral			 "Referral"))
+	(11 . (adminLimitExceeded	 "Admin Limit Exceeded"))
+	(12 . (unavailableCriticalExtension "Unavailable Critical Extension"))
+	(13 . (confidentialityRequired	 "Confidentiality Required"))
+	(14 . (saslBindInProgress	 "SASL Bind In Progress"))
+	(16 . (noSuchAttribute		 "No Such Attribute"))
+	(17 . (undefinedAttributeType	 "Undefined Attribute Type"))
+	(18 . (inappropriateMatching	 "Inappropriate Matching"))
+	(19 . (constraintViolation	 "Constraint Violation"))
+	(20 . (attributeOrValueExists	 "Attribute Or Value Exists"))
+	(21 . (invalidAttributeSyntax	 "Invalid Attribute Syntax"))
+	(32 . (noSuchObject		 "No Such Object"))
+	(33 . (aliasProblem		 "Alias Problem"))
+	(34 . (invalidDNSyntax		 "Invalid DN Syntax"))
+	(36 . (aliasDereferencingProblem    "Alias Dereferencing Problem"))
+	(48 . (inappropriateAuthentication  "Inappropriate Authentication"))
+	(49 . (invalidCredentials	 "Invalid Credentials"))
+	(50 . (insufficientAccessRights	 "Insufficient Access Rights"))
+	(51 . (busy			 "Busy"))
+	(52 . (unavailable		 "Unavailable"))
+	(53 . (unwillingToPerform	 "Unwilling To Perform"))
+	(54 . (loopDetect		 "Loop Detect"))
+	(64 . (namingViolation		 "Naming Violation"))
+	(65 . (objectClassViolation	 "Object Class Violation"))
+	(66 . (notAllowedOnLeaf		 "Not Allowed On Leaf"))
+	(67 . (notAllowedOnRDN		 "Not Allowed On RDN"))
+	(68 . (entryAlreadyExists	 "Entry Already Exists"))
+	(69 . (objectClassModsProhibited "Object Class Mods Prohibited"))
+	(71 . (affectsMultipleDSAs	 "Affects Multiple DSAs"))
+	(80 . (other			 "Other"))))
+
+  ; export the result code symbols.
+  (dolist (i +ldap-result-codes+) (export (second i) :ldap)))
+
+(defun ldap-result-code-string (code)
+  (second (cdr (assoc code +ldap-result-codes+))))
+
+(defun ldap-result-code-symbol (code)
+  (first (cdr (assoc code +ldap-result-codes+))))
+
+
+(define-constant +ldap-scope+ 
+  '((base . 0)
+    (one  . 1)
+    (sub  . 2)))
+
+(define-constant +ldap-deref+
+  '((never  . 0)
+    (search . 1)
+    (find   . 2)
+    (always . 3)))
+
+(define-constant +ldap-modify-type+
+  '((add . 0)
+    (delete . 1)
+    (replace . 2)))
+
+(define-constant +ldap-filter-comparison-char+
+  '((&  . 0)
+    (\| . 1)
+    (!  . 2)
+    (=  . 3)
+    (>= . 5)
+    (<= . 6)
+    (=* . 7)
+    (~= . 8)
+    (substring . 4)))
+
+(define-constant +ldap-substring+
+  '((initial . 0)
+    (any     . 1)
+    (final   . 2)))
+
+(defun ldap-scope (&optional (scope 'sub))
+  "Given a scope symbol return the enumeration int."
+    (cdr (assoc scope +ldap-scope+)))
+
+(defun ldap-deref (&optional (deref 'never))
+  "Given a deref symbol return the enumeration int."
+  (cdr (assoc deref +ldap-deref+)))
+
+(defun ldap-modify-type (type)
+  "Given a modify type, return the enumeration int."
+  (cdr (assoc type +ldap-modify-type+)))
+	
+(defun ldap-filter-comparison-char (comparison-char-as-symbol)
+  "Given a comparison character, return its integer enum value."
+  (cdr (assoc comparison-char-as-symbol +ldap-filter-comparison-char+)))
+    
+(defun ldap-substring (type)
+  "Given a substring type, return its integer choice value."
+  (cdr (assoc type +ldap-substring+)))
+
+(defun attribute-p (attribute)
+  "Return T if string/symb is legal as an attribute, nil otherwise."
+  (let ((string (etypecase attribute 
+		  (string attribute)
+		  (symbol (symbol-name attribute)))))
+    (let ((bad-char-count 
+	   (count-if-not #'(lambda (x) 
+			     (or
+			      (and (char>= x #\0) (char<= x #\9))
+			      (and (char>= x #\A) (char<= x #\Z))
+			      (and (char>= x #\a) (char<= x #\z))
+			      (char= x #\;)
+			      (char= x #\-))) string)))
+      (if (= 0 bad-char-count) (intern (string-upcase string)) nil))))
+
+;;;;
+;;;; BER sequence creators.
+;;;;
+
+;;; writers.
+(define-constant +ber-bind-tag+ 
+  (ber-tag 'application 'constructed 'bindrequest))
+(define-constant +ber-add-tag+  
+  (ber-tag 'application 'constructed 'addrequest))
+(define-constant +ber-del-tag+  
+  (ber-tag 'application 'primitive 'delrequest))
+(define-constant +ber-moddn-tag+  
+  (ber-tag 'application 'constructed 'modifydnrequest))
+(define-constant +ber-comp-tag+ 
+  (ber-tag 'application 'constructed 'comparerequest))
+(define-constant +ber-search-tag+
+  (ber-tag 'application 'constructed 'searchrequest))
+(define-constant +ber-abandon-tag+
+  (ber-tag 'application 'primitive 'abandonrequest))
+(define-constant +ber-unbind-tag+
+  (ber-tag 'application 'primitive 'unbindrequest))
+(define-constant +ber-modify-tag+
+  (ber-tag 'application 'constructed 'modifyrequest))
+
+;;;; readers.
+(define-constant +ber-tag-extendedresponse+
+    (car (ber-tag 'application 'constructed 'extendedresponse)))
+(define-constant +ber-tag-ext-name+  
+    (car (ber-tag 'context 'primitive 10)))
+(define-constant +ber-tag-ext-val+ 
+    (car (ber-tag 'context 'primitive 11)))
+(define-constant +ber-tag-bool+ 
+    (car (ber-tag 'universal 'primitive #x01)))
+(define-constant +ber-tag-int+ 
+    (car (ber-tag 'universal 'primitive #x02)))
+(define-constant +ber-tag-enum+ 
+    (car(ber-tag 'universal 'primitive #x0A)))
+(define-constant +ber-tag-str+ 
+    (car (ber-tag 'universal 'primitive #x04)))
+(define-constant +ber-tag-seq+ 
+    (car (ber-tag 'universal 'constructed #x10)))
+(define-constant +ber-tag-set+ 
+    (car (ber-tag 'universal 'constructed #x11)))
+
+(defun seq-null ()
+  "BER encode a NULL"
+  (append (ber-tag 'universal 'primitive #x05) (ber-length 0)))
+
+(defun seq-boolean (t/f)
+  "BER encode a boolean value."
+  (let ((value (cond ((eql t/f t)   #xFF)
+		     ((eql t/f nil) #x00)
+		     (t (error "Unknown boolean value.")))))
+    (nconc (ber-tag 'universal 'primitive #x01) (ber-length 1) (list value))))
+
+(defun seq-integer (int)
+  "BER encode an integer value."
+  (assert (integerp int))
+  (let ((bytes (int->octet-list int)))
+    (nconc (ber-tag 'universal 'primitive #x02) (ber-length bytes) bytes)))
+
+(defun seq-enumerated (int)
+  "BER encode an enumeration value."
+  (assert (integerp int))
+  (let ((bytes (int->octet-list int)))
+    (nconc (ber-tag 'universal 'primitive #x0A) (ber-length bytes) bytes)))
+
+(defun seq-octet-string (string)
+  "BER encode an octet string value."
+  (let ((bytes (seq-primitive-string string)))
+    (nconc (ber-tag 'universal 'primitive #x04) (ber-length bytes) bytes)))
+
+(defun seq-sequence (tlv-seq)
+  "BER encode a sequence of TLVs."
+  (assert (or (null tlv-seq) (consp tlv-seq)))
+  (nconc (ber-tag 'universal 'constructed #x10) (ber-length tlv-seq) tlv-seq))
+
+(defun seq-set (tlv-set)
+  "BER encode a set of TLVs."
+  (assert (consp tlv-set))
+  (nconc (ber-tag 'universal 'constructed #x11) (ber-length tlv-set) tlv-set))
+
+(defun seq-primitive-choice (int &optional data)
+  "BER encode a context-specific choice."
+  (assert (integerp int))
+  (let ((tag (ber-tag 'context 'primitive int)))
+    (etypecase data
+      (null (append tag (list #x00)))
+      (string  (if (string= data "") 
+		   (append tag (list #x00))
+		   (append tag (ber-length data) 
+			   (string->char-code-list data))))
+      (integer (seq-integer data))
+      (boolean (seq-boolean data))
+      (symbol  (let ((str (symbol-name data)))
+		 (append tag (ber-length str) 
+			 (string->char-code-list str)))))))
+
+(defun seq-constructed-choice (int &optional data)
+  "BER encode a context-specific, constructed choice."
+  (assert (integerp int))
+  (let ((tag (ber-tag 'context 'constructed int)))
+    (etypecase data
+      (string (let* ((val (seq-octet-string data))
+		     (len (ber-length val)))
+		(append tag len val)))
+      (sequence (let ((len (ber-length data)))
+		  (append tag len data))))))
+		     
+(defun seq-primitive-string (string)
+  "BER encode a string/symbol for use in a primitive context."
+  (assert (or (stringp string) (symbolp string)))
+  (string->char-code-list string))
+
+(defun seq-attribute-alist (atts)
+  "BER encode an entry object's attribute alist (for use in add)."
+  (seq-sequence (mapcan #'(lambda (i) 
+			    (seq-att-and-values (car i) (cdr i))) atts)))
+    
+(defun seq-attribute-list (att-list)
+  "BER encode a list of attributes (for use in search)."
+  (seq-sequence (mapcan #'seq-octet-string att-list)))
+
+(defun seq-attribute-assertion (att val)
+  "BER encode an ldap attribute assertion (for use in compare)."
+  (seq-sequence (nconc (seq-octet-string att) (seq-octet-string val))))
+  
+(defun seq-attribute-value-assertion (att val)
+  "BER encode an ldap attribute value assertion (for use in filters)."
+  (nconc (seq-octet-string att) (seq-octet-string val)))
+
+(defun seq-att-and-values (att vals)
+  "BER encode an attribute and set of values (for use in modify)."
+  (unless (listp vals) (setf vals (list vals)))
+  (seq-sequence (nconc (seq-octet-string att) 
+		       (seq-set (mapcan #'seq-octet-string vals)))))
+
+(defun seq-filter (filter)
+  (let* ((filter (etypecase filter
+		   (cons   filter)
+		   (symbol filter)
+		   (string (filter-string->sexp filter))))
+	 (op  (car filter))
+	 (sub (if (and (eq '= op)
+		       (> (count #\* (symbol-name (third filter))) 0)) t nil)))
+    (cond
+      ((eq '! op) (seq-constructed-choice (ldap-filter-comparison-char op)
+					  (seq-filter (cadr filter))))
+      ((or (eq '&  op) (eq '\| op))
+       (seq-constructed-choice (ldap-filter-comparison-char op)
+			       (mapcan #'seq-filter (cdr filter))))
+      ((or (and (eq '= op) (not sub))
+	   (eq '<= op) (eq '>= op) (eq '~= op))
+       (seq-constructed-choice (ldap-filter-comparison-char op) 
+			       (seq-attribute-value-assertion
+				(second filter) (third filter))))
+      ((eq '=* op) (seq-primitive-choice 
+		    (ldap-filter-comparison-char op) (second filter)))
+      ((and (eq '= op) sub)
+       (seq-constructed-choice (ldap-filter-comparison-char 'substring)
+			       (append (seq-octet-string (second filter))
+				       (seq-substrings (third filter)))))
+      (t (error 'ldap-filter-error 
+		:mesg "unable to determine operator." :filter filter)))))
+
+
+(defun seq-substrings (value)
+  "Given a search value with *s in it, return a BER encoded list."
+  (let ((list (etypecase value 
+		  (symbol (split-substring (symbol-name value)))
+		  (string (split-substring value))))
+	(initial ()) (any ()) (final ()))
+    (when (string/= "*" (car list))   ; initial
+      (setf initial (seq-primitive-choice (ldap-substring 'initial)
+					  (car list))))
+    (setf list (cdr list))            ; last
+    (when (and (> (length list) 0) (string/= "*" (car (last list))))
+      (setf final (seq-primitive-choice (ldap-substring 'final)
+					(car (last list)))))
+    (setf list (butlast list))
+    (when (> (length list) 0)         ; any
+      (dolist (i (remove "*" list :test #'string=))
+	(setf any (append any (seq-primitive-choice 
+			       (ldap-substring 'any) i)))))
+    (seq-sequence (nconc initial any final))))
+
+(defun valid-ldap-response-p (tag-byte)
+  "Return T if this is the valid initial tag byte for an LDAP response."
+  (if (= tag-byte (car (ber-tag 'universal 'constructed #x10))) t nil))
+
+
+;;;;
+;;;; referrer class & methods.
+;;;;
+
+(defclass referrer ()
+  ((url :initarg :url 
+	:initform (error "No URL specified")
+	:type string
+	:accessor url)))
+
+(defun new-referrer (url)
+  "Instantiate a new referrer object."
+  (make-instance 'referrer :url url))
+
+;;;;
+;;;; entry class & methods.
+;;;;
+
+(defclass entry ()
+  ((dn    :initarg :dn     :type string  :accessor dn)
+   (rdn   :initarg :rdn    :type string  :accessor rdn)
+   (attrs :initarg :attrs  :type cons    :accessor attrs)))
+
+(defmethod dn ((dn string)) dn)
+
+(defun rdn-from-dn (dn)
+  "Given a DN, return its RDN and a cons of (att . val)"
+  (let* ((eql-pos (position #\= dn))
+	 (rdn (subseq dn 0 (position #\, dn)))
+	 (rdn-att (subseq rdn 0 eql-pos))
+	 (rdn-val (subseq rdn (1+ eql-pos) (length rdn))))
+    (values rdn (list (intern (string-upcase rdn-att)) rdn-val))))
+
+(defun new-entry (dn &key (attrs ()) (infer-rdn t))
+  "Instantiate a new entry object."
+  (multiple-value-bind (rdn rdn-list) (rdn-from-dn dn)
+   (when (and infer-rdn
+	      (not (assoc (car rdn-list) attrs)))
+     (setf attrs (acons (car rdn-list) (cdr rdn-list) attrs)))
+   (make-instance 'entry :dn dn :rdn rdn :attrs attrs)))
+
+(defmethod change-rdn ((entry entry) new-rdn)
+  "Change the DN and RDN of the specified object, don't touch LDAP."
+  (let* ((len-old (length (rdn entry)))
+	 (dn (concatenate 'string new-rdn (subseq (dn entry) len-old))))
+    (multiple-value-bind (old-rdn old-rdn-parts) (rdn-from-dn (dn entry))
+      (declare (ignore old-rdn))
+      (del-attr entry (first old-rdn-parts) (second old-rdn-parts)))
+    (setf (dn entry) dn  
+	  (rdn entry) new-rdn)
+    (multiple-value-bind (new-rdn new-rdn-parts) (rdn-from-dn (dn entry))
+      (declare (ignore new-rdn))
+      (add-attr entry (first new-rdn-parts) (second new-rdn-parts)))))
+
+(defmethod attr-value ((entry entry) attr)
+  "Given an entry object and attr name (symbol), return list of values."
+  (let ((val (cdr (assoc attr (attrs entry)))))
+    (cond 
+      ((null val) nil)
+      ((consp val) val)
+      (t (list val)))))
+
+(defmethod attr-value ((entry entry) (attrs list))
+  "Given an entry object and list of attr names (as symbols), 
+return list of lists of attributes."
+  (mapcar #'(lambda (attr) (attr-value entry attr)) attrs))
+
+(defmethod attr-list ((entry entry))
+  "Given an entry object, return a list of its attributes."
+  (map 'list #'car (attrs entry)))
+
+(defmethod add-attr ((entry entry) attr vals)
+  "Add an attribute to entry object, do not update LDAP."
+  (let ((old-val-list (attr-value entry attr))
+	(new-val-list (if (consp vals) vals (list vals))))
+    (replace-attr entry attr (append old-val-list new-val-list))))
+
+(defmethod del-attr ((entry entry) attr &optional vals)
+  "Delete an attribute from entry object, do not update LDAP"
+  (let ((old-val (attr-value entry attr))
+	(new-val (if (consp vals) vals (list vals))))
+    (dolist (val new-val)
+      (setf old-val (remove-if #'(lambda (x) (string= val x)) old-val)))
+    (if (or (null (car old-val))
+	    (null (car new-val)))
+	(setf (attrs entry) 
+	      (remove-if #'(lambda (x) (eq (car x) attr)) (attrs entry)))
+	(replace-attr entry attr old-val))))
+	      
+(defmethod replace-attr ((entry entry) attr vals)
+  "Replace attribute values from entry object, do not update LDAP"
+  (let ((vals (remove-if #'null vals)))
+    (if (consp (assoc attr (attrs entry)))
+	(rplacd (assoc attr (attrs entry)) vals)
+	(setf (attrs entry) (acons attr vals (attrs entry))))))
+
+(defmethod ldif ((entry entry))
+  "Return an ldif formatted representation of entry."
+  (let ((results (format nil "DN: ~A~%" (dn entry))))
+    (dolist (att (attr-list entry) results)
+      (dolist (val (attr-value entry att))
+	(setf results (format nil "~@[~A~]~A: ~A~%" results att val))))))
+
+(defun new-entry-from-list (list)
+  "Create an entry object from the list return by search."
+  (let ((dn (car list))
+	(attrs (mapcar #'(lambda (x) (cons (intern (string-upcase (car x)))
+					   (cadr x)))
+		       (cadr list))))
+    (new-entry dn :attrs attrs)))
+
+;;;;
+;;;; LDAP class & methods
+;;;;
+
+(defclass ldap () 
+  ((host   :initarg :host 
+	   :initform "localhost"
+	   :type string 
+	   :accessor host)
+   (port   :initarg :port 
+	   :initform +ldap-port-no-ssl+
+	   :type integer 
+	   :accessor port)
+   (sslflag :initarg :sslflag
+	    :initform nil
+	    :type symbol
+	    :accessor sslflag)
+   (user   :initarg :user 
+	   :initform ""
+	   :type string 
+	   :accessor user)
+   (pass   :initarg :pass 
+	   :initform ""
+	   :type string 
+	   :accessor pass)
+   (ldapstream :initarg :ldapstream  
+	   :initform nil 
+	   :type (or null stream) 
+	   :accessor ldapstream)
+   (ldapsock :initarg :ldapsock
+	   :initform nil 
+	   :accessor ldapsock)
+   (reuse-connection :initarg :reuse-connection
+		     :initform t
+		     :type symbol
+		     :documentation "nil, t, or bind"
+		     :accessor reuse-connection)
+   (mesg   :initarg :mesg 
+	   :initform 0 
+	   :type integer 
+	   :accessor mesg)
+   (debugflag  :initarg :debugflag
+	       :initform nil 
+	       :type symbol 
+	       :accessor debugflag)
+   (base   :initarg :base 
+	   :initform nil 
+	   :type (or null string) 
+	   :accessor base)
+   (response :initarg :response
+	     :initform ()
+	     :type list
+	     :accessor response)
+   (entry-buffer :initarg :entry-buffer
+		 :initform nil
+		 :accessor entry-buffer)
+   (results-pending-p :initarg :results-pending-p
+		      :initform nil
+		      :type (boolean)
+		      :accessor results-pending-p)))
+   
+
+(defun new-ldap (&key (host "localhost") (sslflag nil)
+		 (port (if sslflag +ldap-port-ssl+ +ldap-port-no-ssl+))
+		 (user "") (pass "") (base nil) (debug nil)
+		 (reuse-connection nil))
+  "Instantiate a new ldap object."
+  (make-instance 'ldap :host host :port port :user user :sslflag sslflag
+		 :pass pass :debugflag debug :base base 
+		 :reuse-connection reuse-connection))
+
+(defmethod debug-mesg ((ldap ldap)  message)
+  "If debugging in T, print a message."
+  (when (debugflag ldap) (format *debug-io* "~A~%" message)))
+
+(defmethod mesg-incf ((ldap ldap)) (incf (mesg ldap)))
+
+(defmethod get-stream ((ldap ldap))
+  "Open a usocket to the ldap server and set the ldap object's slot.
+If the port number is 636 or the SSLflag is not null, the stream
+will be made with CL+SSL."
+  (let ((existing-stream (ldapstream ldap)))
+    (unless (and (streamp existing-stream) 
+		 (open-stream-p existing-stream))
+      (let* ((sock (usocket:socket-connect (host ldap) (port ldap)
+					   :element-type '(unsigned-byte 8)))
+	     (stream 
+	      (if (or (sslflag ldap) (= (port ldap) 636))
+		  (cl+ssl:make-ssl-client-stream (usocket:socket-stream sock))
+		  (usocket:socket-stream sock))))
+	(debug-mesg ldap "Opening socket and stream.")
+	(setf (ldapsock ldap) sock)
+	(setf (ldapstream ldap) stream))))
+    (ldapstream ldap))
+
+(defmethod close-stream ((ldap ldap))
+  "Close an ldap connection if it is currently open."
+  (let ((existing-stream (ldapstream ldap))
+	(existing-sock (ldapsock ldap)))
+    (when (and (streamp existing-stream) (open-stream-p existing-stream))
+      (ignore-errors
+	(setf (ldapstream ldap) nil)
+	(setf (ldapsock ldap) nil)
+	(close existing-stream)
+	(usocket:socket-close existing-sock)))))
+
+(defmethod possibly-reopen-and-rebind ((ldap ldap) 
+				       &optional (absolutely-no-bind nil))
+  "Take appropriate reopen or rebind actions based on the reuse-connection attr.
+If the attribute is nil, do nothing; if t, reopen; and, if bind, rebind.
+This function exists to help the poor saps (read: me) with very fast idletimeout
+settings on their LDAP servers."
+  (debug-mesg ldap "reusing connection...")
+  (let (stream)
+    (when (reuse-connection ldap) 
+      (close-stream ldap)
+      (setf stream (get-stream ldap)))
+    (when (and (not absolutely-no-bind)
+	       (eq (reuse-connection ldap) 'rebind))
+      (debug-mesg ldap "rebinding...")
+      (bind ldap))
+    stream))
+  
+(defmethod send-message ((ldap ldap) message &optional (response-expected t))
+  "Send a BER encoded message to ldap."
+  (let ((mesg (seq-sequence (append (seq-integer (mesg-incf ldap)) message)))
+	(stream (get-stream ldap)))
+    (debug-mesg ldap (format nil *hex-print* "To LDAP: " mesg))
+    (dolist (byte mesg) (write-byte byte stream))
+    (handler-case (finish-output stream)
+      (error (e) (error 'ldap-connection-error
+			:host (host ldap) :port (port ldap) :mesg e)))
+    (when response-expected (setf (results-pending-p ldap) t))))
+
+(defmethod receive-length ((ldap ldap))
+  "Read length of LDAP message from stream, return length & the bytes read."
+  (let* ((stream (ldapstream ldap))
+	 (length-byte (read-byte stream))
+	 (byte-seq ())
+	 (byte-len (- length-byte 128))
+	 (length-of-message
+	  (cond
+	    ((< length-byte 128) length-byte)
+	    (t (dotimes (i byte-len) (push (read-byte stream) byte-seq))
+	       (base256->base10 (reverse byte-seq)))))
+	 (all-bytes-consumed (append (list length-byte) (nreverse byte-seq))))
+    (values length-of-message all-bytes-consumed)))
+
+(defmethod receive-message ((ldap ldap))
+  "Read incoming LDAP data from the stream, populate LDAP response slot.
+The initial tag and length of message bytes will have been consumed already
+and will not appear in the response.  Note that this method is executed
+only for its side effects."
+  (let* (ber-response 
+	 (stream (get-stream ldap))
+	 (initial-byte (read-byte stream)))
+    (unless (or (null initial-byte) (valid-ldap-response-p initial-byte))
+      (error "Received unparsable data from LDAP server."))
+    (multiple-value-bind (message-length bytes-read) (receive-length ldap)
+      (dotimes (i message-length) (push (read-byte stream) ber-response))
+      (setf (response ldap) (nreverse ber-response))
+      (debug-mesg ldap (format nil *hex-print* "From LDAP:"
+			       (append (list initial-byte) bytes-read 
+				       (response ldap)))))
+    (let ((response-minus-message-number 
+	   (check-message-number (response ldap) (mesg ldap))))
+      (cond
+	((null response-minus-message-number) (receive-message ldap))
+	(t (setf (response ldap) response-minus-message-number))))))
+  
+(defmethod handle-extended-response ((ldap ldap) content)
+  "Process an extended response.
+Currently this means closing the connection if it is a disconnect request
+and throw an error if it's anything else."
+  (if (string= (fourth content) +ldap-disconnection-response+)
+      (close-stream ldap)
+      (error 'ldap-error 
+	     :mesg (format nil "Received unhandled extended response: ~A~%"
+			   content))))
+
+(defmethod parse-ldap-message ((ldap ldap) &optional (return-entry nil))
+  "Parse an ldap object's response slot."
+  (let ((received-content ()))
+    (multiple-value-bind (content appname) (read-decoder (response ldap))
+      (cond
+	((eq appname 'searchresultentry)
+	 (let ((new-entry (new-entry-from-list content)))
+	   (cond
+	     ((null return-entry)
+	      (setf (entry-buffer ldap) new-entry)
+	      (setf received-content t))
+	     (t (setf received-content new-entry)))))
+	((eq appname 'searchresultreference))
+	((eq appname 'searchresultdone)
+	 (setf (results-pending-p ldap) nil)
+	 (setf received-content nil))
+	((eq appname 'extendedresponse) 
+	 (handle-extended-response ldap content)
+	 (push content received-content)
+	 (setf (results-pending-p ldap) nil))
+	(t 
+	 (push content received-content)
+	 (setf (results-pending-p ldap) nil))))
+    received-content))
+	
+(defmethod process-message ((ldap ldap) message &key (success 'success))
+  "Send a simple request to LDAP and return three values:
+T or NIL, the LDAP response code (as a readable string), and any message
+the directory server returned."
+  (let ((bind-p (equal (msg-bind ldap) message)))
+    (possibly-reopen-and-rebind ldap bind-p))
+  (send-message ldap message)
+  (receive-message ldap)
+  (let* ((results (car (parse-ldap-message ldap)))
+	 (code (car results))
+	 (msg (third results))
+	 (code-sym (ldap-result-code-symbol code))
+	 (rc (if (eq code-sym success) t nil)))
+    (values rc code-sym msg)))
+
+;;;;  
+;;;; ldap user-level commands.
+;;;;
+
+(defmethod bind ((ldap ldap))
+  "Send a BindRequest."
+  (process-message ldap (msg-bind ldap)))
+
+(defmethod unbind ((ldap ldap))
+  "Unbind and close the ldap stream."
+  (send-message ldap (msg-unbind) nil)
+  (setf (mesg ldap) 0)
+  (close-stream ldap))
+
+(defmethod abandon ((ldap ldap))
+  "Abandon the request and suck any data off the incoming stream.
+Because the receive-message will keep receiving messages until it gets
+one with the correct message number, no action needs to be taken here to 
+clear the incoming data off the line.  It's unclear that's the best 
+solution, but (clear-input) doesn't actually work and trying to read non-
+existent bytes blocks..."
+  (send-message ldap (msg-abandon ldap) nil))
+
+
+(defmethod add ((ldap ldap) (entry entry))
+  "Add an entry to the directory."
+  (process-message ldap (msg-add entry)))
+
+(defmethod add ((entry entry) (ldap ldap))
+  "Add an entry object to LDAP; error unless successful."
+  (multiple-value-bind (res code msg) (add ldap entry)
+    (or res (error 'ldap-response-error 
+		   :mesg "Cannot add entry to LDAP directory."
+		   :dn (dn entry) :code code :msg msg))))
+
+(defmethod delete ((ldap ldap) dn-or-entry)
+  "Delete an entry (or DN) from the directory."
+  (process-message ldap (msg-delete dn-or-entry)))
+
+(defmethod delete ((entry entry) (ldap ldap))
+  "Delete an entry object from ldap; error unless successful."
+  (delete (dn entry) ldap))
+
+(defmethod delete ((dn string) (ldap ldap))
+  "Delete an entry from LDAP; error unless successful."
+  (multiple-value-bind (res code msg) (delete ldap dn)
+    (or res (error 'ldap-response-error
+		   :mesg "Cannot delete entry from LDAP directory."
+		   :dn dn :code code :msg msg))))
+
+(defmethod moddn ((ldap ldap) dn-or-entry new-rdn &key delete-old new-sup)
+  "Modify an entry's RDN."
+  (process-message ldap (msg-moddn dn-or-entry new-rdn delete-old new-sup)))
+
+(defmethod moddn ((entry entry) (ldap ldap) new-rdn &key delete-old new-sup)
+  "Modify the RDN of an LDAP entry; update the entry object as well."
+  (when (moddn (dn entry) ldap new-rdn :delete-old delete-old :new-sup new-sup)
+    (change-rdn entry new-rdn)))
+
+(defmethod moddn ((dn string) (ldap ldap) new-rdn &key delete-old new-sup)
+  "Modify the RDN of an LDAP entry."
+  (multiple-value-bind (res code msg)
+      (moddn ldap dn new-rdn :delete-old delete-old :new-sup new-sup)
+    (or res (error 'ldap-response-error 
+		   :mesg "Cannot modify RDN in the LDAP directory."
+		   :dn dn :code code :msg msg))))
+
+(defmethod compare ((ldap ldap) dn-or-entry attribute value)
+  "Assert DN has attribute with specified value."
+  (process-message ldap (msg-compare dn-or-entry attribute value)
+		   :success 'comparetrue))
+
+(defmethod compare ((entry entry) (ldap ldap) attribute value)
+  "Assert an entry has an att=val; return t or nil, or throw error."
+  (compare (dn entry) ldap attribute value))
+
+(defmethod compare ((dn string) (ldap ldap) attribute value)
+  "Compare entry's att/val; calle by both entry/compare methods."
+  (multiple-value-bind (res code msg) (compare ldap dn attribute value)
+    (declare (ignore res))
+    (cond ((eq code 'comparetrue) t)
+	  ((eq code 'comparefalse) nil)
+	  (t (error 'ldap-response-error
+		    :mesg "Cannot compare entry's attribute/value."
+		    :dn dn :code code :msg msg)))))
+
+(defmethod modify ((ldap ldap) dn-or-entry list-of-mods)
+  "Modify and entry's attributes."
+  (process-message ldap (msg-modify dn-or-entry list-of-mods)))
+
+(defmethod modify ((entry entry) (ldap ldap) list-of-mods)
+  "Modify entry attributes in ldap, update the entry object.
+LIST-OF-MODS is a list of (type att val) triples."
+  (multiple-value-bind (res code msg) (modify ldap entry list-of-mods)
+    (when (null res) 
+      (error 'ldap-response-error
+	     :mesg "Cannot modify entry in the LDAP directory."
+	     :dn (dn entry) :code code :msg msg))
+    ; succeeded, so modify the entry.
+    (dolist (i list-of-mods t)
+      (cond
+	((eq (car i) 'delete) (del-attr entry (second i) (third i)))
+	((eq (car i) 'add) (add-attr entry (second i) (third i)))
+	(t (replace-attr entry (second i) (third i)))))))
+
+(defmethod search ((ldap ldap) filter &key base (scope 'sub) 
+		   (deref 'never) (size-limit 0) (time-limit 0) 
+		   types-only attributes)
+  "Search the LDAP directory."
+  (let ((base (if (null base) (base ldap) base))
+	(scope (ldap-scope scope))
+	(deref (ldap-deref deref)))
+    (possibly-reopen-and-rebind ldap)
+    (send-message ldap (msg-search filter base scope deref size-limit 
+				   time-limit types-only attributes))
+    (receive-message ldap)
+    (parse-ldap-message ldap)))
+
+(defmethod next-search-result ((ldap ldap))
+  "Return the next search result (as entry obj) or NIL if none."
+  (if (results-pending-p ldap)
+      (let ((pending-entry (entry-buffer ldap)))
+	(cond 
+	  ((not (null pending-entry))
+	   (setf (entry-buffer ldap) nil)
+	   pending-entry)
+	  (t (receive-message ldap)
+	     (parse-ldap-message ldap t))))
+      nil))
+
+(defmacro dosearch ((var search-form) &body body)
+  (let ((ldap (gensym))
+ 	(count (gensym)))
+    `(let ((,ldap ,(second search-form))
+ 	   (,count 0))
+      ,search-form
+      (do ((,var (next-search-result ,ldap) 
+ 		 (next-search-result ,ldap)))
+ 	  ((null ,var))
+ 	(incf ,count)
+ 	,@body)
+      ,count)))
+
+(defmacro ldif-search (&rest search-parameters)
+  (let ((ent (gensym)))
+    `(dosearch (,ent (search ,@search-parameters))
+      (format t "~A~%" (ldif ,ent)))))
+
+;;;;
+;;;; ldap message constructors.
+;;;;
+
+(defmethod msg-bind ((ldap ldap))
+  "Return the sequence of bytes representing a bind message."
+  (let ((req (append (seq-integer +ldap-version+)
+		     (seq-octet-string (user ldap))
+		     (seq-primitive-choice 0 (pass ldap)))))
+    (ber-msg +ber-bind-tag+ req)))
+
+(defmethod msg-unbind ()
+  (ber-msg +ber-unbind-tag+ (seq-null)))
+
+(defmethod msg-abandon ((ldap ldap))
+  "Return the sequence of bytes representing an abandon message"
+  (let ((last-message-number (seq-integer (mesg ldap))))
+    (ber-msg +ber-abandon-tag+ last-message-number)))
+
+(defmethod msg-add ((entry entry))
+  "Return the sequence of bytes representing an add message."
+  (let ((dn (seq-octet-string (dn entry)))
+	(att (seq-attribute-alist (attrs entry))))
+    (ber-msg +ber-add-tag+ (append dn att))))
+
+(defun msg-delete (dn-or-entry)
+  "Return the sequence of bytes representing a delete message."
+  (let ((dn (seq-primitive-string (dn dn-or-entry))))
+    (ber-msg +ber-del-tag+ dn)))
+	
+(defun msg-moddn (dn-or-entry new-rdn delete-old new-sup)
+  "Return the sequence of bytes representing a moddn message."
+  (let ((dn  (seq-octet-string (dn dn-or-entry)))
+	(rdn (seq-octet-string new-rdn))
+	(del (seq-boolean delete-old))
+	(new-sup (if new-sup (seq-octet-string new-sup) nil)))
+    (ber-msg +ber-moddn-tag+ (append dn rdn del new-sup))))
+
+(defun msg-compare (dn-or-entry attribute value)
+  "Return the sequence of bytes representing a compare message."
+  (let ((dn (seq-octet-string (dn dn-or-entry)))
+	(assertion (seq-attribute-assertion attribute value)))
+    (ber-msg +ber-comp-tag+ (append dn assertion))))
+
+(defun msg-modify (dn-or-entry mod-list)
+  "Return the sequence of bytes representing a modify message."
+  (let ((dn (seq-octet-string (dn dn-or-entry)))
+	(mods 
+	 (mapcan #'(lambda (x) (seq-sequence 
+				(nconc
+				 (seq-enumerated (ldap-modify-type (first x)))
+				 (seq-att-and-values (second x) (third x)))))
+		 mod-list)))
+    (ber-msg +ber-modify-tag+ (append dn (seq-sequence mods)))))
+
+(defun msg-search (filter base scope deref size time types attrs)
+  "Return the sequence of bytes representing a search message."
+  (let ((filter (seq-filter filter))
+	(base   (seq-octet-string base))
+	(scope  (seq-enumerated scope))
+	(deref  (seq-enumerated deref))
+	(size   (seq-integer size))
+	(time   (seq-integer time))
+	(types  (seq-boolean types))
+	(attrs  (seq-attribute-list attrs)))
+    (ber-msg +ber-search-tag+ 
+	     (append base scope deref size time types filter attrs))))
+
+;;;;
+;;;; sequence reader & decoder functions
+;;;;
+
+(defun read-decoder (response)
+  "Decode a BER encoded response (minus initial byte & length) from LDAP."
+  (let ((appname (ldap-command-sym (read-app-number (pop response)))))
+    (multiple-value-bind (size bytes) (read-length response)
+      (declare (ignore size)) 
+      (setf response (subseq response bytes)))
+    (values (read-generic response) appname)))
+
+(defun read-generic (message &optional (res ()))
+  (if (and (consp message) (> (length message) 0))
+      (progn
+	(let* ((tag-byte (car message))
+	       (fn (cond
+		     ((= tag-byte +ber-tag-int+)  #'read-integer)
+		     ((= tag-byte +ber-tag-enum+) #'read-integer)
+		     ((= tag-byte +ber-tag-str+)  #'read-string)
+		     ((= tag-byte +ber-tag-ext-name+) #'read-string)
+		     ((= tag-byte +ber-tag-ext-val+)  #'read-string)
+		     (t nil))))
+	  (cond 
+	    ((functionp fn)                                   ; primitive.
+	     (multiple-value-bind (val bytes) (funcall fn message)
+	       (push val res)
+	       (setf message (subseq message bytes))))
+	    ((or (= tag-byte +ber-tag-set+)                   ; constructed.
+		 (= tag-byte +ber-tag-seq+)
+		 (= tag-byte +ber-tag-extendedresponse+))
+	     (multiple-value-bind (length bytes) 
+		 (read-length (subseq message 1))
+	       (let* ((start-of-data (+ 1 bytes)) ; tag + bytes
+		      (end-of-data   (+ start-of-data length)))
+		 (push (read-generic 
+			(subseq message start-of-data end-of-data)) res)
+		 (setf message (subseq message end-of-data)))))
+	    (t (error 'ldap-error :mesg "Unreadable tag value encountered.")))
+	  (read-generic message res)))
+      (nreverse res)))
+
+(define-constant +ber-app-const-base+
+  (car (ber-tag 'application 'constructed 0)))
+
+(defun read-app-number (tag)
+  "Given an application tag, return which ldap app number it represents."
+  (- (etypecase tag
+       (integer tag)
+       (cons (car tag))) +ber-app-const-base+))
+
+(defun read-integer (message)
+  "Read an int from the message, return int and number of bytes consumed."
+  (values (octet-list->int (subseq message 2 (+ 2 (second message))))
+	  (+ 2 (second message))))
+
+(defun read-string (message)
+  "Read a string from the message, return string and bytes consumed.."
+  (pop message) ; lose the tag.
+  (multiple-value-bind (len bytes) (read-length message)
+    (values (char-code-list->string 
+	     (subseq message bytes (+ len bytes))) (+ 1 bytes len))))
+
+(defun read-length (message)
+  "Given message starting with length marker, return length and bytes consumed"
+  (cond
+    ((< (car message) 128) (values (car message) 1))
+    (t (let ((bytes (+ 1 (- (car message) 128))))
+	 (values (base256->base10 (subseq message 1 bytes)) bytes)))))
+
+(defun read-message-number (response expected-mesg-number)
+  "Read message number from the seq, return t or nil and bytes consumed."
+  (multiple-value-bind (value bytes) (read-integer response)
+    (let ((result (if (or (= value 0) ; 0 is unsolicited notification.
+			  (= value expected-mesg-number))
+		      t ; msg number matches up
+		      nil)))
+      (values result bytes))))
+
+(defun check-message-number (response expected-mesg-number)
+  "Determine if the  message number of a BER response is correct.
+Returns BER response with message number bytes consumed if it is correct
+or NIL otherwise."
+  (multiple-value-bind (mesg-ok? bytes)
+      (read-message-number response expected-mesg-number)
+    (if mesg-ok? (subseq response bytes) nil)))
+
+;;; trivial-ldap.lisp ends here.
Index: /trunk/contrib/paine/workpersistence.lisp
===================================================================
--- /trunk/contrib/paine/workpersistence.lisp	(revision 13946)
+++ /trunk/contrib/paine/workpersistence.lisp	(revision 13946)
@@ -0,0 +1,113 @@
+(in-package :cl-user)
+
+;;; Clozure CL Hemlock editor windows persistence
+;;; ie. on restart of CCL re-open (and position) the last session's open files.
+;;;
+;;; LLGPL Copyright (c) Peter Paine 20080611 
+;;; Maintainer: gmail: p2.edoc 
+;;; To use: add (require :workpersistence) to your home:ccl-init.lisp file,
+;;          or (load ~this-file~)
+;;; Updates 
+;;; 20091018: restore original window order
+;;;           option to save independently per platform and CLZ-version
+;;; 20090906: fix not saving closed windows, fix resizing in gui thread, save in home dir.
+;;; 20090928: re-select Listener
+;;; ToDo: 
+;;;   - how to read window from buffer (without external search via path)?
+;;;   - if on quit, an unsaved buffers prompt, remember-hemlock-files not called (or doesn't save)
+;;;   - multiple choice menu of buffers to save
+;;;   - add auto backup process: auto save modified files as file name variant, check/restore on restart 
+
+#-(and clozure-common-lisp hemlock) (error "Workpersistence only runs under CLZ ~
+                                           Hemlock Nextstep/Cocoa API")
+
+;; Allows separation of working file sets for different platform versions.
+(defvar *separate-ccl-working-file-sets-by-platform-p* T)
+
+;; Independently save working file sets by major/minor version of CLZ.
+(defvar *separate-ccl-working-file-sets-by-ccl-version-p* nil)
+
+(defun work-persistence-file (&optional version)
+  (setq version (if version (format nil "-~A" version) ""))
+  (let ((ccl-version
+         (if *separate-ccl-working-file-sets-by-ccl-version-p*
+           (format nil "-~D-~D" ccl::*openmcl-major-version* ccl::*openmcl-minor-version*)
+           "")))
+  (if *separate-ccl-working-file-sets-by-platform-p*
+    (format nil "home:.ccl-workpersistence-~A~A~A.text" (ccl::platform-description) ccl-version version)
+    (format nil "home:.ccl-workpersistence~A~A.text" ccl-version version))))
+
+(defvar *work-persistence-file* (work-persistence-file) "per user")
+;; (ed *work-persistence-file*)
+
+(defun copy-work-persistence ()
+  (when (probe-file *work-persistence-file*)
+    (copy-file *work-persistence-file* (work-persistence-file "copy") :if-exists :overwrite)))
+;; (ed (work-persistence-file "copy"))
+
+(defun remember-hemlock-files ()
+  (with-open-file (*standard-output*
+                   *work-persistence-file*
+                   :direction :output :if-exists :supersede)
+    (loop for buffer in (hi::all-buffers)
+      do (let* ((path (hi:buffer-pathname buffer)))
+           (when path 
+             (let ((frame (slot-value (find-file-buffer-window path) 'ns:_frame)))
+               (loop initially (format T "~&(")
+                 for fn in '(ns:ns-rect-x ns:ns-rect-y ns:ns-rect-width ns:ns-rect-height)
+                 do (format T "~5D " (floor (funcall fn frame)))
+                 finally (format T "~S)" path))))))))
+
+(defun find-file-buffer-window (path)
+   (loop with win-arr = (#/orderedWindows ccl::*NSApp*)
+     for i below (#/count win-arr)
+     for win = (#/objectAtIndex: win-arr i)
+     when (and (typep win '(and gui::hemlock-frame
+                                (not gui::hemlock-listener-frame)))
+               (equalp path (hi:buffer-pathname (hi:hemlock-view-buffer
+                                                 (gui::hemlock-view win)))))
+     return win))
+
+(defun find-listener () ; there must be a standard way to do this
+  ;; only saves first listener found
+  (loop with win-arr = (#/orderedWindows ccl::*NSApp*)
+    for i below (#/count win-arr)
+    for win = (#/objectAtIndex: win-arr i)
+    when (typep win 'gui::hemlock-listener-frame)
+    return win))
+
+(defun select-listener ()
+  (process-wait "Wait for Listener" 'find-listener)
+  (let ((listener (find-listener)))
+    (#/performSelectorOnMainThread:withObject:waitUntilDone:
+     listener (objc:@selector "makeKeyAndOrderFront:") nil nil)))
+
+(defun open-remembered-hemlock-files ()
+  (let (old-file-specs)
+    (with-open-file (buffer-persistence-stream
+                     *work-persistence-file*
+                     :direction :input :if-does-not-exist nil)
+      (when buffer-persistence-stream ;; reverse order
+        (loop for item = (read buffer-persistence-stream nil)
+                while item do (push item old-file-specs))))
+    (gui::execute-in-gui 
+     #'(lambda () 
+         (dolist (old-file-spec old-file-specs)
+           (destructuring-bind (posx posy width height path) old-file-spec
+             (when (probe-file path)
+               (gui::find-or-make-hemlock-view path)
+               (let ((window (find-file-buffer-window path))) ; round about way*
+                 ;;* how to get from hemlock-view
+                 (when window
+                   ;; should check whether coords are still in screen bounds
+                   ;; (could have changed screen realestate since)
+                   (let ((rect (ns:make-ns-rect posx posy width height)))
+                     (#/setFrame:display: window rect t)))))))
+         (select-listener)))))
+    
+         
+(pushnew 'remember-hemlock-files *lisp-cleanup-functions*)
+(pushnew 'open-remembered-hemlock-files *lisp-startup-functions*)
+
+;; (remember-hemlock-files)
+(open-remembered-hemlock-files)
Index: /trunk/contrib/perryman/finger.lisp
===================================================================
--- /trunk/contrib/perryman/finger.lisp	(revision 13946)
+++ /trunk/contrib/perryman/finger.lisp	(revision 13946)
@@ -0,0 +1,180 @@
+;;;; -*- mode: lisp -*-
+;;;; Copyright (C) 2002-2003 Barry Perryman.
+;;;; 
+;;;; finger.lisp
+;;;; A simple finger client and server as specified by RFC 1288.
+;;;;
+;;;; Anyone who wants to use this code for any purpose is free to do so.
+;;;; In doing so, the user acknowledges that this code is provided "as is",
+;;;; without warranty of any kind, and that no other party is legally or
+;;;; otherwise responsible for any consequences of its use.
+;;;;
+;;;; Changes:
+;;;; 2003-xx-xx: General tidy up of code, especially the interface to the
+;;;;             server. Add some error handling. Update copyright.
+;;;;             Remove package.
+;;;; 2002-07-15: New processes are optional. The system can now forward on
+;;;;             nested queries onto other servers, which can be a security
+;;;;             risk, so by default this is not enabled.
+;;;;
+
+(defconstant +input-buffer-size+ 1024
+  "Size of the input buffer used by read-sequence.")
+
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;; Start off with a couple of utility functions
+(defun write-net-line (line stream)
+  "Write out the string line to the stream, terminating with CRLF."
+  (format stream "~a~c~c" line #\return #\linefeed))
+
+(defun read-net-line (stream)
+  "Read a line from stream."
+  (let ((line (make-array 10 :element-type 'character :adjustable t :fill-pointer 0)))
+    (do ((c (read-char stream nil nil) (read-char stream nil nil)))
+	((or (null c)
+	     (and (char= c #\return)
+		  (char= (peek-char nil stream nil nil) #\linefeed)))
+	 (progn
+	   (read-char stream nil nil)
+	   line))
+      (vector-push-extend c line))))
+
+(defmacro aif (test yes no)
+  `(let ((it ,test))
+    (if it
+	,yes
+	,no)))
+
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;; Finger client
+(defun %finger (host query port)
+  "Send query to host:port using the finger protocol, RFC 1288. Returns the output as a string."
+  (declare (ignore verbose))
+  (with-open-socket (net :remote-host host :remote-port port)
+    (write-net-line query net)
+    (force-output net)			; Doesn't seem to be needed, but just incase
+    (let ((inbuf (make-array +input-buffer-size+ :element-type 'character :initial-element #\space)))
+      (do* ((pos (read-sequence inbuf net) (read-sequence inbuf net))
+	    (output (subseq inbuf 0 pos) (concatenate 'string output (subseq inbuf 0 pos))))
+	   ((zerop pos) output)))))
+
+(defun finger (query &key (verbose nil) (port 79))
+  "Takes a query, in the same format as the unix command line tool and execute it."
+  (let (host
+	(host-query (if verbose "/W " "")))
+    (aif (position #\@ query :from-end t)
+	 (setf host (subseq query (1+ it))
+	       host-query (concatenate 'string host-query (subseq query 0 it)))
+	 (setf host query))
+    (%finger host host-query port)))
+
+;; For testing try:
+;; (where "some-host.com" is a host running a finger server):
+;;   (finger "some-host.com")
+;;   (finger "user@some-host.com") 
+
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;; Server code
+(defun finger-daemon (handler &key (port 79) (subqueries nil))
+  "Start up a listner on port that responds to the finger protocol"
+  (process-run-function (format nil "finger-daemon on port ~d" port)
+			#'%finger-daemon handler port subqueries))
+  
+(defun %finger-daemon (handler port subqueries)
+  "Specific implementation routine."
+  (with-open-socket (sock :type :stream :connect :passive :local-port port :reuse-address t)
+    (loop
+       (let ((insock (accept-connection sock)))
+	 (process-run-function "Finger request handler"
+			       #'%finger-daemon-handler handler insock subqueries)))))
+
+(defun %finger-daemon-handler (handler socket subqueries)
+  (let* ((line (read-net-line socket))
+	 (verbose (and (>= (length line) 3)
+		       (string= line "/W " :end1 3)))
+	 (proc-line (if verbose (subseq line 3) line))
+	 (req-sub (find #\@ line :test #'char=))
+	 (ret-str (cond ((and subqueries req-sub)
+			 (finger-forward-handler proc-line verbose))
+			(req-sub
+			 "Sub-Queries not supported.")
+			(t
+			 (funcall handler proc-line verbose)))))
+    (if (null ret-str)
+	(write-sequence "Unknown." socket)
+	(write-sequence ret-str socket))
+    (force-output socket)
+    (close socket)))
+
+(defun finger-forward-handler (line verbose)
+  "Handler for forwarding requests a third party"
+  (handler-bind ((error #'(lambda (c)
+			    (declare (ignore c))
+			    (return-from finger-forward-handler "Unable to process the request."))))
+    (finger line :verbose verbose)))
+
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;; Vending machine code, which becomes a simple server
+(defstruct vending
+  button
+  contents
+  description
+  price)
+
+(defparameter *vending-machine* nil
+  "Holds the data for the vending machine.")
+
+(defun populate-vending-machine (data)
+  "Takes a list of data in the format (button short-desc long-desc price) and turns it into a vending mahcine."
+  (setf *vending-machine* (mapcar #'(lambda (x)
+				      (destructuring-bind (b c d p) x
+					(make-vending :button b
+						      :contents c
+						      :description d
+						      :price p)))
+				  data)))
+
+(populate-vending-machine
+ '(("T1" "English Breakfast Tea" "Probably the best tea in the world." 1.0)
+   ("T2" "Earl Grey" "Well if you like the taste of washing up liquid..." 1.1)
+   ("T3" "Herbal Tea (Various)" "Smells great, tastes just like water." 0.80)
+   ("C1" "Cheap 'n' Nasty coffee." "It's awful, doesn't even taste like coffee." 0.50)
+   ("C2" "Freeze Dried Coffee." "Do yourself a favour and go to a coffee shop and get a real coffee." 1.0)
+   ("H1" "Hot Chocolate" "Carefull, this is so hot it'll cook your tastebuds." 1.0)))
+
+(defun vending-machine-details ()
+  (with-output-to-string (stream)
+    (format stream "~%Button~10,0TContents~50,4TPrice~%")
+    (format stream "-------------------------------------------------------~%")
+    (dolist (i *vending-machine*)
+      (format stream "~a~10,0T~a~50,4T~,2f~%"
+	      (vending-button i)
+	      (vending-contents i)
+	      (vending-price i)))))
+
+(defun specific-button-details (button)
+  "This write the specific information for the button"
+  (with-output-to-string (stream)
+    (let ((item (find button *vending-machine*
+		      :key #'vending-button
+		      :test #'string-equal)))
+      (cond ((null item)
+	     (format stream "Not available on this machine.~%"))
+	    (t
+	     (format stream "Button: ~a~50,0tPrice: ~,2f~%"
+		     (vending-button item)
+		     (vending-price item))
+	     (format stream "Contents: ~a~%"
+		     (vending-contents item))
+	     (format stream "Description: ~a~%"
+		     (vending-description item)))))))
+
+(defun process-vending-machine-command (command verbose)
+  "This is the vending machine."
+  (declare (ignore verbose))
+  (if (string= command "")
+      (vending-machine-details)
+      (specific-button-details command)))
+
+(defun vending-machine-demo (port)
+  (finger-daemon #'process-vending-machine-command :port port))
Index: /trunk/contrib/repenning/anticipat-symbol-complete.lisp
===================================================================
--- /trunk/contrib/repenning/anticipat-symbol-complete.lisp	(revision 13946)
+++ /trunk/contrib/repenning/anticipat-symbol-complete.lisp	(revision 13946)
@@ -0,0 +1,692 @@
+;;; -*- package: ccl -*-
+;*********************************************************************
+;*                                                                   *
+;*    PROGRAM     A N T I C I P A T O R Y   SYMBOL COMPLETE          *
+;*                                                                   *
+;*********************************************************************
+   ;* Author    : Alexander Repenning (alexander@agentsheets.com)    *
+   ;*             http://www.agentsheets.com                         *
+   ;* Copyright : (c) 1996-2008, AgentSheets Inc.                    *
+   ;* Filename  : anticipatory-symbol-complete.lisp                  *
+   ;* Updated   : 12/30/08                                           *
+   ;* Version   :                                                    *
+   ;*   1.0     : 06/19/04                                           *
+   ;*   1.0.1   : 07/04/04 Peter Paine: custom -color*, nil wait     *
+   ;*   1.0.2   : 07/07/04 correct position for fred-dialog-item     *
+   ;*   1.1     : 09/08/04 don't get stuck; args and space on tab    *
+   ;*   1.1.1   : 09/09/04 use *Package* if Fred has no package      *
+   ;*   1.2     : 09/17/04 limited support Traps package, #_blabla   *
+   ;*                      cannot find unloaded traps (most)         *
+   ;*   1.3     : 09/29/04 save-exit function to be image friendly   *
+   ;*   1.4     : 10/06/04 play nice with Glen Foy's Color-Coded     * 
+   ;*   1.4.1   : 10/21/04 handle $updateEvt                         *
+   ;*   1.4.2   : 12/14/04 XML "<..." and "</..." support            *
+   ;*   1.5     : 10/21/05 proactive typo alert                      *
+   ;*   1.5.1   : 08/25/06 use "..." instead of ellipsis char        *
+   ;*   1.5.2   : 09/22/06 works with LF EOL Fred buffers            *
+   ;*   1.5.3   : 08/14/07 symbol-completion-enabled-p method        *
+   ;*   1.5.4   : 10/24/07 handle Apple Events as kHighLevelEvent    *
+   ;*   2.0     : 04/22/08 Clozure CL, Gail Zacharias                *
+   ;*   2.0.1   : 04/25/08 auto enabled, release pool, process fix   *
+   ;*   2.0.2   : 12/30/08 kill processes when typing fast           *
+   ;* HW/SW     : G4,  CCL 1.2, OS X 10.5.2                          *
+   ;* Abstract  : Attempt symbol completion while user is typing.    *
+   ;*             #\tab to complete, show arglist if possible        *
+   ;*             #\esc to cancel                                    *
+   ;* Status    : good to go                                         *
+   ;* License   : LGPL                                               *
+   ;******************************************************************
+
+#+digitool (in-package :ccl)
+#+clozure (in-package :hemlock)
+
+(export '(symbol-completion-enabled-p *anticipatory-symbol-completion-enabled-p*))
+
+
+(defvar *Wait-Time-for-Anticipatory-Symbol-Complete* 0.2 "time in seconds to wait before anticipatory symbol complete begins to search.")
+
+(defvar *Anticipatory-Symbol-Completion-Enabled-p* t)
+
+(defvar *Anticipatory-Symbol-Completion-Font-Color* #+digitool *Gray-Color* #+clozure (#/grayColor ns:ns-color))
+
+(defvar *Anticipatory-Symbol-Completion-Background-Color*
+  #+digitool (make-color 55000 55000 64000)
+  #+clozure (gui::color-values-to-nscolor 55000/65535 55000/65535 64000/65535))
+
+(defvar *Zero-Completion-Hook* #+digitool #'ed-beep #+clozure #'beep "Call this function if there are no completions: could be the sign of a typo. Typically replace with more subtle sound.")
+
+;; Better enable these CCL compiler preferences to get more meaninglful arglists
+
+(eval-when (:compile-toplevel :load-toplevel :execute)
+  (unless ccl:*Save-Local-Symbols* (print "ANTICIPATORY SYMBOL COMPLETE hint: To get meaningful arglists for completed functions you should set ccl:*Save-Local-Symbols* to t"))
+  (unless ccl:*Fasl-Save-Local-Symbols* (print "ANTICIPATORY SYMBOL COMPLETE hint: To get meaningful arglists for completed functions you should set ccl:*Fasl-Save-Local-Symbols* to t")))
+
+;___________________________________ 
+; Completion Overlay Window         |
+;___________________________________ 
+
+(defvar *Assistant* nil)
+
+#+digitool (progn
+(defun COMPLETION-OVERLAY-WINDOW () "
+  Return current overlay window used for symbol completion. 
+  Create one if needed."
+  (or *Assistant*
+      (setq *Assistant*
+            (rlet ((&window :pointer)
+                   (&rect :rect :topleft #@(100 100) :bottomright #@(500 140)))
+              (#_CreateNewWindow #$kOverlayWindowClass 0 &rect &window)
+              (%get-ptr &window)))))
+
+
+(defun WAIT-FOR-TIME-OR-KEY-EVENT (Time)
+  (let ((Wakeup-Time (+ (get-internal-real-time) (* Time internal-time-units-per-second))))
+    (without-interrupts   ;; don't allow other threads to steal events
+     (loop
+       ;; timeout
+       (when (>= (get-internal-real-time) Wakeup-Time) (return))
+       (when (mouse-down-p) (return))
+       ;; poll for key events
+       (rlet ((Event :eventrecord))
+         (when (#_EventAvail #$everyEvent Event)
+           (case (rref Event :eventrecord.what)
+             ((#.#$keyDown #.#$keyUp #.#$autoKey)  ;; Key Event
+              (let ((Char (code-char (logand #$charCodeMask (rref Event :eventrecord.message)))))
+                (unless (char= Char #\null)
+                  (return Char))))
+             ((#.#$activateEvt #.#$osEvt #.#$mouseDown #.#$mouseUp #.#$updateEvt)  ;; Window activation or OS event
+              (#_getNextEvent #$everyEvent Event))
+             ;; let OS X handle this Apple Event as high level event
+             ;; http://developer.apple.com/documentation/AppleScript/Conceptual/AppleEvents/dispatch_aes_aepg/chapter_4_section_3.html
+             ;; listing 3-5
+             (#.#$kHighLevelEvent
+              (#_AEProcessAppleEvent Event))
+             (t 
+              ;; unexpected event: send email to Alex if this happens
+              (ed-beep)
+              (format t "unexpected event=~A (send email to Alex)" (rref Event :eventrecord.what))))))))))
+
+
+(defun SHOW-IN-OVERLAY-WINDOW (Text Position) "
+  in:  Text string, Position point.
+  out: Char char.
+  Show <Text> in overlay window at screen <Position>. 
+  Wait for key event or timeout.
+  In case of key event return char."
+  (let ((Window (completion-overlay-window)))
+    (#_MoveWindow Window (point-h Position) (point-v Position) t)
+    (#_ShowWindow window) 
+    (#_SetPort (#_GetWindowPort window))
+    ;; size of string?
+    (with-cfstrs ((string Text))
+      (rlet ((&ioBounds :point)
+             (&outBaseline :signed-integer))
+        (#_GetThemeTextDimensions 
+         String 
+         #$kThemeSmallSystemFont
+         #$kThemeStateActive
+         nil
+         &ioBounds
+         &outBaseline)
+        (let ((Text-Size (add-points (%get-point &ioBounds) #@(10 0))))
+          ;; paint background
+          (rlet ((&rect :rect :topleft #@(-10 1) :botright Text-Size))
+            (with-fore-color *Anticipatory-Symbol-Completion-Background-Color*
+              (#_PaintRoundRect &rect 12 12)))
+          ;; text
+          (rlet ((&rect :rect :topleft #@(1 0) :botright Text-Size))
+            (with-fore-color *Anticipatory-Symbol-Completion-Font-Color*
+              (#_DrawThemeTextBox
+               String
+               #$kThemeSmallSystemFont
+               #$kThemeStateActive
+               nil
+               &rect
+               #$teJustLeft
+               (%null-ptr)))))))
+    (#_QDFlushPortBuffer (#_GetWindowPort window) (%null-ptr))
+    (prog1
+      (wait-for-time-or-key-event 5)
+      (#_HideWindow window))))
+)
+
+#+clozure (progn
+(defclass completion-overlay (ns:ns-view)
+  ((text-attributes :foreign-type :id)
+   (text :foreign-type :id))
+  (:metaclass ns:+ns-object))
+
+(objc:defmethod (#/drawRect: :void) ((self completion-overlay) (rect :<NSR>ect))
+  (ccl::with-autorelease-pool 
+      (#/set (#/clearColor ns:ns-color))
+    (#_NSRectFill (#/bounds self))
+    (ns:with-ns-point (point 0 1)
+      (#/drawAtPoint:withAttributes: (slot-value self 'text)
+                                     point
+                                     (slot-value self 'text-attributes)))))
+
+(defun COMPLETION-OVERLAY-WINDOW () "
+  Return current overlay window used for symbol completion. 
+  Create one if needed."
+  (or *Assistant*
+      (setq *Assistant*
+            (ns:with-ns-rect (frame 100 100 400 40)
+              (let* ((w (make-instance 'ns:ns-window
+                          :with-content-rect frame
+                          :style-mask #$NSBorderlessWindowMask
+                          :backing #$NSBackingStoreBuffered
+                          :defer #$YES))
+                     (view (make-instance 'completion-overlay
+                             :with-frame (#/frame (#/contentView w))))
+                     ;; Create attributes to use in window
+                     (attribs (make-instance 'ns:ns-mutable-dictionary :with-capacity 3)))
+                (#/setObject:forKey: attribs (#/systemFontOfSize: ns:ns-font (#/smallSystemFontSize ns:ns-font))
+                                     #&NSFontAttributeName)
+                (#/setObject:forKey: attribs *Anticipatory-Symbol-Completion-Font-Color*
+                                     #&NSForegroundColorAttributeName)
+                (#/setObject:forKey: attribs *Anticipatory-Symbol-Completion-Background-Color*
+                                     #&NSBackgroundColorAttributeName)
+                (setf (slot-value view 'text-attributes) (#/retain attribs))
+                (setf (slot-value view 'text) (#/retain (gui::%make-nsstring "")))
+                (#/setContentView: w view)
+                ;; Set the background color to clear so that (along with the setOpaque call below)
+                ;; we can see through the parts of the window that we're not drawing into
+                (#/setBackgroundColor: w (#/clearColor ns:ns-color))
+                ;; No transparency for actual drawing into the window
+                (#/setAlphaValue: w (gui::cgfloat 1.0))
+                ;; Allow see through the parts of the window we're not drawing into
+                (#/setOpaque: w #$NO)
+                ;; Make it as unobtrusive as possible
+                (#/setIgnoresMouseEvents: w #$YES)
+                (#/setExcludedFromWindowsMenu: w #$YES)
+                (#/setHidesOnDeactivate: w #$YES)
+                w)))))
+
+
+(defun OPEN-OVERLAY-WINDOW (Text Position)
+  "Show text at screen position"
+  (ccl::with-autorelease-pool 
+      (let ((w (completion-overlay-window)))
+        (#/setFrameOrigin: w Position)
+        (let* ((w (completion-overlay-window))
+               (overlay (#/contentView w))
+               (nsstring (ccl::%make-nsstring Text)))
+          (with-slots (text) overlay
+            (#/release text)
+            (setf text (#/retain nsstring)))
+          (#/display w)
+          (#/orderFront: w ccl:+null-ptr+)))))
+
+(defun CLOSE-OVERLAY-WINDOW ()
+  "Hide the overlay window"
+  (let ((w (completion-overlay-window)))
+    (#/orderOut: w ccl:+null-ptr+)))
+)
+
+;___________________________________ 
+; Symbol String functions           |
+;___________________________________ 
+
+(defun COMMON-PREFIX (String1 String2)
+  ;; if one string is a complete substring then return it
+  (let ((Short-String (if (< (length String1) (length String2)) String1 String2)))
+    (dotimes (I (length Short-String) Short-String)
+      (let ((Char1 (char String1 i)))
+        (unless (char= Char1 (char String2 i))
+          (return (subseq Short-String 0 i)))))))
+    
+
+(defun LONGEST-PREFIX (Symbols)
+  (when Symbols
+    (reduce #'common-prefix (mapcar #'symbol-name Symbols))))
+
+
+;___________________________________ 
+; Cursor HPOS/VPOS Position fixes   |
+;___________________________________ 
+
+#+digitool
+(defmethod FRED-HPOS ((W listener-fred-item) &optional (Pos (buffer-position 
+                                                          (fred-buffer w))))
+  ;; Alice's listener HPOS fix
+  (let* ((Buf (fred-buffer w))
+         (Frec (frec w))
+         (End (buffer-line-end buf pos)))
+    (cond ((and (fr.wrap-p frec)
+                (eql end (buffer-size buf))
+                (> end 0))
+           (let* ((Start (buffer-line-start buf pos))
+                  (Res (%screen-line-hpos frec start pos end)))  ;; << was end end
+             ;(push (list res (fred-hpos w pos)) cow)
+             (+ res 0)))   ;; fudge epsilon
+          (t (fred-hpos w pos)))))
+
+
+#+digitool
+(defmethod FRED-HPOS ((Self fred-dialog-item) &optional (Pos (buffer-position (fred-buffer Self))))
+  ;; need to add dialog item in window offset
+  (declare (ignore Pos))
+  (+ (point-h (convert-coordinates #@(0 0) Self (view-window Self)))
+     (call-next-method)))
+
+
+#+digitool
+(defmethod FRED-VPOS ((Self fred-dialog-item) &optional (Pos (buffer-position (fred-buffer Self))))
+  ;; need to add dialog item in window offset
+  (declare (ignore Pos))
+  (+ (point-v (convert-coordinates #@(0 0) Self (view-window Self)))
+     (call-next-method)))
+
+;___________________________________ 
+; Completion-Request class          |
+;___________________________________ 
+
+(defclass COMPLETION-REQUEST ()
+  ((time-stamp :accessor time-stamp :initform (get-internal-real-time))
+   (completion-string :accessor completion-string :initform "" :initarg :completion-string)
+   (completion-name :accessor completion-name)
+   (completion-package :accessor completion-package)
+   #+clozure (completion-prefix :accessor completion-prefix :initform nil)
+   (fred-instance :accessor fred-instance :initarg :fred-instance)
+   (fred-buffer-start :accessor fred-buffer-start :initarg :fred-buffer-start)
+   (fred-buffer-end :accessor fred-buffer-end :initarg :fred-buffer-end))
+  (:documentation "captures what the request is, when it was made, and where is what made"))
+
+
+
+(defmethod INITIALIZE-INSTANCE :after ((Self completion-request) &rest Args)
+  (declare (ignore Args))
+  (let ((String (completion-string Self)))
+    ;; explore package clues
+    (when String
+      (setf (completion-name Self) 
+            (case (char String 0)
+              ((#\: #\#) (subseq (string-upcase String) 1))
+              (t (string-upcase String))))
+      (setf (completion-package Self) 
+            (or (and (char= (char String 0) #\:) (find-package :keyword))
+                (and (char= (char String 0) #\#) (find-package :traps))
+                #+digitool (window-package (fred-instance Self))
+                #+clozure (buffer-package (hemlock-view-buffer (fred-instance Self)))
+                *Package* )))))
+
+
+(defun ADD-SPECIAL-PACKAGE-PREFIX (String Package)
+  ;; some packages have a special prefix consisting of a single character
+  (cond
+   ((equal Package (find-package :keyword)) (format nil ":~A" String))
+   ((equal Package (find-package :traps)) (format nil "#~A" String))
+   (t String)))
+
+
+(defmethod PROMISING-PREFIX ((Thing string))
+  ;; heuristicly exclude
+  (and
+   (not (char-equal (char Thing 0) #\\))  ;; char names
+   (not (char-equal (char Thing 0) #\"))  ;; beginning of strings
+   (not (every ;; numbers
+         #'(lambda (Item)
+             (member Item '(#\0 #\1 #\2 #\3 #\4 #\5 #\6 #\7 #\8 #\9 #\d #\D #\s #\S #\e #\E #\. #\/)))
+         Thing))))
+
+#+clozure
+(defmethod completion-screen-position ((Self completion-request))
+  (let* ((view (fred-instance Self))
+         (charpos (mark-absolute-position (buffer-point (hemlock-view-buffer view))))
+         (tv (gui::text-pane-text-view (hi::hemlock-view-pane view))))
+    (multiple-value-bind (x y) (gui::charpos-xy tv charpos)
+      (ns:with-ns-point (pt x (+ y (gui::text-view-line-height tv)))
+        (#/convertBaseToScreen: (#/window tv)
+                                (#/convertPoint:toView: tv pt gui::+null-ptr+))))))
+
+#+clozure
+(defmethod view-active-p ((Self completion-request))
+  (not (ccl:%null-ptr-p (#/window (hi::hemlock-view-pane (fred-instance Self))))))
+
+#+clozure
+(defvar *Completion-Request* nil "Currently active completion request")
+
+
+(defmethod ANTICIPATORY-SYMBOL-COMPLETE ((Self completion-request)) "
+  in: Completion-Request completion-request.
+  Explore the opportunity for symbol completion."
+  (ccl::with-autorelease-pool
+      ;; don't be too eager and wait first a little
+      (sleep *Wait-Time-for-Anticipatory-Symbol-Complete*)
+    ;; find matching symbols
+    (let* ((Local-Symbols (apropos-list (completion-name Self) (completion-package Self)))
+           (Symbols (matching-prefix-symbols (completion-name Self) Local-Symbols))
+           #+digitool (Fred (fred-instance Self)))
+      ;; proactive typo alert
+      (when (and *Zero-Completion-Hook*
+                 (= (length Local-Symbols) 0)
+                 (promising-prefix  (completion-name Self)))
+        (funcall *Zero-Completion-Hook*))  ;; beep when the number has dropped to zero: usually a sign of a typo
+      ;; completion attempt
+      (let ((Prefix (longest-prefix Symbols)))
+        (when (and (> (length Prefix) (length (completion-name Self)))
+                   #+digitool (and (view-window Fred) ;; window may be gone by now!
+                                   (wptr (view-window Fred)))
+                   #+clozure (view-active-p Self))
+          #+digitool (setq *Show-Cursor-P* nil)
+          ;; if we made it this far we better complete things
+          #+digitool
+          (let* ((Extension (string-downcase (subseq Prefix (length (completion-name Self)))))
+                 (Char (show-in-overlay-window
+                        (if (find-symbol Prefix (completion-package Self))
+                          Extension
+                          (format nil "~A..." Extension))
+                        (add-points (add-points (view-position (view-window Fred)) #@(0 -10))
+                                    (make-point (fred-hpos Fred) (fred-vpos Fred))))))
+            (case Char
+              ;; Tab = accept completion but don't do Fred indentation spiel
+              (#\tab
+               (#_FlushEvents (logior #$keyDownMask #$keyUpMask) 0)   ;; avoid indentation
+               (buffer-replace-string
+                Fred
+                (fred-buffer-start Self)
+                (fred-buffer-end Self)
+                (add-special-package-prefix Prefix (completion-package Self))
+                (completion-string Self))
+               (when (find-symbol Prefix (completion-package Self)) 
+                 (without-interrupts  ;; not sure this helps, found cases in which ed-arglist can hang MCL: WHY??
+                  (ed-arglist Fred)))  ;; show arglist if possible
+               (fred-update Fred))))
+          #+clozure
+          (let* ((Extension (string-downcase (subseq Prefix (length (completion-name Self))))))
+            (unwind-protect
+                (progn
+                  (open-overlay-window (if (find-symbol Prefix (completion-package Self))
+                                         Extension
+                                         (format nil "~A..." Extension))
+                                       (completion-screen-position Self))
+                  (setf (completion-prefix Self) Prefix)
+                  ;; If the user types anything while the window is up, this process gets reset with *Completion-Request*
+                  ;; still set, so the Tab command can tell what the Prefix was.  
+                  (setq *Completion-Request* Self)
+                  (sleep 5)
+                  ;; timed out: forget completion request
+                  (setq *Completion-Request* nil))
+              (close-overlay-window)) ))))))
+
+;___________________________________ 
+; Process Management                |
+;___________________________________ 
+
+(defvar *Completion-Process* nil "process used to complete symbols in anticipatory way")
+
+
+(defun COMPLETION-PROCESS ()
+  (or *Completion-Process*
+      (setq *Completion-Process* (ccl:make-process "Anticipatory Symbol Complete" :priority 0 #+digitool :quantum #+digitool 1))))
+
+
+#+digitool
+(defun START-SYMBOL-COMPLETE-PROCESS (Request)
+  (ccl::process-preset (completion-process) #'(lambda ()
+						(setq *Completion-Request* nil)
+						(anticipatory-symbol-complete Request)))
+  (ccl::process-reset-and-enable (completion-process)))
+
+#+clozure
+(defun START-SYMBOL-COMPLETE-PROCESS (Request)
+  (when *Completion-Process*
+    ;; not sure how we get here: before a new completion process is started 
+    ;; the old should have been killed already
+    (ccl:process-kill *Completion-Process*))
+  (setq *Completion-Process*
+	(ccl::process-run-function 
+	 '(:name "Anticipatory Symbol Complete" :priority 0)
+	 #'(lambda () (anticipatory-symbol-complete Request)))))
+
+
+#+clozure
+(defun ABORT-SYMBOL-COMPLETE-PROCESS ()
+  (cond
+   ;; completion still going on
+   (*Completion-Process*
+    (ccl:process-kill *Completion-Process*)
+    (setq *Completion-Process* nil))
+   ;; completion must have timed out: remove completion request
+   (t
+    (setq *Completion-Request* nil))))
+
+;___________________________________ 
+; Symbol-Complete.lisp functions    |
+;___________________________________ 
+
+#+digitool
+(defmethod BUFFER-REPLACE-STRING ((Self fred-mixin) Start End String &optional Old-String) "
+  in:  Self {fred-mixin}, Start End {position}, String {string}, 
+       &optional Old-String {string}.
+  Delete the buffer content between <Start> and <End>, insert
+  <String> and place insertion marker to <End> position."
+  (let ((Mark (fred-buffer Self)))
+    (buffer-delete Mark Start End)
+    (buffer-insert 
+     Mark
+     (if Old-String
+       (case (string-format Old-String)
+         (:upper (string-upcase String))
+         (:lower (string-downcase String))
+         (:capital (string-capitalize String)))
+       String)))
+  ;; play nice with color-coded (when present)
+  (let ((Color-Code-Update-Function (find-symbol "DYNAMICALLY-STYLE-BUFFER" (find-package :cc))))
+    (when (fboundp Color-Code-Update-Function) (funcall Color-Code-Update-Function Self))))
+
+#+clozure
+(defun BUFFER-REPLACE-STRING (Start End String &optional Old-String) "
+  in: Start End {position}, String {string}, 
+       &optional Old-String {string}.
+  Delete the current buffer content between <Start> and <End>, insert
+  <String> and place insertion marker to <End> position."
+  (paste-characters Start (- End Start) 
+                    (if Old-String
+                      (case (string-format Old-String)
+                        (:upper (string-upcase String))
+                        (:lower (string-downcase String))
+                        (:capital (string-capitalize String)))
+                      String)))
+
+(defun STRING-FORMAT (String) "
+  in:  String {string}.
+  out: Capitalization {keyword} :upper, :lower :capital.
+  Return the capitalization status of a string"
+  (case (length String)
+    (0 :lower)
+    (1 (if (lower-case-p (char String 0)) :lower :upper))
+    (t (if (char= (char String 0) #\*)
+         (string-format (subseq String 1))
+         (if (upper-case-p  (char String 0))
+           (if (upper-case-p (char String 1))
+             :upper
+             :capital)
+           :lower)))))
+
+
+(defun MATCHING-PREFIX-SYMBOLS (String Symbols) "
+  in:  String {string}, Symbols {list of: {symbol}}.
+  out: Symbols {list of: {symbol}}.
+  Return only the symbols of which <String> is a prefix."
+  (let ((L (length String)))
+    (remove-if-not
+     #'(lambda (Symbol) (string= String (symbol-name Symbol) :end1 L :end2 L))
+     Symbols)))
+
+;___________________________________ 
+; FRED extensions                   |
+;___________________________________ 
+
+#+digitool
+(defun BUFFER-CURRENT-STRING (Buffer Position)
+  (when (< (buffer-size Buffer) 1) (return-from buffer-current-string))
+  (unless (char= (buffer-char Buffer Position) #\space)
+    (let ((Start Position)
+          (End Position)) 
+      ;; scan left for delimiter
+      (loop
+        (when (= Start 0) (return))
+        (case (buffer-char Buffer Start)
+          ((#\space #\return #\linefeed #\( #\) #\' #\<)
+           ;; special treatment for "<" versus "</" XML prefix 
+           (return (incf Start (if (char= (buffer-char Buffer (1+ Start)) #\/) 2 1)))))
+        (decf Start))
+      ;; scan right for delimiter
+      (loop
+        (when (= End (buffer-size Buffer)) (return))
+        (incf End)
+        (case (buffer-char Buffer End)
+          ((#\space #\return #\linefeed #\( #\)) (return))))
+      (values
+       (buffer-substring Buffer Start End)
+       Start
+       End))))
+
+#+clozure
+(defun BUFFER-CURRENT-STRING ()
+  (with-mark ((Start (current-point))
+              (End (current-point)))
+    (unless (eq (previous-character Start) #\space)
+      ;; scan left for delimiter
+      (loop
+        (case (previous-character Start)
+          ((nil #\space #\tab #\return #\linefeed #\( #\) #\' #\<)
+           ;; special treatment for "<" versus "</" XML prefix
+           (when (eq (next-character start) #\/)
+             (mark-after Start))
+           (return)))
+        (mark-before Start))
+      ;; scan right for delimiter
+      (loop
+        (case (next-character End)
+          ((nil #\space #\tab #\return #\linefeed #\( #\)) (return)))
+        (mark-after End))
+      (values (region-to-string (region Start End))
+              (mark-absolute-position Start)
+              (mark-absolute-position End)))))
+
+#+digitool (progn
+
+(defmethod SYMBOL-COMPLETION-ENABLED-P ((Self fred-mixin))
+  t)
+
+
+(defmethod ED-INSERT-CHAR :after ((Self fred-mixin) Char) "  
+  After typing a delimiter check if there is a link"
+  (unless (and *Anticipatory-Symbol-Completion-Enabled-P* (symbol-completion-enabled-p Self))
+    (return-from ed-insert-char))
+  (case Char
+    ;; user is done with current symbol: stop completion
+    ((#\space #\return)
+       (process-flush (completion-process)))
+    ;; new character part of current symbol
+    (t
+     (multiple-value-bind (String Start End)
+                          (buffer-current-string (fred-buffer Self) (- (buffer-position (fred-buffer Self)) 1))
+       (when (> (length String) 1)
+         (start-symbol-complete-process 
+          (make-instance 'completion-request 
+            :completion-string String
+            :fred-instance Self
+            :fred-buffer-start Start
+            :fred-buffer-end End)))))))
+)
+
+#+clozure (progn
+
+;; enable by default
+(add-hook make-buffer-hook
+                   #'(lambda (buffer)
+                       (setf (buffer-minor-mode buffer "Symbol Completion") t)))
+
+(defmode "Symbol Completion"
+  :documentation "This is a minor mode that provides anticipatory symbol completion")
+
+(defcommand "Symbol Completion Mode" (p)
+  "Toggles Symbol Completion mode in the current buffer"
+  (declare (ignore p))
+  (setf (buffer-minor-mode (current-buffer) "Symbol Completion")
+        (not (buffer-minor-mode (current-buffer) "Symbol Completion"))))
+
+(defhvar "Self Insert Command Name"
+  "Name of command to invoke for quoted insert in Symbol Completion mode"
+  :value "Self Insert With Symbol Completion"
+  :mode "Symbol Completion")
+
+(defcommand "Self Insert With Symbol Completion" (p)
+  "Self Insert and start up the completion process"
+  (self-insert-command p)
+  (when *Anticipatory-Symbol-Completion-Enabled-p*
+    (case (last-char-typed)
+      ((#\space #\newline) nil)
+      (t
+       (multiple-value-bind (String Start End) (buffer-current-string)
+         (when (> (length String) 1)
+           (handler-case (start-symbol-complete-process (make-instance 'completion-request
+                                                          :completion-string String
+                                                          :fred-instance (current-view)
+                                                          :fred-buffer-start start
+                                                          :fred-buffer-end end))
+             (t (Condition) (format t "condition: ~A" Condition)))))))))
+
+
+(dolist (c (command-bindings (getstring "Self Insert" *command-names*)))
+  (bind-key "Self Insert with Symbol Completion" (car c) :mode "Symbol Completion"))
+
+
+(defvar *Last-Hemlock-Key* nil "key last pressed in a hemlock view")
+
+
+(defmethod hi::execute-hemlock-key :before ((view hemlock-view) key)
+  (setq *Last-Hemlock-Key* Key)
+  (abort-symbol-complete-process))
+
+
+;; The :transparent-p flag causes this to do the usual binding for the key
+;; unless we explicitly invoke exit-event-handler.
+(defcommand ("Maybe Insert Symbol Completion" :transparent-p t) (p)
+  "Insert symbol completion if there is one, otherwise do the usual action"
+  (declare (ignore p))
+  (let* ((Request *Completion-Request*)
+         (Prefix (and Request (completion-prefix Request))))
+    (when Prefix
+      (buffer-replace-string (fred-buffer-start request)
+                             (fred-buffer-end request)
+                             (add-special-package-prefix Prefix (completion-package Request))
+                             (completion-string Request))
+      (when (find-symbol Prefix (completion-package Request))
+        (current-function-arglist-command nil))
+      (hi::exit-event-handler))))
+
+(bind-key "Maybe Insert Symbol Completion" #k"Tab" :mode "Symbol Completion")
+
+)
+
+;___________________________________ 
+; save-application support          |
+;___________________________________ 
+
+(defun ANTICIPATORY-SYMBOL-COMPLETE-SAVE-EXIT-FUNCTION ()
+  (setq *Assistant* nil)
+  (when *Completion-Process*
+    (ccl:process-kill *Completion-Process*)
+    (setq *Completion-Process* nil)))
+  
+
+(eval-when (:compile-toplevel :load-toplevel :execute)
+  (pushnew 'anticipatory-symbol-complete-save-exit-function ccl:*Save-Exit-Functions*))
+ 
+
+#| Examples:
+
+(time (common-prefix "WITH-OPEN-FILE" "WITH-CLOSED-HOUSE"))
+
+(time (common-prefix "WITH-OPEN-FILE" "WITH-OPEN-FILENAME"))
+
+(time (common-prefix "WITH-OPEN-FILE" "WITH-OPEN-FILE"))
+
+
+
+|#
+
Index: /trunk/contrib/rittweiler/ccl
===================================================================
--- /trunk/contrib/rittweiler/ccl	(revision 13946)
+++ /trunk/contrib/rittweiler/ccl	(revision 13946)
@@ -0,0 +1,77 @@
+#!/bin/sh
+#
+# Change the definition of CCL_DEFAULT_DIRECTORY below to refer to
+# your Clozure CL installation directory.  
+# Any definition of CCL_DEFAULT_DIRECTORY already present in the environment 
+# takes precedence over definitions made below.
+
+probe()
+{
+    if [ -e "$1"  -a  -e "$1/scripts/ccl" ]; then
+        CCL_DEFAULT_DIRECTORY="$1"
+    fi
+}
+
+if [ -z "$CCL_DEFAULT_DIRECTORY"  -a  -n "`which readlink`" ]; then
+    dir="`readlink $0`"
+    probe "${dir%/scripts/ccl}"
+fi
+
+if [ -z "$CCL_DEFAULT_DIRECTORY" ]; then
+    probe "`pwd`"
+fi
+
+if [ -z "$CCL_DEFAULT_DIRECTORY" ]; then
+    probe "/usr/local/src/ccl"
+fi
+
+if [ -z "$CCL_DEFAULT_DIRECTORY" ]; then
+    echo "Can't find CCL directory.  Please edit $0 or"
+    echo "set the environment variable CCL_DEFAULT_DIRECTORY"
+    echo "and try again."
+    exit 1
+fi
+
+export CCL_DEFAULT_DIRECTORY
+
+# This is shorter (& easier to type), making the invocation below
+# a little easier to read.
+
+DD=${CCL_DEFAULT_DIRECTORY}
+
+# If you don't want to guess the name of the Clozure CL kernel on
+# every invocation (or if you want to use a kernel with a
+# non-default name), you might want to uncomment and change
+# the following line:
+#OPENMCL_KERNEL=some_name
+
+# Set the CCL_DEFAULT_DIRECTORY  environment variable; 
+# the lisp will use this to setup translations for the CCL: logical host.
+
+if [ -z "$OPENMCL_KERNEL" ]; then
+  case `uname -s` in
+    Darwin) case `arch` in
+              ppc*) OPENMCL_KERNEL=dppccl ;;
+              i386) OPENMCL_KERNEL=dx86cl ;;
+            esac ;;
+    Linux) case `uname -m` in
+              ppc*) OPENMCL_KERNEL=ppccl ;;
+              *86*) OPENMCL_KERNEL=lx86cl ;;
+           esac ;;
+    CYGWIN*)
+       OPENMCL_KERNEL=wx86cl.exe
+       CCL_DEFAULT_DIRECTORY="C:/cygwin$CCL_DEFAULT_DIRECTORY"
+    ;;
+    SunOS) OPENMCL_KERNEL=sx86cl
+    ;;
+    FreeBSD) OPENMCL_KERNEL=fx86cl
+    ;;
+    *)
+    echo "Can't determine host OS.  Fix this."
+    exit 1
+    ;;
+  esac
+fi
+
+exec ${DD}/${OPENMCL_KERNEL} "$@"
+
Index: /trunk/contrib/rittweiler/ccl64
===================================================================
--- /trunk/contrib/rittweiler/ccl64	(revision 13946)
+++ /trunk/contrib/rittweiler/ccl64	(revision 13946)
@@ -0,0 +1,109 @@
+#!/bin/sh
+#
+# Change the definition of CCL_DEFAULT_DIRECTORY below to refer to
+# your Clozure CL installation directory.  
+# Any definition of CCL_DEFAULT_DIRECTORY already present in the environment 
+# takes precedence over definitions made below.
+
+probe()
+{
+    if [ -e "$1"  -a  -e "$1/scripts/ccl64" ]; then
+        CCL_DEFAULT_DIRECTORY="$1"
+    fi
+}
+
+if [ -z "$CCL_DEFAULT_DIRECTORY"  -a  -n "`which readlink`" ]; then
+    dir="`readlink $0`"
+    probe "${dir%/scripts/ccl64}"
+fi
+
+if [ -z "$CCL_DEFAULT_DIRECTORY" ]; then
+    probe "`pwd`"
+fi
+
+if [ -z "$CCL_DEFAULT_DIRECTORY" ]; then
+    probe "/usr/local/src/ccl"
+fi
+
+if [ -z "$CCL_DEFAULT_DIRECTORY" ]; then
+    echo "Can't find CCL directory.  Please edit $0 or"
+    echo "set the environment variable CCL_DEFAULT_DIRECTORY"
+    echo "and try again."
+    exit 1
+fi
+
+# This is shorter (& easier to type), making the invocation below
+# a little easier to read.
+
+DD=${CCL_DEFAULT_DIRECTORY}
+
+# If you don't want to guess the name of the Clozure CL kernel on
+# every invocation (or if you want to use a kernel with a
+# non-default name), you might want to uncomment and change
+# the following line:
+#OPENMCL_KERNEL=some_name
+
+# Set the CCL_DEFAULT_DIRECTORY  environment variable; 
+# the lisp will use this to setup translations for the CCL: logical host.
+
+if [ -z "$OPENMCL_KERNEL" ]; then
+  case `uname -s` in
+    Darwin)
+    case `arch` in
+      ppc*)
+      OPENMCL_KERNEL=dppccl64
+      ;;
+      i386|x86_64)
+      OPENMCL_KERNEL=dx86cl64
+      ;;
+    esac
+    ;;
+    Linux)
+    case `uname -m` in
+      ppc64)
+      OPENMCL_KERNEL=ppccl64
+      ;;
+      x86_64)
+      OPENMCL_KERNEL=lx86cl64
+      ;;
+      *)
+      echo "Can't determine machine architecture.  Fix this."
+      exit 1
+      ;;
+    esac
+    ;;
+    FreeBSD)
+    case `uname -m` in
+      amd64)
+      OPENMCL_KERNEL=fx86cl64
+      ;;
+      *)
+      echo "unsupported architecture"
+      exit 1
+      ;;
+    esac
+    ;;
+    SunOS)
+    case `uname -m` in
+      i86pc)
+      OPENMCL_KERNEL=sx86cl64
+      ;;
+      *)
+      echo "unsupported architecture"
+      exit 1
+      ;;
+    esac
+    ;;
+    CYGWIN*)
+    OPENMCL_KERNEL=wx86cl64.exe
+    CCL_DEFAULT_DIRECTORY="C:/cygwin$CCL_DEFAULT_DIRECTORY"
+    ;;
+    *)
+    echo "Can't determine host OS.  Fix this."
+    exit 1
+    ;;
+  esac
+fi
+
+CCL_DEFAULT_DIRECTORY=${DD} exec ${DD}/${OPENMCL_KERNEL} "$@"
+
