Subversion Repositories svn1-original

Rev

Rev 79 | Blame | Compare with Previous | Last modification | View Log | RSS feed

/*************************************************************************
 *          Copyright (C) 1995 Embedded Solutions
 *                      All rights reserved
 *
 * file:        src\print.c
 *
 * purpose: Module to interface to the printer channel (file)
 *
 * functions
 *      open_printer            - Open the printer
 *      close_printer           - Close the printer
 *      print                   - Print to to the printer
 *      printbanner             - Print a page banner
 *
 * programmer: David Purdie
 *
 * revision date        by      reason
 *  00.0    27/01/95    DDP     Tidies up the program and formatted the file
 *
 **************************************************************************/

#include    <stdio.h>
#include    <time.h>
#include    <stdarg.h>

#include    "consts.h"
#include    "structs.h"
#include    "proto.h"

FILE       *pfile;                               /* Fd of the printer channel */
long        pri_time;                            /* Time printer is opened - for banners */
int         print_width;                         /* Width of the printout */
report_type print_html = text;                   /* Printing with HTML */
int         print_col = 0;                       /* Current print column */
int         print_line = 0;                      /* Current print line */
int         print_underline_start;               /* Start of underline */
int         print_underline_end;                 /* End of underline */
long        print_current_colour;                /* Current printing colour */

/*========================================================================
 *
 *  Open the printer
 *
 *  Purpose:
 *      This function is called to open the printer and prepare to print
 *
 *  Parameters:
 *      name        Name of print file
 *      ext         Ext of the print file
 *      width       Width of the printed file
 *      html        Printing in HTML mode
 *
 *  Returns:
 *      TRUE if the printer can be attached
 *
 *
 *  Note: Use an "htm" file extension as DOS cannot handle 4 letter extensions
 *========================================================================*/

bool open_printer( char *name, char *ext, int width, report_type html, char *title )
{
    char    *pname;

    /*
    **  Determine the name of the file
    **  May need to modify the extension if it is an HTML file
    */
    if ( html )
    {
        if ( html == printed )
            pname = p_filename( name[0] ? name : filebase, ext ,"prn.html" );
        else
            pname = p_filename( name[0] ? name : filebase, ext ,"html" );
    }
    else
    {
        pname = p_filename( filebase, name[0] ? name : "", ext[0] ? ext : "lst" );
    }

    /*
    **  Now use basic function
    */
    return open_printer_name (pname, width, html, title );
}

/*----------------------------------------------------------------------------
 * FUNCTION           : open_printer_name
 *
 * DESCRIPTION        : Open a printer with a known name
 *
 *      This function is called to open the printer and prepare to print
 *
 *  Parameters:
 *      pname       Name of print file
 *      width       Width of the printed file
 *      html        Printing in HTML mode
 *
 *  Returns:
 *      TRUE if the printer can be attached
 *
 *
 *  Note: Use an "htm" file extension as DOS cannot handle 4 letter extensions
----------------------------------------------------------------------------*/

bool open_printer_name( char *pname, int width, report_type html, char *title )
{
    print_width = width ? width : 80;
    print_col = 0;
    print_line = 0;
    print_underline_start = -1;
    print_underline_end = -1;
    print_current_colour = 0;

    /*
    **  Open the printer
    **  Ensure that it is opened in text mode
    */
    if( ( pfile = fopen( pname, "wt" ) ) != NULL )
    {
        time( &pri_time );                       /* Latch the time */

        /*
        **  Print out the HTML file header
        */
        if ( html )
        {
            print( "<HTML>\n" );
            print( "<HEAD>\n" );
            print( "<TITLE>%s - %s</TITLE>\n", config.event_name, title );
//            print( "<LINK rel=\"stylesheet\" href=\"brmr.css\" type=\"text/css\">\n");
            print( "</HEAD>\n" );
            print( "<BODY LANG=\"en-US\">\n" );
            print( "<PRE>" );
            print_html = html;
        }

        /*
        **  Print out a common banner
        */
        printbanner(title);
    }
    else
    {
        beep();                                /* Printer not available */
        printf( "Printer not available" );
        flush_out();
        sleep( 5 );
    }
    return ( pfile != 0 );
}

