diff runtime/syntax/2html.vim @ 2321:1902913f2049 vim73

Improved version of 2html.vim. Includes progress bar. Fix dynamic folding in diff view. (Benjamin Fritz)
author Bram Moolenaar <bram@vim.org>
date Fri, 16 Jul 2010 20:35:36 +0200
parents a59e6ac5ed28
children 3c9324c0800e
line wrap: on
line diff
--- a/runtime/syntax/2html.vim
+++ b/runtime/syntax/2html.vim
@@ -1,16 +1,25 @@
 " Vim syntax support file
-" Maintainer: Bram Moolenaar <Bram@vim.org>
-" Last Change: 2009 Jul 14
-"	       (modified by David Ne\v{c}as (Yeti) <yeti@physics.muni.cz>)
-"	       (XHTML support by Panagiotis Issaris <takis@lumumba.luc.ac.be>)
-"	       (made w3 compliant by Edd Barrett <vext01@gmail.com>)
-"	       (added html_font. Edd Barrett <vext01@gmail.com>)
-"	       (dynamic folding by Ben Fritz <fritzophrenic@gmail.com>)
+" Maintainer: Ben Fritz <fritzophrenic@gmail.com>
+" Last Change: 2010 July 15
+"
+" Additional contributors:
+"
+"	      Original by Bram Moolenaar <Bram@vim.org>
+"	      Modified by David Ne\v{c}as (Yeti) <yeti@physics.muni.cz>
+"	      XHTML support by Panagiotis Issaris <takis@lumumba.luc.ac.be>
+"	      Made w3 compliant by Edd Barrett <vext01@gmail.com>
+"	      Added html_font. Edd Barrett <vext01@gmail.com>
+"	      Progress bar based off code from "progressbar widget" plugin by
+"		Andreas Politz, heavily modified:
+"		http://www.vim.org/scripts/script.php?script_id=2006
+"
+"	      See Mercurial change logs for more!
 
 " Transform a file into HTML, using the current syntax highlighting.
 
 " this file uses line continuations
 let s:cpo_sav = &cpo
+let s:ls  = &ls
 set cpo-=C
 
 " Number lines when explicitely requested or when `number' is set
@@ -20,43 +29,23 @@ else
   let s:numblines = &number
 endif
 
+let s:end=line('$')
+" default to using the progress bar
+if exists("g:html_no_progress")
+  let s:html_no_progress = g:html_no_progress
+else
+  let s:html_no_progress = 0
+endif
+
 " Font
 if exists("g:html_font")
-  let s:htmlfont = html_font . ", monospace"
+  let s:htmlfont = "'". html_font . "', monospace"
 else
   let s:htmlfont = "monospace"
 endif
 
-" make copies of the user-defined settings that we may overrule
-if exists("g:html_dynamic_folds")
-  let s:html_dynamic_folds = 1
-endif
-if exists("g:html_hover_unfold")
-  let s:html_hover_unfold = 1
-endif
-if exists("g:html_use_css")
-  let s:html_use_css = 1
-endif
-
-" hover opening implies dynamic folding
-if exists("s:html_hover_unfold")
-  let s:html_dynamic_folds = 1
-endif
-
-" dynamic folding with no foldcolumn implies hover opens
-if exists("s:html_dynamic_folds") && exists("g:html_no_foldcolumn")
-  let s:html_hover_unfold = 1
-endif
-
-" ignore folding overrides dynamic folding
-if exists("g:html_ignore_folding") && exists("s:html_dynamic_folds")
-  unlet s:html_dynamic_folds
-endif
-
-" dynamic folding implies css
-if exists("s:html_dynamic_folds")
-  let s:html_use_css = 1
-endif
+" do any option overrides that are needed for current user settings
+let s:old_html_settings = tohtml#OverrideUserSettings()
 
 " When not in gui we can only guess the colors.
 if has("gui_running")
@@ -98,7 +87,7 @@ else
   endfun
 endif
 
-if !exists("s:html_use_css")
+if !exists("g:html_use_css")
   " Return opening HTML tag for given highlight id
   function! s:HtmlOpening(id)
     let a = ""
@@ -121,7 +110,7 @@ if !exists("s:html_use_css")
   endfun
 
   " Return closing HTML tag for given highlight id
-  function s:HtmlClosing(id)
+  function! s:HtmlClosing(id)
     let a = ""
     if synIDattr(a:id, "underline") | let a = a . "</u>" | endif
     if synIDattr(a:id, "italic") | let a = a . "</i>" | endif
