An Extension of the L^{A}TEX-Theorem Evironment^{∗}

Wolfgang May^{†} Institut für Informatik, Universität Freiburg Am Flughafen 17 D-79110 Freiburg

Federal Republic of Germany Andreas Schlechte^{‡} Am Klepperberg 2 D-38678 Clausthal-Zellerfeld Federal Republic of Germany

1997/07/15

Abstract

ntheorem.sty is a package for handling theorem-like environments. Aditionally to several features for defining the layout of theorem-like environments which can be regarded to be standard requirements for a theorem-package, it provides solutions for two related problems: placement of endmarks and generation of lists of theorem-like environments.

In contrast to former approaches, it solves the problem of setting endmarks of theorem-like environments (theorems, definitions, examples, and proofs) automatically at the right positions, even if the environment ends with a displaymath or (even nested) list environments, it also copes with the amsmath package. This is done in the same manner as the handling of labels by using the .aux file.

It also introduces the generation of lists of theorem-like environments in the same manner as listoffigures.

After running L^{A}TEX several times (depending on the complexity of references, in general, three runs are sufficient), the endmarks are set correctly, and theoremlists are generated.

Since ntheorem.sty uses the standard L^{A}TEX \newtheorem command, existing documents can be switched to ntheorem.sty without having to change the .tex file. Also, it is compatible with L^{A}TEX files using theorem.sty written by Frank Mittelbach.

∗This file has version number 1.03, last revised 1997/07/15.

†may@informatik.uni-freiburg.de ‡Andreas.Schlechte@tu-clausthal.de

Contents

1 Introduction 3

2 The User-Interface 3 2.1 How to include the package . . . . . . . . . . . . . . . . . . . . . . . 3 2.2 Defining New Theorem Sets . . . . . . . . . . . . . . . . . . . . . . . 4 2.3 Defining the Layout of Theorem Sets . . . . . . . . . . . . . . . . . . 4

2.3.1 Parameters for Individual Sets . . . . . . . . . . . . . . . . . 4 2.3.2 Common Parameters for all Theorem Sets . . . . . . . . . . . 5 2.3.3 Font Selection . . . . . . . . . . . . . . . . . . . . . . . . . . . 5 2.3.4 Predefined theorem styles . . . . . . . . . . . . . . . . . . . . 5 2.3.5 Default Setting . . . . . . . . . . . . . . . . . . . . . . . . . . 6 2.3.6 A Standard Set of Theorems . . . . . . . . . . . . . . . . . . 6 2.3.7 Customization and Local Settings . . . . . . . . . . . . . . . 7

2.4 Generating Theoremlists . . . . . . . . . . . . . . . . . . . . . . . . . 7 2.4.1 Defining the List Layout . . . . . . . . . . . . . . . . . . . . . 7 2.4.2 Writing Extra Stuff to Theorem File . . . . . . . . . . . . . . 8

2.5 For Experts: Defining Layout Styles . . . . . . . . . . . . . . . . . . 8 2.5.1 Defining New Theorem Layouts . . . . . . . . . . . . . . . . . 8 2.5.2 Defining New Theorem List Layouts . . . . . . . . . . . . . . 9

2.6 Setting End Marks . . . . . . . . . . . . . . . . . . . . . . . . . . . . 9

3 Possible Interferences 10 3.1 Interfering Document Options. . . . . . . . . . . . . . . . . . . . . . 10 3.2 Combination with amslatex. . . . . . . . . . . . . . . . . . . . . . . . 10

3.2.1 amsmath . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 10 3.2.2 amsthm . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 10

4 Examples 11

5 The End Mark Algorithm 16 5.1 The Idea . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 16 5.2 The Realization . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 17

6 Problems and Questions 18 6.1 Known Limitations . . . . . . . . . . . . . . . . . . . . . . . . . . . . 18 6.2 Known “Bugs” and Problems . . . . . . . . . . . . . . . . . . . . . . 19 6.3 Open Questions . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 20

7 Code Documentation 21

7.1 Documentation of the Macros . . . . . . . . . . . . . . . . . . . . . . 21 7.1.1 Thmmarks-Related Stuff . . . . . . . . . . . . . . . . . . . . . 21 7.1.2 Option leqno to Thmmarks . . . . . . . . . . . . . . . . . . . 26 7.1.3 Option fleqn to Thmmarks . . . . . . . . . . . . . . . . . . . 27 7.1.4 Option amsmath to Thmmarks . . . . . . . . . . . . . . . . . 28 7.1.5 Theorem-Layout Stuff . . . . . . . . . . . . . . . . . . . . . . 33 7.1.6 Theorem-Environment Handling Stuff . . . . . . . . . . . . . 37 7.1.7 Generation of Theorem Lists . . . . . . . . . . . . . . . . . . 43 7.1.8 Auxiliary macros . . . . . . . . . . . . . . . . . . . . . . . . . 47 7.1.9 Other Things . . . . . . . . . . . . . . . . . . . . . . . . . . . 48

7.2 The Standard Configuration . . . . . . . . . . . . . . . . . . . . . . . 48

8 History and Acknowledgements 49 8.1 The endmark-Story (Wolfgang May) . . . . . . . . . . . . . . . . . . 49 8.2 Lists, Lists, Lists (Andreas Schlechte) . . . . . . . . . . . . . . . . . 50 8.3 Let’s come together . . . . . . . . . . . . . . . . . . . . . . . . . . . . 50 8.4 Acknowledgements . . . . . . . . . . . . . . . . . . . . . . . . . . . . 50

1 Introduction

For our purposes here, “theorems” are labelled enunciations, often set off from the main text by extra space and a font change. Theorems, corollaries, conjectures, definitions, examples, remarks, and proofs are all instances of “theorems”. The “header” of these structures is composed of the type of the structure (such as Theorem or Remark), a number which serializes the instances of the same type throughout the document, and an optional name (such as “Correctness Theorem”). The layout of theorems can be changed by parameters as the fonts of the header and the body, the way how to arrange the headers, the indentation, and the way of numbering it. Confronted with these requirements, theorem.sty, a style for dealing with theorem layout was developed by Frank Mittelbach which was the standard theorem-environment for long time. But then the desire for additional features like “endmarks” and “theorem-lists” arose. Two extensions of theorem.sty were developped: One for handling endmarks, thmmarks.sty and one for generating lists, newthm.sty. Thus, Frank Mittelbach suggested to combine the new features into one “standard-to-be” package. And now, here it is.

2 The User-Interface

2.1 How to include the package

The package ntheorem.sty is included by

     \usepackage[⟨options⟩]{ntheorem.sty},

where the optional parameter ⟨options⟩ selects predefined configurations and special requirements. The following ⟨options⟩ are available by now:

thmmarks enables the automatical placement of endmarks (see 2.3).

amsmath adapts [thmmarks] to be used with the amsmath-package (see 3.2).

amsthm provides compatibility with the theorem-layout commands of the amsthmpackage (see 3.2).

standard activates a standard set of theorems (see 2.3.6).

2.2 Defining New Theorem Sets

\newtheorem The syntax and semantics is exactly the same as in standard L^{A}TEX: the command \newtheorem defines a new “theorem set” or “theorem-like structure”. Two required arguments name the new environment set and give the text to be typeset with each instance of the new “set”, while an optional argument determines how the “set” is enumerated:

\newtheorem{foo}{bar} The theorem set foo (whose name is bar) uses its own counter.

\newtheorem{foo2}[foo]{bar2} The theorem set foo2 (printed name bar2) uses the same counter as the theorem set foo.

\newtheorem{foo3}{bar}[section] The theorem set foo3 (printed name bar)

is enumerated within the counter section, i.e. with every new \section the enumeration begins again with 1, and the enumeration is composed from the section-number and the theorem counter itself.

For every environment ⟨name⟩ defined by \newtheorem, two enviroments ⟨name⟩ and ⟨name* ⟩ are defined. In the main document, they have exactly the same effect, but the latter causes no entry in the respective list of theorems (cf. \section and \section*), see also Section 2.4.

\renewtheorem Theorem sets can be redefined by \renewtheorem, with the same arguments as explained for \newtheorem. When redefining a theorem set, the counter is not re-initialized.

2.3 Defining the Layout of Theorem Sets

2.3.1 Parameters for Individual Sets

For every theorem-like environment, the user can set additional parameters by setting several switches and then calling \newtheorem. The layout of a theorem set is defined with the values of the switches at the time \newtheorem is called.

