%%
%% This is file 'bxpapersize.sty'.
%%
%% Copyright (c) 2016-2022  Takayuki YATO (aka. "ZR")
%%   GitHub:   https://github.com/zr-tex8r
%%   Twitter:  @zr_tex8r
%%
%% This package is distributed under the MIT License.
%%

%% package declaration
\NeedsTeXFormat{LaTeX2e}
\ProvidesPackage{bxpapersize}[2022/04/28 v0.6]

%% preparation
\def\bxpr@pkgname{bxpapersize}
\providecommand\bxDebug[1]{}

%--------------------------------------- options

% Note: Only non-key-value global options should be picked.

%% driver options (or 'disabled')
\chardef\bxpr@disabled=0
\DeclareOption{disabled}{%
  \chardef\bxpr@disabled=1 }
\DeclareOption{nodvidriver}{%
  \chardef\bxpr@disabled=1 }
\DeclareOption{autodvidriver}{%
  \chardef\bxpr@disabled=0 }
\DeclareOption{dvips}{%
  \chardef\bxpr@disabled=0 }
\DeclareOption{dvipdfmx}{%
  \chardef\bxpr@disabled=0 }
%% 'olddvips'
\chardef\bxpr@olddvips=0
\DeclareOption{olddvips}{%
  \chardef\bxpr@disabled=0
  \chardef\bxpr@olddvips=1 }
%% keyval
\@onlypreamble\bxpr@kvopt
\let\bxpr@kvopt\@empty % key-value option list
\DeclareOption*{%
  \edef\bxpr@kvopt{\bxpr@kvopt,\CurrentOption}}
\ProcessOptions*

%% If 'disabled' is given, quit now.
\ifnum\bxpr@disabled>\z@
  \providecommand*\papersizesetup{\bxpapersizesetup}%
  \newcommand*\bxpapersizesetup[1]{}%
\expandafter\endinput\fi\relax

%--------------------------------------- general

%% load packages
\RequirePackage{xkeyval}[2008/08/10]% v2.6
\RequirePackage{ifpdf,ifxetex,ifluatex,ifvtex,ifptex}

%% variables
\newdimen\bxpr@dima
\let\bxpr@width\relax
\let\bxpr@height\relax

%% constants
\chardef\bxpr@mode@@papersize=0 % papersize special
\chardef\bxpr@mode@@pdfmode=1 % PDF-mode primitive
\chardef\bxpr@mode@@void=2 % no operation

%% unique tokens
\def\bxpr@end{\bxpr@end@}

%% switch 'bxpr@nosize'
\newif\ifbxpr@nosize
\ifx\ifhint\iftrue \bxpr@nosizetrue \fi

%% switch 'bxpr@new@hook@system'
% Whether the new hook management system is present.
\newif\ifbxpr@new@hook@system
\ifx\AddToHook\@undefined\else
  \PackageInfo\bxpr@pkgname
   {Detected the new LaTeX kernel (2020-10-01)\@gobble}
  \bxpr@new@hook@systemtrue
\fi

%% \bxpr@pagewidth / \bxpr@pageheight
%% \bxpr@horigin / \bxpr@vorigin
\ifluatex           % LuaTeX
  \ifx\pagewidth\@undefined % old version
    \let\bxpr@pagewidth\pdfpagewidth
    \let\bxpr@pageheight\pdfpageheight
  \else % new version
    \let\bxpr@pagewidth\pagewidth
    \let\bxpr@pageheight\pageheight
  \fi
  \ifx\pdfvariable\@undefined % old version
    \let\bxpr@horigin\pdfhorigin
    \let\bxpr@vorigin\pdfvorigin
  \else % new version
    \edef\bxpr@horigin{\pdfvariable horigin}
    \edef\bxpr@vorigin{\pdfvariable vorigin}
  \fi
\else\ifxetex       % XeTeX
  % treated as dvi-mode
\else\ifvtex        % VTeX
  \let\bxpr@pagewidth\mediawidth
  \let\bxpr@pageheight\mediaheight
