[comp.text.tex] RFC:

rchen@m.cs.uiuc.edu (06/14/90)

I just finished writing a LaTeX manpage style file for
documenting a C++ library I wrote in the past year.  It is
by no means complete, rather, I hope it is a good start for
something useful.  I'll post manpage.sty and example.tex
as responses.  I'd appreciate it if you can improve it or
make comments on it.  There must be ton of mistakes as I
am so new to LaTeX (TeX) macro writing.

Enjoy.

-Rong Chen

rchen@m.cs.uiuc.edu (06/14/90)

% MANPAGE DOCUMENT STYLE -- Created 25 May 1990
% manpage.sty

% Rong Chen (rchen@cs.uiuc.edu)
% Department of Computer Science
% University of Illinois at Urbana-Champaign
% Urbana, IL 61801

% Copyright (c) 1990 by Rong Chen 
% Permission to copy all or part of this work is granted, provided
% that the copies are not made or distributed for resale, and that
% the copyright notice and this notice are retained.
% 
% THIS WORK IS PROVIDED ON AN "AS IS" BASIS.  THE AUTHOR PROVIDES NO
% WARRANTY WHATSOEVER, EITHER EXPRESS OR IMPLIED, REGARDING THE WORK,
% INCLUDING WARRANTIES WITH RESPECT TO ITS MERCHANTABILITY OR FITNESS
% FOR ANY PARTICULAR PURPOSE.

% This style option is designed to work with the report document style
% of LaTeX version 2.09.  Use \documentstyle[11pt,manpage]{report}
% 
% The commands that are created in the style file are:
%
% \begin{manpage}{Title}{Module}{Version} % see an example, all will be clear
% \end{manpage}                           % end of manpage environment
% \function#1  (e.g., \function{void demo(int dummy)})  % with \medskip added
% \function*#1 (e.g., \function*{void demo(int dummy)}) % no extra spacing
% \subtitle#1  (e.g., \subtitle{ANTHOR})  % fit into the same line if possible
% \subtitle*#1 (e.g., \subtitle{AUTHOR})  % always break a newline
% "#1"         (e.g., "dummy_variable")   % argument is in italic&unbreakable
% \separator   % draw a line of linewith long to seperate suntitle from text
%
% The following characters (control-sequents) are defined (or redefined):
%
% \* --- the same as $\ast$
% \< --- the same as $\langle$
% \> --- the same as $\rangle$
% <  --- the same as $<$
% >  --- the same as $>$
% _  --- the same as \_
% +  --- the same as $+$
% |  --- the same as $\mid$
% ^  --- hat character that is defined as $\wedge$ being raised 0.6ex

% If you make any improvements, I'd like to hear about them.

\headheight 24pt          % See LaTeX book for definitions
\headsep 12pt
\textwidth 6.25in
\textheight 8.0in
\topmargin 0in
\marginparwidth 0pt
\oddsidemargin 0pt
\evensidemargin 0pt
\marginparsep 0pt
\parindent 0pt

\newdimen\argindent \argindent 3em  % indentation for function arguments

\newdimen\arg@dim         % temp variables that you don't want to know
\newdimen\line@siz
\newbox\arg@box

\catcode`\"=\active
\def\arg@quote#1"{\hbox{\it #1\/}} \def\tt@quote{{\tt \char`\"}}
\let"=\tt@quote

\def\separator{\rule{\linewidth}{0.5pt}}

\def\function{\@ifstar{\@func@star}{\@func@norm}}
\def\@func@star#1{\expandafter\@function#1 \\ }
\def\@func@norm#1{\expandafter\@function#1 \medskip\\ }

\def\@function#1(#2)#3 {
  \begingroup
  \setbox\arg@box=\hbox{\bf #1 \rm $($} \global\arg@dim\wd\arg@box
  \setbox\arg@box=\hbox{\rm $)$;}
  \global\line@siz\linewidth\global\advance\line@siz-\wd\arg@box
  \pagebreak[3]
  \expandafter\print@name#1 \@@{\rm $($}\def\@comma{}\ignorespaces
  \@for\@tempa:=#2\do{\ignorespaces
    \setbox\arg@box=\hbox{\@comma} \global\advance\arg@dim\wd\arg@box
    \unskip\@comma\def\@comma{\nobreak,\penalty-\@m\ }\ignorespaces
    \expandafter\print@arg\@tempa\@@\ignorespaces
  }~{\rm $)$\nobreak#3}
  \endgroup
}

\def\print@arg#1#2 #3\@@{
  \setbox\arg@box=\hbox{#1#2\expandafter\print@dummy#3=\@@}
  \global\advance\arg@dim\wd\arg@box
  \ifdim\arg@dim>\line@siz
    \global\arg@dim\argindent \global\advance\arg@dim\wd\arg@box
    \hfill\penalty-\@m\hbox{}\kern\argindent\fi
  \box\arg@box%
}

