cortav  Diff

Differences From Artifact [ab8e0fd21b]:

To Artifact [62c90e9915]:


    40     40   			if me.linbuf == nil then
    41     41   				me.linbuf = ss.strac()
    42     42   			end
    43     43   			me.linbuf(text)
    44     44   		end;
    45     45   		txt = function(me, str, ...)
    46     46   			if str == nil then return end
           47  +         if me.linbuf == nil then
           48  +	         -- prevent unwanted linebreaks
           49  +	         str = str:gsub('^%s+','')
           50  +         end
    47     51   			me:raw(gsan(str))
    48     52   			-- WARN this will cause problems if str is ever allowed to
    49     53   			-- include a line break. we can sanitize by converting
    50     54   			-- every line break into a new entry in the table, but i
    51     55   			-- don't think it should be possible for a \n to reach us
    52     56   			-- at this point, so i'm omitting the safety check as it
    53     57   			-- would involve an excessive hit to performance
................................................................................
    61     65   			me:flush()
    62     66   			me:txt(...)
    63     67   		end;
    64     68   		req = function(me, r)
    65     69   			me:flush()
    66     70   			table.insert(me.lines, '.'..r)
    67     71   		end;
           72  +		sreq = function(me, r)
           73  +			me:flush()
           74  +			table.insert(me.lines, "'"..r)
           75  +		end;
    68     76   		esc = function(me, e)
    69     77   			me:raw('\\' .. e)
    70     78   		end;
           79  +      draw = function(me, args)
           80  +         for _,v in ipairs(args) do
           81  +				me:esc("D'" .. v .. "'")
           82  +         end
           83  +      end;
    71     84   		flush = function(me)
    72     85   			if me.linbuf ~= nil then
    73     86   				local line = me.linbuf:compile()
    74     87   				local first = line:sub(1,1)
    75     88   				-- make sure our lines aren't accidentally interpreted
    76     89   				-- as groff requests. groff is kinda hostile to script
    77     90   				-- generation, huh?
