#include <stdio.h>
#include <string.h>
#include <math.h>
#include <ctype.h>

#define PALETTE_WRAP 0xE6

#define SQRT3 1.7320508075688772935274463415058723669428L

#define HEIGHT 126
#define WIDTH  320
#define NUM_IN_HEIGHT  6
#define NUM_IN_WIDTH  12

#define SIDE_LEN ( ( long double )( HEIGHT ) / ( NUM_IN_HEIGHT - 1 + ( long double )( NUM_IN_HEIGHT + 1 ) / 2 ) )
#define VERT_SIDE_LEN  ( SIDE_LEN / 2 )
#define HEX_WIDTH ( ( long double )( WIDTH ) / NUM_IN_WIDTH )
#define HORIZ_SIDE_LEN ( HEX_WIDTH / 2 )
//#define HORIZ_SIDE_LEN0 ( SIDE_LEN * SQRT3 / 2 )
//#define HEX_WIDTH0 ( HORIZ_SIDE_LEN * 2 )
#define HEX_HEIGHT ( VERT_SIDE_LEN * 2 + SIDE_LEN )
#define ROW_HEIGHT ( SIDE_LEN + VERT_SIDE_LEN )
#define FONT_HEIGHT ( HEX_HEIGHT * .75 )

#define FEQ( x1, x2 ) ( ( ( x1 ) - ( x2 ) ) < HEX_HEIGHT * .1 && ( ( x2 ) - ( x1 ) ) < HEX_HEIGHT * .1 )

typedef struct {
   int r;
   int g;
   int b;
} RGB;

#include "palette.c"

RGB white = { 255, 255, 255 };
RGB black = { 0, 0, 0 };

RGB boundary = { 0, 0, 0 };
RGB text = { 0, 0, 0 };
RGB blank = { 0, 0, 0 };

char* reformat[ 256 ] = { NULL };
char* relabel[ 256 ] = { NULL };
char font[ 256 ] = "Times New Roman";
char fontStyle[ 256 ] = "normal";
char fontWeight[ 256 ] = "normal";
int useColorTable;
int palmIndex;
int reverse;
int width;
int height;
int noFill;
int stroke;
int upCase;

#define MAX_LINE 60

typedef char Line [ MAX_LINE ];

Line labels[] = {   "[]b k d g . , ? ! 7 8 9 ",
                     "~ T c a n i m q B 4 5 6 { ",
                     "()f l e   s y x R 1 2 3 ",
                     "$ <>j h t o p v ' 0 +-*/} ",
                     "C M I S r u w z \" ;:&\\=%",
                     "Q G H J K L ` @ # ^ | _ Q " };

#define NUM_LABELS 6

Line colors[] = {  "sSA A A A P P P P N N N ",
                     "P X A A A A A A X N N N sP",
                     "sSA A A X A A A X N N N ",
                     "P sSA A A A A A P N sSsSsP",
                     "X X X X A A A A P sSsSsS",
                     "B X N N N N P P P P P P B " };


typedef struct {
    char c;
    RGB  color;
} ColorTable;

#define MAX_COLORS 256

ColorTable colorTable[ MAX_COLORS ] = {
    { 's', {180, 180, 180} },
    { 'S', {220, 220, 220} },
    { 'P', {200, 200, 200} },
    { 'X', { 35,  90, 174} },
    { 'Z', { 15,  53, 109} },
    { 'A', { 73, 136, 231} },
    { 'N', {158, 176, 203} },
    { 'W', {255,255, 255 } },
    { 'B', { 0, 0, 0 } },
    { 0, {255, 255, 255} }
};


RGB GetPalette( unsigned char c )
{
    if ( PALETTE_WRAP <= c ) {
        c = ( c - PALETTE_WRAP ) + 1;
    }

    return palmPalette[ c ];
}

RGB SearchColorTable( char c )
{
    int i;

    for ( i = 0 ; colorTable[ i ].c ; i++ )
         if ( colorTable[ i ].c == c )
             break;

    return colorTable[ i ].color;
}


