namespace eval Syntax {

proc get_word {t start} {
		set ws [$t search -forward -regexp {[^[:space:]]} $start "$start lineend"]
		if {$ws == ""} {
			set new_line_occured 1
			set ws [$t search -forward -regexp {[^[:space:]]} $start "end"]
		} else {
			set new_line_occured 0
		}
		if {$ws == ""} { return "end" }

		if {$ws > $start} {
			set white_space_occured 1
		} else {
			set white_space_occured 0
		}
		if {$white_space_occured && !$new_line_occured} {
			set blank_occured 1
		} else {
			set blank_occured 0
		}
		set we [$t index "$ws wordend"]
		set w [$t get $ws $we]
		return "{$ws} {$we} $new_line_occured $white_space_occured $blank_occured"
}

proc {highlight_tcl} {t start stop} {
	set ws $start
	set we $ws
	set word_no 0
	set Stack ""
	Stack::reset $Stack
	while {$ws != ""} {
		set res [get_word $t $we]
		if {$res == "end"} { 
			Stack::reset $Stack
			break
		}

		set we_old $we
		set ws [lindex $res 0]
		set we [lindex $res 1]
		set new_line_occured [lindex $res 2]
		set white_space_occured [lindex $res 3]
		set blank_occured [lindex $res 4]
		set w [$t get $ws $we]

		if {$new_line_occured} {
			set word_no 0
		}
		incr word_no

		if {$w == "\\"} {
			set we [$t index "$ws + 2 chars"]
			$t tag add escape $ws $we
		} elseif {$w == "\;"} {
			set word_no 0
			$t tag add escape $ws $we
		} elseif {$w == "\["} {
			$t tag add bracket $ws $we
		} elseif {$w == "\""} {
			$t tag add string $ws $we
			set ts $ws
			while {1} {
				set res [get_word $t $we]
				if {$res == "end"} { 
					$t tag add string $ts end
					break
				}
				set we_old $we
				set ws [lindex $res 0]
				set we [lindex $res 1]
				set new_line_occured [lindex $res 2]
				set white_space_occured [lindex $res 3]
				set blank_occured [lindex $res 4]
				set w [$t get $ws $we]
				
				if {$w == "\\"} {
					set we [$t index "$ws + 2 chars"]
				}
				if {$w == "\""} {
					$t tag add string $ts $we
					break
				}				
			}
		} elseif {$w == "\#"} {
			$t tag add comment $ws $we
			set ts $ws
			while {1} {
				set res [get_word $t $we]
				if {$res == "end"} { 
					$t tag add comment $ts end
					break
				}
				set we_old $we
				set ws [lindex $res 0]
				set we [lindex $res 1]
				set new_line_occured [lindex $res 2]
				set white_space_occured [lindex $res 3]
				set blank_occured [lindex $res 4]
				set w [$t get $ws $we]
				
				if {$new_line_occured} {
					$t tag add comment $ts $we_old
					set we $we_old
					break
				}				
			}
		} elseif {$w == "\]"} {
			if {[Stack::top $Stack] == "\["} {
				$t tag add bracket $ws $we
				Stack::pop $Stack
			} else {
				$t tag add none $ws $we
			}
		} elseif {$w == "\{"} {
			$t tag add brace $ws $we
		} elseif {$w == "\}"} {
			$t tag add brace $ws $we
		} elseif {$w == "\$"} {
			$t tag add variable $ws $we
			set we [$t search -forward -regexp { |\]|\}|\;} $ws "$ws lineend"]
			if {$we == ""} {
				set we [$t index "$ws lineend"]
			}
			$t tag add variable $ws $we
		} elseif {$w == "\-"} {
			if {$white_space_occured} {
			    set we [$t search -forward -regexp { } $ws "$ws lineend"]
			    if {$we == ""} {
				set we [$t index "$ws lineend"]
			    }
			    $t tag add switch $ws $we
			}
		} elseif {[string is double -strict $w]} {
			$t tag add number $ws $we
		} elseif {$word_no == 1} {
			if {[info commands $w] == $w} {
				$t tag add command $ws $we
			} else {
				$t tag add none $ws $we
			}
		}
		
#		puts "$w \t ws:$ws we:$we \t NL:$new_line_occured WS:$white_space_occured BL:$blank_occured"
	}
}

