From c805dec0b5fa81b5c9f2b724e2ec12a17d723aca Mon Sep 17 00:00:00 2001 From: Kenichi Handa Date: Thu, 7 Jul 2011 07:43:48 +0900 Subject: [PATCH] Add C interface for Unicode character property table. --- admin/ChangeLog | 35 ++ admin/unidata/Makefile.in | 5 +- admin/unidata/unidata-gen.el | 437 ++++++++---------- lisp/ChangeLog | 36 ++ lisp/international/characters.el | 18 +- lisp/international/charprop.el | 13 +- lisp/international/mule-cmds.el | 47 +- lisp/international/uni-bidi.el | Bin 9287 -> 8719 bytes lisp/international/uni-category.el | Bin 12450 -> 11396 bytes lisp/international/uni-combining.el | Bin 8881 -> 8369 bytes lisp/international/uni-comment.el | Bin 2276 -> 2386 bytes lisp/international/uni-decimal.el | Bin 2483 -> 1869 bytes lisp/international/uni-decomposition.el | Bin 27823 -> 28459 bytes lisp/international/uni-digit.el | Bin 2790 -> 2187 bytes lisp/international/uni-lowercase.el | Bin 5387 -> 5347 bytes lisp/international/uni-mirrored.el | Bin 7904 -> 10452 bytes lisp/international/uni-name.el | Bin 157287 -> 158765 bytes lisp/international/uni-numeric.el | Bin 4258 -> 3688 bytes lisp/international/uni-old-name.el | Bin 19338 -> 19692 bytes lisp/international/uni-titlecase.el | Bin 5477 -> 5434 bytes lisp/international/uni-uppercase.el | Bin 5473 -> 5430 bytes lisp/loadup.el | 4 +- src/ChangeLog | 42 ++ src/character.h | 39 ++ src/chartab.c | 579 +++++++++++++++++++++--- src/composite.c | 5 +- src/dispextern.h | 6 +- src/font.c | 5 +- 28 files changed, 880 insertions(+), 391 deletions(-) diff --git a/admin/ChangeLog b/admin/ChangeLog index 7aaeb1d5ee2..3632a0992a6 100644 --- a/admin/ChangeLog +++ b/admin/ChangeLog @@ -1,3 +1,38 @@ +2011-07-06 Kenichi Handa + + * unidata/unidata-gen.el (unidata-dir): New variable. + (unidata-setup-list): Expand unidata-text-file in unidata-dir. + (unidata-prop-alist): INDEX element may be a function. New + optional element VAL-LIST (for general-category and bidi-class). + New entry `mirroring'. + (unidata-prop-default, unidata-prop-val-list): New subst. + (unidata-get-character, unidata-put-character): Delete them. + (unidata-gen-table-character): New arg IGNORE. Adjusted for the + above changes. + (unidata-get-symbol, unidata-get-integer, unidata-get-numeric) + (unidata-put-symbol, unidata-put-integer, unidata-put-numeric): + Delete them. + (unidata-encode-val): Assume that the first element of VAL-LIST is + a cons (nil . 0). + (unidata-gen-table): Change argument DEFAULT-VALUE to VAL-LIST. + Always store the encoded value. + (unidata-gen-table-symbol): New args DEFAULT-VALUE and VAL-LIST. + Set the 1st and the 2nd extra slots to index numbers for C + functions. + (unidata-gen-table-integer): Likewise. + (unidata-gen-table-numeric): Likewise. + (unidata-gen-table-name): New arg IGNORE. + (unidata-gen-table-decomposition): Likewise. + (unidata-describe-general-category): Add the case nil to the + description alist. + (unidata-gen-mirroring-list): New funciton. + (unidata-gen-files): New arg DATA-DIR. Adjusted for the change of + unidata-prop-alist. Handle the case of storing multiple + char-tables in a file. + + * unidata/Makefile.in (${DSTDIR}/charprop.el): New arg to + unidata-gen-files. + 2011-05-21 Glenn Morris * bzrmerge.el (bzrmerge-resolve): Suppress prompts about file-locals. diff --git a/admin/unidata/Makefile.in b/admin/unidata/Makefile.in index 04f2f1d4380..e1fe247631f 100644 --- a/admin/unidata/Makefile.in +++ b/admin/unidata/Makefile.in @@ -33,9 +33,10 @@ unidata.txt: UnicodeData.txt ${DSTDIR}/charprop.el: unidata-gen.elc unidata.txt ELC=`/bin/pwd`/unidata-gen.elc; \ - DATA=`/bin/pwd`/unidata.txt; \ + DATADIR=`/bin/pwd`; \ + DATA=unidata.txt; \ cd ${DSTDIR}; \ - ${RUNEMACS} -batch --load $${ELC} -f unidata-gen-files $${DATA} + ${RUNEMACS} -batch --load $${ELC} -f unidata-gen-files $${DATADIR} $${DATA} ../../src/biditype.h: UnicodeData.txt gawk -F";" -f biditype.awk $< > $@ diff --git a/admin/unidata/unidata-gen.el b/admin/unidata/unidata-gen.el index 9f898668526..ab1dcd134ac 100644 --- a/admin/unidata/unidata-gen.el +++ b/admin/unidata/unidata-gen.el @@ -33,24 +33,25 @@ ;; ;; charprop.el ;; It contains a series of forms of this format: -;; (char-code-property-register PROP FILE) +;; (define-char-code-property PROP FILE) ;; where PROP is a symbol representing a character property -;; (name, generic-category, etc), and FILE is a name of one of +;; (name, general-category, etc), and FILE is a name of one of ;; the following files. ;; ;; uni-name.el, uni-category.el, uni-combining.el, uni-bidi.el, ;; uni-decomposition.el, uni-decimal.el, uni-digit.el, uni-numeric.el, ;; uni-mirrored.el, uni-old-name.el, uni-comment.el, uni-uppercase.el, ;; uni-lowercase.el, uni-titlecase.el -;; They each contain a single form of this format: -;; (char-code-property-register PROP CHAR-TABLE) +;; They contain one or more forms of this format: +;; (define-char-code-property PROP CHAR-TABLE) ;; where PROP is the same as above, and CHAR-TABLE is a ;; char-table containing property values in a compressed format. ;; ;; When they are installed in .../lisp/international/, the file ;; "charprop.el" is preloaded in loadup.el. The other files are -;; automatically loaded when the functions `get-char-code-property' -;; and `put-char-code-property' are called. +;; automatically loaded when the Lisp functions +;; `get-char-code-property' and `put-char-code-property', and C +;; function uniprop_table are called. ;; ;; FORMAT OF A CHAR TABLE ;; @@ -62,17 +63,22 @@ ;; data in a char-table as below. ;; ;; If succeeding 128*N characters have the same property value, we -;; store that value for them. Otherwise, compress values for -;; succeeding 128 characters into a single string and store it as a -;; value for those characters. The way of compression depends on a -;; property. See the section "SIMPLE TABLE", "RUN-LENGTH TABLE", -;; and "WORD-LIST TABLE". - -;; The char table has four extra slots: +;; store that value (or the encoded one) for them. Otherwise, +;; compress values (or the encoded ones) for succeeding 128 +;; characters into a single string and store it for those +;; characters. The way of compression depends on a property. See +;; the section "SIMPLE TABLE", "RUN-LENGTH TABLE", and "WORD-LIST +;; TABLE". + +;; The char table has five extra slots: ;; 1st: property symbol -;; 2nd: function to call to get a property value -;; 3nd: function to call to put a property value -;; 4th: function to call to get a description of a property value +;; 2nd: function to call to get a property value, +;; or an index number of C function to decode the value, +;; or nil if the value can be directly got from the table. +;; 3nd: function to call to put a property value, +;; or an index number of C function to encode the value, +;; or nil if the value can be directly stored in the table. +;; 4th: function to call to get a description of a property value, or nil ;; 5th: data referred by the above functions ;; List of elements of this form: @@ -82,6 +88,11 @@ (defvar unidata-list nil) +;; Name of the directory containing files of Unicode Character +;; Database. + +(defvar unidata-dir nil) + (defun unidata-setup-list (unidata-text-file) (let* ((table (list nil)) (tail table) @@ -90,6 +101,7 @@ ("^<.*Surrogate" . nil) ("^<.*Private Use" . PRIVATE\ USE))) val char name) + (setq unidata-text-file (expand-file-name unidata-text-file unidata-dir)) (or (file-readable-p unidata-text-file) (error "File not readable: %s" unidata-text-file)) (with-temp-buffer @@ -134,12 +146,17 @@ (setq unidata-list (cdr table)))) ;; Alist of this form: -;; (PROP INDEX GENERATOR FILENAME) +;; (PROP INDEX GENERATOR FILENAME DOCSTRING DESCRIBER VAL-LIST) ;; PROP: character property -;; INDEX: index to each element of unidata-list for PROP +;; INDEX: index to each element of unidata-list for PROP. +;; It may be a function that generates an alist of character codes +;; vs. the corresponding property values. ;; GENERATOR: function to generate a char-table ;; FILENAME: filename to store the char-table +;; DOCSTRING: docstring for the property ;; DESCRIBER: function to call to get a description string of property value +;; DEFAULT: the default value of the property +;; VAL-LIST: list of specially ordered property values (defconst unidata-prop-alist '((name @@ -152,7 +169,12 @@ Property value is a string.") Property value is one of the following symbols: Lu, Ll, Lt, Lm, Lo, Mn, Mc, Me, Nd, Nl, No, Pc, Pd, Ps, Pe, Pi, Pf, Po, Sm, Sc, Sk, So, Zs, Zl, Zp, Cc, Cf, Cs, Co, Cn" - unidata-describe-general-category) + unidata-describe-general-category + nil + ;; The order of elements must be in sync with unicode_category_t + ;; in src/character.h. + (Lu Ll Lt Lm Lo Mn Mc Me Nd Nl No Pc Pd Ps Pe Pi Pf Po + Sm Sc Sk So Zs Zl Zp Cc Cf Cs Co Cn)) (canonical-combining-class 3 unidata-gen-table-integer "uni-combining.el" "Unicode canonical combining class. @@ -164,7 +186,11 @@ Property value is an integer." Property value is one of the following symbols: L, LRE, LRO, R, AL, RLE, RLO, PDF, EN, ES, ET, AN, CS, NSM, BN, B, S, WS, ON" - unidata-describe-bidi-class) + unidata-describe-bidi-class + L + ;; The order of elements must be in sync with bidi_type_t in + ;; src/dispextern.h. + (L R EN AN BN B AL LRE LRO RLE RLO PDF ES ET CS NSM S WS ON)) (decomposition 5 unidata-gen-table-decomposition "uni-decomposition.el" "Unicode decomposition mapping. @@ -188,7 +214,7 @@ Property value is an integer or a floating point.") (mirrored 9 unidata-gen-table-symbol "uni-mirrored.el" "Unicode bidi mirrored flag. -Property value is a symbol `Y' or `N'.") +Property value is a symbol `Y' or `N'. See also the property `mirroring'.") (old-name 10 unidata-gen-table-name "uni-old-name.el" "Unicode old names as published in Unicode 1.0. @@ -211,7 +237,12 @@ Property value is a character." 14 unidata-gen-table-character "uni-titlecase.el" "Unicode simple titlecase mapping. Property value is a character." - string))) + string) + (mirroring + unidata-gen-mirroring-list unidata-gen-table-character "uni-mirrored.el" + "Unicode bidi-mirroring characters. +Property value is a character that has the corresponding mirroring image, +or nil for non-mirrored character."))) ;; Functions to access the above data. (defsubst unidata-prop-index (prop) (nth 1 (assq prop unidata-prop-alist))) @@ -219,6 +250,8 @@ Property value is a character." (defsubst unidata-prop-file (prop) (nth 3 (assq prop unidata-prop-alist))) (defsubst unidata-prop-docstring (prop) (nth 4 (assq prop unidata-prop-alist))) (defsubst unidata-prop-describer (prop) (nth 5 (assq prop unidata-prop-alist))) +(defsubst unidata-prop-default (prop) (nth 6 (assq prop unidata-prop-alist))) +(defsubst unidata-prop-val-list (prop) (nth 7 (assq prop unidata-prop-alist))) ;; SIMPLE TABLE @@ -227,52 +260,34 @@ Property value is a character." ;; values of succeeding character codes are usually different, we use ;; a char-table described here to store such values. ;; -;; If succeeding 128 characters has no property, a char-table has the -;; symbol t for them. Otherwise a char-table has a string of the -;; following format for them. +;; A char-table divides character code space (#x0..#x3FFFFF) into +;; #x8000 blocks (each block contains 128 characters). + +;; If all characters of a block have no property, a char-table has the +;; symbol nil for that block. Otherwise a char-table has a string of +;; the following format for it. ;; -;; The first character of the string is FIRST-INDEX. -;; The Nth (N > 0) character of the string is a property value of the -;; character (BLOCK-HEAD + FIRST-INDEX + N - 1), where BLOCK-HEAD is -;; the first of the characters in the block. +;; The first character of the string is ?\001. +;; The second character of the string is FIRST-INDEX. +;; The Nth (N > 1) character of the string is a property value of the +;; character (BLOCK-HEAD + FIRST-INDEX + N - 2), where BLOCK-HEAD is +;; the first character of the block. ;; -;; The 4th extra slot of a char-table is nil. - -(defun unidata-get-character (char val table) - (cond - ((characterp val) - val) +;; This kind of char-table has these extra slots: +;; 1st: the property symbol +;; 2nd: nil +;; 3rd: 0 (corresponding to uniprop_encode_character in chartab.c) +;; 4th to 5th: nil - ((stringp val) - (let* ((len (length val)) - (block-head (lsh (lsh char -7) 7)) - (vec (make-vector 128 nil)) - (first-index (aref val 0))) - (dotimes (i (1- len)) - (let ((elt (aref val (1+ i)))) - (if (> elt 0) - (aset vec (+ first-index i) elt)))) - (dotimes (i 128) - (aset table (+ block-head i) (aref vec i))) - (aref vec (- char block-head)))))) - -(defun unidata-put-character (char val table) - (or (characterp val) - (not val) - (error "Not a character nor nil: %S" val)) - (let ((current-val (aref table char))) - (unless (eq current-val val) - (if (stringp current-val) - (funcall (char-table-extra-slot table 1) char current-val table)) - (aset table char val)))) - -(defun unidata-gen-table-character (prop) +(defun unidata-gen-table-character (prop &rest ignore) (let ((table (make-char-table 'char-code-property-table)) (prop-idx (unidata-prop-index prop)) (vec (make-vector 128 0)) (tail unidata-list) elt range val idx slot) - (set-char-table-range table (cons 0 (max-char)) t) + (if (functionp prop-idx) + (setq tail (funcall prop-idx) + prop-idx 1)) (while tail (setq elt (car tail) tail (cdr tail)) (setq range (car elt) @@ -301,7 +316,7 @@ Property value is a character." (setq first-index last-index))) (setq tail (cdr tail))) (when first-index - (let ((str (string first-index)) + (let ((str (string 1 first-index)) c) (while (<= first-index last-index) (setq str (format "%s%c" str (or (aref vec first-index) 0)) @@ -309,184 +324,78 @@ Property value is a character." (set-char-table-range table (cons start limit) str)))))) (set-char-table-extra-slot table 0 prop) - (byte-compile 'unidata-get-character) - (byte-compile 'unidata-put-character) - (set-char-table-extra-slot table 1 (symbol-function 'unidata-get-character)) - (set-char-table-extra-slot table 2 (symbol-function 'unidata-put-character)) - + (set-char-table-extra-slot table 2 0) table)) ;; RUN-LENGTH TABLE ;; -;; If the type of character property value is symbol, integer, -;; boolean, or character, we use a char-table described here to store -;; the values. +;; If many characters of successive character codes have the same +;; property value, we use a char-table described here to store the +;; values. ;; -;; The 4th extra slot is a vector of property values (VAL-TABLE), and -;; values for succeeding 128 characters are encoded into this -;; character sequence: +;; At first, instead of a value itself, we store an index number to +;; the VAL-TABLE (5th extra slot) in the table. We call that index +;; number as VAL-CODE here after. +;; +;; A char-table divides character code space (#x0..#x3FFFFF) into +;; #x8000 blocks (each block contains 128 characters). +;; +;; If all characters of a block have the same value, a char-table has +;; VAL-CODE for that block. Otherwise a char-table has a string of +;; the following format for that block. +;; +;; The first character of the string is ?\002. +;; The following characters has this form: ;; ( VAL-CODE RUN-LENGTH ? ) + ;; where: -;; VAL-CODE (0..127): -;; (VAL-CODE - 1) is an index into VAL-TABLE. -;; The value 0 means no-value. +;; VAL-CODE (0..127): index into VAL-TABLE. ;; RUN-LENGTH (130..255): ;; (RUN-LENGTH - 128) specifies how many characters have the same ;; value. If omitted, it means 1. - - -;; Return a symbol-type character property value of CHAR. VAL is the -;; current value of (aref TABLE CHAR). - -(defun unidata-get-symbol (char val table) - (let ((val-table (char-table-extra-slot table 4))) - (cond ((symbolp val) - val) - ((stringp val) - (let ((first-char (lsh (lsh char -7) 7)) - (str val) - (len (length val)) - (idx 0) - this-val count) - (set-char-table-range table (cons first-char (+ first-char 127)) - nil) - (while (< idx len) - (setq val (aref str idx) idx (1+ idx) - count (if (< idx len) (aref str idx) 1)) - (setq val (and (> val 0) (aref val-table (1- val))) - count (if (< count 128) - 1 - (prog1 (- count 128) (setq idx (1+ idx))))) - (dotimes (i count) - (if val - (aset table first-char val)) - (if (= first-char char) - (setq this-val val)) - (setq first-char (1+ first-char)))) - this-val)) - ((> val 0) - (aref val-table (1- val)))))) - -;; Return a integer-type character property value of CHAR. VAL is the -;; current value of (aref TABLE CHAR). - -(defun unidata-get-integer (char val table) - (let ((val-table (char-table-extra-slot table 4))) - (cond ((integerp val) - val) - ((stringp val) - (let ((first-char (lsh (lsh char -7) 7)) - (str val) - (len (length val)) - (idx 0) - this-val count) - (while (< idx len) - (setq val (aref str idx) idx (1+ idx) - count (if (< idx len) (aref str idx) 1)) - (setq val (and (> val 0) (aref val-table (1- val))) - count (if (< count 128) - 1 - (prog1 (- count 128) (setq idx (1+ idx))))) - (dotimes (i count) - (aset table first-char val) - (if (= first-char char) - (setq this-val val)) - (setq first-char (1+ first-char)))) - this-val))))) - -;; Return a numeric-type (integer or float) character property value -;; of CHAR. VAL is the current value of (aref TABLE CHAR). - -(defun unidata-get-numeric (char val table) - (cond - ((numberp val) - val) - ((stringp val) - (let ((val-table (char-table-extra-slot table 4)) - (first-char (lsh (lsh char -7) 7)) - (str val) - (len (length val)) - (idx 0) - this-val count) - (while (< idx len) - (setq val (aref str idx) idx (1+ idx) - count (if (< idx len) (aref str idx) 1)) - (setq val (and (> val 0) (aref val-table (1- val))) - count (if (< count 128) - 1 - (prog1 (- count 128) (setq idx (1+ idx))))) - (dotimes (i count) - (aset table first-char val) - (if (= first-char char) - (setq this-val val)) - (setq first-char (1+ first-char)))) - this-val)))) - -;; Store VAL (symbol) as a character property value of CHAR in TABLE. - -(defun unidata-put-symbol (char val table) - (or (symbolp val) - (error "Not a symbol: %S" val)) - (let ((current-val (aref table char))) - (unless (eq current-val val) - (if (stringp current-val) - (funcall (char-table-extra-slot table 1) char current-val table)) - (aset table char val)))) - -;; Store VAL (integer) as a character property value of CHAR in TABLE. - -(defun unidata-put-integer (char val table) - (or (integerp val) - (not val) - (error "Not an integer nor nil: %S" val)) - (let ((current-val (aref table char))) - (unless (eq current-val val) - (if (stringp current-val) - (funcall (char-table-extra-slot table 1) char current-val table)) - (aset table char val)))) - -;; Store VAL (integer or float) as a character property value of CHAR -;; in TABLE. - -(defun unidata-put-numeric (char val table) - (or (numberp val) - (not val) - (error "Not a number nor nil: %S" val)) - (let ((current-val (aref table char))) - (unless (equal current-val val) - (if (stringp current-val) - (funcall (char-table-extra-slot table 1) char current-val table)) - (aset table char val)))) +;; +;; This kind of char-table has these extra slots: +;; 1st: the property symbol +;; 2nd: 0 (corresponding to uniprop_decode_value in chartab.c) +;; 3rd: 1..3 (corresponding to uniprop_encode_xxx in chartab.c) +;; 4th: function or nil +;; 5th: VAL-TABLE ;; Encode the character property value VAL into an integer value by ;; VAL-LIST. By side effect, VAL-LIST is modified. ;; VAL-LIST has this form: -;; (t (VAL1 . VAL-CODE1) (VAL2 . VAL-CODE2) ...) -;; If VAL is one of VALn, just return VAL-CODEn. Otherwise, -;; VAL-LIST is modified to this: -;; (t (VAL . (1+ VAL-CODE1)) (VAL1 . VAL-CODE1) (VAL2 . VAL-CODE2) ...) +;; ((nil . 0) (VAL1 . 1) (VAL2 . 2) ...) +;; If VAL is one of VALn, just return n. +;; Otherwise, VAL-LIST is modified to this: +;; ((nil . 0) (VAL1 . 1) (VAL2 . 2) ... (VAL . n+1)) (defun unidata-encode-val (val-list val) (let ((slot (assoc val val-list)) val-code) (if slot (cdr slot) - (setq val-code (if (cdr val-list) (1+ (cdr (nth 1 val-list))) 1)) - (setcdr val-list (cons (cons val val-code) (cdr val-list))) + (setq val-code (length val-list)) + (nconc val-list (list (cons val val-code))) val-code))) ;; Generate a char-table for the character property PROP. -(defun unidata-gen-table (prop val-func default-value) +(defun unidata-gen-table (prop val-func default-value val-list) (let ((table (make-char-table 'char-code-property-table)) (prop-idx (unidata-prop-index prop)) - (val-list (list t)) (vec (make-vector 128 0)) tail elt range val val-code idx slot prev-range-data) - (set-char-table-range table (cons 0 (max-char)) default-value) + (setq val-list (cons nil (copy-sequence val-list))) + (setq tail val-list val-code 0) + ;; Convert (nil A B ...) to ((nil . 0) (A . 1) (B . 2) ...) + (while tail + (setcar tail (cons (car tail) val-code)) + (setq tail (cdr tail) val-code (1+ val-code))) + (setq default-value (unidata-encode-val val-list default-value)) + (set-char-table-range table t default-value) + (set-char-table-range table nil default-value) (setq tail unidata-list) (while tail (setq elt (car tail) tail (cdr tail)) @@ -495,7 +404,7 @@ Property value is a character." (setq val-code (if val (unidata-encode-val val-list val))) (if (consp range) (when val-code - (set-char-table-range table range val) + (set-char-table-range table range val-code) (let ((from (car range)) (to (cdr range))) ;; If RANGE doesn't end at the char-table boundary (each ;; 128 characters), we may have to carry over the data @@ -534,7 +443,7 @@ Property value is a character." (if val-code (aset vec (- range start) val-code)) (setq tail (cdr tail))) - (setq str "" val-code -1 count 0) + (setq str "\002" val-code -1 count 0) (mapc #'(lambda (x) (if (= val-code x) (setq count (1+ count)) @@ -549,7 +458,7 @@ Property value is a character." vec) (if (= count 128) (if val - (set-char-table-range table (cons start limit) val)) + (set-char-table-range table (cons start limit) val-code)) (if (= val-code 0) (set-char-table-range table (cons start limit) str) (if (> count 2) @@ -559,34 +468,29 @@ Property value is a character." (setq str (concat str (string val-code))))) (set-char-table-range table (cons start limit) str)))))) - (setq val-list (nreverse (cdr val-list))) (set-char-table-extra-slot table 0 prop) (set-char-table-extra-slot table 4 (vconcat (mapcar 'car val-list))) table)) -(defun unidata-gen-table-symbol (prop) +(defun unidata-gen-table-symbol (prop default-value val-list) (let ((table (unidata-gen-table prop #'(lambda (x) (and (> (length x) 0) (intern x))) - 0))) - (byte-compile 'unidata-get-symbol) - (byte-compile 'unidata-put-symbol) - (set-char-table-extra-slot table 1 (symbol-function 'unidata-get-symbol)) - (set-char-table-extra-slot table 2 (symbol-function 'unidata-put-symbol)) + default-value val-list))) + (set-char-table-extra-slot table 1 0) + (set-char-table-extra-slot table 2 1) table)) -(defun unidata-gen-table-integer (prop) +(defun unidata-gen-table-integer (prop default-value val-list) (let ((table (unidata-gen-table prop #'(lambda (x) (and (> (length x) 0) (string-to-number x))) - t))) - (byte-compile 'unidata-get-integer) - (byte-compile 'unidata-put-integer) - (set-char-table-extra-slot table 1 (symbol-function 'unidata-get-integer)) - (set-char-table-extra-slot table 2 (symbol-function 'unidata-put-integer)) + default-value val-list))) + (set-char-table-extra-slot table 1 0) + (set-char-table-extra-slot table 2 1) table)) -(defun unidata-gen-table-numeric (prop) +(defun unidata-gen-table-numeric (prop default-value val-list) (let ((table (unidata-gen-table prop #'(lambda (x) (if (string-match "/" x) @@ -595,11 +499,9 @@ Property value is a character." (substring x (match-end 0)))) (if (> (length x) 0) (string-to-number x)))) - t))) - (byte-compile 'unidata-get-numeric) - (byte-compile 'unidata-put-numeric) - (set-char-table-extra-slot table 1 (symbol-function 'unidata-get-numeric)) - (set-char-table-extra-slot table 2 (symbol-function 'unidata-put-numeric)) + default-value val-list))) + (set-char-table-extra-slot table 1 0) + (set-char-table-extra-slot table 2 2) table)) @@ -892,7 +794,6 @@ Property value is a character." word-table block-list block-word-table block-end tail elt range val idx slot) - (set-char-table-range table (cons 0 (max-char)) 0) (setq tail unidata-list) (setq block-end -1) (while tail @@ -1025,7 +926,7 @@ Property value is a character." idx (1+ i))))) (nreverse (cons (intern (substring str idx)) l)))))) -(defun unidata-gen-table-name (prop) +(defun unidata-gen-table-name (prop &rest ignore) (let* ((table (unidata-gen-table-word-list prop 'unidata-split-name)) (word-tables (char-table-extra-slot table 4))) (byte-compile 'unidata-get-name) @@ -1064,7 +965,7 @@ Property value is a character." (nreverse l))))) -(defun unidata-gen-table-decomposition (prop) +(defun unidata-gen-table-decomposition (prop &rest ignore) (let* ((table (unidata-gen-table-word-list prop 'unidata-split-decomposition)) (word-tables (char-table-extra-slot table 4))) (byte-compile 'unidata-get-decomposition) @@ -1080,7 +981,8 @@ Property value is a character." (defun unidata-describe-general-category (val) (cdr (assq val - '((Lu . "Letter, Uppercase") + '((nil . "Uknown") + (Lu . "Letter, Uppercase") (Ll . "Letter, Lowercase") (Lt . "Letter, Titlecase") (Lm . "Letter, Modifier") @@ -1171,6 +1073,19 @@ Property value is a character." (string ?')))) val " ")) +(defun unidata-gen-mirroring-list () + (let ((head (list nil)) + tail) + (with-temp-buffer + (insert-file-contents (expand-file-name "BidiMirroring.txt" unidata-dir)) + (goto-char (point-min)) + (setq tail head) + (while (re-search-forward "^\\([0-9A-F]+\\);\\s +\\([0-9A-F]+\\)" nil t) + (let ((char (string-to-number (match-string 1) 16)) + (mirror (match-string 2))) + (setq tail (setcdr tail (list (list char mirror))))))) + (cdr head))) + ;; Verify if we can retrieve correct values from the generated ;; char-tables. @@ -1212,13 +1127,21 @@ Property value is a character." ;; The entry function. It generates files described in the header ;; comment of this file. -(defun unidata-gen-files (&optional unidata-text-file) - (or unidata-text-file - (setq unidata-text-file (car command-line-args-left) +(defun unidata-gen-files (&optional data-dir unidata-text-file) + (or data-dir + (setq data-dir (car command-line-args-left) + command-line-args-left (cdr command-line-args-left) + unidata-text-file (car command-line-args-left) command-line-args-left (cdr command-line-args-left))) - (unidata-setup-list unidata-text-file) (let ((coding-system-for-write 'utf-8-unix) - (charprop-file "charprop.el")) + (charprop-file "charprop.el") + (unidata-dir data-dir)) + (dolist (elt unidata-prop-alist) + (let* ((prop (car elt)) + (file (unidata-prop-file prop))) + (if (file-exists-p file) + (delete-file file)))) + (unidata-setup-list unidata-text-file) (with-temp-file charprop-file (insert ";; Automatically generated by unidata-gen.el.\n") (dolist (elt unidata-prop-alist) @@ -1227,31 +1150,41 @@ Property value is a character." (file (unidata-prop-file prop)) (docstring (unidata-prop-docstring prop)) (describer (unidata-prop-describer prop)) + (default-value (unidata-prop-default prop)) + (val-list (unidata-prop-val-list prop)) table) ;; Filename in this comment line is extracted by sed in ;; Makefile. (insert (format ";; FILE: %s\n" file)) (insert (format "(define-char-code-property '%S %S\n %S)\n" prop file docstring)) - (with-temp-file file + (with-temp-buffer (message "Generating %s..." file) - (setq table (funcall generator prop)) + (when (file-exists-p file) + (insert-file-contents file) + (goto-char (point-max)) + (search-backward ";; Local Variables:")) + (setq table (funcall generator prop default-value val-list)) (when describer (unless (subrp (symbol-function describer)) (byte-compile describer) (setq describer (symbol-function describer))) (set-char-table-extra-slot table 3 describer)) - (insert ";; Copyright (C) 1991-2009 Unicode, Inc. -;; This file was generated from the Unicode data file at -;; http://www.unicode.org/Public/UNIDATA/UnicodeData.txt. -;; See lisp/international/README for the copyright and permission notice.\n" - (format "(define-char-code-property '%S %S %S)\n" - prop table docstring) - ";; Local Variables:\n" - ";; coding: utf-8\n" - ";; no-byte-compile: t\n" - ";; End:\n\n" - (format ";; %s ends here\n" file))))) + (if (bobp) + (insert ";; Copyright (C) 1991-2009 Unicode, Inc. +;; This file was generated from the Unicode data files at +;; http://www.unicode.org/Public/UNIDATA/. +;; See lisp/international/README for the copyright and permission notice.\n")) + (insert (format "(define-char-code-property '%S %S %S)\n" + prop table docstring)) + (if (eobp) + (insert ";; Local Variables:\n" + ";; coding: utf-8\n" + ";; no-byte-compile: t\n" + ";; End:\n\n" + (format ";; %s ends here\n" file))) + (write-file file) + (message "Generating %s...done" file)))) (message "Writing %s..." charprop-file) (insert ";; Local Variables:\n" ";; coding: utf-8\n" diff --git a/lisp/ChangeLog b/lisp/ChangeLog index 89b33dc7a62..b85a1680286 100644 --- a/lisp/ChangeLog +++ b/lisp/ChangeLog @@ -1,3 +1,39 @@ +2011-07-06 Kenichi Handa + + * international/characters.el (build-unicode-category-table): + Delete it. + (unicode-category-table): Set it by + unicode-prroperty-table-internal. + + * international/mule-cmds.el (char-code-property-alist): Moved to + to src/chartab.c. + (get-char-code-property): Call unicode-property-table-internal to + load a file. Call get-unicode-property-internal where necessary. + (put-char-code-property): Call unicode-property-table-internal to + load a file. Call put-unicode-property-internal where necessary. + put-unicode-property-internal where necessary. + (char-code-property-description): Call + unicode-property-table-internal to load a file. + + * international/charprop.el: + * international/uni-bidi.el: + * international/uni-category.el: + * international/uni-combining.el: + * international/uni-comment.el: + * international/uni-decimal.el: + * international/uni-decomposition.el: + * international/uni-digit.el: + * international/uni-lowercase.el: + * international/uni-mirrored.el: + * international/uni-name.el: + * international/uni-numeric.el: + * international/uni-old-name.el: + * international/uni-titlecase.el: + * international/uni-uppercase.el: Regenerate. + + * loadup.el: Load international/charprop.el before + international/characters. + 2011-06-22 Richard Stallman * mail/sendmail.el (mail-bury): If Rmail is in use, return nicely diff --git a/lisp/international/characters.el b/lisp/international/characters.el index 455cbe697d6..a9657c17b9f 100644 --- a/lisp/international/characters.el +++ b/lisp/international/characters.el @@ -1206,22 +1206,8 @@ Setup char-width-table appropriate for non-CJK language environment." ;;; Setting unicode-category-table. -;; This macro is to build unicode-category-table at compile time so -;; that C code can access the table efficiently. -(defmacro build-unicode-category-table () - (let ((table (make-char-table 'unicode-category-table nil))) - (dotimes (i #x110000) - (if (or (< i #xD800) - (and (>= i #xF900) (< i #x30000)) - (and (>= i #xE0000) (< i #xE0200))) - (aset table i (get-char-code-property i 'general-category)))) - (set-char-table-range table '(#xE000 . #xF8FF) 'Co) - (set-char-table-range table '(#xF0000 . #xFFFFD) 'Co) - (set-char-table-range table '(#x100000 . #x10FFFD) 'Co) - (optimize-char-table table 'eq) - table)) - -(setq unicode-category-table (build-unicode-category-table)) +(setq unicode-category-table + (unicode-property-table-internal 'general-category)) (map-char-table #'(lambda (key val) (if (and val (or (and (/= (aref (symbol-name val) 0) ?M) diff --git a/lisp/international/charprop.el b/lisp/international/charprop.el index 5c3efcc9d07..919666010b1 100644 --- a/lisp/international/charprop.el +++ b/lisp/international/charprop.el @@ -1,8 +1,4 @@ -;; Copyright (C) 1991-2010 Unicode, Inc. -;; This file was generated from the Unicode data file at -;; http://www.unicode.org/Public/UNIDATA/UnicodeData.txt. -;; See lisp/international/README for the copyright and permission notice. - +;; Automatically generated by unidata-gen.el. ;; FILE: uni-name.el (define-char-code-property 'name "uni-name.el" "Unicode character name. @@ -45,7 +41,7 @@ Property value is an integer or a floating point.") ;; FILE: uni-mirrored.el (define-char-code-property 'mirrored "uni-mirrored.el" "Unicode bidi mirrored flag. -Property value is a symbol `Y' or `N'.") +Property value is a symbol `Y' or `N'. See also the property `mirroring'.") ;; FILE: uni-old-name.el (define-char-code-property 'old-name "uni-old-name.el" "Unicode old names as published in Unicode 1.0. @@ -66,6 +62,11 @@ Property value is a character.") (define-char-code-property 'titlecase "uni-titlecase.el" "Unicode simple titlecase mapping. Property value is a character.") +;; FILE: uni-mirrored.el +(define-char-code-property 'mirroring "uni-mirrored.el" + "Unicode bidi-mirroring characters. +Property value is a character that has the corresponding mirroring image, +or nil for non-mirrored character.") ;; Local Variables: ;; coding: utf-8 ;; no-byte-compile: t diff --git a/lisp/international/mule-cmds.el b/lisp/international/mule-cmds.el index b3f17bb3fcf..e75a22d6415 100644 --- a/lisp/international/mule-cmds.el +++ b/lisp/international/mule-cmds.el @@ -2709,16 +2709,6 @@ See also `locale-charset-language-names', `locale-language-names', ;;; Character property -;; Each element has the form (PROP . TABLE). -;; PROP is a symbol representing a character property. -;; TABLE is a char-table containing the property value for each character. -;; TABLE may be a name of file to load to build a char-table. -;; Don't modify this variable directly but use `define-char-code-property'. - -(defvar char-code-property-alist nil - "Alist of character property name vs char-table containing property values. -Internal use only.") - (put 'char-code-property-table 'char-table-extra-slots 5) (defun define-char-code-property (name table &optional docstring) @@ -2770,32 +2760,23 @@ See also the documentation of `get-char-code-property' and (defun get-char-code-property (char propname) "Return the value of CHAR's PROPNAME property." - (let ((slot (assq propname char-code-property-alist))) - (if slot - (let (table value func) - (if (stringp (cdr slot)) - (load (cdr slot) nil t)) - (setq table (cdr slot) - value (aref table char) - func (char-table-extra-slot table 1)) + (let ((table (unicode-property-table-internal propname))) + (if table + (let ((func (char-table-extra-slot table 1))) (if (functionp func) - (setq value (funcall func char value table))) - value) + (funcall func char (aref table char) table) + (get-unicode-property-internal table char))) (plist-get (aref char-code-property-table char) propname)))) (defun put-char-code-property (char propname value) "Store CHAR's PROPNAME property with VALUE. It can be retrieved with `(get-char-code-property CHAR PROPNAME)'." - (let ((slot (assq propname char-code-property-alist))) - (if slot - (let (table func) - (if (stringp (cdr slot)) - (load (cdr slot) nil t)) - (setq table (cdr slot) - func (char-table-extra-slot table 2)) + (let ((table (unicode-property-table-internal propname))) + (if table + (let ((func (char-table-extra-slot table 2))) (if (functionp func) (funcall func char value table) - (aset table char value))) + (put-unicode-property-internal table char value))) (let* ((plist (aref char-code-property-table char)) (x (plist-put plist propname value))) (or (eq x plist) @@ -2805,13 +2786,9 @@ It can be retrieved with `(get-char-code-property CHAR PROPNAME)'." (defun char-code-property-description (prop value) "Return a description string of character property PROP's value VALUE. If there's no description string for VALUE, return nil." - (let ((slot (assq prop char-code-property-alist))) - (if slot - (let (table func) - (if (stringp (cdr slot)) - (load (cdr slot) nil t)) - (setq table (cdr slot) - func (char-table-extra-slot table 3)) + (let ((table (unicode-property-table-internal prop))) + (if table + (let ((func (char-table-extra-slot table 3))) (if (functionp func) (funcall func value)))))) diff --git a/lisp/international/uni-bidi.el b/lisp/international/uni-bidi.el index 9e571ef9d0d5b806873a26cfdb86235c1570398d..e7682c6d8ffca6a2c50a63bff9ecac7beea60f8f 100644 GIT binary patch literal 8719 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 literal 9287 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 O?H5WDb3P(RA^E>cXb33) literal 12450 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 A_W%F@ literal 8881 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 Hq{%nP~t^}LTBpjXA!S8f@yWx2qxZ*5KBKii- zdFWWZ9$d~?1``%jSdt8;lv6<@jbI{@Imj6;JRl;HXkZ3JqUTJ?wClRd<$shG1Y zQ%K;6WFd8|qliuzr*=3a!bTZ(DiVd0D|j8zkj+VKM{LTZeM8~}g;&=@4>*gV>R?MU zR+?*v2kW1Y4j(^x`t13OmsU-=Tn~Nl^x05n1>h-T^`~IB-*+q0rf@B<6KHLQV5Mzs5L63USg;HR^&P&5`SM_bC}ImZSU-%$ z5XL*h06PLo{za<#995bEJE;L!2m@%~FruNdfMR5$QoA~8y0WF~5*~?=#L!c)Z_aJb zd9H!qYLy^Hw)^i;kCB%*$~(e`;P|*1Y`P==U!}XZ993w=QgmL>37QQp-T163_`gxM zEtE-=b#&3HY?K@ak}V_g&@KEGGnig3U^GNr<))o~NOO+pgG zCn6XQ^{k6FwH_Fsc3~kWb{h>mvBxW^mPayA)w=6~USb0tbuGMBE6m=6c4!QgM;Xkh Gpw=%al4gDY literal 2483 zcmc&$OK;mo5N2PgM7MMzy9SE3!hk^$D+whoDN!#Jg%KOIfg}iOJ1rt908Or>MJZBP zu4?<%Q;$V|LQg&CH`sryv!oP>qHXk26avNBdF{+M%bn?V;aN1jU|Qm563k7}=GX94qSr!SB8_fGa|^ZoYGxGFA0vgI+Q5U_Y!W1*lt zbOnn-H>mx1u($u>0EQ7y_VwQ9;f6j;DW9-7MokDK!8}@3cYQi!AvL_Q%MF>7G362J ziA#9oQ;$vD!0_3K3FB8cm{EB6wimJhm-S;;_`U}lADYv}}a-Yv7%*8^Ban?~u7dj0k&7g62y&edg*9smMPqhUMq z!;sQ>KeyqK*UWJi=get4ww3#Ea_Z|y+_he!ly#G0Mo6pKs^4XgGOWWN%R2m9Dp#-d zU6ROd3oje&f3>>tTJ7!1>lE;kh2#>gfZn%Fr+|OWzW$}!w;E>OGHp#k(zN=P?I>y& z$worS0K-$KqE*D>aQ{F7!FFz=kv`y{)PtqZp+lux;+dM?x ziB#HIh@Pi>x!(%~T{N~;>Fl-K^=GB19v_xILxz+1@e&QG`-_rr-=MplP3dr3T9voT z+uD}4J>S%7Dg~{i9--XSN*kwXD1<2L7h36Lr=)GAv200?LU}A-kCo4>_bNy=b?Bw7 z2JxCV9f@25p%=|UEFE@a*|O3ul_(qZLU7lJgGfLff_Mx@6PnnMWHTc`tQIi;0s-aPZSQpH;s2)mC zzAAk8J<1zTlnq%%`;pXhifO&ojpD;pw{Wyb`2EqCr#a)ChDlon$~pFX{Us*mh9C!m z5#`w8@nJy+zCG4&fq@L5F-Y?7nFxUeHX_pi2VrSJ8!sY#K6*enn^4X?c|dUrz^Ne_ z4Imi}DpmE>VrWR^I1McWsp=Iu>O7A;EXQk?GdU#09m&IigN36G%*4=WNk$kMXO{xU jk!Ui-ajFB!lyngK9aV~PMl$AGS7`t=^kW!PPSt+^n?O<( diff --git a/lisp/international/uni-decomposition.el b/lisp/international/uni-decomposition.el index f35bcebfed8ed607c4cce0daafcb15a5266ef5b8..b0bf07bbe857c03aa47b689fbf30596df437d15c 100644 GIT binary patch delta 1605 zcmZ2~lX3Mu#tBjr6y|1tZTd7JnpJWR>KyCo2i&awC}uv{8TaVL=W)kc~i& z_v8jPiOu>7R*dRMs_@x1xkm9TJ5(*$fD4=^Tmo4PoMB2JZBQX~Ud~5b7lK8gqDq@* zC`Ss`6KM-R7vPhN#VHAjAR`4^69Y>#aO~hzh{uIc&uP?izM8up?m2Qyg6Y9@FT|Z@ zh9)MsovDwCGBuNfN>!O;FP<&5Vse3V=krz&^;HcZI5_5}#6sG{aLY{qiQc68) U=}LVI2$-)-gpW4&rz)@m0DG_<`2YX_ delta 948 zcmZ2|k8%A?#tBkvItoSxh6WR*Tqefr@`vVSCg-Q5x+In)>XlTKOzfE@Y@nbV7Z+`) z0HKY5w87*?ZspAhj7%Ji2Afkkxf$7kVo-6N&8xZm85s>GJ1To`_TX91q7IdVsK8B5 zb`#8Hg_)wi`K=%aAJ~-S&Cv>0j6hdlz{z_QzcK?wfmRhw4q)Wv5XfTS3{wINRDdNK zxs^6QQjQc%!O)9o8nQ?%G6(E^BLx!!OEbL2fSi%Y!1-$KdY}^sL4*yUz%^1ZGc++F zs0n1~W(o5o34T~ym|2<`17idjAF`8I`Ku%oWdwG&AzXxN2*iDch8E@)CLocQZF42K$IWM*k@2KI?s^mE2~45ipzhbkHy3r&-T#)byw;3SEv s0EGv&*wV<<5JRZ|ib|kkHVeev;=t}Ipsi%NmULZ0m|8Y-XDF}(0Jk{4h5!Hn diff --git a/lisp/international/uni-digit.el b/lisp/international/uni-digit.el index 692dea1edc8007a5a327f8a27f8abbe1f3bc33fa..fc52fd8c28cdaceb2ffc58a845b9606b588ac12d 100644 GIT binary patch literal 2187 zcmd5;OK;Oa5O&k@%C8ui1FeK#Y3jzwscL(u1gL_ROVvuQy-8Mb){(s->J15j5J(7d zbNoL)q9H0H3ry8)KtSX#$49XMvx z3w`nw4w$F62Lm`7(-?*{ATW1h7!gJymlGd`Q8)oUCYc5JE_Wp`2A8AdnDc4hFy`~Q zK1;poVKg!hXXgR+jN=yvdpk!vh79tG5C~{IH7MgGVlJm4a|7e${?6X>eHez3jO68< zUFO4-L=zgv0tqbS)FXO(-6uoJh~|ymNW(O=X%q?^zknw`9Z{~maf2Cw$7d%dFd9G; zsB!mPw6zx4TU(p%v|)h5%3>M%A3ptOD?h#+-CUbz$SEI z3vAei9yo%kx>)JJW)l)o57HgDF5PVC?Za$ErgE|ET?V*^Mcfl=wH^vssGVPMv3$eHRD3S@+9co}|++N-?pi4M_;Kos?P%oTZg?^mHfg zR<->WC@rOhQu@}nJ{9_A`p`c>{>M7Ir@PZhmeZ#ebKcpR*>7j&8?n=9z!PtH?%TaS zgUu&fKx#Fj8MS#i(4#K(Ek--g^}PYG zK8;R5$6{9KXfb}U&)BeDD4d?2=0_oD-t&8f7o!u$ZWoT8@9%6MZWku^?cm`&J7eO? z14_ZMgJHpT8TDO@*`8}Tg)erucb@G+*Ym}_?Klt1?ZA-w13L)N6I_qkZJL)iJG5)N zRBQJwU*kz>L*GL`b`B3acF$(oHxmcEBDREB4oHTDM5rxEm0|sy+^%+Y7fK;TYi7XgTis@AHbH*8G4uU=x31f4y zC$WZ6nxs@(9Ay;Mb?aPHwL&%tnB{WOoV0Z)&*Lnr!?Y)+^oFxBn+)m`{wKz$lgye~ z6s`1Y%p-QlHHBHo)N~}VoRl$EO;JxswNfp;1rekFIf>`rO0zXcUynN;Sx7B0%v!}1 zQK(A^{#y|i$BoR+-S;1AQg74oCV!IvUn&qU(H5x9qHbpJU!|#jAUBP&-Zb>0BB7`o zO`~W^as$P(5SvAUWq>UzC=7)VNq%3+9&TinwJ?@7j>x1(e0e0jm%qJ* zQbmR1@V&-*OAd>nE7fQg|3Y|yk0P8$OnXpTL=i9%~Z1%I1Yu$GxHRZ=7rIbld)3BPg% zdBJR#O;BhW7F&(h8@s_>lXV%OT(L%JTitH?tol9Jj_K&5`d@SIjm*eIJJ< z^*JVHxxlBX9`$iP!q0Z<@ZdmQPzKV1a!cfYtYZlbC}L&GU}9OSP{ZGcI+@$R9Sx{& zw|Rr&D77hicPlTyh$gL2k0WFfKwjPA^WjskjWoQpe49^LL7nSxO0(Tw9Y(CHRk_0T nw3Bm&Gn_XV;tW~`FhlbabGft(|Z2Pd~M9Rsqwn5#we zGIJD^7z@sBWH`H-fq~)db|oNp@-^noK>1FV!$8u9bw7~gW}A`*QcGnVtDqbg7j2|q zVqj?oHXCU94YtyHDqDlo*-DHI4|g;IaWfFN0&zPKcQQ<#&i)SQ=~j+kK(e0m43PBZ zdcp;B70{6;+(ojC%#Yeyl(3o&RI!~q&lw!>gIiK-@ani7y!FlBs;gK=K6NHXvEY?~Kb;#9D^wdWeh73{6ak zad8CIlOovVz<@Uv2y_63Ml2+08Y-BXni`uylPQFa99G!aKtnbPET%Ms@P#C1=wZ5} u9%l#$`4JJp3Yz6>=A;mNR delta 1350 zcmbVLO-~a+7~WdI?FU<$7!yI7VNgRGmh5(0Dxy(hqvc{WC`MTz%XY9U+ZMM&sdA_v z#DjW}j0r!$lU@v|kyB%g@diJ@L=S!(O?orNgK=g{(iW=_Gnt*8_kG@H-shRjm*B(D zr^Ea#< zUdS&NZr*|b63a0{UOL{8{GNB@xO2&m0i54l<2Fki$8D}N#D=p(ZnwN8@z&R*rR~WO z2D==Spm%C&A`BwZ&>*dW`)ezsfn?QV`JJEd zFT*-GBuBg#y8m?yBx~Lu0j-TD*d1wiTs_uDaE#CU{9rdr&7LKDc`GZ^!T*ez*+pdOS`LBUi9S80Ss<^O0BbWQ3IeDq(jecXh9!mPc)G;+ zVfrmbmpK0H0h)}dVOe&oiY%!VE6XbEqDz=gh0cfy5At-4Cc0f?Yz+tjpCAan%Z%|n z#|y&61Y-zvux=@MG+vA-Z67>5=7}MZticy_BZ0Q z{Z)J%bv0_+P93ENxZJiwUHplYwE1X1=NVRu)TcfMjJc>2)Oxqa)msJgqrp0j_Tg2P z`hsPl3>KMmCVNX3vMeeCp37pO)#4ySgH+csaCi*bVbP`%Q2|?;=+2oGFEdp{+E@Aw DrXq`% diff --git a/lisp/international/uni-mirrored.el b/lisp/international/uni-mirrored.el index 5129a93396d49357dc4a866151b8376c11009efd..006cf575591a146a5b0ce5121703c445e3979644 100644 GIT binary patch literal 10452 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 literal 7904 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 diff --git a/lisp/international/uni-name.el b/lisp/international/uni-name.el index 5b9e8323d213fdbac542003976d4a434feb5c641..7fac18b278d1c25b3c88f1581417355d3ad52fd0 100644 GIT binary patch delta 3317 zcmaEUhI8!=&IwWz6L(aBct%vY{p`?05q9c zTn->sd^#ID$fDcj^cgjn1}aoy6_n%RqKy=` zcN#MO;sg7o#ewkFVxVIHRzy}j6pkyDVCK1QTei0>>73=NIYoNq`}se!C%`K@3^ zP8$*e2H^~-rs+Ro7!_#gab)LWV}o48n6o`1mXU`G9NDSqj5i_4)jpHapUZ^=-{CSp zXZwa?MjJM;@oy^`?+Q3mXeh{{?XSBS*%=2i=s>Pe#pY*pvDnFuXH=$V^e`^gCc)#A zFJ5VwzMz-UZ=n5HkM18j^Xo~@m(+D&J)${*k$*|C2~{(s95S>tGQ}u}(EO`}upgIo z(^>i%gGbW|uHd1Mcq$^EP@|earjI2_^>)t*j2V!|#-@pkA1RG=lI+G3j-+Q!ifn|m zP7D<+EsPCJ3>1tNwrfuYHniBGLA-t86vlRVr4UP6$YSvwT24enFkZFp1R@--W+c7a Kd!{koJ`VuZWrL6a delta 1853 zcmZ2`gY)?r&IwX%ItoSxh6WR*Tqefr@`vVSCg-Q5x+In)>XlTKZ0z}`#%Qp)S3SG~ zNIhS#D=TcEfB`25UKZZ$cUFia9YYFJF*QUs>tD0c5XWKJ!(Q<;&Ml^e(4$ea0A8uo2rG3>Y<-tdWev zW;s5w?e~osnfQVBJaJ?^#HdS>N!uA+7&!&wNYVoddgZvdXd?wn14Bb2e2xRjE#DQ& z$SH@_4tO+9{}#un;DA*PA>(24K(n?_i)ZBF0tUs>Ovam_pl{4(^yg9{U@SWh0B*%^Zfs)Mc(u5luimFEKY&K{;9@IU})1p)4^+p(HUWCsk8HiDP^29L59Z0h2Oj+yDRo diff --git a/lisp/international/uni-numeric.el b/lisp/international/uni-numeric.el index 278ad683fe43bc553af50d891ccdedad6f22f5d2..d16e8c00870fdfae6023e3fd220ccd50152b2287 100644 GIT binary patch literal 3688 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 diff --git a/lisp/international/uni-old-name.el b/lisp/international/uni-old-name.el index 2e28349240897050b13126e13bcaaff56b7dfd96..4e704e5cdd0676d3c291521d3062d34fa444e1ce 100644 GIT binary patch delta 912 zcmeC0&iG~~;{>UR3NDPr6H|0IF7Or-&dbbEK*N(0`CTU)aO!KFnZ|r(s-WkQ%}VG> z(D|F2gzFiZf#ytR68#9KL1uhllp1RblK*!%12pg?Y&q6;Zu(qfe=5N8Jd_F5YULKkCdQLVn70u^ZA9v zkL)?T@K_f{I)Nr7i_LqrYFKC;P=vf&Pe=hx<@0mcQgrhYb5kcTG!@%?Re!5A0DkH^ AL;wH) delta 512 zcmaDeld)?$;{+)-9R(u;LxYJ@E)(N*`9t$Elk-zjT@p(Y^-3yAHuiW6aT+K<;pByi zdXt3RCdUbL^TP!plAAk(>lqmhCUc2?1d>2?lNC5sCkKjETB9k1nMDk}*-`ueE2F_? z7Fksw1vFJ|vzO93MtK58ZZ=mr%34oA5xV`c=mJo_a$H=rk%F0_i3w>2PF|#_Fqv1I hgB_|35_bNZ7i!nAkm@!ZP9x1h2-W$Ur3^1g0{})NXM_L% diff --git a/lisp/international/uni-titlecase.el b/lisp/international/uni-titlecase.el index 729a469d10388417b341c0590d0748b46b0fff0b..b8098c818763cc523766c49600b26ea951afdc67 100644 GIT binary patch delta 1322 zcmaE=wM%P))InXJnjg&Zq|_Wm%ONP0!7l9LS|;Kf*@#>_j zldn#>I`!%_C561q9BSfN1?9N7Xd?v^14}bZbF-;y8QcOT#>!W7_cAarJlePz;w2@< z%^TQR7$%?=e-4V!9(8CdMpOS!aagT5-C6p@T$Y6SBcT_)yxKlS2LS{xCMyY zCNJR&nEaW~80Z=`{wt}JFcsC~3=3j(d@!)^n<79sHMXt1{VDR$L z@W|-cmGKD(pz!%QTCR4ZmzFN{&5}czeQQYCpF=L|5frcn(Sr3Ms;^o?Z>w_XX7&3N zkzdTG^N;c<|2V&te*%HNwqOJp(-KO5zvZSG$%>3RZy_2i>m8ul{-kuH&EJtRTm%};jXcS^WJkUfWR(l7EHXBRyj zD`G6iiLeoGJYF8WydpeI;#~+e*@le0nQEpfilWC1#sPw)sNs;o&|GU|M~!GV;jE!3 zQKV{nafWTf5Cd_L!b#puxG~U^`h!a+s5*yH=A@{QS-7KaoNznsj)_n^Chjw6rEv!tl}FsoD2g2|6-N>^_u>AY13a1O<-3A({}7AHo#^# z9cm;`ox#Hk?S!LKOktl|4WQqKoxs-H9k!MtnCxxarqOI(R2iAoG&!y_hIB*rrYu?0 qungFj(1BEngE$UiT_?e@A!vpflZuh&bxmUINfqNcLlwGTzxo^Cjhzbs diff --git a/lisp/international/uni-uppercase.el b/lisp/international/uni-uppercase.el index 0714b14794f38aa93bc14c8d661f20ae2c52a0e4..899276eb7253f308cbd481036771465c1d1aad64 100644 GIT binary patch delta 1341 zcmaE;wM}b+)InXJnjg&Zq|_Wm%ONP0!7lypc_7@&-od$)6Yx0L3>k z?VOy&3}R`q$g?oIo|_3&pgp;qMGPp^%hC%ZrC6sagim zVsv~pvw`8&%qAdi0phmF3-|&izvnXsx<-kA%jB#4PS{*Tiba^NholNKLlYBXTpU5w zGzoV(FyK1{0-1rKGWoWEv=X+^K^6llXBS*dX;{E*M>ZPD#tbJ+MfEttf*9R6HRE#@ jiX1Kdk75y~*TIfg!K$dVpdhszX$ieB zt)Yq1w+SM%m`P^tXHe!rW+}4_fx5pZ1nS1dMxDUTp7QRmq5uW2e}D3cun@%NtCZFi zu9`@r0a?sHkje538Lgkq+9|G>^3q~Fil*o zwd|l4Z6|DH6vgwDy#r_11`N><6%V^r2&0-x1 zHewPV1f!ZnS&RZ*@3?k(CY|$O6BG0to;XRFnwV6*~pXxQB&y1bG)?2LRx*VA7XxO1qZ=O>bo>dev zsxq2%P4<>7QBklA*d0@WkdK2X4q{!W!SOz*hZ&uU5$9D!U@UPN<2g+gS~#@&8@?!> A-2eap diff --git a/lisp/loadup.el b/lisp/loadup.el index 4c677523689..792827dd913 100644 --- a/lisp/loadup.el +++ b/lisp/loadup.el @@ -123,11 +123,11 @@ ;; multilingual text. (load "international/mule-cmds") (load "case-table") -(load "international/characters") -(load "composite") ;; This file doesn't exist when building a development version of Emacs ;; from the repository. It is generated just after temacs is built. (load "international/charprop.el" t) +(load "international/characters") +(load "composite") ;; Load language-specific files. (load "language/chinese") diff --git a/src/ChangeLog b/src/ChangeLog index 78fca60ca28..1a56298ee20 100644 --- a/src/ChangeLog +++ b/src/ChangeLog @@ -1,3 +1,45 @@ +2011-07-06 Kenichi Handa + + * character.h (unicode_category_t): New enum type. + + * chartab.c (uniprop_decoder_t, uniprop_encoder_t): New types. + (Qchar_code_property_table): New variable. + (UNIPROP_TABLE_P, UNIPROP_GET_DECODER) + (UNIPROP_COMPRESSED_FORM_P): New macros. + (char_table_ascii): Uncompress the compressed values. + (sub_char_table_ref): New arg is_uniprop. Callers changed. + Uncompress the compressed values. + (sub_char_table_ref_and_range): Likewise. + (char_table_ref_and_range): Uncompress the compressed values. + (sub_char_table_set): New arg is_uniprop. Callers changed. + Uncompress the compressed values. + (sub_char_table_set_range): Args changed. Callers changed. + (char_table_set_range): Adjuted for the above change. + (map_sub_char_table): Delete args default_val and parent. Add arg + top. Give decoded values to a Lisp function. + (map_char_table): Adjusted for the above change. Give decoded + values to a Lisp function. Gcpro more variables. + (uniprop_table_uncompress) + (uniprop_decode_value_run_length): New functions. + (uniprop_decoder, uniprop_decoder_count): New variables. + (uniprop_get_decoder, uniprop_encode_value_character) + (uniprop_encode_value_run_length, uniprop_encode_value_numeric): + New functions. + (uniprop_encoder, uniprop_encoder_count): New variables. + (uniprop_get_encoder, uniprop_table) + (Funicode_property_table_internal, Fget_unicode_property_internal) + (Fput_unicode_property_internal): New functions. + (syms_of_chartab): DEFSYM Qchar_code_property_table, defsubr + Sunicode_property_table_internal, Sget_unicode_property_internal, + and Sput_unicode_property_internal. Defvar_lisp + char-code-property-alist. + + * composite.c (CHAR_COMPOSABLE_P): Adjusted for the change of + Vunicode_category_table. + + * font.c (font_range): Adjusted for the change of + Vunicode_category_table. + 2011-06-22 Paul Eggert Fixes for GLYPH_DEBUG found by GCC 4.6.0 static checking. diff --git a/src/character.h b/src/character.h index 9a45e7f0033..d8e77c50953 100644 --- a/src/character.h +++ b/src/character.h @@ -597,6 +597,45 @@ along with GNU Emacs. If not, see . */ : (c) <= 0xDFFF ? 2 \ : 0) +/* Data type for Unicode general category. + + The order of members must be in sync with the 8th element of the + member of unidata-prop-alist (in admin/unidata/unidata-getn.el) for + Unicode character property `general-category'. */ + +typedef enum { + UNICODE_CATEGORY_UNKNOWN = 0, + UNICODE_CATEGORY_Lu, + UNICODE_CATEGORY_Ll, + UNICODE_CATEGORY_Lt, + UNICODE_CATEGORY_Lm, + UNICODE_CATEGORY_Lo, + UNICODE_CATEGORY_Mn, + UNICODE_CATEGORY_Mc, + UNICODE_CATEGORY_Me, + UNICODE_CATEGORY_Nd, + UNICODE_CATEGORY_Nl, + UNICODE_CATEGORY_No, + UNICODE_CATEGORY_Pc, + UNICODE_CATEGORY_Pd, + UNICODE_CATEGORY_Ps, + UNICODE_CATEGORY_Pe, + UNICODE_CATEGORY_Pi, + UNICODE_CATEGORY_Pf, + UNICODE_CATEGORY_Po, + UNICODE_CATEGORY_Sm, + UNICODE_CATEGORY_Sc, + UNICODE_CATEGORY_Sk, + UNICODE_CATEGORY_So, + UNICODE_CATEGORY_Zs, + UNICODE_CATEGORY_Zl, + UNICODE_CATEGORY_Zp, + UNICODE_CATEGORY_Cc, + UNICODE_CATEGORY_Cf, + UNICODE_CATEGORY_Cs, + UNICODE_CATEGORY_Co, + UNICODE_CATEGORY_Cn +} unicode_category_t; extern int char_resolve_modifier_mask (int); extern int char_string (unsigned, unsigned char *); diff --git a/src/chartab.c b/src/chartab.c index ed5b238646e..4a9a76bdd60 100644 --- a/src/chartab.c +++ b/src/chartab.c @@ -53,7 +53,38 @@ static const int chartab_bits[4] = #define CHARTAB_IDX(c, depth, min_char) \ (((c) - (min_char)) >> chartab_bits[(depth)]) + +/* Preamble for uniprop (Unicode character property) tables. See the + comment of "Unicode character property tables". */ + +/* Purpose of uniprop tables. */ +static Lisp_Object Qchar_code_property_table; + +/* Types of decoder and encoder functions for uniprop values. */ +typedef Lisp_Object (*uniprop_decoder_t) (Lisp_Object, Lisp_Object); +typedef Lisp_Object (*uniprop_encoder_t) (Lisp_Object, Lisp_Object); + +static Lisp_Object uniprop_table_uncompress (Lisp_Object, int); +static uniprop_decoder_t uniprop_get_decoder (Lisp_Object); + +/* 1 iff TABLE is a uniprop table. */ +#define UNIPROP_TABLE_P(TABLE) \ + (EQ (XCHAR_TABLE (TABLE)->purpose, Qchar_code_property_table) \ + && CHAR_TABLE_EXTRA_SLOTS (XCHAR_TABLE (TABLE)) == 5) + +/* Return a decoder for values in the uniprop table TABLE. */ +#define UNIPROP_GET_DECODER(TABLE) \ + (UNIPROP_TABLE_P (TABLE) ? uniprop_get_decoder (TABLE) : NULL) +/* Nonzero iff OBJ is a string representing uniprop values of 128 + succeeding characters (the bottom level of a char-table) by a + compressed format. We are sure that no property value has a string + starting with '\001' nor '\002'. */ +#define UNIPROP_COMPRESSED_FORM_P(OBJ) \ + (STRINGP (OBJ) && SCHARS (OBJ) > 0 \ + && ((SREF (OBJ, 0) == 1 || (SREF (OBJ, 0) == 2)))) + + 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. @@ -107,7 +138,7 @@ make_sub_char_table (int depth, int min_char, Lisp_Object defalt) static Lisp_Object char_table_ascii (Lisp_Object table) { - Lisp_Object sub; + Lisp_Object sub, val; sub = XCHAR_TABLE (table)->contents[0]; if (! SUB_CHAR_TABLE_P (sub)) @@ -115,7 +146,10 @@ char_table_ascii (Lisp_Object table) sub = XSUB_CHAR_TABLE (sub)->contents[0]; if (! SUB_CHAR_TABLE_P (sub)) return sub; - return XSUB_CHAR_TABLE (sub)->contents[0]; + val = XSUB_CHAR_TABLE (sub)->contents[0]; + if (UNIPROP_TABLE_P (table) && UNIPROP_COMPRESSED_FORM_P (val)) + val = uniprop_table_uncompress (sub, 0); + return val; } static Lisp_Object @@ -169,16 +203,19 @@ copy_char_table (Lisp_Object table) } static Lisp_Object -sub_char_table_ref (Lisp_Object table, int c) +sub_char_table_ref (Lisp_Object table, int c, int is_uniprop) { 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; + int idx = CHARTAB_IDX (c, depth, min_char); - val = tbl->contents[CHARTAB_IDX (c, depth, min_char)]; + val = tbl->contents[idx]; + if (is_uniprop && UNIPROP_COMPRESSED_FORM_P (val)) + val = uniprop_table_uncompress (table, idx); if (SUB_CHAR_TABLE_P (val)) - val = sub_char_table_ref (val, c); + val = sub_char_table_ref (val, c, is_uniprop); return val; } @@ -198,7 +235,7 @@ char_table_ref (Lisp_Object table, int c) { val = tbl->contents[CHARTAB_IDX (c, 0, 0)]; if (SUB_CHAR_TABLE_P (val)) - val = sub_char_table_ref (val, c); + val = sub_char_table_ref (val, c, UNIPROP_TABLE_P (table)); } if (NILP (val)) { @@ -210,7 +247,8 @@ char_table_ref (Lisp_Object table, int c) } static Lisp_Object -sub_char_table_ref_and_range (Lisp_Object table, int c, int *from, int *to, Lisp_Object defalt) +sub_char_table_ref_and_range (Lisp_Object table, int c, int *from, int *to, + Lisp_Object defalt, int is_uniprop) { struct Lisp_Sub_Char_Table *tbl = XSUB_CHAR_TABLE (table); int depth = XINT (tbl->depth); @@ -219,8 +257,10 @@ sub_char_table_ref_and_range (Lisp_Object table, int c, int *from, int *to, Lisp Lisp_Object val; val = tbl->contents[chartab_idx]; + if (is_uniprop && UNIPROP_COMPRESSED_FORM_P (val)) + val = uniprop_table_uncompress (table, chartab_idx); if (SUB_CHAR_TABLE_P (val)) - val = sub_char_table_ref_and_range (val, c, from, to, defalt); + val = sub_char_table_ref_and_range (val, c, from, to, defalt, is_uniprop); else if (NILP (val)) val = defalt; @@ -232,8 +272,11 @@ sub_char_table_ref_and_range (Lisp_Object table, int c, int *from, int *to, Lisp c = min_char + idx * chartab_chars[depth] - 1; idx--; this_val = tbl->contents[idx]; + if (is_uniprop && UNIPROP_COMPRESSED_FORM_P (this_val)) + this_val = uniprop_table_uncompress (table, idx); if (SUB_CHAR_TABLE_P (this_val)) - this_val = sub_char_table_ref_and_range (this_val, c, from, to, defalt); + this_val = sub_char_table_ref_and_range (this_val, c, from, to, defalt, + is_uniprop); else if (NILP (this_val)) this_val = defalt; @@ -251,8 +294,11 @@ sub_char_table_ref_and_range (Lisp_Object table, int c, int *from, int *to, Lisp chartab_idx++; this_val = tbl->contents[chartab_idx]; + if (is_uniprop && UNIPROP_COMPRESSED_FORM_P (this_val)) + this_val = uniprop_table_uncompress (table, chartab_idx); if (SUB_CHAR_TABLE_P (this_val)) - this_val = sub_char_table_ref_and_range (this_val, c, from, to, defalt); + this_val = sub_char_table_ref_and_range (this_val, c, from, to, defalt, + is_uniprop); else if (NILP (this_val)) this_val = defalt; if (! EQ (this_val, val)) @@ -277,17 +323,20 @@ char_table_ref_and_range (Lisp_Object table, int c, int *from, int *to) struct Lisp_Char_Table *tbl = XCHAR_TABLE (table); int chartab_idx = CHARTAB_IDX (c, 0, 0), idx; Lisp_Object val; + int is_uniprop = UNIPROP_TABLE_P (table); val = tbl->contents[chartab_idx]; if (*from < 0) *from = 0; if (*to < 0) *to = MAX_CHAR; + if (is_uniprop && UNIPROP_COMPRESSED_FORM_P (val)) + val = uniprop_table_uncompress (table, chartab_idx); if (SUB_CHAR_TABLE_P (val)) - val = sub_char_table_ref_and_range (val, c, from, to, tbl->defalt); + val = sub_char_table_ref_and_range (val, c, from, to, tbl->defalt, + is_uniprop); else if (NILP (val)) val = tbl->defalt; - idx = chartab_idx; while (*from < idx * chartab_chars[0]) { @@ -296,9 +345,11 @@ char_table_ref_and_range (Lisp_Object table, int c, int *from, int *to) c = idx * chartab_chars[0] - 1; idx--; this_val = tbl->contents[idx]; + if (is_uniprop && UNIPROP_COMPRESSED_FORM_P (this_val)) + this_val = uniprop_table_uncompress (table, idx); if (SUB_CHAR_TABLE_P (this_val)) this_val = sub_char_table_ref_and_range (this_val, c, from, to, - tbl->defalt); + tbl->defalt, is_uniprop); else if (NILP (this_val)) this_val = tbl->defalt; @@ -315,9 +366,11 @@ char_table_ref_and_range (Lisp_Object table, int c, int *from, int *to) chartab_idx++; c = chartab_idx * chartab_chars[0]; this_val = tbl->contents[chartab_idx]; + if (is_uniprop && UNIPROP_COMPRESSED_FORM_P (this_val)) + this_val = uniprop_table_uncompress (table, chartab_idx); if (SUB_CHAR_TABLE_P (this_val)) this_val = sub_char_table_ref_and_range (this_val, c, from, to, - tbl->defalt); + tbl->defalt, is_uniprop); else if (NILP (this_val)) this_val = tbl->defalt; if (! EQ (this_val, val)) @@ -332,7 +385,7 @@ char_table_ref_and_range (Lisp_Object table, int c, int *from, int *to) static void -sub_char_table_set (Lisp_Object table, int c, Lisp_Object val) +sub_char_table_set (Lisp_Object table, int c, Lisp_Object val, int is_uniprop) { struct Lisp_Sub_Char_Table *tbl = XSUB_CHAR_TABLE (table); int depth = XINT ((tbl)->depth); @@ -347,11 +400,17 @@ sub_char_table_set (Lisp_Object table, int c, Lisp_Object val) 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; + if (is_uniprop && UNIPROP_COMPRESSED_FORM_P (sub)) + sub = uniprop_table_uncompress (table, i); + else + { + 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); + sub_char_table_set (sub, c, val, is_uniprop); } } @@ -376,7 +435,7 @@ char_table_set (Lisp_Object table, int c, Lisp_Object val) sub = make_sub_char_table (1, i * chartab_chars[0], sub); tbl->contents[i] = sub; } - sub_char_table_set (sub, c, val); + sub_char_table_set (sub, c, val, UNIPROP_TABLE_P (table)); if (ASCII_CHAR_P (c)) tbl->ascii = char_table_ascii (table); } @@ -384,30 +443,40 @@ char_table_set (Lisp_Object table, int c, Lisp_Object val) } static void -sub_char_table_set_range (Lisp_Object *table, int depth, int min_char, int from, int to, Lisp_Object val) +sub_char_table_set_range (Lisp_Object table, int from, int to, Lisp_Object val, + int is_uniprop) { - int max_char = min_char + chartab_chars[depth] - 1; - - if (depth == 3 || (from <= min_char && to >= max_char)) - *table = val; - else + struct Lisp_Sub_Char_Table *tbl = XSUB_CHAR_TABLE (table); + int depth = XINT ((tbl)->depth); + int min_char = XINT ((tbl)->min_char); + int chars_in_block = chartab_chars[depth]; + int i, c, lim = chartab_size[depth]; + + if (from < min_char) + from = min_char; + i = CHARTAB_IDX (from, depth, min_char); + c = min_char + chars_in_block * i; + for (; i <= lim; i++, c += chars_in_block) { - int i; - unsigned 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 (j++; 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); + if (c > to) + break; + if (from <= c && c + chars_in_block - 1 <= to) + tbl->contents[i] = val; + else + { + Lisp_Object sub = tbl->contents[i]; + if (! SUB_CHAR_TABLE_P (sub)) + { + if (is_uniprop && UNIPROP_COMPRESSED_FORM_P (sub)) + sub = uniprop_table_uncompress (table, i); + else + { + sub = make_sub_char_table (depth + 1, c, sub); + tbl->contents[i] = sub; + } + } + sub_char_table_set_range (sub, from, to, val, is_uniprop); + } } } @@ -417,16 +486,33 @@ char_table_set_range (Lisp_Object table, int from, int to, Lisp_Object val) { struct Lisp_Char_Table *tbl = XCHAR_TABLE (table); Lisp_Object *contents = tbl->contents; - int i; if (from == to) char_table_set (table, from, val); else { - unsigned lim = to / chartab_chars[0] + 1; - for (i = CHARTAB_IDX (from, 0, 0); i < lim; i++) - sub_char_table_set_range (contents + i, 0, i * chartab_chars[0], - from, to, val); + int is_uniprop = UNIPROP_TABLE_P (table); + int lim = CHARTAB_IDX (to, 0, 0); + int i, c; + + for (i = CHARTAB_IDX (from, 0, 0), c = 0; i <= lim; + i++, c += chartab_chars[0]) + { + if (c > to) + break; + if (from <= c && c + chartab_chars[0] - 1 <= to) + tbl->contents[i] = val; + else + { + Lisp_Object 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_range (sub, from, to, val, is_uniprop); + } + } if (ASCII_CHAR_P (from)) tbl->ascii = char_table_ascii (table); } @@ -504,6 +590,8 @@ DEFUN ("set-char-table-extra-slot", Fset_char_table_extra_slot, (Lisp_Object char_table, Lisp_Object n, Lisp_Object value) { CHECK_CHAR_TABLE (char_table); + if (EQ (XCHAR_TABLE (char_table)->purpose, Qchar_code_property_table)) + error ("Can't change extra-slot of char-code-property-table"); CHECK_NUMBER (n); if (XINT (n) < 0 || XINT (n) >= CHAR_TABLE_EXTRA_SLOTS (XCHAR_TABLE (char_table))) @@ -532,8 +620,9 @@ a cons of character codes (for characters in the range), or a character code. * CHECK_CHARACTER_CAR (range); CHECK_CHARACTER_CDR (range); - val = char_table_ref_and_range (char_table, XFASTINT (XCAR (range)), - &from, &to); + from = XFASTINT (XCAR (range)); + to = XFASTINT (XCDR (range)); + val = char_table_ref_and_range (char_table, from, &from, &to); /* Not yet implemented. */ } else @@ -655,8 +744,7 @@ equivalent and can be merged. It defaults to `equal'. */) /* 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 + characters, VAL is a value of FROM in TABLE, TOP is the top char-table. ARG is passed to C_FUNCTION when that is called. @@ -669,7 +757,7 @@ equivalent and can be merged. It defaults to `equal'. */) static Lisp_Object map_sub_char_table (void (*c_function) (Lisp_Object, Lisp_Object, Lisp_Object), Lisp_Object function, Lisp_Object table, Lisp_Object arg, Lisp_Object val, - Lisp_Object range, Lisp_Object default_val, Lisp_Object parent) + Lisp_Object range, Lisp_Object top) { /* Pointer to the elements of TABLE. */ Lisp_Object *contents; @@ -681,6 +769,8 @@ map_sub_char_table (void (*c_function) (Lisp_Object, Lisp_Object, Lisp_Object), int chars_in_block; int from = XINT (XCAR (range)), to = XINT (XCDR (range)); int i, c; + int is_uniprop = UNIPROP_TABLE_P (top); + uniprop_decoder_t decoder = UNIPROP_GET_DECODER (top); if (SUB_CHAR_TABLE_P (table)) { @@ -710,28 +800,33 @@ map_sub_char_table (void (*c_function) (Lisp_Object, Lisp_Object, Lisp_Object), for (c = min_char + chars_in_block * i; c <= max_char; i++, c += chars_in_block) { - Lisp_Object this = contents[i]; + Lisp_Object this = (SUB_CHAR_TABLE_P (table) + ? XSUB_CHAR_TABLE (table)->contents[i] + : XCHAR_TABLE (table)->contents[i]); int nextc = c + chars_in_block; + if (is_uniprop && UNIPROP_COMPRESSED_FORM_P (this)) + this = uniprop_table_uncompress (table, i); 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); + val, range, top); } else { if (NILP (this)) - this = default_val; + this = XCHAR_TABLE (top)->defalt; if (!EQ (val, this)) { int different_value = 1; if (NILP (val)) { - if (! NILP (parent)) + if (! NILP (XCHAR_TABLE (top)->parent)) { + Lisp_Object parent = XCHAR_TABLE (top)->parent; Lisp_Object temp = XCHAR_TABLE (parent)->parent; /* This is to get a value of FROM in PARENT @@ -742,8 +837,7 @@ map_sub_char_table (void (*c_function) (Lisp_Object, Lisp_Object, Lisp_Object), 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); + parent); if (EQ (val, this)) different_value = 0; } @@ -756,14 +850,22 @@ map_sub_char_table (void (*c_function) (Lisp_Object, Lisp_Object, Lisp_Object), if (c_function) (*c_function) (arg, XCAR (range), val); else - call2 (function, XCAR (range), val); + { + if (decoder) + val = decoder (top, val); + call2 (function, XCAR (range), val); + } } else { if (c_function) (*c_function) (arg, range, val); else - call2 (function, range, val); + { + if (decoder) + val = decoder (top, val); + call2 (function, range, val); + } } } val = this; @@ -783,35 +885,39 @@ map_sub_char_table (void (*c_function) (Lisp_Object, Lisp_Object, Lisp_Object), ARG is passed to C_FUNCTION when that is called. */ void -map_char_table (void (*c_function) (Lisp_Object, Lisp_Object, Lisp_Object), Lisp_Object function, Lisp_Object table, Lisp_Object arg) +map_char_table (void (*c_function) (Lisp_Object, Lisp_Object, Lisp_Object), + Lisp_Object function, Lisp_Object table, Lisp_Object arg) { - Lisp_Object range, val; - struct gcpro gcpro1, gcpro2, gcpro3; + Lisp_Object range, val, parent; + struct gcpro gcpro1, gcpro2, gcpro3, gcpro4; + uniprop_decoder_t decoder = UNIPROP_GET_DECODER (table); range = Fcons (make_number (0), make_number (MAX_CHAR)); - GCPRO3 (table, arg, range); + parent = XCHAR_TABLE (table)->parent; + + GCPRO4 (table, arg, range, parent); 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); + table); + /* 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; + Lisp_Object temp; int from = XINT (XCAR (range)); + parent = XCHAR_TABLE (table)->parent; + 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; val = map_sub_char_table (c_function, function, parent, arg, val, range, - XCHAR_TABLE (parent)->defalt, - XCHAR_TABLE (parent)->parent); + parent); table = parent; } @@ -822,14 +928,22 @@ map_char_table (void (*c_function) (Lisp_Object, Lisp_Object, Lisp_Object), Lisp if (c_function) (*c_function) (arg, XCAR (range), val); else - call2 (function, XCAR (range), val); + { + if (decoder) + val = decoder (table, val); + call2 (function, XCAR (range), val); + } } else { if (c_function) (*c_function) (arg, range, val); else - call2 (function, range, val); + { + if (decoder) + val = decoder (table, val); + call2 (function, range, val); + } } } @@ -983,10 +1097,316 @@ map_char_table_for_charset (void (*c_function) (Lisp_Object, Lisp_Object), UNGCPRO; } + +/* Unicode character property tables. + + This section provides a convenient and efficient way to get a + Unicode character property from C code (from Lisp, you must use + get-char-code-property). + + The typical usage is to get a char-table for a specific property at + a proper initialization time as this: + + Lisp_Object bidi_class_table = uniprop_table (intern ("bidi-class")); + + and get a property value for character CH as this: + + Lisp_Object bidi_class = CHAR_TABLE_REF (CH, bidi_class_table); + + In this case, what you actually get is an index number to the + vector of property values (symbols nil, L, R, etc). + + A table for Unicode character property has these characteristics: + + o The purpose is `char-code-property-table', which implies that the + table has 5 extra slots. + + o The second extra slot is a Lisp function, an index (integer) to + the array uniprop_decoder[], or nil. If it is a Lisp function, we + can't use such a table from C (at the moment). If it is nil, it + means that we don't have to decode values. + + o The third extra slot is a Lisp function, an index (integer) to + the array uniprop_enncoder[], or nil. If it is a Lisp function, we + can't use such a table from C (at the moment). If it is nil, it + means that we don't have to encode values. */ + + +/* Uncompress the IDXth element of sub-char-table TABLE. */ + +static Lisp_Object +uniprop_table_uncompress (Lisp_Object table, int idx) +{ + Lisp_Object val = XSUB_CHAR_TABLE (table)->contents[idx]; + int min_char = (XINT (XSUB_CHAR_TABLE (table)->min_char) + + chartab_chars[2] * idx); + Lisp_Object sub = make_sub_char_table (3, min_char, Qnil); + struct Lisp_Sub_Char_Table *subtbl = XSUB_CHAR_TABLE (sub); + const unsigned char *p, *pend; + int i; + + XSUB_CHAR_TABLE (table)->contents[idx] = sub; + p = SDATA (val), pend = p + SBYTES (val); + if (*p == 1) + { + /* SIMPLE TABLE */ + p++; + idx = STRING_CHAR_ADVANCE (p); + while (p < pend && idx < chartab_chars[2]) + { + int v = STRING_CHAR_ADVANCE (p); + subtbl->contents[idx++] = v > 0 ? make_number (v) : Qnil; + } + } + else if (*p == 2) + { + /* RUN-LENGTH TABLE */ + p++; + for (idx = 0; p < pend; ) + { + int v = STRING_CHAR_ADVANCE (p); + int count = 1; + int len; + + if (p < pend) + { + count = STRING_CHAR_AND_LENGTH (p, len); + if (count < 128) + count = 1; + else + { + count -= 128; + p += len; + } + } + while (count-- > 0) + subtbl->contents[idx++] = make_number (v); + } + } +/* It seems that we don't need this function because C code won't need + to get a property that is compressed in this form. */ +#if 0 + else if (*p == 0) + { + /* WORD-LIST TABLE */ + } +#endif + return sub; +} + + +/* Decode VALUE as an elemnet of char-table TABLE. */ + +static Lisp_Object +uniprop_decode_value_run_length (Lisp_Object table, Lisp_Object value) +{ + if (VECTORP (XCHAR_TABLE (table)->extras[4])) + { + Lisp_Object valvec = XCHAR_TABLE (table)->extras[4]; + + if (XINT (value) >= 0 && XINT (value) < ASIZE (valvec)) + value = AREF (valvec, XINT (value)); + } + return value; +} + +static uniprop_decoder_t uniprop_decoder [] = + { uniprop_decode_value_run_length }; + +static int uniprop_decoder_count + = (sizeof uniprop_decoder) / sizeof (uniprop_decoder[0]); + + +/* Return the decoder of char-table TABLE or nil if none. */ + +static uniprop_decoder_t +uniprop_get_decoder (Lisp_Object table) +{ + int i; + + if (! INTEGERP (XCHAR_TABLE (table)->extras[1])) + return NULL; + i = XINT (XCHAR_TABLE (table)->extras[1]); + if (i < 0 || i >= uniprop_decoder_count) + return NULL; + return uniprop_decoder[i]; +} + + +/* Encode VALUE as an element of char-table TABLE which contains + characters as elements. */ + +static Lisp_Object +uniprop_encode_value_character (Lisp_Object table, Lisp_Object value) +{ + if (! NILP (value) && ! CHARACTERP (value)) + wrong_type_argument (Qintegerp, value); + return value; +} + + +/* Encode VALUE as an element of char-table TABLE which adopts RUN-LENGTH + compression. */ + +static Lisp_Object +uniprop_encode_value_run_length (Lisp_Object table, Lisp_Object value) +{ + Lisp_Object *value_table = XVECTOR (XCHAR_TABLE (table)->extras[4])->contents; + int i, size = ASIZE (XCHAR_TABLE (table)->extras[4]); + + for (i = 0; i < size; i++) + if (EQ (value, value_table[i])) + break; + if (i == size) + wrong_type_argument (build_string ("Unicode property value"), value); + return make_number (i); +} + + +/* Encode VALUE as an element of char-table TABLE which adopts RUN-LENGTH + compression and contains numbers as elements . */ + +static Lisp_Object +uniprop_encode_value_numeric (Lisp_Object table, Lisp_Object value) +{ + Lisp_Object *value_table = XVECTOR (XCHAR_TABLE (table)->extras[4])->contents; + int i, size = ASIZE (XCHAR_TABLE (table)->extras[4]); + + CHECK_NUMBER (value); + for (i = 0; i < size; i++) + if (EQ (value, value_table[i])) + break; + value = make_number (i); + if (i == size) + { + Lisp_Object args[2]; + + args[0] = XCHAR_TABLE (table)->extras[4]; + args[1] = Fmake_vector (make_number (1), value); + XCHAR_TABLE (table)->extras[4] = Fvconcat (2, args); + } + return make_number (i); +} + +static uniprop_encoder_t uniprop_encoder[] = + { uniprop_encode_value_character, + uniprop_encode_value_run_length, + uniprop_encode_value_numeric }; + +static int uniprop_encoder_count + = (sizeof uniprop_encoder) / sizeof (uniprop_encoder[0]); + + +/* Return the encoder of char-table TABLE or nil if none. */ + +static uniprop_decoder_t +uniprop_get_encoder (Lisp_Object table) +{ + int i; + + if (! INTEGERP (XCHAR_TABLE (table)->extras[2])) + return NULL; + i = XINT (XCHAR_TABLE (table)->extras[2]); + if (i < 0 || i >= uniprop_encoder_count) + return NULL; + return uniprop_encoder[i]; +} + +/* Return a char-table for Unicode character property PROP. This + function may load a Lisp file and thus may cause + garbage-collection. */ + +Lisp_Object +uniprop_table (Lisp_Object prop) +{ + Lisp_Object val, table, result; + + val = Fassq (prop, Vchar_code_property_alist); + if (! CONSP (val)) + return Qnil; + table = XCDR (val); + if (STRINGP (table)) + { + struct gcpro gcpro1; + GCPRO1 (val); + result = Fload (concat2 (build_string ("international/"), table), + Qt, Qt, Qt, Qt); + UNGCPRO; + if (NILP (result)) + return Qnil; + table = XCDR (val); + } + if (! CHAR_TABLE_P (table) + || ! UNIPROP_TABLE_P (table)) + return Qnil; + val = XCHAR_TABLE (table)->extras[1]; + if (INTEGERP (val) + ? (XINT (val) < 0 || XINT (val) >= uniprop_decoder_count) + : ! NILP (val)) + return Qnil; + /* Prepare ASCII values in advance for CHAR_TABLE_REF. */ + XCHAR_TABLE (table)->ascii = char_table_ascii (table); + return table; +} + +DEFUN ("unicode-property-table-internal", Funicode_property_table_internal, + Sunicode_property_table_internal, 1, 1, 0, + doc: /* Return a char-table for Unicode character property PROP. +Use `get-unicode-property-internal' and +`put-unicode-property-internal' instead of `aref' and `aset' to get +and put an element value. */) + (Lisp_Object prop) +{ + Lisp_Object table = uniprop_table (prop); + + if (CHAR_TABLE_P (table)) + return table; + return Fcdr (Fassq (prop, Vchar_code_property_alist)); +} + +DEFUN ("get-unicode-property-internal", Fget_unicode_property_internal, + Sget_unicode_property_internal, 2, 2, 0, + doc: /* Return an element of CHAR-TABLE for character CH. +CHAR-TABLE must be what returned by `unicode-property-table-internal'. */) + (Lisp_Object char_table, Lisp_Object ch) +{ + Lisp_Object val; + uniprop_decoder_t decoder; + + CHECK_CHAR_TABLE (char_table); + CHECK_CHARACTER (ch); + if (! UNIPROP_TABLE_P (char_table)) + error ("Invalid Unicode property table"); + val = CHAR_TABLE_REF (char_table, XINT (ch)); + decoder = uniprop_get_decoder (char_table); + return (decoder ? decoder (char_table, val) : val); +} + +DEFUN ("put-unicode-property-internal", Fput_unicode_property_internal, + Sput_unicode_property_internal, 3, 3, 0, + doc: /* Set an element of CHAR-TABLE for character CH to VALUE. +CHAR-TABLE must be what returned by `unicode-property-table-internal'. */) + (Lisp_Object char_table, Lisp_Object ch, Lisp_Object value) +{ + uniprop_encoder_t encoder; + + CHECK_CHAR_TABLE (char_table); + CHECK_CHARACTER (ch); + if (! UNIPROP_TABLE_P (char_table)) + error ("Invalid Unicode property table"); + encoder = uniprop_get_encoder (char_table); + if (encoder) + value = encoder (char_table, value); + CHAR_TABLE_SET (char_table, XINT (ch), value); + return Qnil; +} + void syms_of_chartab (void) { + DEFSYM (Qchar_code_property_table, "char-code-property-table"); + defsubr (&Smake_char_table); defsubr (&Schar_table_parent); defsubr (&Schar_table_subtype); @@ -998,4 +1418,19 @@ syms_of_chartab (void) defsubr (&Sset_char_table_default); defsubr (&Soptimize_char_table); defsubr (&Smap_char_table); + defsubr (&Sunicode_property_table_internal); + defsubr (&Sget_unicode_property_internal); + defsubr (&Sput_unicode_property_internal); + + /* Each element has the form (PROP . TABLE). + PROP is a symbol representing a character property. + TABLE is a char-table containing the property value for each character. + TABLE may be a name of file to load to build a char-table. + This variable should be modified only through + `define-char-code-property'. */ + + DEFVAR_LISP ("char-code-property-alist", Vchar_code_property_alist, + doc: /* Alist of character property name vs char-table containing property values. +Internal use only. */); + Vchar_code_property_alist = Qnil; } diff --git a/src/composite.c b/src/composite.c index 796c5a58de6..7123b505e68 100644 --- a/src/composite.c +++ b/src/composite.c @@ -976,9 +976,8 @@ static int _work_char; ((C) > ' ' \ && ((C) == 0x200C || (C) == 0x200D \ || (_work_val = CHAR_TABLE_REF (Vunicode_category_table, (C)), \ - (SYMBOLP (_work_val) \ - && (_work_char = SDATA (SYMBOL_NAME (_work_val))[0]) != 'C' \ - && _work_char != 'Z')))) + (INTEGERP (_work_val) \ + && (XINT (_work_val) <= UNICODE_CATEGORY_So))))) /* Update cmp_it->stop_pos to the next position after CHARPOS (and BYTEPOS) where character composition may happen. If BYTEPOS is diff --git a/src/dispextern.h b/src/dispextern.h index 57fa09d3bfc..c0a67690a5c 100644 --- a/src/dispextern.h +++ b/src/dispextern.h @@ -1773,7 +1773,11 @@ extern int face_change_count; /* Data type for describing the bidirectional character types. The first 7 must be at the beginning, because they are the only values valid in the `bidi_type' member of `struct glyph'; we only reserve - 3 bits for it, so we cannot use there values larger than 7. */ + 3 bits for it, so we cannot use there values larger than 7. + + The order of members must be in sync with the 8th element of the + member of unidata-prop-alist (in admin/unidata/unidata-getn.el) for + Unicode character property `bidi-class'. */ typedef enum { UNKNOWN_BT = 0, STRONG_L, /* strong left-to-right */ diff --git a/src/font.c b/src/font.c index 14390335f3c..5aff20b1346 100644 --- a/src/font.c +++ b/src/font.c @@ -3739,8 +3739,9 @@ font_range (EMACS_INT pos, EMACS_INT *limit, struct window *w, struct face *face else FETCH_STRING_CHAR_ADVANCE_NO_CHECK (c, string, pos, pos_byte); category = CHAR_TABLE_REF (Vunicode_category_table, c); - if (EQ (category, QCf) - || CHAR_VARIATION_SELECTOR_P (c)) + if (INTEGERP (category) + && (XINT (category) == UNICODE_CATEGORY_Cf + || CHAR_VARIATION_SELECTOR_P (c))) continue; if (NILP (font_object)) { -- 2.39.2