\theoremstyle • \theoremstyle{⟨style⟩}: The general structure of the theorem layout is defined via its \theoremstyle. \ntheorem provides several predefined styles including those of Frank Mittelbach’s theorem.sty (cf. Section 2.3.4. Additional styles can be defined by \newtheoremstyle (cf. Section2.5.1).

\theoremheaderfont • \theoremheaderfont{⟨fontcmds⟩}: The theorem header is set in the font specified by ⟨fontcmds⟩.

In contrast to theorem.sty, \theoremheaderfont can be set individually for each environment type.

\theorembodyfont • \theorembodyfont{⟨fontcmds⟩}: The theorem body is set in the font specified by ⟨fontcmds⟩.

\theoremseparator • \theoremseparator{⟨thing⟩}: ⟨thing⟩ separates the header from the body of the theorem-environment. E.g., ⟨thing⟩ can be “:” or “.”.

\theoremindent • \theoremindent{⟨dimen⟩} can be used to indent the theorem wrt. the surrounding text.

! It’s a ‘(dimen)’, so the user shouldn’t try to specify a plus or minus part, cause this leads to an error.

\theoremnumbering • \theoremnumbering{⟨style⟩} specifies the appearance of the numbering of the theorem set. Possible ⟨styles⟩ are arabic (default), alph, Alph, roman,

     Roman, greek, Greek, and fnsymbol.

Clearly, if a theorem-environment uses the counter of another environment type, also the numbering style of that environment is used.

\theoremsymbol  • \theoremsymbol{⟨thing⟩}: This is only active if ntheorem.sty is loaded with

option [thmmarks]. ⟨thing⟩ is set as an endmark at the end of every instance of the environment. If no symbol should appear, say \theoremsymbol{}.

The flexibility provided by these command should relieve the users from the ugly hacking in \newtheorem to fit most of the requirements stated by publishers or supervisors.

2.3.2 Common Parameters for all Theorem Sets

\theorempreskipamount These additional parameters affect the vertical space around theorem environments:

\theorempostskipamount  \theorempreskipamount and \theorempostskipamount define, respectively, the

spacing before and after such an environment. These parameters apply for all theorem sets and can be manipulated with the ordinary length macros. They are rubber lengths, (‘skips’), and therefore can contain plus and minus parts.

2.3.3 Font Selection

From the document structuring point of view, theorem environments are regarded as special parts inside a document. Furthermore, the theorem header is only a distinguished part of a theorem environment. Thus, \theoremheaderfont inherits characteristics of \theorembodyfont which also inherits in characteristics of the font of the surrounding environment. Thus, if for example \theorembodyfont is

\itshape and \theoremheaderfont is \bfseries the font selected for the header

will have the characteristics ‘bold extended italic’. If this is not desired, the corresponding property has to be explicitly overwritten in \theoremheaderfont, e.g.

by \theoremheaderfont{\normalfont\bfseries}

2.3.4 Predefined theorem styles

The following theorem styles are predefined, covering those from theorem.sty:

plain This theorem style emulates the original L^{A}TEX definition, except that additionally the parameters \theorem...skipamount are used.

break In this style, the theorem header is followed by a line break.

change Header number and text are interchanged, without a line break.

changebreak Like change, but with a line break after the header.

margin The number is set in the left margin, without a line break. marginbreak Like margin, but with a line break after the header.

nonumberplain Like plain, without number (e.g. for proofs).

nonumberbreak Like break, without number.

2.3.5 Default Setting

If no option is given, i.e. ntheorem.sty is loaded by \usepackage{ntheorem.sty},

the following default is set up:

     \theoremstyle{plain},
     \theoremheaderfont{\normalfont\bfseries} and
     \theorembodyfont{\itshape},
     \theoremseparator{},
     \theoremindent0cm,
     \theoremnumbering{arabic},
     \theoremsymbol{}.

Thus, by only saying \newtheorem{...}{...}, the user gets the same layout as in standard L^{A}TEX.

2.3.6 A Standard Set of Theorems

A standard configuration of theorem sets is provided within the file ntheorem.std, which will be included by the option [standard]. It uses the amssymb and latexsym (automatically loaded) packages and defines the following sets:

Theorems: Theorem, Lemma, Proposition, Corollary, Satz, Korollar,

Definitions: Definition,

Examples: Example, Beispiel,
Remarks: Anmerkung, Bemerkung, Remark,
Proofs:  Proof and Beweis.

These theorem sets seem to be the most frequently used environments in english and german documents. We set the theoremstyle plain, bodyfont \itshape, Headerfont \bfseries, and chose the endmark (theoremsymbol) \ensuremath{_\Box} for all theorem-like environments^{1}. For the definition-, remark- and example-like sets, the above setting is used, except bodyfont \upshape. The proof-like sets are handled a bit different. We’ve chosen the style nonumberplain, bodyfont \upshape, headerfont \scshape and \ensuremath{_\blacksquare} as endmark. For a more detailed information look at ntheorem.std or at the code-section.

1Note, that mathmode is ensured for the symbol.

2.3.7 Customization and Local Settings

To prevent the user from overwriting or changing ntheorem.std, we’ve added the possibility to use a configuration-file. If one places the file ntheorem.cfg in a path, available to TEX, this file is read by the main part. Thus, just a copy of ntheorem.std to ntheorem.cfg must be made which then can freely be modified by the user. Note, that if a configuration-file exists, this will always be used (I.e. with option standard and an existing configuration-file, the .cfg file will be used and the .std file won’t.

2.4 Generating Theoremlists

\listtheorems Similar to the L^{A}TEX command \listoffigures, any theorem set defined with a \newtheorem statement may be listed at any place in your document by

     \listtheorems{⟨list⟩}

The argument ⟨list⟩ is a comma-separated list of the theorem sets to be listed. For a theorem set ⟨name⟩, only the instances are listed which are instantiated by \begin{⟨name⟩}. Those instantiated by \begin{⟨name⟩*} are omitted (cf.

\section and \section*).

For example, \listtheorems{Corollary,Lemma} leads to a list of all instances of one of the theorem sets “Corollary” or “Lemma”. Note, that the set name given to the command is the first argument which is specified by \newtheorem which is

also the one to be used in \begin{theorem} ... \end{theorem}.

If \listtheorems is called for a set name which is not defined via \newtheorem, the user is informed that a list is generated, but there will be no typeset output at all.

2.4.1 Defining the List Layout

\theoremlisttype Theoremlists can be formatted in different ways. Analogous to theorem layout, there are several predefined types which can be selected by

     \theoremlisttype{⟨type⟩}

The following four ⟨type⟩s are available (for examples, the user is referred to section 4).

all List any theorem of the specified set by number, (optional) name and pagenumber. This one is also the default value.

allname Like all, additionally with leading theoremname.

opt Analogous to all, but only the theorems which have an optional name are listed.

optname Like opt, with leading theoremname.

2.4.2 Writing Extra Stuff to Theorem File Similar to \addcontentsline and \addtocontents, additional entries to theoremlists are supported. Since entries to theoremlists are a bit more intricate than entries to the lists maintained by standard L^{A}TEX \addcontentsline and \addtocontents cannot be used in a straightforward way^{2}.

\addtheoremline Analogous to \addcontentsline, an extra entry for a theorem list can be made by

     \addtheoremline{⟨name⟩}{⟨text⟩}

where ⟨name⟩ is the name of a valid theorem set and ⟨text⟩ is the text, which should appear in the list. For example,

     \addtheoremline{Example}{Extra Entry with number}

generates an entry with the following characteristics:

• The Label of the theorem “Example” is used.

• The current value of the counter for “Example” is used

• The current pagenumber is used.

• The specified text is the optional text for the theorem. Thus, the above command has the same effect as it would be for

     \begin{Example}[Extra Entry with number] \end{Example}

except, that there would be no output of the theorem, and the counter isn’t advanced.

\addtheoremline* Alternatively you can use

     \addtheoremline*{Example}{Extra Entry}

which is the same as above, except that the entry appears without number.

\addtotheoremfile Sometimes, e.g. for long lists, special control sequences (e.g. a pagebreak) or addi-

tional text should be inserted into a list. This is done by

     \addtotheoremfile[⟨name⟩]{⟨text⟩}

where ⟨name⟩ is the name of a theorem set and ⟨text⟩ is the text to be written into the theorem file. If the optional argument ⟨name⟩ is omitted, the given text is inserted in every list, otherwise it is only inserted for the given theorem set.

2.5 For Experts: Defining Layout Styles

2.5.1 Defining New Theorem Layouts

\newtheoremstyle Additional layout styles for theorems can be defined by \newtheoremstyle{⟨name⟩}{⟨head⟩}{⟨opt-head⟩}.

2for a theorem, its number has to be stored explicitly since different theorem sets can use the same counter. Also, it is optional to reset the counter for each section.

After this, \theoremstyle{⟨name⟩} is a valid \theoremstyle. Here, ⟨head⟩ has to be a statement using two arguments, ##1, containing the keyword, and ##2, containing the number. ⟨opt-head⟩ has to be a statement using three arguments where the additional argument ##3 contains the optional parameter. Since L^{A}TEX implements theorem-like environments by \trivlists, both header

declarations must be of the form \item[... \theorem@headerfont ...]...,

where the dotted parts can be formulated by the user. If there are some statements producing output after the \item[...], you have to care about implicit spaces. Because of the @, if \newtheoremstyle is used in a .tex file, it has to be put

between \makeatletter and \makeatother.

For details, look at the code documentation or the definitions of the predefined theoremstyles.

\renewtheoremstyle Theorem styles can be redefined by \renewtheoremstyle, with the same arguments

as explained for \newtheoremstyle.

2.5.2 Defining New Theorem List Layouts

\newtheoremlisttype Analogous, additional layouts for theorem lists can be defined by

     \newtheoremlisttype{⟨name⟩}{⟨start⟩}{⟨line⟩ }{⟨end⟩}.

The first argument, ⟨name⟩, is the name of the listtype, which can the be used as a valid \theoremlisttype. ⟨start⟩ is the sequence of commands to be executed at the very beginning of the list. Corresponding, ⟨end⟩ will be executed at the end of the list. These two are set to do nothing in the standard-types. ⟨line⟩ is the part to be called for every entry of the list. It has to be a statement using four arguments: ##1 will be replaced with the name of the theorem, ##2 with the number, ##3 with the theorem’s optional text and ##4 with the pagenumber.

\renewtheoremlisttype Theorem list types can be redefined by \renewtheoremlisttype, with the same arguments as explained for \newtheoremlisttype.

2.6 Setting End Marks

The automatic placement of endmarks is activated by calling ntheorem.sty with the option [thmmarks]. Since then, the endmarks are set automatically, there are only a few commands for dealing with very special situations.

\qed If in a single environment, the user wants to replace the standard endmark by \qedsymbol some other, this can be done by saying \qed, if \qedsymbol has been defined by

\qedsymbol{⟨something⟩} (in option standard, \qedsymbol is defined to be the symbol used for proofs, since a potential use of this features is to close trivial corollaries without explicitly proving them). Additionally, if in a single environment of a theorem set, that is defined without an endmark, the user wants to set an endmark, this is done with \qedsymbol and \qed as described above. \qedsymbol can be redefined everywhere in the document.

\NoEndMark On the other hand, if in some situation, the user decides to set the endmark man- \TheoremSymbol ually (e.g. inside a figure or a minipage), the automatic handling can be turned

off by \NoEndMark for the current environment. Then – assumed that he current environment is of type ⟨name⟩, the endmark can manually be set by just saying

\⟨name⟩Symbol.

3 Possible Interferences

Since ntheorem reimplements the handling of theorem-environments completely, it is incompatible with every package also concerning those macros. Additionally, the thmmarks algorithm for placing endmarks requires modifications of several environments (cf. Section 7). Thus, environments which are reimplemented or additionally defined by document options or styles are not covered by the endmark algorithm of ntheorem.sty.

3.1 Interfering Document Options.

ntheorem.sty also copes with the usual document options leqno and fleqn^{3}. If one of those options is used in the \documentclass declaration, it is automatically recognized by the thmmarks part of ntheorem.sty. If one of those options is not used in \documentclass, but with amsmath (see next section), it must not be specified for ntheorem, since all amsmath environments detect this option by themselves.

3.2 Combination with amslatex.

ntheorem.sty interferes with amsmath.sty and amsthm.sty.

Note, that the LaTeX amstex package amstex.sty (L^{A}TEX2.09) is obsolete and you should use amsmath and amstext for L^{A}TEX 2ε instead. We would be happy if someone knowing and using amsmath would join the development and maintenance of this style.

3.2.1 amsmath

The math environments of amsmath are adapted in the option [amsmath], (i.e., if

ntheorem.sty is called with option [thmmarks], the statement \usepackage{amsmath}
implies option \usepackage[amsmath,thmmarks]{ntheorem}). Note, that amsmath

has to be loaded before ntheorem since the definitions have to be overwritten.

3.2.2 amsthm

amsthm.sty conflicts with the definition of theorem layouts in theorem.sty, some features of amsthm.sty have been incorporated into option [amsthm] which has to

be used instead of \usepackage{amsthm}.

The Option provides theoremstyles plain, definition, and remark, and a proof environment as in amsthm.sty. The \newtheorem* command is defined even without this option. The com-

mand \newtheoremstyle is not taken over from amsthm.sty. Also, \swapnumbers

is not implemented. Here, the user has to express his definitions by the \newtheoremstyle command provided by ntheorem.sty, including the use of

\theoremheaderfont and \theorembodyfont. The options [amsthm] and [standard]

are in conflict since they both define an environment proof.

3although for fleqn and long formulas reaching to the right margin, equation numbers and endmarks can be smashed over the formula since fleqn does not use \eqno for controlling the setting of the equation number.

Thus, we recommend not to use amsthm, since the features for defining theorem-like environments in ntheorem.sty—following theorem.sty—seem to be more intuitive and user-friendly.

4 Examples

The setting is as follows.

• For Theorems:

\theoremstyle{marginbreak}
\theoremheaderfont{\normalfont\bfseries}\theorembodyfont{\slshape}
\theoremsymbol{\ensuremath{\diamondsuit}}
\theoremseparator{:}
\newtheorem{Theorem}{Theorem}

• For Lemmas:

\theoremstyle{changebreak}
\theoremsymbol{\ensuremath{\heartsuit}}
\theoremindent0.5cm
\theoremnumbering{greek}
\newtheorem{Lemma}{Lemma}

• For Corollaries:

\theoremindent0cm
\theoremsymbol{\ensuremath{\spadesuit}}
\theoremnumbering{arabic}
\newtheorem{Corollary}[Theorem]{Corollary}

• For Examples:

\theoremstyle{change}
\theorembodyfont{\upshape}
\theoremsymbol{\ensuremath{\ast}}
\theoremseparator{}
\newtheorem{Example}{Example}

• For Definitions:

\theoremstyle{plain}
\theoremsymbol{\ensuremath{\clubsuit}}
\theoremseparator{.}
\newtheorem{Definition}{Definition}

• For Proofs:

\theoremheaderfont{\sc}\theorembodyfont{\upshape}
\theoremstyle{nonumberplain}
\theoremseparator{}
\theoremsymbol{\rule{1ex}{1ex}}
\newtheorem{Proof}{Proof}

Note, that parts of the setting are inherited. For instance, the fonts are not reset before defining “Lemma”, so the font setting of “Theorem” is used.

1 Example (Simple one) The first example is just a text. In the next examples, it is shown how an endmark is put at a displaymath, a single equation and both types of eqnarrays. ∗

1 Theorem (Long Theorem): The examples are put into this theorem environment. The next example will not appear in the list of examples since it is written as

     \begin{Example*} ... \end{Example*}

2 Example (Ending with a displayed formula) Look, the endmark is really at the bottom of the line:

f^{(n)}(z) = \frac{n!}{2πi} ∫_{∂D} \frac{f(ζ)}{(ζ − z)^{n+1}} dζ  ∗

At this point, we add an additional entry without number in the Example list:

 \addtheoremline*{Example}{Extra Entry}

α Lemma (Display with array):

Lemmata are indented and numbered with greek symbols. Also for displayed arrays of this form, it looks good:

    \[\begin{array}{l}
         a = \begin{array}[t]{l}
               first\ line \\
               second\ line
             \end{array}%
         \mbox{try to put this text in the lowest line}\end{array}\]

Just try to get this with the presented array structure ... without using dirty tricks, you can position the outer array either [t], [c], or [b], and you will not get the desired effect.

a = \begin{matrix}first line \\ second line \end{matrix} try to put this text in the lowest line  ♡

β Lemma (Equation):

For equations, we decided to put the endmark after the equation number, which is vertically centered. Currently, we do not know, how to get the equation number centered and the endmark at the bottom (one has to know the internal height of the math material) ... If anyone knows, please inform us.

∫_{γ} f(z) dz := ∫_{a}^{b} f(γ(t))γ′(t) dt  (1) ♡

With the break-theoremstyles, if the environment is labeled and written as

     \begin{Lemma}[Breakstyle]\label{breakstyle}

γ Lemma (Breakstyle):

you see, there is a leading space …

If a percent (comment) (or an explicit \ignorespaces) is put directly after the label, e.g.

       \begin{Lemma}[Breakstyle]\label{breakstyle}%,

the space disappears.

From the predefined styles, this is exactly the case for the break-styles. That’s no bug, it’s L^{A}TEX-immanent. The example goes on with an eqnarray:

f(z) = \frac{1}{2πi} ∫_{∂D} \frac{f(ζ)}{ζ − z} dζ  (2)

= \frac{1}{2π} ∫_{0}^{2π}f(z_{0} + re^{it})dt  (3) ♡

Proof (of nothing)

f(z) = \frac{1}{2πi} ∫_{∂D} \frac{f(ζ)}{ζ − z} dζ

= \frac{1}{2π} ∫_{0}^{2π}f(z_{0} + re^{it})dt

That’s it (the end of the Theorem). ♢

If there are some environments in the same thm-environment, the last gets the endmark:

Definition 1 (With a list).

∫_{γ} f(z) dz := ∫_{a}^{b} f(γ(t))γ′(t) dt  (4)

• you’ve seen, how it works for text and

• math environments,

• and it works for lists. ♣

2 Corollary (Q.E.D.): And here is a trivial corollary, which is ended by \qedsymbol{\textrm{q.e.d}} and \qed. q.e.d

3 Example

f^{(n)}(z) = \frac{n!}{2πi} ∫_{∂D} \frac{f(ζ)}{(ζ − z)^{n+1}} dζ

If there is some text after an environment, the endmark is put after the text. ∗ The next one is done by the following sequence. Note, that ~\hfill~ is inserted to prevent L^{A}TEX from using its nested list management (a verbatim is also a trivlist), i.e. this causes L^{A}TEX to start the verbatim-Part in a new line.

     \begin{Example}
     ~\hfill~
     \begin{verbatim}
     And, it also works for verbatim
     ... when the \end{verbatim} is in the
     same line as the text ends. \end{verbatim}

^this space is important !!

     \end{Example}

4 Example (Using verbatim)

 And, it also works for verbatim
 ... when the end{verbatim} is in the
 same line as the text ends.  ∗

Now, there is a corollary which should appear with a different name in the list of corollaries:

     \begin{Corollary*}[title in text]
     ...
     \end{Corollary*} \addtheoremline{Corollary}{title in list}

3 Corollary (title in text):

It also works in the center

environment. ♠

Here is an example for turning off the endmark automatics and manual handling:

 \begin{Theorem}[Manual End Mark]
 a line of text with a manually set endmark \hfill\TheoremSymbol \\
 some more text, but no automatic endmark set. \NoEndMark
 \end{Theorem}

4 Theorem (Manual End Mark): a line of text with a manually set endmark ♢ some more text, but no automatic endmark set.

Also, one should note, that \hfill is inserted to set the endmark at the right margin.

5 Example (Quickie) It also works for short one’s. ∗

I am tired of the greek numbers and the indentation for lemmata ... so redefine it:

     \theoremstyle{changebreak}
     \theoremheaderfont{\normalfont\bfseries}\theorembodyfont{\slshape}
     \theoremsymbol{\ensuremath{\heartsuit}}

\theoremsymbol{\ensuremath{\diamondsuit}}
\theoremseparator{:}
\theoremindent0.5cm
\theoremnumbering{arabic}
\renewtheorem{Lemma}{Lemma}

4 Lemma: another lemma, with arabic numbering ... note that the numbering continues. ♢

List of Theorems and friends

Note, that we put the following lists into the quote-environment to emphazise them from the surrounding text. So the lists are indented slightly at the margin. With

\addtotheoremfile{Added into all theorem lists},

in every list, an additional line of text would be inserted. But it isn’t actually done in this documentation since we want to use different list formats. Only for the list of Examples, this one is added:

\addtotheoremfile[Example]{Only concerning Example lists}

With

\theoremlisttype{all}
\listtheorems{Lemma},

all lemmas are listed:

α Display with array . . . . . . . . . . . . . . . . . . . . . . . 12

β Equation . . . . . . . . . . . . . . . . . . . . . . . . . . . . 12

γ Breakstyle . . . . . . . . . . . . . . . . . . . . . . . . . . . . 13

4  . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 15
5  . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 19
6  . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 19

From the examples, only those are listed which have an optional name:

\theoremlisttype{opt}
\listtheorems{Example}

leads to

0 Extra Entry with number . . . . . . . . . . . . . . . . . . . 8

Extra Entry . . . . . . . . . . . . . . . . . . . . . . . . . . . 8

1 Simple one . . . . . . . . . . . . . . . . . . . . . . . . . . . 12

Extra Entry . . . . . . . . . . . . . . . . . . . . . . . . . . . 12

4 Using verbatim . . . . . . . . . . . . . . . . . . . . . . . . . 14

5 Quickie . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 14

Only concerning Example lists One should note the line Only concerning example lists, which was added by the

\addtotheoremfile-statement above.

For the next list, another layout, using the tabular-environment, is defined:

   \newtheoremlisttype{tab}%
     {\begin{tabular*}{\linewidth}{@{}lrl@{\extracolsep{\fill}}r@{}}}%
     {##1&##2&##3&##4\\}%
     {\end{tabular*}}

Thus, by saying

     \theoremlisttype{tab}
     \listtheorems{Theorem,Lemma},

theorems and lemmata are listed:

Theorem 1 Long Theorem  12
Lemma α Display with array  12
Lemma β Equation  12
Lemma γ Breakstyle  13
Theorem 4 Manual End Mark  14
Lemma 4  15
Theorem 5 Correctness  17
Theorem 6 Completeness  18
Lemma 5  19
Lemma 6  19
Theorem 7  19

L^{A}TEX-lists can also be used to format the theoremlist. The input

   \newtheoremlisttype{list}%
     {\begin{trivlist}\item}
     {\item[##2 ##1:]\ ##3\dotfill ##4}%
     {\end{trivlist}}
   \theoremlisttype{list}
   \listtheorems{Corollary}

leads to

2 Corollary: Q.E.D. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 13

3 Corollary: title in list . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 14

In this example, after the item, \␣ is used instead of ␣, because in the latter case, \dotfill will produce an error if the optional argument (##3) is missing.

5 The End Mark Algorithm

5.1 The Idea

The handling of endmarks with thmmarks.sty is based on the same two-pass principle as the handling of labels: the necessary information about endmarks is contained in the .aux file. With thmmarks.sty, TEX is always aware whether it is in some theorem-like environment. There, potential positions for endmarks can be 1. at the end of simple text lines in open text,

2. at the end of displaymaths,

3. at the end of equations or equationarrays, or

4. at the end of text lines at the end of lists (or, more general, trivlists, such

     as verbatim or center).

The problem is, that in the cases (2)–(4), the endmarks has to be placed in a box which is already shipped out, when \end{...} is processed. Thus, in those situations, TEX needs to know from the .aux file, whether is has to put an endmark. When TEX is in a theorem-like environment and comes to one of the points mentioned in (2)–(4), and the .aux file says that there is an endmark, then it is put there. Anyway, it maintains a counter of the potential positions of an end mark in the current theorem-like environment. When it comes to an \end{theorem}, it looks if it is in situation (1) (then the endmark is simply put at the end of the current line). Otherwise, the last horizontal box is already shipped out (thus it contains a situation (2)–(4)) and the endmark must be set in it. In this case, a note is written in the .aux file, where the endmark actually has to be set (ie, at the latest potential point for setting an endmark inside the theorem).

5.2 The Realization

Let ⟨env⟩ be a theorem-like environment. Then, additional to the counter ⟨env⟩, TEX maintains two counters curr⟨env⟩ctr and end⟨env⟩ctr. In the ith environment of type ⟨env⟩, curr⟨env⟩ctr= i (the L^{A}TEX counter ⟨env⟩ cannot be used since a) environments can use the counter of other environments, and b) often counters are reinitialized inside a document). end⟨env⟩ctr counts the potential situations for putting an endmark inside an environment. It is set to 1 when starting an environment. Each time, when a situation (2)–(4) is reached, the command

     \mark<\roman{currenvctr}>⟨env⟩<\roman{end⟨env⟩ctr}>

is called (<\roman{curr⟨env⟩ctr}>⟨env⟩<\roman{end⟨env⟩ctr}> uniquely identifies all situations (2)–(4) in a document). If at this position an endmark has to be set,

     \mark<\roman{curr⟨env⟩ctr}>⟨env⟩<\roman{end⟨env⟩ctr}>

is defined in the .aux file to be \end⟨env⟩Symbol, otherwise it is undefined and simply ignored. When TEX comes to an \end{⟨env⟩}, it looks if it is in situation (1). If so, the endmark is simply put at the end of the current line. Otherwise,

     \def\mark<\roman{currenvctr}>⟨env⟩%
     <\roman{end⟨env⟩ctr}>{⟨env⟩Symbol}

is written to the .aux file for setting the endmark at the latest potential position inside the theorem in the next run.

5 Theorem (Correctness):

1. For a .tex file, which does not contain nested theorem-like environments of the same type, in the above situation, the following holds: When compiling, at the ith situation in the jth environment of type ⟨env⟩, mark j ⟨env⟩ i is handled.

For .tex files which contain nested theorem-like environments of the same type, mark k ⟨env⟩ l is handled, where k is the number of the latest environment of type ⟨env⟩ which has been called at this moment, and l is the number of situations (2)–(4) which have occurred in environments of type ⟨env⟩ since the the kth \begin{⟨env⟩}.

2. When finishing an environment, either an endmark is set directly (when in a text line) or an order to put the end symbol at the latest potential position is written to the .aux file. ♢

6 Theorem (Completeness): The handling of endmarks is complete wrt. plain text, displaymath, equation, eqnarray, eqnarray*, and all environments ended by endtrivlist, including

center and verbatim.  ♢

So, where can be bugs ?

• in the plain TEX handling of endmarks,

• in some special situations which have not been tested yet,

• in some special environments which have not been tested yet.

• in the amsmath environments. We do not use them, so we do not know their pitfalls, and we ran only general test cases.

6 Problems and Questions

6.1 Known Limitations

• Since ntheorem.sty uses the .aux file for storing information about the positions of endmarks, L^{A}TEX must be run twice for correctly setting the endmarks.

• Since ntheorem.sty uses the .aux file for storing information about lists in the .thm file, a minimum of two runs is needed. If theorems move in any of these runs up to five runs can be needed to generate correct lists.

• Since we need to expand the optional argument of theorems in various ways for the lists, we decided to copy the text verbatim into the .thm file. Thus, if you use things like \thesection etc., the list won’t show the correct text. Therefore you shouldn’t use any command that needs to be expanded.

• In nested environments ending at the same time, only the endmark for the inner environment is set, as the following example shows:

   \begin{Lemma}
    Some text.
    \begin{Proof} The Proof \end{Proof}
   \end{Lemma}

yields to 5 Lemma:

Some text.

Proof The Proof

You can handle this by specifying something invisibl after the end of the inner theorem. Then the endmark for the outer theorem is set in the next line:

   \begin{Lemma}
    Some text.
    \begin{Proof} The Proof \end{Proof}~
   \end{Lemma}

yields to 6 Lemma:

Some text.

Proof The Proof

♢

• Document option fleqn is problematic: fleqn handles equations not by $$ but by lists (check what happens for

    \begin{theorem} \[ displaymath \] \end{theorem}

in standard L^{A}TEX: The displaymath is not set in an own line). Also, for long formulas, the equation number and the endmark are smashed into the formula at the right text margin.

• Naturally, ntheorem.sty will not work correctly in combination with other styles which change the handling of

1. theorem-like environments, or

2. environments concerned with the handling of endmarks, e.g. \[...\],

    eqnarray, etc.

• ntheorem.sty is compatible with Frank Mittelbach’s theorem.sty, which is the most widespread style for setting theorems.

It cannot be used with theorem.sty, but it can be used instead of it.

6.2 Known “Bugs” and Problems

• Ending a theorem directly after the text, e.g.

    \begin{Theorem} text\end{Theorem}

suppresses the endmark: 7 Theorem:

text

Therefore a space or a newline should be inserted before \end{...}.

• With theoremstyle break, if the linebreak would cause ugly linebreaking in the following text, it is suppressed.

• break styles have also problems with labels: If an environment using a breakstyle layout is labeled by \begin{...}\label{...}, an additional space is inserted, leading to a little vertical indentation if text follows, and an empty line if a displaymath or a list follows. When text follows, this can be suppressed by putting a % (or an explicit \ignorespaces) behind the label (in a .dtx file, a % is not sufficient, there \ignorespaces has to be used). If a displaymath or a list follows, this cannot be suppressed due to the setting of whatsits when writing to the .aux file (see also the nect section “Open Questions”). In this case, the label must be placed elsewhere: Here, the same corollary-environment is typeset two times, only, in the second one, the \label{...} is omitted:

    \begin{Corollary*}[title in text]\label{l}\ignorespaces
    \begin{center}
       center
    \end{center}
    \end{Corollary*}

8 Corollary (title in text):

center ♠

9 Corollary (title in text):

center ♠

6.3 Open Questions

• For equations, we decided to put the endmark after the equation number, which is vertically centered. Currently, we do not know, how to get the equation number centered and the endmark at the bottom (one has to know the internal height of the math material).

• The placement of endmarks is mainly based on a check whether L^{A}TEX is in an ordinary text line when encountering an end-of-environment. This question is partially answered by \ifhmode: In a text line, L^{A}TEX is always in \hmode. But, after an displaymath, L^{A}TEX is also in \hmode. Thus, additionally \lastskip is checked: after a displaymath, \lastskip=0 holds. In most situations, when text has been written into a line, \lastskip ≠ 0. But, this does not hold, if the source code is of the following form: ...text\label{bla}: then, \lastskip=0. In those situations, the endmark is suppressed. ?? How can it be detected whether L^{A}TEX has just ended a displaymath?

• The above problem with the label: The break style enforces a linebreak by \hfill\penalty-8000 after the \trivlist-item. Thus, TEX gets back into the horizontal mode. The label places a “whatsit” somewhere ... and, it seems that the “whatsit” makes TEX think that there is a line of text.

If someone has a solution to one of those questions, please inform us. (You can be sure to be mentioned in the Acknowledgements.)

7 Code Documentation

7.1 Documentation of the Macros

1 \typeout{Style `\basename', Version \fileversion\space <\filedate>}
2 \ProvidesPackage{ntheorem}[\filedate \space\fileversion]
3 \newif\if@thmmarks\@thmmarksfalse
4 \newif\ifthm@tempif

general setup.

7.1.1 Thmmarks-Related Stuff

1 \DeclareOption{thmmarks}{%*********************************
2 \PackageInfo{\basename}{Option `thmmarks' loaded}%
3 %
4 \@thmmarkstrue
5 \newcounter{endNonectr}
6 \newcounter{currNonectr}
7 \newif\ifsetendmark\setendmarktrue

activate placement of endmarks and define counters for upper level. \ifsetendmark: true if an endmark has to be set in a complex situation which must be handled by the .aux file. For further comments see \@endtheorem. In the following, all relevant environments are changed for handling potential end mark positions:

Changes to List Environment Original: ltlists.dtx

\endtrivlist Replaces L^{A}TEX’s \endtrivlist. An augmented functionality of L^{A}TEX’s \endtrivlist is contained in \@endtrivlist.

8 \gdef\endtrivlist{%
9 \@endtrivlist{\PotEndMark{\hbox{}\nobreak\hfill\nobreak}}}

At an \endtrivlist (which is called at the end of \list environments and several other environments), \@endtrivlist is called to end the \trivlist and set a potential position for an endmark at the end of the line if TEX is in a text line.

\@endtrivlist A new command] which augments L^{A}TEX’s functionality of \endtrivlist by checking if an end mark has to be set:

10 \gdef\@endtrivlist#1{%  % from \endtrivlist
11 \if@inlabel \indent\fi
12 \if@newlist \@noitemerr\fi
13 \ifhmode
14  \ifdim\lastskip >\z@ #1\unskip \par  %<<<<<<<<<<<<<<<<<<<<<<
15  \else \unskip \par \fi
16  \fi
17 \if@noparlist \else
18  \ifdim\lastskip >\z@
19  \@tempskipa\lastskip \vskip -\lastskip
20  \advance\@tempskipa\parskip \advance\@tempskipa -\@outerparskip
21  \vskip\@tempskipa

22  \fi
23  \@endparenv
24 \fi}

New: parameter #1. #1 is executed when the \trivlist ends with a text line (ie the endmark can be put simply at the end of the line): Line 14: case split: if in hmode and \lastskip > 0, then TEX is in a text line, the endmark is set here.

Changes to Math Environments Original: ltmath.dtx

\endequation For equations, end marks are placed behind the equation number:

25 \gdef\SetMark@endeqn{\quad}%  as default, cf. option leqno
26 \gdef\endequation{\eqno \hbox{\@eqnnum \PotEndMark{\SetMark@endeqn}}%
27  $$\global\@ignoretrue}

Line 25: As default, work for equation numbers at the right: Then, a \quad is placed between equation number and endmark.

Line 26: In addition to the equation number (set by \@eqnnum at the right of the line) \SetMark@endeqn is carried out.

\[ If an end mark is set, a displaymath is put into box such that the end marks appears at its bottom level at the right. Thus, also the definition of \[ has to be changed:

28 \gdef\[{%
29 \relax\ifmmode
30  \@badmath
31 \else
32  \ifvmode
33  \nointerlineskip
34  \makebox[.6\linewidth]%
35  \fi
36  $$\stepcounter{end\InTheoType ctr}%
37  \@ifundefined{mark\roman{curr\InTheoType ctr}%
38  \InTheoType\roman{end\InTheoType ctr}}{\relax}%
39  {\ifx\csname\InTheoType Symbol\endcsname\@empty\else
40  \boxmaxdepth=.5ex\begin{array}[b]{l}%
41  \boxmaxdepth=\maxdimen\displaystyle\fi}%
42  \addtocounter{end\InTheoType ctr}{-1}%
43  %%$$ BRACE MATCH HACK
44 \fi}

Lines 29–35, 43, 44: the old definition. Lines 36–39: The end position of a displaymath inside a theorem-environment cor-

responds to end\InTheoType ctr+1. An endmark has to be set there, if

      \mark<\roman{curr#1ctr}>#1 <\roman{end#1ctr}+1 > is defined and

not the empty symbol. Lines 40–41: If so, the whole displayed stuff is put in an array with maximal depth

0.5ex and vertically adjusted with its bottom line (then, the endmarks will appear adjusted to its bottom line).

Line 42: The counter has to be re-decremented.

\] At the end of a displaymath, the end marks is set at its bottom level:

 45 \gdef\]{%
 46  \stepcounter{end\InTheoType ctr}%
 47  \@ifundefined{mark\roman{curr\InTheoType ctr}%
 48  \InTheoType\roman{end\InTheoType ctr}}{\relax}%
 49  {\ifx\csname\InTheoType Symbol\endcsname\@empty\else
 50  \end{array}\fi}%
 51  \addtocounter{end\InTheoType ctr}{-1}%
 52 \relax\ifmmode
 53  \ifinner
 54  \@badmath
 55  \else
 56  \PotEndMark{\eqno}\global\@ignoretrue$$%%$$ BRACE MATCH HACK
 57  \fi
 58 \else
 59  \@badmath
 60 \fi
 61 \ignorespaces}

Lines 46–51: Look, if an endmark has to be set in this displaymath (analogous to lines 36–42 of \def\[) If so, there is an inner array which has to be closed (line 50).

Lines 52–61: the old definition. Line 56: changed to set an endmark at the right of the line if necessary (this is done

    by \eqno).

\endeqnarray For \eqnarrays, the end marks is set below the number of the last equation:

 62 \gdef\SetMark@endeqnarray#1{\llap{\raisebox{-1.3em}{#1}}}
 63 \gdef\endeqnarray{%
 64  \global\let\Oldeqnnum=\@eqnnum
 65  \gdef\@eqnnum{\Oldeqnnum\PotEndMark{\SetMark@endeqnarray}}%
 66  \@@eqncr
 67  \egroup
 68  \global\advance\c@equation\m@ne
 69 $$\global\@ignoretrue
 70  \global\let\@eqnnum\Oldeqnnum}

Line 62: As default work for equation numbers at the right: Then, the endmark is placed below the last equation number at the right margin.

New: Lines 64, 65, 70: Line 64: save \@eqnnum. Line 65: define \@eqnnum to carry out \Oldeqnnum, then a potential endmark po-

sition is handled: if an endmark is set, between the equation number and the endmark, the command sequence \SetMark@endeqnarray is carried out – there, since \SetMark@endeqnarray is a function of one argument, the endmark will be this argument.

Lines 66–69: from latex.ltx. Line 66 sets the equation number. Line 70: restore \@eqnnum.

\endeqnarray* In an \eqnarray*, the end mark is set at the right of the last equation:

 71 \@namedef{endeqnarray*}{%
 72  %    from \@@eqncr:

73  \let\reserved@a\relax
74  \ifcase\@eqcnt \def\reserved@a{& & &}\or \def\reserved@a{& &}%
75  \or \def\reserved@a{&}\else
76  \let\reserved@a\@empty
77  \@latex@error{Too many columns in eqnarray environment}\@ehc\fi
78  \reserved@a {\normalfont \normalcolor \PotEndMark{}}%
79  \global\@eqnswtrue\global\@eqcnt\z@\cr

80 %

81  \egroup
82  \global\advance\c@equation\m@ne
83 $$\global\@ignoretrue}

This is just L^{A}TEX’s \endeqnarray where lines 73–79 are inserted from \@@eqncr and augmented (line 78) to set a potential endmark (with no additional commands) at the end of the current line.

Changes to Center Environment Original: ltmiscen.dtx

\endcenter In L^{A}TEX, \endcenter just calls \endtrivlist. Here, the situation is more complex since the the endmark has to be put in the last line without affecting its centering: if in a text line (only then, here is a potential endmark position):

84 \gdef\endcenter{%
85 \@endtrivlist
86  {\PotEndMark{\rightskip0pt%
87  \settowidth{\leftskip}%
88  { \csname mark\roman{curr\InTheoType ctr}\InTheoType
89  \roman{end\InTheoType ctr}\endcsname}%
90  \advance\leftskip\@flushglue\hskip\@flushglue}}}

The \rightskip of the line is set to 0, \leftskip is set to the width of one space (since on the right, one space is added after the text) plus the endmark and infinitely stretchable glue (\@flushglue), and also the line is continued with \@flushglue (the actual position is one space after the text), and then the endmark is placed

(by \PotEndMark).

Handling of endmarks

\@endtheorem \@endtheorem is called for every \end{⟨env⟩}, where ⟨env⟩ is a theorem-like environment. \@endtheorem is extended to organize the placement of the corresponding end mark (\InTheoType gives the innermost theorem-like environment, i.e. the one to be ended):

91 \gdef\@empty{}
92 \gdef\@endtheorem{%
93 \expandafter
94 \ifx\csname\InTheoType Symbol\endcsname\@empty\setendmarkfalse\fi
95 \@endtrivlist
96  {\ifsetendmark
97  \hbox{}\nobreak\hfill\nobreak\csname\InTheoType Symbol\endcsname
98  \setendmarkfalse \fi}%
99 \ifsetendmark\OrganizeTheoremSymbol\else\global\setendmarktrue\fi}

Lines 93, 94: if the end symbol of the environment ⟨env⟩ to be closed is empty, simply no end symbol has to be set (it makes a difference, if no end symbol is set, or if an empty end symbol is set).

Lines 95, 99: (originally, it calls \endtrivlist): Lines 95, 97, 98: \@endtrivlist is called to put ⟨env⟩Symbol at the end of the line

and set setendmark to false if TEX is in a text line and setendmark is true. At this point, setendmark is false iff the user has disabled it locally or the end symbol is empty.

Line 96: the endmark is not set, if setendmark is false. Line 99: if setendmark is true, the correct placement of the end symbol is organized,

else (ie either setendmarkfalse is set by the user, or the endmark is already

   set by \@endtrivlist) reset setendmark to true.
   For further comments see \@endtrivlist and \OrganizeTheoremSymbol.

The construction in line 97 guarantees that the endmark is put at the end of the line, even if it is the only letter in this line.

\NoEndMark By \NoEndMark, the automatical setting of an end mark is blocked for the current environment.

100 \gdef\NoEndMark{\global\setendmarkfalse}

set setendmark to false. It is automatically reset to true after the end of the current environment.

\qed With \qed, the user can locally change the end symbol to appear:

101 \gdef\qed{\expandafter\def\csname \InTheoType Symbol\endcsname
102  {\the\qedsymbol}}%

When calling \qed, the end symbol of the innermost theorem-like environment at that time is set to the value stored in \qedsymbol at that time.

\PotEndMark Handling a potential endmark position:

103 \gdef\PotEndMark#1{\SetEndMark{\InTheoType}{#1}}%

Argument: ⟨cmd seq⟩:=#1 is a command sequence to be executed when setting the endmark. It adds the current theorem type ⟨env⟩ to the parameters, and calls

\PotEndMark{⟨env⟩}{⟨cmd seq⟩}.

\SetEndMark \SetEndMark sets an endmark for an environment. It is called by \PotEndMark.

104 \gdef\SetEndMark#1#2{%
105 \stepcounter{end#1ctr}%
106 \@ifundefined{mark\roman{curr#1ctr}#1\roman{end#1ctr}}%
107 {\relax}%
108 {#2{\csname mark\roman{curr#1ctr}#1\roman{end#1ctr}\endcsname}}}%

Arguments: ⟨env⟩:=#1: current theorem-environment. ⟨cmd seq⟩:= #2: is a command sequence to be executed when setting the endmark. Both arguments are transmitted from by \PotEndMark.

Line 105: increments end⟨env⟩ctr for preparing the next situation for setting a potential endmark.

Line 106, 107: if

    \mark<\roman{curr⟨env⟩ctr}>⟨env⟩<\roman{end⟨env⟩ctr}>

is undefined – which is the case iff at this position no endmark has to be set –, nothing is done,

Line 108: otherwise, ⟨cmd seq⟩ and then

    \mark<\roman{curr⟨env⟩ctr}>\env <\roman{end⟨env⟩ctr}>,

which is defined in the .aux file to be the end symbol are called. The construction ⟨cmd seq⟩{… } in line 108 allows the handling of the end symbol as an argument of ⟨cmd seq⟩ as needed for \endeqnarray.

Writing to .aux file. (copied from \def\label (ltxref.dtx))

109 \newskip\mysavskip
110 \gdef\@bbsphack{%
111  \mysavskip\lastskip
112  \unskip}

113 %

114 \gdef\@eesphack{%
115  \ifdim\mysavskip>\z@
116  \vskip\mysavskip \else\fi}

Lines 110–112 and 113–115 are similar to \@bsphack and \@bsphack of latex.ltx. They undo resp. redo the last skip.

\OrganizeTheoremSymbol The information for setting the end marks is written to the .aux file:

117 \gdef\OrganizeTheoremSymbol{%
118 \@bbsphack
119 \edef\thm@tmp{\expandafter\expandafter\expandafter\thm@meaning
120  \expandafter\meaning\csname\InTheoType Symbol\endcsname\relax}%
121 \protected@write\@auxout{}%
122  {\string\global\string\def\string\mark%
123  \roman{curr\InTheoType ctr}\InTheoType \roman{end\InTheoType ctr}%
124  {\thm@tmp}}%
125 \@eesphack}

Lines 121–123: Write

\global\def\mark<\roman{curr⟨env⟩ctr}> ⟨env⟩ <\roman{end⟨env⟩ctr}>
{<⟨env⟩Symbol>} to the .aux file.

⟨env⟩:=\InTheoType gives the innermost theorem-like environment, i.e. the one the end symbol has to be set for.

126 } % end of option [thmmarks]

7.1.2 Option leqno to Thmmarks

127 \DeclareOption{leqno}{%
128 \if@thmmarks
129 \PackageInfo{\basename}{Option `leqno' loaded}%
130 \gdef\SetMark@endeqn#1{\hss\llap{#1}}
131 \gdef\SetMark@endeqnarray#1{\hss\llap{#1}}
132 \fi}%

leqno is only active it thmmarks is also active.

Line 130, 131: Since with leqno, the equation number is placed on the left, after infinitely stretchable glue, the endmark can be set straight at the right margin.

7.1.3 Option fleqn to Thmmarks

133 \DeclareOption{fleqn}{%
134 \if@thmmarks
135 \PackageInfo{\basename}{Option `fleqn' loaded}%

fleqn is only active it thmmarks is also active.

\[ Since fleqn treats displayed math as trivlists, it’s quite another thing:

136 \renewcommand\[{\relax
137  \ifmmode\@badmath
138  \else
139  \begin{trivlist}%
140  \@beginparpenalty\predisplaypenalty
141  \@endparpenalty\postdisplaypenalty
142  \item[]\leavevmode
143  \hb@xt@\linewidth\bgroup $\m@th\displaystyle %$
144  \hskip\mathindent\bgroup
145  \stepcounter{end\InTheoType ctr}%
146  \@ifundefined{mark\roman{curr\InTheoType ctr}%
147  \InTheoType\roman{end\InTheoType ctr}}{\relax}%
148  {\ifx\csname\InTheoType Symbol\endcsname\@empty\else
149  \boxmaxdepth=.5ex\begin{array}[b]{l}%
150  \boxmaxdepth=\maxdimen\displaystyle\fi}%
151  \addtocounter{end\InTheoType ctr}{-1}%
152  \fi}

Lines 136–144, 152: the old definition. Line 145–151: if an endmark has to be set in this displaymath, it is put into an array

with depth ≤ 0.5ex, and vertically adjusted to the bottom line.

\] Here, the end mark is placed after a \hfil ate the end of the line containing the displaymath:

153 \renewcommand\]{%
154  \stepcounter{end\InTheoType ctr}%
155  \@ifundefined{mark\roman{curr\InTheoType ctr}%
156  \InTheoType\roman{end\InTheoType ctr}}{\relax}%
157  {\ifx\csname\InTheoType Symbol\endcsname\@empty\else
158  \end{array}\fi}%
159  \addtocounter{end\InTheoType ctr}{-1}%
160  \relax\ifmmode
161  \egroup $\hfil\PotEndMark{}% $
162  \egroup
163  \end{trivlist}%
164  \else \@badmath
165  \fi}

Lines 154–158: Look, if an endmark has to be set in this displaymath. If so, close the inner array.

Lines 160–165: the old definition. Line 161: Added \PotEndMark.

\endequation for equations, the end mark is also set with the equation number:

166 \gdef\endequation{%
167  $\hfil % $
168  \displaywidth\linewidth\hbox{\@eqnnum \PotEndMark{\SetMark@endeqn}}%
169  \egroup
170  \endtrivlist}

Line 168: When the equation number is set, also the endmark is set with the same trick as for \endequation without fleqn.

\endeqnarray When the equation number is set, also the endmark is set with the same trick as for \endeqnarray without fleqn (see Lines 172, 173, 178):

171 \gdef\endeqnarray{%
172  \global\let\Oldeqnnum=\@eqnnum
173  \gdef\@eqnnum{\Oldeqnnum\PotEndMark{\SetMark@endeqnarray}}%
174  \@@eqncr
175  \egroup
176  \global\advance\c@equation\m@ne$$% $$
177  \global\@ignoretrue
178  \global\let\@eqnnum\Oldeqnnum}
179 \fi}% end of option fleqn

7.1.4 Option amsmath to Thmmarks

 Taken from amsmath.sty.
180 \DeclareOption{amsmath}{%
181 \if@thmmarks
182 \PackageInfo{\basename}{Option `amsmath' loaded}%

amsmath is only active it thmmarks is also active.

183 \newdimen\thm@amstmpdepth

A temporarily used register.

\TagsPlusEndmarks Since amsmath uses “tags” for setting end marks, some macros are defined which prepare tags which include endmarks:

184 \gdef\TagsPlusEndmarks{%
185  \global\let\Old@maketag@@@=\maketag@@@
186  \global\let\Old@df@tag=\df@tag
187  \if@eqnsw\SetTagPlusEndMark\else
188  \iftag@\SetTagPlusEndMark
189  \else\SetOnlyEndMark
190  \fi\fi}

Lines 185, 186: store the original macros. Line 187: if equation numbers are set as default, call \SetTagPlusEndMark to set

tag and end mark. Line 188: if a tag is set manually, call \SetTagPlusEndMark to set tag and end mark. Line 189: otherwise, call \SetOnlyEndMark to set only an end mark.

191 \gdef\SetOnlyEndMark{%
192  \global\tag@true
193  \iftagsleft@
194  \gdef\df@tag{\hbox
195  to \displaywidth{\hss\PotEndMark{\maketag@@@}}}%
196  \else
197  \gdef\df@tag{\PotEndMark{\maketag@@@}}%
198  \fi}

Set only an end mark: Line 192: force setting the end mark as a tag: Lines 194,195: if tags are set to the left, the tag consists of a \hbox over the whole

displaywidth, with the (potential) endmark at its right. Line 197: if tags are set to the right, the tag consists only of the (potential) endmark.

199 \gdef\SetTagPlusEndMark{%
200  \iftagsleft@
201  \gdef\maketag@@@##1{%
202  \hbox to \displaywidth{\m@th\normalfont##1%
203  \PotEndMark{\hss}}}%
204  \else
205  \gdef\maketag@@@##1{\hbox{\m@th\normalfont##1%
206  \llap{\hss\PotEndMark{\raisebox{-1.3em}}}}}%
207  \fi}

Set a tag and an end mark: Lines 200–207: redefine the \maketag@@@ macro: Lines 201–203: if tags are set to the left, build a box of the whole displaywidth and

put the original tag on the left, and the (potential) endmark at the right. Lines 205,206: if the tags are set to the right, the (potential) end mark is put below

it.

208 \gdef\RestoreTags{%
209  \global\let\maketag@@@=\Old@maketag@@@
210  \global\let\df@tag=\Old@df@tag}

Lines 209,210: restore the original macros.

\endgather In the gather environment, just the augmented tag is used:

211 \gdef\endgather{%
212  \TagsPlusEndmarks % <<<<<<<<<
213  \math@cr
214  \black@\totwidth@
215  \egroup
216  $$%
217  \RestoreTags        % <<<<<<<<<
218  \global\@ignoretrue}

219 %

220 \expandafter\let\csname endgather*\endcsname\endgather

New: Line 212: the last tag contains the potential endmark. Line 217: restore the original macros. Line 220: Since let always takes the expansion of a macro when the let is executed,

all let’s have to be adjusted (this is the same for all subsequent let-statements).

\math@cr@@@align This is an internal macro of amsmath, dealing with lines in a align environment:

221 \def\math@cr@@@align{%
222  \ifodd\column@\else{&}\fi     %<<<<<<<<<<<<<<<<<
223  \kern-\alignsep@
224  \ifst@rred\nonumber\fi
225  \if@eqnsw \global\tag@true \fi
226  \global\advance\row@\@ne
227  \iftag@
228  \add@amps\maxfields@
229  \omit
230  \setboxz@h{\@lign\strut@{\make@display@tag}}%
231  \place@tag
232  \fi
233  \ifst@rred\else\global\@eqnswtrue\fi
234  \global\lineht@\z@
235  \cr}

New: Line 222: if the counter column@ is even (ie, the line has 1, 3, or 5 used columns), the next column is started. Otherwise, if an align environment has an odd number of used columns, the endmark not set at the margin.

\endalign \endalign also uses the augmented tags:

236 \def\endalign{%
237  \ifingather@\else       % <<<<<<<<<
238  \TagsPlusEndmarks\fi % <<<<<<<<<
239  \math@cr
240  \black@\totwidth@
241  \egroup
242  \ifingather@
243  \restorealignstate@
244  \egroup
245  \nonumber
246  \ifnum0=`{\fi}%
247  \else
248  $$%
249  \RestoreTags            % <<<<<<<<<
250  \fi
251  \global\@ignoretrue}

New: Lines 237, 238: if the align is not inside another environment, its tags have to

contain the endmarks. Line 249: this case, the original macros have to be restored.

252 \expandafter\let\csname endalign*\endcsname\endalign
253 \let\endxalignat\endalign
254 \expandafter\let\csname endxalignat*\endcsname\endalign
255 \let\endxxalignat\endalign
256 \let\endalignat\endalign
257 \expandafter\let\csname endalignat*\endcsname\endalign
258 \let\endflalign\endalign
259 \expandafter\let\csname endflalign*\endcsname\endalign

Adjust let-statements.

\lendmultline The multline environment has two different \end commands, depending if the equation numbers are set on the left or on the right:

260 \def\lendmultline@{%
261  \@eqnswfalse\tag@true\tagsleft@false
262  \rendmultline@}

End of multline environment if tags are set to the left: in this case, the last line of a multline does not contain a tag. Thus the situation of setting an endmark tag at the right is faked: Lines 261, 262: display no equation number, set a tag, set it at the right, and call

   \rendmultline.
\rendmultline  \rendmultline also uses the augmented tags:
263 \def\rendmultline@{%
264  \TagsPlusEndmarks           % <<<<<<<<<
265  \iftag@
266  \begingroup
267  \ifshifttag@
268  \hskip\multlinegap
269  \llap{\vtop{%
270  \raise@tag
271  \normalbaselines
272  \setbox\@ne\null
273  \dp\@ne\lineht@
274  \box\@ne
275  \hbox{\strut@\make@display@tag}%
276  }}%
277  \else
278  \hskip\multlinetaggap
279  \make@display@tag
280  \fi
281  \endgroup
282  \else
283  \hskip\multlinegap
284  \fi
285  \hfilneg
286  \math@cr
287  \egroup$$%
288  \RestoreTags}                % <<<<<<<<<

New: Line 264: last tag contains the potential endmark. Line 288: restore the original macros

\[ In amsmath, displaymaths are handled by \halign. \[ has to be changed such thet the \halign header contains one more column:

289 \def\[{%
290  \relax\ifmmode% \RIfM@ <<<<<<<<<<<<<<<<<<<<<<<<<<<<
291  \@badmath
292  \else
293  \DN@{%
294  $$%
295  \ingather@true
296  \inany@true

297  \def\\{\@amsmath@err{\Invalid@@\\}\@eha}%
298  \tabskip\@mathmargin
299  \halign to \displaywidth\bgroup
300  \if@fleqn\else\hfil\fi
301  \setboxz@h{$\m@th\displaystyle{####}$}%
302  \global\totwidth@\wdz@
303  \global\thm@amstmpdepth\dp0% <<<<<<<<<<<<
304  \boxz@
305  \tabskip 0pt plus 1000pt%<<<<<<<<<<<<<<
306  & ####% <<<<<<<<<<<<<<<<<<<<<<<<
307  \tabskip 0pt%
308  \cr

309 }%

310  \@xp\next@
311  \fi}
 Note, that in amsmath, \def\RIfM@{\relax\ifmmode}. For here, this has to be

extended since otherwise the surrounding \if@thmmarks...\fi is misinterpreted !! New: Line 303: store depth of current displaymath material (needed if end mark has to

be set). Line 305,306: \halign gets one more column, after \boxz@ which contains the dis-

playmath material, after a hfil, an additional column is inserted.

\] The (potential) end mark is set in the additional column (which is started by the &) (line 315):

312 \def\]{%
313  \relax\ifmmode%  \RIfM@ <<<<<<<<<<
314  \DN@{%
315  \PotEndMark{&\raisebox{-\thm@amstmpdepth}}% <<<<<<<<<
316  \crcr
317  \black@\totwidth@
318  \egroup
319  $$%

320 }%

321  \@xp\next@
322  \else
323  \@badmath
324  \fi}

Added Line 315: set potential end mark at bottom niveau of displaymath.

325 \def\equation{\gather\def\\{\@amsmath@err{\Invalid@@\\}\@eha}}
326 \def\endequation{\endgather}
327 \renewenvironment{equation*}{\equation}{\nonumber\endequation}

unchanged from amsmath.sty.

328 \else\PackageError{\basename}{Option amsmath cannot be used without
329  option thmmarks.}\@eha
330 \fi
331 }% end of option amsmath

If option amsmath is requested without option thmmarks, an error occurs.

7.1.5 Theorem-Layout Stuff

332 \let\thm@usestd\@undefined
333 \DeclareOption{standard}{\let\thm@usestd\relax}

Prepare for loading standard configuration.

334 \gdef\InTheoType{None}

Set \InTheoType to none on the upper document level.

\newtheoremstyle With \newtheoremstyle, new theorem-layout styles are defined.

335 \gdef\newtheoremstyle#1#2#3{%
336 \expandafter\@ifundefined{th@#1}%
337 {\expandafter\gdef\csname th@#1\endcsname{%
338  \def\@begintheorem####1####2{#2}%
339  \def\@opargbegintheorem####1####2####3{#3}}}%
340 {\PackageError{\basename}{Theorem style #1 already defined}\@eha}}

Arguments: ⟨style⟩:=#1: the name of the theoremstyle to be defined, ⟨cmd seq1 ⟩:=#2: command sequence for setting the header for environment instances with no optional text, ⟨cmd seq2 ⟩:=#3: command sequence for setting the header for environment instances with optional text. Line 336: if this style is not yet defined, define it. Line 337: define \th@⟨style⟩ to be a macro which defines Line 338: a) the two-argument macro \@begintheorem#1#2 to be ⟨cmd seq1 ⟩,

Line 339: b) \@opargbegintheorem#1#2#3 to be ⟨cmd seq2 ⟩.

The predefined theorem styles use this command.

\renewtheoremstyle
341 \gdef\renewtheoremstyle#1#2#3{%
342 \expandafter\@ifundefined{th@#1}%
343 {\PackageError{\basename}{Theorem style #1 undefined}\@ehc}%
344  {}%
345 \expandafter\let\csname th@#1\endcsname\relax
346 \newtheoremstyle{#1}{#2}{#3}}

Arguments: ⟨style⟩:=#1: the name of the theoremstyle to be defined,

#2, #3 as for \newtheoremstyle.

Checks, if theoremstyle ⟨style⟩ is already defined. If so, \th@⟨style⟩ is made undefined and \newtheoremstyle is called with the same arguments.

Predefined Theorem Styles

theoremstyles th@plain, th@change, and th@margin taken from theorem.sty by Frank Mittelbach; the break-styles have been changed.

347 \newtheoremstyle{plain}%
348 {\item[\hskip\labelsep \theorem@headerfont ##1\ ##2\theorem@separator]}%
349 {\item[\hskip\labelsep \theorem@headerfont ##1\ ##2\ (##3)\theorem@separator]}

350 %

351 \newtheoremstyle{break}%

352 {\item\hbox to \textwidth{\theorem@headerfont ##1\
353  ##2\theorem@separator\hfill}}%
354 {\item\hbox to \textwidth{\theorem@headerfont ##1\ ##2\
355  (##3)\theorem@separator\hfill}}

356 %

357 \newtheoremstyle{change}%
358 {\item[\hskip\labelsep \theorem@headerfont ##2\ ##1\theorem@separator]}%
359 {\item[\hskip\labelsep \theorem@headerfont ##2\ ##1\ (##3)\theorem@separator]}

360 %

361 \newtheoremstyle{changebreak}%
362 {\item\hbox to \textwidth{\theorem@headerfont ##2\
363  ##1\theorem@separator\hfill}}%
364 {\item\hbox to \textwidth{\theorem@headerfont ##2\ ##1\
365  (##3)\theorem@separator\hfill}}

366 %

367 \newtheoremstyle{margin}%
368 {\item[\theorem@headerfont \llap{##2}\hskip\labelsep ##1\theorem@separator]}%
369 {\item[\theorem@headerfont \llap{##2}\hskip\labelsep ##1\ (##3)\theorem@separator]}

370 %

371 \newtheoremstyle{marginbreak}%
372 {\item\hbox to \textwidth{\theorem@headerfont \llap{##2}\hskip\labelsep
373  ##1\theorem@separator\hfill}}%
374 {\item\hbox to \textwidth{\theorem@headerfont
375  \llap{##2}\hskip\labelsep
376  ##1\ (##3)\theorem@separator\hfill}}

377 %

378 \newtheoremstyle{nonumberplain}%
379 {\item[\theorem@headerfont\hskip\labelsep ##1\theorem@separator]}%
380 {\item[\theorem@headerfont\hskip \labelsep ##1\ (##3)\theorem@separator]}

381 %

382 \newtheoremstyle{nonumberbreak}%
383 {\item\hbox to \textwidth{\theorem@headerfont\hskip\labelsep
384  ##1\theorem@separator\hfill}}%
385 {\item\hbox to \textwidth{\theorem@headerfont\hskip\labelsep
386  ##1\ (##3)\theorem@separator}}

387 %

388 \@namedef{th@nonumbermargin}{\th@nonumberplain}
389 \@namedef{th@nonumberchange}{\th@nonumberplain}
390 \@namedef{th@nonumbermarginbreak}{\th@nonumberbreak}
391 \@namedef{th@nonumberchangebreak}{\th@nonumberbreak}
392 \@namedef{th@plainNo}{\th@nonumberplain}
393 \@namedef{th@breakNo}{\th@nonumberplain}
394 \@namedef{th@marginNo}{\th@nonumberplain}
395 \@namedef{th@changeNo}{\th@nonumberplain}
396 \@namedef{th@marginbreakNo}{\th@nonumberbreak}
397 \@namedef{th@changebreakNo}{\th@nonumberbreak}

For instance, break is commented:

 \newtheoremstyle{break} results in
      \gdef\th@break{%
        \def\@begintheorem##1##2{%
            \item[\hskip\labelsep \theorem@headerfont
                   ##1\ ##2\theorem@separator]%

           \hfill\penalty-8000}%
       \def\@opargbegintheorem##1##2##3{%
         \item[\hskip\labelsep \theorem@headerfont
                ##1\ ##2\ (##3)\theorem@separator]%
         \hfill\penalty-8000}}

Then, calling \th@break sets \@begintheorem as follows: Since each theorem environment is basically a trivlist, the header is set as the item contents: \theorem@headerfont holds the font commands for the header font, ##1 is the keyword to be displayed, and ##2 its environment number. The linebreak after the header is achieved by offering to fill the line with space and the distinct wish to put a linebreak after it. Thus, if plain text follows, the line break is executed, but if a list or a display follows, it is not executed. Note: The \hfill\penalty-8000 causes TEX to leave vertical mode, setting the item contents (ie the header) and entering horizontal mode to perform the \hfill.

\theoremstyle The handling of \theoremstyle, \theorembodyfont, and \theoremskipamounts

is taken from theorem.sty by Frank Mittelbach:

398 \gdef\theoremstyle#1{%
399 \@ifundefined{th@#1}{\@warning
400  {Unknown theoremstyle `#1'. Using `plain'}%
401  \theorem@style{plain}}%
402  {\theorem@style{#1}}}
403 \newtoks\theorem@style
404 \newtoks\theorem@@style
405 \global\theoremstyle{plain}

If \theoremstyle is called, it is checked if the argument is a valid theoremstyle, and if so, it is stored in the token \theorem@style. It is initialized to plain.

\theorembodyfont
406 \newtoks\theorembodyfont
407 \global\theorembodyfont{\itshape}
\theoremnumbering
408 \newtoks\theoremnumbering
409 \global\theoremnumbering{arabic}
\theorempreskipamount
\theorempostskipamount
410 \newskip\theorempreskipamount
411 \newskip\theorempostskipamount
412 \global\theorempreskipamount\topsep
413 \global\theorempostskipamount\topsep
\theoremindent
414 \newdimen\theoremindent
415 \global\theoremindent0cm
416 \newdimen\theorem@indent
\theoremheaderfont
417 \newtoks\theoremheaderfont
418 \global\theoremheaderfont{\normalfont\bfseries}
419 \def\theorem@headerfont{\normalfont\bfseries}

\theoremseparator
420 \newtoks\theoremseparator
421 \global\theoremseparator{}
\theoremsymbol
422 \def\theorem@separator{}
423 \newtoks\theoremsymbol
424 \global\theoremsymbol{}
\qedsymbol
425 \newtoks\qedsymbol
426 \global\qedsymbol{}

Compatibility with amsthm.

amsthm
427 \DeclareOption{amsthm}{%
428 \PackageInfo{\basename}{Option `amsthm' loaded}%
429 \def\swapnumbers{\PackageError{\basename}{swapnumbers not implemented.
430 Use theoremstyle change instead.}\@eha}

431

432 \gdef\th@plain{%
433 \def\theorem@headerfont{\normalfont\bfseries}\itshape%
434 \def\@begintheorem##1##2{%
435  \item[\hskip\labelsep \theorem@headerfont ##1\ ##2.]}%
436 \def\@opargbegintheorem##1##2##3{%
437  \item[\hskip\labelsep \theorem@headerfont ##1\ ##2\ (##3).]}}
438 \gdef\th@nonumberplain{%
439 \def\theorem@headerfont{\normalfont\bfseries}\itshape%
440 \def\@begintheorem##1##2{%
441  \item[\hskip\labelsep \theorem@headerfont ##1.]}%
442 \def\@opargbegintheorem##1##2##3{%
443  \item[\hskip\labelsep \theorem@headerfont ##1\ (##3).]}}
444 \gdef\th@definition{%
445 \th@plain\def\theorem@headerfont{\normalfont\bfseries}\itshape}
446 \gdef\th@nonumberdefinition{%
447 \th@nonumberplain\def\theorem@headerfont{\normalfont\bfseries}\itshape}
448 \gdef\th@remark{%
449 \th@plain\def\theorem@headerfont{\itshape}\normalfont}
450 \gdef\th@nonumberremark{%
451 \th@nonumberplain\def\theorem@headerfont{\itshape}\normalfont}
452 \newcounter{proof}%
453 \if@thmmarks
454 \newcounter{currproofctr}%
455 \newcounter{endproofctr}%
456 \fi
457 \newcommand{\openbox}{\leavevmode
458 \hbox to.77778em{%
459 \hfil\vrule
460 \vbox to.675em{\hrule width.6em\vfil\hrule}%
461 \vrule\hfil}}
462 \gdef\proofSymbol{\openbox}
463 \newcommand{\proofname}{Proof}

464 \newenvironment{proof}[1][\proofname]{
465 \th@nonumberplain
466 \def\theorem@headerfont{\itshape}%
467 \normalfont
468 \theoremsymbol{\ensuremath{_\blacksquare}}
469 \@thm{proof}{proof}{#1}}%
470 {\@endtheorem}
471 }% end of option amsthm

Defines theorem styles plain, definition, and remark, and environment proof according to amsthm.sty.

7.1.6 Theorem-Environment Handling Stuff

Original: ltthm.dtx

472 \newskip\thm@topsepadd

An auxiliary variable.

Defining New Theorem-Environments.

\newtheorem The syntax of \newtheorem is retained. The macro is extended to deal with the additional requirements:

473 \gdef\newtheorem{%
474 \@ifstar
475  {\edef\@tempa{{nonumber\the\theorem@style}}%
476  \expandafter\theorem@@style\@tempa}%
477  {\edef\@tempa{{\the\theorem@style}}%
478  \expandafter\theorem@@style\@tempa}%
479 \@newtheorem}

Defines \theorem@@style to be the current \theoremstyle or – in case of \newtheorem* – to be its non-numbered equivalent, and then calls \@newtheorem.

\renewtheorem
480 \gdef\renewtheorem{%
481 \@ifstar
482  {\edef\@tempa{{nonumber\the\theorem@style}}%
483  \expandafter\theorem@@style\@tempa}%
484  {\edef\@tempa{{\the\theorem@style}}%
485  \expandafter\theorem@@style\@tempa}%
486 \@renewtheorem}

Analogous to \newtheorem.

\@newtheorem \@newtheorem does the main job for initializing a new theorem environment type. It is called by \newtheorem.

487 \gdef\@newtheorem#1{%
488 \thm@tempiffalse
489 \expandafter\@ifdefinable\csname #1\endcsname
490 {\expandafter\@ifdefinable\csname #1*\endcsname
491 {\thm@tempiftrue
492  \thm@definelthm{#1}% for lists
493  \if@thmmarks

494  \expandafter\@ifundefined{c@curr#1ctr}%
495  {\newcounter{curr#1ctr}}{}%
496  \expandafter\@ifundefined{c@end#1ctr}%
497  {\newcounter{end#1ctr}}{}%
498  \fi
499  \expandafter\xdef\csname #1Symbol\endcsname{\the\theoremsymbol}%
500  \expandafter\gdef\csname#1\endcsname{%
501  \let\thm@starredenv\@undefined
502  \csname mkheader@#1\endcsname}%
503  \expandafter\gdef\csname#1*\endcsname{%
504  \let\thm@starredenv\relax
505  \csname mkheader@#1\endcsname}%
506  \def\@tempa{\expandafter\noexpand\csname end#1\endcsname}%
507  \expandafter\xdef\csname end#1*\endcsname{\@tempa}%
508  \expandafter\xdef\csname setparms@#1\endcsname
509  {\noexpand \def \noexpand \theorem@headerfont
510  {\the\theoremheaderfont\noexpand\theorem@checkbold}%
511  \noexpand \def \noexpand \theorem@separator
512  {\the\theoremseparator}%
513  \noexpand \def \noexpand \theorem@indent
514  {\the\theoremindent}%
515  \the \theorembodyfont
516  \noexpand\csname th@\the \theorem@@style \endcsname}}}%
517 \@ifnextchar[{\@othm{#1}}{\@nthm{#1}}}% MUST NOT BE IN ANY IF !!!

Argument: ⟨env⟩:=#1 is the (internal) environment name to be defined, which is read from the L^{A}TEX source. Line 489: check if ⟨env⟩ is not yet defined (or is redefined). Lines 491–516 are executed exactly if ⟨env⟩ and ⟨env⟩* are not yet defined. Line 491: \thm@tempif=true iff ⟨env⟩ and ⟨env⟩* are not yet defined. Line 492: Initialize theorem list handling for ⟨env⟩. Lines 494–497: if thmmarks is active and the counters are not yet defined, for every

theorem-like, define curr⟨env⟩ctr: in the ith environment of type ⟨env⟩, curr⟨env⟩ctr = i, and end⟨env⟩ctr: when the innermost environment is of type ⟨env⟩, in the jth potential position for an end mark in this environment, end⟨env⟩ctr = j. (if the counters are already defined, ⟨env⟩ is redefined, and these internal counters have to be continued).

Lines 499–516: define several commands: (\xdef expands the definition at the time it is called and makes it global):

Line 499: store the current value of \theoremsymbol (\edef: expand \the\theoremsymbol now) as ⟨env⟩Symbol.

Lines 500–502, 503–505: Define the commands \env and \env* to set the header of \env. (using a switch \thm@starredenv: \relax iff starred).

Lines 506, 507: Set \end⟨env⟩* to \end⟨env⟩. Lines 508–516: define \setparms@⟨env⟩ to set the style parameters of the header

for every ⟨env⟩ environment (in the sequel, current means, at the moment

\@newtheorem is called):

Lines 509, 510: setting \theorem@headerfont to the current value of \theoremheaderfont, followed by a check if it is a bold style, Lines 511, 512: setting \theorem@separator to the current value of \theoremseparator, Lines 513, 514: setting \theorem@indent to the current value of \theoremindent, Line 515: executing the command sequence currently stored in \theorembodyfont,

and

Line 516: calling th@\the\theorem@@style (which initializes \@begintheorem and
   \@opargbegintheorem according to the current value of \theoremstyle by
   calling th@\the\theorem@@style),

Note, that the \@ifdefinable from line 489 ends after line 516. Line 517: According to the next character, call \@othm{⟨env⟩} (if another counter

is used) or \@nthm{⟨env⟩}. Thus, when calling \@newthm with #1=⟨env⟩, for current values \theoremstyle=plain,

\theorembodyfont=\upshape, \theoremheaderfont=\bf, \theoremseparator=:,
and \theoremindent=1cm, the macro \setparms@env becomes
     \setparms@⟨env⟩ == \def\theorem@headerfont{\bf\theorem@checkbold}
                          \def\theorem@separator{:}
                          \def\theorem@indent{0cm}
                          \upshape
                          \th@plain

Note, that line 515 must not be inside any \if...\fi construct.

\@renewtheorem
518 \gdef\@renewtheorem#1{%
519 \expandafter\@ifundefined{#1}%
520 {\PackageError{\basename}{Theorem style #1 undefined}\@ehc}%
521  {}%
522 \expandafter\let\csname #1\endcsname\relax
523 \expandafter\let\csname #1*\endcsname\relax
524 \newtheorem{#1}}

Argument: ⟨env⟩:=#1 is the (internal) environment name to be redefined, which is read from the L^{A}TEX source. If ⟨env⟩ is already defined, make it (and ⟨env⟩*, too) undefined and call

\newtheorem{⟨env⟩}.

\@nthm \@nthm is called by \@newtheorem if the environment to be defined has a counter of its own.

525 \gdef\@nthm#1#2{%
526 \expandafter\xdef\csname num@addtheoremline#1\endcsname{%
527  \noexpand\@num@addtheoremline{#1}{#2}}%
528 \expandafter\xdef\csname nonum@addtheoremline#1\endcsname{%
529  \noexpand\@nonum@addtheoremline{#1}{#2}}%
530 \@ifnextchar[{\@xnthm{#1}{#2}}{\@ynthm{#1}{#2}}}

Arguments: ⟨env⟩:=#1 is the (internal) environment name to be defined (transmitted from

\@newtheorem).

⟨output name⟩:=#2 is its “name” to be used in the output (read from the L^{A}TEX source). Lines 526–529: Define \(no)num@addtheoremline⟨env⟩ to call

   \@(no)num@addtheoremline{⟨env⟩}{⟨output name⟩}.

For comments on \@num@addtheoremline and \@nonum@addtheoremline see

Section 7.1.7. Line 530: According to the next character, call \@xnthm{⟨env⟩}{⟨output name⟩} (if

⟨env⟩-environments should be numbered relative to some structuring level) or \@ynthm{⟨env⟩}{⟨output name⟩}.

\@othm \@othm is called by \@newtheorem if the environment to be defined uses another counter.

531 \gdef\@othm#1[#2]#3{%
532 \@ifundefined{c@#2}{\@nocounterr{#2}}%
533 {\ifthm@tempif
534  \global\@namedef{the#1}{\@nameuse{the#2}}%
535  \expandafter\xdef\csname num@addtheoremline#1\endcsname{%
536  \noexpand\@num@addtheoremline{#1}{#3}}%
537  \expandafter\xdef\csname nonum@addtheoremline#1\endcsname{%
538  \noexpand\@nonum@addtheoremline{#1}{#3}}%
539  \expandafter\gdef\csname mkheader@#1\endcsname
540  {\csname setparms@#1\endcsname
541  \@thm{#1}{#2}{#3}}%
542  \global\@namedef{end#1}{\@endtheorem}\fi}}

Arguments: ⟨env⟩:=#1 is the (internal) environment name to be defined (transmitted from

\@newtheorem).

⟨use ctr⟩:=#2 is the internal name of the theorem which counter is used, and ⟨output name⟩:=#3 is its “name” to be used in the output (both read from the L^{A}TEX source). Line 532: if the counter to be used is undefined, goto error, else set \the⟨env⟩ to

use \the⟨use ctr⟩ and do the following: Lines 534–542 happen only if ⟨env⟩ is not yet defined or gets redefined: Line 534: (from latex.ltx) make ⟨env⟩ use the counter ⟨use ctr⟩. Lines 535–538 similar to lines 526–529 of \@nthm. Lines 539–541 define \mkheader@⟨env⟩ to set the style parameters of the header and

set the header (by \@thm):

\mkheader@⟨env⟩ == \setparms@⟨env⟩\@thm{⟨env⟩}{⟨use ctr⟩}{⟨output name⟩}.

(\setparms@⟨env⟩ is defined when \@newtheorem{⟨env⟩} is carried out). Line 542: (from latex.ltx): \end⟨env⟩ calls \@endtheorem.

\@xnthm \@xnthm is called by \@nthm if the numbering is relative to some structuring level.

543 \gdef\@xnthm#1#2[#3]{%
544 \ifthm@tempif
545  \expandafter\@ifundefined{c@#1}%
546  {\@definecounter{#1}}{}%
547  \@newctr{#1}[#3]%
548  \expandafter\xdef\csname the#1\endcsname{%
549  \expandafter\noexpand\csname the#3\endcsname \@thmcountersep
550  {\noexpand\csname\the\theoremnumbering\endcsname{#1}}}%
551  \expandafter\gdef\csname mkheader@#1\endcsname
552  {\csname setparms@#1\endcsname
553  \@thm{#1}{#1}{#2}}%
554  \global\@namedef{end#1}{\@endtheorem}\fi}

Arguments: ⟨env⟩:=#1 is the (internal) environment name to be defined (transmitted from

\@newtheorem).

⟨output name⟩:=#2 is its “name” to be used in the output, ⟨level⟩:=#3 is the structuring level relative to which ⟨env⟩ has to be numbered (both read from the L^{A}TEX source). Lines 545–554 happen only if ⟨env⟩ is not yet defined or gets redefined: Lines 545,546: in not yet defined, define ⟨env⟩- counter (otherwise, ⟨env⟩ is rede-

fined). Line 548: (from latex.ltx): define the counter for ⟨env⟩ and add ⟨level⟩ to its reset-

triggers. Lines 549, 550: define \the⟨env⟩ to be the command sequence

\the⟨level⟩\@thmcountersep⟨numbering⟩{⟨env⟩} ,

where ⟨numbering⟩ is the value of \theoremnumbering when \@xnthm (and thus, \newtheorem{⟨env⟩}) is called.

Lines 551–553: define \mkheader@⟨env⟩ to set the style parameters of the header and set the header (by \@thm):

\mkheader@⟨env⟩ == \setparms@⟨env⟩\@thm{⟨env⟩}{⟨env⟩}{⟨output name⟩}.

(\setparms@⟨env⟩ is defined when \@newtheorem{⟨env⟩} is carried out). Line 554: (from latex.ltx): \end⟨env⟩ calls \@endtheorem.

\@ynthm \@ynthm is called by \@nthm if the counter is not relative to any structuring level.

555 \gdef\@ynthm#1#2{%
556 \ifthm@tempif
557  \expandafter\@ifundefined{c@#1}%
558  {\@definecounter{#1}}{}%
559  \expandafter\xdef\csname the#1\endcsname
560  {\noexpand\csname\the\theoremnumbering\endcsname{#1}}%
561  \expandafter\gdef\csname mkheader@#1\endcsname
562  {\csname setparms@#1\endcsname
563  \@thm{#1}{#1}{#2}}%
564  \global\@namedef{end#1}{\@endtheorem}\fi}

Arguments: ⟨env⟩:=#1 is the (internal) environment name to be defined (transmitted from

\@newtheorem).

⟨output name⟩:=#2 is its “name” to be used in the output. \@ynthm works analogous to \@xnthm.

Handling Instances of Theorem-Environments.

\@thm \@thm is called by \@⟨env⟩ (which is defined by \@othm/\@xnthm/\@ynthm).

565 \gdef\@thm#1#2#3{%
566 \if@thmmarks
567  \stepcounter{end\InTheoType ctr}%
568 \fi
569 \renewcommand{\InTheoType}{#1}%
570 \if@thmmarks

571  \stepcounter{curr#1ctr}%
572  \setcounter{end#1ctr}{0}%
573 \fi
574 \refstepcounter{#2}%
575 \thm@topsepadd \theorempostskipamount   % cf. latex.ltx: \@trivlist
576 \ifvmode \advance\thm@topsepadd\partopsep\fi
577 \trivlist
578 \@topsep \theorempreskipamount
579 \@topsepadd \thm@topsepadd        % used by \@endparenv
580 \advance\linewidth -\theorem@indent
581 \advance\@totalleftmargin \theorem@indent
582 \parshape \@ne \@totalleftmargin \linewidth
583 \@ifnextchar[{\@ythm{#1}{#2}{#3}}{\@xthm{#1}{#2}{#3}}}

Changed to three instead of two parameters (the first one is new): ⟨env⟩:=#1: (added) internal name of the theorem environment, ⟨use ctr⟩:=#2: internal name of the theorem which counter is used, ⟨output name⟩:=#3: keyword to be displayed in the output; all arguments are

transmitted from \@othm/\@xnthm/\@ynthm.

Lines 566–568: if thmmarks is active, the counter for the current environment ⟨env’⟩ is incremented, since the last endmark in environment ⟨env’⟩ is definitely not the position for its endmark (necessary for nested environments ending at the same time).

Lines 569: set \InTheoType to ⟨env⟩. Lines 570–573: if thmmarks is active, increment curr⟨env⟩ctr and set end⟨env⟩ctr

to 0. Lines 574: adapted from latex.ltx: increment the corresponding counter.

Lines 575–579: handle \theorempreskipamount and \theorempostskipamount (if

in vmode, there is additional space, cf. \trivlist and \@trivlist in latex.ltx). Lines 580–582: handle \theoremindent. Lines 583: if there is an optional argument, call \@ythm{⟨env⟩}{⟨use ctr⟩}{⟨output name⟩},

otherwise call \@xthm{⟨env⟩}{⟨use ctr⟩}{⟨output name⟩}.

\@xthm \@xthm is called by \@thm if there is no optional text in the theorem header.

584 \def\@xthm#1#2#3{%
585 \@begintheorem{#3}{\csname the#2\endcsname}%
586 \ifx\thm@starredenv\@undefined
587  \thm@thmcaption{#1}{{#3}{\csname the#2\endcsname}{}}\fi
588 \ignorespaces}

Changed to three instead of two parameters (the first one is new): ⟨env⟩:=#1: (added) internal name of the theorem environment, ⟨use ctr⟩:=#2: internal name of the theorem which counter is used, ⟨output name⟩:=#3: keyword to be displayed in the output. All arguments are transmitted from \@thm. For comments, see \@ythm.

\@ythm \@ythm is called by \@thm if there is an optional text in the theorem header.

589 \def\@ythm#1#2#3[#4]{%
590 \@opargbegintheorem{#3}{\csname the#2\endcsname}{#4}%
591 \ifx\thm@starredenv\@undefined
592  \thm@thmcaption{#1}{{#3}{\csname the#2\endcsname}{#4}}\fi%

593 \ignorespaces}

Changed to four instead of three parameters (the first one is new): ⟨env⟩:=#1: (added) internal name of the theorem environment, ⟨use ctr⟩:=#2: internal name of the theorem which counter is used, ⟨output name⟩:=#3: keyword to be displayed in the output. ⟨opt text⟩:=#4: optional text to appear in the header. #1–#3 are transmitted from \@thm, #4 is read from the L^{A}TEX source. Line 590: call

       \@opargbegintheorem{⟨output name⟩}{\the⟨use ctr⟩}{⟨opt text⟩}

which outputs the header. Line 591, 592: if ⟨env⟩ is not the starred version, call

\thm@thmcaption{⟨output name⟩}{\the⟨use ctr⟩}{⟨opt text⟩}

which makes an entry into the theorem list.

\@endtheorem \@endtheorem it is only changed by option [thmmarks]. Otherwise refer to the definition in latex.ltx

7.1.7 Generation of Theorem Lists

The following macros are are needed for the generation of theorem-lists. We will document it for the theorem \begin{definition}[optional], which we assume to be the first definition at all and which is placed on page 5.

\thm@thmcaption This macro, used internally, strips of the outer brackets from the second argument and calls \thm@@thmcaption. It’s typically called like this

     \thm@thmcaption{defintion}{{Definition}{1}{optional}}
594 \def\thm@thmcaption#1#2{\thm@@thmcaption{#1}#2}

\thm@@thmcaption This macro receives it’s arguments from \thm@caption. The optional text of the theorem is prepared for writing into the .thm-file by \thm@parseforwriting. After this call, \thm@tmp holds the unexpandable optional text. At least, we write the data into the .aux file, which will forward it to the theorem-file.

595 \def\thm@@thmcaption#1#2#3#4{%
596  \thm@parseforwriting{#4}%
597  \edef\thm@t{{#2}{#3}{\thm@tmp}}%
598  \addcontentsline{thm}{#1}{\thm@t}}

The following four macros set up the predefined list-types. To do so, they define the internal macros \thm@@thmlstart (containing the code to be executed at the beginning of the list), \thm@@thmlend (code to be executed at the end of the list) and \thm@@thmline (code to be executed for every line). In order to gain compatibility with newthm.sty, we decided not to make this commands inaccessible to the user. But we recommend not using these commands, because they may disappear in later distributions.

\theoremlistall This one implements the type all.

599 \def\theoremlistall{%
600  \let\thm@@thmlstart=\relax

601  \let\thm@@thmlend=\relax
602  \def\thm@@thmline##1##2##3##4{%
603  \@dottedtocline{-2}{0em}{2.3em}%
604  {\protect\numberline{##2}##3}%
605  {##4}}}
\theoremlistallname And here’s the type allname.
606 \def\theoremlistallname{%
607  \let\thm@@thmlstart=\relax
608  \let\thm@@thmlend=\relax
609  \def\thm@@thmline##1##2##3##4{%
610  \@dottedtocline{-2}{0em}{2.3em}%
611  {##1 \protect\numberline{##2}##3}%
612  {##4}}}
\theoremlistoptional This one is the list-type opt.
613 \def\theoremlistoptional{%
614  \let\thm@@thmlstart=\relax
615  \let\thm@@thmlend=\relax
616  \def\thm@@thmline##1##2##3##4{%
617  \ifx\empty ##3%
618  \else%
619  \@dottedtocline{-2}{0em}{2.3em}%
620  {\protect\numberline{##2}##3}%
621  {##4}%
622  \fi}}
\theoremlistoptname And the last type, optname:
623 \def\theoremlistoptname{%
624  \let\thm@@thmlstart=\relax
625  \let\thm@@thmlend=\relax
626  \def\thm@@thmline##1##2##3##4{%
627  \ifx\empty ##3%
628  \else%
629  \@dottedtocline{-2}{0em}{2.3em}%
630  {##1 \protect\numberline{##2}##3}%
631  {##4}%
632  \fi}}

Now we set up the default type:

633 \theoremlistall

\theoremlisttype The next one is the user-interface for selecting the list-type. It simply calls \thm@thml@⟨type⟩, if the given ⟨type⟩ is defined.

634 \def\theoremlisttype#1{%
635  \@ifundefined{thm@thml@#1}%
636  {\PackageError{\basename}{Listtype #1 not defined}\@eha}
637  {\csname thm@thml@#1\endcsname}}

Now, here is a the code, which maps the types – selected by \theoremlisttype – to the defined macros.

638 \def\thm@thml@all{\theoremlistall}
639 \def\thm@thml@opt{\theoremlistoptional}

640 \def\thm@thml@optname{\theoremlistoptname}
641 \def\thm@thml@allname{\theoremlistallname}

\newtheoremlisttype According to the given documentation, this one can be used to define new listtypes. It’s done by defininig the macro \thm@thml@⟨type⟩, which locally redefines

the commands \thm@thmlstart, \thm@@thmline and \thm@@thmlend.
642 \def\newtheoremlisttype#1#2#3#4{%
643 \@ifundefined{thm@thml@#1}%
644 {\expandafter\gdef\csname thm@thml@#1\endcsname{%
645  \def\thm@@thmlstart{#2}%
646  \def\thm@@thmline####1####2####3####4{#3}%
647  \def\thm@@thmlend{#4}}%
648 }{\PackageError{\basename}{list type #1 already defined}\@eha}}
\renewtheoremlisttype
649 \def\renewtheoremlisttype#1#2#3#4{%
650 \@ifundefined{thm@thml@#1}%
651  {\PackageError{\basename}{List type #1 not defined}\@ehc}{}%
652 \expandafter\let\csname thm@thml@#1\endcsname\relax
653 \newtheoremlisttype{#1}{#2}{#3}{#4}}

if the list type to be redefined is already defined, make it undefined and define it.

\thm@thmline This is another short one, which only discards the outer brackets from the first argument and calls \thm@@thmline. It’s normally called like this:

     \thm@@thmline{{Definition}{1}{optional}}{5}
654 \def\thm@thmline#1#2{\thm@@thmline#1{#2}}

\thm@lgobble The next macro is used to ignore all theorem-sets, which should not be listed.

655 \long\def\thm@lgobble#1#2{\ignorespaces}

\thm@definelthm For each theorem-set, we need to setup two commands. Thus, the next macro is called by \newtheorem. It defines the command \l@⟨theorem-set⟩ and \thm@listdo⟨theorem-set⟩, which initially discard the input by calling \thm@lgobble. The first one is called for each theorem when you are generating lists. The second one is called, if you’ve added something with \addtotheoremfile.

656 \def\thm@definelthm#1{%
657 \expandafter\gdef\csname l@#1\endcsname{\thm@lgobble}%
658 \expandafter\gdef\csname thm@listdo#1\endcsname{\thm@lgobble}}

\thm@inlistdo If in some case, you’ve written addtional text into the theorem-file by \addtotheoremfile, this one is called internally. It simply discards the first argument and strips of the outer brackets from the second one.

659 \long\def\thm@inlistdo#1#2{#2}%

\listtheorems Now we need the user-interface for generating lists. This is done by the next macro. We set the tocdepth to −2 to assure that the predefined list-types work. After storing the names of the theorem-sets, we call \thm@processlist, which actually generates the list.

660 \def\listtheorems#1{\begingroup%
661 \c@tocdepth=-2%
662 \def\thm@list{#1}\thm@processlist%
663 \endgroup}

\thm@processlist To generate the specified list, we redefine globally the commands \l@⟨theorem-set⟩ and \thm@listdo⟨theorem-set⟩. Remember that these initially were set to ignore everything. After reading in the theorem-file, we redefine the mentioned commands to discard everything again. We need to define the macros globally, to deal with complex list-types, which the user may define.

664 \def\thm@processlist{%
665 \begingroup%
666 \typeout{** Generating table of \thm@list}%
667 \thm@@thmlstart
668 \@for\thm@currentlist:=\thm@list\do{%
669 \ifx\thm@currentlist\@empty\else%
670 \expandafter\gdef\csname l@\thm@currentlist\endcsname{\thm@thmline}%
671 \expandafter\gdef\csname thm@listdo\thm@currentlist\endcsname{\thm@inlistdo}%
672 \fi%

673 }%

674 \@input{\jobname .thm}%
675 \thm@@thmlend%
676 \@for\thm@currentlist:=\thm@list\do{%
677 \ifx\thm@currentlist\@empty\else%
678 \expandafter\gdef\csname l@\thm@currentlist\endcsname{\thm@lgobble}%
679 \expandafter\gdef\csname thm@listdo\thm@currentlist\endcsname{\thm@lgobble}%
680 \fi%

681 }%

682 \endgroup}

\thm@enablelistoftheorems Up to now, we’ve set up various macros to write and read the theorem-file. Thus, it’s time to set up the file itself. This is done by the next macro. We simply took the lines for \@starttoc from the L^{A}TEX-base and changed some things. The main intention to copy \@starttoc is, that we don’t want the file to be input when it is set up – like it’s done by \@starttoc.

683 \def\thm@enablelistoftheorems{%
684 \begingroup%
685  \makeatletter%
686  \if@filesw%
687  \expandafter\newwrite\csname tf@thm\endcsname%
688  \immediate\openout \csname tf@thm\endcsname \jobname.thm\relax%
689  \fi%
690  \@nobreakfalse%
691 \endgroup}

\addtheoremline Using this one, the user may insert an extra entry into the theorem-file. The macro first checks if it ends with an asterix. In this case, the internal macro

\nonum@addtheoremline is called, otherwise we call \num@addtheoremline. The

latter two will append the given name of the theorem-set to the macroname and call these new macros, which itself will call \@nonum@addtheoremlline or \@num@addtheoremline. This may sound a bit fuzzy, but we do it this way, to extract additional information from the theorem-definition.

692 \def\addtheoremline{\@ifstar{\nonum@addtheoremline}{\num@addtheoremline}}
693 \def\nonum@addtheoremline#1{\csname nonum@addtheoremline#1\endcsname}%
694 \def\num@addtheoremline#1{\csname num@addtheoremline#1\endcsname}%

\@nonum@addtheoremline Now here is the code, used to write the extra entry for theorems with no numbering.

695 \def\@nonum@addtheoremline#1#2#3{%
696  \thm@parseforwriting{#3}%
697  \edef\thm@t{{#2}{}{\thm@tmp}}%
698  \addcontentsline{thm}{#1}{\thm@t}}

\@num@addtheoremline And this one is used to write numbered extra entries.

699 \def\@num@addtheoremline#1#2#3{%
700 \thm@parseforwriting{#3}%
701  \edef\thm@t{{#2}{\csname the#1\endcsname}{\thm@tmp}}%
702  \addcontentsline{thm}{#1}{\thm@t}}

\addtotheoremfile To write any addtional stuff into the theorem-file, the next macro is used. It first checks, if the optional name of a theorem-set is given. In that case, the macro

 \@@addtotheoremfile, otherwise \@addtotheoremfile is used to write the stuff

into the file.

703 \long\def\addtotheoremfile{%
704 \@ifnextchar[{\@@addtotheoremfile}{\@addtotheoremfile}}

\@addtotheoremfile Write a additional stuff for all theorems.

705 \long\def\@addtotheoremfile#1{%
706 \thm@parseforwriting{#1}%
707 \protected@write\@auxout%
708  {}{\string\@writefile{thm}{\thm@tmp}}}

\@@addtotheoremfile Write additional stuff for a theorem-set.

709 \long\def\@@addtotheoremfile[#1]#2{%
710 \thm@parseforwriting{#2}%
711 \protected@write\@auxout%
712  {}{\string\@writefile{thm}{\string\theoremlistdo{#1}{\thm@tmp}}}}

\theoremlistdo This one is called out of the theorem-file to insert the addtional stuff for a theoremset.

713 \long\def\theoremlistdo#1#2{\csname thm@listdo#1\endcsname{#1}{#2}}

Now we assure, that the theorem-file is activated. This is done by inserting a hook at the end of the document.

714 \AtEndDocument{\thm@enablelistoftheorems}

7.1.8 Auxiliary macros

To generate theorem-lists, we need to write informations into a separate file. Cause, we don’t wand to exand these information, we parse them specially for writing.

715 \def\thm@meaning#1->#2\relax{#2}% remove "macro:->"
716 \long\def\thm@parseforwriting#1{%
717  \def\thm@tmp{#1}%
718  \edef\thm@tmp{\expandafter\thm@meaning\meaning\thm@tmp\relax}}

In some countries it’s usual to number theorems with greek letters. Cause L^{A}TEX doesn’t support this type, we implemented it into ntheorem.sty.

\theorem@checkbold For correctness, we need to check if a bold font is actived. This is done by the follwing macro:

719 \def\theorem@checkbold{\if b\expandafter\@car\f@series\@nil\boldmath\fi}

\@greek Accoding to L^{A}TEX-base, this is the internal command for generating lowercase greek numberings.

720 \def\@greek#1{\theorem@checkbold%
721 \ifcase#1\or$\alpha$\or$\beta$\or$\gamma$\or$\delta$\or$\varepsilon$%
722 \or$\zeta$\or$\eta$\or$\vartheta$\or$\iota$\or$\kappa$\or$\lambda$\or$%
723 \mu$\or$\nu$\or$\xi$\or$ o$\or$\varpi$\or$\varrho$\or$\varsigma$\or$\tau$%
724 \or$\upsilon$\or$\varphi$\or$\chi$\or$\psi$\or$\omega$\else\@ctrerr\fi}

\@Greek Accoding to L^{A}TEX-base, this is the internal command for generating uppercase greek numberings.

725 \def\@Greek#1{\theorem@checkbold%
726 \ifcase#1\or A\or B\or$\Gamma$\or$\Delta$\or E%
727 \or Z\or H\or$\Theta$\or I\or K\or$\Lambda$\or M%
728 \or N\or$\Xi$\or O\or$\Pi$\or P\or$\Sigma$\or T%
729 \or$\Upsilon$\or$\Phi$\or X\or$\Psi$\or$\Omega$\else\@ctrerr\fi}

\greek According to L^{A}TEX-base, this is the user interface for lowercase greek numberings.

730 \def\greek#1{\@greek{\csname c@#1\endcsname}}

\Greek According to L^{A}TEX-base, this is the user interface for uppercase greek numberings.

731 \def\Greek#1{\@Greek{\csname c@#1\endcsname}}

7.1.9 Other Things

After declaring several package-options, we need to process the specified ones. The additional relax was mentioned by Rainer Schöpf at DANTE’97.

732 \ProcessOptions\relax

Now we check if the file ntheorem.cfg is present and eventually read the definitions in that file. If it’s not present and the option standard was specified, the file

 ntheorem.std is used.
733 \InputIfFileExists{ntheorem.cfg}%
734 {\PackageInfo{\basename}{Local config file ntheorem.cfg used}}%
735 {\ifx\thm@usestd\@undefined%
736 \else%
737  \InputIfFileExists{ntheorem.std}%
738  {\PackageInfo{\basename}{Standard config file ntheorem.std used}}{}
739 \fi}

7.2 The Standard Configuration

  1 \theoremnumbering{arabic}
  2 \theoremstyle{plain}
  3 \RequirePackage{latexsym}
  4 \theoremsymbol{\ensuremath{_\Box}}
  5 \theorembodyfont{\itshape}
  6 \theoremheaderfont{\normalfont\bfseries}
  7 \theoremseparator{}
  8 \newtheorem{Theorem}{Theorem}
  9 \newtheorem{theorem}{Theorem}
 10 \newtheorem{Satz}{Satz}
 11 \newtheorem{satz}{Satz}
 12 \newtheorem{Proposition}{Proposition}

13 \newtheorem{proposition}{Proposition}
14 \newtheorem{Lemma}{Lemma}
15 \newtheorem{lemma}{Lemma}
16 \newtheorem{Korollar}{Korollar}
17 \newtheorem{korollar}{Korollar}
18 \newtheorem{Corollary}{Corollary}
19 \newtheorem{corollary}{Corollary}

20

21 \theorembodyfont{\upshape}
22 \newtheorem{Example}{Example}
23 \newtheorem{example}{Example}
24 \newtheorem{Beispiel}{Beispiel}
25 \newtheorem{beispiel}{Beispiel}
26 \newtheorem{Bemerkung}{Bemerkung}
27 \newtheorem{bemerkung}{Bemerkung}
28 \newtheorem{Anmerkung}{Anmerkung}
29 \newtheorem{anmerkung}{Anmerkung}
30 \newtheorem{Remark}{Remark}
31 \newtheorem{remark}{Remark}
32 \newtheorem{Definition}{Definition}
33 \newtheorem{definition}{Definition}

34

35 \theoremstyle{nonumberplain}
36 \theoremheaderfont{\scshape}
37 \theorembodyfont{\normalfont}
38 \theoremsymbol{\ensuremath{_\blacksquare}}
39 \RequirePackage{amssymb}
40 \newtheorem{Proof}{Proof}
41 \newtheorem{proof}{Proof}
42 \newtheorem{Beweis}{Beweis}
43 \newtheorem{beweis}{Beweis}
44 \qedsymbol{\ensuremath{_\blacksquare}}

8 History and Acknowledgements

8.1 The endmark-Story (Wolfgang May)

In 1995, I started a hack for setting endmarks semiautomatically at the end of displayed formulas. The work on thmmarks.sty was initiated in October 1996 by a thread asking for a routine for setting endmarks in de.comp.tex founded by Boris Piwinger. Version 0.1 incorporated the main features for setting endmarks automagically by using the .aux file. Version 0.2 included some bugfixes and was the first one accessible on the internet. Boris suggested to include fleqn and leqno which has been done in version 0.3 (which was never made public). Since at this point, thmmarks.sty was incompatible to the widely used theorem.sty written by Frank Mittelbach, in Version 0.4, the features of theorem.sty have been integrated. To version 0.5, the case of “empty” end symbols has been handled, \qed has been added (also suggested by Boris), and the handling of theoremstyles by

\newtheoremstyle has been included.

For version 0.6, the handling of endmarks in displaymaths has been changed in order to adjust them with the bottom of the displayed math.

Version 0.6 was the first one announced in comp.text.tex. For version 0.7, I added the handling of amslatex features, suggested by my colleague Peter Neuhaus. Versions 0.71 and 0.72 incorporated minor bugfixes.

8.2 Lists, Lists, Lists (Andreas Schlechte)

I often saw questions on theoremlists in the german newsgroup de.comp.text.tex, but I never spent any attention on those postings. This changed in summer 1996, when I needed those lists for myself. Thus, I asked the holy question. But none of the given answers satisfied my wish for an simple, easy to use and short solution. I decided to take a look at Frank Mittelbachs theorem.sty. First I didn’t understand much of the code, but Bernd Raichle helped me a lot by answering my boring questions and I finally understood it. I started the coding and within a few days, a first experimental version was born. Not only, that I had implemented the lists, I also inserted a separator and a flexible numbering of the theorems. After a long period of testing, I wanted to share the new features with other TEX-Freaks and wrote an article for the “Die TEXnische Komödie” (Journal of german tug, DANTE e.V.). As soon as I had sent the article to DANTE, I got first reactions on the style. Gerd Neugebauer gave me many hints. I hided several cryptical notations in easy definitions and improved the user interface. In January 1997, I released “newthm” to the world and it was uploaded to the CTAN-Archives. Few days later I send my files to Frank Mittelbach in order to show him my extensions. He told me, that already other extensions were made, and that it would be good, to combine alltogether.

8.3 Let’s come together

With version 0.8, in February 1997, the combination of thmmarks.sty with

newthm.sty to ntheorem.sty has been started.

Since this time, the following changes were made: On April 21, 1997, version 0.94 beta has been made public as version 1.0.

8.4 Acknowledgements

This place is dedicated to all those, who helped us developing our separate styles and this combined package. Thanks to (listed in alphabetical order):

Frank Mittelbach, Gerd Neugebauer, Boris Piwinger, Bernd Raichle and Rainer Schöpf