xref: /vim-8.2.3635/runtime/syntax/2html.vim (revision 166af9bb)
1071d4279SBram Moolenaar" Vim syntax support file
2349b2fb0SBram Moolenaar" Maintainer: Ben Fritz <[email protected]>
3*166af9bbSBram Moolenaar" Last Change: 2010 Sep 04
4349b2fb0SBram Moolenaar"
5349b2fb0SBram Moolenaar" Additional contributors:
6349b2fb0SBram Moolenaar"
7349b2fb0SBram Moolenaar"             Original by Bram Moolenaar <[email protected]>
8349b2fb0SBram Moolenaar"             Modified by David Ne\v{c}as (Yeti) <[email protected]>
9349b2fb0SBram Moolenaar"             XHTML support by Panagiotis Issaris <[email protected]>
10349b2fb0SBram Moolenaar"             Made w3 compliant by Edd Barrett <[email protected]>
11349b2fb0SBram Moolenaar"             Added html_font. Edd Barrett <[email protected]>
12349b2fb0SBram Moolenaar"             Progress bar based off code from "progressbar widget" plugin by
13349b2fb0SBram Moolenaar"               Andreas Politz, heavily modified:
14349b2fb0SBram Moolenaar"               http://www.vim.org/scripts/script.php?script_id=2006
15349b2fb0SBram Moolenaar"
16349b2fb0SBram Moolenaar"             See Mercurial change logs for more!
17071d4279SBram Moolenaar
18071d4279SBram Moolenaar" Transform a file into HTML, using the current syntax highlighting.
19071d4279SBram Moolenaar
205c73622aSBram Moolenaar" this file uses line continuations
215c73622aSBram Moolenaarlet s:cpo_sav = &cpo
22349b2fb0SBram Moolenaarlet s:ls  = &ls
235c73622aSBram Moolenaarset cpo-=C
245c73622aSBram Moolenaar
25349b2fb0SBram Moolenaarlet s:end=line('$')
26349b2fb0SBram Moolenaar
27313b7237SBram Moolenaar" Font
28b02cbe34SBram Moolenaarif exists("g:html_font")
29076e8b2aSBram Moolenaar  let s:htmlfont = "'". g:html_font . "', monospace"
30313b7237SBram Moolenaarelse
31313b7237SBram Moolenaar  let s:htmlfont = "monospace"
32313b7237SBram Moolenaarendif
33313b7237SBram Moolenaar
34076e8b2aSBram Moolenaarlet s:settings = tohtml#GetUserSettings()
355c73622aSBram Moolenaar
36071d4279SBram Moolenaar" When not in gui we can only guess the colors.
37071d4279SBram Moolenaarif has("gui_running")
38071d4279SBram Moolenaar  let s:whatterm = "gui"
39071d4279SBram Moolenaarelse
40071d4279SBram Moolenaar  let s:whatterm = "cterm"
41071d4279SBram Moolenaar  if &t_Co == 8
42313b7237SBram Moolenaar    let s:cterm_color = {0: "#808080", 1: "#ff6060", 2: "#00ff00", 3: "#ffff00", 4: "#8080ff", 5: "#ff40ff", 6: "#00ffff", 7: "#ffffff"}
43071d4279SBram Moolenaar  else
44313b7237SBram Moolenaar    let s:cterm_color = {0: "#000000", 1: "#c00000", 2: "#008000", 3: "#804000", 4: "#0000c0", 5: "#c000c0", 6: "#008080", 7: "#c0c0c0", 8: "#808080", 9: "#ff6060", 10: "#00ff00", 11: "#ffff00", 12: "#8080ff", 13: "#ff40ff", 14: "#00ffff", 15: "#ffffff"}
45313b7237SBram Moolenaar
46313b7237SBram Moolenaar    " Colors for 88 and 256 come from xterm.
47313b7237SBram Moolenaar    if &t_Co == 88
48313b7237SBram Moolenaar      call extend(s:cterm_color, {16: "#000000", 17: "#00008b", 18: "#0000cd", 19: "#0000ff", 20: "#008b00", 21: "#008b8b", 22: "#008bcd", 23: "#008bff", 24: "#00cd00", 25: "#00cd8b", 26: "#00cdcd", 27: "#00cdff", 28: "#00ff00", 29: "#00ff8b", 30: "#00ffcd", 31: "#00ffff", 32: "#8b0000", 33: "#8b008b", 34: "#8b00cd", 35: "#8b00ff", 36: "#8b8b00", 37: "#8b8b8b", 38: "#8b8bcd", 39: "#8b8bff", 40: "#8bcd00", 41: "#8bcd8b", 42: "#8bcdcd", 43: "#8bcdff", 44: "#8bff00", 45: "#8bff8b", 46: "#8bffcd", 47: "#8bffff", 48: "#cd0000", 49: "#cd008b", 50: "#cd00cd", 51: "#cd00ff", 52: "#cd8b00", 53: "#cd8b8b", 54: "#cd8bcd", 55: "#cd8bff", 56: "#cdcd00", 57: "#cdcd8b", 58: "#cdcdcd", 59: "#cdcdff", 60: "#cdff00", 61: "#cdff8b", 62: "#cdffcd", 63: "#cdffff", 64: "#ff0000"})
49313b7237SBram Moolenaar      call extend(s:cterm_color, {65: "#ff008b", 66: "#ff00cd", 67: "#ff00ff", 68: "#ff8b00", 69: "#ff8b8b", 70: "#ff8bcd", 71: "#ff8bff", 72: "#ffcd00", 73: "#ffcd8b", 74: "#ffcdcd", 75: "#ffcdff", 76: "#ffff00", 77: "#ffff8b", 78: "#ffffcd", 79: "#ffffff", 80: "#2e2e2e", 81: "#5c5c5c", 82: "#737373", 83: "#8b8b8b", 84: "#a2a2a2", 85: "#b9b9b9", 86: "#d0d0d0", 87: "#e7e7e7"})
50313b7237SBram Moolenaar    elseif &t_Co == 256
51313b7237SBram Moolenaar      call extend(s:cterm_color, {16: "#000000", 17: "#00005f", 18: "#000087", 19: "#0000af", 20: "#0000d7", 21: "#0000ff", 22: "#005f00", 23: "#005f5f", 24: "#005f87", 25: "#005faf", 26: "#005fd7", 27: "#005fff", 28: "#008700", 29: "#00875f", 30: "#008787", 31: "#0087af", 32: "#0087d7", 33: "#0087ff", 34: "#00af00", 35: "#00af5f", 36: "#00af87", 37: "#00afaf", 38: "#00afd7", 39: "#00afff", 40: "#00d700", 41: "#00d75f", 42: "#00d787", 43: "#00d7af", 44: "#00d7d7", 45: "#00d7ff", 46: "#00ff00", 47: "#00ff5f", 48: "#00ff87", 49: "#00ffaf", 50: "#00ffd7", 51: "#00ffff", 52: "#5f0000", 53: "#5f005f", 54: "#5f0087", 55: "#5f00af", 56: "#5f00d7", 57: "#5f00ff", 58: "#5f5f00", 59: "#5f5f5f", 60: "#5f5f87", 61: "#5f5faf", 62: "#5f5fd7", 63: "#5f5fff", 64: "#5f8700"})
52313b7237SBram Moolenaar      call extend(s:cterm_color, {65: "#5f875f", 66: "#5f8787", 67: "#5f87af", 68: "#5f87d7", 69: "#5f87ff", 70: "#5faf00", 71: "#5faf5f", 72: "#5faf87", 73: "#5fafaf", 74: "#5fafd7", 75: "#5fafff", 76: "#5fd700", 77: "#5fd75f", 78: "#5fd787", 79: "#5fd7af", 80: "#5fd7d7", 81: "#5fd7ff", 82: "#5fff00", 83: "#5fff5f", 84: "#5fff87", 85: "#5fffaf", 86: "#5fffd7", 87: "#5fffff", 88: "#870000", 89: "#87005f", 90: "#870087", 91: "#8700af", 92: "#8700d7", 93: "#8700ff", 94: "#875f00", 95: "#875f5f", 96: "#875f87", 97: "#875faf", 98: "#875fd7", 99: "#875fff", 100: "#878700", 101: "#87875f", 102: "#878787", 103: "#8787af", 104: "#8787d7", 105: "#8787ff", 106: "#87af00", 107: "#87af5f", 108: "#87af87", 109: "#87afaf", 110: "#87afd7", 111: "#87afff", 112: "#87d700"})
53313b7237SBram Moolenaar      call extend(s:cterm_color, {113: "#87d75f", 114: "#87d787", 115: "#87d7af", 116: "#87d7d7", 117: "#87d7ff", 118: "#87ff00", 119: "#87ff5f", 120: "#87ff87", 121: "#87ffaf", 122: "#87ffd7", 123: "#87ffff", 124: "#af0000", 125: "#af005f", 126: "#af0087", 127: "#af00af", 128: "#af00d7", 129: "#af00ff", 130: "#af5f00", 131: "#af5f5f", 132: "#af5f87", 133: "#af5faf", 134: "#af5fd7", 135: "#af5fff", 136: "#af8700", 137: "#af875f", 138: "#af8787", 139: "#af87af", 140: "#af87d7", 141: "#af87ff", 142: "#afaf00", 143: "#afaf5f", 144: "#afaf87", 145: "#afafaf", 146: "#afafd7", 147: "#afafff", 148: "#afd700", 149: "#afd75f", 150: "#afd787", 151: "#afd7af", 152: "#afd7d7", 153: "#afd7ff", 154: "#afff00", 155: "#afff5f", 156: "#afff87", 157: "#afffaf", 158: "#afffd7"})
54313b7237SBram Moolenaar      call extend(s:cterm_color, {159: "#afffff", 160: "#d70000", 161: "#d7005f", 162: "#d70087", 163: "#d700af", 164: "#d700d7", 165: "#d700ff", 166: "#d75f00", 167: "#d75f5f", 168: "#d75f87", 169: "#d75faf", 170: "#d75fd7", 171: "#d75fff", 172: "#d78700", 173: "#d7875f", 174: "#d78787", 175: "#d787af", 176: "#d787d7", 177: "#d787ff", 178: "#d7af00", 179: "#d7af5f", 180: "#d7af87", 181: "#d7afaf", 182: "#d7afd7", 183: "#d7afff", 184: "#d7d700", 185: "#d7d75f", 186: "#d7d787", 187: "#d7d7af", 188: "#d7d7d7", 189: "#d7d7ff", 190: "#d7ff00", 191: "#d7ff5f", 192: "#d7ff87", 193: "#d7ffaf", 194: "#d7ffd7", 195: "#d7ffff", 196: "#ff0000", 197: "#ff005f", 198: "#ff0087", 199: "#ff00af", 200: "#ff00d7", 201: "#ff00ff", 202: "#ff5f00", 203: "#ff5f5f", 204: "#ff5f87"})
55313b7237SBram Moolenaar      call extend(s:cterm_color, {205: "#ff5faf", 206: "#ff5fd7", 207: "#ff5fff", 208: "#ff8700", 209: "#ff875f", 210: "#ff8787", 211: "#ff87af", 212: "#ff87d7", 213: "#ff87ff", 214: "#ffaf00", 215: "#ffaf5f", 216: "#ffaf87", 217: "#ffafaf", 218: "#ffafd7", 219: "#ffafff", 220: "#ffd700", 221: "#ffd75f", 222: "#ffd787", 223: "#ffd7af", 224: "#ffd7d7", 225: "#ffd7ff", 226: "#ffff00", 227: "#ffff5f", 228: "#ffff87", 229: "#ffffaf", 230: "#ffffd7", 231: "#ffffff", 232: "#080808", 233: "#121212", 234: "#1c1c1c", 235: "#262626", 236: "#303030", 237: "#3a3a3a", 238: "#444444", 239: "#4e4e4e", 240: "#585858", 241: "#626262", 242: "#6c6c6c", 243: "#767676", 244: "#808080", 245: "#8a8a8a", 246: "#949494", 247: "#9e9e9e", 248: "#a8a8a8", 249: "#b2b2b2", 250: "#bcbcbc", 251: "#c6c6c6", 252: "#d0d0d0", 253: "#dadada", 254: "#e4e4e4", 255: "#eeeeee"})
56313b7237SBram Moolenaar    endif
57071d4279SBram Moolenaar  endif
58071d4279SBram Moolenaarendif
59071d4279SBram Moolenaar
60071d4279SBram Moolenaar" Return good color specification: in GUI no transformation is done, in
61313b7237SBram Moolenaar" terminal return RGB values of known colors and empty string for unknown
62071d4279SBram Moolenaarif s:whatterm == "gui"
63071d4279SBram Moolenaar  function! s:HtmlColor(color)
64071d4279SBram Moolenaar    return a:color
65071d4279SBram Moolenaar  endfun
66071d4279SBram Moolenaarelse
67071d4279SBram Moolenaar  function! s:HtmlColor(color)
68313b7237SBram Moolenaar    if has_key(s:cterm_color, a:color)
69313b7237SBram Moolenaar      return s:cterm_color[a:color]
70071d4279SBram Moolenaar    else
71071d4279SBram Moolenaar      return ""
72071d4279SBram Moolenaar    endif
73071d4279SBram Moolenaar  endfun
74071d4279SBram Moolenaarendif
75071d4279SBram Moolenaar
76bebca9daSBram Moolenaarif !s:settings.use_css
77071d4279SBram Moolenaar  " Return opening HTML tag for given highlight id
78071d4279SBram Moolenaar  function! s:HtmlOpening(id)
79071d4279SBram Moolenaar    let a = ""
80071d4279SBram Moolenaar    if synIDattr(a:id, "inverse")
81071d4279SBram Moolenaar      " For inverse, we always must set both colors (and exchange them)
82071d4279SBram Moolenaar      let x = s:HtmlColor(synIDattr(a:id, "fg#", s:whatterm))
83071d4279SBram Moolenaar      let a = a . '<span style="background-color: ' . ( x != "" ? x : s:fgc ) . '">'
84071d4279SBram Moolenaar      let x = s:HtmlColor(synIDattr(a:id, "bg#", s:whatterm))
85071d4279SBram Moolenaar      let a = a . '<font color="' . ( x != "" ? x : s:bgc ) . '">'
86071d4279SBram Moolenaar    else
87071d4279SBram Moolenaar      let x = s:HtmlColor(synIDattr(a:id, "bg#", s:whatterm))
88071d4279SBram Moolenaar      if x != "" | let a = a . '<span style="background-color: ' . x . '">' | endif
89071d4279SBram Moolenaar      let x = s:HtmlColor(synIDattr(a:id, "fg#", s:whatterm))
90071d4279SBram Moolenaar      if x != "" | let a = a . '<font color="' . x . '">' | endif
91071d4279SBram Moolenaar    endif
92071d4279SBram Moolenaar    if synIDattr(a:id, "bold") | let a = a . "<b>" | endif
93071d4279SBram Moolenaar    if synIDattr(a:id, "italic") | let a = a . "<i>" | endif
94071d4279SBram Moolenaar    if synIDattr(a:id, "underline") | let a = a . "<u>" | endif
95071d4279SBram Moolenaar    return a
96071d4279SBram Moolenaar  endfun
97071d4279SBram Moolenaar
98071d4279SBram Moolenaar  " Return closing HTML tag for given highlight id
99349b2fb0SBram Moolenaar  function! s:HtmlClosing(id)
100071d4279SBram Moolenaar    let a = ""
101071d4279SBram Moolenaar    if synIDattr(a:id, "underline") | let a = a . "</u>" | endif
102071d4279SBram Moolenaar    if synIDattr(a:id, "italic") | let a = a . "</i>" | endif
103071d4279SBram Moolenaar    if synIDattr(a:id, "bold") | let a = a . "</b>" | endif
104071d4279SBram Moolenaar    if synIDattr(a:id, "inverse")
105071d4279SBram Moolenaar      let a = a . '</font></span>'
106071d4279SBram Moolenaar    else
107071d4279SBram Moolenaar      let x = s:HtmlColor(synIDattr(a:id, "fg#", s:whatterm))
108071d4279SBram Moolenaar      if x != "" | let a = a . '</font>' | endif
109071d4279SBram Moolenaar      let x = s:HtmlColor(synIDattr(a:id, "bg#", s:whatterm))
110071d4279SBram Moolenaar      if x != "" | let a = a . '</span>' | endif
111071d4279SBram Moolenaar    endif
112071d4279SBram Moolenaar    return a
113071d4279SBram Moolenaar  endfun
114071d4279SBram Moolenaarendif
115071d4279SBram Moolenaar
11635a9aaabSBram Moolenaar" Return HTML valid characters enclosed in a span of class style_name with
11735a9aaabSBram Moolenaar" unprintable characters expanded and double spaces replaced as necessary.
1188ada2ccaSBram Moolenaarfunction! s:HtmlFormat(text, style_name, diff_style_name)
11935a9aaabSBram Moolenaar  " Replace unprintable characters
12035a9aaabSBram Moolenaar  let formatted = strtrans(a:text)
12135a9aaabSBram Moolenaar
1228ada2ccaSBram Moolenaar  " separate the two classes by a space to apply them both if there is a diff
1238ada2ccaSBram Moolenaar  " style name
1248ada2ccaSBram Moolenaar  let l:style_name = a:style_name . (a:diff_style_name == '' ? '' : ' ') . a:diff_style_name
1258ada2ccaSBram Moolenaar
12635a9aaabSBram Moolenaar  " Replace the reserved html characters
12735a9aaabSBram Moolenaar  let formatted = substitute(substitute(substitute(substitute(substitute(formatted, '&', '\&amp;', 'g'), '<', '\&lt;', 'g'), '>', '\&gt;', 'g'), '"', '\&quot;', 'g'), "\x0c", '<hr class="PAGE-BREAK">', 'g')
12835a9aaabSBram Moolenaar
1298df7f888SBram Moolenaar  " Replace double spaces, leading spaces, and trailing spaces if needed
13035a9aaabSBram Moolenaar  if ' ' != s:HtmlSpace
13135a9aaabSBram Moolenaar    let formatted = substitute(formatted, '  ', s:HtmlSpace . s:HtmlSpace, 'g')
1328424a624SBram Moolenaar    let formatted = substitute(formatted, '^ ', s:HtmlSpace, 'g')
1338df7f888SBram Moolenaar    let formatted = substitute(formatted, ' \+$', s:HtmlSpace, 'g')
13435a9aaabSBram Moolenaar  endif
13535a9aaabSBram Moolenaar
13635a9aaabSBram Moolenaar  " Enclose in a span of class style_name
1378ada2ccaSBram Moolenaar  let formatted = '<span class="' . l:style_name . '">' . formatted . '</span>'
13835a9aaabSBram Moolenaar
1398ada2ccaSBram Moolenaar  " Add the class to class list if it's not there yet.
1408ada2ccaSBram Moolenaar  " Add normal groups to the beginning so diff groups can override them.
14135a9aaabSBram Moolenaar  let s:id = hlID(a:style_name)
1428ada2ccaSBram Moolenaar  if index(s:idlist, s:id ) == -1
1438ada2ccaSBram Moolenaar    if a:style_name =~ 'Diff\%(Add\|Change\|Delete\|Text\)'
1448ada2ccaSBram Moolenaar      call add(s:idlist, s:id)
1458ada2ccaSBram Moolenaar    else
1468ada2ccaSBram Moolenaar      call insert(s:idlist, s:id)
1478ada2ccaSBram Moolenaar    endif
1488ada2ccaSBram Moolenaar  endif
1498ada2ccaSBram Moolenaar
1508ada2ccaSBram Moolenaar  " Add the diff highlight class to class list if used and it's not there yet.
1518ada2ccaSBram Moolenaar  " Add diff groups to the end so they override the other highlighting.
1528ada2ccaSBram Moolenaar  if a:diff_style_name != ""
1538ada2ccaSBram Moolenaar    let s:diff_id = hlID(a:diff_style_name)
1548ada2ccaSBram Moolenaar    if index(s:idlist, s:diff_id) == -1
1558ada2ccaSBram Moolenaar      call add(s:idlist, s:diff_id)
1568ada2ccaSBram Moolenaar    endif
15735a9aaabSBram Moolenaar  endif
15835a9aaabSBram Moolenaar
15935a9aaabSBram Moolenaar  return formatted
16035a9aaabSBram Moolenaarendfun
16135a9aaabSBram Moolenaar
162071d4279SBram Moolenaar" Return CSS style describing given highlight id (can be empty)
163071d4279SBram Moolenaarfunction! s:CSS1(id)
164071d4279SBram Moolenaar  let a = ""
165071d4279SBram Moolenaar  if synIDattr(a:id, "inverse")
166071d4279SBram Moolenaar    " For inverse, we always must set both colors (and exchange them)
167071d4279SBram Moolenaar    let x = s:HtmlColor(synIDattr(a:id, "bg#", s:whatterm))
168071d4279SBram Moolenaar    let a = a . "color: " . ( x != "" ? x : s:bgc ) . "; "
169071d4279SBram Moolenaar    let x = s:HtmlColor(synIDattr(a:id, "fg#", s:whatterm))
170071d4279SBram Moolenaar    let a = a . "background-color: " . ( x != "" ? x : s:fgc ) . "; "
171071d4279SBram Moolenaar  else
172071d4279SBram Moolenaar    let x = s:HtmlColor(synIDattr(a:id, "fg#", s:whatterm))
173071d4279SBram Moolenaar    if x != "" | let a = a . "color: " . x . "; " | endif
174071d4279SBram Moolenaar    let x = s:HtmlColor(synIDattr(a:id, "bg#", s:whatterm))
175071d4279SBram Moolenaar    if x != "" | let a = a . "background-color: " . x . "; " | endif
176071d4279SBram Moolenaar  endif
177071d4279SBram Moolenaar  if synIDattr(a:id, "bold") | let a = a . "font-weight: bold; " | endif
178071d4279SBram Moolenaar  if synIDattr(a:id, "italic") | let a = a . "font-style: italic; " | endif
179071d4279SBram Moolenaar  if synIDattr(a:id, "underline") | let a = a . "text-decoration: underline; " | endif
180071d4279SBram Moolenaar  return a
181071d4279SBram Moolenaarendfun
182071d4279SBram Moolenaar
183076e8b2aSBram Moolenaarif s:settings.dynamic_folds
1845c73622aSBram Moolenaar  " compares two folds as stored in our list of folds
1855c73622aSBram Moolenaar  " A fold is "less" than another if it starts at an earlier line number,
1865c73622aSBram Moolenaar  " or ends at a later line number, ties broken by fold level
1875c73622aSBram Moolenaar  function! s:FoldCompare(f1, f2)
1885c73622aSBram Moolenaar    if a:f1.firstline != a:f2.firstline
1895c73622aSBram Moolenaar      " put it before if it starts earlier
1905c73622aSBram Moolenaar      return a:f1.firstline - a:f2.firstline
1915c73622aSBram Moolenaar    elseif a:f1.lastline != a:f2.lastline
1925c73622aSBram Moolenaar      " put it before if it ends later
1935c73622aSBram Moolenaar      return a:f2.lastline - a:f1.lastline
1945c73622aSBram Moolenaar    else
1955c73622aSBram Moolenaar      " if folds begin and end on the same lines, put lowest fold level first
1965c73622aSBram Moolenaar      return a:f1.level - a:f2.level
1975c73622aSBram Moolenaar    endif
1985c73622aSBram Moolenaar  endfunction
1995c73622aSBram Moolenaar
2005c73622aSBram Moolenaarendif
2015c73622aSBram Moolenaar
202071d4279SBram Moolenaar
203071d4279SBram Moolenaar" Set some options to make it work faster.
204071d4279SBram Moolenaar" Don't report changes for :substitute, there will be many of them.
2058df7f888SBram Moolenaar" Don't change other windows; turn off scroll bind temporarily
206071d4279SBram Moolenaarlet s:old_title = &title
207071d4279SBram Moolenaarlet s:old_icon = &icon
208071d4279SBram Moolenaarlet s:old_et = &l:et
2098df7f888SBram Moolenaarlet s:old_bind = &l:scrollbind
210071d4279SBram Moolenaarlet s:old_report = &report
211071d4279SBram Moolenaarlet s:old_search = @/
212349b2fb0SBram Moolenaarlet s:old_more = &more
213071d4279SBram Moolenaarset notitle noicon
214071d4279SBram Moolenaarsetlocal et
215349b2fb0SBram Moolenaarset nomore
216071d4279SBram Moolenaarset report=1000000
2178df7f888SBram Moolenaarsetlocal noscrollbind
218071d4279SBram Moolenaar
2197510fe74SBram Moolenaarif exists(':ownsyntax') && exists('w:current_syntax')
2207510fe74SBram Moolenaar  let s:current_syntax = w:current_syntax
2217510fe74SBram Moolenaarelseif exists('b:current_syntax')
2227510fe74SBram Moolenaar  let s:current_syntax = b:current_syntax
2237510fe74SBram Moolenaarelse
2247510fe74SBram Moolenaar  let s:current_syntax = 'none'
2257510fe74SBram Moolenaarendif
2267510fe74SBram Moolenaar
2277510fe74SBram Moolenaarif s:current_syntax == ''
2287510fe74SBram Moolenaar  let s:current_syntax = 'none'
2297510fe74SBram Moolenaarendif
2307510fe74SBram Moolenaar
231071d4279SBram Moolenaar" Split window to create a buffer with the HTML file.
232071d4279SBram Moolenaarlet s:orgbufnr = winbufnr(0)
233349b2fb0SBram Moolenaarlet s:origwin_stl = &l:stl
234071d4279SBram Moolenaarif expand("%") == ""
235076e8b2aSBram Moolenaar  exec 'new Untitled.'.(s:settings.use_xhtml ? 'x' : '').'html'
236071d4279SBram Moolenaarelse
237076e8b2aSBram Moolenaar  exec 'new %.'.(s:settings.use_xhtml ? 'x' : '').'html'
238071d4279SBram Moolenaarendif
239349b2fb0SBram Moolenaar
240349b2fb0SBram Moolenaar" Resize the new window to very small in order to make it draw faster
241349b2fb0SBram Moolenaarlet s:old_winheight = winheight(0)
242349b2fb0SBram Moolenaarlet s:old_winfixheight = &l:winfixheight
243349b2fb0SBram Moolenaarif s:old_winheight > 2
244349b2fb0SBram Moolenaar  resize 1 " leave enough room to view one line at a time
245349b2fb0SBram Moolenaar  norm! G
246349b2fb0SBram Moolenaar  norm! zt
247349b2fb0SBram Moolenaarendif
248349b2fb0SBram Moolenaarsetlocal winfixheight
249349b2fb0SBram Moolenaar
250349b2fb0SBram Moolenaarlet s:newwin_stl = &l:stl
251349b2fb0SBram Moolenaar
252349b2fb0SBram Moolenaar" on the new window, set the least time-consuming fold method
253349b2fb0SBram Moolenaarlet s:old_fdm = &foldmethod
2548df7f888SBram Moolenaarlet s:old_fen = &foldenable
255349b2fb0SBram Moolenaarsetlocal foldmethod=manual
2568df7f888SBram Moolenaarsetlocal nofoldenable
257349b2fb0SBram Moolenaar
258071d4279SBram Moolenaarlet s:newwin = winnr()
259071d4279SBram Moolenaarlet s:orgwin = bufwinnr(s:orgbufnr)
260071d4279SBram Moolenaar
261349b2fb0SBram Moolenaarsetlocal modifiable
262071d4279SBram Moolenaar%d
263071d4279SBram Moolenaarlet s:old_paste = &paste
264071d4279SBram Moolenaarset paste
265071d4279SBram Moolenaarlet s:old_magic = &magic
266071d4279SBram Moolenaarset magic
267071d4279SBram Moolenaar
268*166af9bbSBram Moolenaar" set the fileencoding to match the charset we'll be using
269*166af9bbSBram Moolenaarlet &l:fileencoding=s:settings.vim_encoding
270*166af9bbSBram Moolenaar
271*166af9bbSBram Moolenaar" According to http://www.w3.org/TR/html4/charset.html#doc-char-set, the byte
272*166af9bbSBram Moolenaar" order mark is highly recommend on the web when using multibyte encodings. But,
273*166af9bbSBram Moolenaar" it is not a good idea to include it on UTF-8 files. Otherwise, let Vim
274*166af9bbSBram Moolenaar" determine when it is actually inserted.
275*166af9bbSBram Moolenaarif s:settings.vim_encoding == 'utf-8'
276*166af9bbSBram Moolenaar  setlocal nobomb
277*166af9bbSBram Moolenaarelse
278*166af9bbSBram Moolenaar  setlocal bomb
279*166af9bbSBram Moolenaarendif
280*166af9bbSBram Moolenaar
281349b2fb0SBram Moolenaarlet s:lines = []
282349b2fb0SBram Moolenaar
283076e8b2aSBram Moolenaarif s:settings.use_xhtml
284bebca9daSBram Moolenaar  if s:settings.encoding != ""
285bebca9daSBram Moolenaar    call add(s:lines, "<?xml version=\"1.0\" encoding=\"" . s:settings.encoding . "\"?>")
2861cd871b5SBram Moolenaar  else
287349b2fb0SBram Moolenaar    call add(s:lines, "<?xml version=\"1.0\"?>")
2881cd871b5SBram Moolenaar  endif
28935a9aaabSBram Moolenaar  let s:tag_close = ' />'
290071d4279SBram Moolenaarelse
29135a9aaabSBram Moolenaar  let s:tag_close = '>'
29235a9aaabSBram Moolenaarendif
29335a9aaabSBram Moolenaar
29435a9aaabSBram Moolenaarlet s:HtmlSpace = ' '
295c1e37901SBram Moolenaarlet s:LeadingSpace = ' '
29635a9aaabSBram Moolenaarlet s:HtmlEndline = ''
297076e8b2aSBram Moolenaarif s:settings.no_pre
29835a9aaabSBram Moolenaar  let s:HtmlEndline = '<br' . s:tag_close
299c1e37901SBram Moolenaar  let s:LeadingSpace = '&nbsp;'
300c1e37901SBram Moolenaar  let s:HtmlSpace = '\' . s:LeadingSpace
301071d4279SBram Moolenaarendif
302071d4279SBram Moolenaar
303071d4279SBram Moolenaar" HTML header, with the title and generator ;-). Left free space for the CSS,
304071d4279SBram Moolenaar" to be filled at the end.
305349b2fb0SBram Moolenaarcall extend(s:lines, [
306349b2fb0SBram Moolenaar      \ "<html>",
307bebca9daSBram Moolenaar      \ "<head>"])
308bebca9daSBram Moolenaar" include encoding as close to the top as possible, but only if not already
309bebca9daSBram Moolenaar" contained in XML information (to avoid haggling over content type)
310bebca9daSBram Moolenaarif s:settings.encoding != "" && !s:settings.use_xhtml
311bebca9daSBram Moolenaar  call add(s:lines, "<meta http-equiv=\"content-type\" content=\"text/html; charset=" . s:settings.encoding . '"' . s:tag_close)
312bebca9daSBram Moolenaarendif
313bebca9daSBram Moolenaarcall extend(s:lines, [
314349b2fb0SBram Moolenaar      \ ("<title>".expand("%:p:~")."</title>"),
315349b2fb0SBram Moolenaar      \ ("<meta name=\"Generator\" content=\"Vim/".v:version/100.".".v:version%100.'"'.s:tag_close),
316bebca9daSBram Moolenaar      \ ("<meta name=\"plugin-version\" content=\"".g:loaded_2html_plugin.'"'.s:tag_close)
317349b2fb0SBram Moolenaar      \ ])
3187510fe74SBram Moolenaarcall add(s:lines, '<meta name="syntax" content="'.s:current_syntax.'"'.s:tag_close)
319076e8b2aSBram Moolenaarcall add(s:lines, '<meta name="settings" content="'.
320076e8b2aSBram Moolenaar      \ join(filter(keys(s:settings),'s:settings[v:val]'),',').
321076e8b2aSBram Moolenaar      \ '"'.s:tag_close)
322313b7237SBram Moolenaar
323076e8b2aSBram Moolenaarif s:settings.use_css
324076e8b2aSBram Moolenaar  if s:settings.dynamic_folds
325076e8b2aSBram Moolenaar    if s:settings.hover_unfold
3265c73622aSBram Moolenaar      " if we are doing hover_unfold, use css 2 with css 1 fallback for IE6
327349b2fb0SBram Moolenaar      call extend(s:lines, [
328349b2fb0SBram Moolenaar	    \ "<style type=\"text/css\">",
329bebca9daSBram Moolenaar	    \ s:settings.use_xhtml ? "" : "<!--",
330349b2fb0SBram Moolenaar	    \ ".FoldColumn { text-decoration: none; white-space: pre; }",
331349b2fb0SBram Moolenaar	    \ "",
332349b2fb0SBram Moolenaar	    \ "body * { margin: 0; padding: 0; }", "",
333349b2fb0SBram Moolenaar	    \ ".open-fold   > .Folded { display: none;  }",
334349b2fb0SBram Moolenaar	    \ ".open-fold   > .fulltext { display: inline; }",
335349b2fb0SBram Moolenaar	    \ ".closed-fold > .fulltext { display: none;  }",
336349b2fb0SBram Moolenaar	    \ ".closed-fold > .Folded { display: inline; }",
337349b2fb0SBram Moolenaar	    \ "",
338349b2fb0SBram Moolenaar	    \ ".open-fold   > .toggle-open   { display: none;   }",
339349b2fb0SBram Moolenaar	    \ ".open-fold   > .toggle-closed { display: inline; }",
340349b2fb0SBram Moolenaar	    \ ".closed-fold > .toggle-open   { display: inline; }",
341349b2fb0SBram Moolenaar	    \ ".closed-fold > .toggle-closed { display: none;   }",
342349b2fb0SBram Moolenaar	    \ "", "",
343349b2fb0SBram Moolenaar	    \ '/* opening a fold while hovering won''t be supported by IE6 and other',
344349b2fb0SBram Moolenaar	    \ "similar browsers, but it should fail gracefully. */",
345349b2fb0SBram Moolenaar	    \ ".closed-fold:hover > .fulltext { display: inline; }",
346349b2fb0SBram Moolenaar	    \ ".closed-fold:hover > .toggle-filler { display: none; }",
347349b2fb0SBram Moolenaar	    \ ".closed-fold:hover > .Folded { display: none; }",
348bebca9daSBram Moolenaar	    \ s:settings.use_xhtml ? "" : '-->',
3498df7f888SBram Moolenaar	    \ '</style>'])
350bebca9daSBram Moolenaar      " TODO: IE7 doesn't *actually* support XHTML, maybe we should remove this.
351bebca9daSBram Moolenaar      " But if it's served up as tag soup, maybe the following will work, so
352bebca9daSBram Moolenaar      " leave it in for now.
353bebca9daSBram Moolenaar      call extend(s:lines, [
354349b2fb0SBram Moolenaar	    \ "<!--[if lt IE 7]><style type=\"text/css\">",
355349b2fb0SBram Moolenaar	    \ ".open-fold   .Folded      { display: none; }",
356349b2fb0SBram Moolenaar	    \ ".open-fold   .fulltext      { display: inline; }",
357349b2fb0SBram Moolenaar	    \ ".open-fold   .toggle-open   { display: none; }",
358349b2fb0SBram Moolenaar	    \ ".closed-fold .toggle-closed { display: inline; }",
359349b2fb0SBram Moolenaar	    \ "",
360349b2fb0SBram Moolenaar	    \ ".closed-fold .fulltext      { display: none; }",
361349b2fb0SBram Moolenaar	    \ ".closed-fold .Folded      { display: inline; }",
362349b2fb0SBram Moolenaar	    \ ".closed-fold .toggle-open   { display: inline; }",
363349b2fb0SBram Moolenaar	    \ ".closed-fold .toggle-closed { display: none; }",
364349b2fb0SBram Moolenaar	    \ "</style>",
365349b2fb0SBram Moolenaar	    \ "<![endif]-->",
366349b2fb0SBram Moolenaar	    \])
3675c73622aSBram Moolenaar    else
3685c73622aSBram Moolenaar      " if we aren't doing hover_unfold, use CSS 1 only
369349b2fb0SBram Moolenaar      call extend(s:lines, [
370349b2fb0SBram Moolenaar	    \ "<style type=\"text/css\">",
371bebca9daSBram Moolenaar	    \ s:settings.use_xhtml ? "" :"<!--",
372349b2fb0SBram Moolenaar	    \ ".FoldColumn { text-decoration: none; white-space: pre; }",
373349b2fb0SBram Moolenaar	    \ ".open-fold   .Folded      { display: none; }",
374349b2fb0SBram Moolenaar	    \ ".open-fold   .fulltext      { display: inline; }",
375349b2fb0SBram Moolenaar	    \ ".open-fold   .toggle-open   { display: none; }",
376349b2fb0SBram Moolenaar	    \ ".closed-fold .toggle-closed { display: inline; }",
377349b2fb0SBram Moolenaar	    \ "",
378349b2fb0SBram Moolenaar	    \ ".closed-fold .fulltext      { display: none; }",
379349b2fb0SBram Moolenaar	    \ ".closed-fold .Folded      { display: inline; }",
380349b2fb0SBram Moolenaar	    \ ".closed-fold .toggle-open   { display: inline; }",
381349b2fb0SBram Moolenaar	    \ ".closed-fold .toggle-closed { display: none; }",
382bebca9daSBram Moolenaar	    \ s:settings.use_xhtml ? "" : '-->',
383349b2fb0SBram Moolenaar	    \ '</style>'
384349b2fb0SBram Moolenaar	    \])
3855c73622aSBram Moolenaar    endif
3865c73622aSBram Moolenaar  else
3875c73622aSBram Moolenaar    " if we aren't doing any dynamic folding, no need for any special rules
388349b2fb0SBram Moolenaar    call extend(s:lines, [
389349b2fb0SBram Moolenaar	  \ "<style type=\"text/css\">",
390bebca9daSBram Moolenaar	  \ s:settings.use_xhtml ? "" : "<!--",
391bebca9daSBram Moolenaar	  \ s:settings.use_xhtml ? "" : '-->',
392349b2fb0SBram Moolenaar	  \ "</style>",
393349b2fb0SBram Moolenaar	  \])
394071d4279SBram Moolenaar  endif
3955c73622aSBram Moolenaarendif
3965c73622aSBram Moolenaar
3975c73622aSBram Moolenaar" insert javascript to toggle folds open and closed
398076e8b2aSBram Moolenaarif s:settings.dynamic_folds
399349b2fb0SBram Moolenaar  call extend(s:lines, [
400349b2fb0SBram Moolenaar	\ "",
401349b2fb0SBram Moolenaar	\ "<script type='text/javascript'>",
402bebca9daSBram Moolenaar	\ s:settings.use_xhtml ? '//<![CDATA[' : "<!--",
403349b2fb0SBram Moolenaar	\ "function toggleFold(objID)",
404349b2fb0SBram Moolenaar	\ "{",
405349b2fb0SBram Moolenaar	\ "  var fold;",
406349b2fb0SBram Moolenaar	\ "  fold = document.getElementById(objID);",
407349b2fb0SBram Moolenaar	\ "  if(fold.className == 'closed-fold')",
408349b2fb0SBram Moolenaar	\ "  {",
409349b2fb0SBram Moolenaar	\ "    fold.className = 'open-fold';",
410349b2fb0SBram Moolenaar	\ "  }",
411349b2fb0SBram Moolenaar	\ "  else if (fold.className == 'open-fold')",
412349b2fb0SBram Moolenaar	\ "  {",
413349b2fb0SBram Moolenaar	\ "    fold.className = 'closed-fold';",
414349b2fb0SBram Moolenaar	\ "  }",
415349b2fb0SBram Moolenaar	\ "}",
416bebca9daSBram Moolenaar	\ s:settings.use_xhtml ? '//]]>' : '-->',
417349b2fb0SBram Moolenaar	\ "</script>"
418349b2fb0SBram Moolenaar	\])
4195c73622aSBram Moolenaarendif
4205c73622aSBram Moolenaar
421076e8b2aSBram Moolenaarif s:settings.no_pre
422349b2fb0SBram Moolenaar  call extend(s:lines, ["</head>", "<body>"])
423071d4279SBram Moolenaarelse
424349b2fb0SBram Moolenaar  call extend(s:lines, ["</head>", "<body>", "<pre>"])
425071d4279SBram Moolenaarendif
426071d4279SBram Moolenaar
427071d4279SBram Moolenaarexe s:orgwin . "wincmd w"
428071d4279SBram Moolenaar
429071d4279SBram Moolenaar" List of all id's
4308ada2ccaSBram Moolenaarlet s:idlist = []
431071d4279SBram Moolenaar
432349b2fb0SBram Moolenaar" set up progress bar in the status line
433076e8b2aSBram Moolenaarif !s:settings.no_progress
434349b2fb0SBram Moolenaar  " ProgressBar Indicator
435349b2fb0SBram Moolenaar  let s:progressbar={}
436349b2fb0SBram Moolenaar
437349b2fb0SBram Moolenaar  " Progessbar specific functions
438349b2fb0SBram Moolenaar  func! s:ProgressBar(title, max_value, winnr)
439349b2fb0SBram Moolenaar    let pgb=copy(s:progressbar)
440349b2fb0SBram Moolenaar    let pgb.title = a:title.' '
441349b2fb0SBram Moolenaar    let pgb.max_value = a:max_value
442349b2fb0SBram Moolenaar    let pgb.winnr = a:winnr
443349b2fb0SBram Moolenaar    let pgb.cur_value = 0
444349b2fb0SBram Moolenaar    let pgb.items = { 'title'   : { 'color' : 'Statusline' },
445349b2fb0SBram Moolenaar	  \'bar'     : { 'color' : 'Statusline' , 'fillcolor' : 'DiffDelete' , 'bg' : 'Statusline' } ,
446349b2fb0SBram Moolenaar	  \'counter' : { 'color' : 'Statusline' } }
447349b2fb0SBram Moolenaar    let pgb.last_value = 0
448349b2fb0SBram Moolenaar    let pgb.needs_redraw = 0
449349b2fb0SBram Moolenaar    " Note that you must use len(split) instead of len() if you want to use
450349b2fb0SBram Moolenaar    " unicode in title.
451349b2fb0SBram Moolenaar    "
452349b2fb0SBram Moolenaar    " Subtract 3 for spacing around the title.
453349b2fb0SBram Moolenaar    " Subtract 4 for the percentage display.
454349b2fb0SBram Moolenaar    " Subtract 2 for spacing before this.
455349b2fb0SBram Moolenaar    " Subtract 2 more for the '|' on either side of the progress bar
456349b2fb0SBram Moolenaar    let pgb.subtractedlen=len(split(pgb.title, '\zs'))+3+4+2+2
457349b2fb0SBram Moolenaar    let pgb.max_len = 0
458349b2fb0SBram Moolenaar    set laststatus=2
459349b2fb0SBram Moolenaar    return pgb
460349b2fb0SBram Moolenaar  endfun
461349b2fb0SBram Moolenaar
462349b2fb0SBram Moolenaar  " Function: progressbar.calculate_ticks() {{{1
463349b2fb0SBram Moolenaar  func! s:progressbar.calculate_ticks(pb_len)
464349b2fb0SBram Moolenaar    if a:pb_len<=0
465349b2fb0SBram Moolenaar      let pb_len = 100
466349b2fb0SBram Moolenaar    else
467349b2fb0SBram Moolenaar      let pb_len = a:pb_len
468349b2fb0SBram Moolenaar    endif
469349b2fb0SBram Moolenaar    let self.progress_ticks = map(range(pb_len+1), "v:val * self.max_value / pb_len")
470349b2fb0SBram Moolenaar  endfun
471349b2fb0SBram Moolenaar
472349b2fb0SBram Moolenaar  "Function: progressbar.paint()
473349b2fb0SBram Moolenaar  func! s:progressbar.paint()
474349b2fb0SBram Moolenaar    " Recalculate widths.
475349b2fb0SBram Moolenaar    let max_len = winwidth(self.winnr)
476349b2fb0SBram Moolenaar    let pb_len = 0
477349b2fb0SBram Moolenaar    " always true on first call because of initial value of self.max_len
478349b2fb0SBram Moolenaar    if max_len != self.max_len
479349b2fb0SBram Moolenaar      let self.max_len = max_len
480349b2fb0SBram Moolenaar
481349b2fb0SBram Moolenaar      " Progressbar length
482349b2fb0SBram Moolenaar      let pb_len = max_len - self.subtractedlen
483349b2fb0SBram Moolenaar
484349b2fb0SBram Moolenaar      call self.calculate_ticks(pb_len)
485349b2fb0SBram Moolenaar
486349b2fb0SBram Moolenaar      let self.needs_redraw = 1
487349b2fb0SBram Moolenaar      let cur_value = 0
488349b2fb0SBram Moolenaar      let self.pb_len = pb_len
489349b2fb0SBram Moolenaar    else
490349b2fb0SBram Moolenaar      " start searching at the last found index to make the search for the
491349b2fb0SBram Moolenaar      " appropriate tick value normally take 0 or 1 comparisons
492349b2fb0SBram Moolenaar      let cur_value = self.last_value
493349b2fb0SBram Moolenaar      let pb_len = self.pb_len
494349b2fb0SBram Moolenaar    endif
495349b2fb0SBram Moolenaar
496349b2fb0SBram Moolenaar    let cur_val_max = pb_len > 0 ? pb_len : 100
497349b2fb0SBram Moolenaar
498349b2fb0SBram Moolenaar    " find the current progress bar position based on precalculated thresholds
499349b2fb0SBram Moolenaar    while cur_value < cur_val_max && self.cur_value > self.progress_ticks[cur_value]
500349b2fb0SBram Moolenaar      let cur_value += 1
501349b2fb0SBram Moolenaar    endwhile
502349b2fb0SBram Moolenaar
503349b2fb0SBram Moolenaar    " update progress bar
504349b2fb0SBram Moolenaar    if self.last_value != cur_value || self.needs_redraw || self.cur_value == self.max_value
505349b2fb0SBram Moolenaar      let self.needs_redraw = 1
506349b2fb0SBram Moolenaar      let self.last_value = cur_value
507349b2fb0SBram Moolenaar
508349b2fb0SBram Moolenaar      let t_color  = self.items.title.color
509349b2fb0SBram Moolenaar      let b_fcolor = self.items.bar.fillcolor
510349b2fb0SBram Moolenaar      let b_color  = self.items.bar.color
511349b2fb0SBram Moolenaar      let c_color  = self.items.counter.color
512349b2fb0SBram Moolenaar
513349b2fb0SBram Moolenaar      let stl =  "%#".t_color."#%-( ".self.title." %)".
514349b2fb0SBram Moolenaar	    \"%#".b_color."#".
515349b2fb0SBram Moolenaar	    \(pb_len>0 ?
516349b2fb0SBram Moolenaar	    \	('|%#'.b_fcolor."#%-(".repeat(" ",cur_value)."%)".
517349b2fb0SBram Moolenaar	    \	 '%#'.b_color."#".repeat(" ",pb_len-cur_value)."|"):
518349b2fb0SBram Moolenaar	    \	('')).
519349b2fb0SBram Moolenaar	    \"%=%#".c_color."#%( ".printf("%3.d ",100*self.cur_value/self.max_value)."%% %)"
520349b2fb0SBram Moolenaar      call setwinvar(self.winnr, '&stl', stl)
521349b2fb0SBram Moolenaar    endif
522349b2fb0SBram Moolenaar  endfun
523349b2fb0SBram Moolenaar
524349b2fb0SBram Moolenaar  func! s:progressbar.incr( ... )
525349b2fb0SBram Moolenaar    let self.cur_value += (a:0 ? a:1 : 1)
526349b2fb0SBram Moolenaar    " if we were making a general-purpose progress bar, we'd need to limit to a
527349b2fb0SBram Moolenaar    " lower limit as well, but since we always increment with a positive value
528349b2fb0SBram Moolenaar    " in this script, we only need limit the upper value
529349b2fb0SBram Moolenaar    let self.cur_value = (self.cur_value > self.max_value ? self.max_value : self.cur_value)
530349b2fb0SBram Moolenaar    call self.paint()
531349b2fb0SBram Moolenaar  endfun
532349b2fb0SBram Moolenaar  " }}}
533076e8b2aSBram Moolenaar  if s:settings.dynamic_folds
534349b2fb0SBram Moolenaar    " to process folds we make two passes through each line
535349b2fb0SBram Moolenaar    let s:pgb = s:ProgressBar("Processing folds:", line('$')*2, s:orgwin)
536349b2fb0SBram Moolenaar  endif
537349b2fb0SBram Moolenaarendif
538349b2fb0SBram Moolenaar
5395c73622aSBram Moolenaar" First do some preprocessing for dynamic folding. Do this for the entire file
5405c73622aSBram Moolenaar" so we don't accidentally start within a closed fold or something.
5415c73622aSBram Moolenaarlet s:allfolds = []
5425c73622aSBram Moolenaar
543076e8b2aSBram Moolenaarif s:settings.dynamic_folds
5445c73622aSBram Moolenaar  let s:lnum = 1
5455c73622aSBram Moolenaar  let s:end = line('$')
5465c73622aSBram Moolenaar  " save the fold text and set it to the default so we can find fold levels
5475c73622aSBram Moolenaar  let s:foldtext_save = &foldtext
548349b2fb0SBram Moolenaar  setlocal foldtext&
5495c73622aSBram Moolenaar
5505c73622aSBram Moolenaar  " we will set the foldcolumn in the html to the greater of the maximum fold
5515c73622aSBram Moolenaar  " level and the current foldcolumn setting
5525c73622aSBram Moolenaar  let s:foldcolumn = &foldcolumn
5535c73622aSBram Moolenaar
5545c73622aSBram Moolenaar  " get all info needed to describe currently closed folds
555349b2fb0SBram Moolenaar  while s:lnum <= s:end
5565c73622aSBram Moolenaar    if foldclosed(s:lnum) == s:lnum
5575c73622aSBram Moolenaar      " default fold text has '+-' and then a number of dashes equal to fold
5585c73622aSBram Moolenaar      " level, so subtract 2 from index of first non-dash after the dashes
5595c73622aSBram Moolenaar      " in order to get the fold level of the current fold
5605c73622aSBram Moolenaar      let s:level = match(foldtextresult(s:lnum), '+-*\zs[^-]') - 2
5615c73622aSBram Moolenaar      if s:level+1 > s:foldcolumn
5625c73622aSBram Moolenaar	let s:foldcolumn = s:level+1
5635c73622aSBram Moolenaar      endif
5645c73622aSBram Moolenaar      " store fold info for later use
5655c73622aSBram Moolenaar      let s:newfold = {'firstline': s:lnum, 'lastline': foldclosedend(s:lnum), 'level': s:level,'type': "closed-fold"}
5665c73622aSBram Moolenaar      call add(s:allfolds, s:newfold)
5675c73622aSBram Moolenaar      " open the fold so we can find any contained folds
5685c73622aSBram Moolenaar      execute s:lnum."foldopen"
5695c73622aSBram Moolenaar    else
570076e8b2aSBram Moolenaar      if !s:settings.no_progress
571349b2fb0SBram Moolenaar	call s:pgb.incr()
572349b2fb0SBram Moolenaar	if s:pgb.needs_redraw
573349b2fb0SBram Moolenaar	  redrawstatus
574349b2fb0SBram Moolenaar	  let s:pgb.needs_redraw = 0
575349b2fb0SBram Moolenaar	endif
576349b2fb0SBram Moolenaar      endif
5775c73622aSBram Moolenaar      let s:lnum = s:lnum + 1
5785c73622aSBram Moolenaar    endif
5795c73622aSBram Moolenaar  endwhile
5805c73622aSBram Moolenaar
5815c73622aSBram Moolenaar  " close all folds to get info for originally open folds
5825c73622aSBram Moolenaar  silent! %foldclose!
5835c73622aSBram Moolenaar  let s:lnum = 1
5845c73622aSBram Moolenaar
5855c73622aSBram Moolenaar  " the originally open folds will be all folds we encounter that aren't
5865c73622aSBram Moolenaar  " already in the list of closed folds
587349b2fb0SBram Moolenaar  while s:lnum <= s:end
5885c73622aSBram Moolenaar    if foldclosed(s:lnum) == s:lnum
5895c73622aSBram Moolenaar      " default fold text has '+-' and then a number of dashes equal to fold
5905c73622aSBram Moolenaar      " level, so subtract 2 from index of first non-dash after the dashes
5915c73622aSBram Moolenaar      " in order to get the fold level of the current fold
5925c73622aSBram Moolenaar      let s:level = match(foldtextresult(s:lnum), '+-*\zs[^-]') - 2
5935c73622aSBram Moolenaar      if s:level+1 > s:foldcolumn
5945c73622aSBram Moolenaar	let s:foldcolumn = s:level+1
5955c73622aSBram Moolenaar      endif
5965c73622aSBram Moolenaar      let s:newfold = {'firstline': s:lnum, 'lastline': foldclosedend(s:lnum), 'level': s:level,'type': "closed-fold"}
5975c73622aSBram Moolenaar      " only add the fold if we don't already have it
5985c73622aSBram Moolenaar      if empty(s:allfolds) || index(s:allfolds, s:newfold) == -1
5995c73622aSBram Moolenaar	let s:newfold.type = "open-fold"
6005c73622aSBram Moolenaar	call add(s:allfolds, s:newfold)
6015c73622aSBram Moolenaar      endif
6025c73622aSBram Moolenaar      " open the fold so we can find any contained folds
6035c73622aSBram Moolenaar      execute s:lnum."foldopen"
6045c73622aSBram Moolenaar    else
605076e8b2aSBram Moolenaar      if !s:settings.no_progress
606349b2fb0SBram Moolenaar	call s:pgb.incr()
607349b2fb0SBram Moolenaar	if s:pgb.needs_redraw
608349b2fb0SBram Moolenaar	  redrawstatus
609349b2fb0SBram Moolenaar	  let s:pgb.needs_redraw = 0
610349b2fb0SBram Moolenaar	endif
611349b2fb0SBram Moolenaar      endif
6125c73622aSBram Moolenaar      let s:lnum = s:lnum + 1
6135c73622aSBram Moolenaar    endif
6145c73622aSBram Moolenaar  endwhile
6155c73622aSBram Moolenaar
6165c73622aSBram Moolenaar  " sort the folds so that we only ever need to look at the first item in the
6175c73622aSBram Moolenaar  " list of folds
6185c73622aSBram Moolenaar  call sort(s:allfolds, "s:FoldCompare")
6195c73622aSBram Moolenaar
620349b2fb0SBram Moolenaar  let &l:foldtext = s:foldtext_save
6215c73622aSBram Moolenaar  unlet s:foldtext_save
6225c73622aSBram Moolenaar
6235c73622aSBram Moolenaar  " close all folds again so we can get the fold text as we go
6245c73622aSBram Moolenaar  silent! %foldclose!
6255c73622aSBram Moolenaarendif
6265c73622aSBram Moolenaar
6275c73622aSBram Moolenaar" Now loop over all lines in the original text to convert to html.
628071d4279SBram Moolenaar" Use html_start_line and html_end_line if they are set.
629b02cbe34SBram Moolenaarif exists("g:html_start_line")
630071d4279SBram Moolenaar  let s:lnum = html_start_line
631071d4279SBram Moolenaar  if s:lnum < 1 || s:lnum > line("$")
632071d4279SBram Moolenaar    let s:lnum = 1
633071d4279SBram Moolenaar  endif
634071d4279SBram Moolenaarelse
635071d4279SBram Moolenaar  let s:lnum = 1
636071d4279SBram Moolenaarendif
637b02cbe34SBram Moolenaarif exists("g:html_end_line")
638071d4279SBram Moolenaar  let s:end = html_end_line
639071d4279SBram Moolenaar  if s:end < s:lnum || s:end > line("$")
640071d4279SBram Moolenaar    let s:end = line("$")
641071d4279SBram Moolenaar  endif
642071d4279SBram Moolenaarelse
643071d4279SBram Moolenaar  let s:end = line("$")
644071d4279SBram Moolenaarendif
645071d4279SBram Moolenaar
6465c73622aSBram Moolenaar" stack to keep track of all the folds containing the current line
6475c73622aSBram Moolenaarlet s:foldstack = []
6485c73622aSBram Moolenaar
649076e8b2aSBram Moolenaarif !s:settings.no_progress
650349b2fb0SBram Moolenaar  let s:pgb = s:ProgressBar("Processing lines:", s:end - s:lnum + 1, s:orgwin)
651349b2fb0SBram Moolenaarendif
652349b2fb0SBram Moolenaar
653076e8b2aSBram Moolenaarif s:settings.number_lines
6545c73622aSBram Moolenaar  let s:margin = strlen(s:end) + 1
6555c73622aSBram Moolenaarelse
6565c73622aSBram Moolenaar  let s:margin = 0
6575c73622aSBram Moolenaarendif
6585c73622aSBram Moolenaar
659076e8b2aSBram Moolenaarif has('folding') && !s:settings.ignore_folding
66035a9aaabSBram Moolenaar  let s:foldfillchar = &fillchars[matchend(&fillchars, 'fold:')]
66135a9aaabSBram Moolenaar  if s:foldfillchar == ''
66235a9aaabSBram Moolenaar    let s:foldfillchar = '-'
6637b0294cbSBram Moolenaar  endif
66435a9aaabSBram Moolenaarendif
66535a9aaabSBram Moolenaarlet s:difffillchar = &fillchars[matchend(&fillchars, 'diff:')]
66635a9aaabSBram Moolenaarif s:difffillchar == ''
66735a9aaabSBram Moolenaar  let s:difffillchar = '-'
6687b0294cbSBram Moolenaarendif
6697b0294cbSBram Moolenaar
6705c73622aSBram Moolenaarlet s:foldId = 0
6717b0294cbSBram Moolenaar
672071d4279SBram Moolenaarwhile s:lnum <= s:end
673071d4279SBram Moolenaar
67447136d70SBram Moolenaar  " If there are filler lines for diff mode, show these above the line.
67547136d70SBram Moolenaar  let s:filler = diff_filler(s:lnum)
67647136d70SBram Moolenaar  if s:filler > 0
67747136d70SBram Moolenaar    let s:n = s:filler
67847136d70SBram Moolenaar    while s:n > 0
67935a9aaabSBram Moolenaar      let s:new = repeat(s:difffillchar, 3)
68047136d70SBram Moolenaar
681076e8b2aSBram Moolenaar      if s:n > 2 && s:n < s:filler && !s:settings.whole_filler
68235a9aaabSBram Moolenaar	let s:new = s:new . " " . s:filler . " inserted lines "
68335a9aaabSBram Moolenaar	let s:n = 2
68435a9aaabSBram Moolenaar      endif
68535a9aaabSBram Moolenaar
686076e8b2aSBram Moolenaar      if !s:settings.no_pre
68735a9aaabSBram Moolenaar	" HTML line wrapping is off--go ahead and fill to the margin
6885c73622aSBram Moolenaar	let s:new = s:new . repeat(s:difffillchar, &columns - strlen(s:new) - s:margin)
6895c73622aSBram Moolenaar      else
6905c73622aSBram Moolenaar	let s:new = s:new . repeat(s:difffillchar, 3)
69135a9aaabSBram Moolenaar      endif
69235a9aaabSBram Moolenaar
6938ada2ccaSBram Moolenaar      let s:new = s:HtmlFormat(s:new, "DiffDelete", "")
694076e8b2aSBram Moolenaar      if s:settings.number_lines
6955c73622aSBram Moolenaar	" Indent if line numbering is on; must be after escaping.
6965c73622aSBram Moolenaar	let s:new = repeat(s:LeadingSpace, s:margin) . s:new
6975c73622aSBram Moolenaar      endif
698349b2fb0SBram Moolenaar      call add(s:lines, s:new.s:HtmlEndline)
69935a9aaabSBram Moolenaar
70047136d70SBram Moolenaar      let s:n = s:n - 1
70147136d70SBram Moolenaar    endwhile
70247136d70SBram Moolenaar    unlet s:n
70347136d70SBram Moolenaar  endif
70447136d70SBram Moolenaar  unlet s:filler
70547136d70SBram Moolenaar
70647136d70SBram Moolenaar  " Start the line with the line number.
707076e8b2aSBram Moolenaar  if s:settings.number_lines
7085c73622aSBram Moolenaar    let s:numcol = repeat(' ', s:margin - 1 - strlen(s:lnum)) . s:lnum . ' '
70947136d70SBram Moolenaar  else
7105c73622aSBram Moolenaar    let s:numcol = ""
71147136d70SBram Moolenaar  endif
71247136d70SBram Moolenaar
7135c73622aSBram Moolenaar  let s:new = ""
7145c73622aSBram Moolenaar
715076e8b2aSBram Moolenaar  if has('folding') && !s:settings.ignore_folding && foldclosed(s:lnum) > -1 && !s:settings.dynamic_folds
7167b0294cbSBram Moolenaar    "
7175c73622aSBram Moolenaar    " This is the beginning of a folded block (with no dynamic folding)
7187b0294cbSBram Moolenaar    "
7195c73622aSBram Moolenaar    let s:new = s:numcol . foldtextresult(s:lnum)
720076e8b2aSBram Moolenaar    if !s:settings.no_pre
72135a9aaabSBram Moolenaar      " HTML line wrapping is off--go ahead and fill to the margin
72235a9aaabSBram Moolenaar      let s:new = s:new . repeat(s:foldfillchar, &columns - strlen(s:new))
7237b0294cbSBram Moolenaar    endif
7247b0294cbSBram Moolenaar
7258ada2ccaSBram Moolenaar    let s:new = s:HtmlFormat(s:new, "Folded", "")
7267b0294cbSBram Moolenaar
7277b0294cbSBram Moolenaar    " Skip to the end of the fold
728349b2fb0SBram Moolenaar    let s:new_lnum = foldclosedend(s:lnum)
729349b2fb0SBram Moolenaar
730076e8b2aSBram Moolenaar    if !s:settings.no_progress
731349b2fb0SBram Moolenaar      call s:pgb.incr(s:new_lnum - s:lnum)
732349b2fb0SBram Moolenaar    endif
733349b2fb0SBram Moolenaar
734349b2fb0SBram Moolenaar    let s:lnum = s:new_lnum
7357b0294cbSBram Moolenaar
7367b0294cbSBram Moolenaar  else
7377b0294cbSBram Moolenaar    "
7385c73622aSBram Moolenaar    " A line that is not folded, or doing dynamic folding.
7397b0294cbSBram Moolenaar    "
74035a9aaabSBram Moolenaar    let s:line = getline(s:lnum)
7417b0294cbSBram Moolenaar    let s:len = strlen(s:line)
7427b0294cbSBram Moolenaar
743076e8b2aSBram Moolenaar    if s:settings.dynamic_folds
7445c73622aSBram Moolenaar      " First insert a closing for any open folds that end on this line
7455c73622aSBram Moolenaar      while !empty(s:foldstack) && get(s:foldstack,0).lastline == s:lnum-1
7465c73622aSBram Moolenaar	let s:new = s:new."</span></span>"
7475c73622aSBram Moolenaar	call remove(s:foldstack, 0)
7485c73622aSBram Moolenaar      endwhile
7495c73622aSBram Moolenaar
7505c73622aSBram Moolenaar      " Now insert an opening any new folds that start on this line
7515c73622aSBram Moolenaar      let s:firstfold = 1
7525c73622aSBram Moolenaar      while !empty(s:allfolds) && get(s:allfolds,0).firstline == s:lnum
7535c73622aSBram Moolenaar	let s:foldId = s:foldId + 1
754349b2fb0SBram Moolenaar	let s:new .= "<span id='"
755349b2fb0SBram Moolenaar	let s:new .= (exists('g:html_diff_win_num') ? "win".g:html_diff_win_num : "")
756349b2fb0SBram Moolenaar	let s:new .= "fold".s:foldId."' class='".s:allfolds[0].type."'>"
757349b2fb0SBram Moolenaar
7585c73622aSBram Moolenaar
7595c73622aSBram Moolenaar	" Unless disabled, add a fold column for the opening line of a fold.
7605c73622aSBram Moolenaar	"
7615c73622aSBram Moolenaar	" Note that dynamic folds require using css so we just use css to take
7625c73622aSBram Moolenaar	" care of the leading spaces rather than using &nbsp; in the case of
7635c73622aSBram Moolenaar	" html_no_pre to make it easier
764076e8b2aSBram Moolenaar	if !s:settings.no_foldcolumn
7655c73622aSBram Moolenaar	  " add fold column that can open the new fold
7665c73622aSBram Moolenaar	  if s:allfolds[0].level > 1 && s:firstfold
7675c73622aSBram Moolenaar	    let s:new = s:new . "<a class='toggle-open FoldColumn' href='javascript:toggleFold(\"fold".s:foldstack[0].id."\")'>"
7685c73622aSBram Moolenaar	    let s:new = s:new . repeat('|', s:allfolds[0].level - 1) . "</a>"
7695c73622aSBram Moolenaar	  endif
7705c73622aSBram Moolenaar	  let s:new = s:new . "<a class='toggle-open FoldColumn' href='javascript:toggleFold(\"fold".s:foldId."\")'>+</a>"
7715c73622aSBram Moolenaar	  let s:new = s:new . "<a class='toggle-open "
7725c73622aSBram Moolenaar	  " If this is not the last fold we're opening on this line, we need
7735c73622aSBram Moolenaar	  " to keep the filler spaces hidden if the fold is opened by mouse
7745c73622aSBram Moolenaar	  " hover. If it is the last fold to open in the line, we shouldn't hide
7755c73622aSBram Moolenaar	  " them, so don't apply the toggle-filler class.
7765c73622aSBram Moolenaar	  if get(s:allfolds, 1, {'firstline': 0}).firstline == s:lnum
7775c73622aSBram Moolenaar	    let s:new = s:new . "toggle-filler "
7785c73622aSBram Moolenaar	  endif
7795c73622aSBram Moolenaar	  let s:new = s:new . "FoldColumn' href='javascript:toggleFold(\"fold".s:foldId."\")'>"
7805c73622aSBram Moolenaar	  let s:new = s:new . repeat(" ", s:foldcolumn - s:allfolds[0].level) . "</a>"
7815c73622aSBram Moolenaar
7825c73622aSBram Moolenaar	  " add fold column that can close the new fold
7835c73622aSBram Moolenaar	  let s:new = s:new . "<a class='toggle-closed FoldColumn' href='javascript:toggleFold(\"fold".s:foldId."\")'>"
7845c73622aSBram Moolenaar	  if s:firstfold
7855c73622aSBram Moolenaar	    let s:new = s:new . repeat('|', s:allfolds[0].level - 1)
7865c73622aSBram Moolenaar	  endif
7875c73622aSBram Moolenaar	  let s:new = s:new . "-"
7885c73622aSBram Moolenaar	  " only add spaces if we aren't opening another fold on the same line
7895c73622aSBram Moolenaar	  if get(s:allfolds, 1, {'firstline': 0}).firstline != s:lnum
7905c73622aSBram Moolenaar	    let s:new = s:new . repeat(" ", s:foldcolumn - s:allfolds[0].level)
7915c73622aSBram Moolenaar	  endif
7925c73622aSBram Moolenaar	  let s:new = s:new . "</a>"
7935c73622aSBram Moolenaar	  let s:firstfold = 0
7945c73622aSBram Moolenaar	endif
7955c73622aSBram Moolenaar
7965c73622aSBram Moolenaar	" add fold text, moving the span ending to the next line so collapsing
7975c73622aSBram Moolenaar	" of folds works correctly
7988ada2ccaSBram Moolenaar	let s:new = s:new . substitute(s:HtmlFormat(s:numcol . foldtextresult(s:lnum), "Folded", ""), '</span>', s:HtmlEndline.'\n\0', '')
7995c73622aSBram Moolenaar	let s:new = s:new . "<span class='fulltext'>"
8005c73622aSBram Moolenaar
8015c73622aSBram Moolenaar	" open the fold now that we have the fold text to allow retrieval of
8025c73622aSBram Moolenaar	" fold text for subsequent folds
8035c73622aSBram Moolenaar	execute s:lnum."foldopen"
8045c73622aSBram Moolenaar	call insert(s:foldstack, remove(s:allfolds,0))
8055c73622aSBram Moolenaar	let s:foldstack[0].id = s:foldId
8065c73622aSBram Moolenaar      endwhile
8075c73622aSBram Moolenaar
8085c73622aSBram Moolenaar      " Unless disabled, add a fold column for other lines.
8095c73622aSBram Moolenaar      "
8105c73622aSBram Moolenaar      " Note that dynamic folds require using css so we just use css to take
8115c73622aSBram Moolenaar      " care of the leading spaces rather than using &nbsp; in the case of
8125c73622aSBram Moolenaar      " html_no_pre to make it easier
813076e8b2aSBram Moolenaar      if !s:settings.no_foldcolumn
8145c73622aSBram Moolenaar	if empty(s:foldstack)
8157510fe74SBram Moolenaar	  " add the empty foldcolumn for unfolded lines if there is a fold
8167510fe74SBram Moolenaar	  " column at all
8177510fe74SBram Moolenaar	  if s:foldcolumn > 0
8188ada2ccaSBram Moolenaar	    let s:new = s:new . s:HtmlFormat(repeat(' ', s:foldcolumn), "FoldColumn", "")
8197510fe74SBram Moolenaar	  endif
8205c73622aSBram Moolenaar	else
8215c73622aSBram Moolenaar	  " add the fold column for folds not on the opening line
8225c73622aSBram Moolenaar	  if get(s:foldstack, 0).firstline < s:lnum
8235c73622aSBram Moolenaar	    let s:new = s:new . "<a class='FoldColumn' href='javascript:toggleFold(\"fold".s:foldstack[0].id."\")'>"
8245c73622aSBram Moolenaar	    let s:new = s:new . repeat('|', s:foldstack[0].level)
8255c73622aSBram Moolenaar	    let s:new = s:new . repeat(' ', s:foldcolumn - s:foldstack[0].level) . "</a>"
8265c73622aSBram Moolenaar	  endif
8275c73622aSBram Moolenaar	endif
8285c73622aSBram Moolenaar      endif
8295c73622aSBram Moolenaar    endif
8305c73622aSBram Moolenaar
8315c73622aSBram Moolenaar    " Now continue with the unfolded line text
832076e8b2aSBram Moolenaar    if s:settings.number_lines
8338ada2ccaSBram Moolenaar      " TODO: why not use the real highlight name here?
8348ada2ccaSBram Moolenaar      let s:new = s:new . s:HtmlFormat(s:numcol, "lnr", "")
835071d4279SBram Moolenaar    endif
836071d4279SBram Moolenaar
83747136d70SBram Moolenaar    " Get the diff attribute, if any.
83847136d70SBram Moolenaar    let s:diffattr = diff_hlID(s:lnum, 1)
83947136d70SBram Moolenaar
8407510fe74SBram Moolenaar    " initialize conceal info to act like not concealed, just in case
8417510fe74SBram Moolenaar    let s:concealinfo = [0, '']
8427510fe74SBram Moolenaar
843071d4279SBram Moolenaar    " Loop over each character in the line
844071d4279SBram Moolenaar    let s:col = 1
8458ada2ccaSBram Moolenaar
8468ada2ccaSBram Moolenaar    " most of the time we won't use the diff_id, initialize to zero
8478ada2ccaSBram Moolenaar    let s:diff_id = 0
8488ada2ccaSBram Moolenaar    let s:diff_id_name = ""
8498ada2ccaSBram Moolenaar
85035a9aaabSBram Moolenaar    while s:col <= s:len || (s:col == 1 && s:diffattr)
851071d4279SBram Moolenaar      let s:startcol = s:col " The start column for processing text
852076e8b2aSBram Moolenaar      if !s:settings.ignore_conceal && has('conceal')
8537510fe74SBram Moolenaar	let s:concealinfo = synconcealed(s:lnum, s:col)
8547510fe74SBram Moolenaar      endif
855076e8b2aSBram Moolenaar      if !s:settings.ignore_conceal && s:concealinfo[0]
8567510fe74SBram Moolenaar	let s:col = s:col + 1
8577510fe74SBram Moolenaar	" Speed loop (it's small - that's the trick)
8587510fe74SBram Moolenaar	" Go along till we find a change in the match sequence number (ending
8597510fe74SBram Moolenaar	" the specific concealed region) or until there are no more concealed
8607510fe74SBram Moolenaar	" characters.
8617510fe74SBram Moolenaar	while s:col <= s:len && s:concealinfo == synconcealed(s:lnum, s:col) | let s:col = s:col + 1 | endwhile
8627510fe74SBram Moolenaar      elseif s:diffattr
8638ada2ccaSBram Moolenaar	let s:diff_id = diff_hlID(s:lnum, s:col)
8648ada2ccaSBram Moolenaar	let s:id = synID(s:lnum, s:col, 1)
86547136d70SBram Moolenaar	let s:col = s:col + 1
86647136d70SBram Moolenaar	" Speed loop (it's small - that's the trick)
86747136d70SBram Moolenaar	" Go along till we find a change in hlID
8688ada2ccaSBram Moolenaar	while s:col <= s:len && s:id == synID(s:lnum, s:col, 1)
8698ada2ccaSBram Moolenaar	      \   && s:diff_id == diff_hlID(s:lnum, s:col) |
8708ada2ccaSBram Moolenaar	      \     let s:col = s:col + 1 |
8718ada2ccaSBram Moolenaar	      \ endwhile
872076e8b2aSBram Moolenaar	if s:len < &columns && !s:settings.no_pre
8738ada2ccaSBram Moolenaar	  " Add spaces at the end of the raw text line to extend the changed
8748ada2ccaSBram Moolenaar	  " line to the full width.
8755c73622aSBram Moolenaar	  let s:line = s:line . repeat(' ', &columns - virtcol([s:lnum, s:len]) - s:margin)
87635a9aaabSBram Moolenaar	  let s:len = &columns
87735a9aaabSBram Moolenaar	endif
87847136d70SBram Moolenaar      else
879071d4279SBram Moolenaar	let s:id = synID(s:lnum, s:col, 1)
880071d4279SBram Moolenaar	let s:col = s:col + 1
881071d4279SBram Moolenaar	" Speed loop (it's small - that's the trick)
882071d4279SBram Moolenaar	" Go along till we find a change in synID
883071d4279SBram Moolenaar	while s:col <= s:len && s:id == synID(s:lnum, s:col, 1) | let s:col = s:col + 1 | endwhile
88447136d70SBram Moolenaar      endif
885071d4279SBram Moolenaar
886076e8b2aSBram Moolenaar      if s:settings.ignore_conceal || !s:concealinfo[0]
88735a9aaabSBram Moolenaar	" Expand tabs
88835a9aaabSBram Moolenaar	let s:expandedtab = strpart(s:line, s:startcol - 1, s:col - s:startcol)
8895c73622aSBram Moolenaar	let s:offset = 0
8905c73622aSBram Moolenaar	let s:idx = stridx(s:expandedtab, "\t")
8915c73622aSBram Moolenaar	while s:idx >= 0
8925c73622aSBram Moolenaar	  if has("multi_byte_encoding")
8935c73622aSBram Moolenaar	    if s:startcol + s:idx == 1
8945c73622aSBram Moolenaar	      let s:i = &ts
8955c73622aSBram Moolenaar	    else
8965c73622aSBram Moolenaar	      if s:idx == 0
8975c73622aSBram Moolenaar		let s:prevc = matchstr(s:line, '.\%' . (s:startcol + s:idx + s:offset) . 'c')
8985c73622aSBram Moolenaar	      else
8995c73622aSBram Moolenaar		let s:prevc = matchstr(s:expandedtab, '.\%' . (s:idx + 1) . 'c')
9005c73622aSBram Moolenaar	      endif
9015c73622aSBram Moolenaar	      let s:vcol = virtcol([s:lnum, s:startcol + s:idx + s:offset - len(s:prevc)])
9025c73622aSBram Moolenaar	      let s:i = &ts - (s:vcol % &ts)
9035c73622aSBram Moolenaar	    endif
9045c73622aSBram Moolenaar	    let s:offset -= s:i - 1
9055c73622aSBram Moolenaar	  else
9065c73622aSBram Moolenaar	    let s:i = &ts - ((s:idx + s:startcol - 1) % &ts)
9075c73622aSBram Moolenaar	  endif
9085c73622aSBram Moolenaar	  let s:expandedtab = substitute(s:expandedtab, '\t', repeat(' ', s:i), '')
9095c73622aSBram Moolenaar	  let s:idx = stridx(s:expandedtab, "\t")
91035a9aaabSBram Moolenaar	endwhile
91135a9aaabSBram Moolenaar
9127510fe74SBram Moolenaar	" get the highlight group name to use
913071d4279SBram Moolenaar	let s:id = synIDtrans(s:id)
914071d4279SBram Moolenaar	let s:id_name = synIDattr(s:id, "name", s:whatterm)
9158ada2ccaSBram Moolenaar	if s:diff_id
9168ada2ccaSBram Moolenaar	  let s:diff_id_name = synIDattr(s:diff_id, "name", s:whatterm)
9178ada2ccaSBram Moolenaar	endif
9187510fe74SBram Moolenaar      else
9197510fe74SBram Moolenaar	" use Conceal highlighting for concealed text
9207510fe74SBram Moolenaar	let s:id_name = 'Conceal'
9217510fe74SBram Moolenaar	let s:expandedtab = s:concealinfo[1]
9227510fe74SBram Moolenaar      endif
9237510fe74SBram Moolenaar
9247510fe74SBram Moolenaar      " Output the text with the same synID, with class set to {s:id_name},
9258ada2ccaSBram Moolenaar      " unless it has been concealed completely.
9267510fe74SBram Moolenaar      if strlen(s:expandedtab) > 0
9278ada2ccaSBram Moolenaar	let s:new = s:new . s:HtmlFormat(s:expandedtab,  s:id_name, s:diff_id_name)
9287510fe74SBram Moolenaar      endif
929071d4279SBram Moolenaar    endwhile
9307b0294cbSBram Moolenaar  endif
931071d4279SBram Moolenaar
9327510fe74SBram Moolenaar  call extend(s:lines, split(s:new.s:HtmlEndline, '\n', 1))
933076e8b2aSBram Moolenaar  if !s:settings.no_progress && s:pgb.needs_redraw
934349b2fb0SBram Moolenaar    redrawstatus
935349b2fb0SBram Moolenaar    let s:pgb.needs_redraw = 0
936349b2fb0SBram Moolenaar  endif
937071d4279SBram Moolenaar  let s:lnum = s:lnum + 1
938313b7237SBram Moolenaar
939076e8b2aSBram Moolenaar  if !s:settings.no_progress
940349b2fb0SBram Moolenaar    call s:pgb.incr()
941349b2fb0SBram Moolenaar  endif
942349b2fb0SBram Moolenaarendwhile
943349b2fb0SBram Moolenaar
944076e8b2aSBram Moolenaarif s:settings.dynamic_folds
9455c73622aSBram Moolenaar  " finish off any open folds
9465c73622aSBram Moolenaar  while !empty(s:foldstack)
947349b2fb0SBram Moolenaar    let s:lines[-1].="</span></span>"
9485c73622aSBram Moolenaar    call remove(s:foldstack, 0)
9495c73622aSBram Moolenaar  endwhile
9505c73622aSBram Moolenaar
9515c73622aSBram Moolenaar  " add fold column to the style list if not already there
9525c73622aSBram Moolenaar  let s:id = hlID('FoldColumn')
9538ada2ccaSBram Moolenaar  if index(s:idlist, s:id) == -1
9548ada2ccaSBram Moolenaar    call insert(s:idlist, s:id)
9555c73622aSBram Moolenaar  endif
9565c73622aSBram Moolenaarendif
9575c73622aSBram Moolenaar
958076e8b2aSBram Moolenaarif s:settings.no_pre
959076e8b2aSBram Moolenaar  if !s:settings.use_css
9608ada2ccaSBram Moolenaar    " Close off the font tag that encapsulates the whole <body>
961bebca9daSBram Moolenaar    call extend(s:lines, ["</font>", "</body>", "</html>"])
9628ada2ccaSBram Moolenaar  else
963349b2fb0SBram Moolenaar    call extend(s:lines, ["</body>", "</html>"])
9648ada2ccaSBram Moolenaar  endif
965071d4279SBram Moolenaarelse
966349b2fb0SBram Moolenaar  call extend(s:lines, ["</pre>", "</body>", "</html>"])
967071d4279SBram Moolenaarendif
968071d4279SBram Moolenaar
969349b2fb0SBram Moolenaarexe s:newwin . "wincmd w"
970349b2fb0SBram Moolenaarcall setline(1, s:lines)
971349b2fb0SBram Moolenaarunlet s:lines
972071d4279SBram Moolenaar
973071d4279SBram Moolenaar" Now, when we finally know which, we define the colors and styles
974076e8b2aSBram Moolenaarif s:settings.use_css
975071d4279SBram Moolenaar  1;/<style type="text/+1
976071d4279SBram Moolenaarendif
977071d4279SBram Moolenaar
978071d4279SBram Moolenaar" Find out the background and foreground color.
979071d4279SBram Moolenaarlet s:fgc = s:HtmlColor(synIDattr(hlID("Normal"), "fg#", s:whatterm))
980071d4279SBram Moolenaarlet s:bgc = s:HtmlColor(synIDattr(hlID("Normal"), "bg#", s:whatterm))
981071d4279SBram Moolenaarif s:fgc == ""
982071d4279SBram Moolenaar  let s:fgc = ( &background == "dark" ? "#ffffff" : "#000000" )
983071d4279SBram Moolenaarendif
984071d4279SBram Moolenaarif s:bgc == ""
985071d4279SBram Moolenaar  let s:bgc = ( &background == "dark" ? "#000000" : "#ffffff" )
986071d4279SBram Moolenaarendif
987071d4279SBram Moolenaar
988071d4279SBram Moolenaar" Normal/global attributes
989071d4279SBram Moolenaar" For Netscape 4, set <body> attributes too, though, strictly speaking, it's
990071d4279SBram Moolenaar" incorrect.
991076e8b2aSBram Moolenaarif s:settings.use_css
992076e8b2aSBram Moolenaar  if s:settings.no_pre
993313b7237SBram Moolenaar    execute "normal! A\nbody { color: " . s:fgc . "; background-color: " . s:bgc . "; font-family: ". s:htmlfont ."; }\e"
994071d4279SBram Moolenaar  else
995313b7237SBram Moolenaar    execute "normal! A\npre { font-family: ". s:htmlfont ."; color: " . s:fgc . "; background-color: " . s:bgc . "; }\e"
996071d4279SBram Moolenaar    yank
997071d4279SBram Moolenaar    put
998071d4279SBram Moolenaar    execute "normal! ^cwbody\e"
999071d4279SBram Moolenaar  endif
1000071d4279SBram Moolenaarelse
1001bebca9daSBram Moolenaar  execute '%s:<body>:<body bgcolor="' . s:bgc . '" text="' . s:fgc . '">\r<font face="'. s:htmlfont .'">'
1002071d4279SBram Moolenaarendif
1003071d4279SBram Moolenaar
1004071d4279SBram Moolenaar" Line numbering attributes
1005076e8b2aSBram Moolenaarif s:settings.number_lines
1006076e8b2aSBram Moolenaar  if s:settings.use_css
1007071d4279SBram Moolenaar    execute "normal! A\n.lnr { " . s:CSS1(hlID("LineNr")) . "}\e"
1008071d4279SBram Moolenaar  else
10098424a624SBram Moolenaar    execute '%s+^<span class="lnr">\([^<]*\)</span>+' . s:HtmlOpening(hlID("LineNr")) . '\1' . s:HtmlClosing(hlID("LineNr")) . '+g'
1010071d4279SBram Moolenaar  endif
1011071d4279SBram Moolenaarendif
1012071d4279SBram Moolenaar
1013071d4279SBram Moolenaar" Gather attributes for all other classes
1014076e8b2aSBram Moolenaarif !s:settings.no_progress && !empty(s:idlist)
1015349b2fb0SBram Moolenaar  let s:pgb = s:ProgressBar("Processing classes:", len(s:idlist),s:newwin)
1016349b2fb0SBram Moolenaarendif
1017349b2fb0SBram Moolenaarwhile !empty(s:idlist)
1018071d4279SBram Moolenaar  let s:attr = ""
1019349b2fb0SBram Moolenaar  let s:id = remove(s:idlist, 0)
1020071d4279SBram Moolenaar  let s:attr = s:CSS1(s:id)
1021071d4279SBram Moolenaar  let s:id_name = synIDattr(s:id, "name", s:whatterm)
1022349b2fb0SBram Moolenaar
1023071d4279SBram Moolenaar  " If the class has some attributes, export the style, otherwise DELETE all
1024071d4279SBram Moolenaar  " its occurences to make the HTML shorter
1025071d4279SBram Moolenaar  if s:attr != ""
1026076e8b2aSBram Moolenaar    if s:settings.use_css
1027071d4279SBram Moolenaar      execute "normal! A\n." . s:id_name . " { " . s:attr . "}"
1028071d4279SBram Moolenaar    else
10298ada2ccaSBram Moolenaar      " replace spans of just this class name with non-CSS style markup
10308ada2ccaSBram Moolenaar      execute '%s+<span class="' . s:id_name . '">\([^<]*\)</span>+' . s:HtmlOpening(s:id) . '\1' . s:HtmlClosing(s:id) . '+ge'
10318ada2ccaSBram Moolenaar      " Replace spans of this class name AND a diff class with non-CSS style
10328ada2ccaSBram Moolenaar      " markup surrounding a span of just the diff class. The diff class will
10338ada2ccaSBram Moolenaar      " be handled later because we know that information is at the end.
10348ada2ccaSBram Moolenaar      execute '%s+<span class="' . s:id_name . ' \(Diff\%(Add\|Change\|Delete\|Text\)\)">\([^<]*\)</span>+' . s:HtmlOpening(s:id) . '<span class="\1">\2</span>' . s:HtmlClosing(s:id) . '+ge'
1035071d4279SBram Moolenaar    endif
1036071d4279SBram Moolenaar  else
1037313b7237SBram Moolenaar    execute '%s+<span class="' . s:id_name . '">\([^<]*\)</span>+\1+ge'
10388ada2ccaSBram Moolenaar    execute '%s+<span class="' . s:id_name . ' \(Diff\%(Add\|Change\|Delete\|Text\)\)">\([^<]*\)</span>+<span class="\1">\2</span>+ge'
1039076e8b2aSBram Moolenaar    if s:settings.use_css
10408ada2ccaSBram Moolenaar      1;/<\/style>/-2
1041071d4279SBram Moolenaar    endif
1042071d4279SBram Moolenaar  endif
1043349b2fb0SBram Moolenaar
1044076e8b2aSBram Moolenaar  if !s:settings.no_progress
1045349b2fb0SBram Moolenaar    call s:pgb.incr()
1046349b2fb0SBram Moolenaar    if s:pgb.needs_redraw
1047349b2fb0SBram Moolenaar      redrawstatus
1048349b2fb0SBram Moolenaar      let s:pgb.needs_redraw = 0
1049bebca9daSBram Moolenaar      " TODO: sleep here to show the progress bar, but only if total time spent
1050bebca9daSBram Moolenaar      " so far on this step is < 1 second? Too slow for batch runs like the test
1051bebca9daSBram Moolenaar      " suite to sleep all the time. Maybe there's no good reason to sleep at
1052bebca9daSBram Moolenaar      " all.
1053349b2fb0SBram Moolenaar    endif
1054349b2fb0SBram Moolenaar  endif
1055071d4279SBram Moolenaarendwhile
1056071d4279SBram Moolenaar
1057071d4279SBram Moolenaar" Add hyperlinks
10581cd871b5SBram Moolenaar%s+\(https\=://\S\{-}\)\(\([.,;:}]\=\(\s\|$\)\)\|[\\"'<>]\|&gt;\|&lt;\|&quot;\)+<a href="\1">\1</a>\2+ge
1059071d4279SBram Moolenaar
1060071d4279SBram Moolenaar" The DTD
1061076e8b2aSBram Moolenaarif s:settings.use_xhtml
1062076e8b2aSBram Moolenaar  exe "normal! gg$a\n<!DOCTYPE html PUBLIC \"-//W3C//DTD XHTML 1.0 Transitional//EN\" \"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd\">"
1063076e8b2aSBram Moolenaarelseif s:settings.use_css && !s:settings.no_pre
1064076e8b2aSBram Moolenaar  exe "normal! gg0i<!DOCTYPE HTML PUBLIC \"-//W3C//DTD HTML 4.01//EN\" \"http://www.w3.org/TR/html4/strict.dtd\">\n"
10651cd871b5SBram Moolenaarelse
1066076e8b2aSBram Moolenaar  exe "normal! gg0i<!DOCTYPE HTML PUBLIC \"-//W3C//DTD HTML 4.01 Transitional//EN\" \"http://www.w3.org/TR/html4/loose.dtd\">\n"
10671cd871b5SBram Moolenaarendif
10681cd871b5SBram Moolenaar
1069076e8b2aSBram Moolenaarif s:settings.use_xhtml
10701cd871b5SBram Moolenaar  exe "normal! gg/<html/e\na xmlns=\"http://www.w3.org/1999/xhtml\"\e"
10711cd871b5SBram Moolenaarendif
1072071d4279SBram Moolenaar
1073071d4279SBram Moolenaar" Cleanup
1074071d4279SBram Moolenaar%s:\s\+$::e
1075071d4279SBram Moolenaar
1076071d4279SBram Moolenaar" Restore old settings
10778df7f888SBram Moolenaarlet &l:foldenable = s:old_fen
1078349b2fb0SBram Moolenaarlet &l:foldmethod = s:old_fdm
1079071d4279SBram Moolenaarlet &report = s:old_report
1080071d4279SBram Moolenaarlet &title = s:old_title
1081071d4279SBram Moolenaarlet &icon = s:old_icon
1082071d4279SBram Moolenaarlet &paste = s:old_paste
1083071d4279SBram Moolenaarlet &magic = s:old_magic
1084071d4279SBram Moolenaarlet @/ = s:old_search
1085349b2fb0SBram Moolenaarlet &more = s:old_more
1086071d4279SBram Moolenaarexe s:orgwin . "wincmd w"
1087*166af9bbSBram Moolenaarlet &l:stl = s:origwin_stl
1088071d4279SBram Moolenaarlet &l:et = s:old_et
10898df7f888SBram Moolenaarlet &l:scrollbind = s:old_bind
1090071d4279SBram Moolenaarexe s:newwin . "wincmd w"
1091*166af9bbSBram Moolenaarlet &l:stl = s:newwin_stl
1092349b2fb0SBram Moolenaarexec 'resize' s:old_winheight
1093349b2fb0SBram Moolenaarlet &l:winfixheight = s:old_winfixheight
1094071d4279SBram Moolenaar
1095349b2fb0SBram Moolenaarlet &ls=s:ls
1096349b2fb0SBram Moolenaar
1097071d4279SBram Moolenaar" Save a little bit of memory (worth doing?)
1098313b7237SBram Moolenaarunlet s:htmlfont
10998df7f888SBram Moolenaarunlet s:old_et s:old_paste s:old_icon s:old_report s:old_title s:old_search
11008df7f888SBram Moolenaarunlet s:old_magic s:old_more s:old_fdm s:old_fen s:old_winheight
11018df7f888SBram Moolenaarunlet s:whatterm s:idlist s:lnum s:end s:margin s:fgc s:bgc s:old_winfixheight
1102076e8b2aSBram Moolenaarunlet! s:col s:id s:attr s:len s:line s:new s:expandedtab s:concealinfo
11038df7f888SBram Moolenaarunlet! s:orgwin s:newwin s:orgbufnr s:idx s:i s:offset s:ls s:origwin_stl
11048df7f888SBram Moolenaarunlet! s:newwin_stl s:current_syntax
110505159a0cSBram Moolenaarif !v:profiling
1106071d4279SBram Moolenaar  delfunc s:HtmlColor
110735a9aaabSBram Moolenaar  delfunc s:HtmlFormat
1108071d4279SBram Moolenaar  delfunc s:CSS1
1109076e8b2aSBram Moolenaar  if !s:settings.use_css
1110071d4279SBram Moolenaar    delfunc s:HtmlOpening
1111071d4279SBram Moolenaar    delfunc s:HtmlClosing
1112071d4279SBram Moolenaar  endif
1113076e8b2aSBram Moolenaar  if s:settings.dynamic_folds
11145c73622aSBram Moolenaar    delfunc s:FoldCompare
11155c73622aSBram Moolenaar  endif
11165c73622aSBram Moolenaar
1117076e8b2aSBram Moolenaar  if !s:settings.no_progress
1118349b2fb0SBram Moolenaar    delfunc s:ProgressBar
1119349b2fb0SBram Moolenaar    delfunc s:progressbar.paint
1120349b2fb0SBram Moolenaar    delfunc s:progressbar.incr
1121349b2fb0SBram Moolenaar    unlet s:pgb s:progressbar
1122349b2fb0SBram Moolenaar  endif
1123349b2fb0SBram Moolenaarendif
1124349b2fb0SBram Moolenaar
11258df7f888SBram Moolenaarunlet! s:new_lnum s:diffattr s:difffillchar s:foldfillchar s:HtmlSpace
11268df7f888SBram Moolenaarunlet! s:LeadingSpace s:HtmlEndline s:firstfold s:foldcolumn
1127076e8b2aSBram Moolenaarunlet s:foldstack s:allfolds s:foldId s:numcol s:settings
11285c73622aSBram Moolenaar
11295c73622aSBram Moolenaarlet &cpo = s:cpo_sav
1130349b2fb0SBram Moolenaarunlet! s:cpo_sav
11315c73622aSBram Moolenaar
1132349b2fb0SBram Moolenaar" Make sure any patches will probably use consistent indent
11337c86f4ccSBram Moolenaar"   vim: ts=8 sw=2 sts=2 noet
1134