RGB GetColor( char c )
{
    int i;
    int j;
    for ( i = 0 ; i < NUM_LABELS ; i++ ) {
        for ( j = 0 ; labels[ i ][ j ]; j++ ) {
             if ( labels[ i ][ j ] == c && ( c != ' ' || j % 2 == 0 ) ) {
                 return SearchColorTable( colors[ i ][ j ] );
             }
        }
    }
    return SearchColorTable( 0 );
}

typedef long double Point[2];

Point hexagon[6] =
   { { 0, VERT_SIDE_LEN },
     { HORIZ_SIDE_LEN, 0 },
     { HEX_WIDTH, VERT_SIDE_LEN },
     { HEX_WIDTH, VERT_SIDE_LEN + SIDE_LEN },
     { HORIZ_SIDE_LEN, 2 * VERT_SIDE_LEN + SIDE_LEN },
     { 0, VERT_SIDE_LEN + SIDE_LEN } };

Point topHalf[6] =
   { { 0, VERT_SIDE_LEN },
     { HORIZ_SIDE_LEN, 0 },
     { HEX_WIDTH, VERT_SIDE_LEN },
     { HEX_WIDTH, VERT_SIDE_LEN + SIDE_LEN / 2 },
     { 0, VERT_SIDE_LEN + SIDE_LEN / 2 } };

Point bottomHalf[6] =
   { { 0, VERT_SIDE_LEN + SIDE_LEN / 2 },
     { HEX_WIDTH, VERT_SIDE_LEN + SIDE_LEN / 2 },
     { HEX_WIDTH, VERT_SIDE_LEN + SIDE_LEN },
     { HORIZ_SIDE_LEN, 2 * VERT_SIDE_LEN + SIDE_LEN },
     { 0, VERT_SIDE_LEN + SIDE_LEN } };

Point leftHalf[5] =
   { { 0, VERT_SIDE_LEN },
     { HORIZ_SIDE_LEN, 0 },
     { ( HEX_WIDTH + HORIZ_SIDE_LEN ) / 2, VERT_SIDE_LEN / 2 },
     { HORIZ_SIDE_LEN / 2, 3 * VERT_SIDE_LEN / 2 + SIDE_LEN },
     { 0, VERT_SIDE_LEN + SIDE_LEN } };

Point rightHalf[5] =
   { { HORIZ_SIDE_LEN * 3 / 2, VERT_SIDE_LEN / 2 },
     { HEX_WIDTH, VERT_SIDE_LEN },
     { HEX_WIDTH, VERT_SIDE_LEN + SIDE_LEN },
     { HORIZ_SIDE_LEN, 2 * VERT_SIDE_LEN + SIDE_LEN },
     { HORIZ_SIDE_LEN / 2, VERT_SIDE_LEN * 3 / 2 + SIDE_LEN } };


void EmitPath( long double x, long double y, int reverse, Point* fig, int nsides, 
     long double* minx, long double* miny, long double* maxx, long double* maxy,
     int skipLeft, int skipRight )
{
    int   n;
    int   move;

    *minx = width;
    *maxx = 0;
    *miny = height;
    *maxy = 0;

    move = 1;

    for ( n = 0 ; n <= nsides ; n++ ) {
         long double curx;
         long double cury;
         int  i;
         
         i = n % nsides;

         if ( reverse ) {
             curx = y+fig[i][1];
             cury = x+fig[i][0];
         }
         else {
             cury = y+fig[i][1];
             curx = x+fig[i][0];
         }

         printf( "%c %.16Lf,%.16Lf ", move ? 'M' : 'L',
                 curx, cury );

         move = 0;

         if ( FEQ( fig[ i ][ 0 ], fig[ ( i + 1 ) % nsides ][ 0 ] ) ) {
             if ( skipLeft && FEQ( fig[ i ][ 0 ], 0 ) ) {
                 move = 1;
             }
             else if ( skipRight && FEQ( fig[ i ][ 0 ], HEX_WIDTH ) ) {
                 move = 1;
             }
         }

         if ( curx < *minx )
             *minx = curx;
         if ( *maxx < curx )
             *maxx = curx;
         if ( cury < *miny )
             *miny =  cury;
         if ( *maxy < cury )
             *maxy = cury;
    }

    if ( *minx < 0 )
        *minx = 0;
    if ( *miny < 0 )
        *miny = 0;
    if ( width-1 < *maxx )
        *maxx = width-1;
    if ( height-1 < *maxy )
        *maxy = height-1;

    printf( "\"/>\n" ); //z
}


