;;; uko-predict.el -- decode the input string, (formerly: uko-noclient.el, merged with uko-proposals.el)

;; 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-predict.el,v 1.7 2004/01/21 13:53:50 rriipp Exp $


;; uko-predict used to be split into uko-proposals.el and uko-predict.el

;;;; UKO_PREDICT
;;;; Handles decoding of input keypad numbers and
;;;; searches for matchings in the dictionary file.
;;;; The matchings are displayed in the prediction window in order of their probability

;;;; ------------------------------------------------------------------------



(defvar uko-noclient-retrieve-code nil)

(defvar uko-proposal-buffer nil
  "Buffer containing the matches that are retrieved from the server.")

(defvar uko-proposal-window nil
  "Window where proposals are displayed.")

(defvar uko-proposal-empty-buffer nil
  "Buffer if proposals should not be displayed.")

(defvar uko-proposal-buffer-extent nil
  "Extent used for highlighting the current match in UKO-PROPOSAL-BUFFER.")

(defvar uko-proposal-block-size 5
  "Size of block that is selected if more than MATCHES-PREVIEW-NUM'\
matches are available."
)

(defvar uko-proposal-preview-num 200
  "Number of matches that are shown successively at the beginning of retrieval."
)

(defvar uko-proposal-block-start 0)

(defvar uko-proposal-window-width 15
  "Width of the proposal window.") ;;Sollten wir diese nicht vieleicht customizable machen?

(defvar uko-proposal-keep-window t)   ;;Was ist der Nutzen hiervon?

(defvar uko-proposal-hide-preblock t)





(defun uko-disconnect ()
  "Not implemented yet"
  nil)


;; Ensure, that the necessary dictionary file is loaded and available.
(defun uko-connect ()
  "Ensure that uko-noclient-dictionary-buffer contains the content of uko-dictionary-file."
  (save-current-buffer
    (set-buffer uko-noclient-dictionary-buffer)	; Set current buffer
    (goto-char (point-min))		; Set point to the beginning of the buffer
    (when (eobp)			; If the buffer is empty insert the dictionary-file
      (insert-file (concat uko-emacs-directory uko-dictionary-file))
    ) ) )

;; Start process of decoding input, i.e. retrieve all matching words from dictionary file and sort them by their probability.
;; Finally display them in the Prediction window.
(defun uko-retrieve (code &optional part)
  "Retrieve all matchings for inserted code.
Set buffer to uko-proposal-buffer, delete all, retrieve next."
  ; Save the current Buffer, execute the listed Methods, and restore it.
  (save-current-buffer
    (set-buffer uko-proposal-buffer)	; set active buffer to uko-proposal-buffer
    (delete-region (point-min) (point-max)) ; delete all text in uko-proposal-buffer
    (set-buffer uko-noclient-dictionary-buffer)	; set active buffer to uko-noclient-dictionary-buffer (contains dictionary)
    (goto-char (point-min))		; go to beginning of buffer
    )
  (setq uko-noclient-retrieve-code code)
  (uko-retrieve-next part)
  )


;; Search for matching words in the dictionary file and sort them among each other. 
(defun uko-retrieve-next (&optional part)
  "Search for matchings in dictionary-buffer. Sort them among each other."
  (let (find)
    (save-current-buffer
      (set-buffer uko-noclient-dictionary-buffer)
      (if (uko-search-forward uko-noclient-retrieve-code t (not part))
	  (progn
	    (beginning-of-line)
	    (let ((start (point)))
	      (forward-line 1)
	      (setq find (buffer-substring start (point)))
	      )
	    (insert-string find uko-proposal-buffer)
	    )
	(insert-string "\n" uko-proposal-buffer)
	)
      (forward-line -1 uko-proposal-buffer)
      ) ) )



(defun uko-complete (code)
  (interactive "s")
    (save-excursion
      (set-buffer uko-noclient-dictionary-buffer)
      (goto-char (point-min))
      (if (uko-search-forward code t nil)
	  (progn
	    (beginning-of-line)
	    (let ((start (point)))
	      (end-of-line)
	      (buffer-substring start (point))
	      ) )
	nil) ) )


