/************************************************************************* * 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 #include #include #include #include #include #include "mainwindow.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 */ QString printFileName; /* Last printer file opened */ char print_href[200]; /* Current HREF string */ /*======================================================================== * * 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( const char *name, const char *ext, int width, report_type html, const 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( const char *pname, int width, report_type htmltype, const char *title ) { printFileName = filepath; switch (htmltype) { case printed: printFileName.append("webtxt/"); break; case html: printFileName.append("web/"); break; default: printFileName.append("text/"); break; } /* ** Ensure that the directory exists */ { QDir dir(filepath); dir.mkpath(printFileName); } /* ** Append the filename to the directory */ printFileName.append(pname); 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 */ //qDebug() << "Opening File: " << qPrintable(printFileName); if( ( pfile = fopen( qPrintable(printFileName), "wt" ) ) != NULL ) { time( &pri_time ); /* Latch the time */ /* ** Print out the HTML file header */ if ( htmltype ) { print( "\n" ); print( "\n" ); print( "%s - %s\n", config.event_name, title ); // print( "\n"); print( "\n" ); print( "\n" ); print ("
"); print( "
" );
            print_html = html;
        }

        /*
        **  Print out a common banner
        */
        printbanner(title);
    }
    else
    {
        MainWindow::showMessage("Printer not available");
    }
    return ( pfile != 0 );
}

const QString &getPrinterFile(void)
{
    return printFileName;
}

/*========================================================================
 *
 *  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( "
\n" ); print( "\n" ); print( "\n" ); print( "\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( const 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; } // Insert pre-set HTML HREF into the string if (print_html && *print_href) { int iStart = 0; int iEnd = len; char *debugPtr = pp; for (int ii = 0; ii < len; ii++) { if (pp[ii] != ' ') { iStart = ii; break; } } for (int ii = len-1; ii >= iStart; ii--) { if (pp[ii] != ' ') { iEnd = ii + 1; break; } } debugPtr = print_href; strncat(print_href, &pp[iStart], iEnd - iStart); strcat(print_href, ""); strncat(print_href, &pp[iEnd], len - iEnd ); strcpy(&pp[iStart], print_href); len = strlen(pp); } *print_href = 0; 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( const 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( const 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( "" ); else raw_print( "" ); } } /*======================================================================== * * 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( "" ); print_underline_start = 1; } else if ( print_underline_start > 0 ) { raw_print( "" ); 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( "" ); print_current_colour = 0L; } if ( colour ) { print_current_colour = colour; raw_print( "", colour ); } } } /*======================================================================== * * Print a page banner * * Purpose: * This function is called to print a page banner * * Parameters: * None * * Returns: * Nothing * *========================================================================*/ void printbanner( const 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( "", 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( "" ); 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 , "" ); /* ** Debug support - dummy the print time */ QString dbgDate = QProcessEnvironment::systemEnvironment().value("MARA_REPORT_DATE", "") ; if (dbgDate.length() > 1) { print( "%.24s", qPrintable(dbgDate) ); } else { 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( const char *filename, const char *suffix, const 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( const 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 ); } /*======================================================================== * * Set HTML HREF to be used in the next print * * Purpose: * Create and save a printf like string so that it will be used * to create an HTML HREF * * Down-side. Can only have one at a time * Only valid for the next print * Strings have a limited length * * Parameters: * Standard printf type parameters * * Returns: * TRUE : Operation was succesful * *========================================================================*/ char *setHref( const char *format, ... ) { va_list ap; *print_href = 0; va_start( ap, format ); vsprintf( print_href, format, ap ); va_end( ap ); return ( print_href ); } /*---------------------------------------------------------------------------- ** 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(const 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]; const 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 ***********************************/