;;; uko-editing.el -- editing functions of UKO-II

;; Copyright (C) 2003 Michael Kuehn, Universität Koblenz-Landau

;; Author: Michael Kuehn <kuehn@uni-koblenz.de>
;; Maintainer: Michael Kuehn <kuehn@uni-koblenz.de
;; Created: March 2003
;; 
;; $Id: uko-editing.el,v 1.6 2003/08/28 09:53:18 deee Exp $

;; delete last completed word
(defun uko-delete-word ()
  "Delete last completed word in front of cursor position."
  (interactive)
;  (delete-extent uko-expand-extent)
  (setq uko-delete-stack '())
  (uko-set-delete-word-state)
  (uko-delete-back-word)
  )

;; 
(defun uko-delete-back-word ()
  (interactive)
  (uko-leave)
  (if (> (point) (point-min))
      (let ((here (point)))
	(backward-word)
	(setq uko-delete-stack
	      (cons (buffer-substring here (point)) uko-delete-stack) )
	(delete-region here (point))
	)
    (beep)
    )
  (uko-enter)
  (uko-set-delete-word-state)
  )

;; Complete deletion process and leave
(defun uko-delete-word-done ()
  "Complete deletion process and leave delete mode."
  (interactive)
  (uko-leave)
  (uko-enter)
  )

;; Undo all previously executed deletions.
(defun uko-delete-word-undo ()
  "Undo all previously executed deletion. Insert all deleted words in their former position."
  (interactive)
  (uko-leave)
  (while uko-delete-stack
    (insert (car uko-delete-stack))
    (setq uko-delete-stack (cdr uko-delete-stack))
    )
  (uko-enter)
  )

;; Undo the previously executed deletion.
(defun uko-delete-word-undel ()
  "Insert deleted word in former position."
  (interactive)
  (uko-leave)
  (if uko-delete-stack
      (progn 
	(insert (car uko-delete-stack))
	(setq uko-delete-stack (cdr uko-delete-stack))
	)
    (beep)
    )
  (uko-enter)
  (uko-set-delete-word-state)
  )

;; Delete mode if uko-insert-best-guess is not activated. Delete int code in front of cursor position.
(defun uko-delete-code ()
  "Delete last entered int of code in front of cursor position."
  (interactive)
  (setq uko-code-extent (substring (extent-string uko-expand-extent) 0 -1))
  (uko-set-delete-state)
  (setq uko-delete-stack '())
  (uko-delete-char)
  )

;; Delete mode if uko-insert-best-guess is active. Delete char in front of cursor position.
(defun uko-delete-char ()
  "Delete last entered char in front of cursor position."
  (interactive)
  (if (> (point) (extent-start-position uko-expand-extent))
      (progn 
	(when uko-insert-best-guess
	  (uko-insert-proposal uko-last-proposal-code)
	  )
	(setq uko-delete-stack (cons (char-before) uko-delete-stack))
	(delete-backward-char 1)
	(when uko-insert-best-guess
	  (setq uko-last-proposal-code
		(buffer-substring (extent-start-position uko-expand-extent) (- (extent-end-position uko-expand-extent) 1)) 
		)
	  (uko-expand)
	  )
	)
    (beep)
    )
  (uko-set-delete-state)
  )

(defun uko-delete-done ()
  (interactive)
  (setq uko-delete-stack '())
  (uko-set-default-state)
  )

(defun uko-delete-undo ()
  (interactive)
  (uko-insert-proposal uko-code-extent)
  (setq uko-delete-stack '())
  (uko-set-default-state)
  )

(defun uko-delete-undel ()
  (interactive)
  (if uko-delete-stack
      (progn 
	(when uko-insert-best-guess
	  (uko-insert-proposal uko-last-proposal-code)
	  )
	(insert (car uko-delete-stack))
	(setq uko-delete-stack (cdr uko-delete-stack))
	(when uko-insert-best-guess
	  (setq uko-last-proposal-code
		(buffer-substring (extent-start-position uko-expand-extent) (- (extent-end-position uko-expand-extent) 1)) 
		)
	  (uko-expand)
	  )
	)
    (beep)
    )
  (uko-set-delete-state)
  )

(defvar uko-move-point nil)

;; Mode for cursor movement
(defun uko-move ()
  "Start mode for cursor movement"
  (interactive)
  (setq uko-move-point (point))
  (uko-set-move-state)
  )

;; Move cursor position one word forward, into space behind the next word.
(defun uko-move-forward ()
  "Move one word forward if not at end of buffer, else do nothing."
  (interactive)
  (uko-leave)
  (let ((here (point)))
    (if (forward-word)
	(progn
	  ;(when (eobp)
	  ;  (insert " ") )
	  (forward-char)
	  (uko-enter)
	  (delete-char -1)
	  (uko-set-move-state)
	  )
      (progn
	(beep)
	(goto-char here)
	(delete-char 1)
	(uko-enter)
	(uko-set-move-state)
	) 
      ) 
    )
  )


;; Move cursor position one word backward, into space between the previous word.
(defun uko-move-backward ()
  "Move one word backward if not at beginning of buffer, else do nothing."
  (interactive)
  (uko-leave)
  (let ((here (point)))
    (if (backward-word)
	(progn
	  (when (bobp)
	    (insert " ") )
	  ;(forward-char)
	  (uko-enter)
	  (when (not (bobp))
	    (delete-char -1)
	    )
	  (uko-set-move-state)
	  )
      (progn
	(beep)
	(goto-char here)
	(uko-enter)
	(forward-char)
	(delete-char 1)
	(backward-char)
	(uko-set-move-state)
	) 
      ) 
    )

;;The old version
;  (uko-leave)
;  (if (bobp)
;      (beep)
;    (backward-word)
;    )
;  (uko-enter)
;  (delete-char -1)
;  (uko-set-move-state)
  )


;; Complete move mode, return to default mode.
(defun uko-move-done ()
  "Complete movement. Return to default mode and insert one blank in front of the extent."
  (interactive)
  (uko-leave)
  (forward-char)
  (uko-enter)
  (when (= (point) 2) 
    (delete-char -1)
    )
  )

;; Cancel all movements. Put cursor to starting position.
(defun uko-move-undo ()
  "Cancel all executed movements."
  (interactive)
  (when (bobp)
    (delete-char 1)
    )
  (goto-char uko-move-point)
  (uko-leave)
  (delete-char 1)
  (uko-enter)
  )

(defvar uko-spell-next-letter-list '())
(defvar uko-spell-prev-letter-list '())


;; Mode for spelling
(defun uko-spell ()
  "Method called when the spell button is pressed in command mode.
Proposal for the first letter is shown while the other letters remain numbers."
  (interactive)
  (uko-set-spell-state)
  (if uko-insert-best-guess
    (uko-insert-proposal uko-last-proposal-code)
    (uko-insert-proposal uko-code-extent)
    )
  (goto-char (extent-start-position uko-expand-extent))
  (setq uko-spell-next-letter-list '())
  (setq uko-spell-prev-letter-list '())
  (uko-spell-letter (char-after))
  )


;; Spell first letter of inserted code
(defun uko-spell-letter (char)
  (setq uko-spell-prev-letter-list '())
  (let ((code (- (char-to-int char) (char-to-int ?0))))
    (setq uko-spell-next-letter-list (nth (- code 1) uko-keyboard-layout)) )
  (uko-spell-next-letter)
  (pop uko-spell-prev-letter-list)
  )


;; Show next letter from uko-keyboard-layout
(defun uko-spell-next-letter ()
  (interactive)
  (when (null uko-spell-next-letter-list)
    (setq uko-spell-next-letter-list (reverse uko-spell-prev-letter-list))
    (setq uko-spell-prev-letter-list '())
    )
  (push (char-after) uko-spell-prev-letter-list)
  (let ((here (point)))
    (delete-char)
    (insert-char (pop uko-spell-next-letter-list))
    (goto-char here)
    ) )


;; Show previous letter from uko-keyboard-layout
(defun uko-spell-prev-letter ()
  (interactive)
  (when (null uko-spell-prev-letter-list)
    (setq uko-spell-prev-letter-list (reverse uko-spell-next-letter-list))
    (setq uko-spell-next-letter-list '())
    )
  (push (char-after) uko-spell-next-letter-list)
  (let ((here (point)))
    (delete-char)
    (insert-char (pop uko-spell-prev-letter-list))
    (goto-char here)
    ) )
  
(defun uko-spell-done-letter ()
  (interactive)
  (if (= (+ (point) 2) (extent-end-position uko-expand-extent))
    (progn
      (uko-select (substring (extent-string uko-expand-extent) 0 -1))
      (setq uko-last-proposal-code "")
      )
    (forward-char)
    (uko-spell-letter (char-after)) 
    ) 
  )
  

