% This is part of the OpTeX project, see http://petr.olsak.net/optex

\_codedecl \cite {Cite, Bibliography <2021-04-13>} % preloaded in format

   \_doc -----------------------------
   Registers used by `\cite`, `\bib` macros are declared here.
   The \`\bibnum` counts the bibliography items from one.
   The \`\bibmark` is used when `\nonumcitations` is set.
   \_cod -----------------------------

\_newcount\_bibnum                       % the bibitem counter
\_newtoks\_bibmark                       % the bibmark used if \nonumcitations
\_newcount\_lastcitenum \_lastcitenum=0  % for \shortcitations
\_public \bibnum \bibmark ;

   \_doc -----------------------------
   \`\_bibp` expands to \^`\bibpart``/`.
   By default, \^`\bibpart` is empty, so internal links are in the form
   `cite:/<number>`. If \^`\bibpart` is set to `<bibpart>`, then internal
   links are `cite:<bibpart>/<number>`.
   \_cod -----------------------------

\_def\_bibp{\_the\_bibpart/}             % unique name for each bibliography list

   \_doc -----------------------------
   \`\cite` `[<label>,<label>,...,<label>]` manages <labes> using `\_citeA`
   and prints `[<bib-marks>]` using `\_printsavedcites`.
   \nl
   \`\nocite` `[<label>,<label>,...,<label>]` only manages <labels> but prints nothing.
   \nl
   \`\rcite` `[<label>,<label>,...,<label>]` behaves like `\cite` but prints
    <bib-marks> without brackets.
   \nl
   \`\ecite` `[<label>]{<text>}` behaves like `\rcite [<label>]` but prints
   <text> instead <bib-mark>. The <text> is hyperlinked like <bib-marks>
   when `\cite` or `\rcite` is used.
   The empty internal macro \`\_savedcites` will include the `<bib-marks>` list to
   be printed. This list is set by `\_citeA` inside a group and it is used by
   `\_printsavedcites` in the same group. Each `\cite`/`\rcite`/`\ecite`  macro
   starts from empty list of <bib-marks> because new group is opened.
   \_cod -----------------------------