void DrawCell( long double x, long double y, Point* fig, int nsides,
     RGB color, char c, int skipLeft, int skipRight )
{
    int i;
    long double cx;
    long double cy;
    long double minx;
    long double maxx;
    long double miny;
    long double maxy;
    long double fsize;

    if ( ! noFill ) {
        printf( "<path style=\"fill-opacity:1.0; fill:rgb(%d,%d,%d); shape-rendering:%s\"\nd=\"", color.r,color.g,color.b,
           palmIndex?"crispEdges":"geometricPrecision" );
        EmitPath( x, y, reverse, fig, nsides, &minx, &miny, &maxx, &maxy, 0,0 );
    }

    if ( 0 <= boundary.r ) {
        printf( "<path style=\"fill-opacity:1.0; fill:rgb(%d,%d,%d); shape-rendering:%s", color.r,color.g,color.b,
           palmIndex?"crispEdges":"geometricPrecision" );
        if ( stroke ) {
            printf( "; stroke:rgb(%d,%d,%d); stroke-width:1", boundary.r, boundary.g, boundary.b );
        }
        printf( "\"\nd=\"" );
        EmitPath( x, y, reverse, fig, nsides, &minx, &miny, &maxx, &maxy, skipLeft, skipRight );
    }

    fsize = FONT_HEIGHT;

    if ( upCase && islower( c ) )
        fsize *= .85;

    if ( ( reverse ? ( maxy - miny ) : ( maxx - minx ) ) < HEX_WIDTH * .9 ) {
        fsize *= .5;
    }
    else if ( fig == hexagon &&
              ( reverse ? ( maxx - minx ) : ( maxy - miny ) ) < HEX_HEIGHT * .8 ) {
        fsize *= .5;
    }

    if ( fig == topHalf || fig == bottomHalf )
        fsize *= reverse ? .8 : .7;

    if ( c == 'C' )
        fsize *= .5;
//    if ( c == 'T' )
//        fsize *= .8;

    if ( c && ! palmIndex ) {
        char* myFont;
        char* format;

        cx = ( minx + maxx ) /2;
        cy = ( miny + maxy + fsize*.5 ) / 2;

        if ( upCase && islower( c ) ) {
            cy += .05 * fsize;
        }

        if ( fig == leftHalf )
            cx -= HORIZ_SIDE_LEN * .3;
        if ( fig == rightHalf )
            cx += HORIZ_SIDE_LEN * .3;

        if ( fig == leftHalf && reverse && c != '*' )
            cy -= HORIZ_SIDE_LEN * .1;
        if ( fig == rightHalf && reverse )
            cy += HORIZ_SIDE_LEN * .1;

//        if ( reverse ) {
//            printf( "\n<! %lf %lf  %lf %lf>\n",y,cy,miny,maxy );
//        }

        if ( fig == hexagon &&
              ( reverse ? ( maxx - minx ) : ( maxy - miny ) ) < HEX_HEIGHT * .8 ) {
            if ( reverse ) {
                cx += fsize * .25;
            }
            else {
                cy += fsize * .25;
            }
            if ( ! reverse && ( c == '@' || c == '_' ) )
                cy -= fsize * .15;
        }

        if ( fig == hexagon &&
              ! reverse && ( maxx - minx ) < HEX_HEIGHT * .8 ) {
            if ( minx < width / 2 )
                cx -= .1 * fsize;
            else
                cx += .1 * fsize;
        }


        if ( fig == hexagon && reverse && ( maxy - miny ) < HEX_HEIGHT * .8 ) {
            cy += fsize * .1;
        }

        if ( fig == topHalf || fig == bottomHalf ) {
            if ( ! reverse && WIDTH < x + HEX_WIDTH ) {
                cx += HORIZ_SIDE_LEN * .23;
            }
            else if ( reverse && fig == topHalf ) {
                cx += HORIZ_SIDE_LEN * .2;
            }
            else if ( reverse && fig == bottomHalf ) {
                cx -= HORIZ_SIDE_LEN * .2;
            }
//            else if ( reverse && WIDTH < y + HEX_WIDTH ) {
//                cy += HORIZ_SIDE_LEN * .23;
//            }
        }
        
        if ( c == 'M' ) {
            if ( c=='M' && ! palmIndex ) {
               printf( "<g transform=\"translate(%.16Lf,%.16Lf)scale(%.16Lf)\">\n", cx-fsize*.3, cy-fsize*.55, .6*fsize/32. );
    printf( "  <path d=\"M 5.983317 25.882729 A 1.2055937 1.2055937 0 1 1  3.5721296,25.882729 A 1.2055937 1.2055937 0 1 1  5.983317 25.882729 z\" transform=\"translate(-0.233317,1.661678)\" style=\"fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:rgb(%d,%d,%d);stroke-width:6.5;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1\"/>\n",
             text.r, text.g, text.b );
    printf( "  <path d=\"M 4,27.534838 L 31,0.534838\" style=\"fill:none;fill-opacity:1;fill-rule:evenodd;stroke:rgb(%d,%d,%d);stroke-width:2px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1\" />\n",
             text.r, text.g, text.b );
               printf( "</g>" );
            }
            return;
        }

        if ( c == '^' )
            cy += .1 * fsize;
            
        if ( c == 'G' && ! reverse )
            cy -= .2 * fsize;

        switch ( c ) {
            case 'B':
            case 'R':
            case 'H':
            case 'J':
            case 'K':
            case 'L':
                myFont = "Symbol";
                break;
            case 'G':
                myFont = "Lucida Handwriting";
                break;
            case 'S':
                myFont = "Wingdings";
                break;
            case 'X':
            case 'Y':
            case 'Z':
            case 'D':
            case 'E':
            case 'F':
            case 'N':
            case 'O':
            case 'P':
            case 'U':
                myFont = "Wingdings-2";
                fsize *= 1.1;
                cy += .05*fsize;
                if ( ! reverse )
                    cy += .05*fsize;
                break;
            case 'I':
                myFont = "Lucida Sans Unicode";
                break;
            case 'T':
                myFont = "Wingdings-3"; //"Lucida Sans Unicode";
                break;
            default:
                myFont = font;
                break;
        }

        if ( c == 'S' )
            cy += fsize*.1;
        if ( c == 'I' )
            cy += fsize*.1;
        if ( c == 'T' ) {
            cy += fsize*.1;
            cx -= fsize*.05;
        }

        printf( "<text x=\"%.16Lf\" y=\"%.16Lf\"", cx, cy );

        format = reformat[ ( unsigned char ) c ];

        if ( format == NULL || NULL == strstr( format, "font-family=" ) )
            printf( " font-family=\"%s\"", myFont );

        if ( format == NULL || NULL == strstr( format, "font-style=" ) )
            printf( " font-style=\"%s\"", fontStyle );

        if ( format == NULL || NULL == strstr( format, "font-weight=" ) )
            printf( " font-weight=\"%s\"", fontWeight );

        if ( format == NULL || NULL == strstr( format, "font-size=" ) )
            printf( " font-size=\"%.16Lf\"", fsize );

        if ( format == NULL || NULL == strstr( format, "fill=" ) )
            printf( " fill=\"rgb(%d,%d,%d)\"", text.r, text.g, text.b );

        if ( format == NULL || NULL == strstr( format, "text-anchor=" ) )
            printf( " text-anchor=\"middle\"" );

        if ( format != NULL )
            printf( " %s>", format );
        else
            printf( ">" );

        if ( relabel[ ( unsigned char )c ] != NULL )
            printf( "%s</text>", relabel[ ( unsigned char )c ] );
        else
            switch( c ) {
                case '\x80':
                    printf( "&#8364;</text>\n" );
                    break;
                case '<':
                    printf( "&lt;</text>\n" );
                    break;
                case '>':
                    printf( "&gt;</text>\n" );
                    break;
                case '&':
                    printf( "&amp;</text>\n" );
                    break;
                case 'G':
                    printf( "g</text>\n" );
                    break;
                case 'X':
                    printf( "&#9312;</text>\n" ); //&#9471;&#9312;
                    break;
                case 'Y':
                    printf( "&#9313;</text>\n" );//&#10102;&#9313
                    break;
                case 'Z':
                    printf( "&#9314;</text>\n" );//&#10102;&#9313
                    break;
                case 'D':
                    printf( "&#9315;</text>\n" );//&#10102;&#9313
                    break;
                case 'E':
                    printf( "&#9316;</text>\n" );//&#10102;&#9313
                    break;
                case 'F':
                    printf( "&#9317;</text>\n" );//&#10102;&#9313
                    break;
                case 'N':
                    printf( "&#9318;</text>\n" );//&#10102;&#9313
                    break;
                case 'O':
                    printf( "&#9319;</text>\n" );//&#10102;&#9313
                    break;
                case 'P':
                    printf( "&#9320;</text>\n" );//&#10102;&#9313
                    break;
                case 'U':
                    printf( "&#9450;</text>\n" );//&#10102;&#9313
                    break;
                case 'B':
                case 'H':
                    printf( "&#8592;</text>\n" );
                    break;
                case 'S':
                    printf( "&#8679;</text>\n" ); //
                    break;
                case 'T':
                    printf( "&#8614;</text>\n" ); //
                    break;
                case 'J':
                    printf( "&#8594;</text>\n" ); //
                    break;
                case 'C':
                    printf( "caps</text>\n" );
                    break;
                case 'I':
                    printf( "&#8634;</text>\n" ); //
                    break;
                case 'R':
                    printf( "&#8629;</text>\n" ); //
                    break;
                case 'K':
                    printf( "&#8593;</text>\n" ); //
                    break;
                case 'L':
                    printf( "&#8595;</text>\n" ); //
                    break;
                default:
                    printf( "%c</text>\n", upCase ? toupper( c ) : c );
                    break;
            }
    }
}