/*========================================================================
 *
 *  Close the printer
 *
 *  Purpose:
 *      This function is called to close and release the printer
 *      All reports are terminated with a formfeed
 *
 *  Parameters:
 *      None
 *
 *  Returns:
 *      TRUE if the printer channel can be released
 *
 *========================================================================*/

bool close_printer(void)
{
    if ( print_html )
    {
        print_html = text;
        print( "</PRE>\n" );
        print( "</BODY>\n" );
        print( "</HTML>\n" );
    }
    else
    {
        print( "\014" );
    }
    fclose( pfile );
    return ( TRUE );
}

/*========================================================================
 *
 *  Print to to the printer
 *
 *  Purpose:
 *      This function is called to do print data on the printer
 *      Track current character index so as to assist in tracking the
 *      use of underline.
 *
 *  Assume:
 *      New lines are at the end of a line printed. This does allow for
 *      a single new-line.
 *
 *
 *  Parameters:
 *      Standard printf type parameters
 *
 *  Returns:
 *      TRUE : Operation was succesful
 *
 *========================================================================*/

int print( char *format, ... )
{
    va_list     ap;
    char        pp[200];
    int         len;
    bool        eol = FALSE;


    /*
    **  If this is the start of a new line then we may need to colour it
    */
    if ( print_col == 0 && print_html && (print_line & 1) )
    {
        print_colour( HTML_COLOUR_GREEN );
    }

    /*
    **  If this is the start of a new line then we may need to perform
    **  a perf-skip
    */
    if ( print_col == 0 && print_line && ! print_html && config.lines_per_page && config.perf_skip )
    {
        if ( 0 == ((print_line + 2) % (config.lines_per_page - config.perf_skip)) )
        {
            int count = config.perf_skip;
            while ( count-- )
                fwrite( "\n", 1, 1, pfile );
        }
    }

    va_start( ap, format );
    len = vsprintf( pp, format, ap );
    va_end( ap );

    /*
    **  Detect the end of a line and flag for later processing
    */
    if ( len > 0 && pp[len - 1] == '\n' )
    {
        len--;
        eol = TRUE;
    }

    if ( len )
    {
        fwrite( pp, 1, len, pfile );
        print_col += len;
    }

    /*
    **  Perform End of Line operation before printing the final newline
    */
    if ( eol )
    {
        print_line++;

        /*
        **  Detect the end of a non-HTML underline
        */
        print_underline ( FALSE );
        if ( print_underline_start < print_underline_end )
        {
            int length;

            fwrite( "\n", 1, 1, pfile );

            length = print_underline_start;
            while( length-- )
                fwrite( " ", 1, 1, pfile );

            length = print_underline_end - print_underline_start;
            while ( length-- )
                fwrite( "=", 1, 1, pfile );
        }

        print_underline_start = -1;
        print_underline_end = -1;
        print_col = 0;

        /*
        **  Track the background colour
        */
        if ( print_html )
        {
            print_colour( 0 );
        }

        /*
        **  Now print the final newline
        */
        fwrite( "\n", 1, 1, pfile );
        len ++;
    }

    return ( len );
}

/*========================================================================
 *
 *  Print to to the printer
 *
 *  Purpose:
 *      This function is called to do print data on the printer
 *
 *  Assume:
 *      One CSV field per print
 *      New lines are at the end of a line printed. This does allow for
 *      a single new-line.
 *
 *
 *  Parameters:
 *      Standard printf type parameters
 *
 *  Returns:
 *      TRUE : Operation was succesful
 *
 *========================================================================*/

int csv_print( char *format, ... )
{
    va_list     ap;
    char        pp[200];
    int         len;
    bool        eol = FALSE;


    va_start( ap, format );
    len = vsprintf( pp, format, ap );
    va_end( ap );

    /*
    **  Detect the end of a line and flag for later processing
    */
    if ( len > 0 && pp[len - 1] == '\n' )
    {
        len--;
        eol = TRUE;
    }

    if ( ! eol )
    {
        if ( print_col )
            fwrite( ",", 1, 1, pfile );
        fwrite( "\"", 1, 1, pfile );
        fwrite( pp, 1, len, pfile );
        print_col += len;
        fwrite( "\"", 1, 1, pfile );
    }

    /*
    **  Perform End of Line operation before printing the final newline
    */
    if ( eol )
    {
        print_line++;
        print_col = 0;

        /*
        **  Now print the final newline
        */
        fwrite( "\n", 1, 1, pfile );
        len ++;
    }

    return ( len );
}