\_def\_cite[#1]{{\_citeA#1,,,[\_printsavedcites]}}
\_def\_nocite[#1]{{\_citeA#1,,,}}
\_def\_rcite[#1]{{\_citeA#1,,,\_printsavedcites}}
\_def\_ecite[#1]{\_bgroup\_citeA#1,,,\_ea\_eciteB\_savedcites;}
\_def\_eciteB#1,#2;#3{\_if?#1\_relax #3\_else \_ilink[cite:\_bibp#1]{#3}\_fi\_egroup}
\_def\_savedcites{}

\_public \cite \nocite \rcite \ecite ;

   \_doc -----------------------------
   `<bib-marks>` may be numbers or a special text related to cited bib-entry.
   It depends on \`\nonumcitations` and on used bib-style. The mapping from
   <label> to <bib-mark> is done when `\bib` or `\usebib` is processed.
   These macros store the information to
   \`\_Xbib``{<bibpart>}{<label>}{<number>}{<nonumber>}`
   where <number> and <nonumber> are
   two variants of <bib-mark> (numbered or text-like). This information is
   read from `.ref` file and it is saved to macros
   `\_bib:<bibpart>/<label>` and `\_bim:<bibpart>/<number>`.
   First one includes <number> and second one includes <nonumber>.
   The `\_lastbn:<bibpart>` macro includes last number of
   bib-entry used in the document with given <bibpart>.
   A designer can use it to set appropriate
   indentation when printing the list of all bib-entries.
   \_cod -----------------------------

\_def\_Xbib#1#2#3#4{\_sxdef{_bib:#1/#2}{\_bibnn{#3}&}%
   \_if^#4^\_else\_sxdef{_bim:#1/#3}{#4}\_fi\_sxdef{_lastbn:#1}{#3}}

   \_doc -----------------------------
   \`\_citeA` `<label>,` processes one label from the list of labels given in the
   parameter of `\cite`, `\nocite`, `\rcite` or `\ecite` macros. It adds the
   <label> to a global list `\_ctlst:<bibpart>/` which will be used by `\usebib` (it
   must know what <labels> are used in the document to pick-up
   only relevant bib-entries from the database. Because we want to save
   space and to avoid duplications of <label> in the `\_ctlst:<bibpart>/`, we
   distinguish four cases:
   \begitems
   * `<label>` was not declared by \^`\_Xbib` before and it is first such a <label> in the
     document: Then `\_bib:<bibpart>/<label>` is undefined and we save label using
     \^`\_addcitelist`, write warning on the terminal and define
     `\_bib:<bibpart>/<label>` as empty.
   * `<label>` was not declared by \^`\_Xbib` before but it was used previously in the
     document: Then `\_bib:<bibpart>/<label>` is empty and we do nothing (only data to
     `\_savedcites` are saved).
   * `<label>` was declared by \^`\_Xbib` before and it is first such <label>
     used in the document: Then `\_bib:<bibpart>/<label>` includes \`\_bibnn``{<number>}&` and we
     test this case by the command `\if &\_bibnn{<number>}&`. This is true when `\_bibnn{<number>}`
     expands to empty. The <label> is saved by \^`\_addcitelist` and
     `\_bib:<bibpart>/<label>` is re-defined directly as <number>.
   * `<label>` was declared by \^`\_Xbib` and it was used previously in the
     document. Then we do nothing (only data to `\_savedcites` are saved.
   \enditems
   The `\_citeA` macro runs repeatedly over the whole list of <labels>.
   \_cod -----------------------------

\_def\_citeA #1#2,{\_if#1,\_else
   \_if *#1\_addcitelist{*}\_sxdef{_bib:\_bibp*}{}\_ea\_skiptorelax \_fi
   \_ifcsname _bib:\_bibp#1#2\_endcsname \_else
      \_addcitelist{#1#2}%
      \_opwarning{{\_the\_bibpart} \_noexpand\cite [#1#2] unknown. Try to TeX me again}\_openref
      \_incr\_unresolvedrefs
      \_addto\_savedcites{?,}\_def\_sortcitesA{}\_lastcitenum=0
      \_ea\_gdef \_csname _bib:\_bibp#1#2\_endcsname {}%
      \_ea\_skiptorelax \_fi
   \_ea\_ifx \_csname _bib:\_bibp#1#2\_endcsname \_empty
      \_addto\_savedcites{?,}\_def\_sortcitesA{}\_lastcitenum=0
      \_ea\_skiptorelax \_fi
   \_def\_bibnn##1{}%
   \_if &\_csname _bib:\_bibp#1#2\_endcsname
      \_def\_bibnn##1##2{##1}%
      \_addcitelist{#1#2}%
      \_sxdef{_bib:\_bibp#1#2}{\_csname _bib:\_bibp#1#2\_endcsname}%
   \_fi
   \_edef\_savedcites{\_savedcites \_csname _bib:\_bibp#1#2\_endcsname,}%
   \_relax
   \_ea\_citeA\_fi
}
\_let\_bibnn=\_relax

   \_doc ----------------------------
   Because we implement possibility of more independent bibliography lists
   distinguished by <bibpart>, the \`\_addcitelist``{<label>}` macro
   must add the <label> to given `\_ctlst:<bibpart>/`.\nl
   When `\_addcitelist` is processed before \^`\usebib`,
   then \^`\_citeI``[<label>]` is added. \^`\usebib` will use this list for selecting
   right records from `.bib` file. Then \^`\usebib` sets
   `\_ctlst:<bibpart>/` to `\_write`.\nl
   If `\_addcitelist` is processed after \^`\usebib`, then
   \`\_Xcite``{<bibpart>/}{<label>}` is saved to the `.ref`
   file. The `\_Xcite` creates `\_ctlstB:<bibpart>/` as a list of saved
   `\_citeI[<label>]`. Finally, \^`\usebib` concats both lists `\_ctlst:<bibpart>/`
   and `\_ctlstB:<bibpart>/` in the second \TeX/ run.
   \_cod ----------------------------

\_def\_addcitelist#1{%
   \_unless \_ifcsname _ctlst:\_bibp\_endcsname \_sxdef{_ctlst:\_bibp}{}\_fi
   \_ea \_ifx \_csname _ctlst:\_bibp\_endcsname \_write
       \_openref \_immediate\_wref\_Xcite{{\_bibp}{#1}}%
   \_else \_global \_ea\_addto \_csname _ctlst:\_bibp\_endcsname {\_citeI[#1]}\_fi
}
\_def\_Xcite#1#2{%
   \_unless \_ifcsname _ctlstB:#1\_endcsname \_sxdef{_ctlstB:#1}{}\_fi
   \_global \_ea\_addto \_csname _ctlstB:#1\_endcsname {\_citeI[#2]}%
}

   \_doc -----------------------------
   The `<bib-marks>` (in numeric or text form) are saved in \^`\_savedcites`
   macro separated by commas.
   The \`\_printsavedcites` prints them by normal order or sorted if
   \`\sortcitations` is specified or condensed if \`\shortcitations` is
   specified.\nl
   The \^`\sortcitations` appends the dummy number 300000 and we suppose that normal
   numbers of bib-entries are less than this constant.
   This constant is removed after the sorting algorithm.
   The \^`\shortcitations` sets simply `\_lastcitenum=1`.
   The macros for <bib-marks> printing follows (sorry, without detail
   documentation). They are documented in `opmac-d.pdf` (but only in Czech).
   \_cod -----------------------------

\_def\_printsavedcites{\_sortcitesA
   \_chardef\_tmpb=0 \_ea\_citeB\_savedcites,%
   \_ifnum\_tmpb>0 \_printdashcite{\_the\_tmpb}\_fi
}
\_def\_sortcitesA{}
\_def\_sortcitations{%
  \_def\_sortcitesA{\_edef\_savedcites{300000,\_ea}\_ea\_sortcitesB\_savedcites,%
                    \_def\_tmpa####1300000,{\_def\_savedcites{####1}}\_ea\_tmpa\_savedcites}%
}
\_def\_sortcitesB #1,{\_if $#1$%
  \_else
     \_mathchardef\_tmpa=#1
     \_edef\_savedcites{\_ea}\_ea\_sortcitesC \_savedcites\_end
     \_ea\_sortcitesB
  \_fi
}
\_def\_sortcitesC#1,{\_ifnum\_tmpa<#1\_edef\_tmpa{\_the\_tmpa,#1}\_ea\_sortcitesD
                   \_else\_edef\_savedcites{\_savedcites#1,}\_ea\_sortcitesC\_fi}
\_def\_sortcitesD#1\_end{\_edef\_savedcites{\_savedcites\_tmpa,#1}}

\_def\_citeB#1,{\_if$#1$\_else
   \_if?#1\_relax??%
      \_else
      \_ifnum\_lastcitenum=0   % only comma separated list
         \_printcite{#1}%
      \_else
         \_ifx\_citesep\_empty  % first cite item
            \_lastcitenum=#1\_relax
            \_printcite{#1}%
         \_else               % next cite item
            \_advance\_lastcitenum by1
            \_ifnum\_lastcitenum=#1\_relax % cosecutive cite item
               \_mathchardef\_tmpb=\_lastcitenum
            \_else  % there is a gap between cite items
               \_lastcitenum=#1\_relax
               \_ifnum\_tmpb=0 % previous items were printed
                  \_printcite{#1}%
               \_else
                  \_printdashcite{\_the\_tmpb}\_printcite{#1}\_chardef\_tmpb=0
   \_fi\_fi\_fi\_fi\_fi
   \_ea\_citeB\_fi
}
\_def\_shortcitations{\_lastcitenum=1 }

\_def\_printcite#1{\_citesep
   \_ilink[cite:\_bibp#1]{\_citelinkA{#1}}\_def\_citesep{,\_hskip.2em\_relax}}
\_def\_printdashcite#1{\_ifmmode-\_else\_hbox{--}\_fi\_ilink[cite:\_bibp#1]{\_citelinkA{#1}}}
\_def\_citesep{}

\_def\_nonumcitations{\_lastcitenum=0\_def\_sortcitesA{}\_def\_etalchar##1{$^{##1}$}%
   \_def\_citelinkA##1{\_trycs{_bim:\_bibp##1}
       {##1\_opwarning{\_noexpand\nonumcitations + empty bibmark. Maybe bad bib-style}}}%
}
\_def\_citelinkA{}

\_public \nonumcitations \sortcitations \shortcitations ;

   \_doc -----------------------------
   The \`\bib` `[<label>]` or `\bib [<label>] ={<bib-mark>}` prints one bib-entry
   without reading any database. The bib-entry follows after this command.
   This command counts the used `\bib`s from one by `\bibnum` counter and
   saves \^`\_Xbib``{<bibpart>}{<label>}{<number>}{<nonumber>}` into `.ref` file
   immediately using \`\_wbib``{<label>}{<number>}{<nonumber>}`.
   This is the core of creation of mapping from `<labels>` to `<number>` and
   `<nonumber>`.\nl
   \`\_bibA` and \`\_bibB` implement the scanner of the optional argument
   with the \^`\bibmark`.\nl
   \`\_bibgl` is `\relax` by default but \^`\slides` do `\let\_bibgl=\_global`.\nl
   \`\_dbib``{<label>}` creates destination for hyperlinks.
   \_cod -----------------------------

\_def\_bib[#1]{\_def\_tmp{\_isnextchar={\_bibA[#1]}{\_bibmark={}\_bibB[#1]}}%
   \_nospaceafter\_tmp} % ignore optional space
\_def\_bibA[#1]=#2{\_bibmark={#2}\_bibB[#1]}
\_def\_bibB[#1]{\_par \_bibskip
   \_bibgl\_advance\_bibnum by1
   \_noindent \_def\_tmpb{#1}\_dbib{#1}\_wbib{#1}{\_the\_bibnum}{\_the\_bibmark}%
   \_printbib \_ignorespaces
}
\_def\_dbib#1{\_dest[cite:\_bibp\_the\_bibnum]\_printlabel{#1}}
\_def\_wbib#1#2#3{%
   \_ifx\_wref\_wrefrelax\_else \_immediate\_wref\_Xbib{{\_the\_bibpart}{#1}{#2}{#3}}\_fi
   \_unless \_ifcsname bib:\_bibp#1\_endcsname \_Xbib{\_the\_bibpart}{#1}{#2}{#3}\_fi
}
\_let\_bibgl=\_relax

\_public \bib ;

   \_doc -----------------------------
   The \`\_printbib` prints the bib-entry itself. You can re-define it if you
   want a different design. The `\_pritbib` starts in horizontal mode after
   `\noindent` and after the eventual hyperlink destination is inserted.
   By default, the `\_printbib` sets the indentation
   by `\hangindent` and prints numeric <bib-marks> by
   `\llap{[\the\bibnum]}` If `\nonumcitations` then the `\_citelinkA` is not
   empty and <bib-marks> (`\the\bibnum` nor `\the\bibmark`) are not printed.
   The text of bib-entry follows. User can create this text manually
   using `\bib` command or it is generated automatically from a `.bib` database
   by `\usebib` command.

   The vertical space between bib-entries is controlled by \`\_bibskip` macro.
   \_cod -----------------------------

\_def \_printbib {\_hangindent=\_iindent
   \_ifx\_citelinkA\_empty \_hskip\_iindent \_llap{[\_the\_bibnum] }\_fi
}
\_def \_bibskip {\_ifnum\_bibnum>0 \_smallskip \_fi}

   \_doc -----------------------------
   The \`\usebib` command is implemented in `usebib.opm` file which is loaded
   when the `\usebib` command is used first.
   The `usebib.opm` file loads the `librarian.tex` for scanning the `.bib`
   files. See the section~\ref[usebib], where the file `usebib.opm` is
   documented.
   \_cod -----------------------------

\_def\_usebib{\_par \_opinput {usebib.opm} \_usebib}
\_def\usebib{\_usebib}

   \_doc ------------------------------
   \_fw\`\nobibwarning` `[<list of bib-labels>]`
   declares a list of bib labels
   which are not fully declared in `.bib` file but we want to suppress the
   warning about it. List of bib labels are comma-separated case sensitive
   list without spaces.
   \_cod ------------------------------

\_def\_nobibwarnlist{,}
\_def\_nobibwarning[#1]{\_global\_addto\_nobibwarnlist{#1,}}
\_public \nobibwarning ;

\_endcode % -------------------------------------

See end of the `usebib.opm` file for documentation about creating style
files `bib-<style>.opm`.

See end of the `bib-iso690.opm` file for large documentation about `.bib` files
structure and about the usage of `iso690` bib-style.

History:
2021-04-13 ... \bibpart implemented
2021-04-13 ... \_bibgl introduced (used in \slides)
2020-03-09 ... released