\def\print@name#1#2 #3\@@{
  \unskip\edef\tmp@name{#3}\ignorespaces
  \ifx\tmp@name\@empty{\bf #1#2 }\else{\rm #1#2 \bf #3}\fi
}

\def\print@dummy#1=#2\@@{
  {\it #1\/}\ifx #2\@nil\else{\rm $=$}\expandafter\strip@eq#2\fi
}

\def\strip@eq#1={{\rm #1}}

\def\subtitle{\@ifstar{\@subtit@star}{\@subtit@norm}}

\def\@subtit@star#1{
  \item[\hbox{\large\bf\begin{tabular}[t]{l}#1\end{tabular}}\hfill]
  \hfil\par
  \expandafter{\let\par=\space\ignorespaces\let\par=\endgraf}
}

\def\@subtit@norm#1{
  \setbox\arg@box=\hbox{\large\bf\begin{tabular}[t]{l}#1\end{tabular}}
  \ifdim \wd\arg@box > \labelwidth \item[\copy\arg@box\hfill]\hfil\par
  \else \dp\arg@box=0pt \item[\copy\arg@box\hfill] \fi
  \expandafter{\let\par=\space\ignorespaces\let\par=\endgraf}
}

\newenvironment{manpage}[3]{\@beginManpage#1\@@#2\@@#3\@@}{\@endManpage}

\def\@beginManpage#1\@@#2\@@#3\@@{
  \clearpage
  \gdef\@header{{#2}{#1}{#2}}
  \gdef\@footer{{#3}{\thepage}{\today}}
  \begin{list}{}{
    \setlength\labelwidth{1.2in}
    \setlength\leftmargin{\labelwidth}
    \addtolength\leftmargin{\labelsep}
    \topsep  5pt plus 2pt minus 2pt
    \itemsep 5pt plus 2pt minus 2pt
    \parsep 10pt plus 2pt minus 2pt
  }
  \raggedbottom
  \let"=\arg@quote
}

\def\@endManpage{
  \end{list} \clearpage \flushbottom
}

\def\@first#1#2#3{#1}
\def\@second#1#2#3{#2}
\def\@third#1#2#3{#3}

\def\ps@headings{
  \def\@oddhead{\parbox{\textwidth}{
    {\rm\ \ \expandafter\@first\@header\hfill
      \expandafter\@second\@header\hfill
      \expandafter\@third\@header\ \ } \\[.1cm]
    \hbox{}\rule[12pt]{\textwidth}{1pt}
  }}
  \def\@evenhead{\parbox{\textwidth}{
    {\rm\ \ \expandafter\@third\@header\hfill
      \expandafter\@second\@header\hfill
      \expandafter\@first\@header\ \ } \\[.1cm]
    \hbox{}\rule[12pt]{\textwidth}{1pt}
  }}
  \def\@oddfoot{\parbox{\textwidth}{
    \hbox{}\rule{\textwidth}{1pt} \\[.1cm]
    {\sl\ \ \expandafter\@first\@footer\hfill
      \rm\expandafter\@second\@footer\hfill
      \sl\expandafter\@third\@footer\ }
  }}
  \def\@evenfoot{\parbox{\textwidth}{
    \hbox{}\rule{\textwidth}{1pt} \\[.1cm]
    {\sl\ \ \expandafter\@third\@footer\hfill
      \rm\expandafter\@second\@footer\hfill
      \sl\expandafter\@first\@footer\ }
  }}
}

\pagestyle{headings}

\catcode`\<=\active \def\mit@less{$\char`\<$} \let<=\mit@less
\catcode`\>=\active \def\mit@more{$\char`\>$} \let>=\mit@more
\def\<{$\langle$} \def\>{$\rangle$} \def\*{$\ast$}

%\catcode`\_=\active \def_{\kern.06em \vbox{\hrule width.3em}}
\catcode`\_=\active \global\let_=\_
\catcode`\^=\active \def^{\raise.06ex \hbox{\small $\wedge$}}
\catcode`\+=\active \def+{$\char`\+$}
\catcode`\|=\active \def|{$\mid$}

rchen@m.cs.uiuc.edu (06/14/90)

\documentstyle[11pt,manpage]{report}
\begin{document}

\begin{manpage}{OIM Library}{Box}{Draft}

\subtitle{Name}
    Box --- a rectangle area with color, frame and text

\subtitle{Declaration}
    \#include \<box.h\>

\function{Box(Point origin, Point corner,
	    int foreground_color = WHITE,
	    int background_color = BLACK,
	    int fill_pattern     = EMPTY_FILL,
	    int frame_style      = IN_BORDER,
	    Boolean show_status  = HIDE)}
    Construct a box with lower left vertex at "origin" and upper
    right vertex at "corner".  A box will not be shown when created
    by default.  You may change the defaults in box.h.

\function{Box(int left, int bottom, int right, int top,
	    int foreground_color = WHITE,
	    int background_color = BLACK,
	    int fill_pattern     = EMPTY_FILL,
	    int frame_style      = ON_BORDER,
	    Boolean show_status  = SHOW)}
    Construct a box with "left", "bottom", "right" and "top" as
    its boundaries.  Box will be shown when created by default.

\function{Box()}
    Used to construct an array of boxes.  It is forbidden to have
    arguments in the constructors of array objects in C++.  The
    attributes should be explicitly assigned later. See resize().

\subtitle{Description}

    A Box object is a rectangular area painted with a background color,
    foreground color, fill pattern, border and text.  A box may have a
    title bar (can only be on the top) and a shadow attached to it as well.
    Usually, boxes are shown on the screen as soon as they are created,
    but that can be overridden by using different constructors.  Text is,
    by default, centered in the middle of the boxe, which may also be
    overridden later.  A 2-D table is considered as 2-D array of boxes.
    There is only one title bar style, that can be changed if needed.

\subtitle{Public \\ Operations}

\function*{void resize(Point origin, Point corner)}
\function{void resize(int left, int bottom, int right, int top)}
    Redefine the boundaries of the box.  They are useful for an array
    of boxes.  The arguments are the same as the ones in constructors.

\function{int width()}
    Return the width of the box in pixels.

\function{int height()}
    Return the height of the box in pixels.

\function{void title(char\* label)}
    Display a title, given by label, for the box.  There is only one style.
    After displaying a title bar, the reference porint (see textAlign())
    will be moved to the inside of upper-left corner, assuming you are
    going to print pages (a full box is a page) of texts.

\function{void titleBarColor(int color)}
    Set the title bar color.

\function{void titleTextColor(int color)}
    Set the title label text color.

\subtitle{Inherited \\ Operations}

\function*{int textColor()}
\function{void textColor(int color)}
    Query and set text color.

\function*{int textHighLightColor()}
\function{void textHighLightColor(int color)}
    Query and set highlighted text color.  A substring that is quoted with
    a couple of @ characters will be highlighted.  For example, a string
    with @highlighted text@ is shown here.  By default, the highlighted
    text color is set to the highlight color of the current text color,
    i.e., (textColor() ^ HIGH_LIGHT).

\function{void textAlign(Point p, Align alignment)}
    Texts are usually printed in the middle of the box (default), but
    that may be overriden using this call.  You may choose to adjust your
    text relative to the point "p" with following alignment possibilities:
    ALIGN_NONE, ALIGN_CENTER, ALIGN_LEFT, ALIGN_RIGHT.  ALIGN_NONE has
    the same effect as ALIGH_LEFT, if there is only one line of text
    in the following printText() or << operations.  In other words,
    ALIGN_NONE only affect text temperately (one line), whereas, the
    others will affect all lines of text in the same call and all the
    following << operations until next textAlign() is called.
    Finally, the point "p" is relative to the origin of the box.

\function*{int textLinePitch()}
\function{void textLinePitch(int pixels)}
    Query and set the spacing between the lines of text.

\function{char\* text()}
    Return a pointer to the current text in the box.

\function{int textWidth()}
    Return the string width in pixels for the longest line of the text.

\function{void printText()}
    Reprint text from the text buffer.  The buffer was filled by <<
    operation only.  ``Send a message to an object and let the object
    decide what to do.'' It is the key idea of object-oriented programming.
    Like it or not, I am just trying to make a point here, so do not
    use printText() unless it is necessary.

\function{int displayPlane()}
    Return the display plane number (1 or 2) on which the box was created.

\function*{Boolean showStatus()}
\function{void showStatus(Boolean hide_or_show)}
    Query and set the display status.  Two predefined constants are HIDE
    and SHOW, try to use them, although TRUE and FALSE are also valid.

\subtitle{Virtual \\ Operations}

\function{Point origin()}
    Return the origin, lower left vertex, of the box.

\function{Point corner()}
    Return the corner, upper right vertex, of the box.

\function{void draw()}
    Make the box show if it was hidding previously.  This function
    may also be used to redraw a box including title bar and shdow.

\function{void clear()}
    Clear the area inside the box frame.  Usually, it is used for
    clearing text without flashing the border frame and title bar.

\function{void fill()}
    Fill the box with foreground, background colors and pattern.
    Do nothing if the show status is HIDE.  The colors and fill
    patterns have to be set before this call.  See foreColor(),
    backColor(), and fillPattern() operations below.

\function{void frame()}
    Plot the border frame of the box, according to default frame style.
    Do nothing if the show status is HIDE.  The default frame style is
    EMPTY_FILL (fill with background color) or the value that is set by
    frameStyle() operation if the latter has been called at least once.

\function{void shadow(int to_right = 5, int to_bottom = 4,
	    int color = BLACK)}
    Add a shadow to the box.  The next time you use draw() operation,
    the shadow will be redrawn as well.  The first two arguments tell
    how much you want the shadow shift to the bottom-right of the box.
    The "color" is for the color of the shadow.

\function{Boolean contains(Point p)}
    Return TRUE if point "p" is inside the box, otherwise return FALSE.
    Note that if the current display plane is different from the one
    in which the box was created, this routine will always return FALSE.

\function{void highLight()}
    Draw the box with highlight colors.  This operation will not change
    the existing foreground, background and text colors.  It only uses
    them to find out what are the highlight colors.

\function{void reverse()}
    Swap the foreground and background colors.  If the text color is
    the same as foreground color, change it to background color as well.

\function{Point center()}
    Return the center point of the box.

\function{void moveTo(Point p)}
    Move the box to a new location with center at point "p".
    The old box will not be erased and the new box will not be drawn.
    You have to do it yourself if that is what you want.

\function*{int foreColor()}
\function{void foreColor(int color)}
    Query and set foreground color.  There are total of 16 colors
    for EGA screen and they are listed in grafix.h.

\function*{int backColor()}
\function{void backColor(int color)}
    Query and set background color.

\function*{int fillPattern()}
\function{void fillPattern(int pattern)}
    Query and set fill pattern.  Five predefined patterns are
    SOLID_FILL, DENSE_DOTTED, MEDIUM_DOTTED, SPARSE_DOTTED, and
    EMPTY_FILL.  They are also listed in grafix.h.

\function*{int frameStyle()}
\function{void frameStyle(int border_type)}
    Query and set frame style for the box border.  A frame style
    value consists of two bytes (an integer on IBM-PC).  The first
    byte (the least significant byte) is for line types, possible
    choices are SOLID_LINE, LONG_DASH_LINE, MEDIUM_DOTTED_LINE,
    DASH_DOTTED_LINE, MEDIUM_DASHED_LINE, DASH_W_2_DOTS_LINE,
    SHORT_DASH_LINE, DENSE_DOTTED_LINE, and SPARSE_DOTTED_LINE.
    The secode byte is border styles, and the possible values are
    NO_BORDER (no border, no matter what the line style would be.),
    ON_BORDER (frame on the border --- it's the default), and IN_BORDER
    (frame inside the box border by 3 pixels --- more or less).
    So a frame style can be set by a bit-by-bit OR function ( | ) or add
    function (+).  For example, aBox.frameStyle(SOLID_LINE | IN_BORDER).

\function*{void operator<<(const char\* string)}
\function*{void operator<<(long integer)}
\function*{void operator<<(int integer)}
\function*{void operator<<(double real_number)}
\function{void operator<<(float real_number)}
    Print a string, an integer or a real number in the box.
    The text will be saved in an internal buffer, in case you want to
    redraw the box later.  If the current show status is SHOW, the
    text will be printed using printText().  << stands for sending
    a message to the box object, which is similar to sending something
    to the standard output (cout << something;) in C++ library.
    Avoid calling these operations as aBox.operator<<(something),
    although it should work.  Operators are intented to be used as
    operators, just like you use +, $-$ in grammer schools.

\subtitle{Bugs}
    No clipping is done for box, so if the text is too long or the reference
    point is out of bound, you may expect looking for your text all over the
    screen.  Fill patterns are slow because we use only C functions for our
    implementation.  The function moveTo() will not erase old box and will
    show the new box either.

\subtitle{See Also}
     Rectangle, Point, Pen, Figure, Shape

\subtitle{Author}
     Ron Chen at the Office for Information Management, UIUC. 9-1-89.

\end{manpage}

\newpage

\begin{verbatim}

    #include <stdio.h>
    #include <stdlib.h>
    #include "box.h"

    main()
    {
        Box background(0, 0, MAX_X, MAX_Y, GRAY, GRAY);

        Box a(100, 100, 400, 220, YELLOW, RED);
        a << "The strings are centered!\n"
             "This is the @second@ line\n"
             "and the @third@.";
        getch();

        a.shadow(6, 5, GREEN); getch();
        a.reverse(); getch();
        a.fill(); getch();
        a.frame(); getch();

        a.textAlign(Point(10, 100), ALIGN_LEFT);
        a.textHighLightColor(MAGENTA);
        a << "This string is left justified!\n"
             "The @second@ line will follow suit.\n"
             "So does the @third@";
        getch();

        Box b(300, 200, 500, 300, WHITE, BLUE, EMPTY_FILL, NO_BORDER);
        b.title("@DO IT AGAIN@");
        b << "Hello, World.";
        getch();

        b.shadow(); getch();
        b.clear(); getch();
        b.highLight(); getch();
        exit(0);
    }
\end{verbatim}

\end{document}