@@ -186,8 +175,7 @@ function! s:CSS1(id)
   return a
 endfun
 
-if exists("s:html_dynamic_folds")
-
+if exists("g:html_dynamic_folds")
   " compares two folds as stored in our list of folds
   " A fold is "less" than another if it starts at an earlier line number,
   " or ends at a later line number, ties broken by fold level
@@ -208,7 +196,7 @@ endif
 
 " Figure out proper MIME charset from the 'encoding' option.
 if exists("g:html_use_encoding")
-  let s:html_encoding = html_use_encoding
+  let s:html_encoding = g:html_use_encoding
 else
   let s:vim_encoding = &encoding
   if s:vim_encoding =~ '^8bit\|^2byte'
@@ -247,32 +235,54 @@ let s:old_icon = &icon
 let s:old_et = &l:et
 let s:old_report = &report
 let s:old_search = @/
+let s:old_more = &more
 set notitle noicon
 setlocal et
+set nomore
 set report=1000000
 
 " Split window to create a buffer with the HTML file.
 let s:orgbufnr = winbufnr(0)
+let s:origwin_stl = &l:stl
 if expand("%") == ""
   new Untitled.html
 else
   new %.html
 endif
+
+" Resize the new window to very small in order to make it draw faster
+let s:old_winheight = winheight(0)
+let s:old_winfixheight = &l:winfixheight
+if s:old_winheight > 2
+  resize 1 " leave enough room to view one line at a time
+  norm! G
+  norm! zt
+endif
+setlocal winfixheight
+
+let s:newwin_stl = &l:stl
+
+" on the new window, set the least time-consuming fold method
+let s:old_fdm = &foldmethod
+setlocal foldmethod=manual
+
 let s:newwin = winnr()
 let s:orgwin = bufwinnr(s:orgbufnr)
 
-set modifiable
+setlocal modifiable
 %d
 let s:old_paste = &paste
 set paste
 let s:old_magic = &magic
 set magic
 
+let s:lines = []
+
 if exists("g:use_xhtml")
   if s:html_encoding != ""
-    exe "normal!  a<?xml version=\"1.0\" encoding=\"" . s:html_encoding . "\"?>\n\e"
+    call add(s:lines, "<?xml version=\"1.0\" encoding=\"" . s:html_encoding . "\"?>")
   else
-    exe "normal! a<?xml version=\"1.0\"?>\n\e"
+    call add(s:lines, "<?xml version=\"1.0\"?>")
   endif
   let s:tag_close = ' />'
 else
@@ -281,12 +291,12 @@ endif
 
 " Cache html_no_pre in case we have to turn it on for non-css mode
 if exists("g:html_no_pre")
-  let s:old_html_no_pre = html_no_pre
+  let s:old_html_no_pre = g:html_no_pre
 endif
 
-if !exists("s:html_use_css")
+if !exists("g:html_use_css")
   " Can't put font tags in <pre>
-  let html_no_pre=1
+  let g:html_no_pre=1
 endif
 
 let s:HtmlSpace = ' '
@@ -300,97 +310,114 @@ endif
 
 " HTML header, with the title and generator ;-). Left free space for the CSS,
 " to be filled at the end.
-exe "normal! a<html>\n\e"
-exe "normal! a<head>\n<title>" . expand("%:p:~") . "</title>\n\e"
-exe "normal! a<meta name=\"Generator\" content=\"Vim/" . v:version/100 . "." . v:version %100 . '"' . s:tag_close . "\n\e"
+call extend(s:lines, [
+      \"<html>",
+      \"<head>",
+      \("<title>".expand("%:p:~")."</title>"),
+      \("<meta name=\"Generator\" content=\"Vim/".v:version/100.".".v:version%100.'"'.s:tag_close),
+      \])
 if s:html_encoding != ""
-  exe "normal! a<meta http-equiv=\"content-type\" content=\"text/html; charset=" . s:html_encoding . '"' . s:tag_close . "\n\e"
+  call add(s:lines, "<meta http-equiv=\"content-type\" content=\"text/html; charset=" . s:html_encoding . '"' . s:tag_close)
 endif
 
-if exists("s:html_use_css")
-  if exists("s:html_dynamic_folds")
-    if exists("s:html_hover_unfold")
+if exists("g:html_use_css")
+  if exists("g:html_dynamic_folds")
+    if exists("g:html_hover_unfold")
       " if we are doing hover_unfold, use css 2 with css 1 fallback for IE6
