├── version.lisp-expr ├── package.lisp ├── weblocks-bootstrap-date-entry-presentation-tests.asd ├── weblocks-bootstrap-date-entry-presentation.asd ├── README.txt ├── tests.lisp ├── weblocks-bootstrap-date-entry-presentation.lisp └── license.txt /version.lisp-expr: -------------------------------------------------------------------------------- 1 | "0.2.2" 2 | -------------------------------------------------------------------------------- /package.lisp: -------------------------------------------------------------------------------- 1 | ;;;; package.lisp 2 | 3 | (defpackage #:weblocks-bootstrap-date-entry-presentation 4 | (:use #:cl #:weblocks #:weblocks-util) 5 | (:export :bootstrap-date-parser :bootstrap-date-entry-presentation :*datepicker-locale-file)) 6 | 7 | -------------------------------------------------------------------------------- /weblocks-bootstrap-date-entry-presentation-tests.asd: -------------------------------------------------------------------------------- 1 | ;;;; weblocks-bootstrap-date-entry-presentation-tests.asd 2 | 3 | (asdf:defsystem #:weblocks-bootstrap-date-entry-presentation-tests 4 | :serial t 5 | :version "0.0.2" 6 | :description "Tests for weblocks-bootstrap-date-entry-presentation" 7 | :author "Olexiy Zamkoviy " 8 | :license "LLGPL" 9 | :depends-on (#:weblocks-bootstrap-date-entry-presentation #:weblocks-selenium-tests #:weblocks-utils #:weblocks-twitter-bootstrap-application-tests) 10 | :components ((:file "tests"))) 11 | 12 | -------------------------------------------------------------------------------- /weblocks-bootstrap-date-entry-presentation.asd: -------------------------------------------------------------------------------- 1 | ;;;; weblocks-bootstrap-date-entry-presentation.asd 2 | 3 | (asdf:defsystem #:weblocks-bootstrap-date-entry-presentation 4 | :serial t 5 | :version (:read-from-file "version.lisp-expr") 6 | :description "Bootstrap date/time picker form presentation for weblocks" 7 | :author "Olexiy Zamkoviy " 8 | :license "LLGPL" 9 | :depends-on (#:weblocks 10 | #:yaclml 11 | #:parenscript 12 | #:metatilities 13 | #:weblocks-utils) 14 | :components ((:file "package") 15 | (:file "weblocks-bootstrap-date-entry-presentation"))) 16 | 17 | -------------------------------------------------------------------------------- /README.txt: -------------------------------------------------------------------------------- 1 | This is bootstrap date entry presentation for weblocks. 2 | 3 | It gives you ability to use bootstrap date entry component https://github.com/eternicode/bootstrap-datepicker 4 | and time entry component from here https://github.com/jdewit/bootstrap-timepicker 5 | 6 | To use it you should load package :weblocks-bootstrap-date-entry-presentation from weblocks app and use it in your defview body like this 7 | 8 | (pub-date 9 | :label "Publication date" 10 | :present-as bootstrap-date-entry 11 | :reader (lambda(item) 12 | (firephp:fb "Editing item ~A" item) 13 | (or 14 | (slot-value item 'pub-date) 15 | (get-universal-time))) 16 | :parse-as bootstrap-date) 17 | 18 | Package uses weblocks assets so all dependencies should be installed automatically. 19 | -------------------------------------------------------------------------------- /tests.lisp: -------------------------------------------------------------------------------- 1 | (defpackage #:weblocks-bootstrap-date-entry-presentation-tests 2 | (:use #:cl #:weblocks 3 | #:weblocks-selenium-tests 4 | #:selenium 5 | #:weblocks-utils 6 | #:weblocks-bootstrap-date-entry-presentation 7 | #:weblocks-twitter-bootstrap-application-tests) 8 | (:import-from :weblocks-bootstrap-date-entry-presentation #:with-yaclml)) 9 | 10 | (in-package :weblocks-bootstrap-date-entry-presentation-tests) 11 | 12 | (defmacro date-entry-action (caption presentation) 13 | `(lambda (&rest args) 14 | (let ((widget (make-instance 'composite))) 15 | (setf 16 | (composite-widgets widget) 17 | (list 18 | (make-quickform 19 | (defview 20 | nil 21 | (:caption ,caption :type form :persistp nil :enctype "multipart/form-data" :use-ajax-p t) 22 | (date 23 | :present-as ,presentation 24 | :parse-as bootstrap-date)) 25 | :answerp nil 26 | :on-success (lambda/cc (form result) 27 | (let ((date (slot-value result 'date))) 28 | (do-information (format nil "Parsed date result is ~A" 29 | (if date 30 | (format nil "~A, which is date ~A" 31 | date (metatilities:format-date "%d.%m.%Y %I:%M:%S %p" date)) 32 | date)))))) 33 | (lambda (&rest args) 34 | (render-link (lambda (&rest args) 35 | (answer widget t)) "back")))) 36 | (do-page widget)))) 37 | 38 | (defun bootstrap-date-entry-demonstration-action (&rest args) 39 | (let ((render-links)) 40 | (setf render-links (make-widget 41 | (lambda (&rest args) 42 | (with-yaclml 43 | (<:h1 "Date entry demos") 44 | (<:hr) 45 | (render-link 46 | (date-entry-action "Input with bootstrap date entry" bootstrap-date-entry) 47 | "Default configuration (date, time without seconds showing)") 48 | (<:br) 49 | (render-link 50 | (date-entry-action "Input with bootstrap date entry with seconds showing" (bootstrap-date-entry :show-seconds-p t)) 51 | "Date and time with seconds showing") 52 | (<:br) 53 | (render-link 54 | (date-entry-action "Input with bootstrap date entry without time showing" (bootstrap-date-entry :show-time-p nil)) 55 | "Date only (without time showing)") 56 | (<:br) 57 | (render-link 58 | (date-entry-action "Date entry with custom datepicker options" 59 | (bootstrap-date-entry 60 | :datepicker-options (list :autoclose t 61 | :format "dd.mm.yyyy" 62 | "startView" 2) 63 | :show-time-p nil)) 64 | "Date with custom datepicker options") 65 | (<:br) 66 | (render-link 67 | (date-entry-action "Date entry with default date set" 68 | (bootstrap-date-entry 69 | :default-date "1970-01-01" 70 | :show-time-p nil)) 71 | "Date with custom initial date") 72 | (<:hr) 73 | (render-link (lambda (&rest args) 74 | (answer render-links)) 75 | "back"))))) 76 | (do-page render-links))) 77 | 78 | (define-bootstrap-demo-action "Date entry demos" #'bootstrap-date-entry-demonstration-action) 79 | 80 | (def-test-suite weblocks-bootstrap-date-entry-presentation-tests) 81 | 82 | (deftest shows-date-entry () 83 | (with-new-or-existing-selenium-session-on-bootstrap-site 84 | (do-click-and-wait "link=Date entry demos") 85 | (do-click-and-wait "link=Default configuration (date, time without seconds showing)") 86 | (do-screen-state-test "bootstrap/date-entry") 87 | (do-click-and-wait "name=submit") 88 | (is (string= (do-get-text "css=.modal-body") "Parsed date result is NIL")))) 89 | 90 | (deftest parses-date-entry-with-default-params () 91 | (with-new-or-existing-selenium-session-on-bootstrap-site 92 | (do-click-and-wait "link=Date entry demos") 93 | (do-click-and-wait "link=Default configuration (date, time without seconds showing)") 94 | (do-click-and-wait "name=date[date]") 95 | (do-click-and-wait "css=td:contains(10)") 96 | (do-click-and-wait "css=.bootstrap-timepicker-component .add-on") 97 | (do-click-and-wait "css=.show-meridian a:first") 98 | (do-click-and-wait "name=submit") 99 | (is 100 | (integerp (ppcre:scan 101 | (format nil "which is date ~A 02:00:00 AM" (metatilities:format-date "10.%m.%Y" (get-universal-time))) 102 | (do-get-text "css=.modal-body")))))) 103 | 104 | (deftest parses-date-entry-with-seconds-showing () 105 | (with-new-or-existing-selenium-session-on-bootstrap-site 106 | (do-click-and-wait "link=Date entry demos") 107 | (do-click-and-wait "link=Date and time with seconds showing") 108 | (do-click-and-wait "name=date[date]") 109 | (do-click-and-wait "css=td:contains(10)") 110 | (do-click-and-wait "css=.bootstrap-timepicker-component .add-on") 111 | (do-click-and-wait "css=.show-meridian a:nth(2)") 112 | (do-click-and-wait "name=submit") 113 | (is 114 | (integerp (ppcre:scan 115 | (format nil "which is date ~A 01:00:15 AM" 116 | (metatilities:format-date "10.%m.%Y" (get-universal-time))) 117 | (do-get-text "css=.modal-body")))))) 118 | 119 | (deftest parses-date-entry-without-time-showing () 120 | (with-new-or-existing-selenium-session-on-bootstrap-site 121 | (do-click-and-wait "link=Date entry demos") 122 | (do-click-and-wait "link=Date only (without time showing)") 123 | (do-click-and-wait "name=date[date]") 124 | (do-click-and-wait "css=td:contains(10)") 125 | (do-click-and-wait "name=submit") 126 | (is 127 | (integerp (ppcre:scan 128 | (format nil "which is date ~A 12:00:00 AM" 129 | (metatilities:format-date "10.%m.%Y" (get-universal-time))) 130 | (do-get-text "css=.modal-body")))))) 131 | 132 | (deftest parses-date-entry-with-custom-datepicker-options () 133 | (with-new-or-existing-selenium-session-on-bootstrap-site 134 | (do-click-and-wait "link=Date entry demos") 135 | (do-click-and-wait "link=Date with custom datepicker options") 136 | (do-click-and-wait "name=date[date]") 137 | (do-click-and-wait "css=.year.active") 138 | (do-click-and-wait "css=.month:first") 139 | (do-click-and-wait "css=td:contains(10):first") 140 | (do-click-and-wait "name=submit") 141 | (is 142 | (integerp (ppcre:scan 143 | (format nil "which is date ~A 12:00:00 AM" 144 | (metatilities:format-date "10.01.%Y" (get-universal-time))) 145 | (do-get-text "css=.modal-body")))))) 146 | 147 | (deftest parses-date-entry-with-custom-initial-date () 148 | (with-new-or-existing-selenium-session-on-bootstrap-site 149 | (do-click-and-wait "link=Date entry demos") 150 | (do-click-and-wait "link=Date with custom initial date") 151 | (do-click-and-wait "name=date[date]") 152 | (do-click-and-wait "css=td:contains(10):first") 153 | (do-click-and-wait "name=submit") 154 | (is 155 | (integerp (ppcre:scan 156 | (format nil "which is date ~A 12:00:00 AM" "10.01.1970") 157 | (do-get-text "css=.modal-body")))))) 158 | -------------------------------------------------------------------------------- /weblocks-bootstrap-date-entry-presentation.lisp: -------------------------------------------------------------------------------- 1 | ;;;; weblocks-bootstrap-date-entry-presentation.lisp 2 | 3 | (in-package #:weblocks-bootstrap-date-entry-presentation) 4 | 5 | (defmacro with-yaclml (&body body) 6 | "A wrapper around cl-yaclml with-yaclml-stream macro." 7 | `(yaclml:with-yaclml-stream *weblocks-output-stream* 8 | ,@body)) 9 | 10 | (defclass bootstrap-date-parser (date-parser) 11 | ()) 12 | 13 | (defmethod parse-view-field-value ((parser date-parser) value obj 14 | (view form-view) (field form-view-field) &rest args) 15 | (declare (ignore args)) 16 | (let* ((name (attributize-name (view-field-slot-name field))) 17 | (date (request-parameter (format nil "~A[date]" name))) 18 | (time (request-parameter (format nil "~A[time]" name))) 19 | (hour)) 20 | (multiple-value-bind (date-matched date-elements) (cl-ppcre:scan-to-strings "(\\d+)\\.(\\d+)\\.(\\d+)" date) 21 | (when (not date-matched) 22 | (return-from parse-view-field-value (values t nil nil))) 23 | (setf date-elements (loop for i across date-elements collect (parse-integer i))) 24 | 25 | (multiple-value-bind (time-matched time-elements) (cl-ppcre:scan-to-strings "^(\\d+):(\\d+)(:(\\d+))?\\s(AM|PM)$" time) 26 | 27 | (unless time-matched 28 | (setf time-elements #("0" "0" "0" "0" "AM"))) 29 | 30 | (setf hour (+ (parse-integer (aref time-elements 0)) 31 | (if (string= (aref time-elements 4) "PM") 32 | 12 33 | 0))) 34 | 35 | (cond 36 | ((= hour 24) 37 | (setf hour 12)) 38 | ((= hour 12) 39 | (setf hour 0))) 40 | 41 | (values t t 42 | (eval `(encode-universal-time 43 | ,(if (aref time-elements 3) 44 | (parse-integer (aref time-elements 3)) 45 | 0) 46 | ,(parse-integer (aref time-elements 1)) 47 | ,hour 48 | ,@date-elements))))))) 49 | 50 | (defclass bootstrap-date-entry-presentation (date-entry-presentation) 51 | ((show-time-p :initform t 52 | :initarg :show-time-p 53 | :accessor bootstrap-date-entry-presentation-show-time-p) 54 | (show-seconds-p :initform nil :initarg :show-seconds-p :accessor bootstrap-date-entry-presentation-show-seconds-p) 55 | (datepicker-options :initform (list :autoclose t 56 | :format "dd.mm.yyyy") 57 | :initarg :datepicker-options) 58 | (default-date :initform (metatilities:format-date "%Y-%m-%d" (get-universal-time)) 59 | :initarg :default-date))) 60 | 61 | (defparameter *datepicker-locale-file* "/pub/scripts/bootstrap-datepicker-locales/bootstrap-datepicker.ru.js") 62 | 63 | (defmethod render-view-field-value (value 64 | (presentation bootstrap-date-entry-presentation) 65 | (field form-view-field) 66 | (view form-view) 67 | widget obj 68 | &rest args &key intermediate-values field-info &allow-other-keys) 69 | (declare (special *presentation-dom-id*)) 70 | 71 | (with-slots (datepicker-options default-date) presentation 72 | (let* ((name (attributize-name (view-field-slot-name field))) 73 | (date (request-parameter (format nil "~A[date]" name))) 74 | (time (request-parameter (format nil "~A[time]" name))) 75 | (date-input-id (format nil "~A-date" *presentation-dom-id*)) 76 | (time-input-id (format nil "~A-time" *presentation-dom-id*)) 77 | (field-name (if field-info 78 | (attributize-view-field-name field-info) 79 | (attributize-name (view-field-slot-name field))))) 80 | (with-yaclml 81 | (<:div :class "input-append date" :id *presentation-dom-id* 82 | (<:input :class "input-small" :size "10" :type "text" :id date-input-id 83 | :value (or date 84 | (when value 85 | (metatilities:format-date "%d.%m.%Y" value))) 86 | :name (format nil "~A[date]" field-name)) 87 | (<:span :class "add-on" 88 | (<:i :class "icon-th"))) 89 | (when (bootstrap-date-entry-presentation-show-time-p presentation) 90 | (<:as-is " ") 91 | (<:div :class "input-append bootstrap-timepicker-component" 92 | (<:input :id time-input-id :type "text" :class "input-small" 93 | :value (or time 94 | (when value 95 | (if (bootstrap-date-entry-presentation-show-seconds-p presentation) 96 | (metatilities:format-date "%I:%M:%S %p" value) 97 | (metatilities:format-date "%I:%M %p" value)))) 98 | :name (format nil "~A[time]" field-name)) 99 | (<:span :class "add-on" 100 | (<:i :class "icon-time"))))) 101 | 102 | (weblocks-utils:require-assets 103 | "https://raw.github.com/html/weblocks-assets/master/bootstrap-datepicker/1.2.0/") 104 | 105 | (send-script 106 | (ps:ps 107 | (weblocks-utils:ps-with-scripts-and-styles 108 | ("/pub/scripts/bootstrap-datepicker.js" (ps:LISP *datepicker-locale-file*)) 109 | ("/pub/stylesheets/bootstrap-datepicker.css") 110 | (let* ((date-elem (ps:chain 111 | (j-query (ps:LISP (format nil "#~A" date-input-id))) 112 | (parent))) 113 | (set-default-date (lambda () 114 | (unless (ps:chain date-elem (data "date")) 115 | (ps:chain date-elem (data "date" (ps:new ((ps:LISP (intern "Date")) (ps:LISP default-date))))))))) 116 | 117 | (ps:chain 118 | date-elem 119 | (datepicker 120 | (ps:LISP `(ps:create 121 | ,@datepicker-options)))) 122 | 123 | (ps:chain date-elem (on "click" set-default-date)) 124 | (ps:chain date-elem (on "keydown" set-default-date)) 125 | (ps:chain date-elem (on "keyup" set-default-date)) 126 | 127 | (ps:chain 128 | (j-query (ps:LISP (format nil "#~A" *presentation-dom-id*))) 129 | (find ".icon-th") 130 | (click (lambda () 131 | (set-default-date) 132 | (ps:chain date-elem (datepicker "show"))))) 133 | (ps:LISP 134 | (when default-date 135 | `(let ((interval)) 136 | (setf interval 137 | (set-interval 138 | (lambda () 139 | (when (and (not (ps:chain date-elem (find "input:first") (val))) 140 | (ps:chain date-elem (data "datepicker"))) 141 | (clear-interval interval) 142 | (ps:chain date-elem 143 | (data "datepicker") 144 | (update (ps:new (,(intern "Date") ,default-date)))) 145 | (ps:chain date-elem (find "input:first") (val "")))) 146 | 100))))))))) 147 | 148 | (when (bootstrap-date-entry-presentation-show-time-p presentation) 149 | 150 | (weblocks-utils:require-assets 151 | "https://raw.github.com/html/weblocks-assets/master/bootstrap-timepicker/0.2.3/") 152 | 153 | (send-script 154 | (ps:ps 155 | (weblocks-utils:ps-with-scripts-and-styles 156 | ("/pub/scripts/bootstrap-timepicker.js") 157 | ("/pub/stylesheets/bootstrap-timepicker.css") 158 | (ps:chain 159 | (j-query (ps:LISP (format nil "#~A" time-input-id))) 160 | (timepicker 161 | (eval 162 | (ps:LISP 163 | (format 164 | nil 165 | "(~A)" 166 | (cl-json:encode-json-plist-to-string 167 | (append 168 | (list "defaultTime" "value") 169 | (when (bootstrap-date-entry-presentation-show-seconds-p presentation) 170 | (list "showSeconds" t)))))))))))))))) 171 | -------------------------------------------------------------------------------- /license.txt: -------------------------------------------------------------------------------- 1 | Preamble to the Gnu Lesser General Public License 2 | 3 | Copyright (c) 2000 Franz Incorporated, Berkeley, CA 94704 4 | 5 | The concept of the GNU Lesser General Public License version 2.1 6 | ("LGPL") has been adopted to govern the use and distribution of 7 | above-mentioned application. However, the LGPL uses terminology that 8 | is more appropriate for a program written in C than one written in 9 | Lisp. Nevertheless, the LGPL can still be applied to a Lisp program if 10 | certain clarifications are made. This document details those 11 | clarifications. Accordingly, the license for the open-source Lisp 12 | applications consists of this document plus the LGPL. Wherever there 13 | is a conflict between this document and the LGPL, this document takes 14 | precedence over the LGPL. 15 | 16 | A "Library" in Lisp is a collection of Lisp functions, data and 17 | foreign modules. The form of the Library can be Lisp source code (for 18 | processing by an interpreter) or object code (usually the result of 19 | compilation of source code or built with some other 20 | mechanisms). Foreign modules are object code in a form that can be 21 | linked into a Lisp executable. When we speak of functions we do so in 22 | the most general way to include, in addition, methods and unnamed 23 | functions. Lisp "data" is also a general term that includes the data 24 | structures resulting from defining Lisp classes. A Lisp application 25 | may include the same set of Lisp objects as does a Library, but this 26 | does not mean that the application is necessarily a "work based on the 27 | Library" it contains. 28 | 29 | The Library consists of everything in the distribution file set before 30 | any modifications are made to the files. If any of the functions or 31 | classes in the Library are redefined in other files, then those 32 | redefinitions ARE considered a work based on the Library. If 33 | additional methods are added to generic functions in the Library, 34 | those additional methods are NOT considered a work based on the 35 | Library. If Library classes are subclassed, these subclasses are NOT 36 | considered a work based on the Library. If the Library is modified to 37 | explicitly call other functions that are neither part of Lisp itself 38 | nor an available add-on module to Lisp, then the functions called by 39 | the modified Library ARE considered a work based on the Library. The 40 | goal is to ensure that the Library will compile and run without 41 | getting undefined function errors. 42 | 43 | It is permitted to add proprietary source code to the Library, but it 44 | must be done in a way such that the Library will still run without 45 | that proprietary code present. Section 5 of the LGPL distinguishes 46 | between the case of a library being dynamically linked at runtime and 47 | one being statically linked at build time. Section 5 of the LGPL 48 | states that the former results in an executable that is a "work that 49 | uses the Library." Section 5 of the LGPL states that the latter 50 | results in one that is a "derivative of the Library", which is 51 | therefore covered by the LGPL. Since Lisp only offers one choice, 52 | which is to link the Library into an executable at build time, we 53 | declare that, for the purpose applying the LGPL to the Library, an 54 | executable that results from linking a "work that uses the Library" 55 | with the Library is considered a "work that uses the Library" and is 56 | therefore NOT covered by the LGPL. 57 | 58 | Because of this declaration, section 6 of LGPL is not applicable to 59 | the Library. However, in connection with each distribution of this 60 | executable, you must also deliver, in accordance with the terms and 61 | conditions of the LGPL, the source code of Library (or your derivative 62 | thereof) that is incorporated into this executable. 63 | 64 | GNU LESSER GENERAL PUBLIC LICENSE 65 | Version 3, 29 June 2007 66 | 67 | Copyright (C) 2007 Free Software Foundation, Inc. 68 | Everyone is permitted to copy and distribute verbatim copies 69 | of this license document, but changing it is not allowed. 70 | 71 | 72 | This version of the GNU Lesser General Public License incorporates 73 | the terms and conditions of version 3 of the GNU General Public 74 | License, supplemented by the additional permissions listed below. 75 | 76 | 0. Additional Definitions. 77 | 78 | As used herein, "this License" refers to version 3 of the GNU Lesser 79 | General Public License, and the "GNU GPL" refers to version 3 of the GNU 80 | General Public License. 81 | 82 | "The Library" refers to a covered work governed by this License, 83 | other than an Application or a Combined Work as defined below. 84 | 85 | An "Application" is any work that makes use of an interface provided 86 | by the Library, but which is not otherwise based on the Library. 87 | Defining a subclass of a class defined by the Library is deemed a mode 88 | of using an interface provided by the Library. 89 | 90 | A "Combined Work" is a work produced by combining or linking an 91 | Application with the Library. The particular version of the Library 92 | with which the Combined Work was made is also called the "Linked 93 | Version". 94 | 95 | The "Minimal Corresponding Source" for a Combined Work means the 96 | Corresponding Source for the Combined Work, excluding any source code 97 | for portions of the Combined Work that, considered in isolation, are 98 | based on the Application, and not on the Linked Version. 99 | 100 | The "Corresponding Application Code" for a Combined Work means the 101 | object code and/or source code for the Application, including any data 102 | and utility programs needed for reproducing the Combined Work from the 103 | Application, but excluding the System Libraries of the Combined Work. 104 | 105 | 1. Exception to Section 3 of the GNU GPL. 106 | 107 | You may convey a covered work under sections 3 and 4 of this License 108 | without being bound by section 3 of the GNU GPL. 109 | 110 | 2. Conveying Modified Versions. 111 | 112 | If you modify a copy of the Library, and, in your modifications, a 113 | facility refers to a function or data to be supplied by an Application 114 | that uses the facility (other than as an argument passed when the 115 | facility is invoked), then you may convey a copy of the modified 116 | version: 117 | 118 | a) under this License, provided that you make a good faith effort to 119 | ensure that, in the event an Application does not supply the 120 | function or data, the facility still operates, and performs 121 | whatever part of its purpose remains meaningful, or 122 | 123 | b) under the GNU GPL, with none of the additional permissions of 124 | this License applicable to that copy. 125 | 126 | 3. Object Code Incorporating Material from Library Header Files. 127 | 128 | The object code form of an Application may incorporate material from 129 | a header file that is part of the Library. You may convey such object 130 | code under terms of your choice, provided that, if the incorporated 131 | material is not limited to numerical parameters, data structure 132 | layouts and accessors, or small macros, inline functions and templates 133 | (ten or fewer lines in length), you do both of the following: 134 | 135 | a) Give prominent notice with each copy of the object code that the 136 | Library is used in it and that the Library and its use are 137 | covered by this License. 138 | 139 | b) Accompany the object code with a copy of the GNU GPL and this license 140 | document. 141 | 142 | 4. Combined Works. 143 | 144 | You may convey a Combined Work under terms of your choice that, 145 | taken together, effectively do not restrict modification of the 146 | portions of the Library contained in the Combined Work and reverse 147 | engineering for debugging such modifications, if you also do each of 148 | the following: 149 | 150 | a) Give prominent notice with each copy of the Combined Work that 151 | the Library is used in it and that the Library and its use are 152 | covered by this License. 153 | 154 | b) Accompany the Combined Work with a copy of the GNU GPL and this license 155 | document. 156 | 157 | c) For a Combined Work that displays copyright notices during 158 | execution, include the copyright notice for the Library among 159 | these notices, as well as a reference directing the user to the 160 | copies of the GNU GPL and this license document. 161 | 162 | d) Do one of the following: 163 | 164 | 0) Convey the Minimal Corresponding Source under the terms of this 165 | License, and the Corresponding Application Code in a form 166 | suitable for, and under terms that permit, the user to 167 | recombine or relink the Application with a modified version of 168 | the Linked Version to produce a modified Combined Work, in the 169 | manner specified by section 6 of the GNU GPL for conveying 170 | Corresponding Source. 171 | 172 | 1) Use a suitable shared library mechanism for linking with the 173 | Library. A suitable mechanism is one that (a) uses at run time 174 | a copy of the Library already present on the user's computer 175 | system, and (b) will operate properly with a modified version 176 | of the Library that is interface-compatible with the Linked 177 | Version. 178 | 179 | e) Provide Installation Information, but only if you would otherwise 180 | be required to provide such information under section 6 of the 181 | GNU GPL, and only to the extent that such information is 182 | necessary to install and execute a modified version of the 183 | Combined Work produced by recombining or relinking the 184 | Application with a modified version of the Linked Version. (If 185 | you use option 4d0, the Installation Information must accompany 186 | the Minimal Corresponding Source and Corresponding Application 187 | Code. If you use option 4d1, you must provide the Installation 188 | Information in the manner specified by section 6 of the GNU GPL 189 | for conveying Corresponding Source.) 190 | 191 | 5. Combined Libraries. 192 | 193 | You may place library facilities that are a work based on the 194 | Library side by side in a single library together with other library 195 | facilities that are not Applications and are not covered by this 196 | License, and convey such a combined library under terms of your 197 | choice, if you do both of the following: 198 | 199 | a) Accompany the combined library with a copy of the same work based 200 | on the Library, uncombined with any other library facilities, 201 | conveyed under the terms of this License. 202 | 203 | b) Give prominent notice with the combined library that part of it 204 | is a work based on the Library, and explaining where to find the 205 | accompanying uncombined form of the same work. 206 | 207 | 6. Revised Versions of the GNU Lesser General Public License. 208 | 209 | The Free Software Foundation may publish revised and/or new versions 210 | of the GNU Lesser General Public License from time to time. Such new 211 | versions will be similar in spirit to the present version, but may 212 | differ in detail to address new problems or concerns. 213 | 214 | Each version is given a distinguishing version number. If the 215 | Library as you received it specifies that a certain numbered version 216 | of the GNU Lesser General Public License "or any later version" 217 | applies to it, you have the option of following the terms and 218 | conditions either of that published version or of any later version 219 | published by the Free Software Foundation. If the Library as you 220 | received it does not specify a version number of the GNU Lesser 221 | General Public License, you may choose any version of the GNU Lesser 222 | General Public License ever published by the Free Software Foundation. 223 | 224 | If the Library as you received it specifies that a proxy can decide 225 | whether future versions of the GNU Lesser General Public License shall 226 | apply, that proxy's public statement of acceptance of any version is 227 | permanent authorization for you to choose that version for the 228 | Library. 229 | --------------------------------------------------------------------------------