/*========================================================================
 *
 *  Print to to the printer without any frills
 *
 *  Purpose:
 *      This function is called to do print data on the printer
 *
 *  Parameters:
 *      Standard printf type parameters
 *
 *  Returns:
 *      TRUE : Operation was succesful
 *
 *========================================================================*/

int raw_print( char *format, ... )
{
    va_list     ap;
    char        pp[200];
    int         len;


    va_start( ap, format );
    len = vsprintf( pp, format, ap );
    va_end( ap );

    fwrite( pp, 1, len, pfile );

    return ( len );
}


/*========================================================================
 *
 *  Control bolding
 *
 *  Purpose:
 *      This function is called to turn bolding on and off
 *      This function will ONLY affect HTML printing
 *
 *  Parameters:
 *      on              - TRUE
 *
 *  Returns:
 *      Nothing
 *
 *========================================================================*/

void print_bold( bool on )
{
    if ( print_html )
    {
        if ( on )
            raw_print( "<B>" );
        else
            raw_print( "</B>" );
    }
}

/*========================================================================
 *
 *  Control underline
 *
 *  Purpose:
 *      This function is called to turn underline on and off
 *      This function will ONLY affect HTML printing and Non-HTML printing
 *      But in a different manner
 *
 *  Parameters:
 *      on              - TRUE
 *
 *  Returns:
 *      Nothing
 *
 *========================================================================*/

void print_underline( bool on )
{
    if ( print_html )
    {
        /*
        **  For HTML printing underline is simple
        */
        if ( on )
        {
            raw_print( "<U>" );
            print_underline_start = 1;
        }
        else if ( print_underline_start > 0 )
        {
            raw_print( "</U>" );
            print_underline_start = 0;
        }
    }
    else
    {
        /*
        **  Non-HTML printing
        **  Store underline start and stop column
        */
        if ( on )
            print_underline_start = print_col;
        else if ( print_underline_start >= 0 )
            print_underline_end = print_col;
    }
}

/*========================================================================
 *
 *  Control colour - HTML printing only
 *
 *  Purpose:
 *      This function is called to change the background colour within
 *      HTML text
 *
 *  Parameters:
 *      colour      - Colour control string
 *                    or NULL to trun colour OFF
 *
 *
 *  Returns:
 *      Nothing
 *
 *========================================================================*/

void print_colour( long colour )
{
    if ( print_html )
    {
        if ( print_current_colour )
        {
            raw_print( "</SPAN>" );
            print_current_colour = 0L;
        }

        if ( colour )
        {
            print_current_colour = colour;
            raw_print( "<SPAN STYLE=\"background: #%6.6lx\">", colour );
        }
    }
}


/*========================================================================
 *
 *  Print a page banner
 *
 *  Purpose:
 *      This function is called to print a page banner
 *
 *  Parameters:
 *      None
 *
 *  Returns:
 *      Nothing
 *
 *========================================================================*/

void printbanner( char *title )
{
    int         l, s;

    if ( !title )
        return;

    l = strlen( config.event_name );
    s = ( print_width - l ) / 2;
    print( "%*s", s, "" );

    if ( print_html == html )
        print( "<A HREF=\"%s\">", p_filename(filebase, "index" ,"html"));
    print_underline( TRUE);
    print_bold( TRUE );

    print( "%s", config.event_name );

    print_bold( FALSE );
    print_underline( FALSE );
    if ( print_html == html )
        print( "</A>" );

    print( "\n" );

    /*
    **  Print out one line with the report title
    **  on the left and the report time on the right
    */
    if ( title )
        print( "%s", title );

    s = print_width - print_col - 24 - 4;
    print( "%*s", s , "" );

    print( "%.24s", ctime( &pri_time ) );
    print( "\n" );
    print( "\n" );
}