-      exe "normal! a".
-	  \ "<style type=\"text/css\">\n<!--\n".
-	  \ ".FoldColumn { text-decoration: none; white-space: pre; }\n\n".
-	  \ "body * { margin: 0; padding: 0; }\n".
-	  \ "\n".
-	  \ ".open-fold   > .Folded { display: none;  }\n".
-	  \ ".open-fold   > .fulltext { display: inline; }\n".
-	  \ ".closed-fold > .fulltext { display: none;  }\n".
-	  \ ".closed-fold > .Folded { display: inline; }\n".
-	  \ "\n".
-	  \ ".open-fold   > .toggle-open   { display: none;   }\n".
-	  \ ".open-fold   > .toggle-closed { display: inline; }\n".
-	  \ ".closed-fold > .toggle-open   { display: inline; }\n".
-	  \ ".closed-fold > .toggle-closed { display: none;   }\n"
-      exe "normal! a\n/* opening a fold while hovering won't be supported by IE6 and other\n".
-	  \ "similar browsers, but it should fail gracefully. */\n".
-	  \ ".closed-fold:hover > .fulltext { display: inline; }\n".
-	  \ ".closed-fold:hover > .toggle-filler { display: none; }\n".
-	  \ ".closed-fold:hover > .Folded { display: none; }\n"
-      exe "normal! a-->\n</style>\n"
-      exe "normal! a<!--[if lt IE 7]>".
-	  \ "<style type=\"text/css\">\n".
-	  \ ".open-fold   .Folded      { display: none; }\n".
-	  \ ".open-fold   .fulltext      { display: inline; }\n".
-	  \ ".open-fold   .toggle-open   { display: none; }\n".
-	  \ ".closed-fold .toggle-closed { display: inline; }\n".
-	  \ "\n".
-	  \ ".closed-fold .fulltext      { display: none; }\n".
-	  \ ".closed-fold .Folded      { display: inline; }\n".
-	  \ ".closed-fold .toggle-open   { display: inline; }\n".
-	  \ ".closed-fold .toggle-closed { display: none; }\n".
-	  \ "</style>\n".
-	  \ "<![endif]-->\n"
+      call extend(s:lines, [
+	    \ "<style type=\"text/css\">",
+	    \ "<!--",
+	    \ ".FoldColumn { text-decoration: none; white-space: pre; }",
+	    \ "",
+	    \ "body * { margin: 0; padding: 0; }", "",
+	    \ ".open-fold   > .Folded { display: none;  }",
+	    \ ".open-fold   > .fulltext { display: inline; }",
+	    \ ".closed-fold > .fulltext { display: none;  }",
+	    \ ".closed-fold > .Folded { display: inline; }",
+	    \ "",
+	    \ ".open-fold   > .toggle-open   { display: none;   }",
+	    \ ".open-fold   > .toggle-closed { display: inline; }",
+	    \ ".closed-fold > .toggle-open   { display: inline; }",
+	    \ ".closed-fold > .toggle-closed { display: none;   }",
+	    \ "", "",
+	    \ '/* opening a fold while hovering won''t be supported by IE6 and other',
+	    \ "similar browsers, but it should fail gracefully. */",
+	    \ ".closed-fold:hover > .fulltext { display: inline; }",
+	    \ ".closed-fold:hover > .toggle-filler { display: none; }",
+	    \ ".closed-fold:hover > .Folded { display: none; }",
+	    \ '-->',
+	    \ '<style>',
+	    \ "<!--[if lt IE 7]><style type=\"text/css\">",
+	    \ ".open-fold   .Folded      { display: none; }",
+	    \ ".open-fold   .fulltext      { display: inline; }",
+	    \ ".open-fold   .toggle-open   { display: none; }",
+	    \ ".closed-fold .toggle-closed { display: inline; }",
+	    \ "",
+	    \ ".closed-fold .fulltext      { display: none; }",
+	    \ ".closed-fold .Folded      { display: inline; }",
+	    \ ".closed-fold .toggle-open   { display: inline; }",
+	    \ ".closed-fold .toggle-closed { display: none; }",
+	    \ "</style>",
+	    \ "<![endif]-->",
+	    \])
     else
       " if we aren't doing hover_unfold, use CSS 1 only