proc {highlight_plpgsql} {t start stop} {
	set ws $start
	set we $ws
	while {$ws != ""} {
		set res [get_word $t $we]
		if {$res == "end"} { 
			break
		}

		set we_old $we
		set ws [lindex $res 0]
		set we [lindex $res 1]
		set new_line_occured [lindex $res 2]
		set white_space_occured [lindex $res 3]
		set blank_occured [lindex $res 4]
		set w [$t get $ws $we]


		if {![string compare -nocase $w "declare"]} {
			$t tag add command $ws $we
		} elseif {![string compare -nocase $w "begin"]} {
			$t tag add command $ws $we
		} elseif {![string compare -nocase $w "end"]} {
			$t tag add command $ws $we
		} elseif {![string compare -nocase $w "if"]} {
			$t tag add command $ws $we
		} elseif {![string compare -nocase $w "then"]} {
			$t tag add command $ws $we
		} elseif {![string compare -nocase $w "else"]} {
			$t tag add command $ws $we
		} elseif {![string compare -nocase $w "elsif"]} {
			$t tag add command $ws $we
		} elseif {![string compare -nocase $w "select"]} {
			$t tag add command $ws $we
		} elseif {![string compare -nocase $w "into"]} {
			$t tag add command $ws $we
		} elseif {![string compare -nocase $w "perform"]} {
			$t tag add command $ws $we
		} elseif {![string compare -nocase $w "execute"]} {
			$t tag add command $ws $we
		} elseif {![string compare -nocase $w "alias"]} {
			$t tag add command $ws $we
		} elseif {![string compare -nocase $w "for"]} {
			$t tag add command $ws $we
		} elseif {![string compare -nocase $w "loop"]} {
			$t tag add command $ws $we
		} elseif {![string compare -nocase $w "get"]} {
			$t tag add command $ws $we
		} elseif {![string compare -nocase $w "diagnostics"]} {
			$t tag add command $ws $we
		} elseif {![string compare -nocase $w "return"]} {
			$t tag add command $ws $we
		} elseif {![string compare -nocase $w "while"]} {
			$t tag add command $ws $we
		} elseif {![string compare -nocase $w "exit"]} {
			$t tag add command $ws $we
		} elseif {![string compare -nocase $w "cursor"]} {
			$t tag add command $ws $we
		} elseif {![string compare -nocase $w "open"]} {
			$t tag add command $ws $we
		} elseif {![string compare -nocase $w "fetch"]} {
			$t tag add command $ws $we
		} elseif {![string compare -nocase $w "close"]} {
			$t tag add command $ws $we
		} elseif {![string compare -nocase $w "raise"]} {
			$t tag add command $ws $we
		# for sql highlight
		} elseif {![string compare -nocase $w "abort"]} {
			$t tag add command $ws $we
		} elseif {![string compare -nocase $w "alter"]} {
			$t tag add command $ws $we
		} elseif {![string compare -nocase $w "group"]} {
			$t tag add command $ws $we
		} elseif {![string compare -nocase $w "table"]} {
			$t tag add command $ws $we
		} elseif {![string compare -nocase $w "user"]} {
			$t tag add command $ws $we
		} elseif {![string compare -nocase $w "analyze"]} {
			$t tag add command $ws $we
		} elseif {![string compare -nocase $w "checkpoint"]} {
			$t tag add command $ws $we
		} elseif {![string compare -nocase $w "cluster"]} {
			$t tag add command $ws $we
		} elseif {![string compare -nocase $w "comment"]} {
			$t tag add command $ws $we
		} elseif {![string compare -nocase $w "commit"]} {
			$t tag add command $ws $we
		} elseif {![string compare -nocase $w "copy"]} {
			$t tag add command $ws $we
		} elseif {![string compare -nocase $w "to"]} {
			$t tag add command $ws $we
		} elseif {![string compare -nocase $w "create"]} {
			$t tag add command $ws $we
		} elseif {![string compare -nocase $w "aggregate"]} {
			$t tag add command $ws $we
		} elseif {![string compare -nocase $w "constraint"]} {
			$t tag add command $ws $we
		} elseif {![string compare -nocase $w "trigger"]} {
			$t tag add command $ws $we
		} elseif {![string compare -nocase $w "database"]} {
			$t tag add command $ws $we
		} elseif {![string compare -nocase $w "function"]} {
			$t tag add command $ws $we
		} elseif {![string compare -nocase $w "group"]} {
			$t tag add command $ws $we
		} elseif {![string compare -nocase $w "index"]} {
			$t tag add command $ws $we
		} elseif {![string compare -nocase $w "language"]} {
			$t tag add command $ws $we
		} elseif {![string compare -nocase $w "operator"]} {
			$t tag add command $ws $we
		} elseif {![string compare -nocase $w "rule"]} {
			$t tag add command $ws $we
		} elseif {![string compare -nocase $w "sequence"]} {
			$t tag add command $ws $we
		} elseif {![string compare -nocase $w "table"]} {
			$t tag add command $ws $we
		} elseif {![string compare -nocase $w "trigger"]} {
			$t tag add command $ws $we
		} elseif {![string compare -nocase $w "type"]} {
			$t tag add command $ws $we
		} elseif {![string compare -nocase $w "view"]} {
			$t tag add command $ws $we
		} elseif {![string compare -nocase $w "declare"]} {
			$t tag add command $ws $we
		} elseif {![string compare -nocase $w "delete"]} {
			$t tag add command $ws $we
		} elseif {![string compare -nocase $w "drop"]} {
			$t tag add command $ws $we
		} elseif {![string compare -nocase $w "explain"]} {
			$t tag add command $ws $we
		} elseif {![string compare -nocase $w "fetch"]} {
			$t tag add command $ws $we
		} elseif {![string compare -nocase $w "grant"]} {
			$t tag add command $ws $we
		} elseif {![string compare -nocase $w "insert"]} {
			$t tag add command $ws $we
		} elseif {![string compare -nocase $w "listen"]} {
			$t tag add command $ws $we
		} elseif {![string compare -nocase $w "load"]} {
			$t tag add command $ws $we
		} elseif {![string compare -nocase $w "lock"]} {
			$t tag add command $ws $we
		} elseif {![string compare -nocase $w "move"]} {
			$t tag add command $ws $we
		} elseif {![string compare -nocase $w "notify"]} {
			$t tag add command $ws $we
		} elseif {![string compare -nocase $w "reindex"]} {
			$t tag add command $ws $we
		} elseif {![string compare -nocase $w "reset"]} {
			$t tag add command $ws $we
		} elseif {![string compare -nocase $w "revoke"]} {
			$t tag add command $ws $we
		} elseif {![string compare -nocase $w "rollback"]} {
			$t tag add command $ws $we
		} elseif {![string compare -nocase $w "set"]} {
			$t tag add command $ws $we
		} elseif {![string compare -nocase $w "constrains"]} {
			$t tag add command $ws $we
		} elseif {![string compare -nocase $w "session"]} {
			$t tag add command $ws $we
		} elseif {![string compare -nocase $w "authorization"]} {
			$t tag add command $ws $we
		} elseif {![string compare -nocase $w "transaction"]} {
			$t tag add command $ws $we
		} elseif {![string compare -nocase $w "show"]} {
			$t tag add command $ws $we
		} elseif {![string compare -nocase $w "truncate"]} {
			$t tag add command $ws $we
		} elseif {![string compare -nocase $w "unlisten"]} {
			$t tag add command $ws $we
		} elseif {![string compare -nocase $w "update"]} {
			$t tag add command $ws $we
		} elseif {![string compare -nocase $w "vacuum"]} {
			$t tag add command $ws $we
		} elseif {![string compare -nocase $w "from"]} {
			$t tag add command $ws $we
		} elseif {![string compare -nocase $w "where"]} {
			$t tag add command $ws $we
		} elseif {![string compare -nocase $w "group"]} {
			$t tag add command $ws $we
		} elseif {![string compare -nocase $w "by"]} {
			$t tag add command $ws $we
		} elseif {![string compare -nocase $w "having"]} {
			$t tag add command $ws $we
		} elseif {![string compare -nocase $w "order"]} {
			$t tag add command $ws $we
		} elseif {![string compare -nocase $w "limit"]} {
			$t tag add command $ws $we
		} elseif {![string compare -nocase $w "offset"]} {
			$t tag add command $ws $we
		} elseif {![string compare -nocase $w "add"]} {
			$t tag add command $ws $we
		} elseif {![string compare -nocase $w "drop"]} {
			$t tag add command $ws $we
		} elseif {![string compare -nocase $w "as"]} {
			$t tag add command $ws $we
		} elseif {![string compare -nocase $w "and"]} {
			$t tag add command $ws $we

		} elseif {$w == "\""} {
			$t tag add string $ws $we
			set ts $ws
			while {1} {
				set res [get_word $t $we]
				if {$res == "end"} { 
					$t tag add string $ts end
					break
				}
				set we_old $we
				set ws [lindex $res 0]
				set we [lindex $res 1]
				set new_line_occured [lindex $res 2]
				set white_space_occured [lindex $res 3]
				set blank_occured [lindex $res 4]
				set w [$t get $ws $we]
				
				if {$new_line_occured} {
					$t tag add string $ts $we_old
					break
				}				
				if {$w == "\""} {
					$t tag add string $ts $we
					break
				}				
			}
		} elseif {$w == "\'"} {
			$t tag add string $ws $we
			set ts $ws
			while {1} {
				set res [get_word $t $we]
				if {$res == "end"} { 
					$t tag add string $ts end
					break
				}
				set we_old $we
				set ws [lindex $res 0]
				set we [lindex $res 1]
				set new_line_occured [lindex $res 2]
				set white_space_occured [lindex $res 3]
				set blank_occured [lindex $res 4]
				set w [$t get $ws $we]
				
				if {$w == "\'"} {
					$t tag add string $ts $we
					break
				}				
			}
		} elseif {$w == "\/"} {
			if {[$t get $ws "$ws + 2 chars"] == "\/\*"} {
				set ts $ws
				while {1} {
					set res [get_word $t $we]
					if {$res == "end"} { 
						$t tag add comment $ts end
						break
					}
					set we_old $we
					set ws [lindex $res 0]
					set we [lindex $res 1]
					set new_line_occured [lindex $res 2]
					set white_space_occured [lindex $res 3]
					set blank_occured [lindex $res 4]
					set w [$t get $ws $we]
					
					if {$w == "\*"} {
						if {[$t get $ws "$ws + 2 chars"] == "\*\/"} {
							set we [$t index "$ws + 2 chars"] 
							$t tag add comment $ts $we
							break
						}
					}				
				}
			}
		} elseif {$w == "\-"} {
			if {[$t get $ws "$ws + 2 chars"] == "--"} {
				set we [$t index "$ws lineend"] 
				$t tag add comment $ws $we
			}
		} elseif {$w == "\;"} {
			$t tag add escape $ws $we
		} elseif {$w == "\$"} {
			$t tag add variable $ws $we
			set we [$t search -forward -regexp { |\)|\;} $ws "$ws lineend"]
			if {$we == ""} {
				set we [$t index "$ws lineend"]
			}
			$t tag add variable $ws $we
		} elseif {$w == "\:"} {
			if {[$t get $ws "$ws + 2 chars"] == ":="} {
				set we [$t index "$ws + 2 chars"] 
				$t tag add escape $ws $we
			}
		} elseif {[string is double -strict $w]} {
			$t tag add number $ws $we
		}
		
#		puts "$w \t ws:$ws we:$we \t NL:$new_line_occured WS:$white_space_occured BL:$blank_occured"
	}
}

proc {highlight} {t type {start 1.0} {stop ""} args} {
	$t tag configure none -foreground black
	$t tag configure command -foreground DarkBlue
	$t tag configure number -foreground DarkGreen
	$t tag configure comment -foreground gray
	$t tag configure variable -foreground red
	$t tag configure string -foreground purple
	$t tag configure escape -foreground brown
	$t tag configure brace -foreground black
	$t tag configure bracket -foreground black
	$t tag configure switch -foreground DarkGreen

	if {$stop == ""} {
		set stop [$t index end]
	}
	foreach tag {none command number comment variable string escape brace bracket switch} {
		$t tag remove $tag $start $stop
	}

	if {$type == "tcl"} {
		highlight_tcl $t $start $stop
	} elseif {$type == "pltcl"} {
		highlight_tcl $t $start $stop
	} elseif {$type == "plpgsql"} {
		highlight_plpgsql $t $start $stop
	} elseif {$type == "sql"} {
		highlight_plpgsql $t $start $stop
	}
}

}; # end namespace