void GetLines( Line* labels, FILE* f )
{
    int i;

    for ( i = 0 ; i < NUM_LABELS ; i++ ) {
         int len;
         int j;
         int c;

         len = strlen( labels[ i ] );

         for ( j = 0 ; j < len ; j++ ) {

              c = fgetc( f );

              if ( c == EOF || c == '\n' || c == '\r' ) {
                  break;
              }

              labels[ i ][ j ] = c;
         }
         for ( ; j < len ; j++ ) {
              labels[ i ][ j ] = ' ';
         }

         if ( c != '\n' )
             while ( ( c = fgetc( f ) ) != '\n' && c != EOF );
    }
}



void Strip( char* p )
{
    char* q;
    
    q = strstr( p, "//" );
    
    if ( q != NULL )
        *q = 0;

    q = p + strlen( p ) - 1;

    while ( p <= q ) {
        if ( ! ( isspace( *q ) || *q == '\n' || *q == '\r' ) )
            break;
        *q-- = 0;
    }
}



void GetRe( FILE* f, char* re[ 256 ] )
{
    static char buffer[ 32768 ];

    while ( fgets( buffer, 32768, f ) != NULL ) {
        Strip( buffer );

        if ( ! strcmp( buffer, ":END" ) )
            return;

        if ( buffer[ 0 ] && buffer[ 1 ] == ':' ) {
            re[ ( unsigned char )buffer[ 0 ] ] = strdup( buffer + 2 );
        }
        else if ( buffer[ 0 ] && buffer[ 1 ] == '-' && buffer[ 2 ] && buffer[ 3 ] == ':' ) {
            char* newText;
            int   i;

            newText = strdup( buffer + 4 );

            for ( i = ( unsigned char )buffer[ 0 ] ; i <= ( unsigned char )buffer[ 2 ] ; i++ )
                 re[ i ] = newText;
        }
    }
}


