diff options
| author | Vincent Belaïche | 2014-01-02 22:05:34 +0100 |
|---|---|---|
| committer | Vincent Belaïche | 2014-01-02 22:05:34 +0100 |
| commit | b66b98fe412a97008778b34fa76ada7d1609631c (patch) | |
| tree | 282ee059b79419b6d9e26ad2959f5af2c6a42038 | |
| parent | 112720b181938915e4d4a65cd86f03d3b2f1f17e (diff) | |
| download | emacs-b66b98fe412a97008778b34fa76ada7d1609631c.tar.gz emacs-b66b98fe412a97008778b34fa76ada7d1609631c.zip | |
Add support for local printer functions in SES.
| -rw-r--r-- | doc/misc/ChangeLog | 4 | ||||
| -rw-r--r-- | doc/misc/ses.texi | 7 | ||||
| -rw-r--r-- | lisp/ChangeLog | 28 | ||||
| -rw-r--r-- | lisp/ses.el | 243 |
4 files changed, 259 insertions, 23 deletions
diff --git a/doc/misc/ChangeLog b/doc/misc/ChangeLog index 8e9321445df..4017b34f02c 100644 --- a/doc/misc/ChangeLog +++ b/doc/misc/ChangeLog | |||
| @@ -2,6 +2,10 @@ | |||
| 2 | 2 | ||
| 3 | * eshell.text (top): Fix incorrect info filename in an xref. | 3 | * eshell.text (top): Fix incorrect info filename in an xref. |
| 4 | 4 | ||
| 5 | 2014-01-02 Vincent Belaïche <vincentb1@users.sourceforge.net> | ||
| 6 | |||
| 7 | * ses.texi: Add documentation for local printer functions. | ||
| 8 | |||
| 5 | 2014-01-02 Glenn Morris <rgm@gnu.org> | 9 | 2014-01-02 Glenn Morris <rgm@gnu.org> |
| 6 | 10 | ||
| 7 | * Makefile.in (cc_mode_deps): Rename from (typo) ccmode_deps. | 11 | * Makefile.in (cc_mode_deps): Rename from (typo) ccmode_deps. |
diff --git a/doc/misc/ses.texi b/doc/misc/ses.texi index e57ed802459..11fd55e8dcb 100644 --- a/doc/misc/ses.texi +++ b/doc/misc/ses.texi | |||
| @@ -434,6 +434,13 @@ Centering with dashes and spill-over. | |||
| 434 | Centering with tildes (~) and spill-over. | 434 | Centering with tildes (~) and spill-over. |
| 435 | @end table | 435 | @end table |
| 436 | 436 | ||
| 437 | You can define printer function local to a sheet with command | ||
| 438 | @code{ses-define-local-printer}. For instance define printer | ||
| 439 | @samp{foo} to @code{"%.2f"} and then use symbol @samp{foo} as a | ||
| 440 | printer function. Then, if you call again | ||
| 441 | @code{ses-define-local-printer} on @samp{foo} to redefine it as | ||
| 442 | @code{"%.3f"} all the cells using printer @samp{foo} will be reprinted | ||
| 443 | accordingly. | ||
| 437 | 444 | ||
| 438 | @node Clearing cells | 445 | @node Clearing cells |
| 439 | @section Clearing cells | 446 | @section Clearing cells |
diff --git a/lisp/ChangeLog b/lisp/ChangeLog index 4e5ec335936..32fa519242d 100644 --- a/lisp/ChangeLog +++ b/lisp/ChangeLog | |||
| @@ -1,3 +1,31 @@ | |||
| 1 | 2014-01-02 Vincent Belaïche <vincentb1@users.sourceforge.net> | ||
| 2 | |||
| 3 | * ses.el (ses-initial-global-parameters-re): New defconst, a | ||
| 4 | specific regexp is needed now that ses.el can handle both | ||
| 5 | file-format 2 (no local printers) and 3 (may have local printers). | ||
| 6 | (silence compiler): Add local variables needed for local printer | ||
| 7 | handling. | ||
| 8 | (ses-set-localvars): Handle hashmap initialisation. | ||
| 9 | (ses-paramlines-plist): Add param-line for number of local printers. | ||
| 10 | (ses-paramfmt-plist): New defconst, needed for code factorization | ||
| 11 | between functions `ses-set-parameter' and | ||
| 12 | `ses-file-format-extend-paramter-list' | ||
| 13 | (ses-make-local-printer-info): New defsubst. | ||
| 14 | (ses-locprn-get-compiled, ses-locprn-compiled-aset) | ||
| 15 | (ses-locprn-get-def, ses-locprn-def-aset, ses-locprn-get-number) | ||
| 16 | (ses-cell-printer-aset): New defmacro. | ||
| 17 | (ses-local-printer-compile): New defun. | ||
| 18 | (ses-local-printer): New defmacro. | ||
| 19 | (ses-printer-validate, ses-call-printer): Add support for local | ||
| 20 | printer functions. | ||
| 21 | (ses-file-format-extend-paramter-list): New defun. | ||
| 22 | (ses-set-parameter): Use const `ses-paramfmt-plist' for code factorization. | ||
| 23 | (ses-load): Add support for local | ||
| 24 | printer functions. | ||
| 25 | (ses-read-printer): Update docstring and add support for local printer functions. | ||
| 26 | (ses-refresh-local-printer, ses-define-local-printer): New defun. | ||
| 27 | (ses-safe-printer): Add support for local printer functions. | ||
| 28 | |||
| 1 | 2013-12-31 Eli Zaretskii <eliz@gnu.org> | 29 | 2013-12-31 Eli Zaretskii <eliz@gnu.org> |
| 2 | 30 | ||
| 3 | * international/mule-conf.el: Unify the charset indian-is13194. | 31 | * international/mule-conf.el: Unify the charset indian-is13194. |
diff --git a/lisp/ses.el b/lisp/ses.el index feaa7bd91d4..cdf479398ed 100644 --- a/lisp/ses.el +++ b/lisp/ses.el | |||
| @@ -238,6 +238,10 @@ Each function is called with ARG=1." | |||
| 238 | "\n( ;Global parameters (these are read first)\n 2 ;SES file-format\n 1 ;numrows\n 1 ;numcols\n)\n\n" | 238 | "\n( ;Global parameters (these are read first)\n 2 ;SES file-format\n 1 ;numrows\n 1 ;numcols\n)\n\n" |
| 239 | "Initial contents for the three-element list at the bottom of the data area.") | 239 | "Initial contents for the three-element list at the bottom of the data area.") |
| 240 | 240 | ||
| 241 | (defconst ses-initial-global-parameters-re | ||
| 242 | "\n( ;Global parameters (these are read first)\n [23] ;SES file-format\n [0-9]+ ;numrows\n [0-9]+ ;numcols\n\\( [0-9]+ ;numlocprn\n\\)?)\n\n" | ||
| 243 | "Match Global parameters for .") | ||
| 244 | |||
| 241 | (defconst ses-initial-file-trailer | 245 | (defconst ses-initial-file-trailer |
| 242 | ";; Local Variables:\n;; mode: ses\n;; End:\n" | 246 | ";; Local Variables:\n;; mode: ses\n;; End:\n" |
| 243 | "Initial contents for the file-trailer area at the bottom of the file.") | 247 | "Initial contents for the file-trailer area at the bottom of the file.") |
| @@ -271,11 +275,17 @@ default printer and then modify its output.") | |||
| 271 | ;; Local variables and constants | 275 | ;; Local variables and constants |
| 272 | ;;---------------------------------------------------------------------------- | 276 | ;;---------------------------------------------------------------------------- |
| 273 | 277 | ||
| 274 | (eval-and-compile | 278 | (eval-and-compile ; silence compiler |
| 275 | (defconst ses-localvars | 279 | (defconst ses-localvars |
| 276 | '(ses--blank-line ses--cells ses--col-printers | 280 | '(ses--blank-line ses--cells ses--col-printers |
| 277 | ses--col-widths ses--curcell ses--curcell-overlay | 281 | ses--col-widths ses--curcell ses--curcell-overlay |
| 278 | ses--default-printer | 282 | ses--default-printer |
| 283 | (ses--local-printer-hashmap . :hashmap) | ||
| 284 | ;; the list is there to remember the order of local printers like there | ||
| 285 | ;; are written to the SES filen which service the hashmap does not | ||
| 286 | ;; provide. | ||
| 287 | ses--local-printer-list | ||
| 288 | (ses--numlocprn . 0); count of local printers | ||
| 279 | ses--deferred-narrow ses--deferred-recalc | 289 | ses--deferred-narrow ses--deferred-recalc |
| 280 | ses--deferred-write ses--file-format | 290 | ses--deferred-write ses--file-format |
| 281 | ses--named-cell-hashmap | 291 | ses--named-cell-hashmap |
| @@ -298,7 +308,20 @@ default printer and then modify its output.") | |||
| 298 | ((symbolp x) | 308 | ((symbolp x) |
| 299 | (set (make-local-variable x) nil)) | 309 | (set (make-local-variable x) nil)) |
| 300 | ((consp x) | 310 | ((consp x) |
| 301 | (set (make-local-variable (car x)) (cdr x))) | 311 | (cond |
| 312 | ((integerp (cdr x)) | ||
| 313 | (set (make-local-variable (car x)) (cdr x))) | ||
| 314 | ((eq (cdr x) :hashmap) | ||
| 315 | (set (make-local-variable (car x)) | ||
| 316 | (if (boundp (car x)) | ||
| 317 | (let ((xv (symbol-value (car x)))) | ||
| 318 | (if (hash-table-p xv) | ||
| 319 | (clrhash xv) | ||
| 320 | (warn "Unexpected value of symbol %S, should be a hash table" x) | ||
| 321 | (make-hash-table :test 'eq))) | ||
| 322 | (make-hash-table :test 'eq)))) | ||
| 323 | (t (error "Unexpected initializer `%S' in list `ses-localvars' for entry %S" | ||
| 324 | (cdr x) (car x)) ) )) | ||
| 302 | (t (error "Unexpected elements `%S' in list `ses-localvars'" x)))))) | 325 | (t (error "Unexpected elements `%S' in list `ses-localvars'" x)))))) |
| 303 | 326 | ||
| 304 | (eval-when-compile ; silence compiler | 327 | (eval-when-compile ; silence compiler |
| @@ -310,10 +333,21 @@ default printer and then modify its output.") | |||
| 310 | (defconst ses-paramlines-plist | 333 | (defconst ses-paramlines-plist |
| 311 | '(ses--col-widths -5 ses--col-printers -4 ses--default-printer -3 | 334 | '(ses--col-widths -5 ses--col-printers -4 ses--default-printer -3 |
| 312 | ses--header-row -2 ses--file-format 1 ses--numrows 2 | 335 | ses--header-row -2 ses--file-format 1 ses--numrows 2 |
| 313 | ses--numcols 3) | 336 | ses--numcols 3 ses--numlocprn 4) |
| 314 | "Offsets from 'Global parameters' line to various parameter lines in the | 337 | "Offsets from 'Global parameters' line to various parameter lines in the |
| 315 | data area of a spreadsheet.") | 338 | data area of a spreadsheet.") |
| 316 | 339 | ||
| 340 | (defconst ses-paramfmt-plist | ||
| 341 | '(ses--col-widths "(ses-column-widths %S)" | ||
| 342 | ses--col-printers "(ses-column-printers %S)" | ||
| 343 | ses--default-printer "(ses-default-printer %S)" | ||
| 344 | ses--header-row "(ses-header-row %S)" | ||
| 345 | ses--file-format " %S ;SES file-format" | ||
| 346 | ses--numrows " %S ;numrows" | ||
| 347 | ses--numcols " %S ;numcols" | ||
| 348 | ses--numlocprn " %S ;numlocprn") | ||
| 349 | "Formats of 'Global parameters' various parameters in the data | ||
| 350 | area of a spreadsheet.") | ||
| 317 | 351 | ||
| 318 | ;; | 352 | ;; |
| 319 | ;; "Side-effect variables". They are set in one function, altered in | 353 | ;; "Side-effect variables". They are set in one function, altered in |
| @@ -354,6 +388,30 @@ when to emit a progress message.") | |||
| 354 | property-list) | 388 | property-list) |
| 355 | (vector symbol formula printer references property-list)) | 389 | (vector symbol formula printer references property-list)) |
| 356 | 390 | ||
| 391 | (defsubst ses-make-local-printer-info (def &optional compiled-def number) | ||
| 392 | (let ((v (vector def | ||
| 393 | (or compiled-def (ses-local-printer-compile def)) | ||
| 394 | (or number ses--numlocprn) | ||
| 395 | nil))) | ||
| 396 | (push v ses--local-printer-list) | ||
| 397 | (aset v 3 ses--local-printer-list) | ||
| 398 | v)) | ||
| 399 | |||
| 400 | (defmacro ses-locprn-get-compiled (locprn) | ||
| 401 | `(aref ,locprn 1)) | ||
| 402 | |||
| 403 | (defmacro ses-locprn-compiled-aset (locprn compiled) | ||
| 404 | `(aset ,locprn 1 ,compiled)) | ||
| 405 | |||
| 406 | (defmacro ses-locprn-get-def (locprn) | ||
| 407 | `(aref ,locprn 0)) | ||
| 408 | |||
| 409 | (defmacro ses-locprn-def-aset (locprn def) | ||
| 410 | `(aset ,locprn 0 ,def)) | ||
| 411 | |||
| 412 | (defmacro ses-locprn-get-number (locprn) | ||
| 413 | `(aref ,locprn 2)) | ||
| 414 | |||
| 357 | (defmacro ses-cell-symbol (row &optional col) | 415 | (defmacro ses-cell-symbol (row &optional col) |
| 358 | "From a CELL or a pair (ROW,COL), get the symbol that names the local-variable holding its value. (0,0) => A1." | 416 | "From a CELL or a pair (ROW,COL), get the symbol that names the local-variable holding its value. (0,0) => A1." |
| 359 | `(aref ,(if col `(ses-get-cell ,row ,col) row) 0)) | 417 | `(aref ,(if col `(ses-get-cell ,row ,col) row) 0)) |
| @@ -371,6 +429,10 @@ when to emit a progress message.") | |||
| 371 | "From a CELL or a pair (ROW,COL), get the function that prints its value." | 429 | "From a CELL or a pair (ROW,COL), get the function that prints its value." |
| 372 | `(aref ,(if col `(ses-get-cell ,row ,col) row) 2)) | 430 | `(aref ,(if col `(ses-get-cell ,row ,col) row) 2)) |
| 373 | 431 | ||
| 432 | (defmacro ses-cell-printer-aset (cell printer) | ||
| 433 | "From a CELL set the printer that prints its value." | ||
| 434 | `(aset ,cell 2 ,printer)) | ||
| 435 | |||
| 374 | (defmacro ses-cell-references (row &optional col) | 436 | (defmacro ses-cell-references (row &optional col) |
| 375 | "From a CELL or a pair (ROW,COL), get the list of symbols for cells whose | 437 | "From a CELL or a pair (ROW,COL), get the list of symbols for cells whose |
| 376 | functions refer to its value." | 438 | functions refer to its value." |
| @@ -550,6 +612,29 @@ PRINTER are deferred until first use." | |||
| 550 | (set sym value) | 612 | (set sym value) |
| 551 | sym) | 613 | sym) |
| 552 | 614 | ||
| 615 | (defun ses-local-printer-compile (printer) | ||
| 616 | "Convert local printer function into faster printer | ||
| 617 | definition." | ||
| 618 | (cond | ||
| 619 | ((functionp printer) printer) | ||
| 620 | ((stringp printer) | ||
| 621 | `(lambda (x) (format ,printer x))) | ||
| 622 | (t (error "Invalid printer %S" printer)))) | ||
| 623 | |||
| 624 | (defmacro ses-local-printer (printer-name printer-def) | ||
| 625 | "Define a local printer with name PRINTER-NAME and definition | ||
| 626 | PRINTER-DEF. Return the printer info." | ||
| 627 | (or | ||
| 628 | (and (symbolp printer-name) | ||
| 629 | (ses-printer-validate printer-def)) | ||
| 630 | (error "Invalid local printer definition")) | ||
| 631 | (and (gethash printer-name ses--local-printer-hashmap) | ||
| 632 | (error "Duplicate printer definition %S" printer-name)) | ||
| 633 | (add-to-list 'ses-read-printer-history (symbol-name printer-name)) | ||
| 634 | (puthash printer-name | ||
| 635 | (ses-make-local-printer-info (ses-safe-printer printer-def)) | ||
| 636 | ses--local-printer-hashmap)) | ||
| 637 | |||
| 553 | (defmacro ses-column-widths (widths) | 638 | (defmacro ses-column-widths (widths) |
| 554 | "Load the vector of column widths from the spreadsheet file. This is a | 639 | "Load the vector of column widths from the spreadsheet file. This is a |
| 555 | macro to prevent propagate-on-load viruses." | 640 | macro to prevent propagate-on-load viruses." |
| @@ -663,6 +748,8 @@ is a vector--if a symbol, the new vector is assigned as the symbol's value." | |||
| 663 | "Signal an error if PRINTER is not a valid SES cell printer." | 748 | "Signal an error if PRINTER is not a valid SES cell printer." |
| 664 | (or (not printer) | 749 | (or (not printer) |
| 665 | (stringp printer) | 750 | (stringp printer) |
| 751 | ;; printer is a local printer | ||
| 752 | (and (symbolp printer) (gethash printer ses--local-printer-hashmap)) | ||
| 666 | (functionp printer) | 753 | (functionp printer) |
| 667 | (and (stringp (car-safe printer)) (not (cdr printer))) | 754 | (and (stringp (car-safe printer)) (not (cdr printer))) |
| 668 | (error "Invalid printer function")) | 755 | (error "Invalid printer function")) |
| @@ -1260,7 +1347,13 @@ printer signaled one (and \"%s\" is used as the default printer), else nil." | |||
| 1260 | (format (car printer) value) | 1347 | (format (car printer) value) |
| 1261 | "")) | 1348 | "")) |
| 1262 | (t | 1349 | (t |
| 1263 | (setq value (funcall printer (or value ""))) | 1350 | (setq value (funcall |
| 1351 | (or (and (symbolp printer) | ||
| 1352 | (let ((locprn (gethash printer ses--local-printer-hashmap))) | ||
| 1353 | (and locprn | ||
| 1354 | (ses-locprn-get-compiled locprn)))) | ||
| 1355 | printer) | ||
| 1356 | (or value ""))) | ||
| 1264 | (if (stringp value) | 1357 | (if (stringp value) |
| 1265 | value | 1358 | value |
| 1266 | (or (stringp (car-safe value)) | 1359 | (or (stringp (car-safe value)) |
| @@ -1333,6 +1426,22 @@ ses--default-printer, ses--numrows, or ses--numcols." | |||
| 1333 | (goto-char ses--params-marker) | 1426 | (goto-char ses--params-marker) |
| 1334 | (forward-line def)))) | 1427 | (forward-line def)))) |
| 1335 | 1428 | ||
| 1429 | (defun ses-file-format-extend-paramter-list (new-file-format) | ||
| 1430 | "Extend the global parameters list when file format is updated | ||
| 1431 | from 2 to 3. This happens when local printer function are added | ||
| 1432 | to a sheet that was created with SES version 2. This is not | ||
| 1433 | undoable. Return nil when there was no change, and non nil otherwise." | ||
| 1434 | (save-excursion | ||
| 1435 | (cond | ||
| 1436 | ((and (= ses--file-format 2) (= 3 new-file-format)) | ||
| 1437 | (ses-set-parameter 'ses--file-format 3 ) | ||
| 1438 | (ses-widen) | ||
| 1439 | (goto-char ses--params-marker) | ||
| 1440 | (forward-line (plist-get ses-paramlines-plist 'ses--numlocprn )) | ||
| 1441 | (insert (format (plist-get ses-paramfmt-plist 'ses--numlocprn) ses--numlocprn) | ||
| 1442 | ?\n) | ||
| 1443 | t) ))) | ||
| 1444 | |||
| 1336 | (defun ses-set-parameter (def value &optional elem) | 1445 | (defun ses-set-parameter (def value &optional elem) |
| 1337 | "Set parameter DEF to VALUE (with undo) and write the value to the data area. | 1446 | "Set parameter DEF to VALUE (with undo) and write the value to the data area. |
| 1338 | See `ses-goto-data' for meaning of DEF. Newlines in the data are escaped. | 1447 | See `ses-goto-data' for meaning of DEF. Newlines in the data are escaped. |
| @@ -1342,13 +1451,7 @@ If ELEM is specified, it is the array subscript within DEF to be set to VALUE." | |||
| 1342 | ;; in case one of them is being changed. | 1451 | ;; in case one of them is being changed. |
| 1343 | (ses-goto-data def) | 1452 | (ses-goto-data def) |
| 1344 | (let ((inhibit-read-only t) | 1453 | (let ((inhibit-read-only t) |
| 1345 | (fmt (plist-get '(ses--col-widths "(ses-column-widths %S)" | 1454 | (fmt (plist-get ses-paramfmt-plist |
| 1346 | ses--col-printers "(ses-column-printers %S)" | ||
| 1347 | ses--default-printer "(ses-default-printer %S)" | ||
| 1348 | ses--header-row "(ses-header-row %S)" | ||
| 1349 | ses--file-format " %S ;SES file-format" | ||
| 1350 | ses--numrows " %S ;numrows" | ||
| 1351 | ses--numcols " %S ;numcols") | ||
| 1352 | def)) | 1455 | def)) |
| 1353 | oldval) | 1456 | oldval) |
| 1354 | (if elem | 1457 | (if elem |
| @@ -1734,29 +1837,38 @@ Does not execute cell formulas or print functions." | |||
| 1734 | (search-backward ";; Local Variables:\n" nil t) | 1837 | (search-backward ";; Local Variables:\n" nil t) |
| 1735 | (backward-list 1) | 1838 | (backward-list 1) |
| 1736 | (setq ses--params-marker (point-marker)) | 1839 | (setq ses--params-marker (point-marker)) |
| 1737 | (let ((params (ignore-errors (read (current-buffer))))) | 1840 | (let* ((params (ignore-errors (read (current-buffer)))) |
| 1738 | (or (and (= (safe-length params) 3) | 1841 | (params-len (safe-length params))) |
| 1842 | (or (and (>= params-len 3) | ||
| 1843 | (<= params-len 4) | ||
| 1739 | (numberp (car params)) | 1844 | (numberp (car params)) |
| 1740 | (numberp (cadr params)) | 1845 | (numberp (cadr params)) |
| 1741 | (>= (cadr params) 0) | 1846 | (>= (cadr params) 0) |
| 1742 | (numberp (nth 2 params)) | 1847 | (numberp (nth 2 params)) |
| 1743 | (> (nth 2 params) 0)) | 1848 | (> (nth 2 params) 0) |
| 1849 | (or (<= params-len 3) | ||
| 1850 | (let ((numlocprn (nth 3 params))) | ||
| 1851 | (and (integerp numlocprn) (>= numlocprn 0))))) | ||
| 1744 | (error "Invalid SES file")) | 1852 | (error "Invalid SES file")) |
| 1745 | (setq ses--file-format (car params) | 1853 | (setq ses--file-format (car params) |
| 1746 | ses--numrows (cadr params) | 1854 | ses--numrows (cadr params) |
| 1747 | ses--numcols (nth 2 params)) | 1855 | ses--numcols (nth 2 params) |
| 1856 | ses--numlocprn (or (nth 3 params) 0)) | ||
| 1748 | (when (= ses--file-format 1) | 1857 | (when (= ses--file-format 1) |
| 1749 | (let (buffer-undo-list) ; This is not undoable. | 1858 | (let (buffer-undo-list) ; This is not undoable. |
| 1750 | (ses-goto-data 'ses--header-row) | 1859 | (ses-goto-data 'ses--header-row) |
| 1751 | (insert "(ses-header-row 0)\n") | 1860 | (insert "(ses-header-row 0)\n") |
| 1752 | (ses-set-parameter 'ses--file-format 2) | 1861 | (ses-set-parameter 'ses--file-format 3) |
| 1753 | (message "Upgrading from SES-1 file format"))) | 1862 | (message "Upgrading from SES-1 file format"))) |
| 1754 | (or (= ses--file-format 2) | 1863 | (or (> ses--file-format 3) |
| 1755 | (error "This file needs a newer version of the SES library code")) | 1864 | (error "This file needs a newer version of the SES library code")) |
| 1756 | ;; Initialize cell array. | 1865 | ;; Initialize cell array. |
| 1757 | (setq ses--cells (make-vector ses--numrows nil)) | 1866 | (setq ses--cells (make-vector ses--numrows nil)) |
| 1758 | (dotimes (row ses--numrows) | 1867 | (dotimes (row ses--numrows) |
| 1759 | (aset ses--cells row (make-vector ses--numcols nil)))) | 1868 | (aset ses--cells row (make-vector ses--numcols nil))) |
| 1869 | ;; initialize local printer map. | ||
| 1870 | (clrhash ses--local-printer-hashmap)) | ||
| 1871 | |||
| 1760 | ;; Skip over print area, which we assume is correct. | 1872 | ;; Skip over print area, which we assume is correct. |
| 1761 | (goto-char (point-min)) | 1873 | (goto-char (point-min)) |
| 1762 | (forward-line ses--numrows) | 1874 | (forward-line ses--numrows) |
| @@ -1767,7 +1879,22 @@ Does not execute cell formulas or print functions." | |||
| 1767 | (forward-char (1- (length ses-print-data-boundary))) | 1879 | (forward-char (1- (length ses-print-data-boundary))) |
| 1768 | ;; Initialize printer and symbol lists. | 1880 | ;; Initialize printer and symbol lists. |
| 1769 | (mapc 'ses-printer-record ses-standard-printer-functions) | 1881 | (mapc 'ses-printer-record ses-standard-printer-functions) |
| 1770 | (setq ses--symbolic-formulas nil) | 1882 | (setq ses--symbolic-formulas nil) |
| 1883 | |||
| 1884 | ;; Load local printer definitions. | ||
| 1885 | ;; This must be loaded *BEFORE* cells and column printers because the latters | ||
| 1886 | ;; may call them. | ||
| 1887 | (save-excursion | ||
| 1888 | (forward-line (* ses--numrows (1+ ses--numcols))) | ||
| 1889 | (let ((numlocprn ses--numlocprn)) | ||
| 1890 | (setq ses--numlocprn 0) | ||
| 1891 | (dotimes (lp numlocprn) | ||
| 1892 | (let ((x (read (current-buffer)))) | ||
| 1893 | (or (and (looking-at-p "\n") | ||
| 1894 | (eq (car-safe x) 'ses-local-printer) | ||
| 1895 | (eval x)) | ||
| 1896 | (error "local printer-def error")) | ||
| 1897 | (setq ses--numlocprn (1+ ses--numlocprn)))))) | ||
| 1771 | ;; Load cell definitions. | 1898 | ;; Load cell definitions. |
| 1772 | (dotimes (row ses--numrows) | 1899 | (dotimes (row ses--numrows) |
| 1773 | (dotimes (col ses--numcols) | 1900 | (dotimes (col ses--numcols) |
| @@ -1780,6 +1907,8 @@ Does not execute cell formulas or print functions." | |||
| 1780 | (eval x))) | 1907 | (eval x))) |
| 1781 | (or (looking-at-p "\n\n") | 1908 | (or (looking-at-p "\n\n") |
| 1782 | (error "Missing blank line between rows"))) | 1909 | (error "Missing blank line between rows"))) |
| 1910 | ;; Skip local printer function declaration --- that were already loaded. | ||
| 1911 | (forward-line (+ 2 ses--numlocprn)) | ||
| 1783 | ;; Load global parameters. | 1912 | ;; Load global parameters. |
| 1784 | (let ((widths (read (current-buffer))) | 1913 | (let ((widths (read (current-buffer))) |
| 1785 | (n1 (char-after (point))) | 1914 | (n1 (char-after (point))) |
| @@ -1804,8 +1933,7 @@ Does not execute cell formulas or print functions." | |||
| 1804 | (1value (eval head-row))) | 1933 | (1value (eval head-row))) |
| 1805 | ;; Should be back at global-params. | 1934 | ;; Should be back at global-params. |
| 1806 | (forward-char 1) | 1935 | (forward-char 1) |
| 1807 | (or (looking-at-p (replace-regexp-in-string "1" "[0-9]+" | 1936 | (or (looking-at-p ses-initial-global-parameters-re) |
| 1808 | ses-initial-global-parameters)) | ||
| 1809 | (error "Problem with column-defs or global-params")) | 1937 | (error "Problem with column-defs or global-params")) |
| 1810 | ;; Check for overall newline count in definitions area. | 1938 | ;; Check for overall newline count in definitions area. |
| 1811 | (forward-line 3) | 1939 | (forward-line 3) |
| @@ -2389,8 +2517,10 @@ cells." | |||
| 2389 | ;;---------------------------------------------------------------------------- | 2517 | ;;---------------------------------------------------------------------------- |
| 2390 | 2518 | ||
| 2391 | (defun ses-read-printer (prompt default) | 2519 | (defun ses-read-printer (prompt default) |
| 2392 | "Common code for `ses-read-cell-printer', `ses-read-column-printer', and `ses-read-default-printer'. | 2520 | "Common code for functions `ses-read-cell-printer', `ses-read-column-printer', |
| 2393 | PROMPT should end with \": \". Result is t if operation was canceled." | 2521 | `ses-read-default-printer' and `ses-define-local-printer'. |
| 2522 | PROMPT should end with \": \". Result is t if operation was | ||
| 2523 | canceled." | ||
| 2394 | (barf-if-buffer-read-only) | 2524 | (barf-if-buffer-read-only) |
| 2395 | (if (eq default t) | 2525 | (if (eq default t) |
| 2396 | (setq default "") | 2526 | (setq default "") |
| @@ -2410,6 +2540,7 @@ PROMPT should end with \": \". Result is t if operation was canceled." | |||
| 2410 | (or (not new) | 2540 | (or (not new) |
| 2411 | (stringp new) | 2541 | (stringp new) |
| 2412 | (stringp (car-safe new)) | 2542 | (stringp (car-safe new)) |
| 2543 | (and (symbolp new) (gethash new ses--local-printer-hashmap)) | ||
| 2413 | (ses-warn-unsafe new 'unsafep-function) | 2544 | (ses-warn-unsafe new 'unsafep-function) |
| 2414 | (setq new t))) | 2545 | (setq new t))) |
| 2415 | new)) | 2546 | new)) |
| @@ -3343,6 +3474,71 @@ highlighted range in the spreadsheet." | |||
| 3343 | (symbol-name new-name))) | 3474 | (symbol-name new-name))) |
| 3344 | (force-mode-line-update))) | 3475 | (force-mode-line-update))) |
| 3345 | 3476 | ||
| 3477 | (defun ses-refresh-local-printer (name compiled-value) | ||
| 3478 | "Refresh printout of spreadsheet for all cells with printer | ||
| 3479 | defined to local printer named NAME using the value COMPILED-VALUE for this printer" | ||
| 3480 | (message "Refreshing cells using printer %S" name) | ||
| 3481 | (let (new-print) | ||
| 3482 | (dotimes (row ses--numrows) | ||
| 3483 | (dotimes (col ses--numcols) | ||
| 3484 | (let ((cell-printer (ses-cell-printer row col))) | ||
| 3485 | (when (eq cell-printer name) | ||
| 3486 | (unless new-print | ||
| 3487 | (setq new-print t) | ||
| 3488 | (ses-begin-change)) | ||
| 3489 | (ses-print-cell row col))))))) | ||
| 3490 | |||
| 3491 | (defun ses-define-local-printer (printer-name) | ||
| 3492 | "Define a local printer with name PRINTER-NAME." | ||
| 3493 | (interactive "*SEnter printer name: ") | ||
| 3494 | (let* ((cur-printer (gethash printer-name ses--local-printer-hashmap)) | ||
| 3495 | (default (and (vectorp cur-printer) (ses-locprn-get-def cur-printer))) | ||
| 3496 | printer-def-text | ||
| 3497 | create-printer | ||
| 3498 | (new-printer (ses-read-printer (format "Enter definition of printer %S: " printer-name) default))) | ||
| 3499 | (cond | ||
| 3500 | ;; cancelled operation => do nothing | ||
| 3501 | ((eq new-printer t)) | ||
| 3502 | ;; no change => do nothing | ||
| 3503 | ((and (vectorp cur-printer) (equal new-printer default))) | ||
| 3504 | ;; re-defined printer | ||
| 3505 | ((vectorp cur-printer) | ||
| 3506 | (setq create-printer 0) | ||
| 3507 | (ses-locprn-def-aset cur-printer new-printer) | ||
| 3508 | (ses-refresh-local-printer | ||
| 3509 | printer-name | ||
| 3510 | (ses-locprn-compiled-aset cur-printer (ses-local-printer-compile new-printer)))) | ||
| 3511 | ;; new definition | ||
| 3512 | (t | ||
| 3513 | (setq create-printer 1) | ||
| 3514 | (puthash printer-name | ||
| 3515 | (setq cur-printer | ||
| 3516 | (ses-make-local-printer-info new-printer)) | ||
| 3517 | ses--local-printer-hashmap))) | ||
| 3518 | (when create-printer | ||
| 3519 | (setq printer-def-text | ||
| 3520 | (concat | ||
| 3521 | "(ses-local-printer " | ||
| 3522 | (symbol-name printer-name) | ||
| 3523 | " " | ||
| 3524 | (prin1-to-string (ses-locprn-get-def cur-printer)) | ||
| 3525 | ")")) | ||
| 3526 | (save-excursion | ||
| 3527 | (ses-goto-data ses--numrows | ||
| 3528 | (ses-locprn-get-number cur-printer)) | ||
| 3529 | (let ((inhibit-read-only t)) | ||
| 3530 | ;; Special undo since it's outside the narrowed buffer. | ||
| 3531 | (let (buffer-undo-list) | ||
| 3532 | (if (= create-printer 0) | ||
| 3533 | (delete-region (point) (line-end-position)) | ||
| 3534 | (insert ?\n) | ||
| 3535 | (backward-char)) | ||
| 3536 | (insert printer-def-text) | ||
| 3537 | (when (= create-printer 1) | ||
| 3538 | (ses-file-format-extend-paramter-list 3) | ||
| 3539 | (ses-set-parameter 'ses--numlocprn (+ ses--numlocprn create-printer))) ))))) ) | ||
| 3540 | |||
| 3541 | |||
| 3346 | ;;---------------------------------------------------------------------------- | 3542 | ;;---------------------------------------------------------------------------- |
| 3347 | ;; Checking formulas for safety | 3543 | ;; Checking formulas for safety |
| 3348 | ;;---------------------------------------------------------------------------- | 3544 | ;;---------------------------------------------------------------------------- |
| @@ -3352,6 +3548,7 @@ highlighted range in the spreadsheet." | |||
| 3352 | (if (or (stringp printer) | 3548 | (if (or (stringp printer) |
| 3353 | (stringp (car-safe printer)) | 3549 | (stringp (car-safe printer)) |
| 3354 | (not printer) | 3550 | (not printer) |
| 3551 | (and (symbolp printer) (gethash printer ses--local-printer-hashmap)) | ||
| 3355 | (ses-warn-unsafe printer 'unsafep-function)) | 3552 | (ses-warn-unsafe printer 'unsafep-function)) |
| 3356 | printer | 3553 | printer |
| 3357 | 'ses-unsafe)) | 3554 | 'ses-unsafe)) |