-      exe "normal! a<style type=\"text/css\">\n<!--\n".
-	    \ ".FoldColumn { text-decoration: none; white-space: pre; }\n\n".
-	    \ ".open-fold   .Folded      { display: none; }\n".
-	    \ ".open-fold   .fulltext      { display: inline; }\n".
-	    \ ".open-fold   .toggle-open   { display: none; }\n".
-	    \ ".closed-fold .toggle-closed { display: inline; }\n".
-	    \ "\n".
-	    \ ".closed-fold .fulltext      { display: none; }\n".
-	    \ ".closed-fold .Folded      { display: inline; }\n".
-	    \ ".closed-fold .toggle-open   { display: inline; }\n".
-	    \ ".closed-fold .toggle-closed { display: none; }\n".
-	    \ "-->\n</style>\n"
+      call extend(s:lines, [
+	    \ "<style type=\"text/css\">",
+	    \ "<!--",
+	    \ ".FoldColumn { text-decoration: none; white-space: pre; }",
+	    \ ".open-fold   .Folded      { display: none; }",
+	    \ ".open-fold   .fulltext      { display: inline; }",
+	    \ ".open-fold   .toggle-open   { display: none; }",
+	    \ ".closed-fold .toggle-closed { display: inline; }",
+	    \ "",
+	    \ ".closed-fold .fulltext      { display: none; }",
+	    \ ".closed-fold .Folded      { display: inline; }",
+	    \ ".closed-fold .toggle-open   { display: inline; }",
+	    \ ".closed-fold .toggle-closed { display: none; }",
+	    \ '-->',
+	    \ '</style>'
+	    \])
     endif
   else
     " if we aren't doing any dynamic folding, no need for any special rules
-    exe "normal! a<style type=\"text/css\">\n<!--\n-->\n</style>\n\e"
+    call extend(s:lines, [
+	  \ "<style type=\"text/css\">",
+	  \ "<!--",
+	  \ '-->',
+	  \ "</style>",
+	  \])
   endif
 endif
 
 " insert javascript to toggle folds open and closed
-if exists("s:html_dynamic_folds")
-  exe "normal! a\n".
-	\ "<script type='text/javascript'>\n".
-	\ "<!--\n".
-	\ "function toggleFold(objID)\n".
-	\ "{\n".
-	\ "  var fold;\n".
-	\ "  fold = document.getElementById(objID);\n".
-	\ "  if(fold.className == 'closed-fold')\n".
-	\ "  {\n".
-	\ "    fold.className = 'open-fold';\n".
-	\ "  }\n".
-	\ "  else if (fold.className == 'open-fold')\n".
-	\ "  {\n".
-	\ "    fold.className = 'closed-fold';\n".
-	\ "  }\n".
-	\ "}\n".
-	\ "-->\n".
-	\ "</script>\n\e"
+if exists("g:html_dynamic_folds")
+  call extend(s:lines, [
+	\ "",
+	\ "<script type='text/javascript'>",
+	\ "<!--",
+	\ "function toggleFold(objID)",
+	\ "{",
+	\ "  var fold;",
+	\ "  fold = document.getElementById(objID);",
+	\ "  if(fold.className == 'closed-fold')",
+	\ "  {",
+	\ "    fold.className = 'open-fold';",
+	\ "  }",
+	\ "  else if (fold.className == 'open-fold')",
+	\ "  {",
+	\ "    fold.className = 'closed-fold';",
+	\ "  }",
+	\ "}",
+	\ '-->',
+	\ "</script>"
+	\])
 endif
 
 if exists("g:html_no_pre")
-  exe "normal! a</head>\n<body>\n\e"
+  call extend(s:lines, ["</head>", "<body>"])
 else
-  exe "normal! a</head>\n<body>\n<pre>\n\e"
+  call extend(s:lines, ["</head>", "<body>", "<pre>"])
 endif
 
 exe s:orgwin . "wincmd w"
@@ -398,23 +425,132 @@ exe s:orgwin . "wincmd w"
 " List of all id's
 let s:idlist = ","
 
