blob: fdee1eaf102c1ad65afbb068664dda943994b1d4 [file] [log] [blame]
Bram Moolenaar071d4272004-06-13 20:20:40 +00001" Vim syntax support file
Bram Moolenaar349b2fb2010-07-16 20:35:36 +02002" Maintainer: Ben Fritz <fritzophrenic@gmail.com>
Bram Moolenaar6c35bea2012-07-25 17:49:10 +02003" Last Change: 2012 Jun 30
Bram Moolenaar349b2fb2010-07-16 20:35:36 +02004"
5" Additional contributors:
6"
Bram Moolenaar7510fe72010-07-25 12:46:44 +02007" Original by Bram Moolenaar <Bram@vim.org>
8" Modified by David Ne\v{c}as (Yeti) <yeti@physics.muni.cz>
9" XHTML support by Panagiotis Issaris <takis@lumumba.luc.ac.be>
10" Made w3 compliant by Edd Barrett <vext01@gmail.com>
11" Added html_font. Edd Barrett <vext01@gmail.com>
12" Progress bar based off code from "progressbar widget" plugin by
13" Andreas Politz, heavily modified:
14" http://www.vim.org/scripts/script.php?script_id=2006
Bram Moolenaar349b2fb2010-07-16 20:35:36 +020015"
Bram Moolenaar7510fe72010-07-25 12:46:44 +020016" See Mercurial change logs for more!
Bram Moolenaar071d4272004-06-13 20:20:40 +000017
18" Transform a file into HTML, using the current syntax highlighting.
19
Bram Moolenaar5c736222010-01-06 20:54:52 +010020" this file uses line continuations
21let s:cpo_sav = &cpo
Bram Moolenaar349b2fb2010-07-16 20:35:36 +020022let s:ls = &ls
Bram Moolenaar6c35bea2012-07-25 17:49:10 +020023set cpo&vim
Bram Moolenaar5c736222010-01-06 20:54:52 +010024
Bram Moolenaar349b2fb2010-07-16 20:35:36 +020025let s:end=line('$')
Bram Moolenaar349b2fb2010-07-16 20:35:36 +020026
Bram Moolenaar313b7232007-05-05 17:56:55 +000027" Font
Bram Moolenaarb02cbe32010-07-11 22:38:52 +020028if exists("g:html_font")
Bram Moolenaar076e8b22010-08-05 21:54:00 +020029 let s:htmlfont = "'". g:html_font . "', monospace"
Bram Moolenaar313b7232007-05-05 17:56:55 +000030else
31 let s:htmlfont = "monospace"
32endif
33
Bram Moolenaar076e8b22010-08-05 21:54:00 +020034let s:settings = tohtml#GetUserSettings()
Bram Moolenaar5c736222010-01-06 20:54:52 +010035
Bram Moolenaar6c35bea2012-07-25 17:49:10 +020036if !exists('s:FOLDED_ID')
37 let s:FOLDED_ID = hlID("Folded") | lockvar s:FOLDED_ID
38 let s:FOLD_C_ID = hlID("FoldColumn") | lockvar s:FOLD_C_ID
39 let s:LINENR_ID = hlID('LineNr') | lockvar s:LINENR_ID
40 let s:DIFF_D_ID = hlID("DiffDelete") | lockvar s:DIFF_D_ID
41 let s:DIFF_A_ID = hlID("DiffAdd") | lockvar s:DIFF_A_ID
42 let s:DIFF_C_ID = hlID("DiffChange") | lockvar s:DIFF_C_ID
43 let s:DIFF_T_ID = hlID("DiffText") | lockvar s:DIFF_T_ID
44 let s:CONCEAL_ID = hlID('Conceal') | lockvar s:CONCEAL_ID
45endif
46
Bram Moolenaar8e5af3e2011-04-28 19:02:44 +020047" Whitespace
48if s:settings.pre_wrap
49 let s:whitespace = "white-space: pre-wrap; "
50else
51 let s:whitespace = ""
52endif
53
Bram Moolenaar6c35bea2012-07-25 17:49:10 +020054if !empty(s:settings.prevent_copy)
55 if s:settings.no_invalid
56 " User has decided they don't want invalid markup. Still works in
57 " OpenOffice, and for text editors, but when pasting into Microsoft Word the
58 " input elements get pasted too and they cannot be deleted (at least not
59 " easily).
60 let s:unselInputType = ""
61 else
62 " Prevent from copy-pasting the input elements into Microsoft Word where
63 " they cannot be deleted easily by deliberately inserting invalid markup.
64 let s:unselInputType = " type='invalid_input_type'"
65 endif
66endif
67
Bram Moolenaar071d4272004-06-13 20:20:40 +000068" When not in gui we can only guess the colors.
Bram Moolenaar6c35bea2012-07-25 17:49:10 +020069" TODO - is this true anymore?
Bram Moolenaar071d4272004-06-13 20:20:40 +000070if has("gui_running")
71 let s:whatterm = "gui"
72else
73 let s:whatterm = "cterm"
74 if &t_Co == 8
Bram Moolenaar6c35bea2012-07-25 17:49:10 +020075 let s:cterm_color = {
76 \ 0: "#808080", 1: "#ff6060", 2: "#00ff00", 3: "#ffff00",
77 \ 4: "#8080ff", 5: "#ff40ff", 6: "#00ffff", 7: "#ffffff"
78 \ }
Bram Moolenaar071d4272004-06-13 20:20:40 +000079 else
Bram Moolenaar6c35bea2012-07-25 17:49:10 +020080 let s:cterm_color = {
81 \ 0: "#000000", 1: "#c00000", 2: "#008000", 3: "#804000",
82 \ 4: "#0000c0", 5: "#c000c0", 6: "#008080", 7: "#c0c0c0",
83 \ 8: "#808080", 9: "#ff6060", 10: "#00ff00", 11: "#ffff00",
84 \ 12: "#8080ff", 13: "#ff40ff", 14: "#00ffff", 15: "#ffffff"
85 \ }
Bram Moolenaar313b7232007-05-05 17:56:55 +000086
87 " Colors for 88 and 256 come from xterm.
88 if &t_Co == 88
Bram Moolenaar6c35bea2012-07-25 17:49:10 +020089 call extend(s:cterm_color, {
90 \ 16: "#000000", 17: "#00008b", 18: "#0000cd", 19: "#0000ff",
91 \ 20: "#008b00", 21: "#008b8b", 22: "#008bcd", 23: "#008bff",
92 \ 24: "#00cd00", 25: "#00cd8b", 26: "#00cdcd", 27: "#00cdff",
93 \ 28: "#00ff00", 29: "#00ff8b", 30: "#00ffcd", 31: "#00ffff",
94 \ 32: "#8b0000", 33: "#8b008b", 34: "#8b00cd", 35: "#8b00ff",
95 \ 36: "#8b8b00", 37: "#8b8b8b", 38: "#8b8bcd", 39: "#8b8bff",
96 \ 40: "#8bcd00", 41: "#8bcd8b", 42: "#8bcdcd", 43: "#8bcdff",
97 \ 44: "#8bff00", 45: "#8bff8b", 46: "#8bffcd", 47: "#8bffff",
98 \ 48: "#cd0000", 49: "#cd008b", 50: "#cd00cd", 51: "#cd00ff",
99 \ 52: "#cd8b00", 53: "#cd8b8b", 54: "#cd8bcd", 55: "#cd8bff",
100 \ 56: "#cdcd00", 57: "#cdcd8b", 58: "#cdcdcd", 59: "#cdcdff",
101 \ 60: "#cdff00", 61: "#cdff8b", 62: "#cdffcd", 63: "#cdffff",
102 \ 64: "#ff0000"
103 \ })
104 call extend(s:cterm_color, {
105 \ 65: "#ff008b", 66: "#ff00cd", 67: "#ff00ff", 68: "#ff8b00",
106 \ 69: "#ff8b8b", 70: "#ff8bcd", 71: "#ff8bff", 72: "#ffcd00",
107 \ 73: "#ffcd8b", 74: "#ffcdcd", 75: "#ffcdff", 76: "#ffff00",
108 \ 77: "#ffff8b", 78: "#ffffcd", 79: "#ffffff", 80: "#2e2e2e",
109 \ 81: "#5c5c5c", 82: "#737373", 83: "#8b8b8b", 84: "#a2a2a2",
110 \ 85: "#b9b9b9", 86: "#d0d0d0", 87: "#e7e7e7"
111 \ })
Bram Moolenaar313b7232007-05-05 17:56:55 +0000112 elseif &t_Co == 256
Bram Moolenaar6c35bea2012-07-25 17:49:10 +0200113 call extend(s:cterm_color, {
114 \ 16: "#000000", 17: "#00005f", 18: "#000087", 19: "#0000af",
115 \ 20: "#0000d7", 21: "#0000ff", 22: "#005f00", 23: "#005f5f",
116 \ 24: "#005f87", 25: "#005faf", 26: "#005fd7", 27: "#005fff",
117 \ 28: "#008700", 29: "#00875f", 30: "#008787", 31: "#0087af",
118 \ 32: "#0087d7", 33: "#0087ff", 34: "#00af00", 35: "#00af5f",
119 \ 36: "#00af87", 37: "#00afaf", 38: "#00afd7", 39: "#00afff",
120 \ 40: "#00d700", 41: "#00d75f", 42: "#00d787", 43: "#00d7af",
121 \ 44: "#00d7d7", 45: "#00d7ff", 46: "#00ff00", 47: "#00ff5f",
122 \ 48: "#00ff87", 49: "#00ffaf", 50: "#00ffd7", 51: "#00ffff",
123 \ 52: "#5f0000", 53: "#5f005f", 54: "#5f0087", 55: "#5f00af",
124 \ 56: "#5f00d7", 57: "#5f00ff", 58: "#5f5f00", 59: "#5f5f5f",
125 \ 60: "#5f5f87", 61: "#5f5faf", 62: "#5f5fd7", 63: "#5f5fff",
126 \ 64: "#5f8700"
127 \ })
128 call extend(s:cterm_color, {
129 \ 65: "#5f875f", 66: "#5f8787", 67: "#5f87af", 68: "#5f87d7",
130 \ 69: "#5f87ff", 70: "#5faf00", 71: "#5faf5f", 72: "#5faf87",
131 \ 73: "#5fafaf", 74: "#5fafd7", 75: "#5fafff", 76: "#5fd700",
132 \ 77: "#5fd75f", 78: "#5fd787", 79: "#5fd7af", 80: "#5fd7d7",
133 \ 81: "#5fd7ff", 82: "#5fff00", 83: "#5fff5f", 84: "#5fff87",
134 \ 85: "#5fffaf", 86: "#5fffd7", 87: "#5fffff", 88: "#870000",
135 \ 89: "#87005f", 90: "#870087", 91: "#8700af", 92: "#8700d7",
136 \ 93: "#8700ff", 94: "#875f00", 95: "#875f5f", 96: "#875f87",
137 \ 97: "#875faf", 98: "#875fd7", 99: "#875fff", 100: "#878700",
138 \ 101: "#87875f", 102: "#878787", 103: "#8787af", 104: "#8787d7",
139 \ 105: "#8787ff", 106: "#87af00", 107: "#87af5f", 108: "#87af87",
140 \ 109: "#87afaf", 110: "#87afd7", 111: "#87afff", 112: "#87d700"
141 \ })
142 call extend(s:cterm_color, {
143 \ 113: "#87d75f", 114: "#87d787", 115: "#87d7af", 116: "#87d7d7",
144 \ 117: "#87d7ff", 118: "#87ff00", 119: "#87ff5f", 120: "#87ff87",
145 \ 121: "#87ffaf", 122: "#87ffd7", 123: "#87ffff", 124: "#af0000",
146 \ 125: "#af005f", 126: "#af0087", 127: "#af00af", 128: "#af00d7",
147 \ 129: "#af00ff", 130: "#af5f00", 131: "#af5f5f", 132: "#af5f87",
148 \ 133: "#af5faf", 134: "#af5fd7", 135: "#af5fff", 136: "#af8700",
149 \ 137: "#af875f", 138: "#af8787", 139: "#af87af", 140: "#af87d7",
150 \ 141: "#af87ff", 142: "#afaf00", 143: "#afaf5f", 144: "#afaf87",
151 \ 145: "#afafaf", 146: "#afafd7", 147: "#afafff", 148: "#afd700",
152 \ 149: "#afd75f", 150: "#afd787", 151: "#afd7af", 152: "#afd7d7",
153 \ 153: "#afd7ff", 154: "#afff00", 155: "#afff5f", 156: "#afff87",
154 \ 157: "#afffaf", 158: "#afffd7"
155 \ })
156 call extend(s:cterm_color, {
157 \ 159: "#afffff", 160: "#d70000", 161: "#d7005f", 162: "#d70087",
158 \ 163: "#d700af", 164: "#d700d7", 165: "#d700ff", 166: "#d75f00",
159 \ 167: "#d75f5f", 168: "#d75f87", 169: "#d75faf", 170: "#d75fd7",
160 \ 171: "#d75fff", 172: "#d78700", 173: "#d7875f", 174: "#d78787",
161 \ 175: "#d787af", 176: "#d787d7", 177: "#d787ff", 178: "#d7af00",
162 \ 179: "#d7af5f", 180: "#d7af87", 181: "#d7afaf", 182: "#d7afd7",
163 \ 183: "#d7afff", 184: "#d7d700", 185: "#d7d75f", 186: "#d7d787",
164 \ 187: "#d7d7af", 188: "#d7d7d7", 189: "#d7d7ff", 190: "#d7ff00",
165 \ 191: "#d7ff5f", 192: "#d7ff87", 193: "#d7ffaf", 194: "#d7ffd7",
166 \ 195: "#d7ffff", 196: "#ff0000", 197: "#ff005f", 198: "#ff0087",
167 \ 199: "#ff00af", 200: "#ff00d7", 201: "#ff00ff", 202: "#ff5f00",
168 \ 203: "#ff5f5f", 204: "#ff5f87"
169 \ })
170 call extend(s:cterm_color, {
171 \ 205: "#ff5faf", 206: "#ff5fd7", 207: "#ff5fff", 208: "#ff8700",
172 \ 209: "#ff875f", 210: "#ff8787", 211: "#ff87af", 212: "#ff87d7",
173 \ 213: "#ff87ff", 214: "#ffaf00", 215: "#ffaf5f", 216: "#ffaf87",
174 \ 217: "#ffafaf", 218: "#ffafd7", 219: "#ffafff", 220: "#ffd700",
175 \ 221: "#ffd75f", 222: "#ffd787", 223: "#ffd7af", 224: "#ffd7d7",
176 \ 225: "#ffd7ff", 226: "#ffff00", 227: "#ffff5f", 228: "#ffff87",
177 \ 229: "#ffffaf", 230: "#ffffd7", 231: "#ffffff", 232: "#080808",
178 \ 233: "#121212", 234: "#1c1c1c", 235: "#262626", 236: "#303030",
179 \ 237: "#3a3a3a", 238: "#444444", 239: "#4e4e4e", 240: "#585858",
180 \ 241: "#626262", 242: "#6c6c6c", 243: "#767676", 244: "#808080",
181 \ 245: "#8a8a8a", 246: "#949494", 247: "#9e9e9e", 248: "#a8a8a8",
182 \ 249: "#b2b2b2", 250: "#bcbcbc", 251: "#c6c6c6", 252: "#d0d0d0",
183 \ 253: "#dadada", 254: "#e4e4e4", 255: "#eeeeee"
184 \ })
Bram Moolenaar313b7232007-05-05 17:56:55 +0000185 endif
Bram Moolenaar071d4272004-06-13 20:20:40 +0000186 endif
187endif
188
189" Return good color specification: in GUI no transformation is done, in
Bram Moolenaar313b7232007-05-05 17:56:55 +0000190" terminal return RGB values of known colors and empty string for unknown
Bram Moolenaar071d4272004-06-13 20:20:40 +0000191if s:whatterm == "gui"
192 function! s:HtmlColor(color)
193 return a:color
194 endfun
195else
196 function! s:HtmlColor(color)
Bram Moolenaar313b7232007-05-05 17:56:55 +0000197 if has_key(s:cterm_color, a:color)
198 return s:cterm_color[a:color]
Bram Moolenaar071d4272004-06-13 20:20:40 +0000199 else
200 return ""
201 endif
202 endfun
203endif
204
Bram Moolenaar6c35bea2012-07-25 17:49:10 +0200205" Find out the background and foreground color for use later
206let s:fgc = s:HtmlColor(synIDattr(hlID("Normal"), "fg#", s:whatterm))
207let s:bgc = s:HtmlColor(synIDattr(hlID("Normal"), "bg#", s:whatterm))
208if s:fgc == ""
209 let s:fgc = ( &background == "dark" ? "#ffffff" : "#000000" )
210endif
211if s:bgc == ""
212 let s:bgc = ( &background == "dark" ? "#000000" : "#ffffff" )
213endif
214
Bram Moolenaarbebca9d2010-08-07 15:47:30 +0200215if !s:settings.use_css
Bram Moolenaar071d4272004-06-13 20:20:40 +0000216 " Return opening HTML tag for given highlight id
217 function! s:HtmlOpening(id)
218 let a = ""
219 if synIDattr(a:id, "inverse")
220 " For inverse, we always must set both colors (and exchange them)
221 let x = s:HtmlColor(synIDattr(a:id, "fg#", s:whatterm))
222 let a = a . '<span style="background-color: ' . ( x != "" ? x : s:fgc ) . '">'
223 let x = s:HtmlColor(synIDattr(a:id, "bg#", s:whatterm))
224 let a = a . '<font color="' . ( x != "" ? x : s:bgc ) . '">'
225 else
226 let x = s:HtmlColor(synIDattr(a:id, "bg#", s:whatterm))
227 if x != "" | let a = a . '<span style="background-color: ' . x . '">' | endif
228 let x = s:HtmlColor(synIDattr(a:id, "fg#", s:whatterm))
229 if x != "" | let a = a . '<font color="' . x . '">' | endif
230 endif
231 if synIDattr(a:id, "bold") | let a = a . "<b>" | endif
232 if synIDattr(a:id, "italic") | let a = a . "<i>" | endif
233 if synIDattr(a:id, "underline") | let a = a . "<u>" | endif
234 return a
235 endfun
236
237 " Return closing HTML tag for given highlight id
Bram Moolenaar349b2fb2010-07-16 20:35:36 +0200238 function! s:HtmlClosing(id)
Bram Moolenaar071d4272004-06-13 20:20:40 +0000239 let a = ""
240 if synIDattr(a:id, "underline") | let a = a . "</u>" | endif
241 if synIDattr(a:id, "italic") | let a = a . "</i>" | endif
242 if synIDattr(a:id, "bold") | let a = a . "</b>" | endif
243 if synIDattr(a:id, "inverse")
244 let a = a . '</font></span>'
245 else
246 let x = s:HtmlColor(synIDattr(a:id, "fg#", s:whatterm))
247 if x != "" | let a = a . '</font>' | endif
248 let x = s:HtmlColor(synIDattr(a:id, "bg#", s:whatterm))
249 if x != "" | let a = a . '</span>' | endif
250 endif
251 return a
252 endfun
253endif
254
Bram Moolenaar6c35bea2012-07-25 17:49:10 +0200255" Use a different function for formatting based on user options. This way we
256" can avoid a lot of logic during the actual execution.
257"
258" Build the function line by line containing only what is needed for the options
259" in use for maximum code sharing with minimal branch logic for greater speed.
260"
261" Note, 'exec' commands do not recognize line continuations, so must concatenate
262" lines rather than continue them.
263if s:settings.use_css
264 " save CSS to a list of rules to add to the output at the end of processing
265
266 " first, get the style names we need
267 let wrapperfunc_lines = [
268 \ 'function! s:BuildStyleWrapper(style_id, diff_style_id, text, make_unselectable, unformatted)',
269 \ '',
270 \ ' let l:style_name = synIDattr(a:style_id, "name", s:whatterm)'
271 \ ]
272 if &diff
273 let wrapperfunc_lines += [
274 \ ' let l:diff_style_name = synIDattr(a:diff_style_id, "name", s:whatterm)']
275
276 " Add normal groups and diff groups to separate lists so we can order them to
277 " allow diff highlight to override normal highlight
278
279 " if primary style IS a diff style, grab it from the diff cache instead
280 " (always succeeds because we pre-populate it)
281 let wrapperfunc_lines += [
282 \ '',
283 \ ' if a:style_id == s:DIFF_D_ID || a:style_id == s:DIFF_A_ID ||'.
284 \ ' a:style_id == s:DIFF_C_ID || a:style_id == s:DIFF_T_ID',
285 \ ' let l:saved_style = get(s:diffstylelist,a:style_id)',
286 \ ' else'
287 \ ]
288 endif
289
290 " get primary style info from cache or build it on the fly if not found
291 let wrapperfunc_lines += [
292 \ ' let l:saved_style = get(s:stylelist,a:style_id)',
293 \ ' if type(l:saved_style) == type(0)',
294 \ ' unlet l:saved_style',
295 \ ' let l:saved_style = s:CSS1(a:style_id)',
296 \ ' if l:saved_style != ""',
297 \ ' let l:saved_style = "." . l:style_name . " { " . l:saved_style . "}"',
298 \ ' endif',
299 \ ' let s:stylelist[a:style_id]= l:saved_style',
300 \ ' endif'
301 \ ]
302 if &diff
303 let wrapperfunc_lines += [ ' endif' ]
304 endif
305
306 " Build the wrapper tags around the text. It turns out that caching these
307 " gives pretty much zero performance gain and adds a lot of logic.
308
309 let wrapperfunc_lines += [
310 \ '',
311 \ ' if l:saved_style == ""'
312 \ ]
313 if &diff
314 let wrapperfunc_lines += [
315 \ ' if a:diff_style_id <= 0'
316 \ ]
317 endif
318 " no surroundings if neither primary nor diff style has any info
319 let wrapperfunc_lines += [
320 \ ' return a:text'
321 \ ]
322 if &diff
323 " no primary style, but diff style
324 let wrapperfunc_lines += [
325 \ ' else',
326 \ ' return "<span class=\"" .l:diff_style_name . "\">".a:text."</span>"',
327 \ ' endif'
328 \ ]
329 endif
330 " open tag for non-empty primary style
331 let wrapperfunc_lines += [
332 \ ' else']
333 " non-empty primary style. handle either empty or non-empty diff style.
334 "
335 " separate the two classes by a space to apply them both if there is a diff
336 " style name, unless the primary style is empty, then just use the diff style
337 " name
338 let diffstyle =
339 \ (&diff ? '(a:diff_style_id <= 0 ? "" : " ". l:diff_style_name) .'
340 \ : "")
341 if s:settings.prevent_copy == ""
342 let wrapperfunc_lines += [
343 \ ' return "<span class=\"" . l:style_name .'.diffstyle.'"\">".a:text."</span>"'
344 \ ]
345 else
346
347 "
348 " Wrap the <input> in a <span> to allow fixing the stupid bug in some fonts
349 " which cause browsers to display a 1px gap between lines when these
350 " <input>s have a background color (maybe not really a bug, this isn't
351 " well-defined)
352 "
353 " use strwidth, because we care only about how many character boxes are
354 " needed to size the input, we don't care how many characters (including
355 " separately counted composing chars, from strchars()) or bytes (from
356 " len())the string contains. strdisplaywidth() is not needed because none of
357 " the unselectable groups can contain tab characters (fold column, fold
358 " text, line number).
359 "
360 " Note, if maxlength property needs to be added in the future, it will need
361 " to use strchars(), because HTML specifies that the maxlength parameter
362 " uses the number of unique codepoints for its limit.
363 let wrapperfunc_lines += [
364 \ ' if a:make_unselectable',
365 \ ' return "<span class=\"" . l:style_name .'.diffstyle.'"\">'.
366 \ '<input'.s:unselInputType.' class=\"" . l:style_name .'.diffstyle.'"\"'.
367 \ ' value=\"".substitute(a:unformatted,''\s\+$'',"","")."\"'.
368 \ ' onselect=''this.blur(); return false;'''.
369 \ ' onmousedown=''this.blur(); return false;'''.
370 \ ' onclick=''this.blur(); return false;'''.
371 \ ' readonly=''readonly'''.
372 \ ' size=\"".strwidth(a:unformatted)."\"'.
373 \ (s:settings.use_xhtml ? '/' : '').'></span>"',
374 \ ' else',
375 \ ' return "<span class=\"" . l:style_name .'. diffstyle .'"\">".a:text."</span>"'
376 \ ]
377 endif
378 " close off tag for non-empty primary style
379 if s:settings.prevent_copy == ""
380 let wrapperfunc_lines[-1] .=
381 \ ' "\">".a:text."</span>"'
382 else
383 let wrapperfunc_lines[-1] .=
384 \ ' "\">".a:text."</span>"'
385 endif
386 let wrapperfunc_lines += [
387 \ ' endif',
388 \ 'endfun'
389 \ ]
390else
391 " Non-CSS method just needs the wrapper.
392 "
393 " Functions used to get opening/closing automatically return null strings if
394 " no styles exist.
395 if &diff
396 let wrapperfunc_lines = [
397 \ 'function! s:BuildStyleWrapper(style_id, diff_style_id, text, unusedarg, unusedarg2)',
398 \ ' return s:HtmlOpening(a:style_id).(a:diff_style_id <= 0 ? "" :'.
399 \ 's:HtmlOpening(a:diff_style_id)).a:text.'.
400 \ '(a:diff_style_id <= 0 ? "" : s:HtmlClosing(a:diff_style_id)).s:HtmlClosing(a:style_id)',
401 \ 'endfun'
402 \ ]
403 else
404 let wrapperfunc_lines = [
405 \ 'function! s:BuildStyleWrapper(style_id, diff_style_id, text, unusedarg, unusedarg2)',
406 \ ' return s:HtmlOpening(a:style_id).a:text.s:HtmlClosing(a:style_id)',
407 \ 'endfun'
408 \ ]
409 endif
410endif
411
412" create the function we built line by line above
413exec join(wrapperfunc_lines, "\n")
414
415let s:diff_mode = &diff
416
Bram Moolenaar35a9aaa2004-10-24 19:23:07 +0000417" Return HTML valid characters enclosed in a span of class style_name with
418" unprintable characters expanded and double spaces replaced as necessary.
Bram Moolenaar6c35bea2012-07-25 17:49:10 +0200419"
420" TODO: eliminate unneeded logic like done for BuildStyleWrapper
421function! s:HtmlFormat(text, style_id, diff_style_id, make_unselectable)
Bram Moolenaar35a9aaa2004-10-24 19:23:07 +0000422 " Replace unprintable characters
Bram Moolenaar6c35bea2012-07-25 17:49:10 +0200423 let unformatted = strtrans(a:text)
Bram Moolenaar35a9aaa2004-10-24 19:23:07 +0000424
Bram Moolenaar6c35bea2012-07-25 17:49:10 +0200425 let formatted = unformatted
Bram Moolenaar8ada2cc2010-07-29 20:43:36 +0200426
Bram Moolenaar35a9aaa2004-10-24 19:23:07 +0000427 " Replace the reserved html characters
Bram Moolenaar2a8a3ec2011-01-08 16:06:37 +0100428 let formatted = substitute(formatted, '&', '\&amp;', 'g')
429 let formatted = substitute(formatted, '<', '\&lt;', 'g')
430 let formatted = substitute(formatted, '>', '\&gt;', 'g')
431 let formatted = substitute(formatted, '"', '\&quot;', 'g')
Bram Moolenaar6c35bea2012-07-25 17:49:10 +0200432 " &apos; is not valid in HTML but it is in XHTML, so just use the numeric
433 " reference for it instead. Needed because it could appear in quotes
434 " especially if unselectable regions is turned on.
435 let formatted = substitute(formatted, '"', '\&#0039;', 'g')
Bram Moolenaar2a8a3ec2011-01-08 16:06:37 +0100436
437 " Replace a "form feed" character with HTML to do a page break
Bram Moolenaar6c35bea2012-07-25 17:49:10 +0200438 " TODO: need to prevent this in unselectable areas? Probably it should never
439 " BE in an unselectable area...
Bram Moolenaar2a8a3ec2011-01-08 16:06:37 +0100440 let formatted = substitute(formatted, "\x0c", '<hr class="PAGE-BREAK">', 'g')
441
Bram Moolenaar8df7f882010-08-13 11:30:02 +0200442 " Replace double spaces, leading spaces, and trailing spaces if needed
Bram Moolenaarc9b4b052006-04-30 18:54:39 +0000443 if ' ' != s:HtmlSpace
Bram Moolenaar35a9aaa2004-10-24 19:23:07 +0000444 let formatted = substitute(formatted, ' ', s:HtmlSpace . s:HtmlSpace, 'g')
Bram Moolenaar8424a622006-04-19 21:23:36 +0000445 let formatted = substitute(formatted, '^ ', s:HtmlSpace, 'g')
Bram Moolenaar8df7f882010-08-13 11:30:02 +0200446 let formatted = substitute(formatted, ' \+$', s:HtmlSpace, 'g')
Bram Moolenaar35a9aaa2004-10-24 19:23:07 +0000447 endif
448
Bram Moolenaar6c35bea2012-07-25 17:49:10 +0200449 " Enclose in the correct format
450 return s:BuildStyleWrapper(a:style_id, a:diff_style_id, formatted, a:make_unselectable, unformatted)
Bram Moolenaar35a9aaa2004-10-24 19:23:07 +0000451endfun
452
Bram Moolenaar6c35bea2012-07-25 17:49:10 +0200453" set up functions to call HtmlFormat in certain ways based on whether the
454" element is supposed to be unselectable or not
455if s:settings.prevent_copy =~# 'n'
456 function! s:HtmlFormat_n(text, style_id, diff_style_id)
457 return s:HtmlFormat(a:text, a:style_id, a:diff_style_id, 1)
458 endfun
459else
460 function! s:HtmlFormat_n(text, style_id, diff_style_id)
461 return s:HtmlFormat(a:text, a:style_id, a:diff_style_id, 0)
462 endfun
463endif
464if s:settings.prevent_copy =~# 'd'
465 function! s:HtmlFormat_d(text, style_id, diff_style_id)
466 return s:HtmlFormat(a:text, a:style_id, a:diff_style_id, 1)
467 endfun
468else
469 function! s:HtmlFormat_d(text, style_id, diff_style_id)
470 return s:HtmlFormat(a:text, a:style_id, a:diff_style_id, 0)
471 endfun
472endif
473if s:settings.prevent_copy =~# 'f'
474 " Note the <input> elements for fill spaces will have a single space for
475 " content, to allow active cursor CSS selection to work.
476 "
477 " Wrap the whole thing in a span for the 1px padding workaround for gaps.
478 function! s:FoldColumn_build(char, len, numfill, char2, class, click)
479 let l:input_open = "<input readonly='readonly'".s:unselInputType.
480 \ " onselect='this.blur(); return false;'".
481 \ " onmousedown='this.blur(); ".a:click." return false;'".
482 \ " onclick='return false;' size='".
483 \ string(a:len + (empty(a:char2) ? 0 : 1) + a:numfill) .
484 \ "' "
485 let l:common_attrs = "class='FoldColumn' value='"
486 let l:input_close = (s:settings.use_xhtml ? "' />" : "'>")
487 return "<span class='".a:class."'>".
488 \ l:input_open.l:common_attrs.repeat(a:char, a:len).
489 \ (!empty(a:char2) ? a:char2 : "").
490 \ l:input_close . "</span>"
491 endfun
492 function! s:FoldColumn_fill()
493 return s:FoldColumn_build('', s:foldcolumn, 0, '', 'FoldColumn', '')
494 endfun
495else
496 " For normal fold columns, simply space-pad to the desired width (note that
497 " the FoldColumn definition includes a whitespace:pre rule)
498 function! s:FoldColumn_build(char, len, numfill, char2, class, click)
499 return "<a href='#' class='".a:class."' onclick='".a:click."'>".
500 \ repeat(a:char, a:len).a:char2.repeat(' ', a:numfill).
501 \ "</a>"
502 endfun
503 function! s:FoldColumn_fill()
504 return s:HtmlFormat(repeat(' ', s:foldcolumn), s:FOLD_C_ID, 0, 0)
505 endfun
506endif
507if s:settings.prevent_copy =~# 't'
508 " put an extra empty span at the end for dynamic folds, so the linebreak can
509 " be surrounded. Otherwise do it as normal.
510 "
511 " TODO: isn't there a better way to do this, than placing it here and using a
512 " substitute later?
513 if s:settings.dynamic_folds
514 function! s:HtmlFormat_t(text, style_id, diff_style_id)
515 return s:HtmlFormat(a:text, a:style_id, a:diff_style_id, 1) .
516 \ s:HtmlFormat("", a:style_id, 0, 0)
517 endfun
518 else
519 function! s:HtmlFormat_t(text, style_id, diff_style_id)
520 return s:HtmlFormat(a:text, a:style_id, a:diff_style_id, 1)
521 endfun
522 endif
523else
524 function! s:HtmlFormat_t(text, style_id, diff_style_id)
525 return s:HtmlFormat(a:text, a:style_id, a:diff_style_id, 0)
526 endfun
527endif
528
Bram Moolenaar071d4272004-06-13 20:20:40 +0000529" Return CSS style describing given highlight id (can be empty)
530function! s:CSS1(id)
531 let a = ""
532 if synIDattr(a:id, "inverse")
533 " For inverse, we always must set both colors (and exchange them)
534 let x = s:HtmlColor(synIDattr(a:id, "bg#", s:whatterm))
535 let a = a . "color: " . ( x != "" ? x : s:bgc ) . "; "
536 let x = s:HtmlColor(synIDattr(a:id, "fg#", s:whatterm))
537 let a = a . "background-color: " . ( x != "" ? x : s:fgc ) . "; "
538 else
539 let x = s:HtmlColor(synIDattr(a:id, "fg#", s:whatterm))
540 if x != "" | let a = a . "color: " . x . "; " | endif
541 let x = s:HtmlColor(synIDattr(a:id, "bg#", s:whatterm))
Bram Moolenaar6c35bea2012-07-25 17:49:10 +0200542 if x != ""
543 let a = a . "background-color: " . x . "; "
544 " stupid hack because almost every browser seems to have at least one font
545 " which shows 1px gaps between lines which have background
546 let a = a . "padding-bottom: 1px; "
547 elseif (a:id == s:FOLDED_ID || a:id == s:LINENR_ID || a:id == s:FOLD_C_ID) && !empty(s:settings.prevent_copy)
548 " input elements default to a different color than the rest of the page
549 let a = a . "background-color: " . s:bgc . "; "
550 endif
Bram Moolenaar071d4272004-06-13 20:20:40 +0000551 endif
552 if synIDattr(a:id, "bold") | let a = a . "font-weight: bold; " | endif
553 if synIDattr(a:id, "italic") | let a = a . "font-style: italic; " | endif
554 if synIDattr(a:id, "underline") | let a = a . "text-decoration: underline; " | endif
555 return a
556endfun
557
Bram Moolenaar076e8b22010-08-05 21:54:00 +0200558if s:settings.dynamic_folds
Bram Moolenaar5c736222010-01-06 20:54:52 +0100559 " compares two folds as stored in our list of folds
560 " A fold is "less" than another if it starts at an earlier line number,
561 " or ends at a later line number, ties broken by fold level
562 function! s:FoldCompare(f1, f2)
563 if a:f1.firstline != a:f2.firstline
564 " put it before if it starts earlier
565 return a:f1.firstline - a:f2.firstline
566 elseif a:f1.lastline != a:f2.lastline
567 " put it before if it ends later
568 return a:f2.lastline - a:f1.lastline
569 else
570 " if folds begin and end on the same lines, put lowest fold level first
571 return a:f1.level - a:f2.level
572 endif
573 endfunction
574
575endif
576
Bram Moolenaar071d4272004-06-13 20:20:40 +0000577
578" Set some options to make it work faster.
Bram Moolenaar071d4272004-06-13 20:20:40 +0000579" Don't report changes for :substitute, there will be many of them.
Bram Moolenaar8df7f882010-08-13 11:30:02 +0200580" Don't change other windows; turn off scroll bind temporarily
Bram Moolenaar071d4272004-06-13 20:20:40 +0000581let s:old_title = &title
582let s:old_icon = &icon
583let s:old_et = &l:et
Bram Moolenaar8df7f882010-08-13 11:30:02 +0200584let s:old_bind = &l:scrollbind
Bram Moolenaar071d4272004-06-13 20:20:40 +0000585let s:old_report = &report
586let s:old_search = @/
Bram Moolenaar349b2fb2010-07-16 20:35:36 +0200587let s:old_more = &more
Bram Moolenaar071d4272004-06-13 20:20:40 +0000588set notitle noicon
589setlocal et
Bram Moolenaar349b2fb2010-07-16 20:35:36 +0200590set nomore
Bram Moolenaar071d4272004-06-13 20:20:40 +0000591set report=1000000
Bram Moolenaar8df7f882010-08-13 11:30:02 +0200592setlocal noscrollbind
Bram Moolenaar071d4272004-06-13 20:20:40 +0000593
Bram Moolenaar7510fe72010-07-25 12:46:44 +0200594if exists(':ownsyntax') && exists('w:current_syntax')
595 let s:current_syntax = w:current_syntax
596elseif exists('b:current_syntax')
597 let s:current_syntax = b:current_syntax
598else
599 let s:current_syntax = 'none'
600endif
601
602if s:current_syntax == ''
603 let s:current_syntax = 'none'
604endif
605
Bram Moolenaar071d4272004-06-13 20:20:40 +0000606" Split window to create a buffer with the HTML file.
607let s:orgbufnr = winbufnr(0)
Bram Moolenaar349b2fb2010-07-16 20:35:36 +0200608let s:origwin_stl = &l:stl
Bram Moolenaar071d4272004-06-13 20:20:40 +0000609if expand("%") == ""
Bram Moolenaar076e8b22010-08-05 21:54:00 +0200610 exec 'new Untitled.'.(s:settings.use_xhtml ? 'x' : '').'html'
Bram Moolenaar071d4272004-06-13 20:20:40 +0000611else
Bram Moolenaar076e8b22010-08-05 21:54:00 +0200612 exec 'new %.'.(s:settings.use_xhtml ? 'x' : '').'html'
Bram Moolenaar071d4272004-06-13 20:20:40 +0000613endif
Bram Moolenaar349b2fb2010-07-16 20:35:36 +0200614
615" Resize the new window to very small in order to make it draw faster
616let s:old_winheight = winheight(0)
617let s:old_winfixheight = &l:winfixheight
618if s:old_winheight > 2
619 resize 1 " leave enough room to view one line at a time
620 norm! G
621 norm! zt
622endif
623setlocal winfixheight
624
625let s:newwin_stl = &l:stl
626
627" on the new window, set the least time-consuming fold method
628let s:old_fdm = &foldmethod
Bram Moolenaar8df7f882010-08-13 11:30:02 +0200629let s:old_fen = &foldenable
Bram Moolenaar349b2fb2010-07-16 20:35:36 +0200630setlocal foldmethod=manual
Bram Moolenaar8df7f882010-08-13 11:30:02 +0200631setlocal nofoldenable
Bram Moolenaar349b2fb2010-07-16 20:35:36 +0200632
Bram Moolenaar071d4272004-06-13 20:20:40 +0000633let s:newwin = winnr()
634let s:orgwin = bufwinnr(s:orgbufnr)
635
Bram Moolenaar349b2fb2010-07-16 20:35:36 +0200636setlocal modifiable
Bram Moolenaar071d4272004-06-13 20:20:40 +0000637%d
638let s:old_paste = &paste
639set paste
640let s:old_magic = &magic
641set magic
642
Bram Moolenaar166af9b2010-11-16 20:34:40 +0100643" set the fileencoding to match the charset we'll be using
644let &l:fileencoding=s:settings.vim_encoding
645
646" According to http://www.w3.org/TR/html4/charset.html#doc-char-set, the byte
647" order mark is highly recommend on the web when using multibyte encodings. But,
648" it is not a good idea to include it on UTF-8 files. Otherwise, let Vim
649" determine when it is actually inserted.
650if s:settings.vim_encoding == 'utf-8'
651 setlocal nobomb
652else
653 setlocal bomb
654endif
655
Bram Moolenaar349b2fb2010-07-16 20:35:36 +0200656let s:lines = []
657
Bram Moolenaar076e8b22010-08-05 21:54:00 +0200658if s:settings.use_xhtml
Bram Moolenaarbebca9d2010-08-07 15:47:30 +0200659 if s:settings.encoding != ""
660 call add(s:lines, "<?xml version=\"1.0\" encoding=\"" . s:settings.encoding . "\"?>")
Bram Moolenaar1cd871b2004-12-19 22:46:22 +0000661 else
Bram Moolenaar349b2fb2010-07-16 20:35:36 +0200662 call add(s:lines, "<?xml version=\"1.0\"?>")
Bram Moolenaar1cd871b2004-12-19 22:46:22 +0000663 endif
Bram Moolenaar313b7232007-05-05 17:56:55 +0000664 let s:tag_close = ' />'
Bram Moolenaar071d4272004-06-13 20:20:40 +0000665else
Bram Moolenaar35a9aaa2004-10-24 19:23:07 +0000666 let s:tag_close = '>'
667endif
668
669let s:HtmlSpace = ' '
Bram Moolenaarc1e37902006-04-18 21:55:01 +0000670let s:LeadingSpace = ' '
Bram Moolenaar35a9aaa2004-10-24 19:23:07 +0000671let s:HtmlEndline = ''
Bram Moolenaar076e8b22010-08-05 21:54:00 +0200672if s:settings.no_pre
Bram Moolenaar35a9aaa2004-10-24 19:23:07 +0000673 let s:HtmlEndline = '<br' . s:tag_close
Bram Moolenaare37d50a2008-08-06 17:06:04 +0000674 let s:LeadingSpace = '&nbsp;'
Bram Moolenaarc1e37902006-04-18 21:55:01 +0000675 let s:HtmlSpace = '\' . s:LeadingSpace
Bram Moolenaar071d4272004-06-13 20:20:40 +0000676endif
677
678" HTML header, with the title and generator ;-). Left free space for the CSS,
679" to be filled at the end.
Bram Moolenaar349b2fb2010-07-16 20:35:36 +0200680call extend(s:lines, [
Bram Moolenaarbebca9d2010-08-07 15:47:30 +0200681 \ "<html>",
682 \ "<head>"])
683" include encoding as close to the top as possible, but only if not already
684" contained in XML information (to avoid haggling over content type)
685if s:settings.encoding != "" && !s:settings.use_xhtml
686 call add(s:lines, "<meta http-equiv=\"content-type\" content=\"text/html; charset=" . s:settings.encoding . '"' . s:tag_close)
Bram Moolenaar071d4272004-06-13 20:20:40 +0000687endif
Bram Moolenaarbebca9d2010-08-07 15:47:30 +0200688call extend(s:lines, [
689 \ ("<title>".expand("%:p:~")."</title>"),
690 \ ("<meta name=\"Generator\" content=\"Vim/".v:version/100.".".v:version%100.'"'.s:tag_close),
691 \ ("<meta name=\"plugin-version\" content=\"".g:loaded_2html_plugin.'"'.s:tag_close)
692 \ ])
Bram Moolenaar7510fe72010-07-25 12:46:44 +0200693call add(s:lines, '<meta name="syntax" content="'.s:current_syntax.'"'.s:tag_close)
Bram Moolenaar076e8b22010-08-05 21:54:00 +0200694call add(s:lines, '<meta name="settings" content="'.
695 \ join(filter(keys(s:settings),'s:settings[v:val]'),',').
Bram Moolenaar6c35bea2012-07-25 17:49:10 +0200696 \ ',prevent_copy='.s:settings.prevent_copy.
Bram Moolenaar076e8b22010-08-05 21:54:00 +0200697 \ '"'.s:tag_close)
Bram Moolenaar6c35bea2012-07-25 17:49:10 +0200698call add(s:lines, '<meta name="colorscheme" content="'.
699 \ (exists('g:colors_name')
700 \ ? g:colors_name
701 \ : 'none'). '"'.s:tag_close)
Bram Moolenaar313b7232007-05-05 17:56:55 +0000702
Bram Moolenaar076e8b22010-08-05 21:54:00 +0200703if s:settings.use_css
704 if s:settings.dynamic_folds
705 if s:settings.hover_unfold
Bram Moolenaar5c736222010-01-06 20:54:52 +0100706 " if we are doing hover_unfold, use css 2 with css 1 fallback for IE6
Bram Moolenaar349b2fb2010-07-16 20:35:36 +0200707 call extend(s:lines, [
708 \ "<style type=\"text/css\">",
Bram Moolenaarbebca9d2010-08-07 15:47:30 +0200709 \ s:settings.use_xhtml ? "" : "<!--",
Bram Moolenaar349b2fb2010-07-16 20:35:36 +0200710 \ ".FoldColumn { text-decoration: none; white-space: pre; }",
711 \ "",
712 \ "body * { margin: 0; padding: 0; }", "",
713 \ ".open-fold > .Folded { display: none; }",
714 \ ".open-fold > .fulltext { display: inline; }",
715 \ ".closed-fold > .fulltext { display: none; }",
716 \ ".closed-fold > .Folded { display: inline; }",
717 \ "",
718 \ ".open-fold > .toggle-open { display: none; }",
719 \ ".open-fold > .toggle-closed { display: inline; }",
720 \ ".closed-fold > .toggle-open { display: inline; }",
721 \ ".closed-fold > .toggle-closed { display: none; }",
722 \ "", "",
723 \ '/* opening a fold while hovering won''t be supported by IE6 and other',
724 \ "similar browsers, but it should fail gracefully. */",
725 \ ".closed-fold:hover > .fulltext { display: inline; }",
726 \ ".closed-fold:hover > .toggle-filler { display: none; }",
727 \ ".closed-fold:hover > .Folded { display: none; }",
Bram Moolenaarbebca9d2010-08-07 15:47:30 +0200728 \ s:settings.use_xhtml ? "" : '-->',
Bram Moolenaar8df7f882010-08-13 11:30:02 +0200729 \ '</style>'])
Bram Moolenaarbebca9d2010-08-07 15:47:30 +0200730 " TODO: IE7 doesn't *actually* support XHTML, maybe we should remove this.
731 " But if it's served up as tag soup, maybe the following will work, so
732 " leave it in for now.
733 call extend(s:lines, [
Bram Moolenaar349b2fb2010-07-16 20:35:36 +0200734 \ "<!--[if lt IE 7]><style type=\"text/css\">",
735 \ ".open-fold .Folded { display: none; }",
736 \ ".open-fold .fulltext { display: inline; }",
737 \ ".open-fold .toggle-open { display: none; }",
738 \ ".closed-fold .toggle-closed { display: inline; }",
739 \ "",
740 \ ".closed-fold .fulltext { display: none; }",
741 \ ".closed-fold .Folded { display: inline; }",
742 \ ".closed-fold .toggle-open { display: inline; }",
743 \ ".closed-fold .toggle-closed { display: none; }",
744 \ "</style>",
745 \ "<![endif]-->",
746 \])
Bram Moolenaar5c736222010-01-06 20:54:52 +0100747 else
748 " if we aren't doing hover_unfold, use CSS 1 only
Bram Moolenaar349b2fb2010-07-16 20:35:36 +0200749 call extend(s:lines, [
750 \ "<style type=\"text/css\">",
Bram Moolenaarbebca9d2010-08-07 15:47:30 +0200751 \ s:settings.use_xhtml ? "" :"<!--",
Bram Moolenaar349b2fb2010-07-16 20:35:36 +0200752 \ ".FoldColumn { text-decoration: none; white-space: pre; }",
753 \ ".open-fold .Folded { display: none; }",
754 \ ".open-fold .fulltext { display: inline; }",
755 \ ".open-fold .toggle-open { display: none; }",
756 \ ".closed-fold .toggle-closed { display: inline; }",
757 \ "",
758 \ ".closed-fold .fulltext { display: none; }",
759 \ ".closed-fold .Folded { display: inline; }",
760 \ ".closed-fold .toggle-open { display: inline; }",
761 \ ".closed-fold .toggle-closed { display: none; }",
Bram Moolenaarbebca9d2010-08-07 15:47:30 +0200762 \ s:settings.use_xhtml ? "" : '-->',
Bram Moolenaar349b2fb2010-07-16 20:35:36 +0200763 \ '</style>'
764 \])
Bram Moolenaar5c736222010-01-06 20:54:52 +0100765 endif
766 else
767 " if we aren't doing any dynamic folding, no need for any special rules
Bram Moolenaar349b2fb2010-07-16 20:35:36 +0200768 call extend(s:lines, [
769 \ "<style type=\"text/css\">",
Bram Moolenaarbebca9d2010-08-07 15:47:30 +0200770 \ s:settings.use_xhtml ? "" : "<!--",
771 \ s:settings.use_xhtml ? "" : '-->',
Bram Moolenaar349b2fb2010-07-16 20:35:36 +0200772 \ "</style>",
773 \])
Bram Moolenaar5c736222010-01-06 20:54:52 +0100774 endif
Bram Moolenaar071d4272004-06-13 20:20:40 +0000775endif
Bram Moolenaar5c736222010-01-06 20:54:52 +0100776
Bram Moolenaar6c35bea2012-07-25 17:49:10 +0200777" insert script tag if any javascript is needed
778if s:settings.dynamic_folds || s:settings.prevent_copy != ""
779 call extend(s:lines, [
780 \ "",
781 \ "<script type='text/javascript'>",
782 \ s:settings.use_xhtml ? '//<![CDATA[' : "<!--"])
783endif
784
Bram Moolenaar5c736222010-01-06 20:54:52 +0100785" insert javascript to toggle folds open and closed
Bram Moolenaar076e8b22010-08-05 21:54:00 +0200786if s:settings.dynamic_folds
Bram Moolenaar349b2fb2010-07-16 20:35:36 +0200787 call extend(s:lines, [
788 \ "",
Bram Moolenaar349b2fb2010-07-16 20:35:36 +0200789 \ "function toggleFold(objID)",
790 \ "{",
791 \ " var fold;",
792 \ " fold = document.getElementById(objID);",
793 \ " if(fold.className == 'closed-fold')",
794 \ " {",
795 \ " fold.className = 'open-fold';",
796 \ " }",
797 \ " else if (fold.className == 'open-fold')",
798 \ " {",
799 \ " fold.className = 'closed-fold';",
800 \ " }",
Bram Moolenaar6c35bea2012-07-25 17:49:10 +0200801 \ "}"
Bram Moolenaar349b2fb2010-07-16 20:35:36 +0200802 \])
Bram Moolenaar5c736222010-01-06 20:54:52 +0100803endif
804
Bram Moolenaar6c35bea2012-07-25 17:49:10 +0200805" Small text columns like the foldcolumn and line number column need a weird
806" hack to work around Webkit's and (in versions prior to 9) IE's lack of support
807" for the 'ch' unit without messing up Opera, which also doesn't support it but
808" works anyway.
809"
810" The problem is that without the 'ch' unit, it is not possible to specify a
811" size of an <input> in terms of character widths. Only Opera seems to do the
812" "sensible" thing and make the <input> sized to fit exactly as many characters
813" as specified by its "size" attribute, but the spec actually says "at least
814" wide enough to fit 'size' characters", so the other browsers are technically
815" correct as well.
816"
817" Anyway, this leads to two diffculties:
818" 1. The foldcolumn is made up of multiple elements side-by-side with
819" different sizes, each of which has their own extra padding added. Thus, a
820" column made up of one item of size 1 and another of size 2 would not
821" necessarily be equal in size to another line's foldcolumn with a single
822" item of size 3.
823" 2. The extra padding added to the <input> elements adds up to make the
824" foldcolumn and line number column too wide, especially in Webkit
825" browsers.
826"
827" So, the full workaround is:
828" 1. Define a default size in em, equal to the number of characters in the
829" input element, in case javascript is disabled and the browser does not
830" support the 'ch' unit. Unfortunately this makes Opera no longer work
831" properly without javascript. 1em per character is much too wide but it
832" looks better in webkit browsers than unaligned columns.
833" 2. Insert the following javascript to run at page load, which checks for the
834" width of a single character (in an extraneous page element inserted
835" before the page title, and set to hidden) and compares it to the width of
836" another extra <input> element with only one character. If the width
837" matches, the script does nothing more, but if not, it will figure out the
838" fraction of an em unit which would correspond with a ch unit if there
839" were one, and set the containing element (<pre> or <div>) to a class with
840" pre-defined rules which is closest to that fraction of an em. Rules are
841" defined from 0.05 em to 1em per ch.
842if !empty(s:settings.prevent_copy)
843 call extend(s:lines, [
844 \ '',
845 \ '/* simulate a "ch" unit by asking the browser how big a zero character is */',
846 \ 'function FixCharWidth() {',
847 \ ' /* get the hidden element which gives the width of a single character */',
848 \ ' var goodWidth = document.getElementById("oneCharWidth").clientWidth;',
849 \ ' /* get all input elements, we''ll filter on class later */',
850 \ ' var inputTags = document.getElementsByTagName("input");',
851 \ ' var ratio = 5;',
852 \ ' var inputWidth = document.getElementById("oneInputWidth").clientWidth;',
853 \ ' var emWidth = document.getElementById("oneEmWidth").clientWidth;',
854 \ ' if (inputWidth > goodWidth) {',
855 \ ' while (ratio < 100*goodWidth/emWidth && ratio < 100) {',
856 \ ' ratio += 5;',
857 \ ' }',
858 \ ' document.getElementById("vimCodeElement").className = "em"+ratio;',
859 \ ' }',
860 \ '}'
861 \ ])
862endif
863
864" insert script closing tag if any javascript is needed
865if s:settings.dynamic_folds || s:settings.prevent_copy != ""
866 call extend(s:lines, [
867 \ '',
868 \ s:settings.use_xhtml ? '//]]>' : '-->',
869 \ "</script>"
870 \ ])
871endif
872
873call extend(s:lines, ["</head>"])
874if !empty(s:settings.prevent_copy)
875 call extend(s:lines,
876 \ ["<body onload='FixCharWidth();'>",
877 \ "<!-- hidden divs used by javascript to get the width of a char -->",
878 \ "<div id='oneCharWidth'>0</div>",
879 \ "<div id='oneInputWidth'><input size='1' value='0'".s:tag_close."</div>",
880 \ "<div id='oneEmWidth' style='width: 1em;'></div>"
881 \ ])
Bram Moolenaar071d4272004-06-13 20:20:40 +0000882else
Bram Moolenaar6c35bea2012-07-25 17:49:10 +0200883 call extend(s:lines, ["<body>"])
884endif
885if s:settings.no_pre
886 " if we're not using CSS we use a font tag which can't have a div inside
887 if s:settings.use_css
888 call extend(s:lines, ["<div id='vimCodeElement'>"])
889 endif
890else
891 call extend(s:lines, ["<pre id='vimCodeElement'>"])
Bram Moolenaar071d4272004-06-13 20:20:40 +0000892endif
893
894exe s:orgwin . "wincmd w"
895
Bram Moolenaar6c35bea2012-07-25 17:49:10 +0200896" caches of style data
897" initialize to include line numbers if using them
898if s:settings.number_lines
899 let s:stylelist = { s:LINENR_ID : ".LineNr { " . s:CSS1( s:LINENR_ID ) . "}" }
900else
901 let s:stylelist = {}
902endif
903let s:diffstylelist = {
904 \ s:DIFF_A_ID : ".DiffAdd { " . s:CSS1( s:DIFF_A_ID ) . "}",
905 \ s:DIFF_C_ID : ".DiffChange { " . s:CSS1( s:DIFF_C_ID ) . "}",
906 \ s:DIFF_D_ID : ".DiffDelete { " . s:CSS1( s:DIFF_D_ID ) . "}",
907 \ s:DIFF_T_ID : ".DiffText { " . s:CSS1( s:DIFF_T_ID ) . "}"
908 \ }
Bram Moolenaar071d4272004-06-13 20:20:40 +0000909
Bram Moolenaar349b2fb2010-07-16 20:35:36 +0200910" set up progress bar in the status line
Bram Moolenaar076e8b22010-08-05 21:54:00 +0200911if !s:settings.no_progress
Bram Moolenaar349b2fb2010-07-16 20:35:36 +0200912 " ProgressBar Indicator
913 let s:progressbar={}
914
915 " Progessbar specific functions
916 func! s:ProgressBar(title, max_value, winnr)
917 let pgb=copy(s:progressbar)
918 let pgb.title = a:title.' '
919 let pgb.max_value = a:max_value
920 let pgb.winnr = a:winnr
921 let pgb.cur_value = 0
922 let pgb.items = { 'title' : { 'color' : 'Statusline' },
923 \'bar' : { 'color' : 'Statusline' , 'fillcolor' : 'DiffDelete' , 'bg' : 'Statusline' } ,
924 \'counter' : { 'color' : 'Statusline' } }
925 let pgb.last_value = 0
926 let pgb.needs_redraw = 0
927 " Note that you must use len(split) instead of len() if you want to use
928 " unicode in title.
929 "
930 " Subtract 3 for spacing around the title.
931 " Subtract 4 for the percentage display.
932 " Subtract 2 for spacing before this.
933 " Subtract 2 more for the '|' on either side of the progress bar
934 let pgb.subtractedlen=len(split(pgb.title, '\zs'))+3+4+2+2
935 let pgb.max_len = 0
936 set laststatus=2
937 return pgb
938 endfun
939
940 " Function: progressbar.calculate_ticks() {{{1
941 func! s:progressbar.calculate_ticks(pb_len)
942 if a:pb_len<=0
943 let pb_len = 100
944 else
945 let pb_len = a:pb_len
946 endif
947 let self.progress_ticks = map(range(pb_len+1), "v:val * self.max_value / pb_len")
948 endfun
949
950 "Function: progressbar.paint()
951 func! s:progressbar.paint()
952 " Recalculate widths.
953 let max_len = winwidth(self.winnr)
954 let pb_len = 0
955 " always true on first call because of initial value of self.max_len
956 if max_len != self.max_len
957 let self.max_len = max_len
958
959 " Progressbar length
960 let pb_len = max_len - self.subtractedlen
961
962 call self.calculate_ticks(pb_len)
963
964 let self.needs_redraw = 1
965 let cur_value = 0
966 let self.pb_len = pb_len
967 else
968 " start searching at the last found index to make the search for the
969 " appropriate tick value normally take 0 or 1 comparisons
970 let cur_value = self.last_value
971 let pb_len = self.pb_len
972 endif
973
974 let cur_val_max = pb_len > 0 ? pb_len : 100
975
976 " find the current progress bar position based on precalculated thresholds
977 while cur_value < cur_val_max && self.cur_value > self.progress_ticks[cur_value]
978 let cur_value += 1
979 endwhile
980
981 " update progress bar
982 if self.last_value != cur_value || self.needs_redraw || self.cur_value == self.max_value
983 let self.needs_redraw = 1
984 let self.last_value = cur_value
985
986 let t_color = self.items.title.color
987 let b_fcolor = self.items.bar.fillcolor
988 let b_color = self.items.bar.color
989 let c_color = self.items.counter.color
990
991 let stl = "%#".t_color."#%-( ".self.title." %)".
992 \"%#".b_color."#".
993 \(pb_len>0 ?
994 \ ('|%#'.b_fcolor."#%-(".repeat(" ",cur_value)."%)".
995 \ '%#'.b_color."#".repeat(" ",pb_len-cur_value)."|"):
996 \ ('')).
997 \"%=%#".c_color."#%( ".printf("%3.d ",100*self.cur_value/self.max_value)."%% %)"
998 call setwinvar(self.winnr, '&stl', stl)
999 endif
1000 endfun
1001
1002 func! s:progressbar.incr( ... )
1003 let self.cur_value += (a:0 ? a:1 : 1)
1004 " if we were making a general-purpose progress bar, we'd need to limit to a
1005 " lower limit as well, but since we always increment with a positive value
1006 " in this script, we only need limit the upper value
1007 let self.cur_value = (self.cur_value > self.max_value ? self.max_value : self.cur_value)
1008 call self.paint()
1009 endfun
1010 " }}}
Bram Moolenaar076e8b22010-08-05 21:54:00 +02001011 if s:settings.dynamic_folds
Bram Moolenaar349b2fb2010-07-16 20:35:36 +02001012 " to process folds we make two passes through each line
1013 let s:pgb = s:ProgressBar("Processing folds:", line('$')*2, s:orgwin)
1014 endif
Bram Moolenaar349b2fb2010-07-16 20:35:36 +02001015endif
1016
Bram Moolenaar5c736222010-01-06 20:54:52 +01001017" First do some preprocessing for dynamic folding. Do this for the entire file
1018" so we don't accidentally start within a closed fold or something.
1019let s:allfolds = []
1020
Bram Moolenaar076e8b22010-08-05 21:54:00 +02001021if s:settings.dynamic_folds
Bram Moolenaar5c736222010-01-06 20:54:52 +01001022 let s:lnum = 1
1023 let s:end = line('$')
1024 " save the fold text and set it to the default so we can find fold levels
1025 let s:foldtext_save = &foldtext
Bram Moolenaar349b2fb2010-07-16 20:35:36 +02001026 setlocal foldtext&
Bram Moolenaar5c736222010-01-06 20:54:52 +01001027
1028 " we will set the foldcolumn in the html to the greater of the maximum fold
1029 " level and the current foldcolumn setting
1030 let s:foldcolumn = &foldcolumn
1031
1032 " get all info needed to describe currently closed folds
Bram Moolenaar349b2fb2010-07-16 20:35:36 +02001033 while s:lnum <= s:end
Bram Moolenaar5c736222010-01-06 20:54:52 +01001034 if foldclosed(s:lnum) == s:lnum
1035 " default fold text has '+-' and then a number of dashes equal to fold
1036 " level, so subtract 2 from index of first non-dash after the dashes
1037 " in order to get the fold level of the current fold
1038 let s:level = match(foldtextresult(s:lnum), '+-*\zs[^-]') - 2
Bram Moolenaar5c736222010-01-06 20:54:52 +01001039 " store fold info for later use
1040 let s:newfold = {'firstline': s:lnum, 'lastline': foldclosedend(s:lnum), 'level': s:level,'type': "closed-fold"}
1041 call add(s:allfolds, s:newfold)
1042 " open the fold so we can find any contained folds
1043 execute s:lnum."foldopen"
1044 else
Bram Moolenaar076e8b22010-08-05 21:54:00 +02001045 if !s:settings.no_progress
Bram Moolenaar349b2fb2010-07-16 20:35:36 +02001046 call s:pgb.incr()
1047 if s:pgb.needs_redraw
1048 redrawstatus
1049 let s:pgb.needs_redraw = 0
1050 endif
1051 endif
Bram Moolenaar5c736222010-01-06 20:54:52 +01001052 let s:lnum = s:lnum + 1
1053 endif
1054 endwhile
1055
1056 " close all folds to get info for originally open folds
1057 silent! %foldclose!
1058 let s:lnum = 1
1059
1060 " the originally open folds will be all folds we encounter that aren't
1061 " already in the list of closed folds
Bram Moolenaar349b2fb2010-07-16 20:35:36 +02001062 while s:lnum <= s:end
Bram Moolenaar5c736222010-01-06 20:54:52 +01001063 if foldclosed(s:lnum) == s:lnum
1064 " default fold text has '+-' and then a number of dashes equal to fold
1065 " level, so subtract 2 from index of first non-dash after the dashes
1066 " in order to get the fold level of the current fold
1067 let s:level = match(foldtextresult(s:lnum), '+-*\zs[^-]') - 2
Bram Moolenaar5c736222010-01-06 20:54:52 +01001068 let s:newfold = {'firstline': s:lnum, 'lastline': foldclosedend(s:lnum), 'level': s:level,'type': "closed-fold"}
1069 " only add the fold if we don't already have it
1070 if empty(s:allfolds) || index(s:allfolds, s:newfold) == -1
1071 let s:newfold.type = "open-fold"
1072 call add(s:allfolds, s:newfold)
1073 endif
1074 " open the fold so we can find any contained folds
1075 execute s:lnum."foldopen"
1076 else
Bram Moolenaar076e8b22010-08-05 21:54:00 +02001077 if !s:settings.no_progress
Bram Moolenaar349b2fb2010-07-16 20:35:36 +02001078 call s:pgb.incr()
1079 if s:pgb.needs_redraw
1080 redrawstatus
1081 let s:pgb.needs_redraw = 0
1082 endif
1083 endif
Bram Moolenaar5c736222010-01-06 20:54:52 +01001084 let s:lnum = s:lnum + 1
1085 endif
1086 endwhile
1087
1088 " sort the folds so that we only ever need to look at the first item in the
1089 " list of folds
1090 call sort(s:allfolds, "s:FoldCompare")
1091
Bram Moolenaar349b2fb2010-07-16 20:35:36 +02001092 let &l:foldtext = s:foldtext_save
Bram Moolenaar5c736222010-01-06 20:54:52 +01001093 unlet s:foldtext_save
1094
1095 " close all folds again so we can get the fold text as we go
Bram Moolenaar349b2fb2010-07-16 20:35:36 +02001096 silent! %foldclose!
Bram Moolenaar2a8a3ec2011-01-08 16:06:37 +01001097
Bram Moolenaar251e1912011-06-19 05:09:16 +02001098 " Go through and remove folds we don't need to (or cannot) process in the
1099 " current conversion range
1100 "
1101 " If a fold is removed which contains other folds, which are included, we need
1102 " to adjust the level of the included folds as used by the conversion logic
1103 " (avoiding special cases is good)
1104 "
1105 " Note any time we remove a fold, either all of the included folds are in it,
1106 " or none of them, because we only remove a fold if neither its start nor its
1107 " end are within the conversion range.
1108 let leveladjust = 0
Bram Moolenaar2a8a3ec2011-01-08 16:06:37 +01001109 for afold in s:allfolds
1110 let removed = 0
1111 if exists("g:html_start_line") && exists("g:html_end_line")
1112 if afold.firstline < g:html_start_line
Bram Moolenaar251e1912011-06-19 05:09:16 +02001113 if afold.lastline <= g:html_end_line && afold.lastline >= g:html_start_line
Bram Moolenaar2a8a3ec2011-01-08 16:06:37 +01001114 " if a fold starts before the range to convert but stops within the
1115 " range, we need to include it. Make it start on the first converted
1116 " line.
1117 let afold.firstline = g:html_start_line
1118 else
1119 " if the fold lies outside the range or the start and stop enclose
1120 " the entire range, don't bother parsing it
1121 call remove(s:allfolds, index(s:allfolds, afold))
1122 let removed = 1
Bram Moolenaar251e1912011-06-19 05:09:16 +02001123 if afold.lastline > g:html_end_line
1124 let leveladjust += 1
1125 endif
Bram Moolenaar2a8a3ec2011-01-08 16:06:37 +01001126 endif
1127 elseif afold.firstline > g:html_end_line
1128 " If the entire fold lies outside the range we need to remove it.
1129 call remove(s:allfolds, index(s:allfolds, afold))
1130 let removed = 1
1131 endif
1132 elseif exists("g:html_start_line")
1133 if afold.firstline < g:html_start_line
1134 " if there is no last line, but there is a first line, the end of the
1135 " fold will always lie within the region of interest, so keep it
1136 let afold.firstline = g:html_start_line
1137 endif
1138 elseif exists("g:html_end_line")
1139 " if there is no first line we default to the first line in the buffer so
1140 " the fold start will always be included if the fold itself is included.
1141 " If however the entire fold lies outside the range we need to remove it.
1142 if afold.firstline > g:html_end_line
1143 call remove(s:allfolds, index(s:allfolds, afold))
1144 let removed = 1
1145 endif
1146 endif
1147 if !removed
Bram Moolenaar251e1912011-06-19 05:09:16 +02001148 let afold.level -= leveladjust
Bram Moolenaar2a8a3ec2011-01-08 16:06:37 +01001149 if afold.level+1 > s:foldcolumn
1150 let s:foldcolumn = afold.level+1
1151 endif
1152 endif
1153 endfor
Bram Moolenaar251e1912011-06-19 05:09:16 +02001154
1155 " if we've removed folds containing the conversion range from processing,
1156 " getting foldtext as we go won't know to open the removed folds, so the
1157 " foldtext would be wrong; open them now.
1158 "
1159 " Note that only when a start and an end line is specified will a fold
1160 " containing the current range ever be removed.
1161 while leveladjust > 0
1162 exe g:html_start_line."foldopen"
1163 let leveladjust -= 1
1164 endwhile
Bram Moolenaar5c736222010-01-06 20:54:52 +01001165endif
1166
1167" Now loop over all lines in the original text to convert to html.
Bram Moolenaar071d4272004-06-13 20:20:40 +00001168" Use html_start_line and html_end_line if they are set.
Bram Moolenaarb02cbe32010-07-11 22:38:52 +02001169if exists("g:html_start_line")
Bram Moolenaar071d4272004-06-13 20:20:40 +00001170 let s:lnum = html_start_line
1171 if s:lnum < 1 || s:lnum > line("$")
1172 let s:lnum = 1
1173 endif
1174else
1175 let s:lnum = 1
1176endif
Bram Moolenaarb02cbe32010-07-11 22:38:52 +02001177if exists("g:html_end_line")
Bram Moolenaar071d4272004-06-13 20:20:40 +00001178 let s:end = html_end_line
1179 if s:end < s:lnum || s:end > line("$")
1180 let s:end = line("$")
1181 endif
1182else
1183 let s:end = line("$")
1184endif
1185
Bram Moolenaar5c736222010-01-06 20:54:52 +01001186" stack to keep track of all the folds containing the current line
1187let s:foldstack = []
1188
Bram Moolenaar076e8b22010-08-05 21:54:00 +02001189if !s:settings.no_progress
Bram Moolenaar349b2fb2010-07-16 20:35:36 +02001190 let s:pgb = s:ProgressBar("Processing lines:", s:end - s:lnum + 1, s:orgwin)
1191endif
1192
Bram Moolenaar076e8b22010-08-05 21:54:00 +02001193if s:settings.number_lines
Bram Moolenaar5c736222010-01-06 20:54:52 +01001194 let s:margin = strlen(s:end) + 1
1195else
1196 let s:margin = 0
1197endif
1198
Bram Moolenaar076e8b22010-08-05 21:54:00 +02001199if has('folding') && !s:settings.ignore_folding
Bram Moolenaar35a9aaa2004-10-24 19:23:07 +00001200 let s:foldfillchar = &fillchars[matchend(&fillchars, 'fold:')]
1201 if s:foldfillchar == ''
1202 let s:foldfillchar = '-'
Bram Moolenaar7b0294c2004-10-11 10:16:09 +00001203 endif
Bram Moolenaar35a9aaa2004-10-24 19:23:07 +00001204endif
1205let s:difffillchar = &fillchars[matchend(&fillchars, 'diff:')]
1206if s:difffillchar == ''
1207 let s:difffillchar = '-'
Bram Moolenaar7b0294c2004-10-11 10:16:09 +00001208endif
1209
Bram Moolenaar5c736222010-01-06 20:54:52 +01001210let s:foldId = 0
Bram Moolenaar7b0294c2004-10-11 10:16:09 +00001211
Bram Moolenaar2a8a3ec2011-01-08 16:06:37 +01001212if !s:settings.expand_tabs
1213 " If keeping tabs, add them to printable characters so we keep them when
1214 " formatting text (strtrans() doesn't replace printable chars)
1215 let s:old_isprint = &isprint
1216 setlocal isprint+=9
1217endif
1218
Bram Moolenaar071d4272004-06-13 20:20:40 +00001219while s:lnum <= s:end
1220
Bram Moolenaar47136d72004-10-12 20:02:24 +00001221 " If there are filler lines for diff mode, show these above the line.
1222 let s:filler = diff_filler(s:lnum)
1223 if s:filler > 0
1224 let s:n = s:filler
1225 while s:n > 0
Bram Moolenaar5c736222010-01-06 20:54:52 +01001226 let s:new = repeat(s:difffillchar, 3)
Bram Moolenaar47136d72004-10-12 20:02:24 +00001227
Bram Moolenaar076e8b22010-08-05 21:54:00 +02001228 if s:n > 2 && s:n < s:filler && !s:settings.whole_filler
Bram Moolenaar35a9aaa2004-10-24 19:23:07 +00001229 let s:new = s:new . " " . s:filler . " inserted lines "
1230 let s:n = 2
1231 endif
1232
Bram Moolenaar076e8b22010-08-05 21:54:00 +02001233 if !s:settings.no_pre
Bram Moolenaarc9b4b052006-04-30 18:54:39 +00001234 " HTML line wrapping is off--go ahead and fill to the margin
Bram Moolenaar6c35bea2012-07-25 17:49:10 +02001235 " TODO: what about when CSS wrapping is turned on?
Bram Moolenaar5c736222010-01-06 20:54:52 +01001236 let s:new = s:new . repeat(s:difffillchar, &columns - strlen(s:new) - s:margin)
1237 else
1238 let s:new = s:new . repeat(s:difffillchar, 3)
Bram Moolenaar35a9aaa2004-10-24 19:23:07 +00001239 endif
1240
Bram Moolenaar6c35bea2012-07-25 17:49:10 +02001241 let s:new = s:HtmlFormat_d(s:new, s:DIFF_D_ID, 0)
Bram Moolenaar076e8b22010-08-05 21:54:00 +02001242 if s:settings.number_lines
Bram Moolenaar6c35bea2012-07-25 17:49:10 +02001243 " Indent if line numbering is on. Indent gets style of line number
1244 " column.
1245 let s:new = s:HtmlFormat_n(repeat(' ', s:margin), s:LINENR_ID, 0) . s:new
1246 endif
1247 if s:settings.dynamic_folds && !s:settings.no_foldcolumn && s:foldcolumn > 0
1248 " Indent for foldcolumn if there is one. Assume it's empty, there should
1249 " not be a fold for deleted lines in diff mode.
1250 let s:new = s:FoldColumn_fill() . s:new
Bram Moolenaar5c736222010-01-06 20:54:52 +01001251 endif
Bram Moolenaar349b2fb2010-07-16 20:35:36 +02001252 call add(s:lines, s:new.s:HtmlEndline)
Bram Moolenaar35a9aaa2004-10-24 19:23:07 +00001253
Bram Moolenaar47136d72004-10-12 20:02:24 +00001254 let s:n = s:n - 1
1255 endwhile
1256 unlet s:n
1257 endif
1258 unlet s:filler
1259
1260 " Start the line with the line number.
Bram Moolenaar076e8b22010-08-05 21:54:00 +02001261 if s:settings.number_lines
Bram Moolenaar5c736222010-01-06 20:54:52 +01001262 let s:numcol = repeat(' ', s:margin - 1 - strlen(s:lnum)) . s:lnum . ' '
Bram Moolenaar47136d72004-10-12 20:02:24 +00001263 endif
1264
Bram Moolenaar5c736222010-01-06 20:54:52 +01001265 let s:new = ""
1266
Bram Moolenaar076e8b22010-08-05 21:54:00 +02001267 if has('folding') && !s:settings.ignore_folding && foldclosed(s:lnum) > -1 && !s:settings.dynamic_folds
Bram Moolenaar7b0294c2004-10-11 10:16:09 +00001268 "
Bram Moolenaar5c736222010-01-06 20:54:52 +01001269 " This is the beginning of a folded block (with no dynamic folding)
Bram Moolenaar6c35bea2012-07-25 17:49:10 +02001270 let s:new = foldtextresult(s:lnum)
Bram Moolenaar076e8b22010-08-05 21:54:00 +02001271 if !s:settings.no_pre
Bram Moolenaar35a9aaa2004-10-24 19:23:07 +00001272 " HTML line wrapping is off--go ahead and fill to the margin
1273 let s:new = s:new . repeat(s:foldfillchar, &columns - strlen(s:new))
Bram Moolenaar7b0294c2004-10-11 10:16:09 +00001274 endif
Bram Moolenaarc9b4b052006-04-30 18:54:39 +00001275
Bram Moolenaar6c35bea2012-07-25 17:49:10 +02001276 " put numcol in a separate group for sake of unselectable text
1277 let s:new = (s:settings.number_lines ? s:HtmlFormat_n(s:numcol, s:FOLDED_ID, 0): "") . s:HtmlFormat_t(s:new, s:FOLDED_ID, 0)
Bram Moolenaar071d4272004-06-13 20:20:40 +00001278
Bram Moolenaarc9b4b052006-04-30 18:54:39 +00001279 " Skip to the end of the fold
Bram Moolenaar349b2fb2010-07-16 20:35:36 +02001280 let s:new_lnum = foldclosedend(s:lnum)
1281
Bram Moolenaar076e8b22010-08-05 21:54:00 +02001282 if !s:settings.no_progress
Bram Moolenaar349b2fb2010-07-16 20:35:36 +02001283 call s:pgb.incr(s:new_lnum - s:lnum)
1284 endif
1285
1286 let s:lnum = s:new_lnum
Bram Moolenaar7b0294c2004-10-11 10:16:09 +00001287
1288 else
1289 "
Bram Moolenaar5c736222010-01-06 20:54:52 +01001290 " A line that is not folded, or doing dynamic folding.
Bram Moolenaar7b0294c2004-10-11 10:16:09 +00001291 "
Bram Moolenaar35a9aaa2004-10-24 19:23:07 +00001292 let s:line = getline(s:lnum)
Bram Moolenaar7b0294c2004-10-11 10:16:09 +00001293 let s:len = strlen(s:line)
1294
Bram Moolenaar076e8b22010-08-05 21:54:00 +02001295 if s:settings.dynamic_folds
Bram Moolenaar5c736222010-01-06 20:54:52 +01001296 " First insert a closing for any open folds that end on this line
1297 while !empty(s:foldstack) && get(s:foldstack,0).lastline == s:lnum-1
1298 let s:new = s:new."</span></span>"
1299 call remove(s:foldstack, 0)
1300 endwhile
1301
Bram Moolenaar2a8a3ec2011-01-08 16:06:37 +01001302 " Now insert an opening for any new folds that start on this line
Bram Moolenaar5c736222010-01-06 20:54:52 +01001303 let s:firstfold = 1
1304 while !empty(s:allfolds) && get(s:allfolds,0).firstline == s:lnum
1305 let s:foldId = s:foldId + 1
Bram Moolenaar349b2fb2010-07-16 20:35:36 +02001306 let s:new .= "<span id='"
1307 let s:new .= (exists('g:html_diff_win_num') ? "win".g:html_diff_win_num : "")
1308 let s:new .= "fold".s:foldId."' class='".s:allfolds[0].type."'>"
1309
Bram Moolenaar5c736222010-01-06 20:54:52 +01001310
1311 " Unless disabled, add a fold column for the opening line of a fold.
1312 "
1313 " Note that dynamic folds require using css so we just use css to take
1314 " care of the leading spaces rather than using &nbsp; in the case of
1315 " html_no_pre to make it easier
Bram Moolenaar076e8b22010-08-05 21:54:00 +02001316 if !s:settings.no_foldcolumn
Bram Moolenaar5c736222010-01-06 20:54:52 +01001317 " add fold column that can open the new fold
1318 if s:allfolds[0].level > 1 && s:firstfold
Bram Moolenaar6c35bea2012-07-25 17:49:10 +02001319 let s:new = s:new . s:FoldColumn_build('|', s:allfolds[0].level - 1, 0, "",
1320 \ 'toggle-open FoldColumn','javascript:toggleFold("fold'.s:foldstack[0].id.'");')
Bram Moolenaar5c736222010-01-06 20:54:52 +01001321 endif
Bram Moolenaar6c35bea2012-07-25 17:49:10 +02001322 " add the filler spaces separately from the '+' char so that it can be
1323 " shown/hidden separately during a hover unfold
1324 let s:new = s:new . s:FoldColumn_build("+", 1, 0, "",
1325 \ 'toggle-open FoldColumn', 'javascript:toggleFold("fold'.s:foldId.'");')
Bram Moolenaar5c736222010-01-06 20:54:52 +01001326 " If this is not the last fold we're opening on this line, we need
1327 " to keep the filler spaces hidden if the fold is opened by mouse
1328 " hover. If it is the last fold to open in the line, we shouldn't hide
1329 " them, so don't apply the toggle-filler class.
Bram Moolenaar6c35bea2012-07-25 17:49:10 +02001330 let s:new = s:new . s:FoldColumn_build(" ", 1, s:foldcolumn - s:allfolds[0].level - 1, "",
1331 \ 'toggle-open FoldColumn'. (get(s:allfolds, 1, {'firstline': 0}).firstline == s:lnum ?" toggle-filler" :""),
1332 \ 'javascript:toggleFold("fold'.s:foldId.'");')
Bram Moolenaar5c736222010-01-06 20:54:52 +01001333
1334 " add fold column that can close the new fold
Bram Moolenaar6c35bea2012-07-25 17:49:10 +02001335 " only add extra blank space if we aren't opening another fold on the
1336 " same line
Bram Moolenaar5c736222010-01-06 20:54:52 +01001337 if get(s:allfolds, 1, {'firstline': 0}).firstline != s:lnum
Bram Moolenaar6c35bea2012-07-25 17:49:10 +02001338 let s:extra_space = s:foldcolumn - s:allfolds[0].level
1339 else
1340 let s:extra_space = 0
Bram Moolenaar5c736222010-01-06 20:54:52 +01001341 endif
Bram Moolenaar6c35bea2012-07-25 17:49:10 +02001342 if s:firstfold
1343 " the first fold in a line has '|' characters from folds opened in
1344 " previous lines, before the '-' for this fold
1345 let s:new .= s:FoldColumn_build('|', s:allfolds[0].level - 1, s:extra_space, '-',
1346 \ 'toggle-closed FoldColumn', 'javascript:toggleFold("fold'.s:foldId.'");')
1347 else
1348 " any subsequent folds in the line only add a single '-'
1349 let s:new = s:new . s:FoldColumn_build("-", 1, s:extra_space, "",
1350 \ 'toggle-closed FoldColumn', 'javascript:toggleFold("fold'.s:foldId.'");')
1351 endif
Bram Moolenaar5c736222010-01-06 20:54:52 +01001352 let s:firstfold = 0
1353 endif
1354
Bram Moolenaar6c35bea2012-07-25 17:49:10 +02001355 " Add fold text, moving the span ending to the next line so collapsing
1356 " of folds works correctly.
1357 " Put numcol in a separate group for sake of unselectable text.
1358 let s:new = s:new . (s:settings.number_lines ? s:HtmlFormat_n(s:numcol, s:FOLDED_ID, 0) : "") . substitute(s:HtmlFormat_t(foldtextresult(s:lnum), s:FOLDED_ID, 0), '</span>', s:HtmlEndline.'\n\0', '')
Bram Moolenaar5c736222010-01-06 20:54:52 +01001359 let s:new = s:new . "<span class='fulltext'>"
1360
1361 " open the fold now that we have the fold text to allow retrieval of
1362 " fold text for subsequent folds
1363 execute s:lnum."foldopen"
1364 call insert(s:foldstack, remove(s:allfolds,0))
1365 let s:foldstack[0].id = s:foldId
1366 endwhile
1367
1368 " Unless disabled, add a fold column for other lines.
1369 "
1370 " Note that dynamic folds require using css so we just use css to take
1371 " care of the leading spaces rather than using &nbsp; in the case of
1372 " html_no_pre to make it easier
Bram Moolenaar076e8b22010-08-05 21:54:00 +02001373 if !s:settings.no_foldcolumn
Bram Moolenaar5c736222010-01-06 20:54:52 +01001374 if empty(s:foldstack)
Bram Moolenaar7510fe72010-07-25 12:46:44 +02001375 " add the empty foldcolumn for unfolded lines if there is a fold
1376 " column at all
1377 if s:foldcolumn > 0
Bram Moolenaar6c35bea2012-07-25 17:49:10 +02001378 let s:new = s:new . s:FoldColumn_fill()
Bram Moolenaar7510fe72010-07-25 12:46:44 +02001379 endif
Bram Moolenaar5c736222010-01-06 20:54:52 +01001380 else
1381 " add the fold column for folds not on the opening line
1382 if get(s:foldstack, 0).firstline < s:lnum
Bram Moolenaar6c35bea2012-07-25 17:49:10 +02001383 let s:new = s:new . s:FoldColumn_build('|', s:foldstack[0].level, s:foldcolumn - s:foldstack[0].level, "",
1384 \ 'FoldColumn', 'javascript:toggleFold("fold'.s:foldstack[0].id.'");')
Bram Moolenaar5c736222010-01-06 20:54:52 +01001385 endif
1386 endif
1387 endif
1388 endif
1389
1390 " Now continue with the unfolded line text
Bram Moolenaar076e8b22010-08-05 21:54:00 +02001391 if s:settings.number_lines
Bram Moolenaar6c35bea2012-07-25 17:49:10 +02001392 let s:new = s:new . s:HtmlFormat_n(s:numcol, s:LINENR_ID, 0)
Bram Moolenaar071d4272004-06-13 20:20:40 +00001393 endif
Bram Moolenaar7b0294c2004-10-11 10:16:09 +00001394
Bram Moolenaar47136d72004-10-12 20:02:24 +00001395 " Get the diff attribute, if any.
1396 let s:diffattr = diff_hlID(s:lnum, 1)
1397
Bram Moolenaar7510fe72010-07-25 12:46:44 +02001398 " initialize conceal info to act like not concealed, just in case
1399 let s:concealinfo = [0, '']
1400
Bram Moolenaar7b0294c2004-10-11 10:16:09 +00001401 " Loop over each character in the line
1402 let s:col = 1
Bram Moolenaar8ada2cc2010-07-29 20:43:36 +02001403
1404 " most of the time we won't use the diff_id, initialize to zero
1405 let s:diff_id = 0
Bram Moolenaar8ada2cc2010-07-29 20:43:36 +02001406
Bram Moolenaar35a9aaa2004-10-24 19:23:07 +00001407 while s:col <= s:len || (s:col == 1 && s:diffattr)
Bram Moolenaar7b0294c2004-10-11 10:16:09 +00001408 let s:startcol = s:col " The start column for processing text
Bram Moolenaar076e8b22010-08-05 21:54:00 +02001409 if !s:settings.ignore_conceal && has('conceal')
Bram Moolenaar7510fe72010-07-25 12:46:44 +02001410 let s:concealinfo = synconcealed(s:lnum, s:col)
1411 endif
Bram Moolenaar076e8b22010-08-05 21:54:00 +02001412 if !s:settings.ignore_conceal && s:concealinfo[0]
Bram Moolenaar7510fe72010-07-25 12:46:44 +02001413 let s:col = s:col + 1
1414 " Speed loop (it's small - that's the trick)
1415 " Go along till we find a change in the match sequence number (ending
1416 " the specific concealed region) or until there are no more concealed
1417 " characters.
1418 while s:col <= s:len && s:concealinfo == synconcealed(s:lnum, s:col) | let s:col = s:col + 1 | endwhile
1419 elseif s:diffattr
Bram Moolenaar8ada2cc2010-07-29 20:43:36 +02001420 let s:diff_id = diff_hlID(s:lnum, s:col)
1421 let s:id = synID(s:lnum, s:col, 1)
Bram Moolenaar47136d72004-10-12 20:02:24 +00001422 let s:col = s:col + 1
1423 " Speed loop (it's small - that's the trick)
1424 " Go along till we find a change in hlID
Bram Moolenaar8ada2cc2010-07-29 20:43:36 +02001425 while s:col <= s:len && s:id == synID(s:lnum, s:col, 1)
1426 \ && s:diff_id == diff_hlID(s:lnum, s:col) |
1427 \ let s:col = s:col + 1 |
1428 \ endwhile
Bram Moolenaar076e8b22010-08-05 21:54:00 +02001429 if s:len < &columns && !s:settings.no_pre
Bram Moolenaar8ada2cc2010-07-29 20:43:36 +02001430 " Add spaces at the end of the raw text line to extend the changed
1431 " line to the full width.
Bram Moolenaar5c736222010-01-06 20:54:52 +01001432 let s:line = s:line . repeat(' ', &columns - virtcol([s:lnum, s:len]) - s:margin)
Bram Moolenaarc9b4b052006-04-30 18:54:39 +00001433 let s:len = &columns
1434 endif
Bram Moolenaar47136d72004-10-12 20:02:24 +00001435 else
1436 let s:id = synID(s:lnum, s:col, 1)
1437 let s:col = s:col + 1
1438 " Speed loop (it's small - that's the trick)
1439 " Go along till we find a change in synID
1440 while s:col <= s:len && s:id == synID(s:lnum, s:col, 1) | let s:col = s:col + 1 | endwhile
1441 endif
Bram Moolenaar7b0294c2004-10-11 10:16:09 +00001442
Bram Moolenaar076e8b22010-08-05 21:54:00 +02001443 if s:settings.ignore_conceal || !s:concealinfo[0]
Bram Moolenaar2a8a3ec2011-01-08 16:06:37 +01001444 " Expand tabs if needed
Bram Moolenaar7510fe72010-07-25 12:46:44 +02001445 let s:expandedtab = strpart(s:line, s:startcol - 1, s:col - s:startcol)
Bram Moolenaar2a8a3ec2011-01-08 16:06:37 +01001446 if s:settings.expand_tabs
1447 let s:offset = 0
Bram Moolenaar7510fe72010-07-25 12:46:44 +02001448 let s:idx = stridx(s:expandedtab, "\t")
Bram Moolenaar2a8a3ec2011-01-08 16:06:37 +01001449 while s:idx >= 0
1450 if has("multi_byte_encoding")
1451 if s:startcol + s:idx == 1
1452 let s:i = &ts
1453 else
1454 if s:idx == 0
1455 let s:prevc = matchstr(s:line, '.\%' . (s:startcol + s:idx + s:offset) . 'c')
1456 else
1457 let s:prevc = matchstr(s:expandedtab, '.\%' . (s:idx + 1) . 'c')
1458 endif
1459 let s:vcol = virtcol([s:lnum, s:startcol + s:idx + s:offset - len(s:prevc)])
1460 let s:i = &ts - (s:vcol % &ts)
1461 endif
1462 let s:offset -= s:i - 1
1463 else
1464 let s:i = &ts - ((s:idx + s:startcol - 1) % &ts)
1465 endif
1466 let s:expandedtab = substitute(s:expandedtab, '\t', repeat(' ', s:i), '')
1467 let s:idx = stridx(s:expandedtab, "\t")
1468 endwhile
1469 end
Bram Moolenaar35a9aaa2004-10-24 19:23:07 +00001470
Bram Moolenaar7510fe72010-07-25 12:46:44 +02001471 " get the highlight group name to use
1472 let s:id = synIDtrans(s:id)
Bram Moolenaar7510fe72010-07-25 12:46:44 +02001473 else
1474 " use Conceal highlighting for concealed text
Bram Moolenaar6c35bea2012-07-25 17:49:10 +02001475 let s:id = s:CONCEAL_ID
Bram Moolenaar7510fe72010-07-25 12:46:44 +02001476 let s:expandedtab = s:concealinfo[1]
1477 endif
1478
Bram Moolenaar6c35bea2012-07-25 17:49:10 +02001479 " Output the text with the same synID, with class set to the highlight ID
1480 " name, unless it has been concealed completely.
Bram Moolenaar7510fe72010-07-25 12:46:44 +02001481 if strlen(s:expandedtab) > 0
Bram Moolenaar6c35bea2012-07-25 17:49:10 +02001482 let s:new = s:new . s:HtmlFormat(s:expandedtab, s:id, s:diff_id, 0)
Bram Moolenaar7510fe72010-07-25 12:46:44 +02001483 endif
Bram Moolenaar7b0294c2004-10-11 10:16:09 +00001484 endwhile
1485 endif
Bram Moolenaar071d4272004-06-13 20:20:40 +00001486
Bram Moolenaar7510fe72010-07-25 12:46:44 +02001487 call extend(s:lines, split(s:new.s:HtmlEndline, '\n', 1))
Bram Moolenaar076e8b22010-08-05 21:54:00 +02001488 if !s:settings.no_progress && s:pgb.needs_redraw
Bram Moolenaar349b2fb2010-07-16 20:35:36 +02001489 redrawstatus
1490 let s:pgb.needs_redraw = 0
1491 endif
Bram Moolenaar071d4272004-06-13 20:20:40 +00001492 let s:lnum = s:lnum + 1
Bram Moolenaar313b7232007-05-05 17:56:55 +00001493
Bram Moolenaar076e8b22010-08-05 21:54:00 +02001494 if !s:settings.no_progress
Bram Moolenaar349b2fb2010-07-16 20:35:36 +02001495 call s:pgb.incr()
1496 endif
1497endwhile
1498
Bram Moolenaar076e8b22010-08-05 21:54:00 +02001499if s:settings.dynamic_folds
Bram Moolenaar5c736222010-01-06 20:54:52 +01001500 " finish off any open folds
1501 while !empty(s:foldstack)
Bram Moolenaar349b2fb2010-07-16 20:35:36 +02001502 let s:lines[-1].="</span></span>"
Bram Moolenaar5c736222010-01-06 20:54:52 +01001503 call remove(s:foldstack, 0)
1504 endwhile
1505
1506 " add fold column to the style list if not already there
Bram Moolenaar6c35bea2012-07-25 17:49:10 +02001507 let s:id = s:FOLD_C_ID
1508 if !has_key(s:stylelist, s:id)
1509 let s:stylelist[s:id] = '.FoldColumn { ' . s:CSS1(s:id) . '}'
Bram Moolenaar5c736222010-01-06 20:54:52 +01001510 endif
1511endif
1512
Bram Moolenaar076e8b22010-08-05 21:54:00 +02001513if s:settings.no_pre
1514 if !s:settings.use_css
Bram Moolenaar8ada2cc2010-07-29 20:43:36 +02001515 " Close off the font tag that encapsulates the whole <body>
Bram Moolenaarbebca9d2010-08-07 15:47:30 +02001516 call extend(s:lines, ["</font>", "</body>", "</html>"])
Bram Moolenaar8ada2cc2010-07-29 20:43:36 +02001517 else
Bram Moolenaar6c35bea2012-07-25 17:49:10 +02001518 call extend(s:lines, ["</div>", "</body>", "</html>"])
Bram Moolenaar8ada2cc2010-07-29 20:43:36 +02001519 endif
Bram Moolenaar071d4272004-06-13 20:20:40 +00001520else
Bram Moolenaar349b2fb2010-07-16 20:35:36 +02001521 call extend(s:lines, ["</pre>", "</body>", "</html>"])
Bram Moolenaar071d4272004-06-13 20:20:40 +00001522endif
1523
Bram Moolenaar349b2fb2010-07-16 20:35:36 +02001524exe s:newwin . "wincmd w"
1525call setline(1, s:lines)
1526unlet s:lines
Bram Moolenaar071d4272004-06-13 20:20:40 +00001527
Bram Moolenaar6c35bea2012-07-25 17:49:10 +02001528" Mangle modelines so Vim doesn't try to use HTML text as a modeline if editing
1529" this file in the future; need to do this after generating all the text in case
1530" the modeline text has different highlight groups which all turn out to be
1531" stripped from the final output.
1532%s!\v(%(^|\s+)%(vim?|ex)):!\1\&#0058;!ge
1533
Bram Moolenaar071d4272004-06-13 20:20:40 +00001534" Now, when we finally know which, we define the colors and styles
Bram Moolenaar076e8b22010-08-05 21:54:00 +02001535if s:settings.use_css
Bram Moolenaar071d4272004-06-13 20:20:40 +00001536 1;/<style type="text/+1
1537endif
1538
Bram Moolenaar071d4272004-06-13 20:20:40 +00001539" Normal/global attributes
1540" For Netscape 4, set <body> attributes too, though, strictly speaking, it's
1541" incorrect.
Bram Moolenaar076e8b22010-08-05 21:54:00 +02001542if s:settings.use_css
1543 if s:settings.no_pre
Bram Moolenaar6c35bea2012-07-25 17:49:10 +02001544 call append('.', "body { color: " . s:fgc . "; background-color: " . s:bgc . "; font-family: ". s:htmlfont ."; }")
1545 +
Bram Moolenaar071d4272004-06-13 20:20:40 +00001546 else
Bram Moolenaar6c35bea2012-07-25 17:49:10 +02001547 call append('.', "pre { " . s:whitespace . "font-family: ". s:htmlfont ."; color: " . s:fgc . "; background-color: " . s:bgc . "; }")
1548 +
Bram Moolenaar071d4272004-06-13 20:20:40 +00001549 yank
1550 put
1551 execute "normal! ^cwbody\e"
Bram Moolenaar8e5af3e2011-04-28 19:02:44 +02001552 " body should not have the wrap formatting, only the pre section
1553 if s:whitespace != ''
1554 exec 's#'.s:whitespace
1555 endif
Bram Moolenaar071d4272004-06-13 20:20:40 +00001556 endif
Bram Moolenaar6c35bea2012-07-25 17:49:10 +02001557 " fix browser inconsistencies (sometimes within the same browser) of different
1558 " default font size for different elements
1559 call append('.', '* { font-size: 1em; }')
1560 +
1561 " if we use any input elements for unselectable content, make sure they look
1562 " like normal text
1563 if !empty(s:settings.prevent_copy)
1564 call append('.', 'input { border: none; margin: 0; padding: 0; font-family: '.s:htmlfont.'; }')
1565 +
1566 " ch units for browsers which support them, em units for a somewhat
1567 " reasonable fallback. Also make sure the special elements for size
1568 " calculations aren't seen.
1569 call append('.', [
1570 \ "input[size='1'] { width: 1em; width: 1ch; }",
1571 \ "input[size='2'] { width: 2em; width: 2ch; }",
1572 \ "input[size='3'] { width: 3em; width: 3ch; }",
1573 \ "input[size='4'] { width: 4em; width: 4ch; }",
1574 \ "input[size='5'] { width: 5em; width: 5ch; }",
1575 \ "input[size='6'] { width: 6em; width: 6ch; }",
1576 \ "input[size='7'] { width: 7em; width: 7ch; }",
1577 \ "input[size='8'] { width: 8em; width: 8ch; }",
1578 \ "input[size='9'] { width: 9em; width: 9ch; }",
1579 \ "input[size='10'] { width: 10em; width: 10ch; }",
1580 \ "input[size='11'] { width: 11em; width: 11ch; }",
1581 \ "input[size='12'] { width: 12em; width: 12ch; }",
1582 \ "input[size='13'] { width: 13em; width: 13ch; }",
1583 \ "input[size='14'] { width: 14em; width: 14ch; }",
1584 \ "input[size='15'] { width: 15em; width: 15ch; }",
1585 \ "input[size='16'] { width: 16em; width: 16ch; }",
1586 \ "input[size='17'] { width: 17em; width: 17ch; }",
1587 \ "input[size='18'] { width: 18em; width: 18ch; }",
1588 \ "input[size='19'] { width: 19em; width: 19ch; }",
1589 \ "input[size='20'] { width: 20em; width: 20ch; }",
1590 \ "#oneCharWidth, #oneEmWidth, #oneInputWidth { padding: 0; margin: 0; position: absolute; left: -999999px; visibility: hidden; }"
1591 \ ])
1592 +21
1593 for w in range(5, 100, 5)
1594 let base = 0.01 * w
1595 call append('.', join(map(range(1,20), "'.em'.w.' input[size='''.v:val.'''] { width: '.string(v:val*base).'em; }'")))
1596 +
1597 endfor
1598 if s:settings.prevent_copy =~# 'f'
1599 " Make the cursor show active fold columns as active areas, and empty fold
1600 " columns as not interactive.
1601 call append('.', ['input.FoldColumn { cursor: pointer; }',
1602 \ 'input.FoldColumn[value=""] { cursor: default; }'
1603 \ ])
1604 +2
1605 endif
1606 " make line number column show as non-interactive if not selectable
1607 if s:settings.prevent_copy =~# 'n'
1608 call append('.', 'input.LineNr { cursor: default; }')
1609 +
1610 endif
1611 " make fold text and line number column within fold text show as
1612 " non-interactive if not selectable
1613 if (s:settings.prevent_copy =~# 'n' || s:settings.prevent_copy =~# 't') && !s:settings.ignore_folding
1614 call append('.', 'input.Folded { cursor: default; }')
1615 +
1616 endif
1617 endif
Bram Moolenaar071d4272004-06-13 20:20:40 +00001618else
Bram Moolenaarbebca9d2010-08-07 15:47:30 +02001619 execute '%s:<body>:<body bgcolor="' . s:bgc . '" text="' . s:fgc . '">\r<font face="'. s:htmlfont .'">'
Bram Moolenaar071d4272004-06-13 20:20:40 +00001620endif
1621
Bram Moolenaar6c35bea2012-07-25 17:49:10 +02001622" Gather attributes for all other classes. Do diff first so that normal
1623" highlight groups are inserted before it.
1624if s:settings.use_css
1625 if s:diff_mode
1626 call append('.', filter(map(keys(s:diffstylelist), "s:diffstylelist[v:val]"), 'v:val != ""'))
1627 endif
1628 if !empty(s:stylelist)
1629 call append('.', filter(map(keys(s:stylelist), "s:stylelist[v:val]"), 'v:val != ""'))
Bram Moolenaar071d4272004-06-13 20:20:40 +00001630 endif
1631endif
1632
Bram Moolenaar071d4272004-06-13 20:20:40 +00001633" Add hyperlinks
Bram Moolenaar6c35bea2012-07-25 17:49:10 +02001634" TODO: add option to not do this? Maybe just make the color the same as the
1635" text highlight group normally is?
Bram Moolenaar1cd871b2004-12-19 22:46:22 +00001636%s+\(https\=://\S\{-}\)\(\([.,;:}]\=\(\s\|$\)\)\|[\\"'<>]\|&gt;\|&lt;\|&quot;\)+<a href="\1">\1</a>\2+ge
Bram Moolenaar071d4272004-06-13 20:20:40 +00001637
1638" The DTD
Bram Moolenaar076e8b22010-08-05 21:54:00 +02001639if s:settings.use_xhtml
1640 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\">"
1641elseif s:settings.use_css && !s:settings.no_pre
1642 exe "normal! gg0i<!DOCTYPE HTML PUBLIC \"-//W3C//DTD HTML 4.01//EN\" \"http://www.w3.org/TR/html4/strict.dtd\">\n"
Bram Moolenaar313b7232007-05-05 17:56:55 +00001643else
Bram Moolenaar076e8b22010-08-05 21:54:00 +02001644 exe "normal! gg0i<!DOCTYPE HTML PUBLIC \"-//W3C//DTD HTML 4.01 Transitional//EN\" \"http://www.w3.org/TR/html4/loose.dtd\">\n"
Bram Moolenaar1cd871b2004-12-19 22:46:22 +00001645endif
1646
Bram Moolenaar076e8b22010-08-05 21:54:00 +02001647if s:settings.use_xhtml
Bram Moolenaar1cd871b2004-12-19 22:46:22 +00001648 exe "normal! gg/<html/e\na xmlns=\"http://www.w3.org/1999/xhtml\"\e"
Bram Moolenaar071d4272004-06-13 20:20:40 +00001649endif
1650
1651" Cleanup
1652%s:\s\+$::e
1653
Bram Moolenaar2a8a3ec2011-01-08 16:06:37 +01001654" Restore old settings (new window first)
Bram Moolenaar8df7f882010-08-13 11:30:02 +02001655let &l:foldenable = s:old_fen
Bram Moolenaar349b2fb2010-07-16 20:35:36 +02001656let &l:foldmethod = s:old_fdm
Bram Moolenaar071d4272004-06-13 20:20:40 +00001657let &report = s:old_report
1658let &title = s:old_title
1659let &icon = s:old_icon
1660let &paste = s:old_paste
1661let &magic = s:old_magic
1662let @/ = s:old_search
Bram Moolenaar349b2fb2010-07-16 20:35:36 +02001663let &more = s:old_more
Bram Moolenaar2a8a3ec2011-01-08 16:06:37 +01001664
1665" switch to original window to restore those settings
Bram Moolenaar071d4272004-06-13 20:20:40 +00001666exe s:orgwin . "wincmd w"
Bram Moolenaar2a8a3ec2011-01-08 16:06:37 +01001667
1668if !s:settings.expand_tabs
1669 let &l:isprint = s:old_isprint
1670endif
Bram Moolenaar166af9b2010-11-16 20:34:40 +01001671let &l:stl = s:origwin_stl
Bram Moolenaar071d4272004-06-13 20:20:40 +00001672let &l:et = s:old_et
Bram Moolenaar8df7f882010-08-13 11:30:02 +02001673let &l:scrollbind = s:old_bind
Bram Moolenaar2a8a3ec2011-01-08 16:06:37 +01001674
1675" and back to the new window again to end there
Bram Moolenaar071d4272004-06-13 20:20:40 +00001676exe s:newwin . "wincmd w"
Bram Moolenaar2a8a3ec2011-01-08 16:06:37 +01001677
Bram Moolenaar166af9b2010-11-16 20:34:40 +01001678let &l:stl = s:newwin_stl
Bram Moolenaar349b2fb2010-07-16 20:35:36 +02001679exec 'resize' s:old_winheight
1680let &l:winfixheight = s:old_winfixheight
Bram Moolenaar071d4272004-06-13 20:20:40 +00001681
Bram Moolenaar349b2fb2010-07-16 20:35:36 +02001682let &ls=s:ls
1683
Bram Moolenaar071d4272004-06-13 20:20:40 +00001684" Save a little bit of memory (worth doing?)
Bram Moolenaar8e5af3e2011-04-28 19:02:44 +02001685unlet s:htmlfont s:whitespace
Bram Moolenaar8df7f882010-08-13 11:30:02 +02001686unlet s:old_et s:old_paste s:old_icon s:old_report s:old_title s:old_search
1687unlet s:old_magic s:old_more s:old_fdm s:old_fen s:old_winheight
Bram Moolenaar2a8a3ec2011-01-08 16:06:37 +01001688unlet! s:old_isprint
Bram Moolenaar6c35bea2012-07-25 17:49:10 +02001689unlet s:whatterm s:stylelist s:diffstylelist s:lnum s:end s:margin s:fgc s:bgc s:old_winfixheight
1690unlet! s:col s:id s:attr s:len s:line s:new s:expandedtab s:concealinfo s:diff_mode
Bram Moolenaar8df7f882010-08-13 11:30:02 +02001691unlet! s:orgwin s:newwin s:orgbufnr s:idx s:i s:offset s:ls s:origwin_stl
1692unlet! s:newwin_stl s:current_syntax
Bram Moolenaar05159a02005-02-26 23:04:13 +00001693if !v:profiling
1694 delfunc s:HtmlColor
1695 delfunc s:HtmlFormat
1696 delfunc s:CSS1
Bram Moolenaar6c35bea2012-07-25 17:49:10 +02001697 delfunc s:BuildStyleWrapper
Bram Moolenaar076e8b22010-08-05 21:54:00 +02001698 if !s:settings.use_css
Bram Moolenaar05159a02005-02-26 23:04:13 +00001699 delfunc s:HtmlOpening
1700 delfunc s:HtmlClosing
1701 endif
Bram Moolenaar076e8b22010-08-05 21:54:00 +02001702 if s:settings.dynamic_folds
Bram Moolenaar349b2fb2010-07-16 20:35:36 +02001703 delfunc s:FoldCompare
1704 endif
1705
Bram Moolenaar076e8b22010-08-05 21:54:00 +02001706 if !s:settings.no_progress
Bram Moolenaar349b2fb2010-07-16 20:35:36 +02001707 delfunc s:ProgressBar
1708 delfunc s:progressbar.paint
1709 delfunc s:progressbar.incr
1710 unlet s:pgb s:progressbar
1711 endif
Bram Moolenaar071d4272004-06-13 20:20:40 +00001712endif
Bram Moolenaar349b2fb2010-07-16 20:35:36 +02001713
Bram Moolenaar8df7f882010-08-13 11:30:02 +02001714unlet! s:new_lnum s:diffattr s:difffillchar s:foldfillchar s:HtmlSpace
Bram Moolenaar6c35bea2012-07-25 17:49:10 +02001715unlet! s:LeadingSpace s:HtmlEndline s:firstfold s:numcol s:foldcolumn
1716unlet s:foldstack s:allfolds s:foldId s:settings
Bram Moolenaar5c736222010-01-06 20:54:52 +01001717
1718let &cpo = s:cpo_sav
Bram Moolenaar349b2fb2010-07-16 20:35:36 +02001719unlet! s:cpo_sav
Bram Moolenaar5c736222010-01-06 20:54:52 +01001720
Bram Moolenaar349b2fb2010-07-16 20:35:36 +02001721" Make sure any patches will probably use consistent indent
Bram Moolenaar7c86f4c2010-07-18 14:07:22 +02001722" vim: ts=8 sw=2 sts=2 noet