(cl:in-package #:cluffer-base)

(defclass cluffer:buffer () ())

(defclass cluffer:line ()
  ((%dock :initarg :dock :initform nil
	  :accessor cluffer-internal:dock)))

(defclass cluffer:cursor () ())

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;
;;; Generic function LINE-COUNT.
;;;
;;; Return the number of lines in BUFFER.

(defgeneric cluffer:line-count (buffer))

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;
;;; Generic function ITEM-COUNT.
;;;
;;; Return the number of items in ENTITY.
;;;
;;; If ENTITY is a buffer, then the total number of items in the
;;; buffer is returned.
;;;
;;; IF ENTITY is a line, then the number of items in the line is
;;; returned.
;;;
;;; If ENTITY is a cursor that is currently attached to a line, the
;;; number of items of the line to which the cursor is attached is
;;; returned.
;;;
;;; If ENTITY is a cursor that is currently not attached to a line,
;;; then an error of type DETACHED-CURSOR is signaled.

(defgeneric cluffer:item-count (entity))

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;
;;; Generic function CURSOR-ATTACHED-P.
;;;
;;; Given a cursor, return true if and only if the cursor is attached
;;; to a line.

(defgeneric cluffer:cursor-attached-p (cursor))

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;
;;; Generic function CURSOR-POSITION.
;;;
;;; Given a cursor, return its conceptual position.
;;;
;;; If CURSOR is currently not attached to a line, then an error of
;;; type DETACHED-CURSOR is signaled.

(defgeneric cluffer:cursor-position (cursor))

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;
;;; Generic function (SETF CURSOR-POSITION).
;;;
;;; Given a cursor, set its conceptual position.
;;;
;;; If POSITION is negative or greater than the item count of the line
;;; to which the cursor is attached, then an error is signaled.
;;;
;;; If CURSOR is currently not attached to a line, then an error of
;;; type DETACHED-CURSOR is signaled.

(defgeneric (setf cluffer:cursor-position) (position cursor))

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;
;;; Generic function BEGINNING-OF-LINE-P.
;;;
;;; Return true if and only if CURSOR is positioned at the beginning
;;; of the line to which it is attached.
;;;
;;; If CURSOR is currently not attached to a line, then an error of
;;; type DETACHED-CURSOR is signaled.
;;;
;;; Calling this function has the same effect as calling the function
;;; CURSOR-POSITION and checking whether the return value is zero, but
;;; this function might be implemented differently.

(defgeneric cluffer:beginning-of-line-p (cursor))

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;
;;; Generic function END-OF-LINE-P.
;;;
;;; Return true if and only if CURSOR is positioned at the end of the
;;; line to which it is attached.
;;;
;;; If CURSOR is currently not attached to a line, then an error of
;;; type DETACHED-CURSOR is signaled.
;;;
;;; Calling this function has the same effect as calling the functions
;;; CURSOR-POSITION and ITEM-COUNT checking whether the return values
;;; are the same, but this function might be implemented differently.

(defgeneric cluffer:end-of-line-p (cursor))

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;
;;; Generic function FORWARD-ITEM.
;;;
;;; CURSOR is moved forward by one position.
;;;
;;; If CURSOR is already at the end of the line to which it is
;;; attached, then the error END-OF-LINE is signaled.
;;;
;;; If CURSOR is currently not attached to a line, then an error of
;;; type DETACHED-CURSOR is signaled.

(defgeneric cluffer:forward-item (cursor))

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;
;;; Generic function BACKWARD-ITEM.
;;;
;;; CURSOR is moved backward by one position.
;;;
;;; If CURSOR is already at the beginning of the line to which it is
;;; attached, then the error BEGINNING-OF-LINE is signaled.
;;;
;;; If CURSOR is currently not attached to a line, then an error of
;;; type DETACHED-CURSOR is signaled.

(defgeneric cluffer:backward-item (cursor))

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;
;;; Generic function BEGINNING-OF-LINE.
;;;
;;; CURSOR is moved so that it is positioned at the beginning of the
;;; line to which it is attached.
;;;
;;; If CURSOR is currently not attached to a line, then an error of
;;; type DETACHED-CURSOR is signaled.

(defgeneric cluffer:beginning-of-line (cursor))

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;
;;; Generic function END-OF-LINE.
;;;
;;; CURSOR is moved so that it is positioned at the end of the line to
;;; which it is attached.
;;;
;;; If CURSOR is currently not attached to a line, then an error of
;;; type DETACHED-CURSOR is signaled.

(defgeneric cluffer:end-of-line (cursor))

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;
;;; Generic function ITEM-AT-POSITION.
;;;
;;; Return the item at POSITION in LINE.

(defgeneric cluffer:item-at-position (line position))

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;
;;; Generic function ITEM-BEFORE-CURSOR.
;;;
;;; Return the item that occurs immediately before CURSOR.
;;;
;;; If CURSOR is at the beginning of the line to which it is attached,
;;; then the error BEGINNING-OF-LINE is signaled.
;;;
;;; If CURSOR is currently not attached to a line, then an error of
;;; type DETACHED-CURSOR is signaled.

(defgeneric cluffer:item-before-cursor (cursor))

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;
;;; Generic function ITEM-AFTER-CURSOR.
;;;
;;; Return the item that occurs immediately after CURSOR.
;;;
;;; If CURSOR is at the end of the line to which it is attached, then
;;; the error END-OF-LINE is signaled.
;;;
;;; If CURSOR is currently not attached to a line, then an error of
;;; type DETACHED-CURSOR is signaled.

(defgeneric cluffer:item-after-cursor (cursor))

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;
;;; Generic function INSERT-ITEM-AT-POSITION.
;;;
;;; Insert ITEM into LINE at POSITION.
;;;
;;; How the positions of cursors located at POSITION are affected by
;;; this operation is defined by the exact type of the line and the
;;; exact types of these cursors.
;;;
;;; The STANDARD-LINE implementation supplies two different cursor
;;; types, namely LEFT-STICKY and RIGHT-STICKY cursors.  each
;;; LEFT-STICKY cursor at POSITION will maintain its position, whereas
;;; each RIGHT-STICKY cursor at POSITION will have its position
;;; incremented as a result of this operation.

(defgeneric cluffer:insert-item-at-position (line item position))

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;
;;; Generic function DELETE-ITEM-AT-POSITION.
;;;
;;; Delete the item at POSITION in LINE.

(defgeneric cluffer:delete-item-at-position (line position))

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;
;;; Generic function INSERT-ITEM.
;;;
;;; Insert ITEM into the line to which CURSOR is attached at the
;;; current position of CURSOR.
;;;
;;; How the position of CURSOR (and other cursors at the same position
;;; as CURSOR) is affected by this operation is defined by the exact
;;; types of these cursors.
;;;
;;; If CURSOR is currently not attached to a line, then an error of
;;; type DETACHED-CURSOR is signaled.

(defgeneric cluffer:insert-item (cursor item))

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;
;;; Generic function DELETE-ITEM.
;;;
;;; Delete the item immediately after CURSOR.
;;;
;;; If CURSOR is at the end of the line to which it is attached, then
;;; the error END-OF-LINE is signaled.
;;;
;;; If CURSOR is currently not attached to a line, then an error of
;;; type DETACHED-CURSOR is signaled.

(defgeneric cluffer:delete-item (cursor))

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;
;;; Generic function ERASE-ITEM.
;;;
;;; Delete the item immediately before CURSOR.
;;;
;;; If CURSOR is at the beginning of the line to which it is attached,
;;; then the error BEGINNING-OF-LINE is signaled.
;;;
;;; If CURSOR is currently not attached to a line, then an error of
;;; type DETACHED-CURSOR is signaled.

(defgeneric cluffer:erase-item (cursor))

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;
;;; Generic function LINE-NUMBER.
;;;
;;; Return the line number of ENTITY.
;;;
;;; If ENTITY is a line, then the number of that line in the buffer to
;;; which the line belongs is returned.  The first line in the buffer
;;; has number 0.
;;;
;;; If ENTITY is a cursor, then the number of the line to which the
;;; cursor is attached is returned.
;;;
;;; If ENTITY is a cursor that is currently not attached to a line,
;;; then an error of type DETACHED-CURSOR is signaled.

(defgeneric cluffer:line-number (entity))

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;
;;; Generic function FIND-LINE.
;;;
;;; Return the line with the number LINE-NUMBER in BUFFER.
;;;
;;; The first line in the buffer has number 0.
;;;
;;; If LINE-NUMBER is negative, then an error of type
;;; BEGINNING-OF-BUFFER is signaled.  If LINE-NUMBER is greater than
;;; or equal to the number of lines in BUFFER, then an error of type
;;; END-OF-BUFFER is signaled.

(defgeneric cluffer:find-line (buffer line-number))

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;
;;; Generic function BEGINNING-OF-BUFFER-P.
;;;
;;; Return true if and only if CURSOR is positioned at the beginning
;;; of the buffer.
;;;
;;; If CURSOR is currently not attached to a line, then an error of
;;; type DETACHED-CURSOR is signaled.
;;;
;;; Calling this function has the same effect as calling the functions
;;; LINE-NUMBER and BEGINNING-OF-LINE-P, checking that the line number
;;; of the cursor is 0 and that BEGINNING-OF-LINE-P returns true, but
;;; the actual implementation of this function might be different for
;;; performance reasons.

(defgeneric cluffer:beginning-of-buffer-p (cursor))

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;
;;; Generic function END-OF-BUFFER-P.
;;;
;;; Return true if and only if CURSOR is positioned at the end
;;; of the buffer.
;;;
;;; If CURSOR is currently not attached to a line, then an error of
;;; type DETACHED-CURSOR is signaled.
;;;
;;; Calling this function has the same effect as calling the functions
;;; LINE-COUNT, LINE-NUMBER, and END-OF-LINE-P, checking that the line
;;; number of the cursor is the last line of the buffer and that
;;; END-OF-LINE-P returns true, but the actual implementation of this
;;; function might be different for performance reasons.

(defgeneric cluffer:end-of-buffer-p (cursor))

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;
;;; Generic function SPLIT-LINE-AT-POSITION.

(defgeneric cluffer:split-line-at-position (line position))

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;
;;; Generic function SPLIT-LINE.

(defgeneric cluffer:split-line (cursor))

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;
;;; Generic function JOIN-LINE.
;;;
;;; If entity is a line, then the line following it is appended to
;;; the end of this line.  If entity is a cursor, then the line to
;;; which the cursor is attached is joined with the line following it.

(defgeneric cluffer:join-line (entity))

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;
;;; ITEMS.
;;;
;;; Return the items of ENTITY in a vector.  If ENTITY is a line, then
;;; return the items in that line.  If ENTITY is a cursor, then return
;;; the items in the line to which the cursor is attached.
;;;
;;; If entity is a cursor that is not currently attached to a line,
;;; then signal a condition of type CURSOR-DETACHED.

(defgeneric cluffer:items (entity &key start end))

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;
;;; Generic function ATTACH-CURSOR.

(defgeneric cluffer:attach-cursor (cursor line &optional position))

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;
;;; Generic function DETACH-CURSOR.

(defgeneric cluffer:detach-cursor (cursor))

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;
;;; Generic function BUFFER.
;;;
;;; Return the buffer of a cursor or a line.

(defgeneric cluffer:buffer (entity))

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;
;;; Generic function FIRST-LINE-P.

(defgeneric cluffer:first-line-p (line))

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;
;;; Generic function LAST-LINE-P.

(defgeneric cluffer:last-line-p (line))

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;
;;; Generic function LINE
;;;
;;; Return the line of CURSOR.
;;;
;;; If CURSOR is a cursor that is currently not attached to a line,
;;; then an error of type DETACHED-CURSOR is signaled.

(defgeneric cluffer:line (cursor))
