/*
 * Copyright (c) 2007-2010 Kai Braaten
 *
 * Permission is hereby granted, free of charge, to any person
 * obtaining a copy of this software and associated documentation
 * files (the "Software"), to deal in the Software without
 * restriction, including without limitation the rights to use,
 * copy, modify, merge, publish, distribute, sublicense, and/or sell
 * copies of the Software, and to permit persons to whom the
 * Software is furnished to do so, subject to the following
 * conditions:
 *
 * The above copyright notice and this permission notice shall be
 * included in all copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
 * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
 * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
 * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
 * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
 * OTHER DEALINGS IN THE SOFTWARE.
 */

TableGenerator 1.3
====================
This file provides all the documentation available for the TableGenerator
library. TableGenerator is a piece of code written in C++ that helps you create
nicely formatted ASCII tables. It was originally written for use in a MUD
(Multi-User Dungeon), but its applicability is not limited to that in any
way. This release contains four different table types, all described below in
detail. All the table types allows some customization from you. Some more than
others. Number of fields and column widths are all adjusted automatically to
ensure you get a properly formatted table.

Installing
============
Since you're reading this, I assume you have already unpacked the archive.
First of all you have to decide where you want to install the library. You
can install it in a global location (will normally require administrative
privileges), you can install it in your home directory, or you can simply
install it in the same directory as the project you want to use it with.

Now open the Makefile in an editor. The first few lines will configure the
Makefile to compile for either Cygwin or Mac OS X. This is needed because
these platforms handle dynamic libraries differently from Linux (and because
I'm too lazy to write a proper configure script). Just uncomment the "CYGWIN"
or "MACOSX" variable as appropriate.

Next we have this:

PREFIX =

This is where you will supply the install destination path. Example:

PREFIX = /usr/local

With this path the library file will be installed in /usr/local/lib, and the
header files will be installed in /usr/local/include. Note that if you want to
install the files manually you don't need to worry about this.

Type 'make' to build the library. If you want to install it to the directory
you specified in the PREFIX variable you can now type 'make install'.

First spin
============
Whether you actually installed the library or not, it's now time for a test
drive. Type 'make test'. This will build the test file which prints some
tables for your enjoyment. You run it with ./test .

Using TableGenerator in other software
========================================
There are just two things you need to do. 1) Include the header files and 2)
link in the library. The latter is done by supplying -ltablegenerator to the
linker. If the compiler fails to locate the headers, or the linker fails to
locate the library, then compilation will fail. The only way this can happen
is that you have installed the files at a location that the compiler or linker
don't know about. If the linker can't find the library, you can give it
the location manually: -L/path/to/library
Similarly you can give the header file location to the compiler:
-I/path/to/headerfiles
Even after a successful build the application may fail at runtime. Again, this
can happen if you install in a non-standard location. This is normal behaviour
when using shared libraries (as opposed to statically linked libraries).
One solution to this is to give the information as a link option:
-Wl,-rpath,/path/to/library

This may sound like a lot of fuss, but this is quite normal if you don't
install things at global places the compiler knows about.

If at this point you're tired of shared libraries, you can comment out:
LINK_SHARED_LIBRARY = 1
in the Makefile, in which case it will be a static link library instead.

Programming with the TableGenerator API
=========================================
Now that we've covered the dirty business above we can focus on actually using
the library to generate tables. It's probably a good idea to take a look at
the test.cpp file before reading on. Also you may want to take a look at the
rather limited project page:
http://kaicpp.totj.net/index.php/Projects/TableGenerator

You really should check out both these things, because the rest of this
document is a reference section, and there will be a distinct lack of examples.

Overview
==========
There are three main concepts, or entities, in the API. First of all there
is the TableGenerator, which is the central actor. The TableGenerator can
be configured with a TableStrategy, which is basically an implementation of
a specific table type. There are four different TableStrategyS in this release.
Finally there is the TableRow that plays an important part when you initially
feed the data to the TableGenerator.

A standard work cycle is as such:

1) Create a strategy object, and configure it by giving constructor arguments.
2) Create a TableGenerator, and feed the strategy to its constructor.
3) Create a TableRow, and insert data into it.
4) Feed the TableRow into the TableGenerator.
5) Repeat 3-4 as many times as needed.
6) Render the table by either feeding the table into some object derived from
   std::ostream, or by calling the str() member function. You can also create
   your own insertion operators to feed the table into existing classes you
   may have, but that is beyond the scope of this document.
7) Optional: Create a different strategy object and pass it to the
   TableGenerator::changeStrategy() function, if you want to render a different
   kind of table with the same data. The test.cpp program contains examples
   of this.

Reference section
==================
Since the test.cpp file and the project page covers the usage, I will only
document the TableStrategy constructions here. Some of them have many
options. There are also comments in the tablestrategy.hpp file for the
constructor arguments.

SimpleTable
============
This just creates a plain table with no frills like frames or drop shadows.

SimpleTable( int fieldspace = 1,
             int columns = 1,
             int columnspace = 1,
             const string &newline = "\r\n" )

-fieldspace: 
This is the number of spaces between each field, or column if you will.

