page-sel.mklx /size: 18 Kb    last modification: 2025-02-21 11:03
1%D \module
2%D   [       file=page-sel, % moved from page-imp
3%D        version=1998.01.15,
4%D          title=\CONTEXT\ Page Macros,
5%D       subtitle=Page Selection,
6%D         author=Hans Hagen,
7%D           date=\currentdate,
8%D      copyright={PRAGMA ADE \& \CONTEXT\ Development Team}]
9%C
10%C This module is part of the \CONTEXT\ macro||package and is
11%C therefore copyrighted by \PRAGMA. See mreadme.pdf for
12%C details.
13
14%D This code relates to old texexec features and one can wonder if it needs
15%D to be in the core. So, this could become runtime loaded code. Some of
16%D the alternatives need checking.
17
18%D Todo: update to use luametatex features.
19
20\writestatus{loading}{ConTeXt Page Macros / Page Selection}
21
22\unprotect
23
24\registerctxluafile{page-sel}{autosuffix}
25
26\startcontextdefinitioncode
27
28%D One can (mis)use this mechanism to (re)arrange pages of already produced files.
29%D
30%D \starttyping
31%D \insertpages[file.pdf][1,3][n=30,width=18cm]
32%D \stoptyping
33%D
34%D The pages are inserted in the text area, and even pages are repositioned
35%D according to the width. In this example empty pages are added after page 1 and 3.
36%D
37%D Selecting pages can be accomplished by:
38%D
39%D \starttyping
40%D \filterpages[file.pdf][1,3,5][n=30,width=18cm]
41%D \stoptyping
42%D
43%D One may pass \type {odd} or \type {even} instead of a comma separated list. A
44%D third alternative is:
45%D
46%D \starttyping
47%D \copypages[file.pdf][n=30,scale=950]
48%D \stoptyping
49%D
50%D This macros inserts the page, according to the settings provided.
51
52%D Beware: width is not the width of the image, but height can be used to control
53%D its dimensions.
54
55\installcorenamespace{withpages}
56
57\installsetuponlycommandhandler \??withpages {withpages}
58%  \installdirectcommandhandler \??withpages {withpages}
59
60\newinteger\c_page_selectors_n
61
62\permanent\tolerant\protected\def\insertpages[#filename]#spacer[#emptylist]#spacer[#S#settings]%
63  {\doifelseassignment{#emptylist}%
64     {\page_selectors_insert_indeed[#filename][][#emptylist]}%
65     {\page_selectors_insert_indeed[#filename][#emptylist][#settings]}}
66
67\def\page_selectors_insert_indeed[#filename][#emptylist][#S#settings]%
68  {\bgroup
69   \dontcomplain
70   \getfiguredimensions[#filename]%
71   \setupcurrentwithpages
72     [\c!width=\zeropoint,
73      \c!n=\noffigurepages,
74      \c!category=,
75      \c!alternative=\v!a,
76      #settings]%
77   \global\c_page_selectors_n{\directwithpagesparameter\c!n}%
78   \scratchwidth{\directwithpagesparameter\c!width}%
79   \ifinset{0}{#emptylist}%
80     \emptyhbox
81     \page
82   \fi
83   \dorecurse\c_page_selectors_n
84     {\page_selectors_filter_alternative{#filename}\recurselevel
85      \ifinset{\recurselevel}{#emptylist}%
86        \emptyhbox
87        \page
88      \fi}%
89   \egroup}
90
91\let\page_selectors_filter_step_indeed\gobbleoneargument
92\let\page_selectors_filter_step       \gobbleoneargument
93
94\installcorenamespace{filterpagesalternative}
95
96\protected\def\page_selectors_filter_alternative
97  {\expandnamespaceparameter
98     \??filterpagesalternative
99     \directwithpagesparameter\c!alternative
100     \v!a}
101
102\permanent\tolerant\protected\def\filterpages[#filename]#spacer[#selection]#spacer[#S#settings]%
103  {\doifelseassignment{#selection}%
104     {\page_selectors_filter_indeed[#filename][][#selection]}%
105     {\page_selectors_filter_indeed[#filename][#selection][#settings]}}
106
107\def\page_selectors_filter_indeed[#filename][#selection][#S#settings]% % \noffigurepages not yet supported
108  {\bgroup
109   \dontcomplain
110   \getfiguredimensions[#filename]%
111   \setupcurrentwithpages
112     [\c!width=\zeropoint,
113      \c!n=\noffigurepages,
114      \c!category=,
115      \c!alternative=\v!a,
116      #settings]%
117   \global\c_page_selectors_n{\directwithpagesparameter\c!n}%
118   \scratchwidth{\directwithpagesparameter\c!width}%
119   \edef\p_selection{#selection}%
120   \ifempty\p_selection
121     \let\p_selection\v!all
122   \fi
123   \ifx\p_selection\v!all
124     \dorecurse\c_page_selectors_n
125       {\page_selectors_filter_alternative{#filename}\recurselevel}%
126   \orelse\ifx\p_selection\v!even
127     \dorecurse\c_page_selectors_n
128       {\ifodd\recurselevel\else
129          \page_selectors_filter_alternative{#filename}\recurselevel
130        \fi}%
131   \orelse\ifx\p_selection\v!odd
132     \dorecurse\c_page_selectors_n
133       {\ifodd\recurselevel\relax
134          \page_selectors_filter_alternative{#filename}\recurselevel
135        \fi}%
136   \else
137     \def\page_selectors_filter_step_indeed#page%
138       {\ifnum#page>\c_page_selectors_n\else
139          \page_selectors_filter_alternative{#filename}{#page}%
140        \fi}%
141     % todo: use the context lua slicer
142     \def\page_selectors_filter_step#step%
143       {\dowithminmaxrangeslice
144          {1}{\noffigurepages}% where we take from
145          {1}{\noffigurepages}% what we want
146          {#step}%              the set
147          \page_selectors_filter_step_indeed}%
148     \processcommacommand[\p_selection]\page_selectors_filter_step
149   \fi
150   \egroup}
151
152\defcsname\??filterpagesalternative\v!a\endcsname#filename#page%
153  {\hpack to \textwidth
154     {\ifdim\scratchwidth>\zeropoint
155        \rightorleftpageaction{\scratchwidth\zeropoint}{\hfill}%
156      \fi
157      \setbox\scratchbox\hpack
158        {\hskip-\scratchwidth
159         \edef\p_category{\directwithpagesparameter\c!category}% \useexternalfigure[foo][width=\textwidth]
160         \ifx\p_category\empty
161           \externalfigure[#filename][\c!page=#page,\c!height=\textheight]%
162         \else
163           \externalfigure[#filename][\p_category][\c!page=#page]%
164         \fi
165         \hss}%
166      \wd\scratchbox\zeropoint
167      \box\scratchbox}%
168   \page}
169
170\defcsname\??filterpagesalternative\v!b\endcsname#filename#page%
171  {\startTEXpage
172     \scratchcounter#page\relax
173     \ifnum\scratchcounter<\zerocount
174        \getfiguredimensions[#filename]%
175        \scratchcounter{\noffigurepages-\scratchcounter+\plusone}%
176     \fi
177     \normalexpanded{\externalfigure[#filename][\c!page=\the\scratchcounter]}%
178   \stopTEXpage}
179
180\letcsname\??filterpagesalternative\v!default\expandafter\endcsname\csname\??filterpagesalternative\v!a\endcsname
181\letcsname\??filterpagesalternative\v!page   \expandafter\endcsname\csname\??filterpagesalternative\v!b\endcsname
182
183\permanent\tolerant\protected\def\copypages[#filename]#spacer[#S#settings]#spacer[#S#figuresettings]%
184  {\bgroup
185   \getfiguredimensions[#filename]%
186   \setupcurrentwithpages
187     [\c!marking=\v!off,
188      \c!offset=\zeropoint,
189      \c!n=\noffigurepages,
190      \c!category=,
191      #settings]%
192   \global\c_page_selectors_n{\directwithpagesparameter\c!n}%
193   \scratchoffset{\directwithpagesparameter\c!offset}%
194   \dorecurse\c_page_selectors_n
195     {\vbox to \textheight
196        {\hsize\textwidth
197         \centeredbox
198           {\ifcstok{\directwithpagesparameter\c!marking}\v!on
199              \expandafter\cuthbox
200            \else
201              \expandafter\hpack % only place where cuthbox is used
202            \fi
203              {\ifdim\scratchoffset>\zeropoint\relax
204                 \advanceby\vsize -2\scratchoffset
205                 \advanceby\hsize -2\scratchoffset
206                 \externalfigure[#filename][\c!page=\recurselevel,#figuresettings,\c!scale=,\c!factor=\v!max,\c!offset=\v!overlay]%
207               \else
208                 \externalfigure[#filename][\c!page=\recurselevel,#figuresettings,\c!offset=\v!overlay]%
209               \fi}}}%
210      \page}%
211   \egroup}
212
213%D \macros
214%D   {combinepages}
215%D
216%D Yet another way of postprocessing is handles by \type {\combinepages}. This macro
217%D builds a matrix of pages from a file, for example:
218%D
219%D \starttyping
220%D \setuppapersize
221%D   [A4][A4] % or [A4,landscape][A4,landscape]
222%D
223%D \setuplayout
224%D   [header=0pt,footer=1cm,
225%D    backspace=1cm,topspace=1cm,
226%D    width=middle,height=middle]
227%D
228%D \setupfootertexts
229%D   [presentation---\currentdate\space---\space\pagenumber]
230%D
231%D \starttext
232%D   \combinepages[slides][nx=2,ny=3,frame=on]
233%D \stoptext
234%D \stoptyping
235%D
236%D One can influence the way the pages are combined. (This will be explained some
237%D time.)
238
239\installcorenamespace{combinepagesalternative}
240
241\permanent\tolerant\protected\def\combinepages[#filename]#spacer[#S#settings]% a=perpag b=free
242  {\bgroup
243   \dontcomplain
244   \getfiguredimensions[#filename]%
245   \setupcurrentwithpages
246     [\c!alternative=\v!a,
247      \c!n=\noffigurepages,\c!nx=\plustwo,\c!ny=\plustwo,
248      \c!start=\plusone,\c!stop=\maxcard,
249      \c!distance=\bodyfontsize,
250      \c!bottom=\vfill,\c!top=\vss,\c!left=\hss,\c!right=\hss,
251      \c!before=\page,\c!after=\page,\c!inbetween=\blank,
252      \c!frame=,\c!background=,\c!backgroundcolor=,
253      \c!name={#filename},
254      \c!category=,
255      #settings]%
256   \global\c_page_selectors_n\directwithpagesparameter\c!n\relax
257   \directwithpagesparameter\c!before
258   \scratchnx{\directwithpagesparameter\c!nx}%
259   \scratchny{\directwithpagesparameter\c!ny}%
260   \scratchdistance{\directwithpagesparameter\c!distance}%
261   \scratchwidth{(\textwidth-\scratchnx\scratchdistance+\scratchdistance)/\scratchnx}%
262   \scratchheight{(\textheight-\scratchny\scratchdistance+\scratchdistance)/\scratchny}%
263   \expandnamespaceparameter\??combinepagesalternative\directwithpagesparameter\c!alternative\v!b
264   \directwithpagesparameter\c!after
265   \egroup}
266
267\defcsname\??combinepagesalternative\v!a\endcsname % use hpacks
268  {\global\combinedpagescounter\directwithpagesparameter\c!start\relax
269   \doloop
270     {\vbox to \textheight
271        {\dorecurse\scratchny
272           {\hbox to \textwidth
273              {\dorecurse\scratchnx
274                 {\vbox to \scratchheight
275                    {\hsize\scratchwidth
276                     \vsize\scratchheight
277                     \directwithpagesparameter\c!top
278                     \hbox to \hsize
279                       {\directwithpagesparameter\c!left
280                        \ifnum\combinedpagescounter>\directwithpagesparameter\c!stop\relax
281                          \global\c_page_selectors_n\zerocount
282                        \orelse\ifnum\combinedpagescounter>\c_page_selectors_n \else
283                          \externalfigure
284                            [\directwithpagesparameter\c!name]
285                            [\c!object=\v!no,
286                             \c!page=\number\combinedpagescounter,
287                             \c!factor=\v!max,
288                             \c!background=\directwithpagesparameter\c!background,
289                             \c!backgroundcolor=\directwithpagesparameter\c!backgroundcolor,
290                             \c!frame=\directwithpagesparameter\c!frame]%
291                        \fi
292                        \directwithpagesparameter\c!right}%
293                     \directwithpagesparameter\c!bottom}%
294                  \global\advanceby\combinedpagescounter\plusone
295                  \hfil}%
296               \hfilneg}
297            \vfil}%
298         \vfilneg}%
299         \page
300         \ifnum\combinedpagescounter>\c_page_selectors_n
301           \exitloop
302         \fi}}
303
304\defcsname\??combinepagesalternative\v!c\endcsname
305  {\global\combinedpagescounter\directwithpagesparameter\c!start\relax
306   \doloop
307     {\vbox to \textheight
308        {\hbox to \textwidth
309           {\dorecurse\scratchnx
310              {\directwithpagesparameter\c!left
311               \vbox to \textheight
312                 {\hsize\scratchwidth
313                  \dorecurse\scratchny
314                    {\directwithpagesparameter\c!top
315                     \hbox to \hsize
316                       {\vbox to \scratchheight
317                          {\hsize\scratchwidth
318                           \vsize\scratchheight
319                           \ifnum\combinedpagescounter>\directwithpagesparameter\c!stop\relax
320                             \global\c_page_selectors_n\zerocount
321                           \orunless\ifnum\combinedpagescounter>\c_page_selectors_n
322                             \externalfigure
323                               [\directwithpagesparameter\c!name]
324                               [\c!object=\v!no,
325                                \c!page=\number\combinedpagescounter,
326                                \c!factor=\v!max,
327                                \c!background=\directwithpagesparameter\c!background,
328                                \c!backgroundcolor=\directwithpagesparameter\c!backgroundcolor,
329                                \c!frame=\directwithpagesparameter\c!frame]%
330                           \fi}}
331                      \global\advanceby\combinedpagescounter\plusone
332                      \directwithpagesparameter\c!bottom}}%
333                \hfil}%
334            \hfilneg}}%
335      \page
336      \ifnum\combinedpagescounter>\c_page_selectors_n
337        \exitloop
338      \fi}}
339
340\letcsname\??combinepagesalternative\v!horizontal\expandafter\endcsname\csname\??combinepagesalternative\v!a\endcsname
341\letcsname\??combinepagesalternative\v!vertical  \expandafter\endcsname\csname\??combinepagesalternative\v!c\endcsname
342
343\defcsname\??combinepagesalternative\v!b\endcsname
344  {\global\combinedpagescounter\directwithpagesparameter\c!start\relax
345   \doloop
346     {\startbaselinecorrection
347        \hbox to \textwidth
348          {\dorecurse\scratchnx
349             {\global\advanceby\combinedpagescounter\plusone
350              \ifnum\combinedpagescounter>\c_page_selectors_n \else
351                 \normalexpanded{\externalfigure
352                   [\directwithpagesparameter\c!name]
353                   [\c!page=\number\combinedpagescounter,
354                    \c!width=\the\scratchwidth,
355                    \c!background=\directwithpagesparameter\c!background,
356                    \c!backgroundcolor=\directwithpagesparameter\c!backgroundcolor,
357                    \c!frame=\directwithpagesparameter\c!frame]}%
358                 \hfill
359              \fi}%
360              \hfillneg}%
361      \stopbaselinecorrection
362      \ifnum\combinedpagescounter<\c_page_selectors_n\relax
363        \directwithpagesparameter\c!inbetween
364      \else
365        \exitloop
366      \fi}}
367
368% This macro cuts a page into n parts that can be pasted together.
369
370\permanent\tolerant\protected\def\slicepages[#filename]#spacer[#S#oddsettings]#spacer[#S#evensettings]%
371  {\ifparameter#evensettings\or
372     \page_selectors_slice_indeed[#filename][#oddsettings][#evensettings]%
373   \else
374     \page_selectors_slice_indeed[#filename][#oddsettings][#oddsettings]%
375   \fi}
376
377\mutable\let\slicedpagenumber\!!zerocount
378\mutable\let\slicedpagestepx \!!zerocount
379\mutable\let\slicedpagestepy \!!zerocount
380
381\def\page_selectors_slice_indeed[#filename][#S#oddsettings][#S#evensettings]%
382  {\bgroup
383   \dontcomplain
384   \glet\slicedpagenumber\!!zerocount
385   \getfiguredimensions[#filename]%
386   \setupcurrentwithpages
387     [\c!offset=\zeropoint,
388      \c!hoffset=\zeropoint,
389      \c!voffset=\zeropoint,
390      \c!width=\figurewidth,
391      \c!height=\figureheight,
392      \c!n=\noffigurepages,
393      \c!category=,
394      #oddsettings]%
395   \global\c_page_selectors_n\directwithpagesparameter\c!n\relax
396   \ifnum\c_page_selectors_n>\zerocount
397     \definepapersize
398       [\s!dummy]
399       [\c!height=\directwithpagesparameter\c!height,
400        \c!width=\directwithpagesparameter\c!width]%
401     \setuppapersize
402       [\s!dummy]
403       [\s!dummy]%
404     \setuplayout
405       [\c!backspace=\zeropoint,\c!topspace=\zeropoint,
406        \c!height=\v!middle,\c!width=\v!middle,
407        \c!textdistance=\zeropoint,
408        \c!header=\zeropoint,\c!footer=\zeropoint]%
409   \fi
410   \dorecurse\noffigurepages
411     {\glet\slicedpagenumber\recurselevel
412      \ifnum\c_page_selectors_n>\plusone
413        \dorecurse\c_page_selectors_n
414          {\let\slicedpagestepx\recurselevel
415           \dorecurse\c_page_selectors_n
416             {\let\slicedpagestepy\recurselevel
417              \clip
418                [\c!nx=\c_page_selectors_n,\c!ny=\c_page_selectors_n,\c!x=\slicedpagestepx,\c!y=\slicedpagestepy]%
419                {\scale
420                   [\c!scale=\the\c_page_selectors_n000]%
421                   {\externalfigure[#filename][\c!page=\slicedpagenumber]}}%
422              \page}}%
423      \else
424        \ifodd\slicedpagenumber\relax
425          \setupcurrentwithpages[#oddsettings]%
426        \else
427          \setupcurrentwithpages[#evensettings]%
428        \fi
429        \hskip{\directwithpagesparameter\c!offset}%
430        \clip
431          [\c!hoffset=\directwithpagesparameter\c!hoffset,%
432           \c!voffset=\directwithpagesparameter\c!voffset,
433           \c!height=\directwithpagesparameter\c!height,%
434           \c!width=\directwithpagesparameter\c!width]
435          {\externalfigure[#filename][\c!page=\slicedpagenumber]}%
436        \page
437      \fi}
438   \egroup}
439
440% \starttext \slicepages[slice1.pdf][n=3] \stoptext
441
442\permanent\protected\def\trimpages[#S#1]% was for a over decade in p-pdf-51.tex
443  {\begingroup
444   \getdummyparameters
445     [\c!file=dummy,%
446      \c!hoffset=\zeropoint,
447      \c!voffset=\zeropoint,
448      \c!width=17cm,
449      \c!height=24cm,
450      \c!x=\zeropoint,
451      \c!y=\zeropoint,
452      #1]%
453   \getfiguredimensions
454     [\dummyparameter\c!file]
455     [\c!object=\v!no]%
456   \dorecurse\noffigurepages
457     {\scale
458        [\c!width=\paperwidth,
459         \c!height=\paperheight]%
460        {\offset
461           [\c!x=\dummyparameter\c!x,
462            \c!y=\dummyparameter\c!y]
463           {\clip
464              [\c!hoffset=\dummyparameter\c!hoffset,
465               \c!voffset=\dummyparameter\c!voffset,
466               \c!width=\dummyparameter\c!width,
467               \c!height=\dummyparameter\c!height]
468              {% we correct by default, if not needed, introduce option
469               \setbox\nextbox\hbox
470                 {\externalfigure[\dummyparameter\c!file][\c!page=##1]}%
471               \ifdim\wd\nextbox>\ht\nextbox
472                 \rotate[\c!rotation=90]{\box\nextbox}%
473               \else
474                 \box\nextbox
475               \fi}}}}%
476   \endgroup}
477
478\stopcontextdefinitioncode
479
480%D Implemented in Lua:
481
482% crap.tex:
483%
484% \starttext
485%     \dorecurse{10}{
486%         \startchapter[title=Chapter #1,reference=chapter:#1]
487%             \dorecurse{10}{
488%                 \startsubject[title=Subject #1]
489%                     \dorecurse{2}{\samplefile{tufte}\par}
490%                 \stopsubject
491%                 \startsection[title=Section #1.##1,reference=#1.##1]
492%                     \dorecurse{10}{\samplefile{tufte}\par}
493%                 \stopsection
494%             }
495%         \stopchapter
496%     }
497% \stoptext
498%
499% load.tex:
500%
501% \starttext
502%     \dostepwiserecurse {\firstsectionpage[crap][chapter:3]} {\lastsectionpage[crap][chapter:3]} {1} {
503%         \startpagemakeup
504%             \externalfigure[crap.pdf][page=#1]
505%         \stoppagemakeup
506%     }
507%     \dostepwiserecurse {\firstsectionpage[crap][chapter:5]} {\lastsectionpage[crap][chapter:5]} {1} {
508%         \dontleavehmode
509%         \externalfigure[crap.pdf][page=#1,width=3cm,frame=on]%
510%         \space\allowbreak
511%     }
512% \stoptext
513
514\protect \endinput
515