Mercurial > hg > xemacs-beta
diff lisp/w3/css.el @ 82:6a378aca36af r20-0b91
Import from CVS: tag r20-0b91
author | cvs |
---|---|
date | Mon, 13 Aug 2007 09:07:36 +0200 |
parents | 0293115a14e9 |
children | 859a2309aef8 |
line wrap: on
line diff
--- a/lisp/w3/css.el Mon Aug 13 09:06:45 2007 +0200 +++ b/lisp/w3/css.el Mon Aug 13 09:07:36 2007 +0200 @@ -1,12 +1,12 @@ ;;; css.el -- Cascading Style Sheet parser ;; Author: wmperry -;; Created: 1996/12/26 16:49:58 -;; Version: 1.18 +;; Created: 1997/01/17 14:30:54 +;; Version: 1.25 ;; Keywords: ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;;; Copyright (c) 1996 by William M. Perry (wmperry@cs.indiana.edu) -;;; Copyright (c) 1996 Free Software Foundation, Inc. +;;; Copyright (c) 1996, 1997 Free Software Foundation, Inc. ;;; ;;; This file is not part of GNU Emacs, but the same permissions apply. ;;; @@ -38,46 +38,110 @@ (defconst css-properties '(;; Property name Inheritable? Type of data - [font-family nil string-list] - [font-style nil string] - [font-variant nil symbol-list] - [font-weight nil weight] - [font-size nil length] + ;; Base CSS level 1 properties: http://www.w3.org/pub/WWW/TR/REC-CSS1 + ;; Font properties, Section 5.2 + [font-family t string-list] + [font-style t symbol] + [font-variant t symbol] + [font-weight t weight] + [font-size t length] [font nil font] - [color nil color] - [background nil color] - [word-spacing nil length] ; CBI - [letter-spacing nil length] ; CBI - [text-decoration nil symbol-list] - [vertical-align nil symbol] ; CBI - [text-transform nil string] + + ;; Color and background properties, Section 5.3 + [color t color] + [background nil color-shorthand] + [background-color nil color] + [background-image nil url] ; NYI + [background-repeat nil symbol] ; CBI + [background-attachment nil symbol] ; CBI + [background-position nil symbol] ; CBI + + ;; Text properties, Section 5.4 + [word-spacing t length] ; CBI + [letter-spacing t length] ; CBI + [text-decoration t symbol-list] + [vertical-align nil symbol] + [text-transform t symbol] [text-align t symbol] [text-indent t length] ; NYI [line-height t length] ; CBI - [margin nil margin] - [margin-left nil margin] - [margin-right nil margin] - [margin-top nil margin] - [margin-bottom nil margin] - [padding nil padding] - [padding-left nil padding] - [padding-right nil padding] - [padding-top nil padding] - [padding-bottom nil padding] - [border nil border] + + ;; Box properties, Section 5.5 + [margin nil boundary-shorthand] + [margin-left nil length] + [margin-right nil length] + [margin-top nil length] + [margin-bottom nil length] + [padding nil boundary-shorthand] + [padding-left nil length] + [padding-right nil length] + [padding-top nil length] + [padding-bottom nil length] + [border nil border-shorthand] [border-left nil border] [border-right nil border] [border-top nil border] [border-bottom nil border] + [border-top-width nil nil] + [border-right-width nil nil] + [border-bottom-width nil nil] + [border-left-width nil nil] + [border-width nil boundary-shorthand] + [border-color nil color] + [border-style nil symbol] [width nil length] ; NYPI [height nil length] ; NYPI [float nil symbol] [clear nil symbol] + + ;; Classification properties, Section 5.6 [display nil symbol] - [list-style t symbol] ;!! can't specify 'inside|outside' + [list-style-type t symbol] + [list-style-image t url] + [list-style-position t symbol] + [list-style nil list-style] [white-space t symbol] - ;; These are for specifying speech properties + ;; These are for specifying speech properties (ACSS-style) + ;; http://www.w3.org/pub/WWW/Style/CSS/Speech/NOTE-ACSS + + ;; General audio properties, Section 3 + [volume t string] ; Needs its own type? + [pause-before nil time] + [pause-after nil time] + [pause nil pause] + [cue-before nil string] + [cue-after nil string] + [cue-during nil string] + [cue nil string] ; Needs its own type? + + ;; Spatial properties, Section 4 + [azimuth t angle] + [elevation t elevation] + + ;; Speech properties, Section 5 + [speed t string] + [voice-family t string-list] + [pitch t string] + [pitch-range t percentage] + [stress t percentage] + [richness t percentage] + [speak-punctuation t symbol] + [speak-date t symbol] + [speak-numeral t symbol] + [speak-time t symbol] + + ;; Proposed printing extensions + ;; http://www.w3.org/pub/WWW/Style/Group/WD-PRINT-961220 + ;; These apply only to pages (@page directive) + [size nil symbol] + [orientation nil symbol] + [margin-inside nil length] + ;; These apply to the document + [page-break-before nil symbol] + [page-break-after nil symbol] + + ;; These are for specifying speech properties (Raman-style) [voice-family t string] [gain t integer] [left-volume t integer] @@ -89,6 +153,13 @@ ) "A description of the various CSS properties and how to interpret them.") +(put 'font 'css-shorthand t) +(put 'background 'css-shorthand t) +(put 'margin 'css-shorthand t) +(put 'padding 'css-shorthand t) +(put 'border 'css-shorthand t) +(put 'list-style 'css-shorthand t) + (mapcar (lambda (entry) (put (aref entry 0) 'css-inherit (aref entry 1)) @@ -133,10 +204,6 @@ (string-match "XEmacs" (emacs-version)) "Whether we are running in XEmacs or not.") -(defvar css-ie-compatibility t - "Whether we want to do Internet Explorer 3.0 compatible parsing of -CSS stylesheets.") - (defsubst css-replace-regexp (regexp to-string) (goto-char (point-min)) (while (re-search-forward regexp nil t) @@ -328,6 +395,13 @@ ord (1- ord))) rval)) +(defmacro css-symbol-list-as-regexp (&rest keys) + (` (eval-when-compile + (concat "^\\(" + (mapconcat 'symbol-name + (quote (, keys)) + "\\|") "\\)$")))) + (defun css-expand-color (color) (cond ((string-match "^#" color) @@ -370,15 +444,6 @@ g (round (* g 2.55)) b (round (* b 2.55)) color (vector 'rgb r g b)))) - ((string-match "url *(\\([^ )]+\\) *)" color) - ;; A picture in the background - (let ((pixmap (match-string 1 color)) - (attributes nil)) - (setq color (concat (substring color 0 (match-beginning 0)) - (substring color (match-end 0) nil)) - attributes (split-string color " ")) - ) - ) (t ;; Hmmm... pass it through unmangled and hope the underlying ;; windowing system can handle it. @@ -388,50 +453,138 @@ ) (defun css-expand-value (type value) - (case type - ((symbol integer) ; Read it in - (setq value (read (downcase value)))) - (symbol-list - (setq value (downcase value) - value (split-string value "[ ,]+") - value (mapcar 'intern value))) - (string-list - (setq value (split-string value " *, *"))) - (color ; A color, possibly with URLs - (setq value (css-expand-color value))) - (length ; Pixels, picas, ems, etc. - (setq value (css-expand-length value))) - (font ; Font shorthand - (setq value (css-split-font-shorthand value))) - ((margin padding) ; length|percentage|auto {1,4} - (setq value (split-string value "[ ,]+")) - (if (/= 1 (length value)) - ;; More than one value - a shortcut + (if value + (case type + (length ; CSS, Section 6.1 + (setq value (css-expand-length value))) + (percentage ; CSS, Section 6.2 + (setq value (/ (string-to-number value) + (if (fboundp 'float) (float 100) 1)))) + (color ; CSS, Section 6.3 + (setq value (css-expand-color value))) + (url ; CSS, Section 6.4 + (declare (special url purl)) + (if (string-match "url *(\\([^ )]+\\) *)" value) + (setq value (match-string 1 value))) + (if (string-match " *\\([^ ]+\\) *" value) + (setq value (match-string 1 value))) + (setq value (url-expand-file-name value (or url purl)))) + (angle ; ACSS, Section 2.2.1 + ) + (time ; ACSS, Section 2.2.2 + (let ((val (string-to-number value)) + (units 'ms)) + (if (string-match "^[0-9]+ *\\([a-zA-Z.]+\\)" value) + (setq units (intern (downcase (match-string 1 value))))) + (setq value (case units + ((s second seconds) + val) + ((min minute minutes) + (* val 60)) + ((hr hour hours) + (* val 60 60)) + ((day days) + (* val 24 60 60)) + (otherwise + (/ val (float 1000))))))) + (elevation ; ACSS, Section 4.2 + (if (string-match + (css-symbol-list-as-regexp below level above higher lower) value) + (setq value (intern (downcase (match-string value 1))) + value (case value + (below -90) + (above 90) + (level 0) + (higher 45) + (lower -45) + )) + (setq value (css-expand-value 'angle value)))) + (color-shorthand ; CSS, Section 5.3.7 + ;; color|image|repeat|attach|position + (let ((keys (split-string value " +")) + cur color image repeat attach position) + (while (setq cur (pop keys)) + (cond + ((string-match "url" cur) ; Only image can have a URL + (setq image (css-expand-value 'url cur))) + ((string-match "%" cur) ; Only position can have a perc. + (setq position (css-expand-value 'percentage cur))) + ((string-match "repeat" cur) ; Only repeat + (setq repeat (intern (downcase cur)))) + ((string-match "scroll\\|fixed" cur) + (setq attach (intern (downcase (substring cur + (match-beginning 0) + (match-end 0)))))) + ((string-match (css-symbol-list-as-regexp + top center bottom left right) cur) + ) + (t + (setq color cur)))) + (setq value (list (cons 'background-color color) + (cons 'background-image image) + (cons 'background-repeat repeat) + (cons 'background-attachment attach) + (cons 'background-position position))))) + (font ; CSS, Section 5.2.7 + ;; [style | variant | weight]? size[/line-height]? family + (setq value (css-split-font-shorthand value))) + (border ; width | style | color + ;; FIX + ) + (border-shorthand ; width | style | color + ;; FIX + ) + (list-style ; CSS, Section 5.6.6 + ;; keyword | position | url + (setq value (split-string value "[ ,]+")) + (if (= (length value) 1) + (setq value (list (cons 'list-style-type + (intern (downcase (car value)))))) + (setq value (list (cons 'list-style-type + (css-expand-value 'symbol (nth 0 value))) + (cons 'list-style-position + (css-expand-value 'symbol (nth 1 value))) + (cons 'list-style-image + (css-expand-value 'url (nth 2 value))))))) + (boundary-shorthand ; CSS, Section 5.5.x + ;; length|percentage|auto {1,4} + (setq value (split-string value "[ ,]+")) (let* ((top (intern (format "%s-top" type))) (bottom (intern (format "%s-bottom" type))) (left (intern (format "%s-left" type))) (right (intern (format "%s-right" type)))) - (setq top (cons top (css-expand-length (nth 0 value))) - right (cons right (css-expand-length (nth 1 value))) - bottom (cons bottom (css-expand-length (nth 2 value))) - left (cons left (css-expand-length (nth 3 value))) - value (list top right bottom left))) - (setq value (css-expand-length (car value))))) - (border - (cond - ((member (downcase value) '("none" "dotted" "dashed" "solid" - "double" "groove" "ridge" "inset" "outset")) - (setq value (intern (downcase value)))) - ((string-match "^[0-9]+" value) - (setq value (font-spatial-to-canonical value))) - (t nil))) - (weight ; normal|bold|bolder|lighter|[1-9]00 - (if (string-match "^[0-9]+" value) - (setq value (/ (read value) 100) - value (or (nth value css-weights) :bold)) - (setq value (intern (downcase (concat ":" value)))))) - (otherwise ; Leave it as is - t) + (setq top (cons top (css-expand-value (get top 'css-type) + (nth 0 value))) + right (cons right (css-expand-value (get right 'css-type) + (nth 1 value))) + bottom (cons bottom (css-expand-value (get bottom 'css-type) + (nth 2 value))) + left (cons left (css-expand-value (get left 'css-type) + (nth 3 value))) + value (list top right bottom left)))) + (weight ; CSS, Section 5.2.5 + ;; normal|bold|bolder|lighter|[1-9]00 + (cond + ((string-match "^[0-9]+" value) + (setq value (/ (string-to-number value) 100) + value (or (nth value css-weights) :bold))) + ((string-match (css-symbol-list-as-regexp normal bold bolder lighter) + value) + (setq value (intern (downcase (concat ":" value))))) + (t setq value (intern ":bold")))) + + ;; The rest of these deal with how we handle things internally + ((symbol integer) ; Read it in + (setq value (read (downcase value)))) + (symbol-list ; A space/comma delimited symlist + (setq value (downcase value) + value (split-string value "[ ,]+") + value (mapcar 'intern value))) + (string-list ; A space/comma delimited list + (setq value (split-string value " *, *"))) + (otherwise ; Leave it as is + t) + ) ) value ) @@ -485,43 +638,46 @@ (t (buffer-substring val-pos (progn - (if css-ie-compatibility - (skip-chars-forward "^;") - (skip-chars-forward "^,;")) + (skip-chars-forward "^;") (skip-chars-backward " \t") (point))))))) (setq value (css-expand-value (get name 'css-type) value)) - (if (eq (get name 'css-type) 'font) + (if (get name 'css-shorthand) (setq results (append value results)) (setq results (cons (cons name value) results))) (skip-chars-forward ";, \n\t")) results)))) -(defun css-handle-import () - (let ((url nil) - (save-pos (point))) - (if (looking-at "'\"") - (condition-case () - (forward-sexp 1) - (error (skip-chars-forward "^ \t\r\n;"))) - (skip-chars-forward "^ \t\r\n;")) - (setq url (url-expand-file-name (buffer-substring save-pos (point)))) - (skip-chars-forward "\"; \t\r\n") - (setq save-pos (point)) - (let ((url-working-buffer (generate-new-buffer-name " *styleimport*")) - (url-mime-accept-string - "text/css ; level=2") - (sheet nil)) - (save-excursion - (set-buffer (get-buffer-create url-working-buffer)) - (setq url-be-asynchronous nil) - (url-retrieve url) - (css-clean-buffer) - (setq sheet (buffer-string)) - (set-buffer-modified-p nil) - (kill-buffer (current-buffer))) - (insert sheet) - (goto-char save-pos)))) +(defun css-handle-media-directive (data active) + (let (type) + (if (string-match "\\([^ \t\r\n{]+\\)" data) + (setq type (intern (downcase (substring data (match-beginning 1) + (match-end 1)))) + data (substring data (match-end 1))) + (setq type 'unknown)) + (if (string-match "^[ \t\r\n]*{" data) + (setq data (substring data (match-end 0)))) + (if (memq type active) + (save-excursion + (insert data))))) + +(defun css-handle-import (data) + (let (url) + (setq url (css-expand-value 'url data)) + (and url + (let ((url-working-buffer (generate-new-buffer-name " *styleimport*")) + (url-mime-accept-string + "text/css ; level=2") + (sheet nil)) + (save-excursion + (set-buffer (get-buffer-create url-working-buffer)) + (setq url-be-asynchronous nil) + (url-retrieve url) + (css-clean-buffer) + (setq sheet (buffer-string)) + (set-buffer-modified-p nil) + (kill-buffer (current-buffer))) + (insert sheet))))) (defun css-clean-buffer () ;; Nuke comments, etc. @@ -541,7 +697,7 @@ (goto-char (point-min))) (defun css-active-device-types (&optional device) - (let ((types (list 'normal 'default (if css-running-xemacs 'xemacs 'emacs))) + (let ((types (list 'all (if css-running-xemacs 'xemacs 'emacs))) (type (device-type device))) (cond ((featurep 'emacspeak) @@ -634,7 +790,7 @@ ) ) -(defun css-parse (fname &optional string inherit) +(defun css-parse (url &optional string inherit) (let ( (url-mime-accept-string "text/css ; level=2") @@ -645,6 +801,7 @@ (cur nil) (val nil) (device-type nil) + (purl (url-view-url t)) (active-device-types (css-active-device-types (selected-device))) (sheet inherit)) (if (not sheet) @@ -654,7 +811,7 @@ (generate-new-buffer-name " *style*"))) (set-syntax-table css-syntax-table) (erase-buffer) - (if fname (url-insert-file-contents fname)) + (if url (url-insert-file-contents url)) (goto-char (point-max)) (if string (insert string)) (css-clean-buffer) @@ -668,25 +825,40 @@ (looking-at "--+>")) ; end (goto-char (match-end 0))) ;; C++ style comments, and we are doing IE compatibility - ((and (looking-at "//") css-ie-compatibility) + ((looking-at "//") (end-of-line)) ;; Pre-Processor directives ((looking-at "[ \t\r]*@\\([^ \t\r\n]\\)") - (let ((directive nil)) + (let (data directive) (skip-chars-forward " @\t\r") ; Past any leading whitespace (setq save-pos (point)) (skip-chars-forward "^ \t\r\n") ; Past the @ directive (downcase-region save-pos (point)) - (setq directive (buffer-substring save-pos (point))) - (skip-chars-forward " \t\r") ; Past any trailing whitespace + (setq directive (intern (buffer-substring save-pos (point)))) + (skip-chars-forward " \t\r") (setq save-pos (point)) (cond - ((string= directive "import") - (css-handle-import)) + ((looking-at ".*\\({\\)") + (goto-char (match-beginning 1)) + (forward-sexp 1) + (setq data (buffer-substring save-pos (1- (point))))) + ((looking-at "[\"']+") + (setq save-pos (1+ save-pos)) + (forward-sexp 1) + (setq data (buffer-substring save-pos (1- (point))))) (t - (message "Unknown directive in stylesheet: @%s" directive))))) + (skip-chars-forward "^;"))) + (if (not data) + (setq data (buffer-substring save-pos (point)))) + (setq save-pos (point)) + (case directive + (import (css-handle-import data)) + (media (css-handle-media-directive data active-device-types)) + (t (message "Unknown directive in stylesheet: @%s" directive))))) ;; Giving us some output device information ((looking-at "[ \t\r]*:\\([^: \n]+\\):") + (message "You are using the old way of specifying device-dependent stylesheets! Please upgrade!") + (sleep-for 2) (downcase-region (match-beginning 1) (match-end 1)) (setq device-type (intern (buffer-substring (match-beginning 1) (match-end 1))))