xref: /vim-8.2.3635/runtime/autoload/tohtml.vim (revision 2a8a3ecb)
1" Vim autoload file for the tohtml plugin.
2" Maintainer: Ben Fritz <[email protected]>
3" Last Change: 2011 Jan 05
4"
5" Additional contributors:
6"
7"	      Original by Bram Moolenaar <[email protected]>
8"	      Diff2HTML() added by Christian Brabandt <[email protected]>
9"
10"	      See Mercurial change logs for more!
11
12" this file uses line continuations
13let s:cpo_sav = &cpo
14set cpo-=C
15
16" Automatically find charsets from all encodings supported natively by Vim. With
17" the 8bit- and 2byte- prefixes, Vim can actually support more encodings than
18" this. Let the user specify these however since they won't be supported on
19" every system. TODO: how? g:html_charsets and g:html_encodings?
20"
21" Note, not all of Vim's supported encodings have a charset to use.
22"
23" Names in this list are from:
24"   http://www.iana.org/assignments/character-sets
25" g:tohtml#encoding_to_charset: {{{
26let g:tohtml#encoding_to_charset = {
27      \ 'latin1' : 'ISO-8859-1',
28      \ 'iso-8859-2' : 'ISO-8859-2',
29      \ 'iso-8859-3' : 'ISO-8859-3',
30      \ 'iso-8859-4' : 'ISO-8859-4',
31      \ 'iso-8859-5' : 'ISO-8859-5',
32      \ 'iso-8859-6' : 'ISO-8859-6',
33      \ 'iso-8859-7' : 'ISO-8859-7',
34      \ 'iso-8859-8' : 'ISO-8859-8',
35      \ 'iso-8859-9' : 'ISO-8859-9',
36      \ 'iso-8859-10' : '',
37      \ 'iso-8859-13' : 'ISO-8859-13',
38      \ 'iso-8859-14' : '',
39      \ 'iso-8859-15' : 'ISO-8859-15',
40      \ 'koi8-r' : 'KOI8-R',
41      \ 'koi8-u' : 'KOI8-U',
42      \ 'macroman' : 'macintosh',
43      \ 'cp437' : '',
44      \ 'cp775' : '',
45      \ 'cp850' : '',
46      \ 'cp852' : '',
47      \ 'cp855' : '',
48      \ 'cp857' : '',
49      \ 'cp860' : '',
50      \ 'cp861' : '',
51      \ 'cp862' : '',
52      \ 'cp863' : '',
53      \ 'cp865' : '',
54      \ 'cp866' : 'IBM866',
55      \ 'cp869' : '',
56      \ 'cp874' : '',
57      \ 'cp1250' : 'windows-1250',
58      \ 'cp1251' : 'windows-1251',
59      \ 'cp1253' : 'windows-1253',
60      \ 'cp1254' : 'windows-1254',
61      \ 'cp1255' : 'windows-1255',
62      \ 'cp1256' : 'windows-1256',
63      \ 'cp1257' : 'windows-1257',
64      \ 'cp1258' : 'windows-1258',
65      \ 'euc-jp' : 'EUC-JP',
66      \ 'sjis' : 'Shift_JIS',
67      \ 'cp932' : 'Shift_JIS',
68      \ 'cp949' : '',
69      \ 'euc-kr' : 'EUC-KR',
70      \ 'cp936' : 'GBK',
71      \ 'euc-cn' : 'GB2312',
72      \ 'big5' : 'Big5',
73      \ 'cp950' : 'Big5',
74      \ 'utf-8' : 'UTF-8',
75      \ 'ucs-2' : 'UTF-8',
76      \ 'ucs-2le' : 'UTF-8',
77      \ 'utf-16' : 'UTF-8',
78      \ 'utf-16le' : 'UTF-8',
79      \ 'ucs-4' : 'UTF-8',
80      \ 'ucs-4le' : 'UTF-8',
81      \ }
82lockvar g:tohtml#encoding_to_charset
83" Notes:
84"   1. All UCS/UTF are converted to UTF-8 because it is much better supported
85"   2. Any blank spaces are there because Vim supports it but at least one major
86"      web browser does not according to http://wiki.whatwg.org/wiki/Web_Encodings.
87" }}}
88
89" Only automatically find encodings supported natively by Vim, let the user
90" specify the encoding if it's not natively supported. This function is only
91" used when the user specifies the charset, they better know what they are
92" doing!
93"
94" Names in this list are from:
95"   http://www.iana.org/assignments/character-sets
96" g:tohtml#charset_to_encoding: {{{
97let g:tohtml#charset_to_encoding = {
98      \ 'iso_8859-1:1987' : 'latin1',
99      \ 'iso-ir-100' : 'latin1',
100      \ 'iso_8859-1' : 'latin1',
101      \ 'iso-8859-1' : 'latin1',
102      \ 'latin1' : 'latin1',
103      \ 'l1' : 'latin1',
104      \ 'ibm819' : 'latin1',
105      \ 'cp819' : 'latin1',
106      \ 'csisolatin1' : 'latin1',
107      \ 'iso_8859-2:1987' : 'iso-8859-2',
108      \ 'iso-ir-101' : 'iso-8859-2',
109      \ 'iso_8859-2' : 'iso-8859-2',
110      \ 'iso-8859-2' : 'iso-8859-2',
111      \ 'latin2' : 'iso-8859-2',
112      \ 'l2' : 'iso-8859-2',
113      \ 'csisolatin2' : 'iso-8859-2',
114      \ 'iso_8859-3:1988' : 'iso-8859-3',
115      \ 'iso-ir-109' : 'iso-8859-3',
116      \ 'iso_8859-3' : 'iso-8859-3',
117      \ 'iso-8859-3' : 'iso-8859-3',
118      \ 'latin3' : 'iso-8859-3',
119      \ 'l3' : 'iso-8859-3',
120      \ 'csisolatin3' : 'iso-8859-3',
121      \ 'iso_8859-4:1988' : 'iso-8859-4',
122      \ 'iso-ir-110' : 'iso-8859-4',
123      \ 'iso_8859-4' : 'iso-8859-4',
124      \ 'iso-8859-4' : 'iso-8859-4',
125      \ 'latin4' : 'iso-8859-4',
126      \ 'l4' : 'iso-8859-4',
127      \ 'csisolatin4' : 'iso-8859-4',
128      \ 'iso_8859-5:1988' : 'iso-8859-5',
129      \ 'iso-ir-144' : 'iso-8859-5',
130      \ 'iso_8859-5' : 'iso-8859-5',
131      \ 'iso-8859-5' : 'iso-8859-5',
132      \ 'cyrillic' : 'iso-8859-5',
133      \ 'csisolatincyrillic' : 'iso-8859-5',
134      \ 'iso_8859-6:1987' : 'iso-8859-6',
135      \ 'iso-ir-127' : 'iso-8859-6',
136      \ 'iso_8859-6' : 'iso-8859-6',
137      \ 'iso-8859-6' : 'iso-8859-6',
138      \ 'ecma-114' : 'iso-8859-6',
139      \ 'asmo-708' : 'iso-8859-6',
140      \ 'arabic' : 'iso-8859-6',
141      \ 'csisolatinarabic' : 'iso-8859-6',
142      \ 'iso_8859-7:1987' : 'iso-8859-7',
143      \ 'iso-ir-126' : 'iso-8859-7',
144      \ 'iso_8859-7' : 'iso-8859-7',
145      \ 'iso-8859-7' : 'iso-8859-7',
146      \ 'elot_928' : 'iso-8859-7',
147      \ 'ecma-118' : 'iso-8859-7',
148      \ 'greek' : 'iso-8859-7',
149      \ 'greek8' : 'iso-8859-7',
150      \ 'csisolatingreek' : 'iso-8859-7',
151      \ 'iso_8859-8:1988' : 'iso-8859-8',
152      \ 'iso-ir-138' : 'iso-8859-8',
153      \ 'iso_8859-8' : 'iso-8859-8',
154      \ 'iso-8859-8' : 'iso-8859-8',
155      \ 'hebrew' : 'iso-8859-8',
156      \ 'csisolatinhebrew' : 'iso-8859-8',
157      \ 'iso_8859-9:1989' : 'iso-8859-9',
158      \ 'iso-ir-148' : 'iso-8859-9',
159      \ 'iso_8859-9' : 'iso-8859-9',
160      \ 'iso-8859-9' : 'iso-8859-9',
161      \ 'latin5' : 'iso-8859-9',
162      \ 'l5' : 'iso-8859-9',
163      \ 'csisolatin5' : 'iso-8859-9',
164      \ 'iso-8859-10' : 'iso-8859-10',
165      \ 'iso-ir-157' : 'iso-8859-10',
166      \ 'l6' : 'iso-8859-10',
167      \ 'iso_8859-10:1992' : 'iso-8859-10',
168      \ 'csisolatin6' : 'iso-8859-10',
169      \ 'latin6' : 'iso-8859-10',
170      \ 'iso-8859-13' : 'iso-8859-13',
171      \ 'iso-8859-14' : 'iso-8859-14',
172      \ 'iso-ir-199' : 'iso-8859-14',
173      \ 'iso_8859-14:1998' : 'iso-8859-14',
174      \ 'iso_8859-14' : 'iso-8859-14',
175      \ 'latin8' : 'iso-8859-14',
176      \ 'iso-celtic' : 'iso-8859-14',
177      \ 'l8' : 'iso-8859-14',
178      \ 'iso-8859-15' : 'iso-8859-15',
179      \ 'iso_8859-15' : 'iso-8859-15',
180      \ 'latin-9' : 'iso-8859-15',
181      \ 'koi8-r' : 'koi8-r',
182      \ 'cskoi8r' : 'koi8-r',
183      \ 'koi8-u' : 'koi8-u',
184      \ 'macintosh' : 'macroman',
185      \ 'mac' : 'macroman',
186      \ 'csmacintosh' : 'macroman',
187      \ 'ibm437' : 'cp437',
188      \ 'cp437' : 'cp437',
189      \ '437' : 'cp437',
190      \ 'cspc8codepage437' : 'cp437',
191      \ 'ibm775' : 'cp775',
192      \ 'cp775' : 'cp775',
193      \ 'cspc775baltic' : 'cp775',
194      \ 'ibm850' : 'cp850',
195      \ 'cp850' : 'cp850',
196      \ '850' : 'cp850',
197      \ 'cspc850multilingual' : 'cp850',
198      \ 'ibm852' : 'cp852',
199      \ 'cp852' : 'cp852',
200      \ '852' : 'cp852',
201      \ 'cspcp852' : 'cp852',
202      \ 'ibm855' : 'cp855',
203      \ 'cp855' : 'cp855',
204      \ '855' : 'cp855',
205      \ 'csibm855' : 'cp855',
206      \ 'ibm857' : 'cp857',
207      \ 'cp857' : 'cp857',
208      \ '857' : 'cp857',
209      \ 'csibm857' : 'cp857',
210      \ 'ibm860' : 'cp860',
211      \ 'cp860' : 'cp860',
212      \ '860' : 'cp860',
213      \ 'csibm860' : 'cp860',
214      \ 'ibm861' : 'cp861',
215      \ 'cp861' : 'cp861',
216      \ '861' : 'cp861',
217      \ 'cp-is' : 'cp861',
218      \ 'csibm861' : 'cp861',
219      \ 'ibm862' : 'cp862',
220      \ 'cp862' : 'cp862',
221      \ '862' : 'cp862',
222      \ 'cspc862latinhebrew' : 'cp862',
223      \ 'ibm863' : 'cp863',
224      \ 'cp863' : 'cp863',
225      \ '863' : 'cp863',
226      \ 'csibm863' : 'cp863',
227      \ 'ibm865' : 'cp865',
228      \ 'cp865' : 'cp865',
229      \ '865' : 'cp865',
230      \ 'csibm865' : 'cp865',
231      \ 'ibm866' : 'cp866',
232      \ 'cp866' : 'cp866',
233      \ '866' : 'cp866',
234      \ 'csibm866' : 'cp866',
235      \ 'ibm869' : 'cp869',
236      \ 'cp869' : 'cp869',
237      \ '869' : 'cp869',
238      \ 'cp-gr' : 'cp869',
239      \ 'csibm869' : 'cp869',
240      \ 'windows-1250' : 'cp1250',
241      \ 'windows-1251' : 'cp1251',
242      \ 'windows-1253' : 'cp1253',
243      \ 'windows-1254' : 'cp1254',
244      \ 'windows-1255' : 'cp1255',
245      \ 'windows-1256' : 'cp1256',
246      \ 'windows-1257' : 'cp1257',
247      \ 'windows-1258' : 'cp1258',
248      \ 'extended_unix_code_packed_format_for_japanese' : 'euc-jp',
249      \ 'cseucpkdfmtjapanese' : 'euc-jp',
250      \ 'euc-jp' : 'euc-jp',
251      \ 'shift_jis' : 'sjis',
252      \ 'ms_kanji' : 'sjis',
253      \ 'sjis' : 'sjis',
254      \ 'csshiftjis' : 'sjis',
255      \ 'ibm-thai' : 'cp874',
256      \ 'csibmthai' : 'cp874',
257      \ 'ks_c_5601-1987' : 'cp949',
258      \ 'iso-ir-149' : 'cp949',
259      \ 'ks_c_5601-1989' : 'cp949',
260      \ 'ksc_5601' : 'cp949',
261      \ 'korean' : 'cp949',
262      \ 'csksc56011987' : 'cp949',
263      \ 'euc-kr' : 'euc-kr',
264      \ 'cseuckr' : 'euc-kr',
265      \ 'gbk' : 'cp936',
266      \ 'cp936' : 'cp936',
267      \ 'ms936' : 'cp936',
268      \ 'windows-936' : 'cp936',
269      \ 'gb_2312-80' : 'euc-cn',
270      \ 'iso-ir-58' : 'euc-cn',
271      \ 'chinese' : 'euc-cn',
272      \ 'csiso58gb231280' : 'euc-cn',
273      \ 'big5' : 'big5',
274      \ 'csbig5' : 'big5',
275      \ 'utf-8' : 'utf-8',
276      \ 'iso-10646-ucs-2' : 'ucs-2',
277      \ 'csunicode' : 'ucs-2',
278      \ 'utf-16' : 'utf-16',
279      \ 'utf-16be' : 'utf-16',
280      \ 'utf-16le' : 'utf-16le',
281      \ 'utf-32' : 'ucs-4',
282      \ 'utf-32be' : 'ucs-4',
283      \ 'utf-32le' : 'ucs-4le',
284      \ 'iso-10646-ucs-4' : 'ucs-4',
285      \ 'csucs4' : 'ucs-4'
286      \ }
287lockvar g:tohtml#charset_to_encoding
288"}}}
289
290func! tohtml#Convert2HTML(line1, line2) "{{{
291  let s:settings = tohtml#GetUserSettings()
292
293  if !&diff || s:settings.diff_one_file "{{{
294    if a:line2 >= a:line1
295      let g:html_start_line = a:line1
296      let g:html_end_line = a:line2
297    else
298      let g:html_start_line = a:line2
299      let g:html_end_line = a:line1
300    endif
301    runtime syntax/2html.vim "}}}
302  else "{{{
303    let win_list = []
304    let buf_list = []
305    windo | if &diff | call add(win_list, winbufnr(0)) | endif
306    let s:settings.whole_filler = 1
307    let g:html_diff_win_num = 0
308    for window in win_list
309      " switch to the next buffer to convert
310      exe ":" . bufwinnr(window) . "wincmd w"
311
312      " figure out whether current charset and encoding will work, if not
313      " default to UTF-8
314      if !exists('g:html_use_encoding') &&
315	    \ (&l:fileencoding!='' && &l:fileencoding!=s:settings.vim_encoding ||
316	    \  &l:fileencoding=='' &&       &encoding!=s:settings.vim_encoding)
317	echohl WarningMsg
318	echomsg "TOhtml: mismatched file encodings in Diff buffers, using UTF-8"
319	echohl None
320	let s:settings.vim_encoding = 'utf-8'
321	let s:settings.encoding = 'UTF-8'
322      endif
323
324      " set up for diff-mode conversion
325      let g:html_start_line = 1
326      let g:html_end_line = line('$')
327      let g:html_diff_win_num += 1
328
329      " convert this file
330      runtime syntax/2html.vim
331
332      " remember the HTML buffer for later combination
333      call add(buf_list, bufnr('%'))
334    endfor
335    unlet g:html_diff_win_num
336    call tohtml#Diff2HTML(win_list, buf_list)
337  endif "}}}
338
339  unlet g:html_start_line
340  unlet g:html_end_line
341  unlet s:settings
342endfunc "}}}
343
344func! tohtml#Diff2HTML(win_list, buf_list) "{{{
345  let xml_line = ""
346  let tag_close = '>'
347
348  let s:old_paste = &paste
349  set paste
350  let s:old_magic = &magic
351  set magic
352
353  if s:settings.use_xhtml
354    if s:settings.encoding != ""
355      let xml_line = "<?xml version=\"1.0\" encoding=\"" . s:settings.encoding . "\"?>"
356    else
357      let xml_line = "<?xml version=\"1.0\"?>"
358    endif
359    let tag_close = ' />'
360  endif
361
362  let style = [s:settings.use_xhtml ? "" : '-->']
363  let body_line = ''
364
365  let html = []
366  if s:settings.use_xhtml
367    call add(html, xml_line)
368  endif
369  if s:settings.use_xhtml
370    call add(html, "<!DOCTYPE html PUBLIC \"-//W3C//DTD XHTML 1.0 Transitional//EN\" \"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd\">")
371    call add(html, '<html xmlns="http://www.w3.org/1999/xhtml">')
372  elseif s:settings.use_css && !s:settings.no_pre
373    call add(html, "<!DOCTYPE HTML PUBLIC \"-//W3C//DTD HTML 4.01//EN\" \"http://www.w3.org/TR/html4/strict.dtd\">")
374    call add(html, '<html>')
375  else
376    call add(html, '<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"')
377    call add(html, '  "http://www.w3.org/TR/html4/loose.dtd">')
378    call add(html, '<html>')
379  endif
380  call add(html, '<head>')
381
382  " include encoding as close to the top as possible, but only if not already
383  " contained in XML information
384  if s:settings.encoding != "" && !s:settings.use_xhtml
385    call add(html, "<meta http-equiv=\"content-type\" content=\"text/html; charset=" . s:settings.encoding . '"' . tag_close)
386  endif
387
388  call add(html, '<title>diff</title>')
389  call add(html, '<meta name="Generator" content="Vim/'.v:version/100.'.'.v:version%100.'"'.tag_close)
390  call add(html, '<meta name="plugin-version" content="'.g:loaded_2html_plugin.'"'.tag_close)
391  call add(html, '<meta name="settings" content="'.
392	\ join(filter(keys(s:settings),'s:settings[v:val]'),',').
393	\ '"'.tag_close)
394
395  call add(html, '</head>')
396  let body_line_num = len(html)
397  call add(html, '<body>')
398  call add(html, '<table border="1" width="100%">')
399
400  call add(html, '<tr>')
401  for buf in a:win_list
402    call add(html, '<th>'.bufname(buf).'</th>')
403  endfor
404  call add(html, '</tr><tr>')
405
406  let diff_style_start = 0
407  let insert_index = 0
408
409  for buf in a:buf_list
410    let temp = []
411    exe bufwinnr(buf) . 'wincmd w'
412
413    " If text is folded because of user foldmethod settings, etc. we don't want
414    " to act on everything in a fold by mistake.
415    setlocal nofoldenable
416
417    " When not using CSS or when using xhtml, the <body> line can be important.
418    " Assume it will be the same for all buffers and grab it from the first
419    " buffer. Similarly, need to grab the body end line as well.
420    if body_line == ''
421      1
422      call search('<body')
423      let body_line = getline('.')
424      $
425      call search('</body>', 'b')
426      let s:body_end_line = getline('.')
427    endif
428
429    " Grab the style information. Some of this will be duplicated so only insert
430    " it if it's not already there. {{{
431    1
432    let style_start = search('^<style type="text/css">')
433    1
434    let style_end = search('^</style>')
435    if style_start > 0 && style_end > 0
436      let buf_styles = getline(style_start + 1, style_end - 1)
437      for a_style in buf_styles
438	if index(style, a_style) == -1
439	  if diff_style_start == 0
440	    if a_style =~ '\<Diff\(Change\|Text\|Add\|Delete\)'
441	      let diff_style_start = len(style)-1
442	    endif
443	  endif
444	  call insert(style, a_style, insert_index)
445	  let insert_index += 1
446	endif
447      endfor
448    endif " }}}
449
450    " everything new will get added before the diff styles so diff highlight
451    " properly overrides normal highlight
452    if diff_style_start != 0
453      let insert_index = diff_style_start
454    endif
455
456    " Delete those parts that are not needed so
457    " we can include the rest into the resulting table
458    1,/^<body/d_
459    $
460    ?</body>?,$d_
461    let temp = getline(1,'$')
462    " undo deletion of start and end part
463    " so we can later save the file as valid html
464    " TODO: restore using grabbed lines if undolevel is 1?
465    normal 2u
466    if s:settings.use_css
467      call add(html, '<td valign="top"><div>')
468    elseif s:settings.use_xhtml
469      call add(html, '<td nowrap="nowrap" valign="top"><div>')
470    else
471      call add(html, '<td nowrap valign="top"><div>')
472    endif
473    let html += temp
474    call add(html, '</div></td>')
475
476    " Close this buffer
477    " TODO: the comment above says we're going to allow saving the file
478    " later...but here we discard it?
479    quit!
480  endfor
481
482  let html[body_line_num] = body_line
483
484  call add(html, '</tr>')
485  call add(html, '</table>')
486  call add(html, s:body_end_line)
487  call add(html, '</html>')
488
489  let i = 1
490  let name = "Diff" . (s:settings.use_xhtml ? ".xhtml" : ".html")
491  " Find an unused file name if current file name is already in use
492  while filereadable(name)
493    let name = substitute(name, '\d*\.x\?html$', '', '') . i . '.' . fnamemodify(copy(name), ":t:e")
494    let i += 1
495  endwhile
496  exe "topleft new " . name
497  setlocal modifiable
498
499  " just in case some user autocmd creates content in the new buffer, make sure
500  " it is empty before proceeding
501  %d
502
503  " set the fileencoding to match the charset we'll be using
504  let &l:fileencoding=s:settings.vim_encoding
505
506  " According to http://www.w3.org/TR/html4/charset.html#doc-char-set, the byte
507  " order mark is highly recommend on the web when using multibyte encodings. But,
508  " it is not a good idea to include it on UTF-8 files. Otherwise, let Vim
509  " determine when it is actually inserted.
510  if s:settings.vim_encoding == 'utf-8'
511    setlocal nobomb
512  else
513    setlocal bomb
514  endif
515
516  call append(0, html)
517
518  if len(style) > 0
519    1
520    let style_start = search('^</head>')-1
521
522    " Insert javascript to toggle matching folds open and closed in all windows,
523    " if dynamic folding is active. {{{
524    if s:settings.dynamic_folds
525      call append(style_start, [
526	    \  "<script type='text/javascript'>",
527	    \  s:settings.use_xhtml ? '//<![CDATA[' : "  <!--",
528	    \  "  function toggleFold(objID)",
529	    \  "  {",
530	    \  "    for (win_num = 1; win_num <= ".len(a:buf_list)."; win_num++)",
531	    \  "    {",
532	    \  "      var fold;",
533	    \  '      fold = document.getElementById("win"+win_num+objID);',
534	    \  "      if(fold.className == 'closed-fold')",
535	    \  "      {",
536	    \  "        fold.className = 'open-fold';",
537	    \  "      }",
538	    \  "      else if (fold.className == 'open-fold')",
539	    \  "      {",
540	    \  "        fold.className = 'closed-fold';",
541	    \  "      }",
542	    \  "    }",
543	    \  "  }",
544	    \  s:settings.use_xhtml ? '//]]>' : "  -->",
545	    \  "</script>"
546	    \ ])
547    endif "}}}
548
549    " Insert styles from all the generated html documents and additional styles
550    " for the table-based layout of the side-by-side diff. The diff should take
551    " up the full browser window (but not more), and be static in size,
552    " horizontally scrollable when the lines are too long. Otherwise, the diff
553    " is pretty useless for really long lines. {{{
554    if s:settings.use_css
555      call append(style_start,
556	    \ ['<style type="text/css">']+
557	    \ style+
558	    \ [ s:settings.use_xhtml ? '' : '<!--',
559	    \   'table { table-layout: fixed; }',
560	    \   'html, body, table, tbody { width: 100%; margin: 0; padding: 0; }',
561	    \   'th, td { width: '.printf("%.1f",100.0/len(a:win_list)).'%; }',
562	    \   'td div { overflow: auto; }',
563	    \   s:settings.use_xhtml ? '' : '-->',
564	    \   '</style>'
565	    \])
566    endif "}}}
567  endif
568
569  let &paste = s:old_paste
570  let &magic = s:old_magic
571endfunc "}}}
572
573" Gets a single user option and sets it in the passed-in Dict, or gives it the
574" default value if the option doesn't actually exist.
575func! tohtml#GetOption(settings, option, default) "{{{
576  if exists('g:html_'.a:option)
577    let a:settings[a:option] = g:html_{a:option}
578  else
579    let a:settings[a:option] = a:default
580  endif
581endfunc "}}}
582
583" returns a Dict containing the values of all user options for 2html, including
584" default values for those not given an explicit value by the user. Discards the
585" html_ prefix of the option for nicer looking code.
586func! tohtml#GetUserSettings() "{{{
587  if exists('s:settings')
588    " just restore the known options if we've already retrieved them
589    return s:settings
590  else
591    " otherwise figure out which options are set
592    let user_settings = {}
593
594    " Define the correct option if the old option name exists and we haven't
595    " already defined the correct one. Maybe I'll put out a warnig message about
596    " this sometime and remove the old option entirely at some even later time,
597    " but for now just silently accept the old option.
598    if exists('g:use_xhtml') && !exists("g:html_use_xhtml")
599      let g:html_use_xhtml = g:use_xhtml
600    endif
601
602    " get current option settings with appropriate defaults {{{
603    call tohtml#GetOption(user_settings,    'no_progress', !has("statusline") )
604    call tohtml#GetOption(user_settings,  'diff_one_file', 0 )
605    call tohtml#GetOption(user_settings,   'number_lines', &number )
606    call tohtml#GetOption(user_settings,        'use_css', 1 )
607    call tohtml#GetOption(user_settings, 'ignore_conceal', 0 )
608    call tohtml#GetOption(user_settings, 'ignore_folding', 0 )
609    call tohtml#GetOption(user_settings,  'dynamic_folds', 0 )
610    call tohtml#GetOption(user_settings,  'no_foldcolumn', 0 )
611    call tohtml#GetOption(user_settings,   'hover_unfold', 0 )
612    call tohtml#GetOption(user_settings,         'no_pre', 0 )
613    call tohtml#GetOption(user_settings,   'whole_filler', 0 )
614    call tohtml#GetOption(user_settings,      'use_xhtml', 0 )
615    " }}}
616
617    " override those settings that need it {{{
618
619    " hover opening implies dynamic folding
620    if user_settings.hover_unfold
621      let user_settings.dynamic_folds = 1
622    endif
623
624    " ignore folding overrides dynamic folding
625    if user_settings.ignore_folding && user_settings.dynamic_folds
626      let user_settings.dynamic_folds = 0
627      let user_settings.hover_unfold = 0
628    endif
629
630    " dynamic folding with no foldcolumn implies hover opens
631    if user_settings.dynamic_folds && user_settings.no_foldcolumn
632      let user_settings.hover_unfold = 1
633    endif
634
635    " dynamic folding implies css
636    if user_settings.dynamic_folds
637      let user_settings.use_css = 1
638    endif
639
640    " if we're not using CSS we cannot use a pre section because <font> tags
641    " aren't allowed inside a <pre> block
642    if !user_settings.use_css
643      let user_settings.no_pre = 1
644    endif "}}}
645
646    " set up expand_tabs option after all the overrides so we know the
647    " appropriate defaults {{{
648    if user_settings.no_pre == 0
649      call tohtml#GetOption(user_settings,
650	    \ 'expand_tabs',
651	    \ &expandtab || &ts != 8 || user_settings.number_lines ||
652	    \   (user_settings.dynamic_folds && !user_settings.no_foldcolumn))
653    else
654      let user_settings.expand_tabs = 1
655    endif
656    " }}}
657
658    if exists("g:html_use_encoding") "{{{
659      " user specified the desired MIME charset, figure out proper
660      " 'fileencoding' from it or warn the user if we cannot
661      let user_settings.encoding = g:html_use_encoding
662      let user_settings.vim_encoding = tohtml#EncodingFromCharset(g:html_use_encoding)
663      if user_settings.vim_encoding == ''
664	echohl WarningMsg
665	echomsg "TOhtml: file encoding for"
666	      \ g:html_use_encoding
667	      \ "unknown, please set 'fileencoding'"
668	echohl None
669      endif
670    else
671      " Figure out proper MIME charset from 'fileencoding' if possible
672      if &l:fileencoding != ''
673	let user_settings.vim_encoding = &l:fileencoding
674	call tohtml#CharsetFromEncoding(user_settings)
675      endif
676
677      " else from 'encoding' if possible
678      if &l:fileencoding == '' || user_settings.encoding == ''
679	let user_settings.vim_encoding = &encoding
680	call tohtml#CharsetFromEncoding(user_settings)
681      endif
682
683      " else default to UTF-8 and warn user
684      if user_settings.encoding == ''
685	let user_settings.vim_encoding = 'utf-8'
686	let user_settings.encoding = 'UTF-8'
687	echohl WarningMsg
688	echomsg "TOhtml: couldn't determine MIME charset, using UTF-8"
689	echohl None
690      endif
691    endif "}}}
692
693    " TODO: font
694
695    return user_settings
696  endif
697endfunc "}}}
698
699" get the proper HTML charset name from a Vim encoding option.
700function! tohtml#CharsetFromEncoding(settings) "{{{
701  let l:vim_encoding = a:settings.vim_encoding
702  if exists('g:html_charset_override') && has_key(g:html_charset_override, l:vim_encoding)
703    let a:settings.encoding = g:html_charset_override[l:vim_encoding]
704  else
705    if l:vim_encoding =~ '^8bit\|^2byte'
706      " 8bit- and 2byte- prefixes are to indicate encodings available on the
707      " system that Vim will convert with iconv(), look up just the encoding name,
708      " not Vim's prefix.
709      let l:vim_encoding = substitute(l:vim_encoding, '^8bit-\|^2byte-', '', '')
710    endif
711    if has_key(g:tohtml#encoding_to_charset, l:vim_encoding)
712      let a:settings.encoding = g:tohtml#encoding_to_charset[l:vim_encoding]
713    else
714      let a:settings.encoding = ""
715    endif
716  endif
717  if a:settings.encoding != ""
718    let l:vim_encoding = tohtml#EncodingFromCharset(a:settings.encoding)
719    if l:vim_encoding != ""
720      " if the Vim encoding to HTML encoding conversion is set up (by default or
721      " by the user) to convert to a different encoding, we need to also change
722      " the Vim encoding of the new buffer
723      let a:settings.vim_encoding = l:vim_encoding
724    endif
725  endif
726endfun "}}}
727
728" Get the proper Vim encoding option setting from an HTML charset name.
729function! tohtml#EncodingFromCharset(encoding) "{{{
730  if exists('g:html_encoding_override') && has_key(g:html_encoding_override, a:encoding)
731    return g:html_encoding_override[a:encoding]
732  elseif has_key(g:tohtml#charset_to_encoding, tolower(a:encoding))
733    return g:tohtml#charset_to_encoding[tolower(a:encoding)]
734  else
735    return ""
736  endif
737endfun "}}}
738
739let &cpo = s:cpo_sav
740unlet s:cpo_sav
741
742" Make sure any patches will probably use consistent indent
743"   vim: ts=8 sw=2 sts=2 noet fdm=marker
744