Index: buffer.lisp
===================================================================
RCS file: /project/gsharp/cvsroot/gsharp/buffer.lisp,v
retrieving revision 1.24
diff -u -r1.24 buffer.lisp
--- buffer.lisp	7 Nov 2005 20:00:52 -0000	1.24
+++ buffer.lisp	9 Nov 2005 21:47:43 -0000
@@ -75,16 +75,14 @@
 
 (defclass fiveline-staff (staff)
   ((print-character :allocation :class :initform #\=)
-   (clef :accessor clef :initarg :clef :initform (make-clef :treble))
-   (keysig :accessor keysig :initarg :keysig
-	   :initform (make-array 7 :initial-element :natural))))
+   (clef :accessor clef :initarg :clef :initform (make-clef :treble))))
 	   
-(defun make-fiveline-staff (&rest args &key name clef keysig)
+(defun make-fiveline-staff (&rest args &key name clef)
   (declare (ignore name clef keysig))
   (apply #'make-instance 'fiveline-staff args))
 
 (defmethod print-object :after ((s fiveline-staff) stream)
-  (format stream ":clef ~W :keysig ~W " (clef s) (keysig s)))
+  (format stream ":clef ~W " (clef s)))
 
 (defun read-fiveline-staff-v3 (stream char n)
   (declare (ignore char n))
@@ -209,48 +207,76 @@
 ;;; currently does not belong to any bar. 
 (defgeneric bar (element))
 
+(defclass element (gsharp-object)
+  ((bar :initform nil :initarg :bar :accessor bar)))
+
+(defmethod duration ((element element))
+  1/8)
+
+(defmethod xoffset ((element element))
+  0)
+
+(defmethod rbeams ((element element)) 0)
+(defmethod lbeams ((element element)) 0)
+
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;;;
+;;; Key Signature
+
+(defclass key-signature (element)
+  ((print-character :allocation :class :initform #\#)
+   (staff :initarg :staff :accessor staff)
+   (keysig :accessor keysig :initarg :keysig
+           :initform (make-array 7 :initial-element :natural))))
+
+(defun make-keysig (staff &rest args &key keysig)
+  (apply #'make-instance 'key-signature :staff staff args))
+
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;;;
+;;; Rhythmic Element
+
 ;;; Return the notehead of the element.  With setf, set the notehead
 ;;; of the element. 
-(defgeneric notehead (element))
-(defgeneric (setf notehead) (notehead element))
+(defgeneric notehead (rhythmic-element))
+(defgeneric (setf notehead) (notehead rhythmic-element))
 
 ;;; Return the number of right beams of the element.  With setf, set
 ;;; the number of right beams of the element.
-(defgeneric rbeams (element))
-(defgeneric (setf rbeams) (rbeams element))
+(defgeneric rbeams (rhythmic-element))
+(defgeneric (setf rbeams) (rbeams rhythmic-element))
 
 ;;; Return the number of left beams of the element.  With setf, set
 ;;; the number of left beams of the element.
-(defgeneric lbeams (element))
-(defgeneric (setf lbeams) (lbeams element))
+(defgeneric lbeams (rhythmic-element))
+(defgeneric (setf lbeams) (lbeams rhythmic-element))
 
 ;;; Return the number of dots of the element.  With setf, set the
 ;;; number of dots of the element. 
-(defgeneric dots (element))
-(defgeneric (setf dots) (dots element))
+(defgeneric dots (rhythmic-element))
+(defgeneric (setf dots) (dots rhythmic-element))
 
-(defclass element (gsharp-object)
-  ((bar :initform nil :initarg :bar :accessor bar)
-   (notehead :initform :whole :initarg :notehead :accessor notehead)
+(defclass rhythmic-element (element)
+  ((notehead :initform :whole :initarg :notehead :accessor notehead)
    (rbeams :initform 0 :initarg :rbeams :accessor rbeams)
    (lbeams :initform 0 :initarg :lbeams :accessor lbeams)
    (dots :initform 0 :initarg :dots :accessor dots)
    (xoffset :initform 0 :initarg :xoffset :accessor xoffset)))
    
-(defmethod print-object :after ((e element) stream)
+(defmethod print-object :after ((e rhythmic-element) stream)
   (with-slots (notehead rbeams lbeams dots xoffset) e
     (format stream
 	    ":notehead ~W :rbeams ~W :lbeams ~W :dots ~W :xoffset ~W "
 	    notehead rbeams lbeams dots xoffset)))
 
-(defmethod undotted-duration ((element element))
+(defmethod undotted-duration ((element rhythmic-element))
   (ecase (notehead element)
     (:whole 1)
     (:half 1/2)
     (:filled (/ (expt 2 (+ 2 (max (rbeams element)
 				  (lbeams element))))))))
 
-(defmethod duration ((element element))
+(defmethod duration ((element rhythmic-element))
   (let ((duration (undotted-duration element)))
     (do ((dot-duration (/ duration 2) (/ dot-duration 2))
 	 (nb-dots (dots element) (1- nb-dots)))
@@ -262,7 +288,7 @@
 ;;;
 ;;; Melody element
 
-(defclass melody-element (element) ())
+(defclass melody-element (rhythmic-element) ())
 
 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
 ;;;
@@ -391,7 +417,7 @@
 ;;;
 ;;; Lyrics element
 
-(defclass lyrics-element (element)
+(defclass lyrics-element (rhythmic-element)
   ((print-character :allocation :class :initform #\A)
    (staff :initarg :staff :reader staff)
    (text :initarg :text
Index: drawing.lisp
===================================================================
RCS file: /project/gsharp/cvsroot/gsharp/drawing.lisp,v
retrieving revision 1.12
diff -u -r1.12 drawing.lisp
--- drawing.lisp	31 Oct 2005 01:41:13 -0000	1.12
+++ drawing.lisp	9 Nov 2005 21:47:43 -0000
@@ -29,24 +29,7 @@
 	       :x ,(+ x1 10)
 	       :staff-step ,(lineno (clef staff)))
 	     :stream pane)
-    (let ((yoffset (ecase (name (clef staff))
-		     (:bass (- (lineno (clef staff)) 4))
-		     (:treble (+ (lineno (clef staff)) 2))
-		     (:c (- (lineno (clef staff))) 1))))
-      (loop for pitch in '(6 2 5 1 4 0 3)
-	    for line in '(0 3 -1 2 -2 1 -3)
-	    for x from (+ x1 10 (score-pane:staff-step 8)) by (score-pane:staff-step 2)
-	    while (eq (aref (keysig staff) pitch) :flat)
-	    do (score-pane:draw-accidental pane :flat x (+ line yoffset))))
-    (let ((yoffset (ecase (name (clef staff))
-		     (:bass (lineno (clef staff)))
-		     (:treble (+ (lineno (clef staff)) 6))
-		     (:c (+ (lineno (clef staff))) 3))))
-      (loop for pitch in '(3 0 4 1 5 2 6)
-	    for line in '(0 -3 1 -2 -5 -1 -4)
-	    for x from (+ x1 10 (score-pane:staff-step 8)) by (score-pane:staff-step 2.5)
-	    while (eq (aref (keysig staff) pitch) :sharp)
-	    do (score-pane:draw-accidental pane :sharp x (+ line yoffset)))))
+)
   (present staff
 	   `((score-pane:fiveline-staff)
 	     :x1 ,x1 :x2 ,x2)
@@ -58,6 +41,27 @@
 	     :x1 ,x1 :x2 ,x2)
 	   :stream pane))
 
+(defmethod draw-element (pane (keysig gsharp-buffer::key-signature) x &optional flags)
+  (let ((staff (staff keysig)))
+    (let ((yoffset (ecase (name (clef staff))
+                     (:bass (- (lineno (clef staff)) 4))
+                     (:treble (+ (lineno (clef staff)) 2))
+                     (:c (- (lineno (clef staff))) 1))))
+      (loop for pitch in '(6 2 5 1 4 0 3)
+            for line in '(0 3 -1 2 -2 1 -3)
+            for x from (+ x 10 (score-pane:staff-step 8)) by (score-pane:staff-step 2)
+            while (eq (aref (keysig keysig) pitch) :flat)
+            do (score-pane:draw-accidental pane :flat x (+ line yoffset))))
+    (let ((yoffset (ecase (name (clef staff))
+                     (:bass (lineno (clef staff)))
+                     (:treble (+ (lineno (clef staff)) 6))
+                     (:c (+ (lineno (clef staff))) 3))))
+      (loop for pitch in '(3 0 4 1 5 2 6)
+            for line in '(0 -3 1 -2 -5 -1 -4)
+            for x from (+ x 10 (score-pane:staff-step 8)) by (score-pane:staff-step 2.5)
+            while (eq (aref (keysig keysig) pitch) :sharp)
+            do (score-pane:draw-accidental pane :sharp x (+ line yoffset))))))
+    
 (defun line-cost (measures method)
   (reduce (lambda (x y) (combine-cost method x y)) measures :initial-value nil))
 
@@ -123,7 +127,7 @@
 (defmethod draw-buffer (pane (buffer buffer) *cursor* x y draw-cursor)
   (score-pane:with-staff-size 6
     (let* ((staves (staves buffer))
-	   (timesig-offset (max (* (score-pane:staff-step 2)
+	   (timesig-offset 0 #+nil (max (* (score-pane:staff-step 2)
 				   (loop for staff in staves
 					 maximize
 					 (if (typep staff 'fiveline-staff)
@@ -163,6 +167,13 @@
 		   (incf yy 90))))
 	 buffer)))))
 
+(define-added-mixin xelement () element
+   ((minpos :accessor element-minpos)
+    (min-yoffset :accessor element-min-yoffset)
+    (maxpos :accessor element-maxpos)
+    (max-yoffset :accessor element-max-yoffset)
+    (xpos :accessor element-xpos)))
+
 (define-added-mixin velement () melody-element
   ((final-stem-direction :accessor final-stem-direction)
    (final-stem-position :accessor final-stem-position)
@@ -313,6 +324,11 @@
 	  notes))
 
 (defun draw-beam-group (pane elements)
+  (let ((e (car elements)))
+    (when (typep e 'gsharp-buffer::key-signature)
+      (assert (null (cdr elements)))
+      (return-from draw-beam-group
+        (draw-element pane e (element-xpos e)))))
   (mapc #'compute-maxpos-minpos elements)
   (if (null (cdr elements))
       (when (or (typep (car elements) 'rest) (notes (car elements)))
@@ -486,7 +502,7 @@
   (loop for note in group do
 	(setf (final-accidental note)
 	      (if (eq (accidentals note)
-		      (aref (keysig (staff note)) (mod (pitch note) 7)))
+		      (aref (keysig note) (mod (pitch note) 7)))
 		  nil
 		  (accidentals note)))))
 
Index: gui.lisp
===================================================================
RCS file: /project/gsharp/cvsroot/gsharp/gui.lisp,v
retrieving revision 1.40
diff -u -r1.40 gui.lisp
--- gui.lisp	7 Nov 2005 20:00:52 -0000	1.40
+++ gui.lisp	9 Nov 2005 21:47:44 -0000
@@ -580,7 +580,7 @@
 	 (staff (car (staves (layer (slice (bar cluster))))))
 	 (note (make-note pitch staff
 		 :head (notehead state)
-		 :accidentals (aref (keysig staff) (mod pitch 7))
+		 :accidentals (aref (keysig cluster) (mod pitch 7))
 		 :dots (dots state))))
     (setf *current-cluster* cluster
 	  *current-note* note)
@@ -812,6 +812,50 @@
     (add-note cluster new-note)
     (setf *current-note* new-note)))
 
+(defun insert-keysig ()
+  (let* ((state (input-state *application-frame*))
+	 (cursor (cursor *application-frame*))
+	 (keysig (if (keysig cursor)
+                     (gsharp-buffer::make-keysig (car (staves (layer (cursor *application-frame*)))) :keysig (copy-seq (keysig cursor)))
+                     (gsharp-buffer::make-keysig (car (staves (layer (cursor *application-frame*))))))))
+    (insert-element keysig cursor)
+    (forward-element cursor)
+    keysig))
+
+(define-gsharp-command com-insert-keysig ()
+  (insert-keysig))
+
+(defmethod keysig ((cursor gsharp-cursor))
+  (let ((element (cursor-element cursor)))
+    ;; FIXME
+    (when element
+      (keysig element))))
+
+(defmethod keysig ((note note))
+  (keysig (cluster note)))
+
+(defmethod keysig ((element element))
+  (let ((bar (bar element)))
+    ;; FIXME: this cursor handling should be abstracted
+    (let ((cursor (make-cursor bar 0)))
+      (loop
+       (when (end-of-bar-p cursor)
+         (return))
+       (when (eq (cursor-element cursor) element)
+         (format *trace-output* "~&KEYSIG: ELEMENT ~S~%" element)
+         (finish-output *trace-output*)
+         (return))
+       (forward-element cursor))
+      (loop
+       (when (typep (cursor-element cursor) 'gsharp-buffer::key-signature)
+         (format *trace-output* "~&KEYSIG: FOUND ~S~%" (cursor-element cursor))
+         (finish-output *trace-output*)
+         (return-from keysig (keysig (cursor-element cursor))))
+       (when (and (first-bar-p cursor) (beginning-of-bar-p cursor))
+         (return))
+       (backward-element cursor)))))
+    
+
 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
 ;;;
 ;;; motion by element
@@ -1077,7 +1121,9 @@
     (remove-staff-from-layer staff layer)))
 
 (define-gsharp-command com-more-sharps ()
-  (let ((keysig (keysig (car (staves (layer (cursor *application-frame*)))))))
+  (format *trace-output* "~&COM-MORE-SHARPS~%")
+  (finish-output *trace-output*)
+  (let ((keysig (keysig (cursor *application-frame*))))
     (cond ((eq (aref keysig 3) :flat) (setf (aref keysig 3) :natural))
 	  ((eq (aref keysig 0) :flat) (setf (aref keysig 0) :natural))
 	  ((eq (aref keysig 4) :flat) (setf (aref keysig 4) :natural))
@@ -1094,7 +1140,7 @@
 	  ((eq (aref keysig 6) :natural) (setf (aref keysig 6) :sharp)))))
 
 (define-gsharp-command com-more-flats ()
-  (let ((keysig (keysig (car (staves (layer (cursor *application-frame*)))))))
+  (let ((keysig (keysig (cursor *application-frame*))))
     (cond ((eq (aref keysig 6) :sharp) (setf (aref keysig 6) :natural))
 	  ((eq (aref keysig 2) :sharp) (setf (aref keysig 2) :natural))
 	  ((eq (aref keysig 5) :sharp) (setf (aref keysig 5) :natural))
Index: modes.lisp
===================================================================
RCS file: /project/gsharp/cvsroot/gsharp/modes.lisp,v
retrieving revision 1.7
diff -u -r1.7 modes.lisp
--- modes.lisp	28 Oct 2005 17:20:30 -0000	1.7
+++ modes.lisp	9 Nov 2005 21:47:44 -0000
@@ -37,6 +37,7 @@
 (set-key 'com-add-note-g 'melody-table '(#\G))
 (set-key 'com-add-note-a 'melody-table '(#\A))
 (set-key 'com-add-note-b 'melody-table '(#\B))
+(set-key 'com-insert-keysig 'melody-table '(#\K))
 (set-key 'com-current-increment 'melody-table '((#\p)))
 (set-key 'com-current-decrement 'melody-table '((#\n)))
 (set-key 'com-istate-more-dots 'melody-table '((#\i) (#\.)))