void GetColorKey( FILE* f )
{
    char buffer[ 256 ];
    int  i;

    i = 0;

    while ( fgets( buffer, 256, f ) != NULL ) {
        if ( i == MAX_COLORS - 1 ||
             buffer[ 0 ] == 0 || buffer[ 0 ] == '\n' || buffer[ 0 ] == '\r' || buffer[ 1 ] != ' ' )
            break;
        colorTable[ i ].c = buffer[ 0 ];
        sscanf( buffer + 2, "%d %d %d", &( colorTable[ i ].color.r ), &colorTable[ i ].color.g, &colorTable[ i ].color.b );
        i++;
    }
    colorTable[ i ].c = 0;
    colorTable[ i ].color.r = 255;
    colorTable[ i ].color.g = 255;
    colorTable[ i ].color.b = 255;
}



void GetColorLine( RGB* c, FILE* f )
{
    char buffer[ 256 ];

    if ( NULL != fgets( buffer, 256, f ) ) {
        char *p;

        p = buffer;

        while ( *p && isspace( *p ) ) p++;
        if ( *p == 'b' || *p == 'B' ) {
            c->r = -1;
            c->g = -1;
            c->b = -1;
            return;
        }

        sscanf( buffer, "%d %d %d", &c->r, &c->g, &c->b );
    }
}


