%\iffalse -*- doctex -*- \fi
%
%% \RCS$Id: pmn-fxme.sty,v 1.5 2004/08/27 23:47:17 turtle Exp $
%% \RCS$Revision: 1.5 $
%% \RCS$Date: 2004/08/27 23:47:17 $
%
%\iffalse metacomment
% -*- latex-mode -*-
%%  (C) 2004 Peter Møller Neergaard
%%  
%%   This program may be distributed and/or modified under the
%%   conditions of the LaTeX Project Public License, either version 1.2
%%   of this license or (at your option) any later version.
%%   The latest version of this license is in
%%     http://www.latex-project.org/lppl.txt
%%   and version 1.2 or later is part of all distributions of LaTeX 
%%   version 1999/12/01 or later.
%
% This program consists of the file pmn-fxme.sty.
% 
% To print the documentation (which for the moment is uninteresting)
% remove (or comment out) the line
%
%   \endinput
%
% occurring immediately after
%
%   %<*documentation>
% 
%\fi
%
% \CheckSum{13}
% \CharacterTable
%  {Upper-case    \A\B\C\D\E\F\G\H\I\J\K\L\M\N\O\P\Q\R\S\T\U\V\W\X\Y\Z
%   Lower-case    \a\b\c\d\e\f\g\h\i\j\k\l\m\n\o\p\q\r\s\t\u\v\w\x\y\z
%   Digits        \0\1\2\3\4\5\6\7\8\9
%   Exclamation   \!     Double quote  \"     Hash (number) \#
%   Dollar        \$     Percent       \%     Ampersand     \&
%   Acute accent  \'     Left paren    \(     Right paren   \)
%   Asterisk      \*     Plus          \+     Comma         \,
%   Minus         \-     Point         \.     Solidus       \/
%   Colon         \:     Semicolon     \;     Less than     \<
%   Equals        \=     Greater than  \>     Question mark \?
%   Commercial at \@     Left bracket  \[     Backslash     \\
%   Right bracket \]     Circumflex    \^     Underscore    \_
%   Grave accent  \`     Left brace    \{     Vertical bar  \|
%   Right brace   \}     Tilde         \~}
%
% \MakeShortVerb{\"}
%
% \title{The \package{pmn-fxme} package\thanks
%   {This file has CVS revision \RCSRevision, dated \RCSDate.}}
% \author{Peter Møller Neergaard}
% \maketitle
%
% \begin{abstract}
%   This an enhancement of the \package{fixme} to allow a priority on
%   each fixme.  The priority is used when printing the list of fixmes.
%   Each fixme is indented according to priority and fixme with a low
%   priority can be suppressed. 
% \end{abstract}
%
% This package extends the \package{fixme} package (loaded
% automatically) which allows you to make fixme notes. It is loaded
% using "\usepackage{pmn-fxme} and has the same options as
% \package{fixme}.
%
% \DescribeMacro{\pmnfix}
% \mcmd{\pmnfix}\oarg{time}\marg{priority}\marg{note} Makes a fixme note of
% priority \meta{priority} (a positive integer).
%
% \DescribeMacro{\pmnlistoffixmes} list the fixmes in order of
% priority.
%
% \DescribeMacro{pmnfixdepth} 
% The counter "pmnfixdepth" controls the deepest level of fixmes that
% should be included in the list of fixmes (fixmes with a priority are
% always included).
%
% \DescribeMacro{\pmnfixIndentation}
% When using \package{fixme}'s \cmd{listoffixmes} the fixmes with
% priority are indented according to the priority.  The indentation
% per level is controled by \cmd{\pmnfixIndentation}.
%
% \DescribeMacro{\pmnfixDefault}
% \DescribeMacro{\cs{pmnfixFormat\meta{priority}}} 
% \mcmd{\pmnfixDefault}\marg{priority}\marg{note}\marg{pageno} is the
% default macro to format an entry in the list of fixmes.  The
% standard entry uses \cmd{\pmnfixIndentation} as described above. If
% you generally want to change the formatting you can modify this
% macro.  If you only want to change a single priority level, modify
% \cs{pmnfixFormat\meta{priority}} where \meta{priority} is the level.
%
% \section{Package identification}
% 
% We identify ourselves and load \package{fixme}.
%    \begin{macrocode}
\NeedsTeXFormat{LaTeX2e}
\ProvidesPackage{pmn-fxme}[2004/07/06 v0.1
                        PMN improved insertion of  fixme notes]
\@ifpackageloaded{fixme}%
  {\DeclareOption*{}}%
  {\DeclareOption*{\PassOptionsToPackage\CurrentOption{fixme}}}
\ProcessOptions*
\@ifpackageloaded{fixme}{}%
  {\RequirePackage{fixme}}
%    \end{macrocode}
% \changes{}{2004/08/25}{only loading fixme if not already loaded}
%
% \section{Inserting a fixme note}
% We define the \cs{pmnfix} command which makes one of my priority
% fixme notes.
% \begin{macro}{\pmnfix}
% \begin{macro}{\pmnfixFixmeCommand}
%   \mcnd{\pmnfx}\oarg{time}\marg{priority}\marg{note} makes a fixme \meta{note} of
%   \meta{priority}.
%    \begin{macrocode}
\newcommand{\pmnfix}[3][]{%
  \pmnfixFixmeCommand{\protect\pfx@pri{#2} \pfx@time{#1} {#3}}}
\let\pmnfixFixmeCommand\fixme
\AtBeginDocument{%
  \let\pfx@nopriority\l@fixme
  \let\pfx@list@standard\l@fixme
  \def\l@fixme{\pmn@l@fixme}%
  \let\pfx@priority\pfx@test@in@range}
%    \end{macrocode}
%   It uses a standard \package{fixme} command (as chosen by
%  \cmd{\pmnfixFixmeCommand}.  It uses
%  "\ifpmnfix@haspriority" to flag that this is note with priority.
% \end{macro} ^^A \pmnfixFixmeCommand
% \end{macro} ^^A \pmnfix
%
% \begin{macro}{\pfx@pri}
% \begin{macro}{\pfx@pri@set}
% \begin{macro}{\pfx@found@priority}
%   When it is a fixme note with priority we store priority using
%   "\pfx@pri{"\meta{priority}"}".  Usually, we let
%   \cmd{\pfx@pri} be \cmd{\relax} so the priority is printed.
%   However, when checking for the existence of a priority we use
%   \cmd{\pfx@pri@set} which stores the priority in
%   \cmd{\pfx@found@priority}. 
%    \begin{macrocode}
\let\pfx@pri\relax
\newcommand{\pfx@pri@set}[1]{\gdef\pfx@found@priority{#1}}
%    \end{macrocode}
% \end{macro}^^A \pfx@found@priority 
% \end{macro}^^A \pfx@pri@set 
% \end{macro}^^A \pfx@pri
%
% \begin{macro}{\pfx@time}
% \begin{macro}{\pfx@time@sum}
% \begin{macro}{\pfx@found@time}
%   When it is a fixme note with priority we store time using
%   "\pfx@time{"\meta{time}"}".  Usually, we let
%   \cmd{\pfx@time} be \cmd{\relax} so the time is simply  printed.
%   However, when print the list of jobs, we let \cmd{\pfx@time} point
%   to  \cmd{\pf@time@sum} which sums up the time annotations.
%    \begin{macrocode}
\let\pfx@time\relax
\newcommand{\pfx@time@sum}[1]{
  #1%
  \pfx@time@sum@m{#1}%
  \pfx@time@sum@h{#1}%
  \pfx@time@sum@d{#1}%
}
\newcommand{\pfx@reset@sums}{}
\newcommand{\pfx@print@sums}{\protect\pfx@print@sum@init}
\def\pfx@make@time@sum@unit#1{%
  \expandafter\expandafter\expandafter\newdimen\@nameuse{pfx@time@#1}%
  \edef\pfx@reset@sums{\global\pfx@reset@sums\@nameuse{pfx@time@#1}=\z@}%
  \protected@edef\pfx@print@sums{\pfx@print@sums \protect\pfx@print@sum{#1}}%
  \@namedef{pfx@time@sum@#1}##1{%
    \@nameuse{pfx@time@sum@#1@i}##1#1\foo}%
  \@namedef{pfx@time@sum@#1@i}##1#1##2\foo{%
     \def\reserved@a{##2}%
     \ifx\reserved@a\@empty\else
        \global\advance\@nameuse{pfx@time@#1} by ##1pt
     \fi}}
\pfx@make@time@sum@unit{d}
\pfx@make@time@sum@unit{m}
\pfx@make@time@sum@unit{h}
\newcommand{\pfx@print@sum@init}{%
  \def\pfx@opt@totaltxt{\noindent Total: }}
\newcommand{\pfx@print@sum}[1]{%
  \ifdim\@nameuse{pfx@time@#1}>\z@
    \pfx@opt@totaltxt
    \let\pfx@opt@totaltxt\relax
    \edef\reserved@a{\@nameuse{pfx@time@#1}}%
    \expandafter\strip@pt\reserved@a#1 
  \fi}
%    \end{macrocode}
% \end{macro}^^A \pfx@found@priority 
% \end{macro}^^A \pfx@time@set 
% \end{macro}^^A \pfx@time
%
% \section{List of Fixmes}
% 
% We then make set up the printing of the list of fixmes.  We first
% define the general dispatching which takes an entry and decides
% whether it should be listed.  Then we have backend procedures to
% actually list the entry if it passes the needle's eye.  We can
% therefore use the dispatching both for the regular list and with
% individual lists.
%
% Concretely, we replace \cmd{\l@fixme} by \cmd{\pmn@l@fixme}.  It
% tests whether it as a standard fixme note (if it is formatted using
% \cmd{\pfx@nopriority} which is usually the standard \cmd{l@fixme});
% otherwise it is formatted using \cmd{\pfx@priority}.  Normally,
% \cmd{\pfx@priority} invokes \cmd{\pfx@test@in@range} which tests
% whether we are in the listable range and if so dispatch the formatting
% procedure specified by \cmd{\pfx@list@in@range}.  
%
% The many definable entries allow us to turn the processing on or off
% in various ways: we can disable processing by letting
% \cmd{\pfx@nopriority} or \cmd{\pfx@priority} gobble their
% arguments.  By changing \cmd{\pfx@list@in@range} we can either
% output the entry directly or, when listing in decreasing priority,
% do some further processing.
%  
% \begin{macro}{pmnfixdepth}
%    The counter "pmnfixdepth" contains the maximum depth of fixme to
%    be included; a negative number means all.
%    \begin{macrocode}
\newcounter{pmnfixdepth}
\setcounter{pmnfixdepth}{-1}
%    \end{macrocode}
% \end{macro}
%
% \begin{macro}{\pmn@l@fixme}
%    \mcmd{\pmn@l@fixme}\marg{fixme note}\marg{page} is a replacement
%    for \cmd{\l@fixme} and therefore a standard contents line
%    formatting macro.  
%
%    It typesets the fixme note in box so the priority information, if
%    any, stored with \cmd{\pfx@priority} can be recovered.  If there
%    is information we use \cmd{\pfx@priority} to typeset the content;
%    otherwise we use \cmd{\pfx@nopriority}.
%    \begin{macrocode}
\newcommand{\pmn@l@fixme}[2]{%
  \let\pfx@found@priority\relax
  \let\pfx@pri\pfx@pri@set
  \setbox\@tempboxa\vbox{#1}%
  \ifx\pfx@found@priority\relax \expandafter\@secondoftwo
  \else \expandafter\@firstoftwo\fi
  {\let\pfx@pri\@gobble
   \pfx@priority{\pfx@found@priority}{#1}{#2}}%
  {\pfx@nopriority{#1}{#2}}}
\newcommand{\pmn@l@fixme@parse}{}
\def\pmn@l@fixme@parse#1\pfx@hasprioritytrue#2 #3#4{%
  \pfx@priority{#2}{#3}{#4}}
%    \end{macrocode}
% \end{macro}^^A \pmn@l@fixme@parse
% \end{macro}^^A \pmn@l@fixme
%
% \begin{macro}{\pfx@test@in@range}
%   \mcmd{\pfx@test@in@range}\marg{priority}\marg{note}\marg{page} is
%   the usual macro to process fixme with priority information.  It
%   tests whether the priority is in the range that should be listed
%   and if so lists it using \cmd{\pfx@list@in@range}.
\newcommand{\pfx@test@in@range}[3]{%
%    \end{macrocode}
%  "if pmnfixdepth < 0
%    \begin{macrocode}
  \ifnum \c@pmnfixdepth<\z@ 
    \expandafter\@secondoftwo
  \else
    \expandafter\@iden 
  \fi
%    \end{macrocode}
%  "   or #1 <= pmnfixdepth then 
%    \begin{macrocode}
  {\ifnum \c@pmnfixdepth<#1\relax 
      \expandafter\@gobble
    \else 
      \expandafter\@iden
    \fi}%
%    \end{macrocode}
%  "   begin"
%    \begin{macrocode}
  {\pfx@list@in@range{#1}{#2}{#3}}}
%    \end{macrocode}
%
% \begin{macro}{\pfx@list@default@or@spec}
%   \mcmd{\pfx@list@default@or@spec}\marg{priority} dispatches either the
%   default formatting or an individual formatting macro for the given
%   priority.  It is the normal value of \cmd{\pfx@list@in@range}.
%    \begin{macrocode}
\newcommand{\pfx@list@default@or@spec}[1]{%
  \@ifundefined{pmnfixFormat\romannumeral#1}%
    {\pmnfixDefault{#1}}%
    {\csname pmnfixFormat\romannumeral#1\endcsname{#1}}}
%    \end{macrocode}
%  "   end"
% \end{macro}^^A \pmn@list@default@or@spec
%
% \begin{macro}{\pfx@list@in@range}%   
%    \cmd{\pfx@list@in@range} is the placeholder for the command to
%    proceed a priority fixme in the listable range.
%    \begin{macrocode}
\let\pfx@list@in@range\pfx@list@default@or@spec
%    \end{macrocode}
% \end{macro}
%
% \section{Indented entry}
% 
% This part handles presenting entry indented according to its
% priority.
%
% \begin{macro}{\pmnfixIndentation}
%    \mcmd{\pmnfixIndentation} defines the indentation for each level
%    of priority.
%    \begin{macrocode}
\newlength{\pmnfixIndentation}
\setlength{\pmnfixIndentation}{2em}
%    \end{macrocode}
% \end{macro}
%
% \begin{macro}{\pmnfixDefault}
%   \mcmd{\pmnfixDefault}\marg{priority}\marg{note}\marg{pageno} is
%   the default formatting of an entry.  The entry is indented
%   proportionally to the priority.  We change the margins so the text
%   can span several lines and finally dots out to the page number.
%    \begin{macrocode}
\newcommand{\pmnfixDefault}[3]{%
  \medskip
%  \vskip \z@ \@plus.2\p@
%    \end{macrocode}
%  Reduce left margin according to priority and right margin according
%  to table of contents settings.
%    \begin{macrocode}
  {\@tempdima -\pmnfixIndentation
  \advance\@tempdima #1\pmnfixIndentation
  \leftskip \@tempdima\relax \rightskip \@tocrmarg 
  \parindent\z@
  \parfillskip -\rightskip
%    \end{macrocode}
%  Then set the text followed by a numbered line.
%    \begin{macrocode}
  \leavevmode
  #2\nobreak
  \leaders\hbox{$\m@th
     \mkern \@dotsep mu\hbox{.}\mkern \@dotsep
     mu$}\hfill
  \nobreak
  \hb@xt@\@pnumwidth{\hfil\normalfont \normalcolor #3}%
  \par}}
%    \end{macrocode}
%   This is very much adapted from \cmd{\dottedtocline}.
% \end{macro}
%
% \section{List of fixmes by priority}
%
% We define the command to \cmd{\pmnlistoffixmes} to list all the
% fixmes in descending priority.  It runs over the list of fixmes
% repeated until all fixmes have been processed.
% 
% \begin{macro}{\pmnlistoffixmes}
%   \mcmd{\pmnlistoffixmes} lists all the fixmes in descending
%   priority.  It is implemented by running over the list over fixmes
%   repeatedly. 
%    \begin{macrocode}
\newcounter{pfx@next@priority}
\newcounter{pfx@current@priority}
\newif\ifpfx@normalfixmes
\newcommand{\pmnlistoffixmes}{%
  \section*{\listfixmename}
  {%
%    \end{macrocode}
%  First set up so we ignore fixmes with no priority and only process
%  fixmes with an actual priority.
%    \begin{macrocode}
  \let\pfx@nopriority\pfx@gobble@nopriority@flag
  \let\pfx@priority\pfx@test@in@range
  \let\pfx@list@in@range\pmn@list@current@priority
  \setlength{\pmnfixIndentation}{0pt}
%    \end{macrocode}
%  Then start the looping where we read through the table of fixmes
%  stored in a file (we use \cmd{\fileswfalse} to off having the file
%  overwritten).  Each time we read over the file "pfx@next@priority"
%  is updated to contain the smallest priority greater than
%  "pfx@current@priority" (or $-1$).
%    \begin{macrocode}
  \@fileswfalse
  \let\contentsline\pfx@ctl
  \global\pfx@normalfixmesfalse        
  \setcounter{pfx@current@priority}{-1}
  \loop
    \setcounter{pfx@next@priority}{-1}
    \pfx@reset@sums
    \@starttoc{lox}
    {\bfseries \pfx@print@sums}
  \ifnum \c@pfx@next@priority>\c@pfx@current@priority
    \subsection*{\listfixmename\ \arabic{pfx@next@priority}}
    \setcounter{pfx@current@priority}{\c@pfx@next@priority}
  \repeat
%    \end{macrocode}
%  We then output any fixmes without priority 
%    \begin{macrocode}
  \ifpfx@normalfixmes
    \let\pfx@nopriority\pfx@list@standard
    \let\pfx@list@in@range\pfx@gobble@priority
    \subsection*{\listfixmename}
    \@starttoc{lox}
  \fi
  }%             
%    \end{macrocode}
%  And finally we make a single scan to get the file started.
%    \begin{macrocode}
  \let\pfx@nopriority\pfx@gobble@nopriority
  \let\pfx@priority\pfx@gobble@priority
  \@starttoc{lox}}
%    \end{macrocode}
% \end{macro}^^A \pmnlistoffixmes
%
% \begin{macro}{\pfx@gobble@priority}
% \begin{macro}{\pfx@gobble@nopriority}
% \begin{macro}{\pfx@gobble@nopriority@flag}
%   \cmd{\pmn@list@gobble} ignores  a priority entry
%    \begin{macrocode}
\def\pfx@gobble@nopriority@flag{%
  \global\pfx@normalfixmestrue\pfx@gobble@nopriority}
\let\pfx@gobble@nopriority\@gobbletwo
\newcommand{\pfx@gobble@priority}[3]{}
%    \end{macrocode}
% \end{macro}^^A \pfx@gobble@nopriority@flag
% \end{macro}^^A \pfx@gobble@nopriority
% \end{macro}^^A \pfx@gobble@priority
%
% \begin{macro}{\pmn@list@current@priority}
%   \mcmd{\pmn@list@current@priority}\marg{priority}\marg{note}\marg{page} 
%    lists a priority entry if it has the priority specified by
%    "pfx@current@priority". It also updates the "pfx@nextpriority"
%    counter so it contains the lowest priority we have encountered.
%    \begin{macrocode}
\newcommand{\pmn@list@current@priority}[3]{%
  \ifnum #1=\thepfx@current@priority
    \let\pfx@time\pfx@time@sum
    \pfx@list@default@or@spec{#1}{#2}{#3}%
    \global\let\pfx@time\relax
  \fi
  \ifnum #1>\c@pfx@current@priority
    \ifnum #1<\c@pfx@next@priority 
      \setcounter{pfx@next@priority}{#1}
    \fi
    \ifnum \thepfx@next@priority<0
      \setcounter{pfx@next@priority}{#1}
    \fi
  \fi}
%    \end{macrocode}
% \end{macro}
%
% \section{Removing \package{fixme} information from
% \cmd{\contentsline}}
%
% \package{fixme} inserts some extra information in front of the user
% supplied text when adding it to the list of fixmes.  When present
% the list in priority we do not want that.  This is handled by the
% following macros.
% \begin{macro}{\pfx@ctl}
%   \mcmd{\pfx@ctl}\marg{type}\marg{text} is a replacement for
%   \cmd{\contentsline} which look whether it is a contentsline for
%   \package{fixme} and remove any extra text added by
%   \package{fixme}.  We cannot simple change \cmd{\l@fixme} since
%   package{hyperref} for instance changes \contentsline.  
%    \begin{macrocode}
\newcommand{\pfx@ctl}[2]{%
  \def\reserved@a{#1}%
  \ifx\reserved@a\pfx@fixmetext\expandafter\@firstoftwo
  \else\expandafter\@secondoftwo \fi
  {\pfx@ctl@parse{#1}#2\pfx@pri\pfx@pri}%
  {\pfx@svd@ctl{#1}{#2}}}
%    \end{macrocode}
% \end{macro}^^A \pfx@ctl
% \begin{macro}{\pfx@ctl@parse}
% If it is a \package{fixme} line, we use \cmd{\pfx@ctl@parse} to
% scan for \cmd{\pfx@pri} in the fixme note.
%    \begin{macrocode}
\def\pfx@ctl@parse#1#2\pfx@pri#3\pfx@pri{%
   \def\reserved@a{#3}%
   \ifx\reserved@a\@empty\expandafter\@firstoftwo
  \else\expandafter\@secondoftwo \fi
  {\pfx@svd@ctl{#1}{#2}}%
  {\pfx@savedctl@gobble{#1}{\pfx@pri#3}}}
%    \end{macrocode}
% \end{macro}^^A \pfx@ctl@parse
% \begin{macro}{\pfx@ctl@parse}
%  If we find \cmd{\pfx@pri} in the note, we have the end
%  delimiting \cmd{\pfx@pri} to be removed.  This is accomplished
%  by \cmd{\pfx@savedctl@gobble} which then continues with the
%  original \cmd{\contentsline} command stored in \cmd{\pfx@svd@ctl}.
%    \begin{macrocode}
\newcommand{\pfx@savedctl@gobble}[3]{\pfx@svd@ctl{#1}{#2}}
%    \end{macrocode}
% \end{macro}^^A \pfx@ctl@parse
%    \begin{macrocode}
\AtBeginDocument{\let\pfx@svd@ctl\contentsline}
\def\pfx@fixmetext{fixme}
%    \end{macrocode}
% We use \cmd{\def} to define \cmd{\pfx@fixmetext} to get the correcet
% setting of \cmd{\global} and \cmd{\outer} when we use comparison
% with \cmd{\ifx}.      
% \StopEventually{}
% 
% And the commands to typeset the documentation.  All enclosed in
% "<*documentation>"$\ldots$"</documentation>" so we exclude it if we
% ever make a docstrip file.  For now, we simply stop input with
% \cmd{\endinput} so the file can be used directly as a package file.
%    \begin{macrocode}
%<*documentation>
\endinput
\makeatother
\def\UseOption{}
\documentclass{pmn-ldoc} 
\newcommand{\docdate}{2003/11/02}
\usepackage[latin1]{inputenc}
 % \OnlyDescription
 % \DisableCrossrefs
\begin{document}
  \DocInput{pmn-fxme.sty}
\end{document}
%</documentation>
%    \end{macrocode}
% \Finale \sloppy \PrintChanges
% ^^A LocalWords:  fixme