\else\ifnum0\ifptexng1\fi\ifpdf1\fi>0 % pdfTeX in PDF mode
  \let\bxpr@pagewidth\pdfpagewidth
  \let\bxpr@pageheight\pdfpageheight
  \let\bxpr@horigin\pdfhorigin
  \let\bxpr@vorigin\pdfvorigin
\fi\fi\fi\fi
\ifx\bxpr@horigin\@undefined % fallback
  \def\bxpr@horigin{1truein }
  \def\bxpr@vorigin{1truein }
\fi

%% \bxpr@mode
\ifbxpr@nosize
  \let\bxpr@mode\bxpr@mode@@void
\else\ifx\bxpr@pagewidth\@undefined
  \let\bxpr@mode\bxpr@mode@@papersize
\else
  \let\bxpr@mode\bxpr@mode@@pdfmode
\fi\fi

%% \bxpr@csletcs{<CSa>}{<CSb>}
\def\bxpr@csletcs#1#2{%
  \expandafter\let\csname#1\expandafter\endcsname\csname#2\endcsname}

%% load 'atbegshi' package
\ifnum\bxpr@mode=\bxpr@mode@@void\else
  \RequirePackage{atbegshi}\relax
\fi

%--------------------------------------- parameters

%% constants
\chardef\bxpr@priority@@low=0
\chardef\bxpr@priority@@middle=1
\chardef\bxpr@priority@@default=1
\chardef\bxpr@priority@@high=2
\ifnum\bxpr@olddvips>\z@
  \chardef\bxpr@priority@@low=2
  \chardef\bxpr@priority@@high=0
\fi
\chardef\bxpr@size@@real=0 %'real', use \paperwidth/height
\chardef\bxpr@size@@realS=1 %'real*'
\chardef\bxpr@size@@box=2 %'box', use shipout box size
\chardef\bxpr@size@@boxS=3 %'box*'
\chardef\bxpr@size@@custom=4 % size explicitly given

%% variables
\newif\ifbxpr@needs@reset@size
\let\bxpr@priority\bxpr@priority@@default
\let\bxpr@size\bxpr@size@@real
\def\bxpr@cs@width{\z@}%  custom page width
\def\bxpr@cs@height{\z@}% custom page height

%% error message
\def\bxpr@err@nlprm#1{%
  \PackageError\bxpr@pkgname
   {You can set '#1' only in preamble}%
   \@ehc}
\def\bxpr@err@ivval#1#2{%
  \PackageError\bxpr@pkgname
   {Invalid value for '#1': #2}%
   \@ehc}
\def\bxpr@err@ivkey{%
  \begingroup \let\MessageBreak\relax % freeze
    \let\bxpr@tmpb\@empty
    \@for\bxpr@tmpa:=\XKV@rm\do{%
      \edef\bxpr@tmpb{\bxpr@tmpb\MessageBreak\@spaces\bxpr@tmpa}}%
    \PackageError\bxpr@pkgname
      {Unknown parameter(s)\bxpr@tmpb\MessageBreak
       are found in the given list}
  \endgroup}

