@@ -88,8 +88,9 @@ =head3 All output formats
8888
8989C<r > for right-aligned column
9090
91- C<p{width} > for a column with left-aligned paragraphs of fixed width.
92- The width needs to be absolute to work in all output formats.
91+ C<p{width} > for a column with left-aligned paragraphs of the given width.
92+ The width can be an absolute width or (unlike in LaTeX) a positive decimal number at most 1.
93+ If it is a decimal, it will be interpreted as a portion of the available width.
9394
9495C<X > for a column that expands to fill (see C<Xratio > below),
9596and will have left-aligned paragraphs
@@ -536,7 +537,8 @@ sub TableEnvironment {
536537 if ($main::displayMode eq ' TeX' ) {
537538 my $tabulartype = $hasX ? ' tabularx' : ' tabular' ;
538539 my $tabularwidth = $hasX ? " $tableOpts ->{Xratio}\\ linewidth" : ' ' ;
539- $rows = latexEnvironment($rows , $tabulartype , [ $tabularwidth , ' [t]' , $tableOpts -> {texalignment } ], ' ' );
540+ my $texalignment = $tableOpts -> {texalignment } =~ s / p\{ 0*(0(\.\d *)?|1(\. 0*)?)\} / p\{ $1 \\ linewidth\} / gr ;
541+ $rows = latexEnvironment($rows , $tabulartype , [ $tabularwidth , ' [t]' , $texalignment ], ' ' );
540542 $rows = prefix($rows , ' \centering%' ) if $tableOpts -> {center };
541543 $rows = prefix($rows , ' \renewcommand{\arraystretch}{' . ($tableOpts -> {padding }[0] + 1) . ' }' , ' ' );
542544 $rows = prefix($rows , ' \setlength{\tabcolsep}{' . ($tableOpts -> {padding }[1] * 10) . ' pt}' , ' ' );
@@ -566,16 +568,15 @@ sub TableEnvironment {
566568 $ptxmargins = " ${leftmargin} % ${rightmargin} %" ;
567569 $ptxwidth .= ' %' ;
568570 } elsif (!$tableOpts -> {center }) {
569- $ptxwidth = ' 100%' ;
570571 $ptxmargins = ' 0% 0%' ;
571572 }
572573 if ($tableOpts -> {LaYoUt }) {
573574 $rows = tag(
574575 $rows ,
575576 ' sbsgroup' ,
576577 {
577- width => $ptxwidth ,
578578 margins => $ptxmargins ,
579+ widths => $cols
579580 }
580581 );
581582 } elsif (!$tableOpts -> {LaYoUt }) {
@@ -584,13 +585,12 @@ sub TableEnvironment {
584585 $rows ,
585586 ' tabular' ,
586587 {
587- valign => ($tableOpts -> {valign } ne ' middle' ) ? $tableOpts -> {valign } : ' ' ,
588- bottom => $tableOpts -> {horizontalrules } ? ' minor' : ' ' ,
589- rowheaders => $tableOpts -> {rowheaders } ? ' yes' : ' ' ,
590- margins => $ptxmargins ,
591- width => $ptxwidth ,
592- left => $ptxleft ,
593- top => $ptxtop ,
588+ valign => ($tableOpts -> {valign } ne ' middle' ) ? $tableOpts -> {valign } : ' ' ,
589+ bottom => $tableOpts -> {horizontalrules } ? ' minor' : ' ' ,
590+ ' row-headers' => $tableOpts -> {rowheaders } ? ' yes' : ' ' ,
591+ width => $ptxwidth ,
592+ left => $ptxleft ,
593+ top => $ptxtop ,
594594 }
595595 );
596596 }
@@ -674,49 +674,87 @@ sub Cols {
674674 }
675675
676676 if ($main::displayMode eq ' PTX' ) {
677- my $ptxhalign = ' ' ;
678- $ptxhalign = ' center' if ($align -> {halign } eq ' c' );
679- $ptxhalign = ' right' if ($align -> {halign } eq ' r' );
680- my $ptxright = ' ' ;
681- $ptxright = getPTXthickness($align -> {right });
682- my $ptxtop = ' ' ;
683- $ptxtop = getPTXthickness($top );
684- my $ptxwidth = ' ' ;
685- $ptxwidth = getWidthPercent($align -> {width }) if $align -> {width };
686- $ptxwidth = ($tableOpts -> {Xratio } / $# $alignment * 100) . ' %'
687- if ($align -> {halign } eq ' X' );
688- $ptxwidth = getWidthPercent($width ) if $width ;
689- push (
690- @cols ,
691- tag(
692- ' ' , ' col' ,
693- {
694- halign => $ptxhalign ,
695- right => $ptxright ,
696- top => $ptxtop ,
697- width => $ptxwidth
698- }
699- )
700- );
677+ if ($tableOpts -> {LaYoUt }) {
678+ push @cols , ($align -> {width } ? getWidthPercent($align -> {width }) : ' %' );
679+ } else {
680+ my $ptxhalign = ' ' ;
681+ $ptxhalign = ' center' if ($align -> {halign } eq ' c' );
682+ $ptxhalign = ' right' if ($align -> {halign } eq ' r' );
683+ my $ptxright = ' ' ;
684+ $ptxright = getPTXthickness($align -> {right });
685+ my $ptxtop = ' ' ;
686+ $ptxtop = getPTXthickness($top );
687+ my $ptxwidth = ' ' ;
688+ $ptxwidth = getWidthPercent($align -> {width }) if $align -> {width };
689+ $ptxwidth = ($tableOpts -> {Xratio } / $# $alignment * 100) . ' %'
690+ if ($align -> {halign } eq ' X' );
691+ $ptxwidth = getWidthPercent($width ) if $width ;
692+ push (
693+ @cols ,
694+ tag(
695+ ' ' , ' col' ,
696+ {
697+ halign => $ptxhalign ,
698+ right => $ptxright ,
699+ top => $ptxtop ,
700+ width => $ptxwidth
701+ }
702+ )
703+ );
704+ }
701705 } else {
702706 my $htmlright = ' ' ;
703707 $htmlright .= css(' border-right' , ' solid 2px' )
704708 if ($i == 1 && $tableOpts -> {rowheaders } && $tableOpts -> {headerrules });
705709 $htmlright .= css(' border-right' , getRuleCSS($align -> {right }));
706710 my $htmltop = ' ' ;
707711 $htmltop .= css(' border-top' , getRuleCSS($top ));
712+ my $htmlwidth = ' ' ;
713+ if ($align -> {width }) {
714+ $htmlwidth = css(' width' , $align -> {width });
715+ $htmlwidth = css(' width' , getWidthPercent($align -> {width }))
716+ if ($align -> {width } =~ / ^0*(0(\.\d *)?|1(\. 0*)?)$ / );
717+ }
708718
709719 # $i starts at 1, but columncss indexing starts at 0
710720 my $htmlcolcss = css($columnscss -> [ $i - 1 ]);
711721 if ($align -> {tex } =~ / \\ columncolor(\[ HTML\] )?\{ (.*?)[}!]/ ) {
712722 $htmlcolcss .= css(' background-color' , ($1 ? ' #' : ' ' ) . $2 );
713723 }
714724
715- push (@cols , tag(' ' , ' col' , { style => " ${htmlright}${htmltop}${htmlcolcss} " }));
725+ push (@cols , tag(' ' , ' col' , { style => " ${htmlright}${htmltop}${htmlcolcss}${htmlwidth} " }));
716726 }
717727
718728 }
719729
730+ if ($main::displayMode eq ' PTX' && $tableOpts -> {LaYoUt }) {
731+ my @decimalcols = map { substr $_ , 0, -1 } @cols ;
732+ my $total = 0;
733+ my $count = 0;
734+ for (@decimalcols ) {
735+ if ($_ eq ' ' ) {
736+ $count ++;
737+ } else {
738+ $total += $_ ;
739+ }
740+ }
741+ # determine if somewhere in the alignment there are X columns
742+ my $hasX = 0;
743+ for my $align (@$alignment ) {
744+ if ($align -> {halign } eq ' X' ) {
745+ $hasX = 1;
746+ last ;
747+ }
748+ }
749+ my $width = ($hasX ? $tableOpts -> {Xratio } * 100 : 100);
750+ my $fill = ($count != 0) ? int (($width - $total ) / $count * 10**4) / 10**4 : 0;
751+ for (@decimalcols ) {
752+ $_ = $fill if ($_ eq ' ' );
753+ }
754+ @cols = map { $_ . ' %' } @decimalcols ;
755+ return join (' ' , @cols );
756+ }
757+
720758 return join (" \n " , @cols );
721759
722760}
@@ -805,52 +843,11 @@ sub Rows {
805843 if (!$ptxleft && $rowArray -> [0]{halign } && $alignment -> [0]{left });
806844
807845 if ($tableOpts -> {LaYoUt }) {
808- my $ptxwidthsum = 0;
809- my $ptxautocols = $#alignment ;
810- for my $j (1 .. $#alignment ) {
811- if ($rowArray -> [ $j - 1 ]{width }) {
812- $ptxwidthsum +=
813- substr getWidthPercent($tableArray -> [ $j - 1 ]{width }),
814- 0, -1;
815- $ptxautocols -= 1;
816- } elsif ($alignment -> [$j ]{width }) {
817- $ptxwidthsum += substr getWidthPercent($alignment -> [$j ]{width }), 0, -1;
818- $ptxautocols -= 1;
819- }
820- }
821-
822- # determine if somewhere in the overall alignment, there are X columns
823- my $hasX = 0;
824- for my $align (@$alignment ) {
825- if ($align -> {halign } eq ' X' ) {
826- $hasX = 1;
827- last ;
828- }
829- }
830- my $leftoverspace =
831- (($hasX ) ? $tableOpts -> {Xratio } * 100 : 100) - $ptxwidthsum ;
832- my $divvyuptherest = 0;
833- $divvyuptherest = int ($leftoverspace / $ptxautocols * 10000) / 10000
834- unless ($ptxautocols == 0);
835- my @ptxwidths ;
836- for my $j (1 .. $#alignment ) {
837- if ($rowOpts -> [ $j - 1 ]{width }) {
838- push (@ptxwidths , getWidthPercent($rowOpts -> [ $j - 1 ]{width }));
839- } elsif ($alignment -> [$j ]{width }) {
840- push (@ptxwidths , getWidthPercent($alignment -> [$j ]{width }));
841- } else {
842- push (@ptxwidths , $divvyuptherest . ' %' );
843- }
844- }
845-
846- my $ptxwidths = join (" " , @ptxwidths );
847846 $row = tag(
848847 $row ,
849848 ' sidebyside' ,
850849 {
851- valign => ($valign ) ? $valign : $tableOpts -> {valign },
852- margins => ' 0% 0%' ,
853- widths => $ptxwidths ,
850+ valign => ($valign ) ? $valign : $tableOpts -> {valign },
854851 }
855852 );
856853 } else {
@@ -954,6 +951,7 @@ sub Row {
954951 || ($tableOpts -> {rowheaders } && $tableOpts -> {headerrules } && $i == 0))
955952 {
956953 my $columntype = $cellOpts -> {halign };
954+ $columntype = $columntype =~ s / p\{ 0*(0(\.\d *)?|1(\. 0*)?)\} / p\{ $1 \\ linewidth\} / gr ;
957955 $columntype = $cellAlign -> {halign } // ' l' unless $columntype ;
958956 $columntype = ' p{' . $tableOpts -> {Xratio } / ($# $rowArray + 1) . " \\ linewidth}"
959957 if ($columntype eq ' X' );
@@ -1038,8 +1036,11 @@ sub Row {
10381036 if ($cellAlign -> {halign } eq ' c' );
10391037 $css .= css(' text-align' , ' right' )
10401038 if ($cellAlign -> {halign } eq ' r' );
1041- $css .= css(' width' , $cellAlign -> {width })
1042- if ($cellAlign -> {width });
1039+ if ($cellAlign -> {width } =~ / ^0*(0(\.\d *)?|1(\. 0*)?)$ / ) {
1040+ $css .= css(' width' , getWidthPercent($1 ));
1041+ } elsif ($cellAlign -> {width }) {
1042+ $css .= css(' width' , $cellAlign -> {width });
1043+ }
10431044 $css .= css(' font-weight' , ' bold' )
10441045 if ($cellAlign -> {tex } =~ / \\ bfseries/ );
10451046 $css .= css(' font-style' , ' italic' )
@@ -1075,8 +1076,11 @@ sub Row {
10751076 if ($cellOpts -> {halign } =~ / ^c/ );
10761077 $css .= css(' text-align' , ' right' ) if ($cellOpts -> {halign } =~ / ^r/ );
10771078 $css .= css(' text-align' , ' left' ) if ($cellOpts -> {halign } =~ / ^p/ );
1078- $css .= css(' width' , $1 )
1079- if ($cellOpts -> {halign } =~ / ^p\{ ([^}]*?)}/ );
1079+ if ($cellOpts -> {halign } =~ / ^p\{ 0*(0(\.\d *)?|1(\. 0*)?)}/ ) {
1080+ $css .= css(' width' , getWidthPercent($1 ));
1081+ } elsif ($cellOpts -> {halign } =~ / ^p\{ ([^}]*?)}/ ) {
1082+ $css .= css(' width' , $1 );
1083+ }
10801084 $css .= css(' font-weight' , ' bold' )
10811085 if ($cellOpts -> {tex } =~ / \\ bfseries/ );
10821086 $css .= css(' font-style' , ' italic' )
@@ -1581,29 +1585,39 @@ sub getPTXthickness {
15811585}
15821586
15831587sub getWidthPercent {
1584- my $absWidth = shift ;
1585- my $x = 0;
1586- my $unit = ' cm' ;
1587- if ($absWidth =~ / ^(\.\d +|\d +\. ?\d *)\s *(\w +)/ ) {
1588+ my $width = shift ;
1589+ return $width if (substr ($width , -1) eq ' %' );
1590+ return $width * 100 . ' %' if ($width =~ / ^0*(0(\.\d *)?|1(\. 0*)?)$ / );
1591+ my $x = 0;
1592+ my $unit = ' cm' ;
1593+ if ($width =~ / ^(\.\d +|\d +\. ?\d *)\s *(\w +)$ / ) {
15881594 $x = $1 ;
15891595 $unit = $2 ;
15901596 }
1591- my %convert_to_cm = (
1592- ' pt' => 1 / 864 * 249 / 250 * 12 * 2.54,
1593- ' mm' => 1 / 10,
1594- ' cm' => 1,
1595- ' in' => 2.54,
1596- ' ex' => 0.15132,
1597- ' em' => 0.35146,
1598- ' mu' => 0.35146 / 8,
1599- ' sp' => 1 / 864 * 249 / 250 * 12 * 2.54 / 65536,
1600- ' bp' => 2.54 / 72,
1601- ' dd' => 1 / 864 * 249 / 250 * 12 * 2.54 * 1238 / 1157,
1602- ' pc' => 1 / 864 * 249 / 250 * 12 * 2.54 * 12,
1603- ' cc' => 1 / 864 * 249 / 250 * 12 * 2.54 * 1238 / 1157 * 12,
1604- ' px' => 2.54 / 72,
1597+ my %convert_to_pt = (
1598+ # units with related absolute defintions
1599+ # the following are as TeX defines them
1600+ pt => 1,
1601+ pc => 12,
1602+ in => 72.27,
1603+ mm => 72.27 / 25.4,
1604+ cm => 72.27 / 2.54,
1605+ sp => 1 / 65536,
1606+ dd => 1238 / 1157,
1607+ cc => 12 * 1238 / 1157,
1608+ bp => 72.27 / 72,
1609+ # CSS defines 1 px to be 1/96 of an inch
1610+ # note that px is not a legal unit in TeX
1611+ px => 72 / 96,
1612+ # units relative to font
1613+ # the following are based on TeX default font
1614+ # (10pt Computer Modern)
1615+ em => 10.00002,
1616+ ex => 4.30554,
16051617 );
1606- return (int ($x * $convert_to_cm {$unit } / (6.25 * 2.54) * 10000) / 100) . ' %' ;
1618+ # This is only used for PTX output, and a PTX document's default width is 340pt.
1619+ # We offer a percent with up to six significant digits
1620+ return (int ($x * $convert_to_pt {$unit } / 340 * 10**6) / 10**4) . ' %' ;
16071621}
16081622
16091623sub hrule {
0 commit comments