+" set up progress bar in the status line
+if !s:html_no_progress && has("statusline")
+  " ProgressBar Indicator
+  let s:progressbar={}
+
+  " Progessbar specific functions
+  func! s:ProgressBar(title, max_value, winnr)
+    let pgb=copy(s:progressbar)
+    let pgb.title = a:title.' '
+    let pgb.max_value = a:max_value
+    let pgb.winnr = a:winnr
+    let pgb.cur_value = 0
+    let pgb.items = { 'title'   : { 'color' : 'Statusline' },
+	  \'bar'     : { 'color' : 'Statusline' , 'fillcolor' : 'DiffDelete' , 'bg' : 'Statusline' } ,
+	  \'counter' : { 'color' : 'Statusline' } }
+    let pgb.last_value = 0
+    let pgb.needs_redraw = 0
+    " Note that you must use len(split) instead of len() if you want to use 
+    " unicode in title.
+    "
+    " Subtract 3 for spacing around the title.
+    " Subtract 4 for the percentage display.
+    " Subtract 2 for spacing before this.
+    " Subtract 2 more for the '|' on either side of the progress bar
+    let pgb.subtractedlen=len(split(pgb.title, '\zs'))+3+4+2+2
+    let pgb.max_len = 0
+    set laststatus=2
+    return pgb
+  endfun
+
+  " Function: progressbar.calculate_ticks() {{{1
+  func! s:progressbar.calculate_ticks(pb_len)
+    if a:pb_len<=0
+      let pb_len = 100
+    else
+      let pb_len = a:pb_len
+    endif
+    let self.progress_ticks = map(range(pb_len+1), "v:val * self.max_value / pb_len")
+  endfun
+
+  "Function: progressbar.paint()
+  func! s:progressbar.paint()
+    " Recalculate widths.
+    let max_len = winwidth(self.winnr)
+    let pb_len = 0
+    " always true on first call because of initial value of self.max_len
+    if max_len != self.max_len
+      let self.max_len = max_len
+
+      " Progressbar length
+      let pb_len = max_len - self.subtractedlen
+
+      call self.calculate_ticks(pb_len)
+
+      let self.needs_redraw = 1
+      let cur_value = 0
+      let self.pb_len = pb_len
+    else
+      " start searching at the last found index to make the search for the
+      " appropriate tick value normally take 0 or 1 comparisons
+      let cur_value = self.last_value
+      let pb_len = self.pb_len
+    endif
+
+    let cur_val_max = pb_len > 0 ? pb_len : 100
+
+    " find the current progress bar position based on precalculated thresholds
+    while cur_value < cur_val_max && self.cur_value > self.progress_ticks[cur_value]
+      let cur_value += 1
+    endwhile
+
+    " update progress bar
+    if self.last_value != cur_value || self.needs_redraw || self.cur_value == self.max_value
+      let self.needs_redraw = 1
+      let self.last_value = cur_value
+
+      let t_color  = self.items.title.color
+      let b_fcolor = self.items.bar.fillcolor
+      let b_color  = self.items.bar.color
+      let c_color  = self.items.counter.color
+
+      let stl =  "%#".t_color."#%-( ".self.title." %)".
+	    \"%#".b_color."#".
+	    \(pb_len>0 ?
+	    \	('|%#'.b_fcolor."#%-(".repeat(" ",cur_value)."%)".
+	    \	 '%#'.b_color."#".repeat(" ",pb_len-cur_value)."|"):
+	    \	('')).
+	    \"%=%#".c_color."#%( ".printf("%3.d ",100*self.cur_value/self.max_value)."%% %)"
+      call setwinvar(self.winnr, '&stl', stl)
+    endif
+  endfun
+
+  func! s:progressbar.incr( ... )
+    let self.cur_value += (a:0 ? a:1 : 1)
+    " if we were making a general-purpose progress bar, we'd need to limit to a
+    " lower limit as well, but since we always increment with a positive value
+    " in this script, we only need limit the upper value
+    let self.cur_value = (self.cur_value > self.max_value ? self.max_value : self.cur_value)
+    call self.paint()
+  endfun
+  " }}}
+  if exists("g:html_dynamic_folds")
+    " to process folds we make two passes through each line
+    let s:pgb = s:ProgressBar("Processing folds:", line('$')*2, s:orgwin)
+  endif
+else
+  let s:html_no_progress=1
+endif
+
 " First do some preprocessing for dynamic folding. Do this for the entire file
 " so we don't accidentally start within a closed fold or something.
 let s:allfolds = []
 
-if exists("s:html_dynamic_folds")
+if exists("g:html_dynamic_folds")
   let s:lnum = 1
   let s:end = line('$')
   " save the fold text and set it to the default so we can find fold levels
   let s:foldtext_save = &foldtext
-  set foldtext&
+  setlocal foldtext&
 
   " we will set the foldcolumn in the html to the greater of the maximum fold
   " level and the current foldcolumn setting
   let s:foldcolumn = &foldcolumn
 
   " get all info needed to describe currently closed folds
-  while s:lnum < s:end
+  while s:lnum <= s:end
     if foldclosed(s:lnum) == s:lnum
       " default fold text has '+-' and then a number of dashes equal to fold
       " level, so subtract 2 from index of first non-dash after the dashes
@@ -429,6 +565,13 @@ if exists("s:html_dynamic_folds")
       " open the fold so we can find any contained folds
       execute s:lnum."foldopen"
     else
