6

OpTeX has the macros \begmultiand \endmulti to split a text into multiple column, but since it becomes inner vertical mode, the \mark command does not have any effect anymore.

Compare

\headline={\botmark}

hello \mark{lorem ipsum}

\bye

and

\headline={\botmark}

\begmulti 2
hello \mark{lorem ipsum}
\endmulti

\bye

How can I use the mark command to record data that should be printed in the headline when the text is typeset in this mode?

3 Answers 3

4

There is an article by Hans Hagen that explains how it is possible to migrate inserts from inner lists.

The code presented there can be easily adapted to work with OpTeX, and with marks as well (didn't test this thoroughly).

\newattribute\insattr

\directlua{
local hlist = node.id('hlist')
local vlist = node.id('vlist')
local ins = node.id('ins')
local mark = node.id('mark')
local has_attribute = node.has_attribute
local set_attribute = node.set_attribute
local ins_attribute = registernumber('insattr')

local function locate(head,first,last)
    local current = head
    while current do
        local id = current.id
        if id == vlist or id == hlist then
            current.list, first, last = locate(current.list,first,last)
            current = current.next
        elseif id == ins or id == mark then
            local insert = current
            head, current = node.remove(head,current)
            insert.next = nil
            if first then
                insert.prev, last.next = last, insert
            else
                insert.prev, first = nil, insert
            end
            last = insert
        else
            current = current.next
        end
    end
    return head, first, last
end

local function migrate_inserts(where)
    local current = tex.lists.contrib_head
    while current do
        local id = current.id
        if id == vlist or id == hlist and not has_attribute(current,ins_attribute) then
            set_attribute(current,ins_attribute,1)
            local h, first, last = current.list, nil, nil
            while h do
                local id = h.id
                if id == vlist or id == hlist then
                    h, first, last = locate(h,first,last)
                end
                h = h.next
            end
            if first then
                local n = current.next
                if n then
                    last.next, n.prev = n, last
                end
                current.next, first.prev = first, current
                current = last
            end
        end
        current = current.next
    end
end

callback.add_to_callback('buildpage_filter',migrate_inserts,'migrate_inserts')
}
\headline={\botmark\hfil}

\begmulti 2
hello\mark{lorem ipsum}\fnote{Test} \lipsum[1-8]
\endmulti

\bye

Top of the page

enter image description here

Bottom of the page

enter image description here

5

You can use OpTeX trick 0111 (although the columns won't be balanced):

\fontfam[lm]
\newcount\numcolumn
\newdimen\xvsize
\def\twocol{\par\penalty0 \setbox0=\vbox\bgroup \hsize=.48\hsize \hbadness=5000 }
\def\endtwocol{\egroup
   \_setxhsize \global\xvsize=\vsize % save the global values of \hsize, \vsize
   \begingroup
      \maxdeadcycles=1000 \vbadness=5000
      \numcolumn=0
      \headline={} \footline={}   % internal \output routine without\head/foot lines
      \output={\incr\numcolumn
         \global\setbox\numexpr10000+\numcolumn=\_completepage      % no \shipout, only save box
         \ifodd\numcolumn\else \global\vsize=\xvsize \fi % correct \vsize for next page
         \ifnum\outputpenalty>-20000 \else\dosupereject\fi
      }
      \ifdim\pagetotal>0pt % if the current page is non empty , we move it to \box10000
         \numcolumn=-1
         \tmpdim=\dimexpr\pagegoal-\pagetotal-\bigskipamount\relax
         \vsize=\dimexpr\pagetotal+\prevdepth\relax
         \vfil\supereject
         \global\vsize=\tmpdim
      \fi
      \unvbox0  % now, we break \box0 to columns using internal output routine
      \vfil\supereject
   \endgroup
   \vsize=\xvsize
   \ifvoid10000 \else \unvbox10000 \bigskip \fi  % print the original current page content
   \fornumstep 2: 1..\numcolumn \do {     % print columns
      \line{\box\numexpr10000+##1\hfil \box\numexpr10001+##1}\vfil\break
   }
}

%% TEST:
\headline={\botmark}
\twocol    % two column mode starts
hello \mark{lorem ipsum}
\lorem[1-10]
\endtwocol % two column mode ends
\bye

enter image description here

1
  • 1
    It is a bit annoying the columns aren't balanced, but this is a fine solution otherwise, thanks
    – richardIII
    Sep 24 at 20:52
4

Sorry, I don't know how to effectively propagate the information about \marks from column material to page material. But, if you know what you want to have in headers at all pages where material from a single \begmulti...\endmulti spans, then you can give the header for first such page, second page etc. using the declaration macro \mpage. The macro can be defined an used as follows:

\fontfam[lm]

\newcount\mpagenum
\def\mpage#1 #2{\sdef{mpage:#1}{#2}}
\addto\_printcolumns{\incr\mpagenum \cs{mpage:\the\mpagenum}}

\headline={\botmark\hfil}

\bgroup
\mpage 1 {\mark{first}}
\mpage 2 {\mark{second}}
\begmulti 2
\lorem[1-10]
\endmulti
\egroup

\bye

The \mpage number {material} adds the vertical material at the page denoted by number. If number=1 then it is the page where \begmulti material starts, the number=2 means the following page etc. The set of \mpage declarations should be in a group with \begmulti...\endmulti because we want to set them to each multicolumn typesetting independently.

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .