home *** CD-ROM | disk | FTP | other *** search
Text File | 1999-04-24 | 32.2 KB | 1,009 lines | [TEXT/ALFA] |
- ## -*-Tcl-*-
- # ###################################################################
- # HTML and CSS mode - tools for editing Cascading Style Sheets
- #
- # FILE: "hctsmsl.tcl"
- # created: 97-03-08 19.32.58
- # last update: 99-04-24 13.20.16
- # Author: Johan Linde
- # E-mail: <jlinde@telia.com>
- # www: <http://www.theophys.kth.se/~jl/Alpha.html>
- #
- # Version: 2.1.4 and 1.1.1
- #
- # Copyright 1996-1999 by Johan Linde
- #
- # This software may be used freely, and distributed freely, as long as the
- # receiver is not obligated in any way by receiving it.
- #
- # If you make improvements to this file, please share them!
- #
- # ###################################################################
- ##
-
- proc hctsmsl.tcl {} {}
-
- # Units allowed for length.
- set cssUnits {em ex px pt cm mm in pc}
-
- # These properties can take a number as value.
- set cssNumbers {line-height}
-
- # These properties can take length values.
- set cssLengths {font-size line-height background-position word-spacing letter-spacing
- text-indent margin-top margin-right margin-bottom margin-left padding-top padding-right
- padding-bottom padding-left border-top-width border-right-width border-bottom-width
- border-left-width border-width width height}
-
- # These properties can take percentage values.
- set cssPercentage {font-size line-height background-position vertical-align text-indent
- margin-top margin-right margin-bottom margin-left padding-top padding-right
- padding-bottom padding-left width}
-
- # These properties can take URL values.
- set cssURLs {background-image list-style-image @import}
-
- # These properties can take color values.
- set cssColors {color background-color border-color}
-
- # These properties can take any value.
- set cssAny {font-family}
-
- # Groups of properties for different dialogs.
- set cssGroup(font) {font-style font-variant font-weight font-size line-height font-family}
- set cssGroup(background) {background-color background-image background-repeat
- background-attachment background-position}
- set cssGroup(text) {word-spacing letter-spacing text-decoration vertical-align
- text-transform text-align text-indent}
- set cssGroup(margin) {margin-top margin-right margin-bottom margin-left}
- set cssGroup(padding) {padding-top padding-right padding-bottom padding-left}
- set cssGroup(border) {border-width border-style border-color}
- set cssGroup(border-width) {border-top-width border-right-width border-bottom-width
- border-left-width}
- set cssGroup(size) {width height}
- set cssGroup(Display) {display white-space}
- set cssGroup(list-style) {list-style-type list-style-image list-style-position}
-
- # These of the above groups are shorthands.
- set cssShorthands {font background margin padding border border-width list-style}
-
- # Possible values of the css properties.
- set cssProperty(font-family) {serif sans-serif cursive fantasy monospace}
- set cssProperty(font-style) {italic oblique normal}
- set cssProperty(font-variant) {small-caps normal}
- set cssProperty(font-weight) {bold bolder lighter 100 200 300 400 500 600 700 800 900 normal}
- set cssProperty(font-size) {larger smaller xx-small x-small small medium large x-large xx-large}
- set cssProperty(line-height) {normal}
- set cssProperty(background-color) {transparent}
- set cssProperty(background-image) {none}
- set cssProperty(background-repeat) {repeat-x repeat-y no-repeat repeat}
- set cssProperty(background-attachment) {fixed scroll}
- set cssProperty(background-position) {{top center bottom} {left center right}}
- set cssProperty(word-spacing) {normal}
- set cssProperty(letter-spacing) {normal}
- set cssProperty(text-decoration) {none {underline overline line-through blink}}
- set cssProperty(vertical-align) {sub super top text-top middle bottom text-bottom baseline}
- set cssProperty(text-transform) {capitalize uppercase lowercase none}
- set cssProperty(text-align) {left right center justify}
- set cssProperty(margin-top) {auto}
- set cssProperty(margin-right) {auto}
- set cssProperty(margin-bottom) {auto}
- set cssProperty(margin-left) {auto}
- set cssProperty(border-width) {thin medium thick}
- set cssProperty(border-top-width) {thin medium thick}
- set cssProperty(border-right-width) {thin medium thick}
- set cssProperty(border-bottom-width) {thin medium thick}
- set cssProperty(border-left-width) {thin medium thick}
- set cssProperty(border-style) {dotted dashed solid double groove ridge inset outset none}
- set cssProperty(width) {auto}
- set cssProperty(height) {auto}
- set cssProperty(float) {left right none}
- set cssProperty(clear) {left right both none}
- set cssProperty(display) {block inline list-item none}
- set cssProperty(white-space) {pre nowrap normal}
- set cssProperty(list-style-type) {disc circle square decimal lower-roman upper-roman lower-alpha
- upper-alpha none}
- set cssProperty(list-style-image) {none}
- set cssProperty(list-style-position) {inside outside}
-
-
- proc cssGetHtmlWords {} {
- global cssHtmlWords htmlElemAttrOptional1 htmlModeIsLoaded
- if {![info exists htmlModeIsLoaded]} {
- return $cssHtmlWords
- } else {
- catch {unset cssHtmlWords}
- return [array names htmlElemAttrOptional1]
- }
- }
-
- proc cssFindWhereToInsert {group pos} {
- if {$pos > 0} {incr pos -1}
- if {[catch {search -s -f 0 -m 0 -r 1 "\{" $pos} lbrace]} {set lbrace 0; set noleft 1}
- set lbrace [expr [lindex $lbrace 0] + 1]
- if {[catch {search -s -f 0 -m 0 -r 1 "\}" $pos} rbrace]} {set rbrace 0}
- set rbrace [expr [lindex $rbrace 0] + 1]
- if {([info exists noleft] || $rbrace > $lbrace) && $group != "@import"} {alertnote "Incorrect position to insert properties."; error "Incorrect position"}
- if {[catch {search -s -f 0 -m 0 -r 1 "\;" $pos} semi] || [lindex $semi 0] < $lbrace} {set semi 0}
- set semi [expr [lindex $semi 0] + 1]
- set go [getPos]
- if {$group != "@import" && ($lbrace > 1 || $semi > 1)} {set go [expr $lbrace > $semi ? $lbrace : $semi]}
- if {[cssIsInComment $go]} {
- set go [lindex [search -s -f 0 -m 0 -r 0 "/*" $go] 0]
- cssFindWhereToInsert $group $go
- } else {
- goto $go
- }
- }
-
- # CSS properties dialog.
- proc cssDialog {group} {
- global cssGroup cssProperty cssAny cssURLs cssLengths cssPercentage cssColors cssUnits
- global htmluserColors htmlColorName basicColors HTMLmodeVars cssShorthands mode cssNumbers
-
- if {$mode == "HTML" && ![htmlIsInContainer STYLE]} {
- beep
- message "Current position is not inside STYLE tags."
- return
- }
- # Find where to insert text.
- cssFindWhereToInsert $group [getPos]
-
- # define colors
- set htmlColors [lsort [array names htmluserColors]]
- append htmlColors " - " $basicColors
-
- # urls
- set URLs $HTMLmodeVars(URLs)
-
- # these fit in half the size of the dialog window
- set halfIsEnough {font-style font-variant font-weight text-transform text-align white-space}
-
- # These needs more space
- set dw 0
- if {$group == "background" || $group == "border-width" || $group == "list-style"} {set dw 40}
- # obtain all props for this group
- if {[info exists cssGroup($group)]} {
- set props $cssGroup($group)
- } else {
- set props $group
- }
-
- # build the dialog
- set invalidInput 1
- set short 1
- set allvalues 0
- set val [cssGetProperties $group]
- if {[info exists errorText] && ![htmlErrorWindow "$group not well-defined" $errorText 1]} {return}
- while {$invalidInput} {
- while {1} {
- if {$group == "@import"} {
- set htxt "Import Style Sheet"
- } else {
- set htxt "[string toupper [string index $group 0]][string range $group 1 end] properties"
- }
- set box "-t [list $htxt] 120 10 450 25"
- set fileIndex ""
- set colorIndex ""
- set proptypes ""
- set hpos 35
- set ind 2
- set wpos 10
- foreach p $props {
- if {[lsearch -exact $halfIsEnough $p] < 0 || $wpos > 235} {
- if {$wpos > 10} {set wpos 10; incr hpos 30}
- }
- if {$p != "@import"} {lappend box -t ${p}: $wpos $hpos [expr $wpos + 110 + $dw] [expr $hpos + 15]}
- incr wpos 120
- incr wpos $dw
- if {[info exists cssProperty($p)]} {
- # A list of choices
- set pr $cssProperty($p)
- # special case with background-position and text-decoration
- if {$p == "background-position" || $p == "text-decoration"} {
- set pr1 [lindex $pr 0]
- if {[llength $pr1] > 1} {
- lappend box -m [concat [list [lindex $val $ind] "No value"] $pr1] \
- $wpos $hpos [expr $wpos + 95] [expr $hpos + 15]
- } else {
- lappend box -c $pr1 [lindex $val $ind] $wpos $hpos [expr $wpos + 95] [expr $hpos + 15]
- }
- incr wpos 105
- incr ind
- set pr [lindex $pr 1]
- lappend proptypes $p choices
- }
- set n 1
- # four times for text-decoration and border-style
- if {$p == "text-decoration" || $group == "border-style"} {set n 4}
- for {set i 0} {$i < $n} {incr i} {
- if {$wpos > 355 + $dw} {
- set wpos [expr 130 + $dw]
- incr hpos 30
- }
- if {[llength $pr] > 1} {
- lappend box -m [concat [list [lindex $val $ind] "No value"] $pr] \
- $wpos $hpos [expr $wpos + 95] [expr $hpos + 15]
- } else {
- lappend box -c $pr [lindex $val $ind] $wpos $hpos [expr $wpos + 95] [expr $hpos + 15]
- }
- incr wpos 105
- incr ind
- lappend proptypes $p choices
- }
- }
- set l [lsearch -exact $cssLengths $p]
- set pr [lsearch -exact $cssPercentage $p]
- if { $l >= 0 || $pr >= 0 } {
- # Length or percentage
- set n 1
- # twice for background-position
- if {$p == "background-position"} {set n 2}
- for {set i 0} {$i < $n} {incr i} {
- if {$wpos > 335 + $dw} {
- set wpos [expr 130 + $dw]
- incr hpos 30
- }
- set units ""
- if {$l >= 0} {set units $cssUnits}
- if {$pr >= 0} {lappend units %}
- set uw 110
- if {[lsearch -exact $cssNumbers $p] >= 0} {set units "{No unit} $units"; set uw 160}
- lappend box -e [lindex $val $ind] $wpos $hpos [expr $wpos + 50] [expr $hpos + 15]
- lappend box -m [concat [list [lindex $val [expr $ind + 1]]] $units] \
- [expr $wpos + 60] $hpos [expr $wpos + $uw] [expr $hpos + 15]
- incr wpos 120
- incr ind 2
- lappend proptypes $p number
- }
- set wpos 10
- incr hpos 30
- }
- if {[lsearch -exact $cssAny $p] >= 0} {
- # Any value
- if {$wpos > 10} {set wpos 10; incr hpos 30}
- lappend box -e [lindex $val $ind] 10 $hpos 450 [expr $hpos + 15]
- incr ind
- set wpos 10
- incr hpos 30
- lappend proptypes $p any
- }
- if {[lsearch -exact $cssColors $p] >=0 } {
- # color
- set n 1
- # four times for border-color
- if {$group == "border-color"} {set n 4}
- for {set i 0} {$i < $n} {incr i} {
- if {$wpos > 130} {set wpos 10; incr hpos 30}
- lappend box -e [lindex $val $ind] 130 $hpos 200 [expr $hpos + 15] \
- -m [concat [list [lindex $val [expr $ind + 1]] {No value}] $htmlColors] \
- 210 $hpos 340 [expr $hpos + 15] \
- -b "New Color…" 350 $hpos 450 [expr $hpos + 20]
- incr ind 3
- lappend colorIndex [expr $ind - 1]
- set wpos 10
- incr hpos 40
- lappend proptypes $p color
- }
- }
- if {[lsearch -exact $cssURLs $p] >= 0} {
- # URL
- if {$wpos > 130} {set wpos 10; incr hpos 30}
- lappend box -e [lindex $val $ind] 120 $hpos 450 [expr $hpos + 15] \
- -m [concat [list [lindex $val [expr $ind + 1]] {No value}] $URLs] \
- 120 [expr $hpos + 25] 450 [expr $hpos + 35] \
- -b "File…" 10 [expr $hpos + 20] 70 [expr $hpos + 40]
- incr ind 3
- lappend fileIndex [expr $ind - 1]
- set wpos 10
- incr hpos 50
- lappend proptypes $p url
- }
- if {[string match "*left*" $p]} {
- if {$wpos > 130} {set wpos 10; incr hpos 30}
- lappend box -r "Set all values individually" $allvalues 10 $hpos 300 [expr $hpos + 15]
- lappend box -r "Add missing values automatically if possible" [expr !$allvalues] 10 [expr $hpos + 20] 350 [expr $hpos + 35]
- set allValIndex $ind
- incr ind 2
- set wpos 10
- incr hpos 40
- lappend proptypes $p allval
- }
- }
- if {$wpos > 10} {incr hpos 20}
- if {[lsearch -exact $cssShorthands $group] >= 0} {
- lappend box -c "Use shorthand form if possible" $short 10 $hpos 250 [expr $hpos + 15]
- incr hpos 20
- set shortIndex $ind
- }
- set val [eval [concat dialog -w [expr 460 + $dw] -h [expr $hpos + 50] \
- -b OK 20 [expr $hpos + 20] 85 [expr $hpos + 40] \
- -b Cancel 110 [expr $hpos + 20] 175 [expr $hpos + 40] $box]]
- if {[info exists shortIndex]} {set short [lindex $val $shortIndex]}
- if {[info exists allValIndex]} {set allvalues [lindex $val $allValIndex]}
- # OK clicked?
- if {[lindex $val 0]} {break}
- # Cancel clicked?
- if {[lindex $val 1]} {return}
- # File button clicked?
- foreach fl $fileIndex {
- if {[lindex $val $fl] && [set newFile [htmlGetFile]] != ""} {
- set URLs $HTMLmodeVars(URLs)
- set val [lreplace $val [expr $fl - 1] [expr $fl - 1] [lindex $newFile 0]]
- }
- }
- # Color button clicked?
- foreach cl $colorIndex {
- if {[lindex $val $cl] && [set newColor [htmlAddNewColor]] != ""} {
- set htmlColors [concat [list $newColor] $htmlColors]
- set val [lreplace $val [expr $cl -1] [expr $cl - 1] "$newColor"]
- }
- }
- }
-
- # Find indentation.
- set indent ""
- if {![catch {matchIt "\}" [getPos]} pos]} {
- regexp {^[ \t]*} [getText [lineStart $pos] $pos] indent
- }
- # Put it all together.
- set j 2
- set prevprop ""
- set proptext ""
- set errtext ""
- set tmptext ""
- for {set i 0} {$i < [llength $proptypes]} {incr i 2} {
- set prop [lindex $proptypes [expr $i + 1]]
- if {$prevprop != [set pr [lindex $proptypes $i]]} {
- if {$tmptext != ""} {
- if {$prevprop == "text-decoration"} {
- if {[lindex $tmptext 0] == "1"} {
- set tmptext " none"
- } elseif {$tmptext != " 0"} {
- set tmptext " [lunique [lrange $tmptext 1 end]]"
- }
- } else {
- set tmptext " [lindex $tmptext 0]"
- }
- if {$tmptext != " 0"} {
- if {[info exists important($prevprop)] || [info exists important($group)]} {append tmptext " ! important"}
- append proptext "\;\r$indent\t$prevprop:$tmptext"
- }
- }
- set prevprop $pr
- set tmptext ""
- }
- switch $prop {
- choices {
- if {[llength $cssProperty($pr)] == 1} {
- if {[lindex $val $j]} {
- append tmptext " $cssProperty($pr)"
- }
- } elseif {[set c [lindex $val $j]] != "No value"} {
- append tmptext " $c"
- }
- incr j
- }
- number {
- if {[set c [string trim [lindex $val $j]]] != ""} {
- if {![catch {cssCheckNumber $pr $c [lindex $val [expr $j + 1]]} c]} {
- append tmptext " $c"
- } else {
- lappend errtext "$pr: $c"
- }
- }
- incr j 2
- }
- any {
- if {[set c [string trim [lindex $val $j]]] != ""} {
- append tmptext ", $c"
- }
- incr j
- }
- color {
- if {[set ctxt [string trim [lindex $val $j]]] != ""} {
- if {[set col [cssCheckColorNumber $ctxt]] == 0} {
- lappend errtext "$pr: $ctxt is not a valid color number."
- } else {
- append tmptext " $col"
- }
- } elseif {[set cval [lindex $val [expr $j + 1]]] != "No value"} {
- if {[info exists htmluserColors($cval)]} {
- append tmptext " $htmluserColors($cval)"
- }
- if {[info exists htmlColorName($cval)]} {
- append tmptext " $htmlColorName($cval)"
- }
- }
- incr j 3
- }
- url {
- if {[set turl [string trim [lindex $val $j]]] != ""} {
- append tmptext " url(\"[htmlURLescape2 $turl]\")"
- htmlAddToCache URLs $turl
- } elseif {[set murl [lindex $val [expr $j + 1]]] != "No value"} {
- append tmptext " url(\"[htmlURLescape2 $murl]\")"
- }
- incr j 3
- }
- allval {
- incr j 2
- }
- }
- }
- if {$tmptext != ""} {
- if {$prevprop == "background-position"} {
- if {[regexp {^[a-z]+$} [lindex $tmptext 0]]} {
- set tp ""
- foreach tm $tmptext {
- if {[regexp {^[a-z]+$} $tm]} {
- lappend tp $tm
- }
- }
- set tmptext " $tp"
- }
- } elseif {$prevprop == "font-family"} {
- set tmptext [string trim $tmptext ,]
- if {[lsearch -exact $cssProperty(font-family) [set first [string trim [lindex $tmptext 0] ,]]] >= 0
- && [llength $tmptext] > 1} {
- set tmptext " [lrange $tmptext 1 end], $first"
- }
- } elseif {$prevprop != "border-style" && $prevprop != "border-color"} {
- set tmptext " [lindex $tmptext 0]"
- }
- if {[info exists important($prevprop)] || [info exists important($group)]} {append tmptext " ! important"}
- append proptext "\;\r$indent\t$pr:$tmptext"
- }
- set proptext [string trimleft $proptext "\;"]
- if {![llength $errtext]} {
- set invalidInput 0
- if {[info exists allValIndex] && !$allvalues} {set proptext [cssAddMissingValues $group $proptext $indent]}
- if {[info exists shortIndex] && $short} {set proptext [cssMakeShort $group $proptext $indent]}
- } else {
- htmlErrorWindow "Invalid input" $errtext
- }
-
- }
- # Special fixes for @import
- if {$group == "@import"} {
- regexp {^[ \t]*} [getText [lineStart [getPos]] [getPos]] indent
- set proptext [string trimleft $proptext ";"]
- regsub "\t+" $proptext "$indent" proptext
- regsub "@import:" $proptext "@import" proptext
- }
- set len 0
- set ps [getPos]
- if {$proptext != ""} {
- insertText "$proptext\;"
- set len [expr [getPos] - $ps]
- }
- set removePos0 [lsort -integer -decreasing $removePos0]
- set removePos1 [lsort -integer -decreasing $removePos1]
- # Check for overlapping positions.
- set r0 [maxPos]
- for {set i 0} {$i < [llength $removePos1]} {incr i} {
- set r00 [lindex $removePos0 $i]
- set r11 [lindex $removePos1 $i]
- if {$r11 > $r0} {set r11 $r0}
- if {$r11 > $r00} {lappend rem [list $r00 $r11]}
- set r0 $r00
- }
- foreach r $rem {
- set xpos 0
- if {[set pos1 [lindex $r 0]] >= $ps} {set xpos $len}
- deleteText [expr $pos1 + $xpos] [expr [lindex $r 1] + $xpos]
- }
- }
-
- # Add missing values to top, right, bottom, left properties.
- proc cssAddMissingValues {group text indent} {
- global cssGroup
- set tmp [split $text "\r"]
- set sideList {top right bottom left}
- # Find those values which have been set
- foreach side $sideList {
- set $side 0
- foreach l $tmp {
- if {[string match *${side}* [lindex $l 0]]} {
- set $side 1
- set ${side}val [string trimright [lindex $l 1] "\;"]
- }
- }
- }
- # Add missing values.
- foreach side $sideList {
- if {![set $side]} {
- switch $side {
- top {set opside bottom}
- right {set opside left}
- bottom {set opside top}
- left {set opside right}
- }
- if {[set $opside]} {
- set use $opside
- } elseif {$top} {
- set use top
- } else {
- # Can't add missing value.
- return $text
- }
- append text "\;\r$indent\t[lindex $cssGroup($group) [lsearch $sideList $side]]: [set ${use}val]"
- }
- }
-
- return $text
- }
-
- # Makes a short form of a group of properties.
- proc cssMakeShort {group text indent} {
- global cssGroup
- set lines [split $text \r]
- set count 0
- set important 0
- foreach pr $cssGroup($group) {
- foreach l $lines {
- if {[lindex $l 0] == "$pr:"} {
- incr important [regsub { ! important} $l {} l]
- incr count
- if {$pr == "font-size"} {set fontSize 1}
- if {$pr == "font-family"} {set fontFamily 1}
- # Line-height is a special case.
- if {$pr == "line-height" && [info exists fontSize]} {
- append values /[string trimright [lrange $l 1 end] "\;"]
- } else {
- append values " " [string trimright [lrange $l 1 end] "\;"]
- }
- }
- }
- }
- if {$important > 0 && $important != $count} {return $text}
- # font-size and font-family must be used for font.
- if {$group == "font" && (![info exists fontSize] || ![info exists fontFamily])} {return $text}
- # Remove unnecessary stuff for margin and padding and border-width.
- if {$group == "margin" || $group == "padding" || $group == "border-width"} {
- # If count ≠ 4, then there is no short form
- if {$count != 4} {return $text}
- if {[llength [lunique $values]] == 1} {
- set values " [lindex $values 0]"
- } elseif {[lindex $values 0] == [lindex $values 2] && [lindex $values 1] == [lindex $values 3]} {
- set values [lrange $values 0 1]
- } elseif {[lindex $values 1] == [lindex $values 3]} {
- set values [lrange $values 0 2]
- }
- }
-
- set text ""
- if {[lindex $lines 0] == "\;"} {set text "\;"}
- if {[info exists values]} {
- if {$group == "font"} {set values " [lunique $values]"}
- append text "\r$indent\t$group:$values"
- if {$important} {append text " ! important"}
- }
- return $text
- }
-
- # Check if a CSS number is ok.
- proc cssCheckNumber {prop num unit} {
- global cssPercentage cssLengths cssUnits
- if {![regexp {^(-?[0-9]+\.?[0-9]*)([%a-z]*)$} $num d n u]} {
- error "Invalid number."
- }
- if {$u != ""} {
- if {[lsearch -exact [concat $cssUnits %] $u] < 0 ||
- $u != "%" && [lsearch -exact $cssLengths $prop] < 0} {
- error "Invalid unit."
- } else {
- set unit $u
- }
- } elseif {$unit == "No unit"} {
- set unit ""
- }
- if {$unit == "%" && [lsearch -exact $cssPercentage $prop] < 0} {
- error "Percentage not allowed."
- }
- return "$n$unit"
- }
-
- # Check if a color number is a valid number, or one of the predefined names.
- # Returns 0 if not and the color number if it is.
- proc cssCheckColorNumber {color} {
- global htmlColorName
- set color [string tolower $color]
- if {[info exists htmlColorName($color)]} {return $htmlColorName($color)}
- # rgb(1,2,3)
- if {[regexp {^rgb\(([0-9]+),([0-9]+),([0-9]+)\)$} $color dum c1 c2 c3]} {
- if {$c1 > -1 && $c1 < 256 && $c2 > -1 && $c2 < 256 && $c3 > -1 && $c3 < 256} {
- return $color
- } else {
- return 0
- }
- }
- # rgb(1.0%,2.0%,3.0%)
- if {[regexp {^rgb\(([0-9]+\.?[0-9]*)%,([0-9]+\.?[0-9]*)%,([0-9]+\.?[0-9]*)%\)$} $color dum c1 c2 c3]} {
- if {$c1 >= 0.0 && $c1 <= 100.0 && $c2 >= 0.0 && $c2 <= 100.0 && $c3 >= 0.0 && $c3 <= 100.0} {
- return $color
- } else {
- return 0
- }
- }
-
- # #123456 or #123
- if {[string index $color 0] != "#"} {
- set color "#${color}"
- }
- set color [string toupper $color]
- if {([string length $color] != 7 && [string length $color] != 4) || ![regexp {^#[0-9A-F]+$} $color]} {
- return 0
- } else {
- return $color
- }
- }
-
- # Extracts the current values for the property to add.
- proc cssGetProperties {group} {
- global cssGroup cssProperty cssAny cssURLs cssLengths cssPercentage cssColors
- global htmluserColorname htmlColorNumber HTMLmodeVars cssShorthands
-
- upvar removePos0 remove0 removePos1 remove1 important important
- upvar short short errorText errorText
-
- if {$group == "@import"} {return}
-
- # obtain all props for this group
- if {[info exists cssGroup($group)]} {
- set props $cssGroup($group)
- } else {
- set props $group
- }
- # Find interval to search in.
- if {[catch {matchIt "\}" [getPos]} start]} {
- if {![catch {search -s -f 0 -m 0 -r 0 "\}" [getPos]} r0] ||
- ![catch {search -s -f 1 -i 1 -m 0 -r 0 "<STYLE([ \t\r]+[^<>]*>|>)" [getPos]} r0]} {
- set start [lindex $r0 1]
- } else {
- set start 0
- }
- }
- if {[catch {matchIt "\{" [getPos]} end]} {
- set rbrace [maxPos]
- set style [maxPos]
- if {![catch {search -s -f 1 -m 0 -r 0 "\{" [getPos]} r0]} {
- set rbrace [lineStart [lindex $r0 0]]
- }
- if {![catch {search -s -f 1 -i 1 -m 0 -r 0 "</STYLE>" [getPos]} r0]} {
- set style [lindex $r0 0]
- }
- set end [expr $rbrace < $style ? $rbrace : $style]
- }
- # build a list with property values
- set val {0 0}
- set remove ""
- # Find shorthand property
- if {[lsearch -exact $cssShorthands $group] >= 0} {
- set groupValue ""
- set st0 $start
- while {1} {
- if {[catch {search -s -f 1 -i 1 -m 0 -r 1 -l $end "(\[ \t\r\]+|;|\{)$group\[ \t\r\]*:" $st0} res]} {
- break
- } elseif {![catch {search -s -f 1 -i 1 -m 0 -r 0 -l $end "\;" [lindex $res 1]} res1]} {
- if {![cssIsInComment [lindex $res 0]]} {
- set groupValue [string trim [getText [lindex $res 1] [expr [lindex $res1 1] - 1]]]
- set r00 [lindex $res 0]
- if {[lookAt $r00] == ";" || [lookAt $r00] == "\{"} {incr r00}
- lappend remove0 $r00
- lappend remove1 [lindex $res1 1]
- break
- } else {
- set st0 [lindex $res1 1]
- }
- } else {
- if {![cssIsInComment [lindex $res 0]]} {
- set groupValue [string trim [getText [lindex $res 1] $end]]
- set r00 [lindex $res 0]
- if {[lookAt $r00] == ";" || [lookAt $r00] == "\{"} {incr r00}
- lappend remove0 $r00
- lappend remove1 $end
- break
- } else {
- set st0 [lindex $res1 1]
- }
- }
- }
- regsub -all {/\*[^\*]*\*/} $groupValue "" groupValue
- if {[regsub -nocase {![ \t\r]*important} $groupValue {} groupValue]} {set important($group) 1}
- if {$groupValue != ""} {
- cssExpandProps $group $groupValue
- }
- }
-
- foreach p $props {
- # Find the property
- if {![info exists propValue($p)]} {set propValue($p) ""}
- set st0 $start
- while {1} {
- if {[catch {search -s -f 1 -i 1 -m 0 -r 1 -l $end "(\[ \t\r\]+|;|\{)$p\[ \t\r\]*:" $st0} res]} {
- break
- } elseif {![catch {search -s -f 1 -i 1 -m 0 -r 0 -l $end "\;" [lindex $res 1]} res1]} {
- if {![cssIsInComment [lindex $res 0]]} {
- set propValue($p) [string trim [getText [lindex $res 1] [expr [lindex $res1 1] - 1]]]
- set r00 [lindex $res 0]
- if {[lookAt $r00] == ";" || [lookAt $r00] == "\{"} {incr r00}
- lappend remove0 $r00
- lappend remove1 [lindex $res1 1]
- set short 0
- break
- } else {
- set st0 [lindex $res1 1]
- }
- } else {
- if {![cssIsInComment [lindex $res 0]]} {
- set propValue($p) [string trim [getText [lindex $res 1] $end]]
- set r00 [lindex $res 0]
- if {[lookAt $r00] == ";" || [lookAt $r00] == "\{"} {incr r00}
- lappend remove0 $r00
- lappend remove1 $end
- set short 0
- break
- } else {
- set st0 [lindex $res1 1]
- }
- }
- }
- regsub -all {/\*[^\*]*\*/} $propValue($p) "" propValue($p)
- }
- foreach p $props {
- set thisValue [string tolower $propValue($p)]
- if {[regsub {![ \t\r]*important} $thisValue {} thisValue]} {set important($p) 1}
- if {[info exists cssProperty($p)]} {
- # A list of choices
- set pr $cssProperty($p)
- # special case with background-position and text-decoration
- if {$p == "background-position" || $p == "text-decoration"} {
- set pr1 [lindex $pr 0]
- if {[llength $pr1] > 1} {
- set found 0
- for {set i 0} {$i < [llength $thisValue]} {incr i} {
- set tv [lindex $thisValue $i]
- if {[lsearch -exact $pr1 $tv] >= 0} {
- lappend val [lindex $thisValue $i]
- set thisValue [lreplace $thisValue $i $i]
- set found 1
- break
- }
- }
- if {!$found} {lappend val "No value"}
- } elseif {[set ww [lsearch -exact $thisValue $pr1]] >= 0} {
- set thisValue [lreplace $thisValue $ww $ww]
- lappend val 1
- } else {
- lappend val 0
- }
- set pr [lindex $pr 1]
- }
- set n 1
- # four times for text-decoration and border-style
- if {$p == "text-decoration" || $group == "border-style"} {set n 4}
- for {set i 0} {$i < $n} {incr i} {
- if {[llength $pr] > 1} {
- if {[llength $thisValue] && [lsearch -exact $pr [lindex $thisValue 0]] >= 0} {
- lappend val [lindex $thisValue 0]
- set thisValue [lrange $thisValue 1 end]
- } else {
- lappend val "No value"
- }
- } elseif {$thisValue == $pr} {
- lappend val 1
- set thisValue ""
- } else {
- lappend val 0
- }
- }
- }
- set l [lsearch -exact $cssLengths $p]
- set pr [lsearch -exact $cssPercentage $p]
- if { $l >= 0 || $pr >= 0 } {
- # Length or percentage
- set n 1
- # twice for background-position
- if {$p == "background-position"} {set n 2}
- for {set i 0} {$i < $n} {incr i} {
- if {$i < [llength $thisValue] && ![catch {cssCheckNumber $p [lindex $thisValue 0] ""} num]} {
- regexp {[0-9]+(.*)} $num dum unit
- lappend val $num $unit
- set thisValue [lrange $thisValue 1 end]
- } else {
- lappend val "" ""
- }
- }
- }
- if {[lsearch -exact $cssAny $p] >= 0} {
- # Any value
- lappend val $thisValue
- set thisValue ""
- }
- if {[lsearch -exact $cssColors $p] >=0 } {
- # color
- set n 1
- # four times for border-color
- if {$group == "border-color"} {set n 4}
- for {set i 0} {$i < $n} {incr i} {
- set tv [cssCheckColorNumber [lindex $thisValue 0]]
- if {$tv == "0"} {
- lappend val "" "No value" 0
- } elseif {[info exists htmluserColorname($tv)]} {
- lappend val "" $htmluserColorname($tv) 0
- } elseif {[info exists htmlColorNumber($tv)]} {
- lappend val "" $htmlColorNumber($tv) 0
- } else {
- lappend val $tv "No value" 0
- }
- if {$tv != "0"} {set thisValue [lrange $thisValue 1 end]}
- }
- }
- if {[lsearch -exact $cssURLs $p] >= 0} {
- # URL
- if {[regexp {url\(\"?([^\"\)]+)\"?\)} $propValue($p) dum thisValue]} {
- set thisValue [htmlURLunEscape $thisValue]
- htmlAddToCache URLs $thisValue
- lappend val "" $thisValue 0
- set thisValue ""
- } else {
- lappend val "" "No value" 0
- }
- }
- if {[llength $thisValue]} {lappend errorText "$p: $thisValue"}
- }
- return $val
- }
-
- proc cssExpandProps {group value} {
- global cssGroup cssProperty cssAny cssURLs cssLengths cssPercentage cssColors cssUnits
- upvar propValue prop errorText errorText
- set valueUP $value
- set value [string tolower $value]
- # Special case with font
- if {$group == "font"} {
- regexp {[^ \t]+(,[ \t]+[^ \t]+)*[ \t]*$} $value family
- set prop(font-family) [string trim $family]
- set value [string range $value 0 [expr [string length $value] - [string length $family] - 1]]
- set fontsize [lindex $value [expr [llength $value] - 1]]
- set lineheight ""
- regexp {^([^/]+)/?(.*)$} $fontsize dum fontsize lineheight
- if {[lsearch -exact $cssProperty(font-size) $fontsize] >= 0 || ![catch {cssCheckNumber font-size $fontsize ""} fontsize]} {
- set prop(font-size) $fontsize
- }
- if {[lsearch -exact $cssProperty(line-height) $lineheight] >= 0 || ![catch {cssCheckNumber line-height $lineheight ""} lineheight]} {
- set prop(line-height) $lineheight
- }
- set value [lrange $value 0 [expr [llength $value] - 2]]
- set normal [lsearch -exact $value normal]
- regsub -all "normal" $value "" value
- }
-
- # Special case with background-position
- if {$group == "background"} {
- foreach bp $cssProperty(background-position) {
- set nv ""
- foreach v $value {
- if {[lsearch -exact $bp $v] >= 0} {
- lappend prop(background-position) $v
- } else {
- lappend nv $v
- }
- }
- set value $nv
- }
- set nv ""
- foreach v $value {
- if {![catch {cssCheckNumber background-position $v ""} v1]} {
- lappend prop(background-position) $v1
- } else {
- lappend nv $v
- }
- }
- set value $nv
- }
-
- # Handle margin, padding and border-width separately
- if {$group == "margin" || $group == "padding" || $group == "border-width"} {
- foreach trbl {top right bottom left} {
- if {$group == "border-width"} {
- set pr "border-${trbl}-width"
- } else {
- set pr ${group}-$trbl
- }
- set v ""
- if {[llength $value]} {
- set v [lindex $value 0]
- set value [lrange $value 1 end]
- }
- if {$group != "padding" && [lsearch -exact $cssProperty($pr) $v] >= 0} {
- set prop($pr) $v
- } elseif {![catch {cssCheckNumber $pr $v ""} v1]} {
- set prop($pr) $v1
- } elseif {$v != ""} {
- append err " $v"
- }
- }
- if {[info exists err]} {lappend errorText "$group:$err"}
- return
- }
-
- # All other properties.
- foreach p $cssGroup($group) {
- if {[info exists cssProperty($p)]} {
- set p1 $cssProperty($p)
- if {$group == "font" && [lsearch -exact {font-style font-weight font-variant line-height} $p] >= 0} {
- set tmp ""
- for {set i 0} {$i < [llength $value]} {incr i} {
- set v [lindex $value $i]
- if {[lsearch -exact $p1 $v] >= 0} {
- set tmp $v
- set value [lreplace $value $i $i]
- break
- }
- }
- if {$tmp != ""} {
- set prop($p) $tmp
- } elseif {$normal >= 0} {
- set prop($p) normal
- }
- } else {
- for {set i 0} {$i < [llength $value]} {incr i} {
- set v [lindex $value $i]
- if {[lsearch -exact $p1 $v] >= 0} {
- set prop($p) $v
- set value [lreplace $value $i $i]
- break
- }
- }
- }
- }
- if {[lsearch -exact $cssURLs $p] >= 0} {
- for {set i 0} {$i < [llength $value]} {incr i} {
- set v [lindex $value $i]
- if {[regexp {^url\(\"?[^\"\)]+\"?\)$} $v]} {
- foreach v1 $valueUP {
- if {$v == [string tolower $v1]} {
- set prop($p) $v1
- }
- }
- set value [lreplace $value $i $i]
- break
- }
- }
- }
- if {[lsearch -exact $cssColors $p] >= 0} {
- for {set i 0} {$i < [llength $value]} {incr i} {
- set v [lindex $value $i]
- if {[set c [cssCheckColorNumber $v]] != "0"} {
- set prop($p) $c
- set value [lreplace $value $i $i]
- break
- }
- }
- }
- set l [lsearch -exact $cssLengths $p]
- set pr [lsearch -exact $cssPercentage $p]
- if { $l >= 0 || $pr >= 0 } {
- for {set i 0} {$i < [llength $value]} {incr i} {
- set v [lindex $value $i]
- if {![catch {cssCheckNumber $p $v ""} num]} {
- set prop($p) $num
- set value [lreplace $value $i $i]
- break
- }
- }
- }
- }
- if {[llength $value]} {lappend errorText "$group: $value"}
- }
-
- proc cssIsInComment {pos} {
- set a [maxPos]
- set b -1
- if {![catch {search -s -f 0 -m 0 -r 0 "/*" $pos} a1]} {set a [lindex $a1 0]}
- if {![catch {search -s -f 0 -m 0 -r 0 "*/" $pos} b1]} {set b [lindex $b1 0]}
- return [expr ($a < $pos && $a > $b)]
- }
-