void SkipToMine( FILE* f )
{
    char buffer[ 256 ];

    while ( NULL != fgets( buffer, 256, f ) ) {
        Strip( buffer );

        if ( ! strcmp( buffer, "GENERIC:" ) ||
             ( reverse && ! strcmp( buffer, "LANDSCAPE:" ) ) ||
             ( ! reverse && ! strcmp( buffer, "PORTRAIT:" ) ) )
            return;
    }
}


void ScanFile( FILE* f )
{
    char buffer[ 256 ];

    while ( fgets( buffer, 256, f ) != NULL ) {
        Strip( buffer );
        if ( ! strcmp( buffer, "LANDSCAPE:"  ) && ! reverse ) {
            SkipToMine( f );
        }
        if ( ! strcmp( buffer, "PORTRAIT:" ) && reverse ) {
            SkipToMine( f );
        }
        if ( ! strcmp( buffer, "LABELS:" ) ) {
            GetLines( labels, f );
        }
        else if ( ! strcmp( buffer, "COLOR-PATTERN:" ) ) {
            GetLines( colors, f );
        }
        else if ( ! strcmp( buffer, "PALM-NAME:" ) ||
                  ! strcmp( buffer, "FILENAME:" ) ) {
            fgets( buffer, 256, f );
        }
        else if ( ! strcmp( buffer, "TEXT-FONT:" ) ) {
            if ( NULL != fgets( buffer, 256, f ) ) {
                Strip( buffer );
                strcpy( font, buffer );
            }
        }
        else if ( ! strcmp( buffer, "TEXT-FONT-STYLE:" ) ) {
            if ( NULL != fgets( buffer, 256, f ) ) {
                Strip( buffer );
                strcpy( fontStyle, buffer );
            }
        }
        else if ( ! strcmp( buffer, "TEXT-FONT-WEIGHT:" ) ) {
            if ( NULL != fgets( buffer, 256, f ) ) {
                Strip( buffer );
                strcpy( fontWeight, buffer );
            }
        }
        else if ( ! strcmp( buffer, "COLOR-KEY:" ) ) {
            GetColorKey( f );
        }
        else if ( ! strcmp( buffer, "RELABEL:" ) ) {
            GetRe( f, relabel );
        }
        else if ( ! strcmp( buffer, "REFORMAT:" ) ) {
            GetRe( f, reformat );
        }
        else if ( ! strcmp( buffer, "BOUNDARY-COLOR:" ) ) {
            GetColorLine( &boundary, f );
        }
        else if ( ! strcmp( buffer, "TEXT-COLOR:" ) ) {
            GetColorLine( &text, f );
        }
        else if ( ! strcmp( buffer, "BLANK-COLOR:" ) ) {
            GetColorLine( &blank, f );
        }
    }
}


