;;; -*- Mode: Lisp -*-

;;;  (c) copyright 1998,1999,2000 by Michael McDonald (mikemac@mikemac.com)
;;;  (c) copyright 2000 by 
;;;           Robert Strandh (strandh@labri.u-bordeaux.fr)
;;;  (c) copyright 2005-2006 by
;;;	      Andreas Fuchs (asf@boinkor.net)
;;;
;;; This library is free software; you can redistribute it and/or
;;; modify it under the terms of the GNU Library General Public
;;; License as published by the Free Software Foundation; either
;;; version 2 of the License, or (at your option) any later version.
;;;
;;; This library is distributed in the hope that it will be useful,
;;; but WITHOUT ANY WARRANTY; without even the implied warranty of
;;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
;;; Library General Public License for more details.
;;;
;;; You should have received a copy of the GNU Library General Public
;;; License along with this library; if not, write to the 
;;; Free Software Foundation, Inc., 59 Temple Place - Suite 330, 
;;; Boston, MA  02111-1307  USA.


;;; Really, I wouldn't bother with anything but ASDF. Almost every lisp
;;; ships with it, and it has the added benefit of ASDF-INSTALL.
;;; Get ASDF, and be welcome to the 21st century. -- [2005-01-31:asf]

(cl:defpackage :mcclim.system
  (:use :asdf :cl)
  (:export #:mp #:fix #:dep-on-swank #:ifswank #:*clim-directory*
           #:mcclim-cl-source-file))
(in-package :mcclim.system)

(defparameter *clim-directory* (directory-namestring *load-truename*))

;;; Legacy CMUCL support stuff
#+cmu
(progn
  (unless (fboundp 'ext:stream-read-char)
    (unless (ignore-errors (ext:search-list "gray-streams:"))
      (setf (ext:search-list "gray-streams:")
	'("target:pcl/" "library:subsystems/")))
    (if (fboundp 'extensions:without-package-locks)
	(extensions:without-package-locks
	 (load "gray-streams:gray-streams-library"))
      (load "gray-streams:gray-streams-library")))
  #-clx
  (require :clx)
  #+mp (when (eq mp::*initial-process* mp::*current-process*)
	 (format t "~%~%You need to run (mp::startup-idle-and-top-level-loops) to start up the multiprocessing support.~%~%")))

;;; Make CLX asdf-loadable on Allegro 6.2
;;; possibly this should be further refined to funciton properly for
;;; Allegro on Windows platforms. [2005/04/18:rpg]
#+allegro
(progn
  (defclass requireable-system (asdf:system)
       ())
  (defmethod asdf:perform ((op asdf:load-op) (system requireable-system))
    (require (intern (slot-value system 'asdf::name) :keyword)))
  (defmethod asdf::traverse ((op asdf:load-op) (system requireable-system))
    (list (cons op system)))  
  (defsystem :clx
    :class requireable-system))

(defmacro clim-defsystem ((module &key depends-on) &rest components)
  `(progn
     (asdf:defsystem ,module
	 ,@(and depends-on
		`(:depends-on ,depends-on))
	 :serial t
	 :components
	 (,@(loop for c in components
		  for p = (merge-pathnames
			   (parse-namestring c)
			   (make-pathname :type "lisp"
					  :defaults *clim-directory*))
		  collect `(:file ,(namestring p) :pathname ,p))))))

(eval-when (:compile-toplevel :execute :load-toplevel)
  (defun fix (&optional (prefix "Lisp-Dep/"))
    (concatenate 'string prefix
                 #+cmu       "fix-cmu"
                 #+scl       "fix-scl"
                 #+excl      "fix-acl"
                 #+sbcl      "fix-sbcl"
                 #+openmcl   "fix-openmcl"
                 #+lispworks "fix-lispworks"
                 #+clisp     "fix-clisp"))
  (defun mp (&optional (prefix "Lisp-Dep/"))
    (concatenate 'string prefix
                 (first '(#+(and :cmu :mp (not :pthread))  "mp-cmu"
                          #+scl                     "mp-scl"
                          #+sb-thread               "mp-sbcl"
                          #+excl                    "mp-acl"
                          #+openmcl                 "mp-openmcl"
                          #+lispworks               "mp-lw"
                          #| fall back |#           "mp-nil"))))
  (defun find-swank-system ()
    (handler-case (asdf:find-system :swank)
      (asdf:missing-component ())))
  (defun ifswank ()
    (if (find-swank-system)
        '(:and)
        '(:or)))) 

(defclass mcclim-cl-source-file (asdf:cl-source-file) ())

(defsystem :clim
  :depends-on (:spatial-trees :flexichain)
  :default-component-class mcclim-cl-source-file
  :components
  #.(let ((component-file (merge-pathnames #p"clim-components.lisp-expr"
                                           *clim-directory*)))
      (when (probe-file component-file)
        (with-open-file (f component-file :direction :input)
          (read f)))))

(defsystem :drei-tests
  :depends-on (:clim :fiveam)
  :components
  ((:module "Tests"
            :pathname #.(make-pathname :directory '(:relative "Drei" "Tests"))
            :components 
            ((:module
              "cl-automaton"
              :depends-on ("testing")
              :components
              ((:file "eqv-hash-tests")
               (:file "state-and-transition-tests")
               (:file "automaton-tests")
               (:file "regexp-tests")))
             (:file "packages")
             (:file "testing" :depends-on ("packages"))
             (:file "buffer-tests" :depends-on ("testing"))
             (:file "base-tests" :depends-on ("testing"))
             (:file "kill-ring-tests" :depends-on ("testing"))
             (:file "motion-tests" :depends-on ("testing"))
             (:file "editing-tests" :depends-on ("testing"))
             (:file "core-tests" :depends-on ("testing"))
             (:file "buffer-streams-tests" :depends-on ("testing"))
             (:file "rectangle-tests" :depends-on ("testing"))
             (:file "undo-tests" :depends-on ("testing"))
             (:file "lisp-syntax-tests" :depends-on ("testing"))))))

(defsystem :clim-clx
    :depends-on (:clim #+(or sbcl openmcl ecl allegro) :clx)
    :components
    ((:module "Backends/CLX"
              :pathname #.(make-pathname :directory '(:relative "Backends" "CLX"))
              :components
              ((:file "package")
               (:file "image" :depends-on ("package"))
               (:file "keysyms-common" :depends-on ("package"))
               (:file "keysyms" :depends-on ("keysyms-common" "package"))
               (:file "keysymdef" :depends-on ("keysyms-common" "package"))
               (:file "port" :depends-on ("keysyms-common" "keysyms" "package"))
               (:file "medium" :depends-on ("port" "keysyms" "package"))
               (:file "graft" :depends-on ("port" "package"))
               (:file "frame-manager" :depends-on ("medium" "port" "package"))))))

(defsystem :clim-null
    :depends-on (:clim)
    :components
    ((:module "Backends/Null"
	      :pathname #.(make-pathname :directory '(:relative "Backends" "Null"))
	      :components
	      ((:file "package")
	       (:file "port" :depends-on ("package"))
	       (:file "medium" :depends-on ("port" "package"))
	       (:file "graft" :depends-on ("port" "package"))
	       (:file "frame-manager" :depends-on ("medium" "port" "package"))))))

;;; TODO/asf: I don't have the required libs to get :clim-opengl to load. tough.
(clim-defsystem (:clim-opengl :depends-on (:clim))
   "Backends/OpenGL/opengl-x-frame-manager"
   "Backends/OpenGL/opengl-frame-manager"
   "Backends/OpenGL/opengl-x-port-before"
   "Backends/OpenGL/opengl-port"
   "Backends/OpenGL/opengl-x-port-after"
   "Backends/OpenGL/opengl-medium"
   "Backends/OpenGL/opengl-x-graft")

;;; A system that loads the appropriate backend for the current
;;; platform.
(defsystem :clim-looks
    :depends-on (:clim
                 ;; If we're on an implementation that ships CLX, use
                 ;; it. Same if the user has loaded CLX already.
                 #+(or sbcl scl openmcl ecl clx allegro) :clim-clx
                 #+gl                        :clim-opengl
                 ;; OpenMCL and MCL support the beagle backend (native
                 ;; OS X look&feel on OS X).

                 ;; But until it's ready, it's no use forcing users to
                 ;; cope with possible bugs.
                 ;; #+(or openmcl mcl)          :clim-beagle

		 ;; null backend
		 :clim-null
                 )
    :components ((:file "Looks/pixie"
                        :pathname #.(make-pathname :directory '(:relative "Looks") :name "pixie" :type "lisp"))))

(defsystem :drei-swank-add-ons
  :depends-on (:swank :clim)
  :components ((:file "lisp-syntax-swank"
                      :pathname #.(make-pathname :directory '(:relative "Drei")
                                                 :name "lisp-syntax-swank"
                                                 :type "lisp"))))

;;; The actual McCLIM system that people should to use in their ASDF
;;; package dependency lists.
(defsystem :mcclim
    :depends-on (:clim-looks #+#.(mcclim.system:ifswank):drei-swank-add-ons))

(defmethod perform :after ((op load-op) (c (eql (find-system :clim))))
  (pushnew :clim *features*)
  (pushnew :mcclim *features*))

(defmethod perform :around (op (c mcclim-cl-source-file))
  (let ((*features* (adjoin :building-mcclim *features*)))
    (call-next-method)))