Mercurial > emacs
view src/chartab.c @ 104810:86b7fe7d1d8f
2009-09-02 Carsten Dominik <carsten.dominik@gmail.com>
* org-protocol.el (org-protocol-store-link)
(org-protocol-remember, org-protocol-open-source): Add autoloads.
* org-compat.el (org-float-time): New function.
* org.el (org-clock-update-time-maybe)
(org-sort-entries-or-items, org-do-sort)
(org-evaluate-time-range, org-time-string-to-seconds)
(org-closed-in-range): Use `org-float-time'.
* org-timer.el (org-timer-start, org-timer-pause-or-continue)
(org-timer-seconds): Use `org-float-time'.
* org-clock.el (org-clock-get-clocked-time, org-clock-out)
(org-clock-sum, org-dblock-write:clocktable)
(org-clocktable-steps): Use `org-float-time'.
* org-agenda.el (org-agenda-last-marker-time)
(org-agenda-new-marker, org-diary): Use `org-float-time'.
* org-compat.el (w32-focus-frame): Declare the w32-focus-frame
function.
* org-exp.el (org-get-file-contents): Only protect lines that
really need it.
* org-html.el (require): Require cl for compilation.
* org.el: Avoid using `default-major-mode'.
* org-plot.el (require): Require CL only at compile time.
* org-exp.el (require): Require CL only at compile time.
* org-agenda.el (org-agenda-quit): When the agenda window is
dedicated, remove other windows before exiting, so that the frame
really will be killed.
* org-exp.el (org-export-handle-include-files): Reset START and
END for each loop cycle.
2009-09-02 Carsten Dominik <carsten.dominik@gmail.com>
* org.el (org-eval-in-calendar): Use
`org-select-frame-set-input-focus'.
* org-compat.el (org-select-frame-set-input-focus): New function.
* org.el (org-update-statistics-cookies): New function.
(org-mode-map): Bind `C-c #' to `org-update-statistics-cookies'.
2009-09-02 Carsten Dominik <carsten.dominik@gmail.com>
* org-src.el (org-edit-fixed-width-region): Set org-src-mode only
after the local variables are set.
* org-latex.el (org-export-latex-protect-amp): New function.
(org-export-latex-links): Protect link ampersands in tables.
* org-exp.el (org-export-select-backend-specific-text): Match in
two steps, to avoid regexp problems.
* org.el (org-offer-links-in-entry): Improve working with many and
duplicate links.
* org-agenda.el (org-agenda-show-1): Make more consistent with
normal cycling.
(org-agenda-cycle-show): Make more consistent with normal cycling.
* org-gnus.el (org-gnus-store-link): Restore the linking to a
website.
2009-09-02 Bastien Guerry <bzg@altern.org>
* org-latex.el (org-export-latex-first-lines): Bugfix.
2009-09-02 Carsten Dominik <carsten.dominik@gmail.com>
* org-clock.el (org-clock-modify-effort-estimate): Emit message
about new effort.
* org.el (org-set-effort): New function.
(org-mode-map): New key for effort setting command.
* org-agenda.el (org-agenda): Keep window setup when calling
agenda from within agenda window.
(org-agenda-mode-map): New keys for effort setting commands.
(org-agenda-menu): Add effort setting commands to menu.
(org-agenda-set-property, org-agenda-set-effort): New functions.
* org-latex.el (org-export-latex-tables): Fix
`org-table-last-alignment' and `org-table-last-column-widths' if
the first column has been removed.
2009-09-02 Carsten Dominik <carsten.dominik@gmail.com>
* org.el (org-remove-timestamp-with-keyword): Only remove in
entry, not in subtree.
* org-src.el (org-src-lang-modes): Add abbreviation elisp for
emacs lisp.
* org.el (org-open-at-point): When on headline, offer all strings
in entry.
* org-remember.el (org-remember-templates): Documentation fix.
* org.el (org-move-subtree-down): Use `org-get-next-sibling' and
`org-get-last-sibling' instead of the outline versions of these
functions.
(org-get-last-sibling): New function.
(org-refile): Use `org-get-next-sibling' instead of the outline
version of this function.
(org-clean-visibility-after-subtree-move): Use
`org-get-next-sibling' and `org-get-last-sibling' instead of the
outline versions of these functions.
2009-09-02 Carsten Dominik <carsten.dominik@gmail.com>
* org-agenda.el (org-prepare-agenda): When creating a new frame
for the agenda, make the window dedicated.
* org-agenda.el (org-agenda-mode-map): New keys for time motion.
* org-table.el (org-table-align): Change the order of reinsertion
and deletion, to avoid problems with overlays following the table.
* org.el (org-parse-time-string): Better error message.
(org-show-subtree): Use org-end-of-subtree.
* org-macs.el (org-goto-line): New defsubst.
* org.el (org-open-file, org-change-tag-in-region)
(org-fast-tag-show-exit): Don't use `goto-line'.
* org-table.el (org-table-align, org-table-insert-column)
(org-table-delete-column, org-table-move-column)
(org-table-sort-lines, org-table-copy-region)
(org-table-paste-rectangle, org-table-wrap-region)
(org-table-get-specials, org-table-rotate-recalc-marks)
(org-table-get-range, org-table-recalculate)
(org-table-edit-formulas, org-table-fedit-convert-buffer)
(org-table-show-reference, org-table-highlight-rectangle): Don't
use `goto-line'.
* org-src.el (org-edit-src-code, org-edit-fixed-width-region)
(org-edit-src-exit): Don't use `goto-line'.
* org-macs.el (org-preserve-lc): Don't use `goto-line'.
* org-list.el (org-renumber-ordered-list, org-fix-bullet-type):
Don't use `goto-line'.
* org-exp.el (org-export-number-lines): Don't use `goto-line'.
* org-colview.el (org-columns, org-columns-redo)
(org-agenda-columns): Don't use `goto-line'.
* org-colview-xemacs.el (org-columns, org-agenda-columns): Don't
use `goto-line'.
* org-agenda.el (org-agenda-mode): Force visual line motion off.
(org-agenda-add-entry-text-maxlines): Improve docstring.
(org-agenda-start-with-entry-text-mode): New option.
(org-agenda-entry-text-maxlines): New option.
(org-agenda-entry-text-mode): New variable.
(org-agenda-mode): Set initial value of
`org-agenda-entry-text-mode'.
(org-agenda-mode-map): Add the `E' key.
(org-agenda-menu): Add entry text mode to the menu.
(org-agenda-get-some-entry-text): Fix line count bug.
(org-finalize-agenda): Apply entry text mode if appropriate.
(org-agenda-entry-text-show-here): New function.
(org-agenda-entry-text-show): New function.
(org-agenda-entry-text-hide): New function.
(org-agenda-view-mode-dispatch): Add entry text mode to the view
key menu.
(org-agenda-entry-text-mode): New command.
(org-agenda-set-mode-name): Add entry text mode to the mode line
string.
(org-agenda-undo, org-agenda-get-restriction-and-command)
(org-agenda-get-some-entry-text, org-agenda-redo): Don't use
`goto-line'.
2009-09-02 Bernt Hansen <bernt@norang.ca>
* org-clock.el (org-notify): Bugfix.
2009-09-02 Carsten Dominik <carsten.dominik@gmail.com>
* org-agenda.el (org-agenda-open-link): Handle multiple links and
check for after-string.
* org-gnus.el (org-gnus-store-link): Simplify.
* org.el (org-latex-regexps): Don't add extra empty lines for
display formulas.
2009-09-02 Carsten Dominik <carsten.dominik@gmail.com>
* org-agenda.el (org-agenda-get-some-entry-text): New function.
(org-agenda-add-entry-text): Use
`org-agenda-get-some-entry-text'.
* org.el (org-cycle-separator-lines): Update docstring.
(org-cycle-show-empty-lines): Handle negative values for
`org-cycle-show-empty-lines'.
* org-exp.el (org-export-protect-sub-super): New function.
(org-export-normalize-links): Protect the url of plain links from
supscript and superscript processing.
* org-remember.el (org-remember-escaped-%): New function.
(org-remember-apply-template): Use `org-remember-escaped-%' to
detect escaped % signs.
2009-09-02 Bastien Guerry <bzg@altern.org>
* org-timer.el (org-timer-set-timer): Use `org-notify' and play a
sound when showing the notification.
* org-clock.el (org-notify): New function.
(org-clock-notify-once-if-expired): Use `org-notify'.
* org-gnus.el (org-gnus-store-link): Handle `gnus-summary-mode'
and `gnus-article-mode' separately.
(gnus-summary-article-header): Fix the declare-function.
2009-09-02 Carsten Dominik <carsten.dominik@gmail.com>
* org-exp.el (org-export-format-source-code-or-example): Translate
language.
* org-src.el (org-src-lang-modes): New variable
(org-edit-src-code): Translate language.
* org-exp.el (org-export-format-source-code-or-example): Deal wit
the new structure of the `org-export-latex-listings-langs'
variable.
* org-latex.el (org-export-latex-listings-langs): Change structure
of the variable from plist to alist.
2009-09-02 Carsten Dominik <carsten.dominik@gmail.com>
* org.el (org-in-commented-line): New function.
2009-09-02 Carsten Dominik <carsten.dominik@gmail.com>
* org.el (org-hide-block-toggle): Make folded blocks searchable.
2009-09-02 Friedrich Delgado Friedrichs <friedel@nomaden.org> (tiny change)
* org.el (org-flag-drawer): More useful error.
2009-09-02 Carsten Dominik <carsten.dominik@gmail.com>
* org-remember.el (org-remember-apply-template): Use
org-icompleting-read.
* org-publish.el (org-publish): Use org-icompleting-read.
* org-colview.el (org-columns-edit-value, org-columns-new)
(org-insert-columns-dblock): Use org-icompleting-read.
* org-colview-xemacs.el (org-columns-edit-value)
(org-columns-new, org-insert-columns-dblock): Use
org-icompleting-read.
* org-attach.el (org-attach-delete-one, org-attach-open): Use
org-icompleting-read.
2009-09-02 Carsten Dominik <carsten.dominik@gmail.com>
* org.el (org-hierarchical-todo-statistics): Improve docstring.
(org-version): Return the version text.
(org-org-menu): Add a menu entry for the new bug reporter.
(org-submit-bug-report): New command.
* org-list.el (org-hierarchical-checkbox-statistics): Improve
docstring.
* org.el (org-emphasis-regexp-components): Add "`" to set of
pre-emphasis characters.
* org-latex.el (org-export-latex-classes): Always include the soul
package.
(org-export-latex-emphasis-alist): Use \st for strikethough.
* org-exp-blocks.el (org-export-blocks-preprocess): Use
`indent-code-rigidly' to indent.
* org-agenda.el (org-agenda-get-restriction-and-command): Remove
properties only if MATCH really is a string.
2009-09-02 Carsten Dominik <carsten.dominik@gmail.com>
* org-latex.el (org-export-latex-packages-alist): Fix
customization type.
* org.el (org-create-formula-image): Also use
`org-export-latex-packages-alist'.
* org-html.el (org-export-as-html): Fix bug in footnote regexp.
(org-export-as-html): Format footnotes correctly.
2009-09-02 Carsten Dominik <carsten.dominik@gmail.com>
* org.el (org-fast-tag-selection): Avoid text properties on tags
in the alist.
* org-agenda.el (org-agenda-get-restriction-and-command): Avoid
text properties on the match element.
2009-09-02 Carsten Dominik <carsten.dominik@gmail.com>
* org.el (org-set-regexps-and-options): Make sure the list of done
keywords is not invalid.
* org-exp.el (org-export-interpolate-newlines): New function.
2009-09-02 Carsten Dominik <carsten.dominik@gmail.com>
* org.el (org-format-latex): Avoid nested overlays.
* org-latex.el (org-export-latex-listings-langs): Add a few more
languages.
* org-exp.el (org-export-preprocess-apply-macros): Make sure to
ignore newlines and space before the first macro argument.
* org-latex.el (org-export-latex-tables): Remove save-excursion
around `org-table-align'.
2009-09-02 Carsten Dominik <carsten.dominik@gmail.com>
* org.el (org-export-html-special-string-regexps): Definition
moved into org.el
* org-exp.el (org-export-preprocess-apply-macros): Allow newlines
in macro calls.
2009-09-02 Carsten Dominik <carsten.dominik@gmail.com>
* org-latex.el (org-export-latex-listings)
(org-export-latex-listings-langs): New options.
* org-exp.el (org-export-format-source-code-or-example): Use
listing package if requested by the user.
2009-09-02 Bastien Guerry <bzg@altern.org>
* org.el (org-iswitchb): Fix bug when aborting the `org-iswitchb'
command before actually switching to a buffer.
2009-09-02 Carsten Dominik <carsten.dominik@gmail.com>
* org-exp.el (org-get-file-contents): Only quote org lines when
the markup is src or example.
* org-agenda.el (org-agenda-skip-scheduled-if-deadline-is-shown):
New option
(org-agenda-get-day-entries): Remember deadline results and pass
them on into the function getting the scheduling information.
(org-agenda-get-scheduled): Accept deadline results as parameters
and maybe skip some entries.
(org-agenda-skip-scheduled-if-deadline-is-shown): New option.
* org.el (org-insert-heading): When respecting content, do not
convert current line to headline.
* org-clock.el (org-clock-save-markers-for-cut-and-paste): Also
cheeeeeck the hd marker
(org-clock-in): Also set the hd marker.
(org-clock-out): Also set the hd marker.
(org-clock-cancel): Reset markers.
* org.el (org-clock-hd-marker): New marker.
* org-faces.el (org-agenda-clocking): New face.
* org-agenda.el (org-agenda-mark-clocking-task): New function.
(org-finalize-agenda): call `org-agenda-mark-clocking-task'.
* org.el (org-modules): Add org-track.el.
* org-agenda.el (org-agenda-bulk-marked-p): New function.
(org-agenda-bulk-mark, org-agenda-bulk-unmark): Use
`org-agenda-bulk-marked-p'.
(org-agenda-bulk-toggle): New command.
2009-09-02 Carsten Dominik <carsten.dominik@gmail.com>
* org.el (org-move-subtree-down): Hide subtree if it was folded,
not just the body.
* org-remember.el (org-remember-finalize): Avoid buffer-modified
messages.
author | Carsten Dominik <dominik@science.uva.nl> |
---|---|
date | Wed, 02 Sep 2009 12:59:52 +0000 |
parents | 65728b0073ee |
children | 68dd71358159 |
line wrap: on
line source
/* chartab.c -- char-table support Copyright (C) 2003, 2004, 2005, 2006, 2007, 2008, 2009 National Institute of Advanced Industrial Science and Technology (AIST) Registration Number H13PRO009 This file is part of GNU Emacs. GNU Emacs is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. GNU Emacs is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>. */ #include <config.h> #include "lisp.h" #include "character.h" #include "charset.h" #include "ccl.h" /* 64/16/32/128 */ /* Number of elements in Nth level char-table. */ const int chartab_size[4] = { (1 << CHARTAB_SIZE_BITS_0), (1 << CHARTAB_SIZE_BITS_1), (1 << CHARTAB_SIZE_BITS_2), (1 << CHARTAB_SIZE_BITS_3) }; /* Number of characters each element of Nth level char-table covers. */ const int chartab_chars[4] = { (1 << (CHARTAB_SIZE_BITS_1 + CHARTAB_SIZE_BITS_2 + CHARTAB_SIZE_BITS_3)), (1 << (CHARTAB_SIZE_BITS_2 + CHARTAB_SIZE_BITS_3)), (1 << CHARTAB_SIZE_BITS_3), 1 }; /* Number of characters (in bits) each element of Nth level char-table covers. */ const int chartab_bits[4] = { (CHARTAB_SIZE_BITS_1 + CHARTAB_SIZE_BITS_2 + CHARTAB_SIZE_BITS_3), (CHARTAB_SIZE_BITS_2 + CHARTAB_SIZE_BITS_3), CHARTAB_SIZE_BITS_3, 0 }; #define CHARTAB_IDX(c, depth, min_char) \ (((c) - (min_char)) >> chartab_bits[(depth)]) DEFUN ("make-char-table", Fmake_char_table, Smake_char_table, 1, 2, 0, doc: /* Return a newly created char-table, with purpose PURPOSE. Each element is initialized to INIT, which defaults to nil. PURPOSE should be a symbol. If it has a `char-table-extra-slots' property, the property's value should be an integer between 0 and 10 that specifies how many extra slots the char-table has. Otherwise, the char-table has no extra slot. */) (purpose, init) register Lisp_Object purpose, init; { Lisp_Object vector; Lisp_Object n; int n_extras; int size; CHECK_SYMBOL (purpose); n = Fget (purpose, Qchar_table_extra_slots); if (NILP (n)) n_extras = 0; else { CHECK_NATNUM (n); n_extras = XINT (n); if (n_extras > 10) args_out_of_range (n, Qnil); } size = VECSIZE (struct Lisp_Char_Table) - 1 + n_extras; vector = Fmake_vector (make_number (size), init); XSETPVECTYPE (XVECTOR (vector), PVEC_CHAR_TABLE); XCHAR_TABLE (vector)->parent = Qnil; XCHAR_TABLE (vector)->purpose = purpose; XSETCHAR_TABLE (vector, XCHAR_TABLE (vector)); return vector; } static Lisp_Object make_sub_char_table (depth, min_char, defalt) int depth, min_char; Lisp_Object defalt; { Lisp_Object table; int size = VECSIZE (struct Lisp_Sub_Char_Table) - 1 + chartab_size[depth]; table = Fmake_vector (make_number (size), defalt); XSETPVECTYPE (XVECTOR (table), PVEC_SUB_CHAR_TABLE); XSUB_CHAR_TABLE (table)->depth = make_number (depth); XSUB_CHAR_TABLE (table)->min_char = make_number (min_char); return table; } static Lisp_Object char_table_ascii (table) Lisp_Object table; { Lisp_Object sub; sub = XCHAR_TABLE (table)->contents[0]; if (! SUB_CHAR_TABLE_P (sub)) return sub; sub = XSUB_CHAR_TABLE (sub)->contents[0]; if (! SUB_CHAR_TABLE_P (sub)) return sub; return XSUB_CHAR_TABLE (sub)->contents[0]; } Lisp_Object copy_sub_char_table (table) Lisp_Object table; { Lisp_Object copy; int depth = XINT (XSUB_CHAR_TABLE (table)->depth); int min_char = XINT (XSUB_CHAR_TABLE (table)->min_char); Lisp_Object val; int i; copy = make_sub_char_table (depth, min_char, Qnil); /* Recursively copy any sub char-tables. */ for (i = 0; i < chartab_size[depth]; i++) { val = XSUB_CHAR_TABLE (table)->contents[i]; if (SUB_CHAR_TABLE_P (val)) XSUB_CHAR_TABLE (copy)->contents[i] = copy_sub_char_table (val); else XSUB_CHAR_TABLE (copy)->contents[i] = val; } return copy; } Lisp_Object copy_char_table (table) Lisp_Object table; { Lisp_Object copy; int size = XCHAR_TABLE (table)->size & PSEUDOVECTOR_SIZE_MASK; int i; copy = Fmake_vector (make_number (size), Qnil); XSETPVECTYPE (XVECTOR (copy), PVEC_CHAR_TABLE); XCHAR_TABLE (copy)->defalt = XCHAR_TABLE (table)->defalt; XCHAR_TABLE (copy)->parent = XCHAR_TABLE (table)->parent; XCHAR_TABLE (copy)->purpose = XCHAR_TABLE (table)->purpose; for (i = 0; i < chartab_size[0]; i++) XCHAR_TABLE (copy)->contents[i] = (SUB_CHAR_TABLE_P (XCHAR_TABLE (table)->contents[i]) ? copy_sub_char_table (XCHAR_TABLE (table)->contents[i]) : XCHAR_TABLE (table)->contents[i]); XCHAR_TABLE (copy)->ascii = char_table_ascii (copy); size -= VECSIZE (struct Lisp_Char_Table) - 1; for (i = 0; i < size; i++) XCHAR_TABLE (copy)->extras[i] = XCHAR_TABLE (table)->extras[i]; XSETCHAR_TABLE (copy, XCHAR_TABLE (copy)); return copy; } Lisp_Object sub_char_table_ref (table, c) Lisp_Object table; int c; { struct Lisp_Sub_Char_Table *tbl = XSUB_CHAR_TABLE (table); int depth = XINT (tbl->depth); int min_char = XINT (tbl->min_char); Lisp_Object val; val = tbl->contents[CHARTAB_IDX (c, depth, min_char)]; if (SUB_CHAR_TABLE_P (val)) val = sub_char_table_ref (val, c); return val; } Lisp_Object char_table_ref (table, c) Lisp_Object table; int c; { struct Lisp_Char_Table *tbl = XCHAR_TABLE (table); Lisp_Object val; if (ASCII_CHAR_P (c)) { val = tbl->ascii; if (SUB_CHAR_TABLE_P (val)) val = XSUB_CHAR_TABLE (val)->contents[c]; } else { val = tbl->contents[CHARTAB_IDX (c, 0, 0)]; if (SUB_CHAR_TABLE_P (val)) val = sub_char_table_ref (val, c); } if (NILP (val)) { val = tbl->defalt; if (NILP (val) && CHAR_TABLE_P (tbl->parent)) val = char_table_ref (tbl->parent, c); } return val; } static Lisp_Object sub_char_table_ref_and_range (table, c, from, to, defalt) Lisp_Object table; int c; int *from, *to; Lisp_Object defalt; { struct Lisp_Sub_Char_Table *tbl = XSUB_CHAR_TABLE (table); int depth = XINT (tbl->depth); int min_char = XINT (tbl->min_char); int max_char = min_char + chartab_chars[depth - 1] - 1; int index = CHARTAB_IDX (c, depth, min_char), idx; Lisp_Object val; val = tbl->contents[index]; if (SUB_CHAR_TABLE_P (val)) val = sub_char_table_ref_and_range (val, c, from, to, defalt); else if (NILP (val)) val = defalt; idx = index; while (idx > 0 && *from < min_char + idx * chartab_chars[depth]) { Lisp_Object this_val; c = min_char + idx * chartab_chars[depth] - 1; idx--; this_val = tbl->contents[idx]; if (SUB_CHAR_TABLE_P (this_val)) this_val = sub_char_table_ref_and_range (this_val, c, from, to, defalt); else if (NILP (this_val)) this_val = defalt; if (! EQ (this_val, val)) { *from = c + 1; break; } } while ((c = min_char + (index + 1) * chartab_chars[depth]) <= max_char && *to >= c) { Lisp_Object this_val; index++; this_val = tbl->contents[index]; if (SUB_CHAR_TABLE_P (this_val)) this_val = sub_char_table_ref_and_range (this_val, c, from, to, defalt); else if (NILP (this_val)) this_val = defalt; if (! EQ (this_val, val)) { *to = c - 1; break; } } return val; } /* Return the value for C in char-table TABLE. Shrink the range *FROM and *TO to cover characters (containing C) that have the same value as C. It is not assured that the values of (*FROM - 1) and (*TO + 1) are different from that of C. */ Lisp_Object char_table_ref_and_range (table, c, from, to) Lisp_Object table; int c; int *from, *to; { struct Lisp_Char_Table *tbl = XCHAR_TABLE (table); int index = CHARTAB_IDX (c, 0, 0), idx; Lisp_Object val; val = tbl->contents[index]; if (*from < 0) *from = 0; if (*to < 0) *to = MAX_CHAR; if (SUB_CHAR_TABLE_P (val)) val = sub_char_table_ref_and_range (val, c, from, to, tbl->defalt); else if (NILP (val)) val = tbl->defalt; idx = index; while (*from < idx * chartab_chars[0]) { Lisp_Object this_val; c = idx * chartab_chars[0] - 1; idx--; this_val = tbl->contents[idx]; if (SUB_CHAR_TABLE_P (this_val)) this_val = sub_char_table_ref_and_range (this_val, c, from, to, tbl->defalt); else if (NILP (this_val)) this_val = tbl->defalt; if (! EQ (this_val, val)) { *from = c + 1; break; } } while (*to >= (index + 1) * chartab_chars[0]) { Lisp_Object this_val; index++; c = index * chartab_chars[0]; this_val = tbl->contents[index]; if (SUB_CHAR_TABLE_P (this_val)) this_val = sub_char_table_ref_and_range (this_val, c, from, to, tbl->defalt); else if (NILP (this_val)) this_val = tbl->defalt; if (! EQ (this_val, val)) { *to = c - 1; break; } } return val; } #define ASET_RANGE(ARRAY, FROM, TO, LIMIT, VAL) \ do { \ int limit = (TO) < (LIMIT) ? (TO) : (LIMIT); \ for (; (FROM) < limit; (FROM)++) (ARRAY)->contents[(FROM)] = (VAL); \ } while (0) #define GET_SUB_CHAR_TABLE(TABLE, SUBTABLE, IDX, DEPTH, MIN_CHAR) \ do { \ (SUBTABLE) = (TABLE)->contents[(IDX)]; \ if (!SUB_CHAR_TABLE_P (SUBTABLE)) \ (SUBTABLE) = make_sub_char_table ((DEPTH), (MIN_CHAR), (SUBTABLE)); \ } while (0) static void sub_char_table_set (table, c, val) Lisp_Object table; int c; Lisp_Object val; { struct Lisp_Sub_Char_Table *tbl = XSUB_CHAR_TABLE (table); int depth = XINT ((tbl)->depth); int min_char = XINT ((tbl)->min_char); int i = CHARTAB_IDX (c, depth, min_char); Lisp_Object sub; if (depth == 3) tbl->contents[i] = val; else { sub = tbl->contents[i]; if (! SUB_CHAR_TABLE_P (sub)) { sub = make_sub_char_table (depth + 1, min_char + i * chartab_chars[depth], sub); tbl->contents[i] = sub; } sub_char_table_set (sub, c, val); } } Lisp_Object char_table_set (table, c, val) Lisp_Object table; int c; Lisp_Object val; { struct Lisp_Char_Table *tbl = XCHAR_TABLE (table); if (ASCII_CHAR_P (c) && SUB_CHAR_TABLE_P (tbl->ascii)) { XSUB_CHAR_TABLE (tbl->ascii)->contents[c] = val; } else { int i = CHARTAB_IDX (c, 0, 0); Lisp_Object sub; sub = tbl->contents[i]; if (! SUB_CHAR_TABLE_P (sub)) { sub = make_sub_char_table (1, i * chartab_chars[0], sub); tbl->contents[i] = sub; } sub_char_table_set (sub, c, val); if (ASCII_CHAR_P (c)) tbl->ascii = char_table_ascii (table); } return val; } static void sub_char_table_set_range (table, depth, min_char, from, to, val) Lisp_Object *table; int depth; int min_char; int from, to; Lisp_Object val; { int max_char = min_char + chartab_chars[depth] - 1; if (depth == 3 || (from <= min_char && to >= max_char)) *table = val; else { int i, j; depth++; if (! SUB_CHAR_TABLE_P (*table)) *table = make_sub_char_table (depth, min_char, *table); if (from < min_char) from = min_char; if (to > max_char) to = max_char; i = CHARTAB_IDX (from, depth, min_char); j = CHARTAB_IDX (to, depth, min_char); min_char += chartab_chars[depth] * i; for (; i <= j; i++, min_char += chartab_chars[depth]) sub_char_table_set_range (XSUB_CHAR_TABLE (*table)->contents + i, depth, min_char, from, to, val); } } Lisp_Object char_table_set_range (table, from, to, val) Lisp_Object table; int from, to; Lisp_Object val; { struct Lisp_Char_Table *tbl = XCHAR_TABLE (table); Lisp_Object *contents = tbl->contents; int i, min_char; if (from == to) char_table_set (table, from, val); else { for (i = CHARTAB_IDX (from, 0, 0), min_char = i * chartab_chars[0]; min_char <= to; i++, min_char += chartab_chars[0]) sub_char_table_set_range (contents + i, 0, min_char, from, to, val); if (ASCII_CHAR_P (from)) tbl->ascii = char_table_ascii (table); } return val; } DEFUN ("char-table-subtype", Fchar_table_subtype, Schar_table_subtype, 1, 1, 0, doc: /* Return the subtype of char-table CHAR-TABLE. The value is a symbol. */) (char_table) Lisp_Object char_table; { CHECK_CHAR_TABLE (char_table); return XCHAR_TABLE (char_table)->purpose; } DEFUN ("char-table-parent", Fchar_table_parent, Schar_table_parent, 1, 1, 0, doc: /* Return the parent char-table of CHAR-TABLE. The value is either nil or another char-table. If CHAR-TABLE holds nil for a given character, then the actual applicable value is inherited from the parent char-table \(or from its parents, if necessary). */) (char_table) Lisp_Object char_table; { CHECK_CHAR_TABLE (char_table); return XCHAR_TABLE (char_table)->parent; } DEFUN ("set-char-table-parent", Fset_char_table_parent, Sset_char_table_parent, 2, 2, 0, doc: /* Set the parent char-table of CHAR-TABLE to PARENT. Return PARENT. PARENT must be either nil or another char-table. */) (char_table, parent) Lisp_Object char_table, parent; { Lisp_Object temp; CHECK_CHAR_TABLE (char_table); if (!NILP (parent)) { CHECK_CHAR_TABLE (parent); for (temp = parent; !NILP (temp); temp = XCHAR_TABLE (temp)->parent) if (EQ (temp, char_table)) error ("Attempt to make a chartable be its own parent"); } XCHAR_TABLE (char_table)->parent = parent; return parent; } DEFUN ("char-table-extra-slot", Fchar_table_extra_slot, Schar_table_extra_slot, 2, 2, 0, doc: /* Return the value of CHAR-TABLE's extra-slot number N. */) (char_table, n) Lisp_Object char_table, n; { CHECK_CHAR_TABLE (char_table); CHECK_NUMBER (n); if (XINT (n) < 0 || XINT (n) >= CHAR_TABLE_EXTRA_SLOTS (XCHAR_TABLE (char_table))) args_out_of_range (char_table, n); return XCHAR_TABLE (char_table)->extras[XINT (n)]; } DEFUN ("set-char-table-extra-slot", Fset_char_table_extra_slot, Sset_char_table_extra_slot, 3, 3, 0, doc: /* Set CHAR-TABLE's extra-slot number N to VALUE. */) (char_table, n, value) Lisp_Object char_table, n, value; { CHECK_CHAR_TABLE (char_table); CHECK_NUMBER (n); if (XINT (n) < 0 || XINT (n) >= CHAR_TABLE_EXTRA_SLOTS (XCHAR_TABLE (char_table))) args_out_of_range (char_table, n); return XCHAR_TABLE (char_table)->extras[XINT (n)] = value; } DEFUN ("char-table-range", Fchar_table_range, Schar_table_range, 2, 2, 0, doc: /* Return the value in CHAR-TABLE for a range of characters RANGE. RANGE should be nil (for the default value), a cons of character codes (for characters in the range), or a character code. */) (char_table, range) Lisp_Object char_table, range; { Lisp_Object val; CHECK_CHAR_TABLE (char_table); if (EQ (range, Qnil)) val = XCHAR_TABLE (char_table)->defalt; else if (INTEGERP (range)) val = CHAR_TABLE_REF (char_table, XINT (range)); else if (CONSP (range)) { int from, to; CHECK_CHARACTER_CAR (range); CHECK_CHARACTER_CDR (range); val = char_table_ref_and_range (char_table, XINT (XCAR (range)), &from, &to); /* Not yet implemented. */ } else error ("Invalid RANGE argument to `char-table-range'"); return val; } DEFUN ("set-char-table-range", Fset_char_table_range, Sset_char_table_range, 3, 3, 0, doc: /* Set the value in CHAR-TABLE for a range of characters RANGE to VALUE. RANGE should be t (for all characters), nil (for the default value), a cons of character codes (for characters in the range), or a character code. Return VALUE. */) (char_table, range, value) Lisp_Object char_table, range, value; { CHECK_CHAR_TABLE (char_table); if (EQ (range, Qt)) { int i; XCHAR_TABLE (char_table)->ascii = value; for (i = 0; i < chartab_size[0]; i++) XCHAR_TABLE (char_table)->contents[i] = value; } else if (EQ (range, Qnil)) XCHAR_TABLE (char_table)->defalt = value; else if (INTEGERP (range)) char_table_set (char_table, XINT (range), value); else if (CONSP (range)) { CHECK_CHARACTER_CAR (range); CHECK_CHARACTER_CDR (range); char_table_set_range (char_table, XINT (XCAR (range)), XINT (XCDR (range)), value); } else error ("Invalid RANGE argument to `set-char-table-range'"); return value; } DEFUN ("set-char-table-default", Fset_char_table_default, Sset_char_table_default, 3, 3, 0, doc: /* This function is obsolete and has no effect. */) (char_table, ch, value) Lisp_Object char_table, ch, value; { return Qnil; } /* Look up the element in TABLE at index CH, and return it as an integer. If the element is not a character, return CH itself. */ int char_table_translate (table, ch) Lisp_Object table; int ch; { Lisp_Object value; value = Faref (table, make_number (ch)); if (! CHARACTERP (value)) return ch; return XINT (value); } static Lisp_Object optimize_sub_char_table (table, test) Lisp_Object table, test; { struct Lisp_Sub_Char_Table *tbl = XSUB_CHAR_TABLE (table); int depth = XINT (tbl->depth); Lisp_Object elt, this; int i, optimizable; elt = XSUB_CHAR_TABLE (table)->contents[0]; if (SUB_CHAR_TABLE_P (elt)) elt = XSUB_CHAR_TABLE (table)->contents[0] = optimize_sub_char_table (elt, test); optimizable = SUB_CHAR_TABLE_P (elt) ? 0 : 1; for (i = 1; i < chartab_size[depth]; i++) { this = XSUB_CHAR_TABLE (table)->contents[i]; if (SUB_CHAR_TABLE_P (this)) this = XSUB_CHAR_TABLE (table)->contents[i] = optimize_sub_char_table (this, test); if (optimizable && (NILP (test) ? NILP (Fequal (this, elt)) /* defaults to `equal'. */ : EQ (test, Qeq) ? !EQ (this, elt) /* Optimize `eq' case. */ : NILP (call2 (test, this, elt)))) optimizable = 0; } return (optimizable ? elt : table); } DEFUN ("optimize-char-table", Foptimize_char_table, Soptimize_char_table, 1, 2, 0, doc: /* Optimize CHAR-TABLE. TEST is the comparison function used to decide whether two entries are equivalent and can be merged. It defaults to `equal'. */) (char_table, test) Lisp_Object char_table, test; { Lisp_Object elt; int i; CHECK_CHAR_TABLE (char_table); for (i = 0; i < chartab_size[0]; i++) { elt = XCHAR_TABLE (char_table)->contents[i]; if (SUB_CHAR_TABLE_P (elt)) XCHAR_TABLE (char_table)->contents[i] = optimize_sub_char_table (elt, test); } /* Reset the `ascii' cache, in case it got optimized away. */ XCHAR_TABLE (char_table)->ascii = char_table_ascii (char_table); return Qnil; } /* Map C_FUNCTION or FUNCTION over TABLE (top or sub char-table), calling it for each character or group of characters that share a value. RANGE is a cons (FROM . TO) specifying the range of target characters, VAL is a value of FROM in TABLE, DEFAULT_VAL is the default value of the char-table, PARENT is the parent of the char-table. ARG is passed to C_FUNCTION when that is called. It returns the value of last character covered by TABLE (not the value inheritted from the parent), and by side-effect, the car part of RANGE is updated to the minimum character C where C and all the following characters in TABLE have the same value. */ static Lisp_Object map_sub_char_table (c_function, function, table, arg, val, range, default_val, parent) void (*c_function) P_ ((Lisp_Object, Lisp_Object, Lisp_Object)); Lisp_Object function, table, arg, val, range, default_val, parent; { /* Pointer to the elements of TABLE. */ Lisp_Object *contents; /* Depth of TABLE. */ int depth; /* Minimum and maxinum characters covered by TABLE. */ int min_char, max_char; /* Number of characters covered by one element of TABLE. */ int chars_in_block; int from = XINT (XCAR (range)), to = XINT (XCDR (range)); int i, c; if (SUB_CHAR_TABLE_P (table)) { struct Lisp_Sub_Char_Table *tbl = XSUB_CHAR_TABLE (table); depth = XINT (tbl->depth); contents = tbl->contents; min_char = XINT (tbl->min_char); max_char = min_char + chartab_chars[depth - 1] - 1; } else { depth = 0; contents = XCHAR_TABLE (table)->contents; min_char = 0; max_char = MAX_CHAR; } chars_in_block = chartab_chars[depth]; if (to < max_char) max_char = to; /* Set I to the index of the first element to check. */ if (from <= min_char) i = 0; else i = (from - min_char) / chars_in_block; for (c = min_char + chars_in_block * i; c <= max_char; i++, c += chars_in_block) { Lisp_Object this = contents[i]; int nextc = c + chars_in_block; if (SUB_CHAR_TABLE_P (this)) { if (to >= nextc) XSETCDR (range, make_number (nextc - 1)); val = map_sub_char_table (c_function, function, this, arg, val, range, default_val, parent); } else { if (NILP (this)) this = default_val; if (!EQ (val, this)) { int different_value = 1; if (NILP (val)) { if (! NILP (parent)) { Lisp_Object temp = XCHAR_TABLE (parent)->parent; /* This is to get a value of FROM in PARENT without checking the parent of PARENT. */ XCHAR_TABLE (parent)->parent = Qnil; val = CHAR_TABLE_REF (parent, from); XCHAR_TABLE (parent)->parent = temp; XSETCDR (range, make_number (c - 1)); val = map_sub_char_table (c_function, function, parent, arg, val, range, XCHAR_TABLE (parent)->defalt, XCHAR_TABLE (parent)->parent); if (EQ (val, this)) different_value = 0; } } if (! NILP (val) && different_value) { XSETCDR (range, make_number (c - 1)); if (EQ (XCAR (range), XCDR (range))) { if (c_function) (*c_function) (arg, XCAR (range), val); else call2 (function, XCAR (range), val); } else { if (c_function) (*c_function) (arg, range, val); else call2 (function, range, val); } } val = this; from = c; XSETCAR (range, make_number (c)); } } XSETCDR (range, make_number (to)); } return val; } /* Map C_FUNCTION or FUNCTION over TABLE, calling it for each character or group of characters that share a value. ARG is passed to C_FUNCTION when that is called. */ void map_char_table (c_function, function, table, arg) void (*c_function) P_ ((Lisp_Object, Lisp_Object, Lisp_Object)); Lisp_Object function, table, arg; { Lisp_Object range, val; struct gcpro gcpro1, gcpro2, gcpro3; range = Fcons (make_number (0), make_number (MAX_CHAR)); GCPRO3 (table, arg, range); val = XCHAR_TABLE (table)->ascii; if (SUB_CHAR_TABLE_P (val)) val = XSUB_CHAR_TABLE (val)->contents[0]; val = map_sub_char_table (c_function, function, table, arg, val, range, XCHAR_TABLE (table)->defalt, XCHAR_TABLE (table)->parent); /* If VAL is nil and TABLE has a parent, we must consult the parent recursively. */ while (NILP (val) && ! NILP (XCHAR_TABLE (table)->parent)) { Lisp_Object parent = XCHAR_TABLE (table)->parent; Lisp_Object temp = XCHAR_TABLE (parent)->parent; int from = XINT (XCAR (range)); /* This is to get a value of FROM in PARENT without checking the parent of PARENT. */ XCHAR_TABLE (parent)->parent = Qnil; val = CHAR_TABLE_REF (parent, from); XCHAR_TABLE (parent)->parent = temp; val = map_sub_char_table (c_function, function, parent, arg, val, range, XCHAR_TABLE (parent)->defalt, XCHAR_TABLE (parent)->parent); table = parent; } if (! NILP (val)) { if (EQ (XCAR (range), XCDR (range))) { if (c_function) (*c_function) (arg, XCAR (range), val); else call2 (function, XCAR (range), val); } else { if (c_function) (*c_function) (arg, range, val); else call2 (function, range, val); } } UNGCPRO; } DEFUN ("map-char-table", Fmap_char_table, Smap_char_table, 2, 2, 0, doc: /* Call FUNCTION for each character in CHAR-TABLE that has non-nil value. FUNCTION is called with two arguments--a key and a value. The key is a character code or a cons of character codes specifying a range of characters that have the same value. */) (function, char_table) Lisp_Object function, char_table; { CHECK_CHAR_TABLE (char_table); map_char_table (NULL, function, char_table, char_table); return Qnil; } static void map_sub_char_table_for_charset (c_function, function, table, arg, range, charset, from, to) void (*c_function) P_ ((Lisp_Object, Lisp_Object)); Lisp_Object function, table, arg, range; struct charset *charset; unsigned from, to; { struct Lisp_Sub_Char_Table *tbl = XSUB_CHAR_TABLE (table); int depth = XINT (tbl->depth); int c, i; if (depth < 3) for (i = 0, c = XINT (tbl->min_char); i < chartab_size[depth]; i++, c += chartab_chars[depth]) { Lisp_Object this; this = tbl->contents[i]; if (SUB_CHAR_TABLE_P (this)) map_sub_char_table_for_charset (c_function, function, this, arg, range, charset, from, to); else { if (! NILP (XCAR (range))) { XSETCDR (range, make_number (c - 1)); if (c_function) (*c_function) (arg, range); else call2 (function, range, arg); } XSETCAR (range, Qnil); } } else for (i = 0, c = XINT (tbl->min_char); i < chartab_size[depth]; i++, c ++) { Lisp_Object this; unsigned code; this = tbl->contents[i]; if (NILP (this) || (charset && (code = ENCODE_CHAR (charset, c), (code < from || code > to)))) { if (! NILP (XCAR (range))) { XSETCDR (range, make_number (c - 1)); if (c_function) (*c_function) (arg, range); else call2 (function, range, arg); XSETCAR (range, Qnil); } } else { if (NILP (XCAR (range))) XSETCAR (range, make_number (c)); } } } /* Support function for `map-charset-chars'. Map C_FUNCTION or FUNCTION over TABLE, calling it for each character or a group of succeeding characters that have non-nil value in TABLE. TABLE is a "mapping table" or a "deunifier table" of a certain charset. If CHARSET is not NULL (this is the case that `map-charset-chars' is called with non-nil FROM-CODE and TO-CODE), it is a charset who owns TABLE, and the function is called only on a character in the range FROM and TO. FROM and TO are not character codes, but code points of a character in CHARSET. This function is called in these two cases: (1) A charset has a mapping file name in :map property. (2) A charset has an upper code space in :offset property and a mapping file name in :unify-map property. In this case, this function is called only for characters in the Unicode code space. Characters in upper code space are handled directly in map_charset_chars. */ void map_char_table_for_charset (c_function, function, table, arg, charset, from, to) void (*c_function) P_ ((Lisp_Object, Lisp_Object)); Lisp_Object function, table, arg; struct charset *charset; unsigned from, to; { Lisp_Object range; int c, i; struct gcpro gcpro1; range = Fcons (Qnil, Qnil); GCPRO1 (range); for (i = 0, c = 0; i < chartab_size[0]; i++, c += chartab_chars[0]) { Lisp_Object this; this = XCHAR_TABLE (table)->contents[i]; if (SUB_CHAR_TABLE_P (this)) map_sub_char_table_for_charset (c_function, function, this, arg, range, charset, from, to); else { if (! NILP (XCAR (range))) { XSETCDR (range, make_number (c - 1)); if (c_function) (*c_function) (arg, range); else call2 (function, range, arg); } XSETCAR (range, Qnil); } } if (! NILP (XCAR (range))) { XSETCDR (range, make_number (c - 1)); if (c_function) (*c_function) (arg, range); else call2 (function, range, arg); } UNGCPRO; } void syms_of_chartab () { defsubr (&Smake_char_table); defsubr (&Schar_table_parent); defsubr (&Schar_table_subtype); defsubr (&Sset_char_table_parent); defsubr (&Schar_table_extra_slot); defsubr (&Sset_char_table_extra_slot); defsubr (&Schar_table_range); defsubr (&Sset_char_table_range); defsubr (&Sset_char_table_default); defsubr (&Soptimize_char_table); defsubr (&Smap_char_table); } /* arch-tag: 18b5b560-7ab5-4108-b09e-d5dd65dc6fda (do not change this comment) */