main( int argc, char** argv )
{
    int row;
    int i;
    FILE* f;

    palmIndex = 0;
    reverse   = 0;
    noFill    = 0;
    stroke    = 0;

    for ( i = 1 ; i < argc ; i++ ) {
        if ( 2 < strlen( argv[ i ] ) && argv[ i ][ 1 ] == ':' ) {
            switch ( argv[ i ][ 0 ] ) {
                case 'f':
                    strcpy( font, argv[ i ] + 2 );
                    break;
                case 'g':
                    f = fopen( argv[ i ] + 2, "r" );
                    if ( f != NULL ) {
                        ScanFile( f );
                        fclose( f );
                    }
            }
            continue;
        }
        if ( NULL != strchr( argv[ i ], 'i' ) )
            palmIndex = 1;
        if ( NULL != strchr( argv[ i ], 'r' ) )
            reverse = 1;
        if ( NULL != strchr( argv[ i ], 'n' ) )
            noFill = 1;
        if ( NULL != strchr( argv[ i ], 's' ) )
            stroke = 1;
        if ( NULL != strchr( argv[ i ], 'c' ) )
            useColorTable = 1;
        if ( NULL != strchr( argv[ i ], 'u' ) )
            upCase = 1;
        if ( NULL != strchr( argv[ i ], 'p' ) ) {
            int j;

            puts ( "Character code to palette mapping\n"
                   "Character  R   G   B  " );

            for ( j = 32 ; j < 256 ; j++ ) {
                 RGB c;

                 c = GetPalette( j );

                 printf( "%3d (%02x %c) %3d %3d %3d\n", j, j, ( j == 127 ) ? ' ' : j, c.r, c.g, c.b );
            }

            return 0;
        }
    }

    if ( reverse ) {
        height = WIDTH;
        width  = HEIGHT;
    }
    else {
        height = HEIGHT;
        width  = WIDTH;
    }

    printf( "<?xml version=\"1.0\" encoding=\"iso-8859-1\"?>\n"
          "<svg width=\"%d\" height=\"%d\">\n", width,
                height );

    for ( row = -1 ; row <= NUM_IN_HEIGHT ; row ++ ) {
         long double y;
         long double x;
         int col;

         y = row * ROW_HEIGHT;

 //        fprintf(stderr,"<%s>\n",labels[row]);

         for ( col = 0, x = ( row % 2 ) ? - HORIZ_SIDE_LEN : 0;
               x < WIDTH;
               x += HEX_WIDTH, col++ ) {
              char c1;
              char c2;
              int  myCol;
              int  skipLeft;
              int  skipRight;
              int  rowLength;

              skipLeft = 0;
              skipRight = 0;

              rowLength = strlen( labels[ row ] );

              if ( row == -1 || row == NUM_IN_HEIGHT ) {
                  DrawCell( x, y, hexagon, 6, useColorTable ? blank : white, 0, 0, 0 );
                  continue;
              }

              if ( row < NUM_LABELS && reverse && 2 * col < strlen( labels[ row ] ) )
                  myCol = rowLength / 2 - 1 - col;
              else
                  myCol = col;

              if ( row < NUM_LABELS &&
                   2 * myCol < strlen( labels[ row ] ) ) {

                  c1 = labels[ row ][ 2 * myCol ];
                  c2 = labels[ row ][ 2 * myCol + 1 ];

                  if ( c1 == ' ' && c2 == ' ' ) {
                      if ( 2 * myCol + 2 < rowLength && ' ' == labels[ row ][ 2 * myCol + 2 ] ) {
                          if ( reverse )
                              skipLeft = 1;
                          else
                              skipRight = 1;
                      }
                      if ( 0 < myCol && labels[ row ][ 2 * myCol - 1 ] == ' ' && labels[ row ][ 2 * myCol - 2 ] == ' ' ) {
                          if ( reverse )
                              skipRight = 1;
                          else
                              skipLeft = 1;
                      }
                  }
 //                 skipLeft = skipRight = 1;
              }
              else {
                  c1 = ' ';
                  c2 = ' ';
              }

              if ( c2 == ' ' ) {
                  DrawCell( x, y, hexagon, 6,
                      useColorTable ? GetColor( c1 ) :
                      GetPalette( c1 ),
                      c1, skipLeft, skipRight );
              }
              else {
                  int upDownStyle = x < 0 || WIDTH < x + HEX_WIDTH * .8;

                  DrawCell( x, y, upDownStyle ? topHalf:leftHalf, 5,
                      useColorTable ? GetColor( c1 ) :
                      GetPalette( c1 ),
                      c1, skipLeft, skipRight );
                  DrawCell( x, y, upDownStyle ? bottomHalf:rightHalf, 5,
                      useColorTable ? GetColor( c2 ) :
                      GetPalette( c2 ),
                      c2, skipLeft, skipRight );
              }
         }

    }

    puts( "</svg>\n");
    return 0;
}
