xref: /vim-8.2.3635/runtime/syntax/2html.vim (revision bebca9da)
1071d4279SBram Moolenaar" Vim syntax support file
2349b2fb0SBram Moolenaar" Maintainer: Ben Fritz <[email protected]>
3*bebca9daSBram Moolenaar" Last Change: 2010 Aug 07
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
76*bebca9daSBram 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
1298424a624SBram Moolenaar  " Replace double spaces and leading spaces
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')
13335a9aaabSBram Moolenaar  endif
13435a9aaabSBram Moolenaar
13535a9aaabSBram Moolenaar  " Enclose in a span of class style_name
1368ada2ccaSBram Moolenaar  let formatted = '<span class="' . l:style_name . '">' . formatted . '</span>'
13735a9aaabSBram Moolenaar
1388ada2ccaSBram Moolenaar  " Add the class to class list if it's not there yet.
1398ada2ccaSBram Moolenaar  " Add normal groups to the beginning so diff groups can override them.
14035a9aaabSBram Moolenaar  let s:id = hlID(a:style_name)
1418ada2ccaSBram Moolenaar  if index(s:idlist, s:id ) == -1
1428ada2ccaSBram Moolenaar    if a:style_name =~ 'Diff\%(Add\|Change\|Delete\|Text\)'
1438ada2ccaSBram Moolenaar      call add(s:idlist, s:id)
1448ada2ccaSBram Moolenaar    else
1458ada2ccaSBram Moolenaar      call insert(s:idlist, s:id)
1468ada2ccaSBram Moolenaar    endif
1478ada2ccaSBram Moolenaar  endif
1488ada2ccaSBram Moolenaar
1498ada2ccaSBram Moolenaar  " Add the diff highlight class to class list if used and it's not there yet.
1508ada2ccaSBram Moolenaar  " Add diff groups to the end so they override the other highlighting.
1518ada2ccaSBram Moolenaar  if a:diff_style_name != ""
1528ada2ccaSBram Moolenaar    let s:diff_id = hlID(a:diff_style_name)
1538ada2ccaSBram Moolenaar    if index(s:idlist, s:diff_id) == -1
1548ada2ccaSBram Moolenaar      call add(s:idlist, s:diff_id)
1558ada2ccaSBram Moolenaar    endif
15635a9aaabSBram Moolenaar  endif
15735a9aaabSBram Moolenaar
15835a9aaabSBram Moolenaar  return formatted
15935a9aaabSBram Moolenaarendfun
16035a9aaabSBram Moolenaar
161071d4279SBram Moolenaar" Return CSS style describing given highlight id (can be empty)
162071d4279SBram Moolenaarfunction! s:CSS1(id)
163071d4279SBram Moolenaar  let a = ""
164071d4279SBram Moolenaar  if synIDattr(a:id, "inverse")
165071d4279SBram Moolenaar    " For inverse, we always must set both colors (and exchange them)
166071d4279SBram Moolenaar    let x = s:HtmlColor(synIDattr(a:id, "bg#", s:whatterm))
167071d4279SBram Moolenaar    let a = a . "color: " . ( x != "" ? x : s:bgc ) . "; "
168071d4279SBram Moolenaar    let x = s:HtmlColor(synIDattr(a:id, "fg#", s:whatterm))
169071d4279SBram Moolenaar    let a = a . "background-color: " . ( x != "" ? x : s:fgc ) . "; "
170071d4279SBram Moolenaar  else
171071d4279SBram Moolenaar    let x = s:HtmlColor(synIDattr(a:id, "fg#", s:whatterm))
172071d4279SBram Moolenaar    if x != "" | let a = a . "color: " . x . "; " | endif
173071d4279SBram Moolenaar    let x = s:HtmlColor(synIDattr(a:id, "bg#", s:whatterm))
174071d4279SBram Moolenaar    if x != "" | let a = a . "background-color: " . x . "; " | endif
175071d4279SBram Moolenaar  endif
176071d4279SBram Moolenaar  if synIDattr(a:id, "bold") | let a = a . "font-weight: bold; " | endif
177071d4279SBram Moolenaar  if synIDattr(a:id, "italic") | let a = a . "font-style: italic; " | endif
178071d4279SBram Moolenaar  if synIDattr(a:id, "underline") | let a = a . "text-decoration: underline; " | endif
179071d4279SBram Moolenaar  return a
180071d4279SBram Moolenaarendfun
181071d4279SBram Moolenaar
182076e8b2aSBram Moolenaarif s:settings.dynamic_folds
1835c73622aSBram Moolenaar  " compares two folds as stored in our list of folds
1845c73622aSBram Moolenaar  " A fold is "less" than another if it starts at an earlier line number,
1855c73622aSBram Moolenaar  " or ends at a later line number, ties broken by fold level
1865c73622aSBram Moolenaar  function! s:FoldCompare(f1, f2)
1875c73622aSBram Moolenaar    if a:f1.firstline != a:f2.firstline
1885c73622aSBram Moolenaar      " put it before if it starts earlier
1895c73622aSBram Moolenaar      return a:f1.firstline - a:f2.firstline
1905c73622aSBram Moolenaar    elseif a:f1.lastline != a:f2.lastline
1915c73622aSBram Moolenaar      " put it before if it ends later
1925c73622aSBram Moolenaar      return a:f2.lastline - a:f1.lastline
1935c73622aSBram Moolenaar    else
1945c73622aSBram Moolenaar      " if folds begin and end on the same lines, put lowest fold level first
1955c73622aSBram Moolenaar      return a:f1.level - a:f2.level
1965c73622aSBram Moolenaar    endif
1975c73622aSBram Moolenaar  endfunction
1985c73622aSBram Moolenaar
1995c73622aSBram Moolenaarendif
2005c73622aSBram Moolenaar
201071d4279SBram Moolenaar
202071d4279SBram Moolenaar" Set some options to make it work faster.
203071d4279SBram Moolenaar" Don't report changes for :substitute, there will be many of them.
204071d4279SBram Moolenaarlet s:old_title = &title
205071d4279SBram Moolenaarlet s:old_icon = &icon
206071d4279SBram Moolenaarlet s:old_et = &l:et
207071d4279SBram Moolenaarlet s:old_report = &report
208071d4279SBram Moolenaarlet s:old_search = @/
209349b2fb0SBram Moolenaarlet s:old_more = &more
210071d4279SBram Moolenaarset notitle noicon
211071d4279SBram Moolenaarsetlocal et
212349b2fb0SBram Moolenaarset nomore
213071d4279SBram Moolenaarset report=1000000
214071d4279SBram Moolenaar
2157510fe74SBram Moolenaarif exists(':ownsyntax') && exists('w:current_syntax')
2167510fe74SBram Moolenaar  let s:current_syntax = w:current_syntax
2177510fe74SBram Moolenaarelseif exists('b:current_syntax')
2187510fe74SBram Moolenaar  let s:current_syntax = b:current_syntax
2197510fe74SBram Moolenaarelse
2207510fe74SBram Moolenaar  let s:current_syntax = 'none'
2217510fe74SBram Moolenaarendif
2227510fe74SBram Moolenaar
2237510fe74SBram Moolenaarif s:current_syntax == ''
2247510fe74SBram Moolenaar  let s:current_syntax = 'none'
2257510fe74SBram Moolenaarendif
2267510fe74SBram Moolenaar
227071d4279SBram Moolenaar" Split window to create a buffer with the HTML file.
228071d4279SBram Moolenaarlet s:orgbufnr = winbufnr(0)
229349b2fb0SBram Moolenaarlet s:origwin_stl = &l:stl
230071d4279SBram Moolenaarif expand("%") == ""
231076e8b2aSBram Moolenaar  exec 'new Untitled.'.(s:settings.use_xhtml ? 'x' : '').'html'
232071d4279SBram Moolenaarelse
233076e8b2aSBram Moolenaar  exec 'new %.'.(s:settings.use_xhtml ? 'x' : '').'html'
234071d4279SBram Moolenaarendif
235349b2fb0SBram Moolenaar
236349b2fb0SBram Moolenaar" Resize the new window to very small in order to make it draw faster
237349b2fb0SBram Moolenaarlet s:old_winheight = winheight(0)
238349b2fb0SBram Moolenaarlet s:old_winfixheight = &l:winfixheight
239349b2fb0SBram Moolenaarif s:old_winheight > 2
240349b2fb0SBram Moolenaar  resize 1 " leave enough room to view one line at a time
241349b2fb0SBram Moolenaar  norm! G
242349b2fb0SBram Moolenaar  norm! zt
243349b2fb0SBram Moolenaarendif
244349b2fb0SBram Moolenaarsetlocal winfixheight
245349b2fb0SBram Moolenaar
246349b2fb0SBram Moolenaarlet s:newwin_stl = &l:stl
247349b2fb0SBram Moolenaar
248349b2fb0SBram Moolenaar" on the new window, set the least time-consuming fold method
249349b2fb0SBram Moolenaarlet s:old_fdm = &foldmethod
250349b2fb0SBram Moolenaarsetlocal foldmethod=manual
251349b2fb0SBram Moolenaar
252071d4279SBram Moolenaarlet s:newwin = winnr()
253071d4279SBram Moolenaarlet s:orgwin = bufwinnr(s:orgbufnr)
254071d4279SBram Moolenaar
255349b2fb0SBram Moolenaarsetlocal modifiable
256071d4279SBram Moolenaar%d
257071d4279SBram Moolenaarlet s:old_paste = &paste
258071d4279SBram Moolenaarset paste
259071d4279SBram Moolenaarlet s:old_magic = &magic
260071d4279SBram Moolenaarset magic
261071d4279SBram Moolenaar
262349b2fb0SBram Moolenaarlet s:lines = []
263349b2fb0SBram Moolenaar
264076e8b2aSBram Moolenaarif s:settings.use_xhtml
265*bebca9daSBram Moolenaar  if s:settings.encoding != ""
266*bebca9daSBram Moolenaar    call add(s:lines, "<?xml version=\"1.0\" encoding=\"" . s:settings.encoding . "\"?>")
2671cd871b5SBram Moolenaar  else
268349b2fb0SBram Moolenaar    call add(s:lines, "<?xml version=\"1.0\"?>")
2691cd871b5SBram Moolenaar  endif
27035a9aaabSBram Moolenaar  let s:tag_close = ' />'
271071d4279SBram Moolenaarelse
27235a9aaabSBram Moolenaar  let s:tag_close = '>'
27335a9aaabSBram Moolenaarendif
27435a9aaabSBram Moolenaar
27535a9aaabSBram Moolenaarlet s:HtmlSpace = ' '
276c1e37901SBram Moolenaarlet s:LeadingSpace = ' '
27735a9aaabSBram Moolenaarlet s:HtmlEndline = ''
278076e8b2aSBram Moolenaarif s:settings.no_pre
27935a9aaabSBram Moolenaar  let s:HtmlEndline = '<br' . s:tag_close
280c1e37901SBram Moolenaar  let s:LeadingSpace = '&nbsp;'
281c1e37901SBram Moolenaar  let s:HtmlSpace = '\' . s:LeadingSpace
282071d4279SBram Moolenaarendif
283071d4279SBram Moolenaar
284071d4279SBram Moolenaar" HTML header, with the title and generator ;-). Left free space for the CSS,
285071d4279SBram Moolenaar" to be filled at the end.
286349b2fb0SBram Moolenaarcall extend(s:lines, [
287349b2fb0SBram Moolenaar      \ "<html>",
288*bebca9daSBram Moolenaar      \ "<head>"])
289*bebca9daSBram Moolenaar" include encoding as close to the top as possible, but only if not already
290*bebca9daSBram Moolenaar" contained in XML information (to avoid haggling over content type)
291*bebca9daSBram Moolenaarif s:settings.encoding != "" && !s:settings.use_xhtml
292*bebca9daSBram Moolenaar  call add(s:lines, "<meta http-equiv=\"content-type\" content=\"text/html; charset=" . s:settings.encoding . '"' . s:tag_close)
293*bebca9daSBram Moolenaarendif
294*bebca9daSBram Moolenaarcall extend(s:lines, [
295349b2fb0SBram Moolenaar      \ ("<title>".expand("%:p:~")."</title>"),
296349b2fb0SBram Moolenaar      \ ("<meta name=\"Generator\" content=\"Vim/".v:version/100.".".v:version%100.'"'.s:tag_close),
297*bebca9daSBram Moolenaar      \ ("<meta name=\"plugin-version\" content=\"".g:loaded_2html_plugin.'"'.s:tag_close)
298349b2fb0SBram Moolenaar      \ ])
2997510fe74SBram Moolenaarcall add(s:lines, '<meta name="syntax" content="'.s:current_syntax.'"'.s:tag_close)
300076e8b2aSBram Moolenaarcall add(s:lines, '<meta name="settings" content="'.
301076e8b2aSBram Moolenaar      \ join(filter(keys(s:settings),'s:settings[v:val]'),',').
302076e8b2aSBram Moolenaar      \ '"'.s:tag_close)
303313b7237SBram Moolenaar
304076e8b2aSBram Moolenaarif s:settings.use_css
305076e8b2aSBram Moolenaar  if s:settings.dynamic_folds
306076e8b2aSBram Moolenaar    if s:settings.hover_unfold
3075c73622aSBram Moolenaar      " if we are doing hover_unfold, use css 2 with css 1 fallback for IE6
308349b2fb0SBram Moolenaar      call extend(s:lines, [
309349b2fb0SBram Moolenaar	    \ "<style type=\"text/css\">",
310*bebca9daSBram Moolenaar	    \ s:settings.use_xhtml ? "" : "<!--",
311349b2fb0SBram Moolenaar	    \ ".FoldColumn { text-decoration: none; white-space: pre; }",
312349b2fb0SBram Moolenaar	    \ "",
313349b2fb0SBram Moolenaar	    \ "body * { margin: 0; padding: 0; }", "",
314349b2fb0SBram Moolenaar	    \ ".open-fold   > .Folded { display: none;  }",
315349b2fb0SBram Moolenaar	    \ ".open-fold   > .fulltext { display: inline; }",
316349b2fb0SBram Moolenaar	    \ ".closed-fold > .fulltext { display: none;  }",
317349b2fb0SBram Moolenaar	    \ ".closed-fold > .Folded { display: inline; }",
318349b2fb0SBram Moolenaar	    \ "",
319349b2fb0SBram Moolenaar	    \ ".open-fold   > .toggle-open   { display: none;   }",
320349b2fb0SBram Moolenaar	    \ ".open-fold   > .toggle-closed { display: inline; }",
321349b2fb0SBram Moolenaar	    \ ".closed-fold > .toggle-open   { display: inline; }",
322349b2fb0SBram Moolenaar	    \ ".closed-fold > .toggle-closed { display: none;   }",
323349b2fb0SBram Moolenaar	    \ "", "",
324349b2fb0SBram Moolenaar	    \ '/* opening a fold while hovering won''t be supported by IE6 and other',
325349b2fb0SBram Moolenaar	    \ "similar browsers, but it should fail gracefully. */",
326349b2fb0SBram Moolenaar	    \ ".closed-fold:hover > .fulltext { display: inline; }",
327349b2fb0SBram Moolenaar	    \ ".closed-fold:hover > .toggle-filler { display: none; }",
328349b2fb0SBram Moolenaar	    \ ".closed-fold:hover > .Folded { display: none; }",
329*bebca9daSBram Moolenaar	    \ s:settings.use_xhtml ? "" : '-->',
330*bebca9daSBram Moolenaar	    \ '<style>'])
331*bebca9daSBram Moolenaar      " TODO: IE7 doesn't *actually* support XHTML, maybe we should remove this.
332*bebca9daSBram Moolenaar      " But if it's served up as tag soup, maybe the following will work, so
333*bebca9daSBram Moolenaar      " leave it in for now.
334*bebca9daSBram Moolenaar      call extend(s:lines, [
335349b2fb0SBram Moolenaar	    \ "<!--[if lt IE 7]><style type=\"text/css\">",
336349b2fb0SBram Moolenaar	    \ ".open-fold   .Folded      { display: none; }",
337349b2fb0SBram Moolenaar	    \ ".open-fold   .fulltext      { display: inline; }",
338349b2fb0SBram Moolenaar	    \ ".open-fold   .toggle-open   { display: none; }",
339349b2fb0SBram Moolenaar	    \ ".closed-fold .toggle-closed { display: inline; }",
340349b2fb0SBram Moolenaar	    \ "",
341349b2fb0SBram Moolenaar	    \ ".closed-fold .fulltext      { display: none; }",
342349b2fb0SBram Moolenaar	    \ ".closed-fold .Folded      { display: inline; }",
343349b2fb0SBram Moolenaar	    \ ".closed-fold .toggle-open   { display: inline; }",
344349b2fb0SBram Moolenaar	    \ ".closed-fold .toggle-closed { display: none; }",
345349b2fb0SBram Moolenaar	    \ "</style>",
346349b2fb0SBram Moolenaar	    \ "<![endif]-->",
347349b2fb0SBram Moolenaar	    \])
3485c73622aSBram Moolenaar    else
3495c73622aSBram Moolenaar      " if we aren't doing hover_unfold, use CSS 1 only
350349b2fb0SBram Moolenaar      call extend(s:lines, [
351349b2fb0SBram Moolenaar	    \ "<style type=\"text/css\">",
352*bebca9daSBram Moolenaar	    \ s:settings.use_xhtml ? "" :"<!--",
353349b2fb0SBram Moolenaar	    \ ".FoldColumn { text-decoration: none; white-space: pre; }",
354349b2fb0SBram Moolenaar	    \ ".open-fold   .Folded      { display: none; }",
355349b2fb0SBram Moolenaar	    \ ".open-fold   .fulltext      { display: inline; }",
356349b2fb0SBram Moolenaar	    \ ".open-fold   .toggle-open   { display: none; }",
357349b2fb0SBram Moolenaar	    \ ".closed-fold .toggle-closed { display: inline; }",
358349b2fb0SBram Moolenaar	    \ "",
359349b2fb0SBram Moolenaar	    \ ".closed-fold .fulltext      { display: none; }",
360349b2fb0SBram Moolenaar	    \ ".closed-fold .Folded      { display: inline; }",
361349b2fb0SBram Moolenaar	    \ ".closed-fold .toggle-open   { display: inline; }",
362349b2fb0SBram Moolenaar	    \ ".closed-fold .toggle-closed { display: none; }",
363*bebca9daSBram Moolenaar	    \ s:settings.use_xhtml ? "" : '-->',
364349b2fb0SBram Moolenaar	    \ '</style>'
365349b2fb0SBram Moolenaar	    \])
3665c73622aSBram Moolenaar    endif
3675c73622aSBram Moolenaar  else
3685c73622aSBram Moolenaar    " if we aren't doing any dynamic folding, no need for any special rules
369349b2fb0SBram Moolenaar    call extend(s:lines, [
370349b2fb0SBram Moolenaar	  \ "<style type=\"text/css\">",
371*bebca9daSBram Moolenaar	  \ s:settings.use_xhtml ? "" : "<!--",
372*bebca9daSBram Moolenaar	  \ s:settings.use_xhtml ? "" : '-->',
373349b2fb0SBram Moolenaar	  \ "</style>",
374349b2fb0SBram Moolenaar	  \])
375071d4279SBram Moolenaar  endif
3765c73622aSBram Moolenaarendif
3775c73622aSBram Moolenaar
3785c73622aSBram Moolenaar" insert javascript to toggle folds open and closed
379076e8b2aSBram Moolenaarif s:settings.dynamic_folds
380349b2fb0SBram Moolenaar  call extend(s:lines, [
381349b2fb0SBram Moolenaar	\ "",
382349b2fb0SBram Moolenaar	\ "<script type='text/javascript'>",
383*bebca9daSBram Moolenaar	\ s:settings.use_xhtml ? '//<![CDATA[' : "<!--",
384349b2fb0SBram Moolenaar	\ "function toggleFold(objID)",
385349b2fb0SBram Moolenaar	\ "{",
386349b2fb0SBram Moolenaar	\ "  var fold;",
387349b2fb0SBram Moolenaar	\ "  fold = document.getElementById(objID);",
388349b2fb0SBram Moolenaar	\ "  if(fold.className == 'closed-fold')",
389349b2fb0SBram Moolenaar	\ "  {",
390349b2fb0SBram Moolenaar	\ "    fold.className = 'open-fold';",
391349b2fb0SBram Moolenaar	\ "  }",
392349b2fb0SBram Moolenaar	\ "  else if (fold.className == 'open-fold')",
393349b2fb0SBram Moolenaar	\ "  {",
394349b2fb0SBram Moolenaar	\ "    fold.className = 'closed-fold';",
395349b2fb0SBram Moolenaar	\ "  }",
396349b2fb0SBram Moolenaar	\ "}",
397*bebca9daSBram Moolenaar	\ s:settings.use_xhtml ? '//]]>' : '-->',
398349b2fb0SBram Moolenaar	\ "</script>"
399349b2fb0SBram Moolenaar	\])
4005c73622aSBram Moolenaarendif
4015c73622aSBram Moolenaar
402076e8b2aSBram Moolenaarif s:settings.no_pre
403349b2fb0SBram Moolenaar  call extend(s:lines, ["</head>", "<body>"])
404071d4279SBram Moolenaarelse
405349b2fb0SBram Moolenaar  call extend(s:lines, ["</head>", "<body>", "<pre>"])
406071d4279SBram Moolenaarendif
407071d4279SBram Moolenaar
408071d4279SBram Moolenaarexe s:orgwin . "wincmd w"
409071d4279SBram Moolenaar
410071d4279SBram Moolenaar" List of all id's
4118ada2ccaSBram Moolenaarlet s:idlist = []
412071d4279SBram Moolenaar
413349b2fb0SBram Moolenaar" set up progress bar in the status line
414076e8b2aSBram Moolenaarif !s:settings.no_progress
415349b2fb0SBram Moolenaar  " ProgressBar Indicator
416349b2fb0SBram Moolenaar  let s:progressbar={}
417349b2fb0SBram Moolenaar
418349b2fb0SBram Moolenaar  " Progessbar specific functions
419349b2fb0SBram Moolenaar  func! s:ProgressBar(title, max_value, winnr)
420349b2fb0SBram Moolenaar    let pgb=copy(s:progressbar)
421349b2fb0SBram Moolenaar    let pgb.title = a:title.' '
422349b2fb0SBram Moolenaar    let pgb.max_value = a:max_value
423349b2fb0SBram Moolenaar    let pgb.winnr = a:winnr
424349b2fb0SBram Moolenaar    let pgb.cur_value = 0
425349b2fb0SBram Moolenaar    let pgb.items = { 'title'   : { 'color' : 'Statusline' },
426349b2fb0SBram Moolenaar	  \'bar'     : { 'color' : 'Statusline' , 'fillcolor' : 'DiffDelete' , 'bg' : 'Statusline' } ,
427349b2fb0SBram Moolenaar	  \'counter' : { 'color' : 'Statusline' } }
428349b2fb0SBram Moolenaar    let pgb.last_value = 0
429349b2fb0SBram Moolenaar    let pgb.needs_redraw = 0
430349b2fb0SBram Moolenaar    " Note that you must use len(split) instead of len() if you want to use
431349b2fb0SBram Moolenaar    " unicode in title.
432349b2fb0SBram Moolenaar    "
433349b2fb0SBram Moolenaar    " Subtract 3 for spacing around the title.
434349b2fb0SBram Moolenaar    " Subtract 4 for the percentage display.
435349b2fb0SBram Moolenaar    " Subtract 2 for spacing before this.
436349b2fb0SBram Moolenaar    " Subtract 2 more for the '|' on either side of the progress bar
437349b2fb0SBram Moolenaar    let pgb.subtractedlen=len(split(pgb.title, '\zs'))+3+4+2+2
438349b2fb0SBram Moolenaar    let pgb.max_len = 0
439349b2fb0SBram Moolenaar    set laststatus=2
440349b2fb0SBram Moolenaar    return pgb
441349b2fb0SBram Moolenaar  endfun
442349b2fb0SBram Moolenaar
443349b2fb0SBram Moolenaar  " Function: progressbar.calculate_ticks() {{{1
444349b2fb0SBram Moolenaar  func! s:progressbar.calculate_ticks(pb_len)
445349b2fb0SBram Moolenaar    if a:pb_len<=0
446349b2fb0SBram Moolenaar      let pb_len = 100
447349b2fb0SBram Moolenaar    else
448349b2fb0SBram Moolenaar      let pb_len = a:pb_len
449349b2fb0SBram Moolenaar    endif
450349b2fb0SBram Moolenaar    let self.progress_ticks = map(range(pb_len+1), "v:val * self.max_value / pb_len")
451349b2fb0SBram Moolenaar  endfun
452349b2fb0SBram Moolenaar
453349b2fb0SBram Moolenaar  "Function: progressbar.paint()
454349b2fb0SBram Moolenaar  func! s:progressbar.paint()
455349b2fb0SBram Moolenaar    " Recalculate widths.
456349b2fb0SBram Moolenaar    let max_len = winwidth(self.winnr)
457349b2fb0SBram Moolenaar    let pb_len = 0
458349b2fb0SBram Moolenaar    " always true on first call because of initial value of self.max_len
459349b2fb0SBram Moolenaar    if max_len != self.max_len
460349b2fb0SBram Moolenaar      let self.max_len = max_len
461349b2fb0SBram Moolenaar
462349b2fb0SBram Moolenaar      " Progressbar length
463349b2fb0SBram Moolenaar      let pb_len = max_len - self.subtractedlen
464349b2fb0SBram Moolenaar
465349b2fb0SBram Moolenaar      call self.calculate_ticks(pb_len)
466349b2fb0SBram Moolenaar
467349b2fb0SBram Moolenaar      let self.needs_redraw = 1
468349b2fb0SBram Moolenaar      let cur_value = 0
469349b2fb0SBram Moolenaar      let self.pb_len = pb_len
470349b2fb0SBram Moolenaar    else
471349b2fb0SBram Moolenaar      " start searching at the last found index to make the search for the
472349b2fb0SBram Moolenaar      " appropriate tick value normally take 0 or 1 comparisons
473349b2fb0SBram Moolenaar      let cur_value = self.last_value
474349b2fb0SBram Moolenaar      let pb_len = self.pb_len
475349b2fb0SBram Moolenaar    endif
476349b2fb0SBram Moolenaar
477349b2fb0SBram Moolenaar    let cur_val_max = pb_len > 0 ? pb_len : 100
478349b2fb0SBram Moolenaar
479349b2fb0SBram Moolenaar    " find the current progress bar position based on precalculated thresholds
480349b2fb0SBram Moolenaar    while cur_value < cur_val_max && self.cur_value > self.progress_ticks[cur_value]
481349b2fb0SBram Moolenaar      let cur_value += 1
482349b2fb0SBram Moolenaar    endwhile
483349b2fb0SBram Moolenaar
484349b2fb0SBram Moolenaar    " update progress bar
485349b2fb0SBram Moolenaar    if self.last_value != cur_value || self.needs_redraw || self.cur_value == self.max_value
486349b2fb0SBram Moolenaar      let self.needs_redraw = 1
487349b2fb0SBram Moolenaar      let self.last_value = cur_value
488349b2fb0SBram Moolenaar
489349b2fb0SBram Moolenaar      let t_color  = self.items.title.color
490349b2fb0SBram Moolenaar      let b_fcolor = self.items.bar.fillcolor
491349b2fb0SBram Moolenaar      let b_color  = self.items.bar.color
492349b2fb0SBram Moolenaar      let c_color  = self.items.counter.color
493349b2fb0SBram Moolenaar
494349b2fb0SBram Moolenaar      let stl =  "%#".t_color."#%-( ".self.title." %)".
495349b2fb0SBram Moolenaar	    \"%#".b_color."#".
496349b2fb0SBram Moolenaar	    \(pb_len>0 ?
497349b2fb0SBram Moolenaar	    \	('|%#'.b_fcolor."#%-(".repeat(" ",cur_value)."%)".
498349b2fb0SBram Moolenaar	    \	 '%#'.b_color."#".repeat(" ",pb_len-cur_value)."|"):
499349b2fb0SBram Moolenaar	    \	('')).
500349b2fb0SBram Moolenaar	    \"%=%#".c_color."#%( ".printf("%3.d ",100*self.cur_value/self.max_value)."%% %)"
501349b2fb0SBram Moolenaar      call setwinvar(self.winnr, '&stl', stl)
502349b2fb0SBram Moolenaar    endif
503349b2fb0SBram Moolenaar  endfun
504349b2fb0SBram Moolenaar
505349b2fb0SBram Moolenaar  func! s:progressbar.incr( ... )
506349b2fb0SBram Moolenaar    let self.cur_value += (a:0 ? a:1 : 1)
507349b2fb0SBram Moolenaar    " if we were making a general-purpose progress bar, we'd need to limit to a
508349b2fb0SBram Moolenaar    " lower limit as well, but since we always increment with a positive value
509349b2fb0SBram Moolenaar    " in this script, we only need limit the upper value
510349b2fb0SBram Moolenaar    let self.cur_value = (self.cur_value > self.max_value ? self.max_value : self.cur_value)
511349b2fb0SBram Moolenaar    call self.paint()
512349b2fb0SBram Moolenaar  endfun
513349b2fb0SBram Moolenaar  " }}}
514076e8b2aSBram Moolenaar  if s:settings.dynamic_folds
515349b2fb0SBram Moolenaar    " to process folds we make two passes through each line
516349b2fb0SBram Moolenaar    let s:pgb = s:ProgressBar("Processing folds:", line('$')*2, s:orgwin)
517349b2fb0SBram Moolenaar  endif
518349b2fb0SBram Moolenaarendif
519349b2fb0SBram Moolenaar
5205c73622aSBram Moolenaar" First do some preprocessing for dynamic folding. Do this for the entire file
5215c73622aSBram Moolenaar" so we don't accidentally start within a closed fold or something.
5225c73622aSBram Moolenaarlet s:allfolds = []
5235c73622aSBram Moolenaar
524076e8b2aSBram Moolenaarif s:settings.dynamic_folds
5255c73622aSBram Moolenaar  let s:lnum = 1
5265c73622aSBram Moolenaar  let s:end = line('$')
5275c73622aSBram Moolenaar  " save the fold text and set it to the default so we can find fold levels
5285c73622aSBram Moolenaar  let s:foldtext_save = &foldtext
529349b2fb0SBram Moolenaar  setlocal foldtext&
5305c73622aSBram Moolenaar
5315c73622aSBram Moolenaar  " we will set the foldcolumn in the html to the greater of the maximum fold
5325c73622aSBram Moolenaar  " level and the current foldcolumn setting
5335c73622aSBram Moolenaar  let s:foldcolumn = &foldcolumn
5345c73622aSBram Moolenaar
5355c73622aSBram Moolenaar  " get all info needed to describe currently closed folds
536349b2fb0SBram Moolenaar  while s:lnum <= s:end
5375c73622aSBram Moolenaar    if foldclosed(s:lnum) == s:lnum
5385c73622aSBram Moolenaar      " default fold text has '+-' and then a number of dashes equal to fold
5395c73622aSBram Moolenaar      " level, so subtract 2 from index of first non-dash after the dashes
5405c73622aSBram Moolenaar      " in order to get the fold level of the current fold
5415c73622aSBram Moolenaar      let s:level = match(foldtextresult(s:lnum), '+-*\zs[^-]') - 2
5425c73622aSBram Moolenaar      if s:level+1 > s:foldcolumn
5435c73622aSBram Moolenaar	let s:foldcolumn = s:level+1
5445c73622aSBram Moolenaar      endif
5455c73622aSBram Moolenaar      " store fold info for later use
5465c73622aSBram Moolenaar      let s:newfold = {'firstline': s:lnum, 'lastline': foldclosedend(s:lnum), 'level': s:level,'type': "closed-fold"}
5475c73622aSBram Moolenaar      call add(s:allfolds, s:newfold)
5485c73622aSBram Moolenaar      " open the fold so we can find any contained folds
5495c73622aSBram Moolenaar      execute s:lnum."foldopen"
5505c73622aSBram Moolenaar    else
551076e8b2aSBram Moolenaar      if !s:settings.no_progress
552349b2fb0SBram Moolenaar	call s:pgb.incr()
553349b2fb0SBram Moolenaar	if s:pgb.needs_redraw
554349b2fb0SBram Moolenaar	  redrawstatus
555349b2fb0SBram Moolenaar	  let s:pgb.needs_redraw = 0
556349b2fb0SBram Moolenaar	endif
557349b2fb0SBram Moolenaar      endif
5585c73622aSBram Moolenaar      let s:lnum = s:lnum + 1
5595c73622aSBram Moolenaar    endif
5605c73622aSBram Moolenaar  endwhile
5615c73622aSBram Moolenaar
5625c73622aSBram Moolenaar  " close all folds to get info for originally open folds
5635c73622aSBram Moolenaar  silent! %foldclose!
5645c73622aSBram Moolenaar  let s:lnum = 1
5655c73622aSBram Moolenaar
5665c73622aSBram Moolenaar  " the originally open folds will be all folds we encounter that aren't
5675c73622aSBram Moolenaar  " already in the list of closed folds
568349b2fb0SBram Moolenaar  while s:lnum <= s:end
5695c73622aSBram Moolenaar    if foldclosed(s:lnum) == s:lnum
5705c73622aSBram Moolenaar      " default fold text has '+-' and then a number of dashes equal to fold
5715c73622aSBram Moolenaar      " level, so subtract 2 from index of first non-dash after the dashes
5725c73622aSBram Moolenaar      " in order to get the fold level of the current fold
5735c73622aSBram Moolenaar      let s:level = match(foldtextresult(s:lnum), '+-*\zs[^-]') - 2
5745c73622aSBram Moolenaar      if s:level+1 > s:foldcolumn
5755c73622aSBram Moolenaar	let s:foldcolumn = s:level+1
5765c73622aSBram Moolenaar      endif
5775c73622aSBram Moolenaar      let s:newfold = {'firstline': s:lnum, 'lastline': foldclosedend(s:lnum), 'level': s:level,'type': "closed-fold"}
5785c73622aSBram Moolenaar      " only add the fold if we don't already have it
5795c73622aSBram Moolenaar      if empty(s:allfolds) || index(s:allfolds, s:newfold) == -1
5805c73622aSBram Moolenaar	let s:newfold.type = "open-fold"
5815c73622aSBram Moolenaar	call add(s:allfolds, s:newfold)
5825c73622aSBram Moolenaar      endif
5835c73622aSBram Moolenaar      " open the fold so we can find any contained folds
5845c73622aSBram Moolenaar      execute s:lnum."foldopen"
5855c73622aSBram Moolenaar    else
586076e8b2aSBram Moolenaar      if !s:settings.no_progress
587349b2fb0SBram Moolenaar	call s:pgb.incr()
588349b2fb0SBram Moolenaar	if s:pgb.needs_redraw
589349b2fb0SBram Moolenaar	  redrawstatus
590349b2fb0SBram Moolenaar	  let s:pgb.needs_redraw = 0
591349b2fb0SBram Moolenaar	endif
592349b2fb0SBram Moolenaar      endif
5935c73622aSBram Moolenaar      let s:lnum = s:lnum + 1
5945c73622aSBram Moolenaar    endif
5955c73622aSBram Moolenaar  endwhile
5965c73622aSBram Moolenaar
5975c73622aSBram Moolenaar  " sort the folds so that we only ever need to look at the first item in the
5985c73622aSBram Moolenaar  " list of folds
5995c73622aSBram Moolenaar  call sort(s:allfolds, "s:FoldCompare")
6005c73622aSBram Moolenaar
601349b2fb0SBram Moolenaar  let &l:foldtext = s:foldtext_save
6025c73622aSBram Moolenaar  unlet s:foldtext_save
6035c73622aSBram Moolenaar
6045c73622aSBram Moolenaar  " close all folds again so we can get the fold text as we go
6055c73622aSBram Moolenaar  silent! %foldclose!
6065c73622aSBram Moolenaarendif
6075c73622aSBram Moolenaar
6085c73622aSBram Moolenaar" Now loop over all lines in the original text to convert to html.
609071d4279SBram Moolenaar" Use html_start_line and html_end_line if they are set.
610b02cbe34SBram Moolenaarif exists("g:html_start_line")
611071d4279SBram Moolenaar  let s:lnum = html_start_line
612071d4279SBram Moolenaar  if s:lnum < 1 || s:lnum > line("$")
613071d4279SBram Moolenaar    let s:lnum = 1
614071d4279SBram Moolenaar  endif
615071d4279SBram Moolenaarelse
616071d4279SBram Moolenaar  let s:lnum = 1
617071d4279SBram Moolenaarendif
618b02cbe34SBram Moolenaarif exists("g:html_end_line")
619071d4279SBram Moolenaar  let s:end = html_end_line
620071d4279SBram Moolenaar  if s:end < s:lnum || s:end > line("$")
621071d4279SBram Moolenaar    let s:end = line("$")
622071d4279SBram Moolenaar  endif
623071d4279SBram Moolenaarelse
624071d4279SBram Moolenaar  let s:end = line("$")
625071d4279SBram Moolenaarendif
626071d4279SBram Moolenaar
6275c73622aSBram Moolenaar" stack to keep track of all the folds containing the current line
6285c73622aSBram Moolenaarlet s:foldstack = []
6295c73622aSBram Moolenaar
630076e8b2aSBram Moolenaarif !s:settings.no_progress
631349b2fb0SBram Moolenaar  let s:pgb = s:ProgressBar("Processing lines:", s:end - s:lnum + 1, s:orgwin)
632349b2fb0SBram Moolenaarendif
633349b2fb0SBram Moolenaar
634076e8b2aSBram Moolenaarif s:settings.number_lines
6355c73622aSBram Moolenaar  let s:margin = strlen(s:end) + 1
6365c73622aSBram Moolenaarelse
6375c73622aSBram Moolenaar  let s:margin = 0
6385c73622aSBram Moolenaarendif
6395c73622aSBram Moolenaar
640076e8b2aSBram Moolenaarif has('folding') && !s:settings.ignore_folding
64135a9aaabSBram Moolenaar  let s:foldfillchar = &fillchars[matchend(&fillchars, 'fold:')]
64235a9aaabSBram Moolenaar  if s:foldfillchar == ''
64335a9aaabSBram Moolenaar    let s:foldfillchar = '-'
6447b0294cbSBram Moolenaar  endif
64535a9aaabSBram Moolenaarendif
64635a9aaabSBram Moolenaarlet s:difffillchar = &fillchars[matchend(&fillchars, 'diff:')]
64735a9aaabSBram Moolenaarif s:difffillchar == ''
64835a9aaabSBram Moolenaar  let s:difffillchar = '-'
6497b0294cbSBram Moolenaarendif
6507b0294cbSBram Moolenaar
6515c73622aSBram Moolenaarlet s:foldId = 0
6527b0294cbSBram Moolenaar
653071d4279SBram Moolenaarwhile s:lnum <= s:end
654071d4279SBram Moolenaar
65547136d70SBram Moolenaar  " If there are filler lines for diff mode, show these above the line.
65647136d70SBram Moolenaar  let s:filler = diff_filler(s:lnum)
65747136d70SBram Moolenaar  if s:filler > 0
65847136d70SBram Moolenaar    let s:n = s:filler
65947136d70SBram Moolenaar    while s:n > 0
66035a9aaabSBram Moolenaar      let s:new = repeat(s:difffillchar, 3)
66147136d70SBram Moolenaar
662076e8b2aSBram Moolenaar      if s:n > 2 && s:n < s:filler && !s:settings.whole_filler
66335a9aaabSBram Moolenaar	let s:new = s:new . " " . s:filler . " inserted lines "
66435a9aaabSBram Moolenaar	let s:n = 2
66535a9aaabSBram Moolenaar      endif
66635a9aaabSBram Moolenaar
667076e8b2aSBram Moolenaar      if !s:settings.no_pre
66835a9aaabSBram Moolenaar	" HTML line wrapping is off--go ahead and fill to the margin
6695c73622aSBram Moolenaar	let s:new = s:new . repeat(s:difffillchar, &columns - strlen(s:new) - s:margin)
6705c73622aSBram Moolenaar      else
6715c73622aSBram Moolenaar	let s:new = s:new . repeat(s:difffillchar, 3)
67235a9aaabSBram Moolenaar      endif
67335a9aaabSBram Moolenaar
6748ada2ccaSBram Moolenaar      let s:new = s:HtmlFormat(s:new, "DiffDelete", "")
675076e8b2aSBram Moolenaar      if s:settings.number_lines
6765c73622aSBram Moolenaar	" Indent if line numbering is on; must be after escaping.
6775c73622aSBram Moolenaar	let s:new = repeat(s:LeadingSpace, s:margin) . s:new
6785c73622aSBram Moolenaar      endif
679349b2fb0SBram Moolenaar      call add(s:lines, s:new.s:HtmlEndline)
68035a9aaabSBram Moolenaar
68147136d70SBram Moolenaar      let s:n = s:n - 1
68247136d70SBram Moolenaar    endwhile
68347136d70SBram Moolenaar    unlet s:n
68447136d70SBram Moolenaar  endif
68547136d70SBram Moolenaar  unlet s:filler
68647136d70SBram Moolenaar
68747136d70SBram Moolenaar  " Start the line with the line number.
688076e8b2aSBram Moolenaar  if s:settings.number_lines
6895c73622aSBram Moolenaar    let s:numcol = repeat(' ', s:margin - 1 - strlen(s:lnum)) . s:lnum . ' '
69047136d70SBram Moolenaar  else
6915c73622aSBram Moolenaar    let s:numcol = ""
69247136d70SBram Moolenaar  endif
69347136d70SBram Moolenaar
6945c73622aSBram Moolenaar  let s:new = ""
6955c73622aSBram Moolenaar
696076e8b2aSBram Moolenaar  if has('folding') && !s:settings.ignore_folding && foldclosed(s:lnum) > -1 && !s:settings.dynamic_folds
6977b0294cbSBram Moolenaar    "
6985c73622aSBram Moolenaar    " This is the beginning of a folded block (with no dynamic folding)
6997b0294cbSBram Moolenaar    "
7005c73622aSBram Moolenaar    let s:new = s:numcol . foldtextresult(s:lnum)
701076e8b2aSBram Moolenaar    if !s:settings.no_pre
70235a9aaabSBram Moolenaar      " HTML line wrapping is off--go ahead and fill to the margin
70335a9aaabSBram Moolenaar      let s:new = s:new . repeat(s:foldfillchar, &columns - strlen(s:new))
7047b0294cbSBram Moolenaar    endif
7057b0294cbSBram Moolenaar
7068ada2ccaSBram Moolenaar    let s:new = s:HtmlFormat(s:new, "Folded", "")
7077b0294cbSBram Moolenaar
7087b0294cbSBram Moolenaar    " Skip to the end of the fold
709349b2fb0SBram Moolenaar    let s:new_lnum = foldclosedend(s:lnum)
710349b2fb0SBram Moolenaar
711076e8b2aSBram Moolenaar    if !s:settings.no_progress
712349b2fb0SBram Moolenaar      call s:pgb.incr(s:new_lnum - s:lnum)
713349b2fb0SBram Moolenaar    endif
714349b2fb0SBram Moolenaar
715349b2fb0SBram Moolenaar    let s:lnum = s:new_lnum
7167b0294cbSBram Moolenaar
7177b0294cbSBram Moolenaar  else
7187b0294cbSBram Moolenaar    "
7195c73622aSBram Moolenaar    " A line that is not folded, or doing dynamic folding.
7207b0294cbSBram Moolenaar    "
72135a9aaabSBram Moolenaar    let s:line = getline(s:lnum)
7227b0294cbSBram Moolenaar    let s:len = strlen(s:line)
7237b0294cbSBram Moolenaar
724076e8b2aSBram Moolenaar    if s:settings.dynamic_folds
7255c73622aSBram Moolenaar      " First insert a closing for any open folds that end on this line
7265c73622aSBram Moolenaar      while !empty(s:foldstack) && get(s:foldstack,0).lastline == s:lnum-1
7275c73622aSBram Moolenaar	let s:new = s:new."</span></span>"
7285c73622aSBram Moolenaar	call remove(s:foldstack, 0)
7295c73622aSBram Moolenaar      endwhile
7305c73622aSBram Moolenaar
7315c73622aSBram Moolenaar      " Now insert an opening any new folds that start on this line
7325c73622aSBram Moolenaar      let s:firstfold = 1
7335c73622aSBram Moolenaar      while !empty(s:allfolds) && get(s:allfolds,0).firstline == s:lnum
7345c73622aSBram Moolenaar	let s:foldId = s:foldId + 1
735349b2fb0SBram Moolenaar	let s:new .= "<span id='"
736349b2fb0SBram Moolenaar	let s:new .= (exists('g:html_diff_win_num') ? "win".g:html_diff_win_num : "")
737349b2fb0SBram Moolenaar	let s:new .= "fold".s:foldId."' class='".s:allfolds[0].type."'>"
738349b2fb0SBram Moolenaar
7395c73622aSBram Moolenaar
7405c73622aSBram Moolenaar	" Unless disabled, add a fold column for the opening line of a fold.
7415c73622aSBram Moolenaar	"
7425c73622aSBram Moolenaar	" Note that dynamic folds require using css so we just use css to take
7435c73622aSBram Moolenaar	" care of the leading spaces rather than using &nbsp; in the case of
7445c73622aSBram Moolenaar	" html_no_pre to make it easier
745076e8b2aSBram Moolenaar	if !s:settings.no_foldcolumn
7465c73622aSBram Moolenaar	  " add fold column that can open the new fold
7475c73622aSBram Moolenaar	  if s:allfolds[0].level > 1 && s:firstfold
7485c73622aSBram Moolenaar	    let s:new = s:new . "<a class='toggle-open FoldColumn' href='javascript:toggleFold(\"fold".s:foldstack[0].id."\")'>"
7495c73622aSBram Moolenaar	    let s:new = s:new . repeat('|', s:allfolds[0].level - 1) . "</a>"
7505c73622aSBram Moolenaar	  endif
7515c73622aSBram Moolenaar	  let s:new = s:new . "<a class='toggle-open FoldColumn' href='javascript:toggleFold(\"fold".s:foldId."\")'>+</a>"
7525c73622aSBram Moolenaar	  let s:new = s:new . "<a class='toggle-open "
7535c73622aSBram Moolenaar	  " If this is not the last fold we're opening on this line, we need
7545c73622aSBram Moolenaar	  " to keep the filler spaces hidden if the fold is opened by mouse
7555c73622aSBram Moolenaar	  " hover. If it is the last fold to open in the line, we shouldn't hide
7565c73622aSBram Moolenaar	  " them, so don't apply the toggle-filler class.
7575c73622aSBram Moolenaar	  if get(s:allfolds, 1, {'firstline': 0}).firstline == s:lnum
7585c73622aSBram Moolenaar	    let s:new = s:new . "toggle-filler "
7595c73622aSBram Moolenaar	  endif
7605c73622aSBram Moolenaar	  let s:new = s:new . "FoldColumn' href='javascript:toggleFold(\"fold".s:foldId."\")'>"
7615c73622aSBram Moolenaar	  let s:new = s:new . repeat(" ", s:foldcolumn - s:allfolds[0].level) . "</a>"
7625c73622aSBram Moolenaar
7635c73622aSBram Moolenaar	  " add fold column that can close the new fold
7645c73622aSBram Moolenaar	  let s:new = s:new . "<a class='toggle-closed FoldColumn' href='javascript:toggleFold(\"fold".s:foldId."\")'>"
7655c73622aSBram Moolenaar	  if s:firstfold
7665c73622aSBram Moolenaar	    let s:new = s:new . repeat('|', s:allfolds[0].level - 1)
7675c73622aSBram Moolenaar	  endif
7685c73622aSBram Moolenaar	  let s:new = s:new . "-"
7695c73622aSBram Moolenaar	  " only add spaces if we aren't opening another fold on the same line
7705c73622aSBram Moolenaar	  if get(s:allfolds, 1, {'firstline': 0}).firstline != s:lnum
7715c73622aSBram Moolenaar	    let s:new = s:new . repeat(" ", s:foldcolumn - s:allfolds[0].level)
7725c73622aSBram Moolenaar	  endif
7735c73622aSBram Moolenaar	  let s:new = s:new . "</a>"
7745c73622aSBram Moolenaar	  let s:firstfold = 0
7755c73622aSBram Moolenaar	endif
7765c73622aSBram Moolenaar
7775c73622aSBram Moolenaar	" add fold text, moving the span ending to the next line so collapsing
7785c73622aSBram Moolenaar	" of folds works correctly
7798ada2ccaSBram Moolenaar	let s:new = s:new . substitute(s:HtmlFormat(s:numcol . foldtextresult(s:lnum), "Folded", ""), '</span>', s:HtmlEndline.'\n\0', '')
7805c73622aSBram Moolenaar	let s:new = s:new . "<span class='fulltext'>"
7815c73622aSBram Moolenaar
7825c73622aSBram Moolenaar	" open the fold now that we have the fold text to allow retrieval of
7835c73622aSBram Moolenaar	" fold text for subsequent folds
7845c73622aSBram Moolenaar	execute s:lnum."foldopen"
7855c73622aSBram Moolenaar	call insert(s:foldstack, remove(s:allfolds,0))
7865c73622aSBram Moolenaar	let s:foldstack[0].id = s:foldId
7875c73622aSBram Moolenaar      endwhile
7885c73622aSBram Moolenaar
7895c73622aSBram Moolenaar      " Unless disabled, add a fold column for other lines.
7905c73622aSBram Moolenaar      "
7915c73622aSBram Moolenaar      " Note that dynamic folds require using css so we just use css to take
7925c73622aSBram Moolenaar      " care of the leading spaces rather than using &nbsp; in the case of
7935c73622aSBram Moolenaar      " html_no_pre to make it easier
794076e8b2aSBram Moolenaar      if !s:settings.no_foldcolumn
7955c73622aSBram Moolenaar	if empty(s:foldstack)
7967510fe74SBram Moolenaar	  " add the empty foldcolumn for unfolded lines if there is a fold
7977510fe74SBram Moolenaar	  " column at all
7987510fe74SBram Moolenaar	  if s:foldcolumn > 0
7998ada2ccaSBram Moolenaar	    let s:new = s:new . s:HtmlFormat(repeat(' ', s:foldcolumn), "FoldColumn", "")
8007510fe74SBram Moolenaar	  endif
8015c73622aSBram Moolenaar	else
8025c73622aSBram Moolenaar	  " add the fold column for folds not on the opening line
8035c73622aSBram Moolenaar	  if get(s:foldstack, 0).firstline < s:lnum
8045c73622aSBram Moolenaar	    let s:new = s:new . "<a class='FoldColumn' href='javascript:toggleFold(\"fold".s:foldstack[0].id."\")'>"
8055c73622aSBram Moolenaar	    let s:new = s:new . repeat('|', s:foldstack[0].level)
8065c73622aSBram Moolenaar	    let s:new = s:new . repeat(' ', s:foldcolumn - s:foldstack[0].level) . "</a>"
8075c73622aSBram Moolenaar	  endif
8085c73622aSBram Moolenaar	endif
8095c73622aSBram Moolenaar      endif
8105c73622aSBram Moolenaar    endif
8115c73622aSBram Moolenaar
8125c73622aSBram Moolenaar    " Now continue with the unfolded line text
813076e8b2aSBram Moolenaar    if s:settings.number_lines
8148ada2ccaSBram Moolenaar      " TODO: why not use the real highlight name here?
8158ada2ccaSBram Moolenaar      let s:new = s:new . s:HtmlFormat(s:numcol, "lnr", "")
816071d4279SBram Moolenaar    endif
817071d4279SBram Moolenaar
81847136d70SBram Moolenaar    " Get the diff attribute, if any.
81947136d70SBram Moolenaar    let s:diffattr = diff_hlID(s:lnum, 1)
82047136d70SBram Moolenaar
8217510fe74SBram Moolenaar    " initialize conceal info to act like not concealed, just in case
8227510fe74SBram Moolenaar    let s:concealinfo = [0, '']
8237510fe74SBram Moolenaar
824071d4279SBram Moolenaar    " Loop over each character in the line
825071d4279SBram Moolenaar    let s:col = 1
8268ada2ccaSBram Moolenaar
8278ada2ccaSBram Moolenaar    " most of the time we won't use the diff_id, initialize to zero
8288ada2ccaSBram Moolenaar    let s:diff_id = 0
8298ada2ccaSBram Moolenaar    let s:diff_id_name = ""
8308ada2ccaSBram Moolenaar
83135a9aaabSBram Moolenaar    while s:col <= s:len || (s:col == 1 && s:diffattr)
832071d4279SBram Moolenaar      let s:startcol = s:col " The start column for processing text
833076e8b2aSBram Moolenaar      if !s:settings.ignore_conceal && has('conceal')
8347510fe74SBram Moolenaar	let s:concealinfo = synconcealed(s:lnum, s:col)
8357510fe74SBram Moolenaar      endif
836076e8b2aSBram Moolenaar      if !s:settings.ignore_conceal && s:concealinfo[0]
8377510fe74SBram Moolenaar	let s:col = s:col + 1
8387510fe74SBram Moolenaar	" Speed loop (it's small - that's the trick)
8397510fe74SBram Moolenaar	" Go along till we find a change in the match sequence number (ending
8407510fe74SBram Moolenaar	" the specific concealed region) or until there are no more concealed
8417510fe74SBram Moolenaar	" characters.
8427510fe74SBram Moolenaar	while s:col <= s:len && s:concealinfo == synconcealed(s:lnum, s:col) | let s:col = s:col + 1 | endwhile
8437510fe74SBram Moolenaar      elseif s:diffattr
8448ada2ccaSBram Moolenaar	let s:diff_id = diff_hlID(s:lnum, s:col)
8458ada2ccaSBram Moolenaar	let s:id = synID(s:lnum, s:col, 1)
84647136d70SBram Moolenaar	let s:col = s:col + 1
84747136d70SBram Moolenaar	" Speed loop (it's small - that's the trick)
84847136d70SBram Moolenaar	" Go along till we find a change in hlID
8498ada2ccaSBram Moolenaar	while s:col <= s:len && s:id == synID(s:lnum, s:col, 1)
8508ada2ccaSBram Moolenaar	      \   && s:diff_id == diff_hlID(s:lnum, s:col) |
8518ada2ccaSBram Moolenaar	      \     let s:col = s:col + 1 |
8528ada2ccaSBram Moolenaar	      \ endwhile
853076e8b2aSBram Moolenaar	if s:len < &columns && !s:settings.no_pre
8548ada2ccaSBram Moolenaar	  " Add spaces at the end of the raw text line to extend the changed
8558ada2ccaSBram Moolenaar	  " line to the full width.
8565c73622aSBram Moolenaar	  let s:line = s:line . repeat(' ', &columns - virtcol([s:lnum, s:len]) - s:margin)
85735a9aaabSBram Moolenaar	  let s:len = &columns
85835a9aaabSBram Moolenaar	endif
85947136d70SBram Moolenaar      else
860071d4279SBram Moolenaar	let s:id = synID(s:lnum, s:col, 1)
861071d4279SBram Moolenaar	let s:col = s:col + 1
862071d4279SBram Moolenaar	" Speed loop (it's small - that's the trick)
863071d4279SBram Moolenaar	" Go along till we find a change in synID
864071d4279SBram Moolenaar	while s:col <= s:len && s:id == synID(s:lnum, s:col, 1) | let s:col = s:col + 1 | endwhile
86547136d70SBram Moolenaar      endif
866071d4279SBram Moolenaar
867076e8b2aSBram Moolenaar      if s:settings.ignore_conceal || !s:concealinfo[0]
86835a9aaabSBram Moolenaar	" Expand tabs
86935a9aaabSBram Moolenaar	let s:expandedtab = strpart(s:line, s:startcol - 1, s:col - s:startcol)
8705c73622aSBram Moolenaar	let s:offset = 0
8715c73622aSBram Moolenaar	let s:idx = stridx(s:expandedtab, "\t")
8725c73622aSBram Moolenaar	while s:idx >= 0
8735c73622aSBram Moolenaar	  if has("multi_byte_encoding")
8745c73622aSBram Moolenaar	    if s:startcol + s:idx == 1
8755c73622aSBram Moolenaar	      let s:i = &ts
8765c73622aSBram Moolenaar	    else
8775c73622aSBram Moolenaar	      if s:idx == 0
8785c73622aSBram Moolenaar		let s:prevc = matchstr(s:line, '.\%' . (s:startcol + s:idx + s:offset) . 'c')
8795c73622aSBram Moolenaar	      else
8805c73622aSBram Moolenaar		let s:prevc = matchstr(s:expandedtab, '.\%' . (s:idx + 1) . 'c')
8815c73622aSBram Moolenaar	      endif
8825c73622aSBram Moolenaar	      let s:vcol = virtcol([s:lnum, s:startcol + s:idx + s:offset - len(s:prevc)])
8835c73622aSBram Moolenaar	      let s:i = &ts - (s:vcol % &ts)
8845c73622aSBram Moolenaar	    endif
8855c73622aSBram Moolenaar	    let s:offset -= s:i - 1
8865c73622aSBram Moolenaar	  else
8875c73622aSBram Moolenaar	    let s:i = &ts - ((s:idx + s:startcol - 1) % &ts)
8885c73622aSBram Moolenaar	  endif
8895c73622aSBram Moolenaar	  let s:expandedtab = substitute(s:expandedtab, '\t', repeat(' ', s:i), '')
8905c73622aSBram Moolenaar	  let s:idx = stridx(s:expandedtab, "\t")
89135a9aaabSBram Moolenaar	endwhile
89235a9aaabSBram Moolenaar
8937510fe74SBram Moolenaar	" get the highlight group name to use
894071d4279SBram Moolenaar	let s:id = synIDtrans(s:id)
895071d4279SBram Moolenaar	let s:id_name = synIDattr(s:id, "name", s:whatterm)
8968ada2ccaSBram Moolenaar	if s:diff_id
8978ada2ccaSBram Moolenaar	  let s:diff_id_name = synIDattr(s:diff_id, "name", s:whatterm)
8988ada2ccaSBram Moolenaar	endif
8997510fe74SBram Moolenaar      else
9007510fe74SBram Moolenaar	" use Conceal highlighting for concealed text
9017510fe74SBram Moolenaar	let s:id_name = 'Conceal'
9027510fe74SBram Moolenaar	let s:expandedtab = s:concealinfo[1]
9037510fe74SBram Moolenaar      endif
9047510fe74SBram Moolenaar
9057510fe74SBram Moolenaar      " Output the text with the same synID, with class set to {s:id_name},
9068ada2ccaSBram Moolenaar      " unless it has been concealed completely.
9077510fe74SBram Moolenaar      if strlen(s:expandedtab) > 0
9088ada2ccaSBram Moolenaar	let s:new = s:new . s:HtmlFormat(s:expandedtab,  s:id_name, s:diff_id_name)
9097510fe74SBram Moolenaar      endif
910071d4279SBram Moolenaar    endwhile
9117b0294cbSBram Moolenaar  endif
912071d4279SBram Moolenaar
9137510fe74SBram Moolenaar  call extend(s:lines, split(s:new.s:HtmlEndline, '\n', 1))
914076e8b2aSBram Moolenaar  if !s:settings.no_progress && s:pgb.needs_redraw
915349b2fb0SBram Moolenaar    redrawstatus
916349b2fb0SBram Moolenaar    let s:pgb.needs_redraw = 0
917349b2fb0SBram Moolenaar  endif
918071d4279SBram Moolenaar  let s:lnum = s:lnum + 1
919313b7237SBram Moolenaar
920076e8b2aSBram Moolenaar  if !s:settings.no_progress
921349b2fb0SBram Moolenaar    call s:pgb.incr()
922349b2fb0SBram Moolenaar  endif
923349b2fb0SBram Moolenaarendwhile
924349b2fb0SBram Moolenaar
925076e8b2aSBram Moolenaarif s:settings.dynamic_folds
9265c73622aSBram Moolenaar  " finish off any open folds
9275c73622aSBram Moolenaar  while !empty(s:foldstack)
928349b2fb0SBram Moolenaar    let s:lines[-1].="</span></span>"
9295c73622aSBram Moolenaar    call remove(s:foldstack, 0)
9305c73622aSBram Moolenaar  endwhile
9315c73622aSBram Moolenaar
9325c73622aSBram Moolenaar  " add fold column to the style list if not already there
9335c73622aSBram Moolenaar  let s:id = hlID('FoldColumn')
9348ada2ccaSBram Moolenaar  if index(s:idlist, s:id) == -1
9358ada2ccaSBram Moolenaar    call insert(s:idlist, s:id)
9365c73622aSBram Moolenaar  endif
9375c73622aSBram Moolenaarendif
9385c73622aSBram Moolenaar
939076e8b2aSBram Moolenaarif s:settings.no_pre
940076e8b2aSBram Moolenaar  if !s:settings.use_css
9418ada2ccaSBram Moolenaar    " Close off the font tag that encapsulates the whole <body>
942*bebca9daSBram Moolenaar    call extend(s:lines, ["</font>", "</body>", "</html>"])
9438ada2ccaSBram Moolenaar  else
944349b2fb0SBram Moolenaar    call extend(s:lines, ["</body>", "</html>"])
9458ada2ccaSBram Moolenaar  endif
946071d4279SBram Moolenaarelse
947349b2fb0SBram Moolenaar  call extend(s:lines, ["</pre>", "</body>", "</html>"])
948071d4279SBram Moolenaarendif
949071d4279SBram Moolenaar
950349b2fb0SBram Moolenaarexe s:newwin . "wincmd w"
951349b2fb0SBram Moolenaarcall setline(1, s:lines)
952349b2fb0SBram Moolenaarunlet s:lines
953071d4279SBram Moolenaar
954071d4279SBram Moolenaar" Now, when we finally know which, we define the colors and styles
955076e8b2aSBram Moolenaarif s:settings.use_css
956071d4279SBram Moolenaar  1;/<style type="text/+1
957071d4279SBram Moolenaarendif
958071d4279SBram Moolenaar
959071d4279SBram Moolenaar" Find out the background and foreground color.
960071d4279SBram Moolenaarlet s:fgc = s:HtmlColor(synIDattr(hlID("Normal"), "fg#", s:whatterm))
961071d4279SBram Moolenaarlet s:bgc = s:HtmlColor(synIDattr(hlID("Normal"), "bg#", s:whatterm))
962071d4279SBram Moolenaarif s:fgc == ""
963071d4279SBram Moolenaar  let s:fgc = ( &background == "dark" ? "#ffffff" : "#000000" )
964071d4279SBram Moolenaarendif
965071d4279SBram Moolenaarif s:bgc == ""
966071d4279SBram Moolenaar  let s:bgc = ( &background == "dark" ? "#000000" : "#ffffff" )
967071d4279SBram Moolenaarendif
968071d4279SBram Moolenaar
969071d4279SBram Moolenaar" Normal/global attributes
970071d4279SBram Moolenaar" For Netscape 4, set <body> attributes too, though, strictly speaking, it's
971071d4279SBram Moolenaar" incorrect.
972076e8b2aSBram Moolenaarif s:settings.use_css
973076e8b2aSBram Moolenaar  if s:settings.no_pre
974313b7237SBram Moolenaar    execute "normal! A\nbody { color: " . s:fgc . "; background-color: " . s:bgc . "; font-family: ". s:htmlfont ."; }\e"
975071d4279SBram Moolenaar  else
976313b7237SBram Moolenaar    execute "normal! A\npre { font-family: ". s:htmlfont ."; color: " . s:fgc . "; background-color: " . s:bgc . "; }\e"
977071d4279SBram Moolenaar    yank
978071d4279SBram Moolenaar    put
979071d4279SBram Moolenaar    execute "normal! ^cwbody\e"
980071d4279SBram Moolenaar  endif
981071d4279SBram Moolenaarelse
982*bebca9daSBram Moolenaar  execute '%s:<body>:<body bgcolor="' . s:bgc . '" text="' . s:fgc . '">\r<font face="'. s:htmlfont .'">'
983071d4279SBram Moolenaarendif
984071d4279SBram Moolenaar
985071d4279SBram Moolenaar" Line numbering attributes
986076e8b2aSBram Moolenaarif s:settings.number_lines
987076e8b2aSBram Moolenaar  if s:settings.use_css
988071d4279SBram Moolenaar    execute "normal! A\n.lnr { " . s:CSS1(hlID("LineNr")) . "}\e"
989071d4279SBram Moolenaar  else
9908424a624SBram Moolenaar    execute '%s+^<span class="lnr">\([^<]*\)</span>+' . s:HtmlOpening(hlID("LineNr")) . '\1' . s:HtmlClosing(hlID("LineNr")) . '+g'
991071d4279SBram Moolenaar  endif
992071d4279SBram Moolenaarendif
993071d4279SBram Moolenaar
994071d4279SBram Moolenaar" Gather attributes for all other classes
995076e8b2aSBram Moolenaarif !s:settings.no_progress && !empty(s:idlist)
996349b2fb0SBram Moolenaar  let s:pgb = s:ProgressBar("Processing classes:", len(s:idlist),s:newwin)
997349b2fb0SBram Moolenaarendif
998349b2fb0SBram Moolenaarwhile !empty(s:idlist)
999071d4279SBram Moolenaar  let s:attr = ""
1000349b2fb0SBram Moolenaar  let s:id = remove(s:idlist, 0)
1001071d4279SBram Moolenaar  let s:attr = s:CSS1(s:id)
1002071d4279SBram Moolenaar  let s:id_name = synIDattr(s:id, "name", s:whatterm)
1003349b2fb0SBram Moolenaar
1004071d4279SBram Moolenaar  " If the class has some attributes, export the style, otherwise DELETE all
1005071d4279SBram Moolenaar  " its occurences to make the HTML shorter
1006071d4279SBram Moolenaar  if s:attr != ""
1007076e8b2aSBram Moolenaar    if s:settings.use_css
1008071d4279SBram Moolenaar      execute "normal! A\n." . s:id_name . " { " . s:attr . "}"
1009071d4279SBram Moolenaar    else
10108ada2ccaSBram Moolenaar      " replace spans of just this class name with non-CSS style markup
10118ada2ccaSBram Moolenaar      execute '%s+<span class="' . s:id_name . '">\([^<]*\)</span>+' . s:HtmlOpening(s:id) . '\1' . s:HtmlClosing(s:id) . '+ge'
10128ada2ccaSBram Moolenaar      " Replace spans of this class name AND a diff class with non-CSS style
10138ada2ccaSBram Moolenaar      " markup surrounding a span of just the diff class. The diff class will
10148ada2ccaSBram Moolenaar      " be handled later because we know that information is at the end.
10158ada2ccaSBram 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'
1016071d4279SBram Moolenaar    endif
1017071d4279SBram Moolenaar  else
1018313b7237SBram Moolenaar    execute '%s+<span class="' . s:id_name . '">\([^<]*\)</span>+\1+ge'
10198ada2ccaSBram Moolenaar    execute '%s+<span class="' . s:id_name . ' \(Diff\%(Add\|Change\|Delete\|Text\)\)">\([^<]*\)</span>+<span class="\1">\2</span>+ge'
1020076e8b2aSBram Moolenaar    if s:settings.use_css
10218ada2ccaSBram Moolenaar      1;/<\/style>/-2
1022071d4279SBram Moolenaar    endif
1023071d4279SBram Moolenaar  endif
1024349b2fb0SBram Moolenaar
1025076e8b2aSBram Moolenaar  if !s:settings.no_progress
1026349b2fb0SBram Moolenaar    call s:pgb.incr()
1027349b2fb0SBram Moolenaar    if s:pgb.needs_redraw
1028349b2fb0SBram Moolenaar      redrawstatus
1029349b2fb0SBram Moolenaar      let s:pgb.needs_redraw = 0
1030*bebca9daSBram Moolenaar      " TODO: sleep here to show the progress bar, but only if total time spent
1031*bebca9daSBram Moolenaar      " so far on this step is < 1 second? Too slow for batch runs like the test
1032*bebca9daSBram Moolenaar      " suite to sleep all the time. Maybe there's no good reason to sleep at
1033*bebca9daSBram Moolenaar      " all.
1034349b2fb0SBram Moolenaar    endif
1035349b2fb0SBram Moolenaar  endif
1036071d4279SBram Moolenaarendwhile
1037071d4279SBram Moolenaar
1038071d4279SBram Moolenaar" Add hyperlinks
10391cd871b5SBram Moolenaar%s+\(https\=://\S\{-}\)\(\([.,;:}]\=\(\s\|$\)\)\|[\\"'<>]\|&gt;\|&lt;\|&quot;\)+<a href="\1">\1</a>\2+ge
1040071d4279SBram Moolenaar
1041071d4279SBram Moolenaar" The DTD
1042076e8b2aSBram Moolenaarif s:settings.use_xhtml
1043076e8b2aSBram 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\">"
1044076e8b2aSBram Moolenaarelseif s:settings.use_css && !s:settings.no_pre
1045076e8b2aSBram Moolenaar  exe "normal! gg0i<!DOCTYPE HTML PUBLIC \"-//W3C//DTD HTML 4.01//EN\" \"http://www.w3.org/TR/html4/strict.dtd\">\n"
10461cd871b5SBram Moolenaarelse
1047076e8b2aSBram Moolenaar  exe "normal! gg0i<!DOCTYPE HTML PUBLIC \"-//W3C//DTD HTML 4.01 Transitional//EN\" \"http://www.w3.org/TR/html4/loose.dtd\">\n"
10481cd871b5SBram Moolenaarendif
10491cd871b5SBram Moolenaar
1050076e8b2aSBram Moolenaarif s:settings.use_xhtml
10511cd871b5SBram Moolenaar  exe "normal! gg/<html/e\na xmlns=\"http://www.w3.org/1999/xhtml\"\e"
10521cd871b5SBram Moolenaarendif
1053071d4279SBram Moolenaar
1054071d4279SBram Moolenaar" Cleanup
1055071d4279SBram Moolenaar%s:\s\+$::e
1056071d4279SBram Moolenaar
1057071d4279SBram Moolenaar" Restore old settings
1058349b2fb0SBram Moolenaarlet &l:foldmethod = s:old_fdm
1059071d4279SBram Moolenaarlet &report = s:old_report
1060071d4279SBram Moolenaarlet &title = s:old_title
1061071d4279SBram Moolenaarlet &icon = s:old_icon
1062071d4279SBram Moolenaarlet &paste = s:old_paste
1063071d4279SBram Moolenaarlet &magic = s:old_magic
1064071d4279SBram Moolenaarlet @/ = s:old_search
1065349b2fb0SBram Moolenaarlet &more = s:old_more
1066071d4279SBram Moolenaarexe s:orgwin . "wincmd w"
1067071d4279SBram Moolenaarlet &l:et = s:old_et
1068071d4279SBram Moolenaarexe s:newwin . "wincmd w"
1069349b2fb0SBram Moolenaarexec 'resize' s:old_winheight
1070349b2fb0SBram Moolenaarlet &l:winfixheight = s:old_winfixheight
1071071d4279SBram Moolenaar
1072349b2fb0SBram Moolenaarcall setwinvar(s:orgwin,'&stl', s:origwin_stl)
1073349b2fb0SBram Moolenaarcall setwinvar(s:newwin,'&stl', s:newwin_stl)
1074349b2fb0SBram Moolenaarlet &ls=s:ls
1075349b2fb0SBram Moolenaar
1076071d4279SBram Moolenaar" Save a little bit of memory (worth doing?)
1077313b7237SBram Moolenaarunlet s:htmlfont
1078349b2fb0SBram Moolenaarunlet s:old_et s:old_paste s:old_icon s:old_report s:old_title s:old_search s:old_magic s:old_more s:old_fdm s:old_winheight s:old_winfixheight
1079349b2fb0SBram Moolenaarunlet s:whatterm s:idlist s:lnum s:end s:margin s:fgc s:bgc
1080076e8b2aSBram Moolenaarunlet! s:col s:id s:attr s:len s:line s:new s:expandedtab s:concealinfo
10817510fe74SBram Moolenaarunlet! s:orgwin s:newwin s:orgbufnr s:idx s:i s:offset s:ls s:origwin_stl s:newwin_stl s:current_syntax
108205159a0cSBram Moolenaarif !v:profiling
1083071d4279SBram Moolenaar  delfunc s:HtmlColor
108435a9aaabSBram Moolenaar  delfunc s:HtmlFormat
1085071d4279SBram Moolenaar  delfunc s:CSS1
1086076e8b2aSBram Moolenaar  if !s:settings.use_css
1087071d4279SBram Moolenaar    delfunc s:HtmlOpening
1088071d4279SBram Moolenaar    delfunc s:HtmlClosing
1089071d4279SBram Moolenaar  endif
1090076e8b2aSBram Moolenaar  if s:settings.dynamic_folds
10915c73622aSBram Moolenaar    delfunc s:FoldCompare
10925c73622aSBram Moolenaar  endif
10935c73622aSBram Moolenaar
1094076e8b2aSBram Moolenaar  if !s:settings.no_progress
1095349b2fb0SBram Moolenaar    delfunc s:ProgressBar
1096349b2fb0SBram Moolenaar    delfunc s:progressbar.paint
1097349b2fb0SBram Moolenaar    delfunc s:progressbar.incr
1098349b2fb0SBram Moolenaar    unlet s:pgb s:progressbar
1099349b2fb0SBram Moolenaar  endif
1100349b2fb0SBram Moolenaarendif
1101349b2fb0SBram Moolenaar
1102349b2fb0SBram Moolenaarunlet! s:new_lnum s:diffattr s:difffillchar s:foldfillchar s:HtmlSpace s:LeadingSpace s:HtmlEndline s:firstfold s:foldcolumn
1103076e8b2aSBram Moolenaarunlet s:foldstack s:allfolds s:foldId s:numcol s:settings
11045c73622aSBram Moolenaar
11055c73622aSBram Moolenaarlet &cpo = s:cpo_sav
1106349b2fb0SBram Moolenaarunlet! s:cpo_sav
11075c73622aSBram Moolenaar
1108349b2fb0SBram Moolenaar" Make sure any patches will probably use consistent indent
11097c86f4ccSBram Moolenaar"   vim: ts=8 sw=2 sts=2 noet
1110