+      if !s:html_no_progress
+	call s:pgb.incr()
+	if s:pgb.needs_redraw
+	  redrawstatus
+	  let s:pgb.needs_redraw = 0
+	endif
+      endif
       let s:lnum = s:lnum + 1
     endif
   endwhile
@@ -439,7 +582,7 @@ if exists("s:html_dynamic_folds")
 
   " the originally open folds will be all folds we encounter that aren't
   " already in the list of closed folds
-  while s:lnum < s:end
+  while s:lnum <= s:end
     if foldclosed(s:lnum) == s:lnum
       " default fold text has '+-' and then a number of dashes equal to fold
       " level, so subtract 2 from index of first non-dash after the dashes
@@ -457,6 +600,13 @@ if exists("s:html_dynamic_folds")
       " open the fold so we can find any contained folds
       execute s:lnum."foldopen"
     else
+      if !s:html_no_progress
+	call s:pgb.incr()
+	if s:pgb.needs_redraw
+	  redrawstatus
+	  let s:pgb.needs_redraw = 0
+	endif
+      endif
       let s:lnum = s:lnum + 1
     endif
   endwhile
@@ -465,11 +615,11 @@ if exists("s:html_dynamic_folds")
   " list of folds
   call sort(s:allfolds, "s:FoldCompare")
 
-  let &foldtext = s:foldtext_save
+  let &l:foldtext = s:foldtext_save
   unlet s:foldtext_save
 
   " close all folds again so we can get the fold text as we go
-  silent! %foldclose! 
+  silent! %foldclose!
 endif
 
 " Now loop over all lines in the original text to convert to html.
@@ -494,6 +644,10 @@ endif
 " stack to keep track of all the folds containing the current line
 let s:foldstack = []
 
+if !s:html_no_progress
+  let s:pgb = s:ProgressBar("Processing lines:", s:end - s:lnum + 1, s:orgwin)
+endif
+
 if s:numblines
   let s:margin = strlen(s:end) + 1
 else
@@ -539,9 +693,7 @@ while s:lnum <= s:end
 	" Indent if line numbering is on; must be after escaping.
 	let s:new = repeat(s:LeadingSpace, s:margin) . s:new
       endif
-      exe s:newwin . "wincmd w"
-      exe "normal! a" . s:new . s:HtmlEndline . "\n\e"
-      exe s:orgwin . "wincmd w"
+      call add(s:lines, s:new.s:HtmlEndline)
 
       let s:n = s:n - 1
     endwhile
@@ -558,7 +710,7 @@ while s:lnum <= s:end
 
   let s:new = ""
 
-  if has('folding') && !exists('g:html_ignore_folding') && foldclosed(s:lnum) > -1 && !exists('s:html_dynamic_folds')
+  if has('folding') && !exists('g:html_ignore_folding') && foldclosed(s:lnum) > -1 && !exists('g:html_dynamic_folds')
     "
     " This is the beginning of a folded block (with no dynamic folding)
     "
@@ -571,7 +723,13 @@ while s:lnum <= s:end
     let s:new = s:HtmlFormat(s:new, "Folded")
 
     " Skip to the end of the fold
-    let s:lnum = foldclosedend(s:lnum)
+    let s:new_lnum = foldclosedend(s:lnum)
+
+    if !s:html_no_progress
+      call s:pgb.incr(s:new_lnum - s:lnum)
+    endif
+
+    let s:lnum = s:new_lnum
 
   else
     "
@@ -580,7 +738,7 @@ while s:lnum <= s:end
     let s:line = getline(s:lnum)
     let s:len = strlen(s:line)
 
-    if exists("s:html_dynamic_folds")
+    if exists("g:html_dynamic_folds")
       " First insert a closing for any open folds that end on this line
       while !empty(s:foldstack) && get(s:foldstack,0).lastline == s:lnum-1
 	let s:new = s:new."</span></span>"
@@ -591,7 +749,10 @@ while s:lnum <= s:end
       let s:firstfold = 1
       while !empty(s:allfolds) && get(s:allfolds,0).firstline == s:lnum
 	let s:foldId = s:foldId + 1
-	let s:new = s:new . "<span id='fold".s:foldId."' class='".s:allfolds[0].type."'>"
+	let s:new .= "<span id='"
+	let s:new .= (exists('g:html_diff_win_num') ? "win".g:html_diff_win_num : "")
+	let s:new .= "fold".s:foldId."' class='".s:allfolds[0].type."'>"
+
 
 	" Unless disabled, add a fold column for the opening line of a fold.
 	"
@@ -632,7 +793,7 @@ while s:lnum <= s:end
 
 	" add fold text, moving the span ending to the next line so collapsing
 	" of folds works correctly