(defun uko-proposal-init ()
  "Create the necesary buffers and initialize the proposal window if needed"
  (interactive)
  ;;Get the buffer for proposals
  (setq uko-proposal-buffer (get-buffer uko-proposal-buffer-name))
  ;;Create empty Buffer
  (setq uko-proposal-empty-buffer (get-buffer-create "*UKO Empty*"))
  (save-current-buffer
    ;;switch to proposal buffer
    (set-buffer uko-proposal-buffer)
    (local-set-key uko-physical-mouse-button 'uko-noop)
    ;;label modeline (statusbar) for this buffer
    (setq modeline-format (list " UKO Matches"))
    ;;switch to empty buffer
    (set-buffer uko-proposal-empty-buffer)
    (local-set-key uko-physical-mouse-button 'uko-noop)
    ;;label modeline
    (setq modeline-format (list " UKO Matches"))
    ;;switch back
    )
  (uko-proposal-clear-buffer)
  ;;If UKO-PROPOSAL-KEEP-WINDOW is true (Bedeutung der Variablen?), 
  ;;then initialize the proposal window
  (when uko-proposal-keep-window (uko-proposal-display-window) )
  )

(defun uko-proposal-clear-buffer ()
  "Delete the content of the proposal buffer"
  ;;Warum hier eigendlich save-excursion statt save-current-buffer?
  (save-excursion
    (set-buffer uko-proposal-buffer)
    (delete-region (point-min) (point-max))
    ) )

(defun uko-proposal-cancel ()
  (interactive)
  (set-window-buffer uko-proposal-window uko-proposal-empty-buffer)
  (uko-command-undo)
  )

(defun uko-proposal-display-window ()
  "Displays the proposal window, set size size of it and"
  (unless (window-live-p uko-proposal-window)
    (save-excursion
      (let ((width (- (window-width) uko-proposal-window-width)))
	(setq uko-proposal-window
	      ;;If there's enough space
	      (if (>= width uko-proposal-window-width)
		;;give it the prefered size
		(split-window nil width 'vertical)
		;;else do not specify the size
		(split-window)
		) )
	(set-window-buffer uko-proposal-window uko-proposal-empty-buffer)
	) ) ) )

(defun uko-proposals (code)
  (save-excursion
    (set-buffer uko-proposal-buffer)
    (unless uko-partial-complete (delete-region (point-min) (point-max)) (uko-retrieve code))
    (uko-retrieve uko-last-proposal-code uko-partial-complete)
    (while (not (eolp uko-proposal-buffer))
      (forward-line 1)
      (uko-retrieve-next)
      )
    (goto-char (point-min))
    )
  (setq uko-proposal-buffer-extent (make-extent 1 1 uko-proposal-buffer))
  (set-extent-property uko-proposal-buffer-extent 'face 'highlight)
  (setq uko-proposal-block-extent (make-extent 1 1 uko-proposal-buffer))
  (set-extent-property uko-proposal-block-extent 'face 'primary-selection)
  )

(defun uko-proposal-select ()
  (interactive)
  (uko-select (uko-get-proposal))
  (uko-proposal-clear-buffer)
  (when uko-proposal-hide-preblock
    (set-window-buffer uko-proposal-window uko-proposal-empty-buffer)
    )
  (uko-proposal-delete-window)
  )

(defun uko-proposal-delete-window ()
  (unless uko-proposal-keep-window
    (delete-window uko-proposal-window)
    ) )

(defun uko-get-proposal ()
  (save-current-buffer
    (set-buffer uko-proposal-buffer)
    (if (eolp) nil
      (let ((start (point)))
	(end-of-line)
	(prog1 
	    (buffer-string start (point))
	  (goto-char start)
	  ) ) ) ) )

;; deprecated:
(defun uko-proposal-next-preview ()
  (interactive)
  (if (null (uko-proposal-forward-line))
      (beep)
    (if (> (uko-proposal-linenumber) uko-proposal-preview-num)
	(uko-set-proposal-block-state)
      (uko-proposal-highlight-line)
      (uko-insert-proposal (uko-get-proposal))
      ) ) )

;; deprecated:
(defun uko-proposal-prev-preview ()
  (interactive)
  (if (null (uko-proposal-backward-line))
      (beep)
    (uko-proposal-highlight-line)
    (uko-insert-proposal (uko-get-proposal))
    ) )

;; deprecated:
(defun uko-proposal-next-block ()
  (interactive)
  (if (null (uko-proposal-forward-block))
      (beep)
    (uko-proposal-highlight-block)
    ) )

;; deprecated:
(defun uko-proposal-prev-block ()
  (interactive)
  (if (and (= (- (uko-proposal-linenumber) 1) uko-proposal-preview-num)
	   (> uko-proposal-preview-num 0) )
      (progn
	(uko-proposal-backward-line)
	(uko-set-proposal-preview-state)
	)
    (if (null (uko-proposal-backward-block))
      (beep)
    (uko-proposal-highlight-block)
    ) ) )

;; deprecated:
(defun uko-proposal-select-block ()
  (interactive)
  (save-current-buffer
    (set-buffer uko-proposal-buffer)
    (setq uko-proposal-block-start  (+ (uko-proposal-linenumber) uko-proposal-preview-num))
    (set-extent-endpoints 
      uko-proposal-block-extent (point) 
      (extent-end-position uko-proposal-buffer-extent) ) )
  (uko-proposal-highlight-line)
  (uko-insert-proposal (uko-get-proposal))
  (uko-set-proposal-intra-state)
    )

;; deprecated:
(defun uko-proposal-intra-next ()
  (interactive)
  (if (or (= (- (uko-proposal-linenumber) uko-proposal-block-start -1)
	     uko-proposal-block-size)
	  (not (uko-proposal-forward-line)) )
      (beep)
    (uko-proposal-highlight-line)
    (uko-insert-proposal (uko-get-proposal))
    ) )

;; deprecated:
(defun uko-proposal-intra-prev ()
  (interactive)
  (if (or (= (uko-proposal-linenumber) uko-proposal-block-start)
	   (not (uko-proposal-backward-line)) )
      (beep)
    (uko-proposal-highlight-line)
    (uko-insert-proposal (uko-get-proposal))
    ) )

;; deprecated:
(defun uko-proposal-intra-undo ()
  (interactive)
  (save-current-buffer
    (set-buffer uko-proposal-buffer)
    (goto-line uko-proposal-block-start)
    (set-extent-endpoints uko-proposal-block-extent (point-min) (point-min))
    )
  (uko-set-proposal-block-state)
  )

;; deprecated:
(defun uko-proposal-forward-line ()
  (save-current-buffer
    (set-buffer uko-proposal-buffer)
    (forward-line 1)
    (if (eolp)
	(progn (forward-line -1) nil)
      t
      ) ) )

;; deprecated:
(defun uko-proposal-backward-line ()
  (save-current-buffer
    (set-buffer uko-proposal-buffer)
    (if (bobp)
	nil
      (forward-line -1)
      t
      ) ) )

;; deprecated:
(defun uko-proposal-linenumber ()
  (save-current-buffer
    (set-buffer uko-proposal-buffer)
    (1+ (count-lines (point-min) (point)))
    ) )

;; deprecated:
(defun uko-proposal-highlight-line ()
  (save-current-buffer
    (set-buffer uko-proposal-buffer)
    (let ((here (point)))
      (forward-line 1)
      (set-extent-endpoints uko-proposal-buffer-extent here (point))
      (save-selected-window
	(let ((window  (get-buffer-window uko-proposal-buffer)))
	  (if (and window (not (pos-visible-in-window-p here window)))
	      (set-window-start window here)
	    ) ) )
      (goto-char here)
      ) ) )

;; deprecated:
(defun uko-proposal-forward-block ()
  (save-current-buffer
    (set-buffer uko-proposal-buffer)
    (let ((here (point)))
      (forward-line uko-proposal-block-size)
      (if (and (= (count-lines here (point)) uko-proposal-block-size) 
	       (not (eobp)) (not (eolp)) )
	  t
	(goto-char here)
	nil
	) ) ) )

;; deprecated:
(defun uko-proposal-backward-block ()
  (save-current-buffer
    (set-buffer uko-proposal-buffer)
    (let ((here (point)))
      (forward-line (- uko-proposal-block-size))
      (if (= (count-lines here (point)) uko-proposal-block-size)
	  t
	(goto-char here)
	nil
	) ) ) )

;; deprecated:
(defun uko-proposal-highlight-block ()
  (save-current-buffer
    (set-buffer uko-proposal-buffer)
;     (forward-line uko-proposal-preview-num)
    (let ((here (point)) (lines uko-proposal-block-size))
      (while (and (> lines 0) (not (eolp)))
	(forward-line 1)
	(setq lines (- lines 1))
	)
      (set-extent-endpoints uko-proposal-buffer-extent here (point))
      (save-selected-window
	(let ((window  (get-buffer-window uko-proposal-buffer)))
	  (if (not (and 
		    (pos-visible-in-window-p here window) 
		  (pos-visible-in-window-p (point) window)))
	    (set-window-start window here)
	    ) ) )
      (goto-char here)
      ) ) )
	
(defun uko-proposal-show-buffer ()
  (set-window-buffer uko-proposal-window uko-proposal-buffer)
  )