Mercurial > emacs
comparison lisp/ses.el @ 58409:924fa48ab4bf
Add coding cookie. Fix up docstrings, follow new commenting conventions.
(ses-header-line-menu): Fix missing variable rename for header-row.
(ses-cell-size): Remove.
(ses-make-cell): New function.
(ses-cell, ses-insert-row, ses-insert-column): Use it.
(ses-calculate-cell): Remove unused var `symbol'.
(ses-narrowed-p): New function.
(ses-goto-data, undo-more, ses-reconstruct-all): Use it.
(ses-initial-file-trailer): Change ;;; to ;; for local vars.
(ses-load, ses-reconstruct-all): Adjust string search accordingly.
(ses-setup): Use restore-buffer-modified-p.
(ses-cleanup): Remove unused var `end'.
(ses-header-string-left-offset): Remove.
(ses-create-header-string): Adjust to new behavior of `align-to'.
Truncate excessively large fields to preserve alignment.
(ses-reconstruct-all): Remove unused var `refs'.
(ses-read-cell-printer): Remove unused var `prompt'.
(ses-delete-row): Remove unused var `pos'.
(ses-delete-column): Remove unused var `new'.
author | Stefan Monnier <monnier@iro.umontreal.ca> |
---|---|
date | Mon, 22 Nov 2004 01:21:07 +0000 |
parents | 6956afbe5459 |
children | c8adcd0d5e2e f2ebccfa87d4 |
comparison
equal
deleted
inserted
replaced
58408:6b5846d74ff0 | 58409:924fa48ab4bf |
---|---|
1 ;;; ses.el -- Simple Emacs Spreadsheet | 1 ;;; ses.el -- Simple Emacs Spreadsheet -*- coding: utf-8 -*- |
2 | 2 |
3 ;; Copyright (C) 2002,03,04 Free Software Foundation, Inc. | 3 ;; Copyright (C) 2002,03,04 Free Software Foundation, Inc. |
4 | 4 |
5 ;; Author: Jonathan Yavner <jyavner@member.fsf.org> | 5 ;; Author: Jonathan Yavner <jyavner@member.fsf.org> |
6 ;; Maintainer: Jonathan Yavner <jyavner@member.fsf.org> | 6 ;; Maintainer: Jonathan Yavner <jyavner@member.fsf.org> |
21 ;; You should have received a copy of the GNU General Public License | 21 ;; You should have received a copy of the GNU General Public License |
22 ;; along with GNU Emacs; see the file COPYING. If not, write to the | 22 ;; along with GNU Emacs; see the file COPYING. If not, write to the |
23 ;; Free Software Foundation, Inc., 59 Temple Place - Suite 330, | 23 ;; Free Software Foundation, Inc., 59 Temple Place - Suite 330, |
24 ;; Boston, MA 02111-1307, USA. | 24 ;; Boston, MA 02111-1307, USA. |
25 | 25 |
26 ;;; Commentary: | |
27 | |
26 ;;; To-do list: | 28 ;;; To-do list: |
29 | |
27 ;; * Use $ or … for truncated fields | 30 ;; * Use $ or … for truncated fields |
28 ;; * Add command to make a range of columns be temporarily invisible. | 31 ;; * Add command to make a range of columns be temporarily invisible. |
29 ;; * Allow paste of one cell to a range of cells -- copy formula to each. | 32 ;; * Allow paste of one cell to a range of cells -- copy formula to each. |
30 ;; * Do something about control characters & octal codes in cell print | 33 ;; * Do something about control characters & octal codes in cell print |
31 ;; areas. Use string-width? | 34 ;; areas. Use string-width? |
33 ;; * Faces (colors & styles) in print cells. | 36 ;; * Faces (colors & styles) in print cells. |
34 ;; * Move a column by dragging its letter in the header line. | 37 ;; * Move a column by dragging its letter in the header line. |
35 ;; * Left-margin column for row number. | 38 ;; * Left-margin column for row number. |
36 ;; * Move a row by dragging its number in the left-margin. | 39 ;; * Move a row by dragging its number in the left-margin. |
37 | 40 |
41 | |
42 ;;; Code: | |
43 | |
38 (require 'unsafep) | 44 (require 'unsafep) |
39 | 45 |
40 | 46 |
41 ;;;---------------------------------------------------------------------------- | 47 ;;---------------------------------------------------------------------------- |
42 ;;;; User-customizable variables | 48 ;; User-customizable variables |
43 ;;;---------------------------------------------------------------------------- | 49 ;;---------------------------------------------------------------------------- |
44 | 50 |
45 (defgroup ses nil | 51 (defgroup ses nil |
46 "Simple Emacs Spreadsheet" | 52 "Simple Emacs Spreadsheet" |
47 :group 'applications | 53 :group 'applications |
48 :prefix "ses-" | 54 :prefix "ses-" |
64 :type '(choice string | 70 :type '(choice string |
65 (list :tag "Parenthesized string" string) | 71 (list :tag "Parenthesized string" string) |
66 function)) | 72 function)) |
67 | 73 |
68 (defcustom ses-after-entry-functions '(forward-char) | 74 (defcustom ses-after-entry-functions '(forward-char) |
69 "Things to do after entering a value into a cell. An abnormal hook that | 75 "Things to do after entering a value into a cell. |
70 usually runs a cursor-movement function. Each function is called with ARG=1." | 76 An abnormal hook that usually runs a cursor-movement function. |
77 Each function is called with ARG=1." | |
71 :group 'ses | 78 :group 'ses |
72 :type 'hook | 79 :type 'hook |
73 :options '(forward-char backward-char next-line previous-line)) | 80 :options '(forward-char backward-char next-line previous-line)) |
74 | 81 |
75 (defcustom ses-mode-hook nil | 82 (defcustom ses-mode-hook nil |
76 "Hook functions to be run upon entering SES mode." | 83 "Hook functions to be run upon entering SES mode." |
77 :group 'ses | 84 :group 'ses |
78 :type 'hook) | 85 :type 'hook) |
79 | 86 |
80 | 87 |
81 ;;;---------------------------------------------------------------------------- | 88 ;;---------------------------------------------------------------------------- |
82 ;;;; Global variables and constants | 89 ;; Global variables and constants |
83 ;;;---------------------------------------------------------------------------- | 90 ;;---------------------------------------------------------------------------- |
84 | 91 |
85 (defvar ses-read-cell-history nil | 92 (defvar ses-read-cell-history nil |
86 "List of formulas that have been typed in.") | 93 "List of formulas that have been typed in.") |
87 | 94 |
88 (defvar ses-read-printer-history nil | 95 (defvar ses-read-printer-history nil |
90 | 97 |
91 (easy-menu-define ses-header-line-menu nil | 98 (easy-menu-define ses-header-line-menu nil |
92 "Context menu when mouse-3 is used on the header-line in an SES buffer." | 99 "Context menu when mouse-3 is used on the header-line in an SES buffer." |
93 '("SES header row" | 100 '("SES header row" |
94 ["Set current row" ses-set-header-row t] | 101 ["Set current row" ses-set-header-row t] |
95 ["Unset row" ses-unset-header-row (> header-row 0)])) | 102 ["Unset row" ses-unset-header-row (> ses--header-row 0)])) |
96 | 103 |
97 (defconst ses-mode-map | 104 (defconst ses-mode-map |
98 (let ((keys `("\C-c\M-\C-l" ses-reconstruct-all | 105 (let ((keys `("\C-c\M-\C-l" ses-reconstruct-all |
99 "\C-c\C-l" ses-recalculate-all | 106 "\C-c\C-l" ses-recalculate-all |
100 "\C-c\C-n" ses-renarrow-buffer | 107 "\C-c\C-n" ses-renarrow-buffer |
206 (define-key map "T" (cons " tab-formulas" 'ses-export-tsf)) | 213 (define-key map "T" (cons " tab-formulas" 'ses-export-tsf)) |
207 (define-key map "t" (cons " tab-values" 'ses-export-tsv)) | 214 (define-key map "t" (cons " tab-values" 'ses-export-tsv)) |
208 map)) | 215 map)) |
209 | 216 |
210 (defconst ses-print-data-boundary "\n\014\n" | 217 (defconst ses-print-data-boundary "\n\014\n" |
211 "Marker string denoting the boundary between print area and data area") | 218 "Marker string denoting the boundary between print area and data area.") |
212 | 219 |
213 (defconst ses-initial-global-parameters | 220 (defconst ses-initial-global-parameters |
214 "\n( ;Global parameters (these are read first)\n 2 ;SES file-format\n 1 ;numrows\n 1 ;numcols\n)\n\n" | 221 "\n( ;Global parameters (these are read first)\n 2 ;SES file-format\n 1 ;numrows\n 1 ;numcols\n)\n\n" |
215 "Initial contents for the three-element list at the bottom of the data area") | 222 "Initial contents for the three-element list at the bottom of the data area.") |
216 | 223 |
217 (defconst ses-initial-file-trailer | 224 (defconst ses-initial-file-trailer |
218 ";;; Local Variables:\n;;; mode: ses\n;;; End:\n" | 225 ";; Local Variables:\n;; mode: ses\n;; End:\n" |
219 "Initial contents for the file-trailer area at the bottom of the file.") | 226 "Initial contents for the file-trailer area at the bottom of the file.") |
220 | 227 |
221 (defconst ses-initial-file-contents | 228 (defconst ses-initial-file-contents |
222 (concat " \n" ;One blank cell in print area | 229 (concat " \n" ;One blank cell in print area |
223 ses-print-data-boundary | 230 ses-print-data-boundary |
229 "(ses-header-row 0)\n" | 236 "(ses-header-row 0)\n" |
230 ses-initial-global-parameters | 237 ses-initial-global-parameters |
231 ses-initial-file-trailer) | 238 ses-initial-file-trailer) |
232 "The initial contents of an empty spreadsheet.") | 239 "The initial contents of an empty spreadsheet.") |
233 | 240 |
234 (defconst ses-cell-size 4 | |
235 "A cell consists of a SYMBOL, a FORMULA, a PRINTER-function, and a list of | |
236 REFERENCES.") | |
237 | |
238 (defconst ses-paramlines-plist | 241 (defconst ses-paramlines-plist |
239 '(ses--col-widths 2 ses--col-printers 3 ses--default-printer 4 | 242 '(ses--col-widths 2 ses--col-printers 3 ses--default-printer 4 |
240 ses--header-row 5 ses--file-format 8 ses--numrows 9 | 243 ses--header-row 5 ses--file-format 8 ses--numrows 9 |
241 ses--numcols 10) | 244 ses--numcols 10) |
242 "Offsets from last cell line to various parameter lines in the data area | 245 "Offsets from last cell line to various parameter lines in the data area |
269 (dolist (x ses-localvars) | 272 (dolist (x ses-localvars) |
270 (make-local-variable x) | 273 (make-local-variable x) |
271 (set x nil))) | 274 (set x nil))) |
272 | 275 |
273 | 276 |
274 ;;; | 277 ;; |
275 ;;; "Side-effect variables". They are set in one function, altered in | 278 ;; "Side-effect variables". They are set in one function, altered in |
276 ;;; another as a side effect, then read back by the first, as a way of | 279 ;; another as a side effect, then read back by the first, as a way of |
277 ;;; passing back more than one value. These declarations are just to make | 280 ;; passing back more than one value. These declarations are just to make |
278 ;;; the compiler happy, and to conform to standard Emacs-Lisp practice (I | 281 ;; the compiler happy, and to conform to standard Emacs-Lisp practice (I |
279 ;;; think the make-local-variable trick above is cleaner). | 282 ;; think the make-local-variable trick above is cleaner). |
280 ;;; | 283 ;; |
281 | 284 |
282 (defvar ses-relocate-return nil | 285 (defvar ses-relocate-return nil |
283 "Set by `ses-relocate-formula' and `ses-relocate-range', read by | 286 "Set by `ses-relocate-formula' and `ses-relocate-range', read by |
284 `ses-relocate-all'. Set to 'delete if a cell-reference was deleted from a | 287 `ses-relocate-all'. Set to 'delete if a cell-reference was deleted from a |
285 formula--so the formula needs recalculation. Set to 'range if the size of a | 288 formula--so the formula needs recalculation. Set to 'range if the size of a |
294 (defvar ses-start-time nil | 297 (defvar ses-start-time nil |
295 "Time when current operation started. Used by `ses-time-check' to decide | 298 "Time when current operation started. Used by `ses-time-check' to decide |
296 when to emit a progress message.") | 299 when to emit a progress message.") |
297 | 300 |
298 | 301 |
299 ;;;---------------------------------------------------------------------------- | 302 ;;---------------------------------------------------------------------------- |
300 ;;;; Macros | 303 ;; Macros |
301 ;;;---------------------------------------------------------------------------- | 304 ;;---------------------------------------------------------------------------- |
302 | 305 |
303 (defmacro ses-get-cell (row col) | 306 (defmacro ses-get-cell (row col) |
304 "Return the cell structure that stores information about cell (ROW,COL)." | 307 "Return the cell structure that stores information about cell (ROW,COL)." |
305 `(aref (aref ses--cells ,row) ,col)) | 308 `(aref (aref ses--cells ,row) ,col)) |
309 | |
310 ;; We might want to use defstruct here, but cells are explicitly used as | |
311 ;; arrays in ses-set-cell, so we'd need to fix this first. --Stef | |
312 (defsubst ses-make-cell (&optional symbol formula printer references) | |
313 (vector symbol formula printer references)) | |
306 | 314 |
307 (defmacro ses-cell-symbol (row &optional col) | 315 (defmacro ses-cell-symbol (row &optional col) |
308 "From a CELL or a pair (ROW,COL), get the symbol that names the local-variable holding its value. (0,0) => A1." | 316 "From a CELL or a pair (ROW,COL), get the symbol that names the local-variable holding its value. (0,0) => A1." |
309 `(aref ,(if col `(ses-get-cell ,row ,col) row) 0)) | 317 `(aref ,(if col `(ses-get-cell ,row ,col) row) 0)) |
310 | 318 |
353 (stringp printer) | 361 (stringp printer) |
354 (eq safe-functions t) | 362 (eq safe-functions t) |
355 (setq printer `(ses-safe-printer ,printer))) | 363 (setq printer `(ses-safe-printer ,printer))) |
356 (aset (aref ses--cells (car rowcol)) | 364 (aset (aref ses--cells (car rowcol)) |
357 (cdr rowcol) | 365 (cdr rowcol) |
358 (vector sym formula printer references))) | 366 (ses-make-cell sym formula printer references))) |
359 (set sym value) | 367 (set sym value) |
360 sym) | 368 sym) |
361 | 369 |
362 (defmacro ses-column-widths (widths) | 370 (defmacro ses-column-widths (widths) |
363 "Load the vector of column widths from the spreadsheet file. This is a | 371 "Load the vector of column widths from the spreadsheet file. This is a |
453 (defmacro noreturn (form) | 461 (defmacro noreturn (form) |
454 "For code-coverage testing, indicate that FORM will always signal an error." | 462 "For code-coverage testing, indicate that FORM will always signal an error." |
455 form) | 463 form) |
456 | 464 |
457 | 465 |
458 ;;;---------------------------------------------------------------------------- | 466 ;;---------------------------------------------------------------------------- |
459 ;;;; Utility functions | 467 ;; Utility functions |
460 ;;;---------------------------------------------------------------------------- | 468 ;;---------------------------------------------------------------------------- |
461 | 469 |
462 (defun ses-vector-insert (array idx new) | 470 (defun ses-vector-insert (array idx new) |
463 "Create a new vector which is one larger than ARRAY and has NEW inserted | 471 "Create a new vector which is one larger than ARRAY and has NEW inserted |
464 before element IDX." | 472 before element IDX." |
465 (let* ((len (length array)) | 473 (let* ((len (length array)) |
536 xcol (+ col mincol) | 544 xcol (+ col mincol) |
537 sym (ses-create-cell-symbol xrow xcol)) | 545 sym (ses-create-cell-symbol xrow xcol)) |
538 (put sym 'ses-cell (cons xrow xcol)) | 546 (put sym 'ses-cell (cons xrow xcol)) |
539 (make-local-variable sym))))) | 547 (make-local-variable sym))))) |
540 | 548 |
541 ;;;We do not delete the ses-cell properties for the cell-variables, in case a | 549 ;;We do not delete the ses-cell properties for the cell-variables, in case a |
542 ;;;formula that refers to this cell is in the kill-ring and is later pasted | 550 ;;formula that refers to this cell is in the kill-ring and is later pasted |
543 ;;;back in. | 551 ;;back in. |
544 (defun ses-destroy-cell-variable-range (minrow maxrow mincol maxcol) | 552 (defun ses-destroy-cell-variable-range (minrow maxrow mincol maxcol) |
545 "Destroy buffer-local variables for cells. This is undoable." | 553 "Destroy buffer-local variables for cells. This is undoable." |
546 (let (sym) | 554 (let (sym) |
547 (dotimes (row (1+ (- maxrow minrow))) | 555 (dotimes (row (1+ (- maxrow minrow))) |
548 (dotimes (col (1+ (- maxcol mincol))) | 556 (dotimes (col (1+ (- maxcol mincol))) |
568 (message format (eval arg)) | 576 (message format (eval arg)) |
569 (setq ses-start-time (float-time))) | 577 (setq ses-start-time (float-time))) |
570 nil) | 578 nil) |
571 | 579 |
572 | 580 |
573 ;;;---------------------------------------------------------------------------- | 581 ;;---------------------------------------------------------------------------- |
574 ;;;; The cells | 582 ;; The cells |
575 ;;;---------------------------------------------------------------------------- | 583 ;;---------------------------------------------------------------------------- |
576 | 584 |
577 (defun ses-set-cell (row col field val) | 585 (defun ses-set-cell (row col field val) |
578 "Install VAL as the contents for field FIELD (named by a quoted symbol) of | 586 "Install VAL as the contents for field FIELD (named by a quoted symbol) of |
579 cell (ROW,COL). This is undoable. The cell's data will be updated through | 587 cell (ROW,COL). This is undoable. The cell's data will be updated through |
580 `post-command-hook'." | 588 `post-command-hook'." |
632 Any cells that depend on this cell are queued for update after the end of | 640 Any cells that depend on this cell are queued for update after the end of |
633 processing for the current keystroke, unless the new value is the same as | 641 processing for the current keystroke, unless the new value is the same as |
634 the old and FORCE is nil." | 642 the old and FORCE is nil." |
635 (let ((cell (ses-get-cell row col)) | 643 (let ((cell (ses-get-cell row col)) |
636 formula-error printer-error) | 644 formula-error printer-error) |
637 (let ((symbol (ses-cell-symbol cell)) | 645 (let ((oldval (ses-cell-value cell)) |
638 (oldval (ses-cell-value cell)) | |
639 (formula (ses-cell-formula cell)) | 646 (formula (ses-cell-formula cell)) |
640 newval) | 647 newval) |
641 (if (eq (car-safe formula) 'ses-safe-formula) | 648 (if (eq (car-safe formula) 'ses-safe-formula) |
642 (ses-set-cell row col 'formula (ses-safe-formula (cadr formula)))) | 649 (ses-set-cell row col 'formula (ses-safe-formula (cadr formula)))) |
643 (condition-case sig | 650 (condition-case sig |
715 ;;Can't use save-excursion here: if the cell under point is | 722 ;;Can't use save-excursion here: if the cell under point is |
716 ;;updated, save-excusion's marker will move past the cell. | 723 ;;updated, save-excusion's marker will move past the cell. |
717 (goto-char pos))) | 724 (goto-char pos))) |
718 | 725 |
719 | 726 |
720 ;;;---------------------------------------------------------------------------- | 727 ;;---------------------------------------------------------------------------- |
721 ;;;; The print area | 728 ;; The print area |
722 ;;;---------------------------------------------------------------------------- | 729 ;;---------------------------------------------------------------------------- |
723 | 730 |
724 (defun ses-in-print-area () | 731 (defun ses-in-print-area () |
725 "Returns t if point is in print area of spreadsheet." | 732 "Returns t if point is in print area of spreadsheet." |
726 (eq (get-text-property (point) 'keymap) 'ses-mode-print-map)) | 733 (eq (get-text-property (point) 'keymap) 'ses-mode-print-map)) |
727 | 734 |
728 ;;;We turn off point-motion-hooks and explicitly position the cursor, in case | 735 ;;We turn off point-motion-hooks and explicitly position the cursor, in case |
729 ;;;the intangible properties have gotten screwed up (e.g., when | 736 ;;the intangible properties have gotten screwed up (e.g., when |
730 ;;;ses-goto-print is called during a recursive ses-print-cell). | 737 ;;ses-goto-print is called during a recursive ses-print-cell). |
731 (defun ses-goto-print (row col) | 738 (defun ses-goto-print (row col) |
732 "Move point to print area for cell (ROW,COL)." | 739 "Move point to print area for cell (ROW,COL)." |
733 (let ((inhibit-point-motion-hooks t)) | 740 (let ((inhibit-point-motion-hooks t)) |
734 (goto-char (point-min)) | 741 (goto-char (point-min)) |
735 (forward-line row) | 742 (forward-line row) |
770 (error "Can't use a range"))) | 777 (error "Can't use a range"))) |
771 ((memq 'needrange args) | 778 ((memq 'needrange args) |
772 (error "Need a range")))) | 779 (error "Need a range")))) |
773 | 780 |
774 (defun ses-print-cell (row col) | 781 (defun ses-print-cell (row col) |
775 "Format and print the value of cell (ROW,COL) to the print area, using the | 782 "Format and print the value of cell (ROW,COL) to the print area. |
776 cell's printer function. If the cell's new print form is too wide, it will | 783 Use the cell's printer function. If the cell's new print form is too wide, |
777 spill over into the following cell, but will not run off the end of the row | 784 it will spill over into the following cell, but will not run off the end of the |
778 or overwrite the next non-nil field. Result is nil for normal operation, or | 785 row or overwrite the next non-nil field. Result is nil for normal operation, |
779 the error signal if the printer function failed and the cell was formatted | 786 or the error signal if the printer function failed and the cell was formatted |
780 with \"%s\". If the cell's value is *skip*, nothing is printed because the | 787 with \"%s\". If the cell's value is *skip*, nothing is printed because the |
781 preceding cell has spilled over." | 788 preceding cell has spilled over." |
782 (catch 'ses-print-cell | 789 (catch 'ses-print-cell |
783 (let* ((cell (ses-get-cell row col)) | 790 (let* ((cell (ses-get-cell row col)) |
784 (value (ses-cell-value cell)) | 791 (value (ses-cell-value cell)) |
946 (backward-char 1) | 953 (backward-char 1) |
947 (let ((rowcol (ses-sym-rowcol (get-text-property (point) 'intangible)))) | 954 (let ((rowcol (ses-sym-rowcol (get-text-property (point) 'intangible)))) |
948 (ses-print-cell (car rowcol) (cdr rowcol))))) | 955 (ses-print-cell (car rowcol) (cdr rowcol))))) |
949 | 956 |
950 | 957 |
951 ;;;---------------------------------------------------------------------------- | 958 ;;---------------------------------------------------------------------------- |
952 ;;;; The data area | 959 ;; The data area |
953 ;;;---------------------------------------------------------------------------- | 960 ;;---------------------------------------------------------------------------- |
961 | |
962 (defun ses-narrowed-p () (/= (- (point-max) (point-min)) (buffer-size))) | |
954 | 963 |
955 (defun ses-goto-data (def &optional col) | 964 (defun ses-goto-data (def &optional col) |
956 "Move point to data area for (DEF,COL). If DEF is a row | 965 "Move point to data area for (DEF,COL). If DEF is a row |
957 number, COL is the column number for a data cell -- otherwise DEF | 966 number, COL is the column number for a data cell -- otherwise DEF |
958 is one of the symbols ses--col-widths, ses--col-printers, | 967 is one of the symbols ses--col-widths, ses--col-printers, |
959 ses--default-printer, ses--numrows, or ses--numcols." | 968 ses--default-printer, ses--numrows, or ses--numcols." |
960 (if (< (point-max) (buffer-size)) | 969 (if (ses-narrowed-p) |
961 (setq ses--deferred-narrow t)) | 970 (setq ses--deferred-narrow t)) |
962 (widen) | 971 (widen) |
963 (let ((inhibit-point-motion-hooks t)) ;In case intangible attrs are wrong | 972 (let ((inhibit-point-motion-hooks t)) ;In case intangible attrs are wrong |
964 (goto-char (point-min)) | 973 (goto-char (point-min)) |
965 (if col | 974 (if col |
969 (setq def (plist-get ses-paramlines-plist def)) | 978 (setq def (plist-get ses-paramlines-plist def)) |
970 (or def (signal 'args-out-of-range nil)) | 979 (or def (signal 'args-out-of-range nil)) |
971 (forward-line (+ (* ses--numrows (+ ses--numcols 2)) def))))) | 980 (forward-line (+ (* ses--numrows (+ ses--numcols 2)) def))))) |
972 | 981 |
973 (defun ses-set-parameter (def value &optional elem) | 982 (defun ses-set-parameter (def value &optional elem) |
974 "Sets parameter DEF to VALUE (with undo) and writes the value to the data | 983 "Set parameter DEF to VALUE (with undo) and write the value to the data area. |
975 area. See `ses-goto-data' for meaning of DEF. Newlines in the data | 984 See `ses-goto-data' for meaning of DEF. Newlines in the data are escaped. |
976 are escaped. If ELEM is specified, it is the array subscript within DEF to | 985 If ELEM is specified, it is the array subscript within DEF to be set to VALUE." |
977 be set to VALUE." | |
978 (save-excursion | 986 (save-excursion |
979 ;;We call ses-goto-data early, using the old values of numrows and | 987 ;;We call ses-goto-data early, using the old values of numrows and |
980 ;;numcols in case one of them is being changed. | 988 ;;numcols in case one of them is being changed. |
981 (ses-goto-data def) | 989 (ses-goto-data def) |
982 (if elem | 990 (if elem |
993 def))) | 1001 def))) |
994 (delete-region (point) (line-end-position)) | 1002 (delete-region (point) (line-end-position)) |
995 (insert (format fmt (symbol-value def)))))) | 1003 (insert (format fmt (symbol-value def)))))) |
996 | 1004 |
997 (defun ses-write-cells () | 1005 (defun ses-write-cells () |
998 "`ses--deferred-write' is a list of (ROW,COL) for cells to be written from | 1006 "Write cells in `ses--deferred-write' from local variables to data area. |
999 buffer-local variables to data area. Newlines in the data are escaped." | 1007 Newlines in the data are escaped." |
1000 (let* ((inhibit-read-only t) | 1008 (let* ((inhibit-read-only t) |
1001 (print-escape-newlines t) | 1009 (print-escape-newlines t) |
1002 rowcol row col cell sym formula printer text) | 1010 rowcol row col cell sym formula printer text) |
1003 (setq ses-start-time (float-time)) | 1011 (setq ses-start-time (float-time)) |
1004 (with-temp-message " " | 1012 (with-temp-message " " |
1039 (delete-region (point) (line-end-position)) | 1047 (delete-region (point) (line-end-position)) |
1040 (insert text))) | 1048 (insert text))) |
1041 (message " ")))) | 1049 (message " ")))) |
1042 | 1050 |
1043 | 1051 |
1044 ;;;---------------------------------------------------------------------------- | 1052 ;;---------------------------------------------------------------------------- |
1045 ;;;; Formula relocation | 1053 ;; Formula relocation |
1046 ;;;---------------------------------------------------------------------------- | 1054 ;;---------------------------------------------------------------------------- |
1047 | 1055 |
1048 (defun ses-formula-references (formula &optional result-so-far) | 1056 (defun ses-formula-references (formula &optional result-so-far) |
1049 "Produce a list of symbols for cells that this formula's value | 1057 "Produce a list of symbols for cells that this formula's value |
1050 refers to. For recursive calls, RESULT-SO-FAR is the list being constructed, | 1058 refers to. For recursive calls, RESULT-SO-FAR is the list being constructed, |
1051 or t to get a wrong-type-argument error when the first reference is found." | 1059 or t to get a wrong-type-argument error when the first reference is found." |
1282 reform (cdr reform)) | 1290 reform (cdr reform)) |
1283 (ses-cell-set-formula row col (ses-cell-formula row col)))) | 1291 (ses-cell-set-formula row col (ses-cell-formula row col)))) |
1284 (message nil)))) | 1292 (message nil)))) |
1285 | 1293 |
1286 | 1294 |
1287 ;;;---------------------------------------------------------------------------- | 1295 ;;---------------------------------------------------------------------------- |
1288 ;;;; Undo control | 1296 ;; Undo control |
1289 ;;;---------------------------------------------------------------------------- | 1297 ;;---------------------------------------------------------------------------- |
1290 | 1298 |
1291 (defadvice undo-more (around ses-undo-more activate preactivate) | 1299 (defadvice undo-more (around ses-undo-more activate preactivate) |
1292 "Define a meaning for conses in buffer-undo-list whose car is a symbol | 1300 "Define a meaning for conses in buffer-undo-list whose car is a symbol |
1293 other than t or nil. To undo these, apply the car--a function--to the | 1301 other than t or nil. To undo these, apply the car--a function--to the |
1294 cdr--its arglist." | 1302 cdr--its arglist." |
1306 (apply (car ses-x) (cdr ses-x))))) | 1314 (apply (car ses-x) (cdr ses-x))))) |
1307 (if (not (eq major-mode 'ses-mode)) | 1315 (if (not (eq major-mode 'ses-mode)) |
1308 ad-do-it | 1316 ad-do-it |
1309 ;;Here is some extra code for SES mode. | 1317 ;;Here is some extra code for SES mode. |
1310 (setq ses--deferred-narrow | 1318 (setq ses--deferred-narrow |
1311 (or ses--deferred-narrow (< (point-max) (buffer-size)))) | 1319 (or ses--deferred-narrow (ses-narrowed-p))) |
1312 (widen) | 1320 (widen) |
1313 (condition-case x | 1321 (condition-case x |
1314 ad-do-it | 1322 ad-do-it |
1315 (error | 1323 (error |
1316 ;;Restore narrow if appropriate | 1324 ;;Restore narrow if appropriate |
1351 (push `(ses-aset-with-undo ,array ,idx ,(aref array idx)) buffer-undo-list) | 1359 (push `(ses-aset-with-undo ,array ,idx ,(aref array idx)) buffer-undo-list) |
1352 (aset array idx newval) | 1360 (aset array idx newval) |
1353 t)) | 1361 t)) |
1354 | 1362 |
1355 | 1363 |
1356 ;;;---------------------------------------------------------------------------- | 1364 ;;---------------------------------------------------------------------------- |
1357 ;;;; Startup for major mode | 1365 ;; Startup for major mode |
1358 ;;;---------------------------------------------------------------------------- | 1366 ;;---------------------------------------------------------------------------- |
1359 | 1367 |
1360 (defun ses-load () | 1368 (defun ses-load () |
1361 "Parse the current buffer and sets up buffer-local variables. Does not | 1369 "Parse the current buffer and sets up buffer-local variables. Does not |
1362 execute cell formulas or print functions." | 1370 execute cell formulas or print functions." |
1363 (widen) | 1371 (widen) |
1364 ;;Read our global parameters, which should be a 3-element list | 1372 ;;Read our global parameters, which should be a 3-element list |
1365 (goto-char (point-max)) | 1373 (goto-char (point-max)) |
1366 (search-backward ";;; Local Variables:\n" nil t) | 1374 (search-backward ";; Local Variables:\n" nil t) |
1367 (backward-list 1) | 1375 (backward-list 1) |
1368 (let ((params (condition-case nil (read (current-buffer)) (error nil))) | 1376 (let ((params (condition-case nil (read (current-buffer)) (error nil)))) |
1369 sym) | |
1370 (or (and (= (safe-length params) 3) | 1377 (or (and (= (safe-length params) 3) |
1371 (numberp (car params)) | 1378 (numberp (car params)) |
1372 (numberp (cadr params)) | 1379 (numberp (cadr params)) |
1373 (> (cadr params) 0) | 1380 (> (cadr params) 0) |
1374 (numberp (nth 2 params)) | 1381 (numberp (nth 2 params)) |
1479 col (1+ col))) | 1486 col (1+ col))) |
1480 (setq end (+ end (ses-col-width col) 1)) | 1487 (setq end (+ end (ses-col-width col) 1)) |
1481 (put-text-property pos end 'intangible sym))) | 1488 (put-text-property pos end 'intangible sym))) |
1482 ;;Adding these properties did not actually alter the text | 1489 ;;Adding these properties did not actually alter the text |
1483 (unless was-modified | 1490 (unless was-modified |
1484 (set-buffer-modified-p nil) | 1491 (restore-buffer-modified-p nil) |
1485 (buffer-disable-undo) | 1492 (buffer-disable-undo) |
1486 (buffer-enable-undo))) | 1493 (buffer-enable-undo))) |
1487 ;;Create the underlining overlay. It's impossible for (point) to be 2, | 1494 ;;Create the underlining overlay. It's impossible for (point) to be 2, |
1488 ;;because column A must be at least 1 column wide. | 1495 ;;because column A must be at least 1 column wide. |
1489 (setq ses--curcell-overlay (make-overlay (1+ (point-min)) (1+ (point-min)))) | 1496 (setq ses--curcell-overlay (make-overlay (1+ (point-min)) (1+ (point-min)))) |
1492 (defun ses-cleanup () | 1499 (defun ses-cleanup () |
1493 "Cleanup when changing a buffer from SES mode to something else. Delete | 1500 "Cleanup when changing a buffer from SES mode to something else. Delete |
1494 overlay, remove special text properties." | 1501 overlay, remove special text properties." |
1495 (widen) | 1502 (widen) |
1496 (let ((inhibit-read-only t) | 1503 (let ((inhibit-read-only t) |
1497 (was-modified (buffer-modified-p)) | 1504 (was-modified (buffer-modified-p))) |
1498 end) | |
1499 ;;Delete read-only, keymap, and intangible properties | 1505 ;;Delete read-only, keymap, and intangible properties |
1500 (set-text-properties (point-min) (point-max) nil) | 1506 (set-text-properties (point-min) (point-max) nil) |
1501 ;;Delete overlay | 1507 ;;Delete overlay |
1502 (mapc 'delete-overlay (overlays-in (point-min) (point-max))) | 1508 (mapc 'delete-overlay (overlays-in (point-min) (point-max))) |
1503 (unless was-modified | 1509 (unless was-modified |
1637 (unless executing-kbd-macro | 1643 (unless executing-kbd-macro |
1638 (ding)) | 1644 (ding)) |
1639 (message (error-message-string err)))) | 1645 (message (error-message-string err)))) |
1640 nil) ;Make coverage-tester happy | 1646 nil) ;Make coverage-tester happy |
1641 | 1647 |
1642 (defun ses-header-string-left-offset () | |
1643 "Number of characters in left fringe and left scrollbar (if any)." | |
1644 (let ((left-fringe (round (or (frame-parameter nil 'left-fringe) 0) | |
1645 (frame-char-width))) | |
1646 (left-scrollbar (if (not (eq (frame-parameter nil | |
1647 'vertical-scroll-bars) | |
1648 'left)) | |
1649 0 | |
1650 (let ((x (frame-parameter nil 'scroll-bar-width))) | |
1651 ;;Non-toolkil bar is always 14 pixels? | |
1652 (unless x (setq x 14)) | |
1653 ;;Always round up | |
1654 (ceiling x (frame-char-width)))))) | |
1655 (+ left-fringe left-scrollbar))) | |
1656 | |
1657 (defun ses-create-header-string () | 1648 (defun ses-create-header-string () |
1658 "Sets up `ses--header-string' as the buffer's header line, based on the | 1649 "Set up `ses--header-string' as the buffer's header line. |
1659 current set of columns and window-scroll position." | 1650 Based on the current set of columns and `window-hscroll' position." |
1660 (let* ((left-offset (ses-header-string-left-offset)) | 1651 (let ((totwidth (- (window-hscroll))) |
1661 (totwidth (- left-offset (window-hscroll))) | 1652 result width x) |
1662 result width result x) | |
1663 ;;Leave room for the left-side fringe and scrollbar | 1653 ;;Leave room for the left-side fringe and scrollbar |
1664 (push (make-string left-offset ? ) result) | 1654 (push (propertize " " 'display '((space :align-to 0))) result) |
1665 (dotimes (col ses--numcols) | 1655 (dotimes (col ses--numcols) |
1666 (setq width (ses-col-width col) | 1656 (setq width (ses-col-width col) |
1667 totwidth (+ totwidth width 1)) | 1657 totwidth (+ totwidth width 1)) |
1668 (if (= totwidth (+ left-offset 1)) | 1658 (if (= totwidth 1) |
1669 ;;Scrolled so intercolumn space is leftmost | 1659 ;;Scrolled so intercolumn space is leftmost |
1670 (push " " result)) | 1660 (push " " result)) |
1671 (when (> totwidth (+ left-offset 1)) | 1661 (when (> totwidth 1) |
1672 (if (> ses--header-row 0) | 1662 (if (> ses--header-row 0) |
1673 (save-excursion | 1663 (save-excursion |
1674 (ses-goto-print (1- ses--header-row) col) | 1664 (ses-goto-print (1- ses--header-row) col) |
1675 (setq x (buffer-substring-no-properties (point) | 1665 (setq x (buffer-substring-no-properties (point) |
1676 (+ (point) width))) | 1666 (+ (point) width))) |
1677 (if (>= width (- totwidth left-offset)) | 1667 ;; Strip trailing space. |
1678 (setq x (substring x (- width totwidth left-offset -1)))) | 1668 (if (string-match "[ \t]+\\'" x) |
1679 (push (propertize x 'face ses-box-prop) result)) | 1669 (setq x (substring x 0 (match-beginning 0)))) |
1680 (setq x (ses-column-letter col)) | 1670 ;; Cut off excess text. |
1671 (if (>= (length x) totwidth) | |
1672 (setq x (substring x 0 (- totwidth -1))))) | |
1673 (setq x (ses-column-letter col))) | |
1681 (push (propertize x 'face ses-box-prop) result) | 1674 (push (propertize x 'face ses-box-prop) result) |
1682 (push (propertize (make-string (- width (length x)) ?.) | 1675 (push (propertize "." |
1683 'display `((space :align-to ,(1- totwidth))) | 1676 'display `((space :align-to ,(1- totwidth))) |
1684 'face ses-box-prop) | 1677 'face ses-box-prop) |
1685 result)) | 1678 result) |
1686 ;;Allow the following space to be squished to make room for the 3-D box | 1679 ;;Allow the following space to be squished to make room for the 3-D box |
1687 ;;Coverage test ignores properties, thinks this is always a space! | 1680 ;;Coverage test ignores properties, thinks this is always a space! |
1688 (push (1value (propertize " " 'display `((space :align-to ,totwidth)))) | 1681 (push (1value (propertize " " 'display `((space :align-to ,totwidth)))) |
1689 result))) | 1682 result))) |
1690 (if (> ses--header-row 0) | 1683 (if (> ses--header-row 0) |
1692 'display '((height (- 1)))) | 1685 'display '((height (- 1)))) |
1693 result)) | 1686 result)) |
1694 (setq ses--header-string (apply 'concat (nreverse result))))) | 1687 (setq ses--header-string (apply 'concat (nreverse result))))) |
1695 | 1688 |
1696 | 1689 |
1697 ;;;---------------------------------------------------------------------------- | 1690 ;;---------------------------------------------------------------------------- |
1698 ;;;; Redisplay and recalculation | 1691 ;; Redisplay and recalculation |
1699 ;;;---------------------------------------------------------------------------- | 1692 ;;---------------------------------------------------------------------------- |
1700 | 1693 |
1701 (defun ses-jump (sym) | 1694 (defun ses-jump (sym) |
1702 "Move point to cell SYM." | 1695 "Move point to cell SYM." |
1703 (interactive "SJump to cell: ") | 1696 (interactive "SJump to cell: ") |
1704 (let ((rowcol (ses-sym-rowcol sym))) | 1697 (let ((rowcol (ses-sym-rowcol sym))) |
1812 (defun ses-reconstruct-all () | 1805 (defun ses-reconstruct-all () |
1813 "Reconstruct buffer based on cell data stored in Emacs variables." | 1806 "Reconstruct buffer based on cell data stored in Emacs variables." |
1814 (interactive "*") | 1807 (interactive "*") |
1815 (ses-begin-change) | 1808 (ses-begin-change) |
1816 ;;Reconstruct reference lists. | 1809 ;;Reconstruct reference lists. |
1817 (let (refs x yrow ycol) | 1810 (let (x yrow ycol) |
1818 ;;Delete old reference lists | 1811 ;;Delete old reference lists |
1819 (ses-dotimes-msg (row ses--numrows) "Deleting references..." | 1812 (ses-dotimes-msg (row ses--numrows) "Deleting references..." |
1820 (dotimes (col ses--numcols) | 1813 (dotimes (col ses--numcols) |
1821 (ses-set-cell row col 'references nil))) | 1814 (ses-set-cell row col 'references nil))) |
1822 ;;Create new reference lists | 1815 ;;Create new reference lists |
1828 ycol (cdr x)) | 1821 ycol (cdr x)) |
1829 (ses-set-cell yrow ycol 'references | 1822 (ses-set-cell yrow ycol 'references |
1830 (cons (ses-cell-symbol row col) | 1823 (cons (ses-cell-symbol row col) |
1831 (ses-cell-references yrow ycol))))))) | 1824 (ses-cell-references yrow ycol))))))) |
1832 ;;Delete everything and reconstruct basic data area | 1825 ;;Delete everything and reconstruct basic data area |
1833 (if (< (point-max) (buffer-size)) | 1826 (if (ses-narrowed-p) |
1834 (setq ses--deferred-narrow t)) | 1827 (setq ses--deferred-narrow t)) |
1835 (widen) | 1828 (widen) |
1836 (let ((inhibit-read-only t)) | 1829 (let ((inhibit-read-only t)) |
1837 (goto-char (point-max)) | 1830 (goto-char (point-max)) |
1838 (if (search-backward ";;; Local Variables:\n" nil t) | 1831 (if (search-backward ";; Local Variables:\n" nil t) |
1839 (delete-region (point-min) (point)) | 1832 (delete-region (point-min) (point)) |
1840 ;;Buffer is quite screwed up - can't even save the user-specified locals | 1833 ;;Buffer is quite screwed up - can't even save the user-specified locals |
1841 (delete-region (point-min) (point-max)) | 1834 (delete-region (point-min) (point-max)) |
1842 (insert ses-initial-file-trailer) | 1835 (insert ses-initial-file-trailer) |
1843 (goto-char (point-min))) | 1836 (goto-char (point-min))) |
1860 (ses-setup) | 1853 (ses-setup) |
1861 (ses-recalculate-all) | 1854 (ses-recalculate-all) |
1862 (goto-char (point-min))) | 1855 (goto-char (point-min))) |
1863 | 1856 |
1864 | 1857 |
1865 ;;;---------------------------------------------------------------------------- | 1858 ;;---------------------------------------------------------------------------- |
1866 ;;;; Input of cell formulas | 1859 ;; Input of cell formulas |
1867 ;;;---------------------------------------------------------------------------- | 1860 ;;---------------------------------------------------------------------------- |
1868 | 1861 |
1869 (defun ses-edit-cell (row col newval) | 1862 (defun ses-edit-cell (row col newval) |
1870 "Display current cell contents in minibuffer, for editing. Returns nil if | 1863 "Display current cell contents in minibuffer, for editing. Returns nil if |
1871 cell formula was unsafe and user declined confirmation." | 1864 cell formula was unsafe and user declined confirmation." |
1872 (interactive | 1865 (interactive |
1966 (ses-set-curcell) | 1959 (ses-set-curcell) |
1967 (let ((rowcol (ses-sym-rowcol ses--curcell))) | 1960 (let ((rowcol (ses-sym-rowcol ses--curcell))) |
1968 (ses-clear-cell (car rowcol) (cdr rowcol)))))) | 1961 (ses-clear-cell (car rowcol) (cdr rowcol)))))) |
1969 | 1962 |
1970 | 1963 |
1971 ;;;---------------------------------------------------------------------------- | 1964 ;;---------------------------------------------------------------------------- |
1972 ;;;; Input of cell-printer functions | 1965 ;; Input of cell-printer functions |
1973 ;;;---------------------------------------------------------------------------- | 1966 ;;---------------------------------------------------------------------------- |
1974 | 1967 |
1975 (defun ses-read-printer (prompt default) | 1968 (defun ses-read-printer (prompt default) |
1976 "Common code for `ses-read-cell-printer', `ses-read-column-printer', and `ses-read-default-printer'. | 1969 "Common code for `ses-read-cell-printer', `ses-read-column-printer', and `ses-read-default-printer'. |
1977 PROMPT should end with \": \". Result is t if operation was cancelled." | 1970 PROMPT should end with \": \". Result is t if operation was cancelled." |
1978 (barf-if-buffer-read-only) | 1971 (barf-if-buffer-read-only) |
2007 one argument, or a symbol that names a function of one argument. In the | 2000 one argument, or a symbol that names a function of one argument. In the |
2008 latter two cases, the function's result should be either a string (will be | 2001 latter two cases, the function's result should be either a string (will be |
2009 right-justified) or a list of one string (will be left-justified)." | 2002 right-justified) or a list of one string (will be left-justified)." |
2010 (interactive | 2003 (interactive |
2011 (let ((default t) | 2004 (let ((default t) |
2012 prompt x) | 2005 x) |
2013 (ses-check-curcell 'range) | 2006 (ses-check-curcell 'range) |
2014 ;;Default is none if not all cells in range have same printer | 2007 ;;Default is none if not all cells in range have same printer |
2015 (catch 'ses-read-cell-printer | 2008 (catch 'ses-read-cell-printer |
2016 (ses-dorange ses--curcell | 2009 (ses-dorange ses--curcell |
2017 (setq x (ses-cell-printer row col)) | 2010 (setq x (ses-cell-printer row col)) |
2057 (ses-begin-change) | 2050 (ses-begin-change) |
2058 (ses-set-parameter 'ses--default-printer newval) | 2051 (ses-set-parameter 'ses--default-printer newval) |
2059 (ses-reprint-all t))) | 2052 (ses-reprint-all t))) |
2060 | 2053 |
2061 | 2054 |
2062 ;;;---------------------------------------------------------------------------- | 2055 ;;---------------------------------------------------------------------------- |
2063 ;;;; Spreadsheet size adjustments | 2056 ;; Spreadsheet size adjustments |
2064 ;;;---------------------------------------------------------------------------- | 2057 ;;---------------------------------------------------------------------------- |
2065 | 2058 |
2066 (defun ses-insert-row (count) | 2059 (defun ses-insert-row (count) |
2067 "Insert a new row before the current one. With prefix, insert COUNT rows | 2060 "Insert a new row before the current one. With prefix, insert COUNT rows |
2068 before current one." | 2061 before current one." |
2069 (interactive "*p") | 2062 (interactive "*p") |
2083 (ses-dotimes-msg (x count) "Inserting row..." | 2076 (ses-dotimes-msg (x count) "Inserting row..." |
2084 ;;Create a row of empty cells. The `symbol' fields will be set by | 2077 ;;Create a row of empty cells. The `symbol' fields will be set by |
2085 ;;the call to ses-relocate-all. | 2078 ;;the call to ses-relocate-all. |
2086 (setq newrow (make-vector ses--numcols nil)) | 2079 (setq newrow (make-vector ses--numcols nil)) |
2087 (dotimes (col ses--numcols) | 2080 (dotimes (col ses--numcols) |
2088 (aset newrow col (make-vector ses-cell-size nil))) | 2081 (aset newrow col (ses-make-cell))) |
2089 (setq ses--cells (ses-vector-insert ses--cells row newrow)) | 2082 (setq ses--cells (ses-vector-insert ses--cells row newrow)) |
2090 (push `(ses-vector-delete ses--cells ,row 1) buffer-undo-list) | 2083 (push `(ses-vector-delete ses--cells ,row 1) buffer-undo-list) |
2091 (insert ses--blank-line)) | 2084 (insert ses--blank-line)) |
2092 ;;Insert empty lines in cell data area (will be replaced by | 2085 ;;Insert empty lines in cell data area (will be replaced by |
2093 ;;ses-relocate-all) | 2086 ;;ses-relocate-all) |
2120 (interactive "*p") | 2113 (interactive "*p") |
2121 (ses-check-curcell) | 2114 (ses-check-curcell) |
2122 (or (> count 0) (signal 'args-out-of-range nil)) | 2115 (or (> count 0) (signal 'args-out-of-range nil)) |
2123 (let ((inhibit-quit t) | 2116 (let ((inhibit-quit t) |
2124 (inhibit-read-only t) | 2117 (inhibit-read-only t) |
2125 (row (car (ses-sym-rowcol ses--curcell))) | 2118 (row (car (ses-sym-rowcol ses--curcell)))) |
2126 pos) | |
2127 (setq count (min count (- ses--numrows row))) | 2119 (setq count (min count (- ses--numrows row))) |
2128 (ses-begin-change) | 2120 (ses-begin-change) |
2129 (ses-set-parameter 'ses--numrows (- ses--numrows count)) | 2121 (ses-set-parameter 'ses--numrows (- ses--numrows count)) |
2130 ;;Delete lines from print area | 2122 ;;Delete lines from print area |
2131 (ses-goto-print row 0) | 2123 (ses-goto-print row 0) |
2147 ;;Reconstruct attributes | 2139 ;;Reconstruct attributes |
2148 (ses-setup) | 2140 (ses-setup) |
2149 (ses-jump-safe ses--curcell)) | 2141 (ses-jump-safe ses--curcell)) |
2150 | 2142 |
2151 (defun ses-insert-column (count &optional col width printer) | 2143 (defun ses-insert-column (count &optional col width printer) |
2152 "Insert a new column before COL (default is the current one). With prefix, | 2144 "Insert a new column before COL (default is the current one). |
2153 insert COUNT columns before current one. If COL is specified, the new | 2145 With prefix, insert COUNT columns before current one. |
2154 column(s) get the specified WIDTH and PRINTER (otherwise they're taken from | 2146 If COL is specified, the new column(s) get the specified WIDTH and PRINTER |
2155 the current column)." | 2147 \(otherwise they're taken from the current column)." |
2156 (interactive "*p") | 2148 (interactive "*p") |
2157 (ses-check-curcell) | 2149 (ses-check-curcell) |
2158 (or (> count 0) (signal 'args-out-of-range nil)) | 2150 (or (> count 0) (signal 'args-out-of-range nil)) |
2159 (or col | 2151 (or col |
2160 (setq col (cdr (ses-sym-rowcol ses--curcell)) | 2152 (setq col (cdr (ses-sym-rowcol ses--curcell)) |
2179 (and (< (1+ col) ses--numcols) (eq (ses-cell-value row col) '*skip*) | 2171 (and (< (1+ col) ses--numcols) (eq (ses-cell-value row col) '*skip*) |
2180 ;;Inserting in the middle of a spill-over | 2172 ;;Inserting in the middle of a spill-over |
2181 (setq has-skip t)) | 2173 (setq has-skip t)) |
2182 (ses-aset-with-undo ses--cells row | 2174 (ses-aset-with-undo ses--cells row |
2183 (ses-vector-insert (aref ses--cells row) | 2175 (ses-vector-insert (aref ses--cells row) |
2184 col | 2176 col (ses-make-cell))) |
2185 (make-vector ses-cell-size nil))) | |
2186 ;;Insert empty lines in cell data area (will be replaced by | 2177 ;;Insert empty lines in cell data area (will be replaced by |
2187 ;;ses-relocate-all) | 2178 ;;ses-relocate-all) |
2188 (ses-goto-data row col) | 2179 (ses-goto-data row col) |
2189 (insert ?\n)) | 2180 (insert ?\n)) |
2190 ;;Insert column width and printer | 2181 ;;Insert column width and printer |
2215 (or (> count 0) (signal 'args-out-of-range nil)) | 2206 (or (> count 0) (signal 'args-out-of-range nil)) |
2216 (let ((inhibit-quit t) | 2207 (let ((inhibit-quit t) |
2217 (inhibit-read-only t) | 2208 (inhibit-read-only t) |
2218 (rowcol (ses-sym-rowcol ses--curcell)) | 2209 (rowcol (ses-sym-rowcol ses--curcell)) |
2219 (width 0) | 2210 (width 0) |
2220 new col origrow has-skip) | 2211 col origrow has-skip) |
2221 (setq origrow (car rowcol) | 2212 (setq origrow (car rowcol) |
2222 col (cdr rowcol) | 2213 col (cdr rowcol) |
2223 count (min count (- ses--numcols col))) | 2214 count (min count (- ses--numcols col))) |
2224 (if (= count ses--numcols) | 2215 (if (= count ses--numcols) |
2225 (error "Can't delete all columns!")) | 2216 (error "Can't delete all columns!")) |
2318 (ses-set-parameter 'ses--col-widths newwidth col)) | 2309 (ses-set-parameter 'ses--col-widths newwidth col)) |
2319 (dotimes (row ses--numrows) | 2310 (dotimes (row ses--numrows) |
2320 (ses-print-cell-new-width row col)))) | 2311 (ses-print-cell-new-width row col)))) |
2321 | 2312 |
2322 | 2313 |
2323 ;;;---------------------------------------------------------------------------- | 2314 ;;---------------------------------------------------------------------------- |
2324 ;;;; Cut and paste, import and export | 2315 ;; Cut and paste, import and export |
2325 ;;;---------------------------------------------------------------------------- | 2316 ;;---------------------------------------------------------------------------- |
2326 | 2317 |
2327 (defadvice copy-region-as-kill (around ses-copy-region-as-kill | 2318 (defadvice copy-region-as-kill (around ses-copy-region-as-kill |
2328 activate preactivate) | 2319 activate preactivate) |
2329 "It doesn't make sense to copy read-only or intangible attributes into the | 2320 "It doesn't make sense to copy read-only or intangible attributes into the |
2330 kill ring. It probably doesn't make sense to copy keymap properties. | 2321 kill ring. It probably doesn't make sense to copy keymap properties. |
2652 (push "\n" result)))) | 2643 (push "\n" result)))) |
2653 (setq result (apply 'concat (nreverse result))) | 2644 (setq result (apply 'concat (nreverse result))) |
2654 (kill-new result))) | 2645 (kill-new result))) |
2655 | 2646 |
2656 | 2647 |
2657 ;;;---------------------------------------------------------------------------- | 2648 ;;---------------------------------------------------------------------------- |
2658 ;;;; Other user commands | 2649 ;; Other user commands |
2659 ;;;---------------------------------------------------------------------------- | 2650 ;;---------------------------------------------------------------------------- |
2660 | 2651 |
2661 (defun ses-unset-header-row () | 2652 (defun ses-unset-header-row () |
2662 "Select the default header row." | 2653 "Select the default header row." |
2663 (interactive) | 2654 (interactive) |
2664 (ses-set-header-row 0)) | 2655 (ses-set-header-row 0)) |
2827 (interactive "*e") | 2818 (interactive "*e") |
2828 (mouse-set-point event) | 2819 (mouse-set-point event) |
2829 (ses-insert-ses-range)) | 2820 (ses-insert-ses-range)) |
2830 | 2821 |
2831 | 2822 |
2832 ;;;---------------------------------------------------------------------------- | 2823 ;;---------------------------------------------------------------------------- |
2833 ;;;; Checking formulas for safety | 2824 ;; Checking formulas for safety |
2834 ;;;---------------------------------------------------------------------------- | 2825 ;;---------------------------------------------------------------------------- |
2835 | 2826 |
2836 (defun ses-safe-printer (printer) | 2827 (defun ses-safe-printer (printer) |
2837 "Returns PRINTER if safe, or the substitute printer `ses-unsafe' otherwise." | 2828 "Returns PRINTER if safe, or the substitute printer `ses-unsafe' otherwise." |
2838 (if (or (stringp printer) | 2829 (if (or (stringp printer) |
2839 (stringp (car-safe printer)) | 2830 (stringp (car-safe printer)) |
2860 t | 2851 t |
2861 (y-or-n-p (format "Formula %S\nmight be unsafe %S. Process it? " | 2852 (y-or-n-p (format "Formula %S\nmight be unsafe %S. Process it? " |
2862 formula checker))))) | 2853 formula checker))))) |
2863 | 2854 |
2864 | 2855 |
2865 ;;;---------------------------------------------------------------------------- | 2856 ;;---------------------------------------------------------------------------- |
2866 ;;;; Standard formulas | 2857 ;; Standard formulas |
2867 ;;;---------------------------------------------------------------------------- | 2858 ;;---------------------------------------------------------------------------- |
2868 | 2859 |
2869 (defmacro ses-range (from to) | 2860 (defmacro ses-range (from to) |
2870 "Expands to a list of cell-symbols for the range. The range automatically | 2861 "Expands to a list of cell-symbols for the range. The range automatically |
2871 expands to include any new row or column inserted into its middle. The SES | 2862 expands to include any new row or column inserted into its middle. The SES |
2872 library code specifically looks for the symbol `ses-range', so don't create an | 2863 library code specifically looks for the symbol `ses-range', so don't create an |
2878 | 2869 |
2879 (defun ses-delete-blanks (&rest args) | 2870 (defun ses-delete-blanks (&rest args) |
2880 "Return ARGS reversed, with the blank elements (nil and *skip*) removed." | 2871 "Return ARGS reversed, with the blank elements (nil and *skip*) removed." |
2881 (let (result) | 2872 (let (result) |
2882 (dolist (cur args) | 2873 (dolist (cur args) |
2883 (and cur (not (eq cur '*skip*)) | 2874 (unless (memq cur '(nil *skip*)) |
2884 (push cur result))) | 2875 (push cur result))) |
2885 result)) | 2876 result)) |
2886 | 2877 |
2887 (defun ses+ (&rest args) | 2878 (defun ses+ (&rest args) |
2888 "Compute the sum of the arguments, ignoring blanks." | 2879 "Compute the sum of the arguments, ignoring blanks." |
2889 (apply '+ (apply 'ses-delete-blanks args))) | 2880 (apply '+ (apply 'ses-delete-blanks args))) |
2914 ;;All standard formulas are safe | 2905 ;;All standard formulas are safe |
2915 (dolist (x '(ses-range ses-delete-blanks ses+ ses-average ses-select)) | 2906 (dolist (x '(ses-range ses-delete-blanks ses+ ses-average ses-select)) |
2916 (put x 'side-effect-free t)) | 2907 (put x 'side-effect-free t)) |
2917 | 2908 |
2918 | 2909 |
2919 ;;;---------------------------------------------------------------------------- | 2910 ;;---------------------------------------------------------------------------- |
2920 ;;;; Standard print functions | 2911 ;; Standard print functions |
2921 ;;;---------------------------------------------------------------------------- | 2912 ;;---------------------------------------------------------------------------- |
2922 | 2913 |
2923 ;;These functions use the variables 'row' and 'col' that are | 2914 ;;These functions use the variables 'row' and 'col' that are |
2924 ;;dynamically bound by ses-print-cell. We define these varables at | 2915 ;;dynamically bound by ses-print-cell. We define these varables at |
2925 ;;compile-time to make the compiler happy. | 2916 ;;compile-time to make the compiler happy. |
2926 (eval-when-compile | 2917 (eval-when-compile |
2980 (dolist (x (cons 'ses-unsafe ses-standard-printer-functions)) | 2971 (dolist (x (cons 'ses-unsafe ses-standard-printer-functions)) |
2981 (put x 'side-effect-free t)) | 2972 (put x 'side-effect-free t)) |
2982 | 2973 |
2983 (provide 'ses) | 2974 (provide 'ses) |
2984 | 2975 |
2985 ;;; arch-tag: 88c1ccf0-4293-4824-8c5d-0757b52217f3 | 2976 ;; arch-tag: 88c1ccf0-4293-4824-8c5d-0757b52217f3 |
2986 ;; ses.el ends here. | 2977 ;;; ses.el ends here |