/*========================================================================
 *
 *  Format a filename
 *
 *  Purpose:
 *      This function is called create a suitably formatted filename
 *      for use in an HTML tag or by the file system
 *
 *      Currently all output filenames are created in uppercase
 *      This is a limitation of DOS
 *      This function is used to ensure that all files are created with
 *      an uppercase name and that all HTML file references are also
 *      in uppercase.
 *
 *
 *  Parameters:
 *      filename        - Base filename
 *      Suffix          - Optional part of the basename
 *                        If present is used to create part of the basename
 *      ext             - Extension
 *
 *  Returns:
 *      Address of a static string that will reference the file
 *
 *========================================================================*/

char * p_filename( char *filename, char *suffix, char *ext )
{
    char    *name;
    char    *cptr;

#ifndef LONG_FILE_NAMES
    /*
    **  Limit the filename to 8.3 format
    **  This is a limitation of the underlying file access library
    **  and may be removed in the future
    */
    if ( suffix[0] )
        name = tprintf ( "%.4s_%.3s.%.3s", filename, suffix, ext );
    else
        name = tprintf ( "%.8s.%.3s", filename, ext );


    /*
    **  Uppercase the filename
    */
    cptr = name;
    while ( *cptr )
    {
        *cptr = toupper( *cptr );
        cptr++;
    }
#else
    /*
    **  This compiler and runtime library supports
    **  long filenames - created printed filenames in lower case
    */
    if ( suffix[0] )
        name = tprintf ( "%s_%s.%s", filename, suffix, ext );
    else
        name = tprintf ( "%s_%s.%s", filename, ext, "txt" );

    cptr = name;
    while ( *cptr )
    {
        *cptr = tolower( *cptr );
        cptr++;
    }
#endif

    return( name );
}


/*========================================================================
 *
 *  Print to a temp string buffer
 *
 *  Purpose:
 *      This function is similar to sprintf() except that the routine
 *      maintains a list of string buffers and will return one to the
 *      user.
 *
 *      This function allows a user to create small, short lived
 *      printed strings, without the memory managment overhead.
 *
 *      Down-side. Use the string quickly.
 *                 Strings have a limited length
 *
 *  Parameters:
 *      Standard printf type parameters
 *
 *  Returns:
 *      TRUE : Operation was succesful
 *
 *========================================================================*/

#define TBUF_COUNT  5               /* Number of buffers */
#define TBUF_LENGTH 100             /* Max length of a single print */

char *tprintf( char *format, ... )
{
    static char tbuf[TBUF_COUNT][TBUF_LENGTH];
    static int  index = 0;

    va_list     ap;
    char       *pp;

    /*
    **  Get the next entry from the small store
    */
    index++;
    if( index >= TBUF_COUNT )
        index = 0;
    pp = tbuf[index];

    va_start( ap, format );
    vsprintf( pp, format, ap );
    va_end( ap );

    return ( pp );
}

/*----------------------------------------------------------------------------
** FUNCTION           : to_hex
**
** DESCRIPTION        : Converts an integer value to its hex character
**
**
** INPUTS             : code        - Code to convert
**
** RETURNS            : Character representation
**
----------------------------------------------------------------------------*/

char to_hex(char code)
{
  static char hex[] = "0123456789abcdef";
  return hex[code & 0x0f];
}

/*----------------------------------------------------------------------------
** FUNCTION           : url_encode
**
** DESCRIPTION        : URL encoded version of a string
**
**
** INPUTS             : string to encode
**
** RETURNS            : Encoded string
**
** WARNING            : Uses a small circular pool of strings so that the
**                      user doesn't need to worry about string release
**
----------------------------------------------------------------------------*/
char *url_encode(char *str)
{
    static char tbuf[TBUF_COUNT][TBUF_LENGTH * 3];
    static int  index = 0;
    char       *pp;

    /*
    **  Get the next entry from the small store
    */
    index++;
    if( index >= TBUF_COUNT )
        index = 0;
    pp = tbuf[index];
    
    char *pstr = str;
    char *pbuf = pp;

    while (*pstr)
    {
        if (isalnum(*pstr) || *pstr == '-' || *pstr == '_' || *pstr == '.' || *pstr == '~')
            *pbuf++ = *pstr;
        else if (*pstr == ' ')
            *pbuf++ = '+';
        else
        {
            *pbuf++ = '%';
            *pbuf++ = to_hex(*pstr >> 4);
            *pbuf++ = to_hex(*pstr & 15);
        }
        pstr++;
    }
    *pbuf = '\0';
  return pp;
}

/********************************* EOF ***********************************/