................................................................................
   163    176   		};
   164    177   		color = {'.color'};
   165    178   		insert = {};
   166    179   		footnote = {
   167    180   			'.de footnote-blank';
   168    181   			'.  sp 0.25m';
   169    182   			'..';
          183  +
   170    184   			'.ev footnote-env';
   171    185   			'.  ps 8p';
   172    186   			'.  in 0.5c';
   173         -			'.  blm footnote-blank';
   174    187   			'.ev';
          188  +
   175    189   			'.de footnote-print';
   176    190   -- 			'.  sp |\\\\n[.p]u-\\\\n[footnote-pos]u';
   177    191   			'.  sp 0.5c';
   178    192   			'.  ev footnote-env';
          193  +			'.    blm footnote-blank';
   179    194   			'.    fn';
          195  +			'.    blm np';
   180    196   			'.  ev';
   181    197   			'.  rm fn';
   182    198   			'.  nr footnote-pos 0';
   183         -			-- move the trap past the bottom of the page so it's not
          199  +			-- move the trap past the top of the page so it's not
   184    200   			-- invoked again until more footnotes have been assembled
   185         -			'.  ch footnote-print |\\\\n[.p]u+10';
          201  +			'.  ch footnote-print |-1000';
   186    202   			'.  bp';
   187    203   			'..';
          204  +
   188    205   			'.wh |\\n[.p]u footnote-print';
   189    206   		};
   190    207   		root = {
   191    208   		-- these are macros included in all documents
   192    209   		-- page offset is hideously broken and unusable; we
   193    210   		-- zero it out so we can use .in to control indents
   194    211   		-- instead. note that the upshot of this is we need
   195    212   		-- to manually specify the indent in every other
   196    213   		-- environment from now on, .evc doesn't seem to cut it
   197    214   		-- set up the page title environment & trap
   198    215   			"'in 2c";
   199         -			"'ll 18c";
          216  +			"'ll 19.5c";
   200    217   			"'po 0";
   201    218   			"'ps 13p";
   202    219   			"'vs 15p";
   203    220   			".ev pgti";
   204    221   			".  evc 0";
   205    222   			".  fam H";
   206    223   			".  ps 10pt";
................................................................................
   212    229   			'.  lt 19c';
   213    230   			".  tl '\\\\*[doctitle]'\\fB\\\\*[title]\\f[]'%'";
   214    231   			'.  po 0';
   215    232   			".  br";
   216    233   			'.  ev';
   217    234   			'.  sp 1.2c';
   218    235   			'..';
   219         -			'.wh 0 ph';
   220    236   			'.de np';
   221         -			'.  sp 0.2c';
          237  +			'.  sp 0.6m';
   222    238   			'..';
   223         -			'.blm np'
          239  +			'.blm np';
          240  +			'.wh 0 ph';
   224    241   
   225    242   		};
   226    243   	}
   227    244   	rs.macsNeeded = {
   228    245   		order = {};
   229    246   		map = {};
   230    247   		count = 0;
................................................................................
   377    394   			elseif spanRenderers[v.kind] then
   378    395   				spanRenderers[v.kind](rc, v, b, sec)
   379    396   			end
   380    397   		end
   381    398   	end
   382    399   
   383    400   	local blockRenderers = {}
          401  +	blockRenderers['horiz-rule'] = function(rc, b, sec)
          402  +		rc.prop.margin = { top = 0.3 }
          403  +		rc.prop.underline = 0.1
          404  +	end
   384    405   	function	blockRenderers.label(rc, b, sec)
   385    406   		if ct.sec.is(b.captions) then
   386    407   			local sizes = {36,24,12,8,4,2}
   387         -			local margins = {0,5,2,1,0.5}
          408  +			local margins = {0,3}
   388    409   			local dedents = {2.5,1.3,0.8,0.4}
          410  +			local uls = {3,1.5,0.5,0.25}
   389    411   			rc.prop.dsz = sizes[b.captions.depth] or 10
   390         -			rc.prop.underline = b.captions.depth < 4
          412  +			rc.prop.underline = uls[b.captions.depth]
   391    413   			rc.prop.bold = b.captions.depth > 3
   392    414   			rc.prop.margin = {
   393         -				top = margins[b.captions.depth] or 0;
          415  +				top = margins[b.captions.depth] or 1;
   394    416   				bottom = 0.1;
   395    417   			}
          418  +			rc.prop.vassure = rc.prop.dsz+70;
   396    419   			rc.prop.indent = -(dedents[b.captions.depth] or 0)
   397         -			rc.prop.underline = true
   398    420   			rc.prop.chtitle = collectText(rc, b.spans, b.spec):compile()
   399    421   			if b.captions.depth == 1 then
   400    422   				rc.prop.breakBefore = true
   401    423   			end
   402    424   			rs.renderSpans(rc, b.spans, b, sec)
   403    425   		else
   404    426   			ss.bug 'tried to render label for an unknown object type':throw()
................................................................................
   419    441   	local skippedFirstPagebreak = doc.secorder[1]:visible()
   420    442   	local deferrer = ss.declare {
   421    443   		ident = 'groff-deferrer';
   422    444   		mk = function(buf) return {ops={}, tgt=buf} end;
   423    445   		fns = {
   424    446   			esc = function(me, str) table.insert(me.ops, {0, str}) end;
   425    447   			req = function(me, str) table.insert(me.ops, {1, str}) end;
          448  +			draw = function(me, lst) table.insert(me.ops,{2, lst}) end;
   426    449   			flush = function(me)
   427    450   				for i=#me.ops,1,-1 do
   428    451   					local d = me.ops[i]
   429    452   					if d[1] == 0 then
   430    453   						me.tgt:esc(d[2])
   431    454   					elseif d[1] == 1 then
   432    455   						me.tgt:req(d[2])
          456  +					elseif d[1] == 2 then
          457  +						me.tgt:draw(d[2])
   433    458   					end
   434    459   				end
   435    460   				me.ops = {}
   436    461   			end;
   437    462   		};
   438    463   	}
   439    464   	function rs.emitSpan(gtxt, s)
................................................................................
   458    483   		else
   459    484   			gtxt:txt(s.txt)
   460    485   		end
   461    486   		defer:flush()
   462    487   		if s.div then
   463    488   			for div, body in pairs(s.div) do
   464    489   				if div == 'fn' then
   465         -					gtxt:req 'ev footnote-env'
          490  +					gtxt:sreq 'ev footnote-env'
   466    491   				end
   467         -				gtxt:req('boxa '..div)
          492  +				gtxt:sreq('boxa '..div)
   468    493   				gtxt:txt(body)
   469    494   				gtxt:raw '\n'
   470         -				gtxt:req 'boxa'
          495  +				gtxt:sreq 'boxa'
   471    496   				if div == 'fn' then
   472         -					gtxt:req 'ev'
   473         -					gtxt:req 'nr footnote-pos (\\n[footnote-pos]u+\\n[dn]u)'
   474         -					gtxt:req 'ch footnote-print -(\\n[footnote-pos]u+1c)'
          497  +					gtxt:sreq 'ev'
          498  +					gtxt:sreq 'nr footnote-pos (\\n[footnote-pos]u+\\n[dn]u)'
          499  +					gtxt:sreq 'ch footnote-print -(\\n[footnote-pos]u+1.5c)'
   475    500   				end
   476    501   			end
   477    502   		end
   478    503   	end
   479    504   	function rs.emitBlock(gtxt, b)
   480    505   		local didfinalbreak = false
   481    506   		local defer = deferrer(gtxt)
................................................................................
   485    510   		end
   486    511   		if ln.breakBefore then
   487    512   			if skippedFirstPagebreak then
   488    513   				gtxt:req 'bp'
   489    514   			else
   490    515   				skippedFirstPagebreak = true
   491    516   			end
          517  +		elseif ln.vassure then
          518  +			gtxt:req(string.format('if (\\n[.t]u < %sp) .bp',ln.vassure))
   492    519   		end
   493    520   		if ln.indent then
   494    521   			if ln.indent < 0 then
   495    522   				gtxt:req('in '..tostring(ln.indent)..'m')
   496    523   				defer:req 'in'
   497    524   				gtxt:req('ll +'..tostring(-ln.indent)..'m')
   498    525   				defer:req 'll'
................................................................................
   505    532   		if ln.margin then
   506    533   			if ln.margin.top then
   507    534   				gtxt:req(string.format('sp %sm', ln.margin.top))
   508    535   			end
   509    536   		end
   510    537   
   511    538   		if ln.underline then
   512         -			defer:esc("D'l \\n[.ll]u-\\n[.in]u 0'")
   513         -			defer:esc"v'-0.5'"
   514    539   			defer:req'br'
          540  +			defer:draw {
          541  +				"t "..tostring(ln.underline).."p";
          542  +				"l \\n[.ll]u-\\n[.in]u 0";
          543  +			}
          544  +			defer:esc("h'-" .. tostring(ln.underline) .. "p'")
          545  +			defer:esc"v'-0.5'"
   515    546   		end
   516    547   
   517    548   		if ln.dsz and ln.dsz > 0 then
   518    549   			gtxt:req('ps +' .. tostring(ln.dsz) .. 'p')
   519    550   			defer:req('ps -' .. tostring(ln.dsz) .. 'p')
   520    551   		elseif ln.sz or ln.dsz then
   521    552   			if ln.sz and ln.sz <= 0 then