Commit 94be2532 authored by Jonathan Yavner's avatar Jonathan Yavner
Browse files

Delete function ses-build-load-map and distribute its functions to

defconst's for the three maps.  Add menus.  Use "ses--" prefixes for
buffer-local variables.  Use (point-min) instead of 1, even when we know the
buffer is unnarrowed.  New function ses-read-number duplicates some code
from interactive "N" spec.
parent 84456793
;;;; ses.el -- Simple Emacs Spreadsheet
;;; ses.el -- Simple Emacs Spreadsheet
;; Copyright (C) 2002,03,04 Free Software Foundation, Inc.
......@@ -24,11 +24,12 @@
;; Boston, MA 02111-1307, USA.
;;; To-do list:
;; * Use $ or … for truncated fields
;; * Add command to make a range of columns be temporarily invisible.
;; * Allow paste of one cell to a range of cells -- copy formula to each.
;; * Do something about control characters & octal codes in cell print
;; areas. Currently they distort the columnar appearance, but fixing them
;; seems like too much work? Use text-char-description?
;; areas. Use string-width?
;; * Input validation functions. How specified?
;; * Menubar and popup menus.
;; * Faces (colors & styles) in print cells.
;; * Move a column by dragging its letter in the header line.
;; * Left-margin column for row number.
......@@ -87,16 +88,119 @@ usually runs a cursor-movement function. Each function is called with ARG=1."
(defvar ses-read-printer-history nil
"List of printer functions that have been typed in.")
(defvar ses-mode-map nil
"Local keymap for Simple Emacs Spreadsheet.")
(easy-menu-define ses-header-line-menu nil
"Context menu when mouse-3 is used on the header-line in an SES buffer."
'("SES header row"
["Set current row" ses-set-header-row t]
["Unset row" ses-unset-header-row (> header-row 0)]))
(defvar ses-mode-print-map nil
"Local keymap for SES print area.")
(defconst ses-mode-map
(let ((keys `("\C-c\M-\C-l" ses-reconstruct-all
"\C-c\C-l" ses-recalculate-all
"\C-c\C-n" ses-renarrow-buffer
"\C-c\C-c" ses-recalculate-cell
"\C-c\M-\C-s" ses-sort-column
"\C-c\M-\C-h" ses-set-header-row
"\C-c\C-t" ses-truncate-cell
"\C-c\C-j" ses-jump
"\C-c\C-p" ses-read-default-printer
"\M-\C-l" ses-reprint-all
[?\S-\C-l] ses-reprint-all
[header-line down-mouse-3] ,ses-header-line-menu
[header-line mouse-2] ses-sort-column-click))
(newmap (make-sparse-keymap)))
(while keys
(define-key (1value newmap) (car keys) (cadr keys))
(setq keys (cddr keys)))
newmap)
"Local keymap for Simple Emacs Spreadsheet.")
(defvar ses-mode-edit-map nil
(easy-menu-define ses-menu ses-mode-map
"Menu bar menu for SES."
'("SES"
["Insert row" ses-insert-row (ses-in-print-area)]
["Delete row" ses-delete-row (ses-in-print-area)]
["Insert column" ses-insert-column (ses-in-print-area)]
["Delete column" ses-delete-column (ses-in-print-area)]
["Set column printer" ses-read-column-printer t]
["Set column width" ses-set-column-width t]
["Set default printer" ses-read-default-printer t]
["Jump to cell" ses-jump t]
["Set cell printer" ses-read-cell-printer t]
["Recalculate cell" ses-recalculate-cell t]
["Truncate cell display" ses-truncate-cell t]
["Export values" ses-export-tsv t]
["Export formulas" ses-export-tsf t]))
(defconst ses-mode-edit-map
(let ((keys '("\C-c\C-r" ses-insert-range
"\C-c\C-s" ses-insert-ses-range
[S-mouse-3] ses-insert-range-click
[C-S-mouse-3] ses-insert-ses-range-click
"\M-\C-i" lisp-complete-symbol))
(newmap (make-sparse-keymap)))
(set-keymap-parent newmap minibuffer-local-map)
(while keys
(define-key newmap (car keys) (cadr keys))
(setq keys (cddr keys)))
newmap)
"Local keymap for SES minibuffer cell-editing.")
;Key map used for 'x' key.
;Local keymap for SES print area
(defalias 'ses-mode-print-map
(let ((keys '([backtab] backward-char
[tab] ses-forward-or-insert
"\C-i" ses-forward-or-insert ;Needed for ses-coverage.el?
"\M-o" ses-insert-column
"\C-o" ses-insert-row
"\C-m" ses-edit-cell
"\M-k" ses-delete-column
"\M-y" ses-yank-pop
"\C-k" ses-delete-row
"\C-j" ses-append-row-jump-first-column
"\M-h" ses-mark-row
"\M-H" ses-mark-column
"\C-d" ses-clear-cell-forward
"\C-?" ses-clear-cell-backward
"(" ses-read-cell
"\"" ses-read-cell
"'" ses-read-symbol
"=" ses-edit-cell
"j" ses-jump
"p" ses-read-cell-printer
"w" ses-set-column-width
"x" ses-export-keymap
"\M-p" ses-read-column-printer))
(repl '(;;We'll replace these wherever they appear in the keymap
clipboard-kill-region ses-kill-override
end-of-line ses-end-of-line
kill-line ses-delete-row
kill-region ses-kill-override
open-line ses-insert-row))
(numeric "0123456789.-")
(newmap (make-keymap)))
;;Get rid of printables
(suppress-keymap newmap t)
;;These keys insert themselves as the beginning of a numeric value
(dotimes (x (length numeric))
(define-key newmap (substring numeric x (1+ x)) 'ses-read-cell))
;;Override these global functions wherever they're bound
(while repl
(substitute-key-definition (car repl) (cadr repl) newmap
(current-global-map))
(setq repl (cddr repl)))
;;Apparently substitute-key-definition doesn't catch this?
(define-key newmap [(menu-bar) edit cut] 'ses-kill-override)
;;Define our other local keys
(while keys
(define-key newmap (car keys) (cadr keys))
(setq keys (cddr keys)))
newmap))
;;Helptext for ses-mode wants keymap as variable, not function
(defconst ses-mode-print-map (symbol-function 'ses-mode-print-map))
;;Key map used for 'x' key.
(defalias 'ses-export-keymap
(let ((map (make-sparse-keymap "SES export")))
(define-key map "T" (cons " tab-formulas" 'ses-export-tsf))
......@@ -132,8 +236,9 @@ usually runs a cursor-movement function. Each function is called with ARG=1."
REFERENCES.")
(defconst ses-paramlines-plist
'(column-widths 2 col-printers 3 default-printer 4 header-row 5
file-format 8 numrows 9 numcols 10)
'(ses--col-widths 2 ses--col-printers 3 ses--default-printer 4
ses--header-row 5 ses--file-format 8 ses--numrows 9
ses--numcols 10)
"Offsets from last cell line to various parameter lines in the data area
of a spreadsheet.")
......@@ -150,11 +255,13 @@ default printer and then modify its output.")
(eval-and-compile
(defconst ses-localvars
'(blank-line cells col-printers column-widths curcell curcell-overlay
default-printer deferred-narrow deferred-recalc deferred-write
file-format header-hscroll header-row header-string linewidth
mode-line-process next-line-add-newlines numcols numrows
symbolic-formulas transient-mark-mode)
'(ses--blank-line ses--cells ses--col-printers ses--col-widths ses--curcell
ses--curcell-overlay ses--default-printer ses--deferred-narrow
ses--deferred-recalc ses--deferred-write ses--file-format
ses--header-hscroll ses--header-row ses--header-string ses--linewidth
ses--numcols ses--numrows ses--symbolic-formulas
;;Global variables that we override
mode-line-process next-line-add-newlines transient-mark-mode)
"Buffer-local variables used by SES."))
;;When compiling, create all the buffer locals and give them values
......@@ -195,7 +302,7 @@ when to emit a progress message.")
(defmacro ses-get-cell (row col)
"Return the cell structure that stores information about cell (ROW,COL)."
`(aref (aref cells ,row) ,col))
`(aref (aref ses--cells ,row) ,col))
(defmacro ses-cell-symbol (row &optional col)
"From a CELL or a pair (ROW,COL), get the symbol that names the local-variable holding its value. (0,0) => A1."
......@@ -220,11 +327,11 @@ functions refer to its value."
(defmacro ses-col-width (col)
"Return the width for column COL."
`(aref column-widths ,col))
`(aref ses--col-widths ,col))
(defmacro ses-col-printer (col)
"Return the default printer for column COL."
`(aref col-printers ,col))
`(aref ses--col-printers ,col))
(defmacro ses-sym-rowcol (sym)
"From a cell-symbol SYM, gets the cons (row . col). A1 => (0 . 0). Result
......@@ -246,7 +353,7 @@ PRINTER are deferred until first use."
(stringp printer)
(eq safe-functions t)
(setq printer `(ses-safe-printer ,printer)))
(aset (aref cells (car rowcol))
(aset (aref ses--cells (car rowcol))
(cdr rowcol)
(vector sym formula printer references)))
(set sym value)
......@@ -255,39 +362,39 @@ PRINTER are deferred until first use."
(defmacro ses-column-widths (widths)
"Load the vector of column widths from the spreadsheet file. This is a
macro to prevent propagate-on-load viruses."
(or (and (vectorp widths) (= (length widths) numcols))
(or (and (vectorp widths) (= (length widths) ses--numcols))
(error "Bad column-width vector"))
;;To save time later, we also calculate the total width of each line in the
;;print area (excluding the terminating newline)
(setq column-widths widths
linewidth (apply '+ -1 (mapcar '1+ widths))
blank-line (concat (make-string linewidth ? ) "\n"))
(setq ses--col-widths widths
ses--linewidth (apply '+ -1 (mapcar '1+ widths))
ses--blank-line (concat (make-string ses--linewidth ? ) "\n"))
t)
(defmacro ses-column-printers (printers)
"Load the vector of column printers from the spreadsheet file and checks
them for safety. This is a macro to prevent propagate-on-load viruses."
(or (and (vectorp printers) (= (length printers) numcols))
(or (and (vectorp printers) (= (length printers) ses--numcols))
(error "Bad column-printers vector"))
(dotimes (x numcols)
(dotimes (x ses--numcols)
(aset printers x (ses-safe-printer (aref printers x))))
(setq col-printers printers)
(setq ses--col-printers printers)
(mapc 'ses-printer-record printers)
t)
(defmacro ses-default-printer (def)
"Load the global default printer from the spreadsheet file and checks it
for safety. This is a macro to prevent propagate-on-load viruses."
(setq default-printer (ses-safe-printer def))
(setq ses--default-printer (ses-safe-printer def))
(ses-printer-record def)
t)
(defmacro ses-header-row (row)
"Load the header row from the spreadsheet file and checks it
for safety. This is a macro to prevent propagate-on-load viruses."
(or (and (wholenump row) (< row numrows))
(or (and (wholenump row) (< row ses--numrows))
(error "Bad header-row"))
(setq header-row row)
(setq ses--header-row row)
t)
(defmacro ses-dotimes-msg (spec msg &rest body)
......@@ -405,7 +512,7 @@ checking that it is a valid printer function."
for this spreadsheet."
(when (and (eq (car-safe formula) 'quote)
(symbolp (cadr formula)))
(add-to-list 'symbolic-formulas
(add-to-list 'ses--symbolic-formulas
(list (symbol-name (cadr formula))))))
(defun ses-column-letter (col)
......@@ -451,7 +558,7 @@ for this spreadsheet."
"Flags the header string for update. Upon undo, the header string will be
updated again."
(push '(ses-reset-header-string) buffer-undo-list)
(setq header-hscroll -1))
(setq ses--header-hscroll -1))
;;Split this code off into a function to avoid coverage-testing difficulties
(defun ses-time-check (format arg)
......@@ -480,7 +587,7 @@ cell (ROW,COL). This is undoable. The cell's data will be updated through
(ses-set-with-undo (ses-cell-symbol cell) val)
(ses-aset-with-undo cell elt val)))
(if change
(add-to-list 'deferred-write (cons row col))))
(add-to-list 'ses--deferred-write (cons row col))))
nil) ;Make coverage-tester happy
(defun ses-cell-set-formula (row col formula)
......@@ -496,7 +603,7 @@ means Emacs will crash if FORMULA contains a circular list."
(newref (ses-formula-references formula))
(inhibit-quit t)
x xrow xcol)
(add-to-list 'deferred-recalc sym)
(add-to-list 'ses--deferred-recalc sym)
;;Delete old references from this cell. Skip the ones that are also
;;in the new list.
(dolist (ref oldref)
......@@ -542,10 +649,10 @@ the old and FORCE is nil."
;;Don't lose the *skip* - previous field spans this one
(setq newval '*skip*))
(when (or force (not (eq newval oldval)))
(add-to-list 'deferred-write (cons row col)) ;In case force=t
(add-to-list 'ses--deferred-write (cons row col)) ;In case force=t
(ses-set-cell row col 'value newval)
(dolist (ref (ses-cell-references cell))
(add-to-list 'deferred-recalc ref))))
(add-to-list 'ses--deferred-recalc ref))))
(setq printer-error (ses-print-cell row col))
(or formula-error printer-error)))
......@@ -558,31 +665,31 @@ the old and FORCE is nil."
"Recalculate cells in LIST, checking for dependency loops. Prints
progress messages every second. Dependent cells are not recalculated
if the cell's value is unchanged if FORCE is nil."
(let ((deferred-recalc list)
(nextlist list)
(pos (point))
(let ((ses--deferred-recalc list)
(nextlist list)
(pos (point))
curlist prevlist rowcol formula)
(with-temp-message " "
(while (and deferred-recalc (not (equal nextlist prevlist)))
(while (and ses--deferred-recalc (not (equal nextlist prevlist)))
;;In each loop, recalculate cells that refer only to other cells that
;;have already been recalculated or aren't in the recalculation
;;region. Repeat until all cells have been processed or until the
;;set of cells being worked on stops changing.
(if prevlist
(message "Recalculating... (%d cells left)"
(length deferred-recalc)))
(setq curlist deferred-recalc
deferred-recalc nil
prevlist nextlist)
(length ses--deferred-recalc)))
(setq curlist ses--deferred-recalc
ses--deferred-recalc nil
prevlist nextlist)
(while curlist
(setq rowcol (ses-sym-rowcol (car curlist))
formula (ses-cell-formula (car rowcol) (cdr rowcol)))
(or (catch 'ref
(dolist (ref (ses-formula-references formula))
(when (or (memq ref curlist)
(memq ref deferred-recalc))
(memq ref ses--deferred-recalc))
;;This cell refers to another that isn't done yet
(add-to-list 'deferred-recalc (car curlist))
(add-to-list 'ses--deferred-recalc (car curlist))
(throw 'ref t))))
;;ses-update-cells is called from post-command-hook, so
;;inhibit-quit is implicitly bound to t.
......@@ -591,19 +698,19 @@ if the cell's value is unchanged if FORCE is nil."
(error "Quit"))
(ses-calculate-cell (car rowcol) (cdr rowcol) force))
(setq curlist (cdr curlist)))
(dolist (ref deferred-recalc)
(dolist (ref ses--deferred-recalc)
(add-to-list 'nextlist ref))
(setq nextlist (sort (copy-sequence nextlist) 'string<))
(if (equal nextlist prevlist)
;;We'll go around the loop one more time.
(add-to-list 'nextlist t)))
(when deferred-recalc
(when ses--deferred-recalc
;;Just couldn't finish these
(dolist (x deferred-recalc)
(dolist (x ses--deferred-recalc)
(let ((rowcol (ses-sym-rowcol x)))
(ses-set-cell (car rowcol) (cdr rowcol) 'value '*error*)
(1value (ses-print-cell (car rowcol) (cdr rowcol)))))
(error "Circular references: %s" deferred-recalc))
(error "Circular references: %s" ses--deferred-recalc))
(message " "))
;;Can't use save-excursion here: if the cell under point is
;;updated, save-excusion's marker will move past the cell.
......@@ -614,46 +721,50 @@ if the cell's value is unchanged if FORCE is nil."
;;;; The print area
;;;----------------------------------------------------------------------------
(defun ses-in-print-area ()
"Returns t if point is in print area of spreadsheet."
(eq (get-text-property (point) 'keymap) 'ses-mode-print-map))
;;;We turn off point-motion-hooks and explicitly position the cursor, in case
;;;the intangible properties have gotten screwed up (e.g., when
;;;ses-goto-print is called during a recursive ses-print-cell).
(defun ses-goto-print (row col)
"Move point to print area for cell (ROW,COL)."
(let ((inhibit-point-motion-hooks t))
(goto-char 1)
(goto-char (point-min))
(forward-line row)
(dotimes (c col)
(forward-char (1+ (ses-col-width c))))))
(defun ses-set-curcell ()
"Sets `curcell' to the current cell symbol, or a cons (BEG,END) for a
"Sets `ses--curcell' to the current cell symbol, or a cons (BEG,END) for a
region, or nil if cursor is not at a cell."
(if (or (not mark-active)
deactivate-mark
(= (region-beginning) (region-end)))
;;Single cell
(setq curcell (get-text-property (point) 'intangible))
(setq ses--curcell (get-text-property (point) 'intangible))
;;Range
(let ((bcell (get-text-property (region-beginning) 'intangible))
(ecell (get-text-property (1- (region-end)) 'intangible)))
(setq curcell (if (and bcell ecell)
(cons bcell ecell)
nil))))
(setq ses--curcell (if (and bcell ecell)
(cons bcell ecell)
nil))))
nil)
(defun ses-check-curcell (&rest args)
"Signal an error if curcell is inappropriate. The end marker is
"Signal an error if ses--curcell is inappropriate. The end marker is
appropriate if some argument is 'end. A range is appropriate if some
argument is 'range. A single cell is appropriate unless some argument is
'needrange."
(if (eq curcell t)
(if (eq ses--curcell t)
;;curcell recalculation was postponed, but user typed ahead
(ses-set-curcell))
(cond
((not curcell)
((not ses--curcell)
(or (memq 'end args)
(error "Not at cell")))
((consp curcell)
((consp ses--curcell)
(or (memq 'range args)
(memq 'needrange args)
(error "Can't use a range")))
......@@ -689,7 +800,7 @@ preceding cell has spilled over."
;;Print the value
(setq text (ses-call-printer (or printer
(ses-col-printer col)
default-printer)
ses--default-printer)
value))
(if (consp ses-call-printer-return)
;;Printer returned an error
......@@ -708,7 +819,7 @@ preceding cell has spilled over."
;;Spill over into following cells, if possible
(let ((maxwidth width))
(while (and (> len maxwidth)
(< maxcol numcols)
(< maxcol ses--numcols)
(or (not (setq x (ses-cell-value row maxcol)))
(eq x '*skip*)))
(unless x
......@@ -748,7 +859,7 @@ preceding cell has spilled over."
(delete-char (1+ (length text)))
;;We use concat instead of inserting separate strings in order to
;;reduce the number of cells in the undo list.
(setq x (concat text (if (< maxcol numcols) " " "\n")))
(setq x (concat text (if (< maxcol ses--numcols) " " "\n")))
;;We use set-text-properties to prevent a wacky print function
;;from inserting rogue properties, and to ensure that the keymap
;;property is inherited (is it a bug that only unpropertied strings
......@@ -759,15 +870,16 @@ preceding cell has spilled over."
(ses-cell-symbol cell))
(when (and (zerop row) (zerop col))
;;Reconstruct special beginning-of-buffer attributes
(put-text-property 1 (point) 'keymap 'ses-mode-print-map)
(put-text-property 1 (point) 'read-only 'ses)
(put-text-property 1 2 'front-sticky t)))
(if (= row (1- header-row))
(put-text-property (point-min) (point) 'keymap 'ses-mode-print-map)
(put-text-property (point-min) (point) 'read-only 'ses)
(put-text-property (point-min) (1+ (point-min)) 'front-sticky t)))
(if (= row (1- ses--header-row))
;;This line is part of the header - force recalc
(ses-reset-header-string))
;;If this cell (or a preceding one on the line) previously spilled over
;;and has gotten shorter, redraw following cells on line recursively.
(when (and (< maxcol numcols) (eq (ses-cell-value row maxcol) '*skip*))
(when (and (< maxcol ses--numcols)
(eq (ses-cell-value row maxcol) '*skip*))
(ses-set-cell row maxcol 'value nil)
(ses-print-cell row maxcol))
;;Return to start of cell
......@@ -808,12 +920,12 @@ COL=NUMCOLS. Deletes characters if CHANGE < 0. Caller should bind
inhibit-quit to t."
(let ((inhibit-read-only t)
(blank (if (> change 0) (make-string change ? )))
(at-end (= col numcols)))
(ses-set-with-undo 'linewidth (+ linewidth change))
(at-end (= col ses--numcols)))
(ses-set-with-undo 'ses--linewidth (+ ses--linewidth change))
;;ses-set-with-undo always returns t for strings.
(1value (ses-set-with-undo 'blank-line
(concat (make-string linewidth ? ) "\n")))
(dotimes (row numrows)
(1value (ses-set-with-undo 'ses--blank-line
(concat (make-string ses--linewidth ? ) "\n")))
(dotimes (row ses--numrows)
(ses-goto-print row col)
(when at-end
;;Insert new columns before newline
......@@ -841,21 +953,22 @@ cell (ROW,COL) has changed."
;;;----------------------------------------------------------------------------
(defun ses-goto-data (def &optional col)
"Move point to data area for (DEF,COL). If DEF is a row number, COL is the
column number for a data cell -- otherwise DEF is one of the symbols
column-widths, col-printers, default-printer, numrows, or numcols."
"Move point to data area for (DEF,COL). If DEF is a row
number, COL is the column number for a data cell -- otherwise DEF
is one of the symbols ses--col-widths, ses--col-printers,
ses--default-printer, ses--numrows, or ses--numcols."
(if (< (point-max) (buffer-size))
(setq deferred-narrow t))
(setq ses--deferred-narrow t))
(widen)
(let ((inhibit-point-motion-hooks t)) ;In case intangible attrs are wrong
(goto-char 1)
(goto-char (point-min))
(if col
;;It's a cell
(forward-line (+ numrows 2 (* def (1+ numcols)) col))
(forward-line (+ ses--numrows 2 (* def (1+ ses--numcols)) col))
;;Convert def-symbol to offset
(setq def (plist-get ses-paramlines-plist def))
(or def (signal 'args-out-of-range nil))
(forward-line (+ (* numrows (+ numcols 2)) def)))))
(forward-line (+ (* ses--numrows (+ ses--numcols 2)) def)))))
(defun ses-set-parameter (def value &optional elem)
"Sets parameter DEF to VALUE (with undo) and writes the value to the data
......@@ -870,19 +983,19 @@ be set to VALUE."
(ses-aset-with-undo (symbol-value def) elem value)
(ses-set-with-undo def value))
(let ((inhibit-read-only t)
(fmt (plist-get '(column-widths "(ses-column-widths %S)"
col-printers "(ses-column-printers %S)"
default-printer "(ses-default-printer %S)"
header-row "(ses-header-row %S)"
file-format " %S ;SES file-format"
numrows " %S ;numrows"
numcols " %S ;numcols")
(fmt (plist-get '(ses--column-widths "(ses-column-widths %S)"
ses--col-printers "(ses-column-printers %S)"
ses--default-printer "(ses-default-printer %S)"
ses--header-row "(ses-header-row %S)"
ses--file-format " %S ;SES file-format"
ses--numrows " %S ;numrows"
ses--numcols " %S ;numcols")
def)))
(delete-region (point) (line-end-position))
(insert (format fmt (symbol-value def))))))
(defun ses-write-cells ()
"`deferred-write' is a list of (ROW,COL) for cells to be written from
"`ses--deferred-write' is a list of (ROW,COL) for cells to be written from
buffer-local variables to data area. Newlines in the data are escaped."
(let* ((inhibit-read-only t)
(print-escape-newlines t)
......@@ -890,10 +1003,10 @@ buffer-local variables to data area. Newlines in the data are escaped."
(setq ses-start-time (float-time))
(with-temp-message " "
(save-excursion
(while deferred-write
(while ses--deferred-write
(ses-time-check "Writing... (%d cells left)"
'(length deferred-write))
(setq rowcol (pop deferred-write)
'(length ses--deferred-write))
(setq rowcol (pop ses--deferred-write)
row (car rowcol)
col (cdr rowcol)
cell (ses-get-cell row col)
......@@ -1013,7 +1126,7 @@ by (ROWINCR,COLINCR)."
(setq row (+ row rowincr)
col (+ col colincr))
(if (and (>= row startrow) (>= col startcol)
(< row numrows) (< col numcols))
(< row ses--numrows) (< col ses--numcols))
;;Relocate this variable
(ses-create-cell-symbol row col)
;;Delete reference to a deleted cell
......@@ -1050,7 +1163,8 @@ if the range was altered."
(if (not max)
(if (> rowincr 0)
;;Trying to insert a nonexistent row
(setq max (ses-create-cell-symbol (1- numrows) (cdr minrowcol)))
(setq max (ses-create-cell-symbol (1- ses--numrows)
(cdr minrowcol)))
;;End of range is being deleted
(setq max (ses-create-cell-symbol (1- startrow) (cdr minrowcol))
ses-relocate-return 'range))
......@@ -1070,7 +1184,8 @@ if the range was altered."
(if (not max)
(if (> colincr 0)
;;Trying to insert a nonexistent column
(setq max (ses-create-cell-symbol (car maxrowcol) (1- numcols)))
(setq max (ses-create-cell-symbol (car maxrowcol)
(1- ses--numcols)))
;;End of range is being deleted
(setq max (ses-create-cell-symbol (car maxrowcol) (1- startcol))
ses-relocate-return 'range))
......@@ -1095,8 +1210,8 @@ the rectangle (MINROW,MINCOL)..(NUMROWS,NUMCOLS) by adding ROWINCR and COLINCR
to each symbol."
(let (reform)
(let (mycell newval)
(ses-dotimes-msg (row numrows) "Relocating formulas..."
(dotimes (col numcols)
(ses-dotimes-msg (row ses--numrows) "Relocating formulas..."
(dotimes (col ses--numcols)
(setq ses-relocate-return nil
mycell (ses-get-cell row col)
newval (ses-relocate-formula (ses-cell-formula mycell)
......@@ -1110,7 +1225,7 @@ to each symbol."
;;This cell referred to a cell that's been deleted or is no
;;longer part of the range. We can't fix that now because
;;reference lists cells have been partially updated.
(add-to-list 'deferred-recalc
(add-to-list 'ses--deferred-recalc
(ses-create-cell-symbol row col)))
(setq newval (ses-relocate-formula (ses-cell-references mycell)
minrow mincol rowincr colincr))
......@@ -1123,25 +1238,25 @@ to each symbol."
(cond
((and (<= rowincr 0) (<= colincr 0))
;;Deletion of rows and/or columns
(ses-dotimes-msg (row (- numrows minrow)) "Relocating variables..."
(ses-dotimes-msg (row (- ses--numrows minrow)) "Relocating variables..."
(setq myrow (+ row minrow))
(dotimes (col (- numcols mincol))
(dotimes (col (- ses--numcols mincol))
(setq mycol (+ col mincol)
xrow (- myrow rowincr)
xcol (- mycol colincr))
(if (and (< xrow numrows) (< xcol numcols))
(if (and (< xrow ses--numrows) (< xcol ses--numcols))
(setq oldval (ses-cell-value xrow xcol))
;;Cell is off the end of the array
(setq oldval (symbol-value (ses-create-cell-symbol xrow xcol))))
(ses-set-cell myrow mycol 'value oldval))))
((and (wholenump rowincr) (wholenump colincr))
;;Insertion of rows and/or columns. Run the loop backwards.
(let ((disty (1- numrows))
(distx (1- numcols))
(let ((disty (1- ses--numrows))
(distx (1- ses--numcols))
myrow mycol)
(ses-dotimes-msg (row (- numrows minrow)) "Relocating variables..."
(ses-dotimes-msg (row (- ses--numrows minrow)) "Relocating variables..."
(setq myrow (- disty row))
(dotimes (col (- numcols mincol))
(dotimes (col (- ses--numcols mincol))
(setq mycol (- distx col)
xrow (- myrow rowincr)
xcol (- mycol colincr))
......@@ -1192,7 +1307,8 @@ cdr--its arglist."
(if (not (eq major-mode 'ses-mode))
ad-do-it
;;Here is some extra code for SES mode.
(setq deferred-narrow (or deferred-narrow (< (point-max) (buffer-size))))
(setq ses--deferred-narrow
(or ses--deferred-narrow (< (point-max) (buffer-size))))
(widen)
(condition-case x
ad-do-it
......@@ -1241,101 +1357,6 @@ stuff."
;;;; Startup for major mode
;;;----------------------------------------------------------------------------
(defun ses-build-mode-map ()
"Set up `ses-mode-map', `ses-mode-print-map', and `ses-mode-edit-map' with
standard keymap bindings for SES."
(message "Building mode map...")
;;;Define ses-mode-map
(let ((keys '("\C-c\M-\C-l" ses-reconstruct-all
"\C-c\C-l" ses-recalculate-all
"\C-c\C-n" ses-renarrow-buffer
"\C-c\C-c" ses-recalculate-cell
"\C-c\M-\C-s" ses-sort-column
"\C-c\M-\C-h" ses-read-header-row
"\C-c\C-t" ses-truncate-cell
"\C-c\C-j" ses-jump