-columns: 
This argument requires some explanation, because it's probably not exactly
what you think. It's NOT about how many columns there are per row, because
that is deduced automatically from the number of variables you give to the
TableRow. Instead this is the number of rows stacked horizontally!

Example of columns = 1:
Each row has two fields; name and age.

Jim    34
Bill   20
Oscar  45
Clara  29
Jenny 100

Same table with columns = 2

Jim    34   Bill   20
Oscar  45   Oscar  45
Jenny 100

I hope that clarifies things.

-columnspace:
The number of blank characters between each horizontal row (as opposed to the
fieldspace in the first argument).

-newline:
A string that is appended at the end of each line in the table.

As a final note you can see from the header file that each of these arguments
have default values. This means that you can ommit them. So:

SimpleTable st;

is the same as

SimpleTable st( 1, 1, 1 );

FramedTable
=============
This is a table that has a ASCII graphics drawn as a frame. It has mostly
the same options as SimpleTable, with the addition that you can provide colours
for the frame, the headers and the values, and you can change the ASCII
characters used for the frame. This table is different from the rest in that
it uses the first row in the table as column headings.

FramedTable( int columns = 1, // Number of TABLES stacked horizontally
             int space = 0, // Add extra padding between frame and values
             const std::string &vcol = "",  // Field data colour token
             const std::string &fcol = "",  // Frame colour token
             const std::string &hcol = "",  // Header colour token
             const std::string &fg = "+-|", // Frame graphics characters
             const std::string &newline = "\r\n" ); // Newline marker

As for the colour codes the FramedTable doesn't interpret then, it just inserts
them. Therefore you can use whatever colour scheme you want, like ANSI
colours sequences, or the colour codes in your MUD.

The last argument, frame graphics, takes a string of three characters. The
first one is used to draw junctions and corners, the second to draw horizontal
lines, and the last to draw vertical lines. If you supply an argument with more
than or fewer that three characters, it will revert to the default.

Space3Table
=============
Space3Table( const std::string &h = "",      // Header text
             const std::string &hcol = "",   // Header colour
             const std::string &vcol = "",   // Field data colour
             const std::string &newline = "\r\n" ); // Newline marker

This table has the fewest option of them all, because it was written for a
very specific purpose. The arguments should explain themselves.

ShadowTable
=============
This is a fancy-schmancy table with solid background, drop shadow, optional
headline, and various padding, indentation and fieldwidth options.

ShadowTable( const std::string &ht, // Header text
             const std::string &tc, // Text colour
             const std::string &fc, // Background fill colour
             const std::string &sc, // Shadow colour
             const std::string &st, // Stop colour
             size_t p = 0,          // Side padding
             size_t fp = 1,         // Field padding
             size_t ind = 0, ;      // Left border indentation
             const std::string &cc = "",   // Closing colour tag
             const std::string &nl = "\r\n" ); // newline character(s)

Note that in this strategy all the first five arguments are required, because
otherwise there wouldn't be enough information available to draw the table at
all.

-Header text
This is a center-justified text string that appears at the top of the table.
The header is optional in the sense that you can provide a blank string. And
I do mean blank quite literally: "" . If you instead provide a string of
spaces, like "  " then the header is still drawn, it'll just be invisible.
If you experiment with it you will see that this is probably not what you
want.

-Text colour
This colour will be used for all text, both header and values in the table.

-Background fill colour
This is the colour that will appear as the solid background. Keep in mind
that this software has no way of checking that the colour tokens you provide
are sensible, so make sure you provide actual background colour, unless you
like odd results.

-Shadow colour
This should also be an actual solid background colour. It's the drop shadow
that is drawn along the right and bottom border of the table.

-Stop colour
This is the colour that will be inserted at the end of lines to stop colour
bleeding, hence the name 'stop colour'. On a Smaug derived MUD the black
background colour ^x is a reasonable value. Resetting (with &D/&d) will
probably also work. Experiment.

-Side padding
This is the number of spaces between the table border edge and the values in
the table (horizontally!).

-Field padding
This is the number of spaces between each field (again horizontally).

-Left border indentation (AKA outer padding)
This is how many blank spaces there should be from the left side of the
screen before the table starts.

-Closing colour tag
This argument was added in version 1.3 to allow the use of colour tags from
a markup language that requires each tag to be closed properly (balanced).
This tag is therefore added N times at the end of the table, where N is the
number of colour tags inserted in the entire table. If you use a typical
Smaug-like colour system where there are only start tags, then you can just
leave this an empty string as default.

-Newline character(s)
A string that is appended at the end of each line in the table.

HtmlTable
===========
This strategy renders the data as a basic HTML table. The constructor's
arguments should be self explanatory.

HtmlTable( bool useHeader = true, // Make first row header
           unsigned long borderWidth = 0, // Width of table border
           // Title of HTML page
           const std::string &title = "TableGenerator 1.3" );


Final words
=============
Now you should have all the information you need to get pretty tables
in a quick and convenient manner. I hope you enjoy using this software as
much as I enjoyed writing it.

If you want to contact me for whatever reason, like bugs, suggestions for
new table layouts, or simply to give me a heads up (I'd appreciate that, you
know), send me a mail on kaibr@users.sourceforge.net

It's also possible to PM me on places like mudbytes.net where I go by the
alias Caius.