-	let s:new = s:new . substitute(s:HtmlFormat(s:numcol . foldtextresult(s:lnum), "Folded"), '</span>', s:HtmlEndline.'\r\0', '')
+	let s:new = s:new . substitute(s:HtmlFormat(s:numcol . foldtextresult(s:lnum), "Folded"), '</span>', s:HtmlEndline.'\n\0', '')
 	let s:new = s:new . "<span class='fulltext'>"
 
 	" open the fold now that we have the fold text to allow retrieval of
@@ -725,18 +886,22 @@ while s:lnum <= s:end
     endwhile
   endif
 
-  exe s:newwin . "wincmd w"
-  exe "normal! a" . s:new . s:HtmlEndline . "\n\e"
-  exe s:orgwin . "wincmd w"
+  call extend(s:lines, split(s:new.s:HtmlEndline, '\n'))
+  if !s:html_no_progress && s:pgb.needs_redraw
+    redrawstatus
+    let s:pgb.needs_redraw = 0
+  endif
   let s:lnum = s:lnum + 1
+
+  if !s:html_no_progress
+    call s:pgb.incr()
+  endif
 endwhile
-" Finish with the last line
-exe s:newwin . "wincmd w"
 
-if exists("s:html_dynamic_folds")
+if exists("g:html_dynamic_folds")
   " finish off any open folds
   while !empty(s:foldstack)
-    exe "normal! a</span></span>"
+    let s:lines[-1].="</span></span>"
     call remove(s:foldstack, 0)
   endwhile
 
@@ -748,19 +913,22 @@ if exists("s:html_dynamic_folds")
 endif
 
 " Close off the font tag that encapsulates the whole <body>
-if !exists("s:html_use_css")
-  exe "normal! a</font>\e"
+if !exists("g:html_use_css")
+  let s:lines[-1].="</font>"
 endif
 
 if exists("g:html_no_pre")
-  exe "normal! a</body>\n</html>\e"
+  call extend(s:lines, ["</body>", "</html>"])
 else
-  exe "normal! a</pre>\n</body>\n</html>\e"
+  call extend(s:lines, ["</pre>", "</body>", "</html>"])
 endif
 
+exe s:newwin . "wincmd w"
+call setline(1, s:lines)
+unlet s:lines
 
 " Now, when we finally know which, we define the colors and styles
-if exists("s:html_use_css")
+if exists("g:html_use_css")
   1;/<style type="text/+1
 endif
 
@@ -777,7 +945,7 @@ endif
 " Normal/global attributes
 " For Netscape 4, set <body> attributes too, though, strictly speaking, it's
 " incorrect.
-if exists("s:html_use_css")
+if exists("g:html_use_css")
   if exists("g:html_no_pre")
     execute "normal! A\nbody { color: " . s:fgc . "; background-color: " . s:bgc . "; font-family: ". s:htmlfont ."; }\e"
   else
@@ -792,7 +960,7 @@ endif
 
 " Line numbering attributes
 if s:numblines
-  if exists("s:html_use_css")
+  if exists("g:html_use_css")
     execute "normal! A\n.lnr { " . s:CSS1(hlID("LineNr")) . "}\e"
   else
     execute '%s+^<span class="lnr">\([^<]*\)</span>+' . s:HtmlOpening(hlID("LineNr")) . '\1' . s:HtmlClosing(hlID("LineNr")) . '+g'
@@ -800,18 +968,22 @@ if s:numblines
 endif
 
 " Gather attributes for all other classes
-let s:idlist = strpart(s:idlist, 1)
-while s:idlist != ""
+let s:idlist_str = s:idlist
+unlet s:idlist
+let s:idlist = split(s:idlist_str, ',')
+if !s:html_no_progress && !empty(s:idlist)
+  let s:pgb = s:ProgressBar("Processing classes:", len(s:idlist),s:newwin)
+endif
+while !empty(s:idlist)
   let s:attr = ""
-  let s:col = stridx(s:idlist, ",")
-  let s:id = strpart(s:idlist, 0, s:col)
-  let s:idlist = strpart(s:idlist, s:col + 1)
+  let s:id = remove(s:idlist, 0)
   let s:attr = s:CSS1(s:id)
   let s:id_name = synIDattr(s:id, "name", s:whatterm)
+
   " If the class has some attributes, export the style, otherwise DELETE all
   " its occurences to make the HTML shorter
   if s:attr != ""
