+(defun calculator-rotate-displayer (&optional new-disp)
+ "Switch to the next displayer on the `calculator-displayers' list.
+Can be called with an optional argument NEW-DISP to force rotation to
+that argument."
+ (interactive)
+ (setq calculator-displayers
+ (if (and new-disp (memq new-disp calculator-displayers))
+ (let ((tmp nil))
+ (while (not (eq (car calculator-displayers) new-disp))
+ (setq tmp (cons (car calculator-displayers) tmp))
+ (setq calculator-displayers (cdr calculator-displayers)))
+ (setq calculator-displayers
+ (nconc calculator-displayers (nreverse tmp))))
+ (nconc (cdr calculator-displayers)
+ (list (car calculator-displayers)))))
+ (message "Using %s." (cadr (car calculator-displayers)))
+ (if calculator-electric-mode
+ (progn (sit-for 1) (message nil)))
+ (calculator-enter))
+
+(defun calculator-rotate-displayer-back ()
+ "Like `calculator-rotate-displayer', but rotates modes back."
+ (interactive)
+ (calculator-rotate-displayer (car (last calculator-displayers))))
+
+(defun calculator-displayer-prev ()
+ "Send the current displayer function a 'left argument.
+This is used to modify display arguments (if the current displayer
+function supports this)."
+ (interactive)
+ (and (car calculator-displayers)
+ (let ((disp (caar calculator-displayers)))
+ (cond ((symbolp disp) (funcall disp 'left))
+ ((and (consp disp) (eq 'std (car disp)))
+ (calculator-standard-displayer 'left (cadr disp)))))))
+
+(defun calculator-displayer-next ()
+ "Send the current displayer function a 'right argument.
+This is used to modify display arguments (if the current displayer
+function supports this)."
+ (interactive)
+ (and (car calculator-displayers)
+ (let ((disp (caar calculator-displayers)))
+ (cond ((symbolp disp) (funcall disp 'right))
+ ((and (consp disp) (eq 'std (car disp)))
+ (calculator-standard-displayer 'right (cadr disp)))))))
+
+(defun calculator-remove-zeros (numstr)
+ "Get a number string NUMSTR and remove unnecessary zeroes.
+the behavior of this function is controlled by
+`calculator-remove-zeros'."
+ (cond ((and (eq calculator-remove-zeros t)
+ (string-match "\\.0+\\([eE][+-]?[0-9]*\\)?$" numstr))
+ ;; remove all redundant zeros leaving an integer
+ (if (match-beginning 1)
+ (concat (substring numstr 0 (match-beginning 0))
+ (match-string 1 numstr))
+ (substring numstr 0 (match-beginning 0))))
+ ((and calculator-remove-zeros
+ (string-match
+ "\\..\\([0-9]*[1-9]\\)?\\(0+\\)\\([eE][+-]?[0-9]*\\)?$"
+ numstr))
+ ;; remove zeros, except for first after the "."
+ (if (match-beginning 3)
+ (concat (substring numstr 0 (match-beginning 2))
+ (match-string 3 numstr))
+ (substring numstr 0 (match-beginning 2))))
+ (t numstr)))
+
+(defun calculator-standard-displayer (num char)
+ "Standard display function, used to display NUM.
+Its behavior is determined by `calculator-number-digits' and the given
+CHAR argument (both will be used to compose a format string). If the
+char is \"n\" then this function will choose one between %f or %e, this
+is a work around %g jumping to exponential notation too fast.
+
+The special 'left and 'right symbols will make it change the current
+number of digits displayed (`calculator-number-digits').
+
+It will also remove redundant zeros from the result."
+ (if (symbolp num)
+ (cond ((eq num 'left)
+ (and (> calculator-number-digits 0)
+ (setq calculator-number-digits
+ (1- calculator-number-digits))
+ (calculator-enter)))
+ ((eq num 'right)
+ (setq calculator-number-digits
+ (1+ calculator-number-digits))
+ (calculator-enter)))
+ (let ((str (if (zerop num)
+ "0"
+ (format
+ (concat "%."
+ (number-to-string calculator-number-digits)
+ (if (eq char ?n)
+ (let ((n (abs num)))
+ (if (or (< n 0.001) (> n 1e8)) "e" "f"))
+ (string char)))
+ num))))
+ (calculator-remove-zeros str))))
+
+(defun calculator-eng-display (num)
+ "Display NUM in engineering notation.
+The number of decimal digits used is controlled by
+`calculator-number-digits', so to change it at runtime you have to use
+the 'left or 'right when one of the standard modes is used."
+ (if (symbolp num)
+ (cond ((eq num 'left)
+ (setq calculator-eng-extra
+ (if calculator-eng-extra
+ (1+ calculator-eng-extra)
+ 1))
+ (let ((calculator-eng-tmp-show t)) (calculator-enter)))
+ ((eq num 'right)
+ (setq calculator-eng-extra
+ (if calculator-eng-extra
+ (1- calculator-eng-extra)
+ -1))
+ (let ((calculator-eng-tmp-show t)) (calculator-enter))))
+ (let ((exp 0))
+ (and (not (= 0 num))
+ (progn
+ (while (< (abs num) 1.0)
+ (setq num (* num 1000.0)) (setq exp (- exp 3)))
+ (while (> (abs num) 999.0)
+ (setq num (/ num 1000.0)) (setq exp (+ exp 3)))
+ (and calculator-eng-tmp-show
+ (not (= 0 calculator-eng-extra))
+ (let ((i calculator-eng-extra))
+ (while (> i 0)
+ (setq num (* num 1000.0)) (setq exp (- exp 3))
+ (setq i (1- i)))
+ (while (< i 0)
+ (setq num (/ num 1000.0)) (setq exp (+ exp 3))
+ (setq i (1+ i)))))))
+ (or calculator-eng-tmp-show (setq calculator-eng-extra nil))
+ (let ((str (format (concat "%." (number-to-string
+ calculator-number-digits)
+ "f")
+ num)))
+ (concat (let ((calculator-remove-zeros
+ ;; make sure we don't leave integers
+ (and calculator-remove-zeros 'x)))
+ (calculator-remove-zeros str))
+ "e" (number-to-string exp))))))
+