%% 'active'
\define@boolkey+[bxpr]{prm}{active}[true]{}%
 {\bxpr@err@ivval{active}{#1}}
\bxpr@prm@activetrue

%% 'priority'
\define@choicekey*+[bxpr]{prm}{priority}%
    {low,middle,default,high}%
 {\bxpr@set@priority{#1}}%
 {\bxpr@err@ivval{priority}{#1}}
\def\bxpr@set@priority#1{%
  \bxpr@csletcs{bxpr@priority}{bxpr@priority@@#1}}
\AtBeginDocument{%
  \def\bxpr@set@priority#1{% invalidate
    \bxpr@err@nlprm{priority}}}

%% 'truedimen'
\define@boolkey+[bxpr]{prm}{truedimen}[true]%
 {\bxpr@needs@reset@sizetrue}%
 {\bxpr@err@ivval{truedimen}{#1}}

%% 'landscape'
\define@boolkey+[bxpr]{prm}{landscape}[true]%
 {\bxpr@needs@reset@sizetrue}%
 {\bxpr@err@ivval{landscape}{#1}}

%% 'size'
\define@choicekey*+[bxpr]{prm}{size}[\bxpr@tmpa\bxpr@tmpb]%
    {real,real*,box,box*,
     % preset paper sizes
     a0paper,a1paper,a2paper,a3paper,a4paper,a5paper,a6paper,%
     b0paper,b1paper,b2paper,b3paper,b4paper,b5paper,b6paper,%
     c0paper,c1paper,c2paper,c3paper,c4paper,c5paper,c6paper,%
     b0j,b1j,b2j,b3j,b4j,b5j,b6j,%
     ansiapaper,ansibpaper,ansicpaper,ansidpaper,ansiepaper,%
     letterpaper,legalpaper,executivepaper,screen}%
 {\def\bxpr@val@size{#1}\bxpr@needs@reset@sizefalse
  \ifcase\bxpr@tmpb\relax
      \let\bxpr@size\bxpr@size@@real
  \or \let\bxpr@size\bxpr@size@@realS
  \or \let\bxpr@size\bxpr@size@@box
  \or \let\bxpr@size\bxpr@size@@boxS
  \or \bxpr@set@size@a(841,1189){mm}%  a0paper
  \or \bxpr@set@size@a(594,841){mm}%   a1paper
  \or \bxpr@set@size@a(420,594){mm}%   a2paper
  \or \bxpr@set@size@a(297,420){mm}%   a3paper
  \or \bxpr@set@size@a(210,297){mm}%   a4paper
  \or \bxpr@set@size@a(148,210){mm}%   a5paper
  \or \bxpr@set@size@a(105,148){mm}%   a6paper
  \or \bxpr@set@size@a(1000,1414){mm}% b0paper
  \or \bxpr@set@size@a(707,1000){mm}%  b1paper
  \or \bxpr@set@size@a(500,707){mm}%   b2paper
  \or \bxpr@set@size@a(353,500){mm}%   b3paper
  \or \bxpr@set@size@a(250,353){mm}%   b4paper
  \or \bxpr@set@size@a(176,250){mm}%   b5paper
  \or \bxpr@set@size@a(125,176){mm}%   b6paper
  \or \bxpr@set@size@a(917,1297){mm}%  c0paper
  \or \bxpr@set@size@a(648,917){mm}%   c1paper
  \or \bxpr@set@size@a(458,648){mm}%   c2paper
  \or \bxpr@set@size@a(324,458){mm}%   c3paper
  \or \bxpr@set@size@a(229,324){mm}%   c4paper
  \or \bxpr@set@size@a(162,229){mm}%   c5paper
  \or \bxpr@set@size@a(114,162){mm}%   c6paper
  \or \bxpr@set@size@a(1030,1456){mm}% b0j
  \or \bxpr@set@size@a(728,1030){mm}%  b1j
  \or \bxpr@set@size@a(515,728){mm}%   b2j
  \or \bxpr@set@size@a(364,515){mm}%   b3j
  \or \bxpr@set@size@a(257,364){mm}%   b4j
  \or \bxpr@set@size@a(182,257){mm}%   b5j
  \or \bxpr@set@size@a(128,182){mm}%   b6j
  \or \bxpr@set@size@a(8.5,11){in}%    ansiapaper
  \or \bxpr@set@size@a(11,17){in}%     ansibpaper
  \or \bxpr@set@size@a(17,22){in}%     ansicpaper
  \or \bxpr@set@size@a(22,34){in}%     ansidpaper
  \or \bxpr@set@size@a(34,44){in}%     ansiepaper
  \or \bxpr@set@size@a(8.5,11){in}%    letterpaper
  \or \bxpr@set@size@a(8.5,14){in}%    legalpaper
  \or \bxpr@set@size@a(7.25,10.5){in}% executivepaper
  \or \bxpr@set@size@a(225,180){mm}%   screen
  \fi}%
 {% custom page size ('size={<width>,<height>}')
  \def\bxpr@val@size{#1}\bxpr@needs@reset@sizefalse
  \def\bxpr@tmpa##1,##2,##3\@nil{%
    \begingroup\setbox\z@\hbox{%
      \@tempdima##1\relax \@tempdimb##2\relax
      \xdef\bxpr@g@next{%
        \def\noexpand\bxpr@cs@width{\the\@tempdima}%
        \def\noexpand\bxpr@cs@height{\the\@tempdimb}}}%
    \endgroup\bxpr@g@next}%
  \def\bxpr@tmpb{#1}%
  \bxpr@set@size@star
  \expandafter\bxpr@tmpa\bxpr@tmpb,,\@nil
  \let\bxpr@size\bxpr@size@@custom}
\def\bxpr@set@size@a(#1,#2)#3{%
  \edef\bxpr@tmpa##1##2{%
    \ifbxpr@prm@landscape##2\else##1\fi
    \ifbxpr@prm@truedimen true\fi #3\relax}%
  \bxpr@dima=\bxpr@tmpa{#1}{#2}\edef\bxpr@cs@width{\the\bxpr@dima}%
  \bxpr@dima=\bxpr@tmpa{#2}{#1}\edef\bxpr@cs@height{\the\bxpr@dima}%
  \let\bxpr@size\bxpr@size@@custom}
\def\bxpr@set@size@star{%
  \expandafter\bxpr@set@size@star@a\bxpr@tmpb**\bxpr@end}
\def\bxpr@set@size@star@a#1*#2*#3\bxpr@end{%
  \ifx*#2*\else \def\bxpr@tmpb{#1,#2}\fi}

%--------------------------------------- user interface

%%<*> \bxpapersizesetup{<key>=<value>,...}
\newcommand*\bxpapersizesetup[1]{%
  \setkeys*[bxpr]{prm}{#1}%
  \ifx\XKV@rm\@empty\else
    \bxpr@err@ivkey
  \fi
  \ifbxpr@needs@reset@size
    \edef\bxpr@tmpa{%
      \noexpand\setkeys[bxpr]{prm}{size=\bxpr@val@size}%
    }\bxpr@tmpa
  \fi}
%%<*> \papersizesetup{<key>=<value>,...}
% Synonym for \bxpapersizesetup, declared only if not yet defined.
\providecommand*\papersizesetup{%
  \bxpapersizesetup}

%% apply package options
\edef\bxpr@tmpa{%
  \noexpand\bxpapersizesetup{\bxpr@kvopt}%
}\bxpr@tmpa

% if priority is not middle...
\ifnum\bxpr@priority=\bxpr@priority@@default\else
\ifbxpr@new@hook@system %----
  \PackageWarningNoLine\bxpr@pkgname
   {!!!!!!!!!! WARNING !!!!!!!!!!\MessageBreak
    You use the new LaTeX kernel (2020-10-01)!\MessageBreak
    Unfortunately, priority setting is not yet\MessageBreak
    available on the new kernel, and thus\MessageBreak
    will be ignored}
  \let\bxpr@priority\bxpr@priority@@default
\else %----
  \ifcase\bxpr@mode % papersize
    \ifptex
      \RequirePackage{pxatbegshi}[]
    \fi
  \or % pdf
    \PackageWarningNoLine\bxpr@pkgname
     {The priority setting will be ignored in PDF mdoe}
  \fi
\fi %----
\fi

%--------------------------------------- page hook

%% \bxpr@begindoc@first@hook
% Placed at the head of the begin-docuemnt hook.
\@onlypreamble\bxpr@begindoc@first@hook
\let\bxpr@begindoc@first@hook\@empty
\ifbxpr@new@hook@system %----
\AddToHook{begindocument/before}{\bxpr@begindoc@first@hook}
\else %----
\begingroup
  \toks@\expandafter{\@begindocumenthook}
  \xdef\@begindocumenthook{%
    \noexpand\bxpr@begindoc@first@hook
    \the\toks@}
\endgroup
\fi %----

%% \bxpr@begindoc@last@hook
% Placed after the begin-docuemnt hook.
\def\bxpr@begindoc@last@hook{%
  \let\bxpr@begindoc@last@hook\@undefined}
\ifbxpr@new@hook@system %----
\AddToHook{begindocument/end}{\bxpr@begindoc@last@hook}
\else %----
\g@addto@macro\document{%
  \bxpr@begindoc@last@hook}
\fi %----

%% add hook for every page
\g@addto@macro\bxpr@begindoc@first@hook{%
  \bxDebug{bxpapersize settings:^^J%
    mode=\the\bxpr@mode^^J%
    priority=\the\bxpr@priority^^J%
    size=\the\bxpr@size(\bxpr@cs@width,\bxpr@cs@height)%
    \ifnum\bxpr@tombow>\z@ [tombow]\fi}%
  \bxpr@geometry@hack
  \ifcase\bxpr@mode % papersize
    \ifcase\bxpr@priority % low
      \AtBeginShipoutInit
      \def\bxpr@every@page@hook{%
        \bxpr@page@process
        \bxpr@modify@output@box\bxpr@special@chunk\relax
        \AtBeginShipoutNext{\bxpr@every@page@hook}}%
      \AtBeginShipoutNext{%
        \bxpr@page@process
        \AtBeginShipoutNext{\bxpr@every@page@hook}}%
      \AtBeginShipoutFirst{\bxpr@special@chunk}
    \or % default
      \def\bxpr@every@page@hook{%
        \bxpr@page@process
        \bxpr@modify@output@box\relax\bxpr@special@chunk}%
      \AtBeginShipout{\bxpr@every@page@hook}%
    \or % high
      \AtBeginShipoutInit
      \def\bxpr@every@page@hook{%
        \bxpr@page@process
        \bxpr@modify@output@box\relax\bxpr@special@chunk
        \AtBeginShipoutNext{\bxpr@every@page@hook}}%
      \AtBeginShipoutNext{\bxpr@every@page@hook}%
    \fi
  \or % pdf
    \def\bxpr@every@page@hook{%
      \bxpr@page@process
      \bxpr@modify@output@box\relax\bxpr@special@chunk}%
    \AtBeginShipout{\bxpr@every@page@hook}%
  \fi}

%% \bxpr@tombow
\chardef\bxpr@tombow=0
\expandafter\ifx\csname iftombow\expandafter\endcsname
    \csname iftrue\endcsname
  \chardef\bxpr@tombow=1
\fi

%% \bxpr@modify@output@box{<pre>}{<post>}
\def\bxpr@modify@output@box#1#2{%
  \setbox\AtBeginShipoutBox\vbox{%
    #1\box\AtBeginShipoutBox#2}}

%--------------------------------------- geometry hack

% The geometry package sets \paperwidth/height to incorrect
% values after its begin-document hook when magnification is
% in effect. For example, when \mag=2000 and the actual paper
% width is 100pt (=200truept), geometry will set \paperwidth
% to 200pt (=400truept), which is clearly incorrect.
% This behavior seems intentional, but I don't know the reason.
% At least it is harmful to the function of this package, so
% that I fixed it by simply revoking the change by geometry.

%% \bxpr@geometry@hack
\@onlypreamble\bxpr@geometry@hack
\def\bxpr@geometry@hack{%
  \@ifpackageloaded{geometry}{%
    \edef\bxpr@tmpa{%
      \paperwidth=\the\paperwidth
      \paperheight=\the\paperheight}%
    \expandafter\g@addto@macro\expandafter\bxpr@begindoc@last@hook
        \expandafter{\bxpr@tmpa}%
  }{}}

%--------------------------------------- per-page process

%% \bxpr@special@chunk
\let\bxpr@special@chunk\@empty

%% \bxpr@set@page@size{<width>}{<height>}
\ifcase\bxpr@mode % dvi
  \def\bxpr@set@page@size#1#2{%
    \begingroup
      \bxpr@let@real@mag@to\bxpr@tmpa
      \paperwidth=#1\relax \paperwidth=\bxpr@tmpa\paperwidth
      \paperheight=#2\relax \paperheight=\bxpr@tmpa\paperheight
      \xdef\bxpr@g@next{%
        \def\noexpand\bxpr@tmpb{\the\paperwidth,\the\paperheight}}%
    \endgroup \bxpr@g@next
    \bxDebug{papersize=\bxpr@tmpb}%
    \edef\bxpr@special@chunk{\special{papersize=\bxpr@tmpb}}}%
\or % pdf
  \def\bxpr@set@page@size#1#2{%
    \bxpr@pagewidth=#1\relax \bxpr@pageheight=#2\relax
    \bxDebug{papersize=\the\bxpr@pagewidth,\the\bxpr@pageheight}}%
\else % void
  \def\bxpr@set@page@size#1#2{%
    \bxDebug{papersize ignored}}
\fi

%% \bxpr@let@real@mag@to\CS
\def\bxpr@let@real@mag@to#1{%
  \begingroup
    \@tempcnta=\mag \advance\@tempcnta100000
    \def\bxpr@tmpa1##1##2##3##4##5\relax{%
      \@tempdima=##1##2.##3##4##5\p@}%
    \expandafter\bxpr@tmpa\the\@tempcnta\relax
    \xdef\bxpr@g@next{%
      \def\noexpand#1{\strip@pt\@tempdima}}%
  \endgroup \bxpr@g@next}

%% \bxpr@page@process
\def\bxpr@page@process{%
  \ifbxpr@prm@active
    \bxpr@page@process@a
  \fi}
\def\bxpr@page@process@a{%
  \ifcase\bxpr@size % real
    \bxpr@use@real@size
    \bxpr@set@page@size{\bxpr@width}{\bxpr@height}%
  \or % real*
    \bxpr@set@page@size{\paperwidth}{\paperheight}%
  \or % box
    \bxpr@use@box@size
    \setbox\AtBeginShipoutBox\vbox{%
      \kern-\bxpr@vorigin
      \moveleft\bxpr@horigin\box\AtBeginShipoutBox}%
    \bxpr@set@page@size{\bxpr@width}{\bxpr@height}%
  \or % box*
    \bxpr@use@box@size
    \bxpr@set@page@size{\bxpr@width}{\bxpr@height}%
  \else % custom
    \bxpr@set@page@size{\bxpr@cs@width}{\bxpr@cs@height}%
  \fi}

%% \bxpr@use@real@size
\def\bxpr@use@real@size{%
  \bxpr@use@real@size@a{width}%
  \bxpr@use@real@size@a{height}}
\def\bxpr@use@real@size@a#1{%
  \begingroup
    \bxpr@csletcs{bxpr@tmpa}{paper#1}%
    \ifnum\bxpr@tombow>\z@
      \advance\bxpr@tmpa2truein\relax
    \fi
    \bxpr@csletcs{bxpr@tmpb}{stock#1}%
    \ifx\bxpr@tmpb\relax\else \ifdim\bxpr@tmpb>\z@
      \bxpr@tmpa\bxpr@tmpb
    \fi\fi
    \xdef\bxpr@g@next{%
      \def\expandafter\noexpand\csname bxpr@#1\endcsname{%
        \the\bxpr@tmpa}}
  \endgroup \bxpr@g@next}

%% \bxpr@use@box@size
\def\bxpr@use@box@size{%
  \edef\bxpr@width{\the\wd\AtBeginShipoutBox}%
  \bxpr@dima\ht\AtBeginShipoutBox
  \advance\bxpr@dima\dp\AtBeginShipoutBox
  \edef\bxpr@height{\the\bxpr@dima}}

%--------------------------------------- all done
\endinput
%% EOF