-    if exists("s:html_use_css")
+    if exists("g:html_use_css")
       execute "normal! A\n." . s:id_name . " { " . s:attr . "}"
     else
       execute '%s+<span class="' . s:id_name . '">\([^<]*\)</span>+' . s:HtmlOpening(s:id) . '\1' . s:HtmlClosing(s:id) . '+g'
@@ -822,7 +994,17 @@ while s:idlist != ""
       1;/<style type="text/+1
     endif
   endif
+
+  if !s:html_no_progress
+    call s:pgb.incr()
+    if s:pgb.needs_redraw
+      redrawstatus
+      let s:pgb.needs_redraw = 0
+      sleep 50m
+    endif
+  endif
 endwhile
+unlet s:idlist_str
 
 " Add hyperlinks
 %s+\(https\=://\S\{-}\)\(\([.,;:}]\=\(\s\|$\)\)\|[\\"'<>]\|&gt;\|&lt;\|&quot;\)+<a href="\1">\1</a>\2+ge
@@ -842,49 +1024,68 @@ endif
 %s:\s\+$::e
 
 " Restore old settings
+let &l:foldmethod = s:old_fdm
 let &report = s:old_report
 let &title = s:old_title
 let &icon = s:old_icon
 let &paste = s:old_paste
 let &magic = s:old_magic
 let @/ = s:old_search
+let &more = s:old_more
 exe s:orgwin . "wincmd w"
 let &l:et = s:old_et
 exe s:newwin . "wincmd w"
+exec 'resize' s:old_winheight
+let &l:winfixheight = s:old_winfixheight
 
 " Reset old <pre> settings
 if exists("s:old_html_no_pre")
-  let html_no_pre = s:old_html_no_pre
+  let g:html_no_pre = s:old_html_no_pre
   unlet s:old_html_no_pre
 elseif exists("g:html_no_pre")
-  unlet html_no_pre
+  unlet g:html_no_pre
 endif
 
+call setwinvar(s:orgwin,'&stl', s:origwin_stl)
+call setwinvar(s:newwin,'&stl', s:newwin_stl)
+let &ls=s:ls
+
 " Save a little bit of memory (worth doing?)
 unlet s:htmlfont
-unlet s:old_et s:old_paste s:old_icon s:old_report s:old_title s:old_search
-unlet s:whatterm s:idlist s:lnum s:end s:margin s:fgc s:bgc s:old_magic
+unlet s:old_et s:old_paste s:old_icon s:old_report s:old_title s:old_search s:old_magic s:old_more s:old_fdm s:old_winheight s:old_winfixheight
+unlet s:whatterm s:idlist s:lnum s:end s:margin s:fgc s:bgc
 unlet! s:col s:id s:attr s:len s:line s:new s:expandedtab s:numblines
-unlet! s:orgwin s:newwin s:orgbufnr s:idx s:i s:offset
+unlet! s:orgwin s:newwin s:orgbufnr s:idx s:i s:offset s:ls s:origwin_stl s:newwin_stl
 if !v:profiling
   delfunc s:HtmlColor
   delfunc s:HtmlFormat
   delfunc s:CSS1
-  if !exists("s:html_use_css")
+  if !exists("g:html_use_css")
     delfunc s:HtmlOpening
     delfunc s:HtmlClosing
   endif
+  if exists("g:html_dynamic_folds")
+    delfunc s:FoldCompare
+  endif
+
+  if !s:html_no_progress
+    delfunc s:ProgressBar
+    delfunc s:progressbar.paint
+    delfunc s:progressbar.incr
+    unlet s:pgb s:progressbar
+  endif
 endif
-silent! unlet s:diffattr s:difffillchar s:foldfillchar s:HtmlSpace s:LeadingSpace s:HtmlEndline s:firstfold s:foldcolumn
+
+unlet! s:new_lnum s:diffattr s:difffillchar s:foldfillchar s:HtmlSpace s:LeadingSpace s:HtmlEndline s:firstfold s:foldcolumn
 unlet s:foldstack s:allfolds s:foldId s:numcol
 
-if exists("s:html_dynamic_folds")
-  delfunc s:FoldCompare
-endif
+unlet! s:html_no_progress
 
-silent! unlet s:html_dynamic_folds s:html_hover_unfold s:html_use_css
+call tohtml#RestoreUserSettings(s:old_html_settings)
+unlet s:old_html_settings
 
 let &cpo = s:cpo_sav
-unlet s:cpo_sav
+unlet! s:cpo_sav
 
-" vim: noet sw=2 sts=2
+" Make sure any patches will probably use consistent indent
+"   vim: noet sw=2 sts=2