% \iffalse % Copyright 2012-2022 Jiro Senju % % This package is free software; you can redistribute it and/or modify % it under the terms of the GNU General Public License as published by % the Free Software Foundation; either version 2 of the License, or % any later version. % % This package is distributed in the hope that it will be useful, % but WITHOUT ANY WARRANTY; without even the implied warranty of % MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the % GNU General Public License for more details. % % You should have received a copy of the GNU General Public License % along with this package. If not, see . % %\NeedsTeXFormat{LaTeX2e} %\ProvidesPackage{dvisirule}% %[2022/09/12 v2.1 dvisirule] % %<*driver> \documentclass[draft]{ltxdoc} % \input{fonts} \usepackage[dvipdfmx,final]{graphicx} \usepackage[final]{listings} \lstset{basicstyle=\small\ttfamily, language=TeX, columns=[c]flexible, tabsize=4, %frame=tb, keepspaces=true, %lineskip=-.1ex, belowskip=\medskipamount} \usepackage{multicol} \usepackage{needspace} % % hyperref should come last \usepackage[dvipdfmx,final,pdfusetitle]{hyperref} % CJKbookmarks=true % bookmarksdepth=section % pdffitwindow=true % pdfpagetransition=Dissolve % pdfstartview=FitB \hypersetup{ hyperfootnotes=false, colorlinks=true, linkcolor=blue, % anchorcolor=black, % citecolor=black, % urlcolor=black, bookmarks=true, bookmarksnumbered=true, setpagesize=false, %pdftitle={}, %pdfauthor={}, pdfpagelayout=SinglePage, pdfpagemode=UseOutlines, pdfstartview=FitH } % \usepackage{\jobname} % \makeatletter % \def\meta@font@select{\slshape} % \def\fps@table{htbp} \def\fps@figure{htbp} % \newcommand{\NoDescription}{\vspace*{-.9\baselineskip}} % % \EnableCrossrefs \DisableCrossrefs \CodelineIndex % \RecordChanges % \begin{document} \MakeShortVerb{\|} \DocInput{\jobname.dtx} \end{document} % % \fi % %\GetFileInfo{\jobname.sty} % % \title{{\spaceskip=1ex\textsf{\jobname} package \fileversion\\ % (\texttt{sitabular} environment)}} % \author{\texttt{jiro1010senju at gmail dot com}} % \date{\filedate} % \maketitle % % Superimpose the hidden\slash covered |\hline| and |\vline| in a LaTeX % tabular\slash colortbl environment. % % %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% % \section{Motivation} % % Over a decade ago, I need to write down some latex tables in color. % Not so many colors used, just two background colors. % One is white as a usual background, and the other is gray which is % to be easier to distinguish the preceding and succeeding rows from each % other. % In other words, the tables have two different row colors one after the % other. % % Fortunately we have |\rowcolors| from |xcolor.sty| and it is really % helpful, except one thing. % The problem is the lines (|\hline|, |\cline| and others) are not shown % in the PDF viewer. % Technically speaking, if we zoom in\slash out, then the lines appear, % but not always. % If I change the thickness of the lines, I can always see them. % But it is too ugly. % It seems highly depending on the monitor resolution and the PDF viewer's % internal calculation of the coordinates. % Even if I set the width of the lines to 4pt, it can be only one pixel on % the screen. % It is totally up to the environment of the viewer. % % To address this issue, I guessed the cause is the order of drawing % lines and painting the row background color. % E.g. drawing lines first, and then painting the background color next. % In that case, the background color may hide the lines due to the % internal rounding-up\slash down the calculated coordinates. % % Some TeXnicians may be able to modify the tabular\slash colortbl % environment, and postpone drawing the lines after completing the % background color. % But I don't have such TeXnique. % I had considered a few ways to get what I want, % and my solution is to draw the lines again at the end of the page by a % new dviware. % % %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% % \section{Basic approach} % % \begin{enumerate} % \item % In |.tex| (actually |.sty|), embed the markers to represent the % begin\slash end of a line. % % \item % A new dviware searches the embedded markers, if found, remembers the % coordinates in the DVI page of them, and the offset in the DVI file. % % \item % When the dviware reaches the end of the page, it copies the DVI % instructions from the marker to the end of the page. % I mean appending the line instructions to the page. % And replace the the markers by NOP at the original position, to keep % silent other dviwares. % \end{enumerate} % % Now the lines are re-drawn over the row background color, and we can % always see them clearly. % % %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% % \section{Compile \& Install} % % \begin{lstlisting}[gobble=2,xleftmargin=1em] % $ cd $this_dir/src % $ configure -q % $ cd .. % $ make -s Dir=/tmp % \end{lstlisting} % % Then you will get these files. % % \begin{lstlisting}[gobble=2,xleftmargin=1em] % /tmp/dvisirule % /tmp/dvisirule-bin % /tmp/dvisirule-expg.mk % /tmp/dvisirule-marker.awk % /tmp/dvisirule-pgnum.awk % /tmp/dvisirule.sty % \end{lstlisting} % % Now you can install them by % % \begin{lstlisting}[gobble=2,xleftmargin=1em] % $ make InstallBase=/tmp/texmf-dist % \end{lstlisting} % % Here |${InstallBase}| is a make-variable which is referred by other make-variables. % % \begin{lstlisting}[gobble=2,xleftmargin=1em] % InstallBin ?= ${InstallBase}/bin % InstallLib ?= ${InstallBase}/lib % InstallSty ?= ${InstallBase}/lib/texinputs % \end{lstlisting} % % and the files will be installed to these dirs. % % \begin{lstlisting}[gobble=2,xleftmargin=1em] % ${InstallBin}/dvisirule % % ${InstallLib}/dvisirule-bin % ${InstallLib}/dvisirule-expg.mk % ${InstallLib}/dvisirule-marker.awk % ${InstallLib}/dvisirule-pgnum.awk % % ${InstallSty}/dvisirule.sty % \end{lstlisting} % % Please note that these installed dirs have to be recognized by % |Kpathsea| since the main |sh| script |dvisirule| searches these % sub-files by |kpsewhich(1)|. % % %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% % \section{Usage} % % |dvisirule.sty| is provided, and |sitabular| environment is a wrapper % of |tabular| (including |colortbl|. You should include |xcolor.sty| % or something BEFORE this pkg). % The tabular syntax are kept, so you can use it by simply replacing |tabular| by % |sitabular|. % But it is not a main part of this package. % |sitabular| does only embedding the markers and stores the % page number to an external file. % The main part of this packages is |dvisirule| (shell script) and the % internal command |dvisirule-bin| (C\: program). % So the usage here is not only including |dvisirule.sty| and % |\begin{sitabular}|, but also run |dvisirule| after LaTeX compilation. % % \begin{lstlisting}[gobble=2,xleftmargin=1em] % (a.tex) % \usepackage{dvisirule} % % \begin{sitabular} ... \end{sitabular} % % latex a.tex % cp -p a.dvi a.dvi.save % dvisirule a.dvi a-si.dvi % mv a-si.dvi a.dvi % \end{lstlisting} % % You don't want run |dvisirule| command unconditionally?\, % Good.\, % |dvisirule.sty| creates and writes a file the page numbers which % contain the line to % be superimposed, so when the size of that file is zero, you can % skip |dvisirule| command. % % \begin{lstlisting}[gobble=2,xleftmargin=1em] % latex a.tex % if [ -s a.sirule ] % then % cp -p a.dvi a.dvi.save % dvisirule a.dvi a-si.dvi % mv a-si.dvi a.dvi % fi % \end{lstlisting} % % %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% % \clearpage % \section{Demo} % % \lstinputlisting{/tmp/demoprint} % % \includegraphics{/tmp/demo.pdf} % \bigskip % % Tested on TeX Live 2019. % \clearpage % % %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% % \section{Limitation} % % |\hline|\, supports |\hline\hline| sequence, which means if followed by % another |\hline|, it inserts |\vskip\doublerulesep|. % This feature doesn't work in |sitabular|. It results a single thick % |\hline|. Use |\hhline| (from |hhline.sty|) instead. % % %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% % \section{\texttt{dvisirule} script and sub-programs} % % The main script runs |dvitype| and other % commands internally. You may want to replace some commands by other % language specific variants. For |dvitype| command, you can set a % environment variable, |$DVITYPE|. If it is set, the main script uses % |$DVITYPE| instead of |dvitype|. Here is an example. % % \begin{lstlisting}[gobble=2,xleftmargin=1em] % DVITYPE=pdvitype % export DVITYPE % dvisirule a.dvi % \end{lstlisting} % % There are two other commands in the same group, |dviselect| % (|$DVISELECT|) and |dviconcat| (|$DVICONCAT|). % % Also the main script refers to |$TMPDIR| environment variable. It % specifies a directory where the extracted DVI page(s) are stored temporarily. % If it is not set, |/tmp| is used. % % \subsection{\texttt{dvisirule} --- main shell script} % % Syntax\,: % \lstinputlisting[xleftmargin=2em]{/tmp/help.txt} % % \begin{enumerate} % \item % Accepts |.dvi|, and searches |.sirule|. % If |.sirule| doesn't exist, exits with an error. % If it exists but the size is zero, then exits with a success. % \item % By an AWK script, |dvisirule-pgnum.awk|, splits |.dvi| per page, % dividing those who contains |sitabular| and who doesn't. % Sequential pages who doesn't contain |sitabular| are grouped into a % single file. % \item % (for each extracted page which contains |sitabular|) % \par % By an AWK script, |dvisirule-marker.awk| finds and extracts the % markers from the page and the DVI line instructions from it. % \item % (for each extracted page which contains |sitabular|) % \par % By a binary program |dvisirule-bin|, copies the line instructions % surrounded by the markers to the end of the page, and replaces the % markers and the line instructions at the original position (in the % DVI page) by NOP instruction, to stop other dviwares complain about % the marker. % \item % Concatenate all pages, and make the final |.dvi|. % \end{enumerate} % % \subsection{\texttt{dvisirule-bin} --- sub binary} % % This command has two inputs, one is a DVI file and the other is the % output from |dvisirule-marker.awk|. % The AWK script parses an output of |dvitype| for a single DVI page, and % extract and prints SETRULE\slash PUTRULE instructions surrounded by the % markers along with the color, the coordinates, and the offset in the DVI % file. % % |dvisirule-bin| command parses the output of the AWK script, and copies % those SETRULE\slash PUTRULE instructions to the end of the page. The % markers and the instructions at the original offset are replaced by NOP % instruction, so that other dviwares don't complain about that such as % ``Unknown special'' or something. At last, |dvisirule-bin| creates and % writes a new DVI file. % % You may be wondering is the AWK script really necessary? Why doesn't % |dvisirule-|\allowbreak|bin| parse the DVI file by itself\,? % Good point. It's just because I'm lazy. I can understand if a single % binary operates all these processing, then the required cost (including % CPU time) will be smaller. The performance will not be bad. But it is a % run-rime performance. The lazy of me wants the develop-time performance % too. % % Roughly speaking, splitting and parsing for each DVI page, and copying % the instructions should be done concurrently. If all were implemented by % C including multi-threading, the technical hurdle would be rather high. % So I chose scripting for splitting and parsing. It can be run % concurrently by |"make -j NCPU"|. Since DVI is a binary format, I had to % implement it by C. It is OK, and the single-threaded C program can be % run in parallel by |"make -j NCPU"| too. % This is my laziness. % % \StopEventually % % %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% % \section{Implementation} % % \subsection{\texttt{.sirule} file} % % \DescribeMacro{\si@RulePageW} % \DescribeMacro{\si@RulePage} % Create a file and store the absolute page numbers which contain % |sitabular|. % \smallskip % % \begin{macrocode} \RequirePackage{zref-abspage} % \newwrite\si@RulePageW \immediate\openout\si@RulePageW=\jobname.sirule%\relax \newcommand{\si@RulePage}{%\immediate \write\si@RulePageW{\theabspage}% } % \end{macrocode} % % \subsection{marker} % % \DescribeMacro{\si@bol} % \DescribeMacro{\si@eol} % Begin/End markers of a line. % \smallskip % % \begin{macrocode} \newcounter{si@rule} \newcommand{\si@bol}{% \stepcounter{si@rule}% \special{sirule BOL\space\thesi@rule}% \si@RulePage% } \newcommand{\si@eol}{% \si@RulePage% \special{sirule EOL\space\thesi@rule}% \addtocounter{si@rule}{-1}% } % \end{macrocode} % % \subsection{\texttt{\textbackslash hline} and \texttt{\textbackslash vline}} % % \DescribeMacro{\si@hline} % \DescribeMacro{\si@vline} % Originally |\hline| issues |\futurelet| internally to support % |\hline\hline| sequence. But |\si@hline| issues |\si@eol| just after % the original |\hline|. So |\hline\hline| would not work % expectedly. Use |\hhline| (|hhline.sty|) instead. % \smallskip % % \begin{macrocode} \let\si@Ohline=\hline \newcommand{\si@hline}{% \noalign{\si@bol}% \si@Ohline% \noalign{\si@eol}% } \let\si@Ovline=\vline \newcommand{\si@vline}{% \si@bol% \si@Ovline% \si@eol% } % \end{macrocode} % % \subsection{\texttt{\textbackslash hhline} if loaded} % % \DescribeMacro{\si@hline} % \DescribeMacro{\si@vline} % \NoDescription % \smallskip % % \begin{macrocode} \newif\ifsi@hhline \@ifundefined{hhline}{}{% \global\si@hhlinetrue% \global\let\si@Ohhline=\hhline% \newcommand{\si@hhline}[1]{% \noalign{\si@bol}% \si@Ohhline{#1}% \noalign{\si@eol}% }% } % \end{macrocode} % % \subsection{\texttt{sitabular} environment} % % \DescribeEnv{sitabular} % \smallskip % % \begin{macrocode} \@ifundefined{newcolumntype}{% \global\let\newcolumntype=\@gobbletwo% }{} \let\si@Otabular=\tabular \let\endsi@Otabular=\endtabular \newenvironment{sitabular}[1]{% \def\hline{\si@hline}% \ifsi@hhline\def\hhline{\si@hhline}\fi% \newcolumntype{|}{!{\si@vline}}% \begin{si@Otabular}{#1}% }{% \end{si@Otabular}% } % \end{macrocode} % % \subsection{\texttt{silongtable} environment if loaded} % % \DescribeEnv{silongtable} % \smallskip % % \begin{macrocode} \@ifclassloaded{longtable}{}{% \global\let\si@OLT@hline=\LT@hline% \newcommand{\si@LT@hline}{% \noalign{\si@bol}% \si@OLT@hline% \noalign{\si@eol}% }% \let\si@Olongtable=\longtable% \let\endsi@Olongtable=\endlongtable% \newenvironment{silongtable}[1]{% \def\LT@hline{\si@LT@hline}% \def\si@Ohline{\hline}% \def\hline{\si@hline}% \ifsi@hhline\def\hhline{\si@hhline}\fi% \newcolumntype{|}{!{\si@vline}}% \begin{si@Olongtable}{#1}% }{% \end{si@Olongtable}% }% } % \end{macrocode} %\Finale