WindowsXP-SP1/admin/cmdline/lib/showresults.c
2020-09-30 16:53:49 +02:00

1034 lines
29 KiB
C

// *********************************************************************************
//
// Copyright (c) Microsoft Corporation
//
// Module Name:
//
// ShowResults.c
//
// Abstract:
//
// This modules has functions which are to shoow formatted Results on screen.
//
// Author:
//
// Sunil G.V.N. Murali (murali.sunil@wipro.com) 24-Sep-2000
//
// Revision History:
//
// Sunil G.V.N. Murali (murali.sunil@wipro.com) 01-Sep-2000 : Created It.
//
// *********************************************************************************
#include "pch.h"
#include "cmdline.h"
#include "cmdlineres.h"
//
// constants / defines / enumerations
//
//
// private functions ... used only within this file
//
// ***************************************************************************
// Routine Description:
// Prepares the pszBuffer string by taking values from arrValues and
// formate these values as per szFormat string.
//
// Arguments:
// [ in ] arrValues : values to be formated.
// [ out ] pszBuffer : output string
// [ in ] dwLength : string length.
// [ in ] szFormat : format
// [ in ] szSeperator : Seperator string
//
// Return Value:
// NONE
//
// ***************************************************************************
VOID __PrepareString( TARRAY arrValues,
LPTSTR pszBuffer, DWORD dwLength,
LPCTSTR szFormat, LPCTSTR szSeperator )
{
// local variables
DWORD dw = 0;
DWORD dwCount = 0;
LPTSTR pszTemp = NULL;
LPTSTR pszValue = NULL;
//
// kick off
// init
lstrcpy( pszBuffer, NULL_STRING );
dwCount = DynArrayGetCount( arrValues );
// allocate memory for buffers
pszTemp = __calloc( dwLength + 5, sizeof( TCHAR ) );
pszValue = __calloc( dwLength + 5, sizeof( TCHAR ) );
if ( pszTemp == NULL || pszValue == NULL )
{
// release memories
__free( pszTemp );
__free( pszValue );
return;
}
//
// traverse thru the list of the values and concatenate them
// to the destination buffer
for( dw = 0; dw < dwCount; dw++ )
{
// get the current value into the temporary string buffer
DynArrayItemAsStringEx( arrValues, dw, pszValue, dwLength );
// concatenate the temporary string to the original buffer
FORMAT_STRING( pszTemp, szFormat, _X( pszValue ) );
lstrcat( pszBuffer, pszTemp );
dwLength -= StringLengthInBytes( pszTemp );
// check whether this is the last value or not
if ( dw + 1 < dwCount )
{
// there are some more values
// check whether is space for adding the seperator or not
if ( dwLength < (DWORD) StringLengthInBytes( szSeperator ) )
{
// no more space available ... break
break;
}
else
{
// add the seperator and update the length accordingly
lstrcat( pszBuffer, szSeperator );
dwLength -= StringLengthInBytes( szSeperator );
}
}
}
// release memories
__free( pszTemp );
__free( pszValue );
}
// ***************************************************************************
// Routine Description:
// Gets the value from arrRecord and copies it to pszValue using
// proper format.
//
// Arguments:
// [ in ] pColumn : format info.
// [ in ] dwColumn : no of columns
// [ in ] arrRecord : value to be formatted
// [ out ] pszValue : output string
// [ in ] szArraySeperator : seperator used.
//
// Return Value:
// NONE
//
// ***************************************************************************
VOID __GetValue( PTCOLUMNS pColumn,
DWORD dwColumn, TARRAY arrRecord,
LPTSTR pszValue, LPCTSTR szArraySeperator )
{
// local variables
LPVOID pData = NULL; // data to be passed to formatter function
TARRAY arrTemp = NULL;
LPCTSTR pszTemp = NULL;
__STRING_64 szFormat = NULL_STRING; // format
// variables used in formatting time
DWORD dwReturn = 0;
SYSTEMTIME systime = { 0 };
// init first
lstrcpy( pszValue, NULL_STRING );
// get the column value and do formatting appropriately
switch( pColumn->dwFlags & SR_TYPE_MASK )
{
case SR_TYPE_STRING:
{
// identify the format to be used
if ( pColumn->dwFlags & SR_VALUEFORMAT )
lstrcpy( szFormat, pColumn->szFormat );
else
lstrcpy( szFormat, _T( "%s" ) ); // default format
// copy the value to the temporary buffer based on the flags specified
if ( pColumn->dwFlags & SR_ARRAY )
{
// get the value into buffer first - AVOIDING PREFIX BUGS
arrTemp = DynArrayItem( arrRecord, dwColumn );
if ( arrTemp == NULL )
return;
// form the array of values into one single string with ',' seperated
__PrepareString( arrTemp, pszValue, pColumn->dwWidth, szFormat, szArraySeperator );
}
else
{
// get the value into buffer first - AVOIDING PREFIX BUGS
pszTemp = DynArrayItemAsString( arrRecord, dwColumn );
if ( pszTemp == NULL )
return;
// now copy the value into buffer
FORMAT_STRING( pszValue, szFormat, _X( pszTemp ) );
}
// switch case completed
break;
}
case SR_TYPE_NUMERIC:
{
// identify the format to be used
if ( pColumn->dwFlags & SR_VALUEFORMAT )
lstrcpy( szFormat, pColumn->szFormat );
else
lstrcpy( szFormat, _T( "%d" ) ); // default format
// copy the value to the temporary buffer based on the flags specified
if ( pColumn->dwFlags & SR_ARRAY )
{
// get the value into buffer first - AVOIDING PREFIX BUGS
arrTemp = DynArrayItem( arrRecord, dwColumn );
if ( arrTemp == NULL )
return;
// form the array of values into one single string with ',' seperated
__PrepareString( arrTemp, pszValue, pColumn->dwWidth, szFormat, _T( ", " ) );
}
else
{
// get the value using format specified
FORMAT_STRING( pszValue, szFormat, DynArrayItemAsDWORD( arrRecord, dwColumn ) );
}
// switch case completed
break;
}
case SR_TYPE_FLOAT:
{
// identify the format to be used
// NOTE: for this type, format needs to be specified
// if not, value displayed is unpredictable
if ( pColumn->dwFlags & SR_VALUEFORMAT )
lstrcpy( szFormat, pColumn->szFormat );
else
lstrcpy( szFormat, _T( "%f" ) ); // default format
// copy the value to the temporary buffer based on the flags specified
if ( pColumn->dwFlags & SR_ARRAY )
{
// get the value into buffer first - AVOIDING PREFIX BUGS
arrTemp = DynArrayItem( arrRecord, dwColumn );
if ( arrTemp == NULL )
return;
// form the array of values into one single string with ',' seperated
__PrepareString( arrTemp, pszValue, pColumn->dwWidth, szFormat, szArraySeperator );
}
else
{
// get the value using format specified
FORMAT_STRING( pszValue, szFormat, DynArrayItemAsFloat( arrRecord, dwColumn ) );
}
// switch case completed
break;
}
case SR_TYPE_DOUBLE:
{
// identify the format to be used
// NOTE: for this type, format needs to be specified
// if not, value displayed is unpredictable
if ( pColumn->dwFlags & SR_VALUEFORMAT )
lstrcpy( szFormat, pColumn->szFormat );
else
lstrcpy( szFormat, _T( "%f" ) ); // default format
// copy the value to the temporary buffer based on the flags specified
if ( pColumn->dwFlags & SR_ARRAY )
{
// get the value into buffer first - AVOIDING PREFIX BUGS
arrTemp = DynArrayItem( arrRecord, dwColumn );
if ( arrTemp == NULL )
return;
// form the array of values into one single string with ',' seperated
__PrepareString( arrTemp, pszValue, pColumn->dwWidth, szFormat, szArraySeperator );
}
else
{
// get the value using format specified
FORMAT_STRING( pszValue, szFormat, DynArrayItemAsDouble( arrRecord, dwColumn ) );
}
// switch case completed
break;
}
case SR_TYPE_TIME:
{
// get the time in the required format
systime = DynArrayItemAsSystemTime( arrRecord, dwColumn );
// get the time in current locale format
dwReturn = GetTimeFormat( LOCALE_USER_DEFAULT, LOCALE_NOUSEROVERRIDE,
&systime, NULL, pszValue, MAX_STRING_LENGTH );
// check the result
if ( dwReturn == 0 )
{
// save the error info that has occurred
SaveLastError();
lstrcpy( pszValue, GetReason() );
}
// switch case completed
break;
}
case SR_TYPE_CUSTOM:
{
// check whether function pointer is specified or not
// if not specified, error
if ( pColumn->pFunction == NULL )
return; // function ptr not specified ... error
// determine the data to be passed to the formatter function
pData = pColumn->pFunctionData;
if ( pData == NULL ) // function data is not defined
pData = pColumn; // the current column info itself as data
// call the custom function
( *pColumn->pFunction)( dwColumn, arrRecord, pData, pszValue );
// switch case completed
break;
}
case SR_TYPE_DATE:
case SR_TYPE_DATETIME:
default:
{
// this should not occur ... still
lstrcpy( pszValue, NULL_STRING );
// switch case completed
break;
}
}
// user wants to display "N/A", when the value is empty, copy that
if ( lstrlen( pszValue ) == 0 && pColumn->dwFlags & SR_SHOW_NA_WHEN_BLANK )
{
// copy N/A
lstrcpy( pszValue, V_NOT_AVAILABLE );
}
}
// ***************************************************************************
// Routine Description:
//
// Arguments:
//
// Return Value:
//
// ***************************************************************************
VOID __DisplayTextWrapped( FILE* fp, LPTSTR pszValue, LPCTSTR pszSeperator, DWORD dwWidth )
{
// local variables
LPTSTR pszBuffer = NULL;
LPCTSTR pszRestValue = NULL;
DWORD dwTemp = 0, dwLength = 0, dwSepLength = 0;
// check the input
if ( pszValue == NULL || dwWidth == 0 || fp == NULL )
return;
// allocate buffer
dwLength = StringLengthInBytes( pszValue );
if ( dwLength < dwWidth )
dwLength = dwWidth;
// ...
pszBuffer = __calloc( dwLength + 5, sizeof( TCHAR ) );
if ( pszBuffer == NULL )
{
SetLastError( E_OUTOFMEMORY );
SaveLastError();
lstrcpy( pszValue, NULL_STRING ); // null-ify the remaining text
return;
}
// determine the length of the seperator
dwSepLength = 0;
if ( pszSeperator != NULL )
dwSepLength = StringLengthInBytes( pszSeperator );
// determine the length of the data that can be displayed in this row
dwTemp = 0;
dwLength = 0;
while ( 1 )
{
pszRestValue = NULL;
if ( pszSeperator != NULL )
pszRestValue = FindString( pszValue, pszSeperator, dwLength );
// check whether seperator is found or not
if ( pszRestValue != NULL )
{
// determine the position
dwTemp = StringLengthInBytes( pszValue ) - StringLengthInBytes( pszRestValue ) + dwSepLength;
// check the length
if ( dwTemp >= dwWidth )
{
// string position exceed the max. width
if ( dwLength == 0 || dwTemp == dwWidth )
dwLength = dwWidth;
// break from the loop
break;
}
// store the current position
dwLength = dwTemp;
}
else
{
// check if length is determined or not .. if not required width itself is length
if ( dwLength == 0 || ((StringLengthInBytes( pszValue ) - dwLength) > dwWidth) )
dwLength = dwWidth;
else if ( StringLengthInBytes( pszValue ) <= (LONG) dwWidth )
dwLength = StringLengthInBytes( pszValue );
// break the loop
break;
}
}
// get the partial value that has to be displayed
lstrcpyn( pszBuffer, pszValue, dwLength + 1 ); // +1 for NULL character
AdjustStringLength( pszBuffer, dwWidth, FALSE ); // adjust the string
ShowMessage( fp, pszBuffer ); // display the value
// change the buffer contents so that it contains rest of the undisplayed text
lstrcpy( pszBuffer, pszValue );
if ( StringLengthInBytes( pszValue ) > (LONG) dwLength )
lstrcpy( pszValue, pszBuffer + dwLength );
else
lstrcpy( pszValue, _T( "" ) );
// release the memory allocated
__free( pszBuffer );
}
// ***************************************************************************
// Routine Description:
// Displays the arrData in Tabular form.
//
// Arguments:
// [ in ] fp : Output Device
// [ in ] dwColumns : no. of columns
// [ in ] pColumns : Header strings
// [ in ] dwFlags : flags
// [ in ] arrData : data to be shown
//
// Return Value:
// NONE
//
// ***************************************************************************
VOID __ShowAsTable( FILE* fp, DWORD dwColumns,
PTCOLUMNS pColumns, DWORD dwFlags, TARRAY arrData )
{
// local variables
DWORD dwCount = 0; // holds the count of the records
DWORD i = 0, j = 0, k = 0; // looping variables
DWORD dwColumn = 0;
LONG lLastColumn = 0;
DWORD dwMultiLineColumns = 0;
BOOL bNeedSpace = FALSE;
BOOL bPadLeft = FALSE;
TARRAY arrRecord = NULL;
TARRAY arrMultiLine = NULL;
LPCTSTR pszData = NULL;
LPCTSTR pszSeperator = NULL;
__STRING_4096 szValue = NULL_STRING; // custom value formatter
// constants
const DWORD cdwColumn = 0;
const DWORD cdwSeperator = 1;
const DWORD cdwData = 2;
// create an multi-line data display helper array
arrMultiLine = CreateDynamicArray();
if ( arrMultiLine == NULL )
{
SetLastError( E_OUTOFMEMORY );
SaveLastError();
return;
}
// check whether header has to be displayed or not
if ( ! ( dwFlags & SR_NOHEADER ) )
{
//
// header needs to be displayed
// traverse thru the column headers and display
bNeedSpace = FALSE;
for ( i = 0; i < dwColumns; i++ )
{
// check whether user wants to display this column or not
if ( pColumns[ i ].dwFlags & SR_HIDECOLUMN )
continue; // user doesn't want this column to be displayed .. skip
// determine the padding direction
bPadLeft = FALSE;
if ( pColumns[ i ].dwFlags & SR_ALIGN_LEFT )
bPadLeft = TRUE;
else
{
switch( pColumns[ i ].dwFlags & SR_TYPE_MASK )
{
case SR_TYPE_NUMERIC:
case SR_TYPE_FLOAT:
case SR_TYPE_DOUBLE:
bPadLeft = TRUE;
break;
}
}
// check if column header seperator is needed or not and based on that show
if ( bNeedSpace == TRUE )
{
// show space as column header seperator
DISPLAY_MESSAGE( fp, _T( " " ) );
}
// print the column heading
// NOTE: column will be displayed either by expanding or shrinking
// based on the length of the column heading as well as width of the column
FORMAT_STRING_EX( szValue, _T( "%s" ),
pColumns[ i ].szColumn, pColumns[ i ].dwWidth, bPadLeft );
DISPLAY_MESSAGE( fp, szValue ); // column heading
// inform that from next time onward display column header separator
bNeedSpace = TRUE;
}
// display the new line character ... seperation b/w headings and separator line
DISPLAY_MESSAGE( fp, _T( "\n" ) );
// display the seperator chars under each column header
bNeedSpace = FALSE;
for ( i = 0; i < dwColumns; i++ )
{
// check whether user wants to display this column or not
if ( pColumns[ i ].dwFlags & SR_HIDECOLUMN )
continue; // user doesn't want this column to be displayed .. skip
// check if column header seperator is needed or not and based on that show
if ( bNeedSpace == TRUE )
{
// show space as column header seperator
DISPLAY_MESSAGE( fp, _T( " " ) );
}
// display seperator based on the required column width
DISPLAY_MESSAGE( fp, Replicate( szValue, _T( "=" ), pColumns[ i ].dwWidth ) );
// inform that from next time onward display column header separator
bNeedSpace = TRUE;
}
// display the new line character ... seperation b/w headings and actual data
DISPLAY_MESSAGE( fp, _T( "\n" ) );
}
//
// start displaying
// get the total no. of records available
dwCount = DynArrayGetCount( arrData );
// traverse thru the records one-by-one
for( i = 0; i < dwCount; i++ )
{
// clear the existing value
lstrcpy( szValue, NULL_STRING );
// get the pointer to the current record
arrRecord = DynArrayItem( arrData, i );
if ( arrRecord == NULL )
continue;
// traverse thru the columns and display the values
bNeedSpace = FALSE;
for ( j = 0; j < dwColumns; j++ )
{
// sub-local variables used in this loop
DWORD dwTempWidth = 0;
BOOL bTruncation = FALSE;
// check whether user wants to display this column or not
if ( pColumns[ j ].dwFlags & SR_HIDECOLUMN )
continue; // user doesn't want this column to be displayed .. skip
// get the value of the column
// NOTE: CHECK IF USER ASKED NOT TO TRUNCATE THE DATA OR NOT
if ( pColumns[ j ].dwFlags & SR_NO_TRUNCATION )
{
bTruncation = TRUE;
dwTempWidth = pColumns[ j ].dwWidth;
pColumns[ j ].dwWidth = SIZE_OF_ARRAY( szValue );
}
// prepare the value
__GetValue( &pColumns[ j ], j, arrRecord, szValue, _T( ", " ) );
// determine the padding direction
bPadLeft = FALSE;
if ( bTruncation == FALSE )
{
if ( pColumns[ j ].dwFlags & SR_ALIGN_LEFT )
bPadLeft = TRUE;
else
{
switch( pColumns[ j ].dwFlags & SR_TYPE_MASK )
{
case SR_TYPE_NUMERIC:
case SR_TYPE_FLOAT:
case SR_TYPE_DOUBLE:
bPadLeft = TRUE;
break;
}
}
// adjust ...
AdjustStringLength( szValue, pColumns[ j ].dwWidth, bPadLeft );
}
// reset the width of the current column if it is modified
if ( bTruncation == TRUE )
pColumns[ j ].dwWidth = dwTempWidth;
// check if column header seperator is needed or not and based on that show
if ( bNeedSpace == TRUE )
{
// show space as column header seperator
DISPLAY_MESSAGE( fp, _T( " " ) );
}
// now display the value
if ( pColumns[ j ].dwFlags & SR_WORDWRAP )
{
// display the text ( might be partial )
__DisplayTextWrapped( fp, szValue, _T( ", " ), pColumns[ j ].dwWidth );
// check if any info is left to be displayed
if ( StringLengthInBytes( szValue ) != 0 )
{
LONG lIndex = 0;
lIndex = DynArrayAppendRow( arrMultiLine, 3 );
if ( lIndex != -1 )
{
DynArraySetDWORD2( arrMultiLine, lIndex, cdwColumn, j );
DynArraySetString2( arrMultiLine, lIndex, cdwData, szValue, 0 );
DynArraySetString2( arrMultiLine, lIndex, cdwSeperator, _T( ", " ), 0 );
}
}
}
else
{
DISPLAY_MESSAGE( fp, szValue );
}
// inform that from next time onward display column header separator
bNeedSpace = TRUE;
}
// display the new line character ... seperation b/w two record
DISPLAY_MESSAGE( fp, _T( "\n" ) );
// now display the multi-line column values
dwMultiLineColumns = DynArrayGetCount( arrMultiLine );
while( dwMultiLineColumns != 0 )
{
// reset
dwColumn = 0;
lLastColumn = -1;
bNeedSpace = FALSE;
// ...
for( j = 0; j < dwMultiLineColumns; j++ )
{
// ge the column number
dwColumn = DynArrayItemAsDWORD2( arrMultiLine, j, cdwColumn );
// show spaces till the current column from the last column
for( k = lLastColumn + 1; k < dwColumn; k++ )
{
// check whether user wants to display this column or not
if ( pColumns[ k ].dwFlags & SR_HIDECOLUMN )
continue; // user doesn't want this column to be displayed .. skip
// check if column header seperator is needed or not and based on that show
if ( bNeedSpace == TRUE )
{
// show space as column header seperator
DISPLAY_MESSAGE( fp, _T( " " ) );
}
// display seperator based on the required column width
DISPLAY_MESSAGE( fp, Replicate( szValue, _T( " " ), pColumns[ k ].dwWidth ) );
// inform that from next time onward display column header separator
bNeedSpace = TRUE;
}
// update the last column
lLastColumn = dwColumn;
// check if column header seperator is needed or not and based on that show
if ( bNeedSpace == TRUE )
{
// show space as column header seperator
DISPLAY_MESSAGE( fp, _T( " " ) );
}
// get the seperator and data
pszData = DynArrayItemAsString2( arrMultiLine, j, cdwData );
pszSeperator = DynArrayItemAsString2( arrMultiLine, j, cdwSeperator );
if ( pszData == NULL || pszSeperator == NULL )
continue;
// display the information
lstrcpyn( szValue, pszData, SIZE_OF_ARRAY( szValue ) );
__DisplayTextWrapped( fp, szValue, pszSeperator, pColumns[ dwColumn ].dwWidth );
// update the multi-line array with rest of the line
if ( StringLengthInBytes( szValue ) == 0 )
{
// data in this column is completely displayed ... remove it
DynArrayRemove( arrMultiLine, j );
// update the indexes
j--;
dwMultiLineColumns--;
}
else
{
// update the multi-line array with the remaining value
DynArraySetString2( arrMultiLine, j, cdwData, szValue, 0 );
}
}
// display the new line character ... seperation b/w two lines
DISPLAY_MESSAGE( fp, _T( "\n" ) );
}
}
// destroy the array
DestroyDynamicArray( &arrMultiLine );
}
// ***************************************************************************
// Routine Description:
// Displays the in List format
//
// Arguments:
// [ in ] fp : Output Device
// [ in ] dwColumns : no. of columns
// [ in ] pColumns : Header strings
// [ in ] dwFlags : flags
// [ in ] arrData : data to be shown
//
// Return Value:
// NONE
//
// ***************************************************************************
VOID __ShowAsList( FILE* fp, DWORD dwColumns,
PTCOLUMNS pColumns, DWORD dwFlags, TARRAY arrData )
{
// local variables
DWORD dwCount = 0; // holds the count of all records
DWORD i = 0, j = 0; // looping variables
DWORD dwTempWidth = 0;
DWORD dwMaxColumnLen = 0; // holds the length of the which max. among all the columns
LPTSTR pszTemp = NULL;
TARRAY arrRecord = NULL;
__STRING_64 szBuffer = NULL_STRING;
__STRING_4096 szValue = NULL_STRING; // custom value formatter
// find out the max. length among all the column headers
dwMaxColumnLen = 0;
for ( i = 0; i < dwColumns; i++ )
{
if ( dwMaxColumnLen < ( DWORD ) StringLengthInBytes( pColumns[ i ].szColumn ) )
dwMaxColumnLen = StringLengthInBytes( pColumns[ i ].szColumn );
}
//
// start displaying the data
// get the total no. of records available
dwCount = DynArrayGetCount( arrData );
// get the total no. of records available
for( i = 0; i < dwCount; i++ )
{
// get the pointer to the current record
arrRecord = DynArrayItem( arrData, i );
if ( arrRecord == NULL )
continue;
// traverse thru the columns and display the values
for ( j = 0; j < dwColumns; j++)
{
// clear the existing value
lstrcpy( szValue, NULL_STRING );
// check whether user wants to display this column or not
if ( pColumns[ j ].dwFlags & SR_HIDECOLUMN )
continue; // user doesn't want this column to be displayed .. skip
// display the column heading and its value
// ( heading will be displayed based on the max. column length )
FORMAT_STRING_EX( szValue, _T( "%s:" ),
pColumns[ j ].szColumn, dwMaxColumnLen + 2, FALSE );
DISPLAY_MESSAGE( fp, szValue );
// get the value of the column
dwTempWidth = pColumns[ j ].dwWidth; // save the current width
pColumns[ j ].dwWidth = SIZE_OF_ARRAY( szValue ); // change the width
__GetValue( &pColumns[ j ], j, arrRecord, szValue, _T( "\n" ) );
pColumns[ j ].dwWidth = dwTempWidth; // restore the original width
// display the [ list of ] values
pszTemp = _tcstok( szValue, _T( "\n" ) );
while ( pszTemp != NULL )
{
// display the value
DISPLAY_MESSAGE( fp, pszTemp );
pszTemp = _tcstok( NULL, _T( "\n" ) );
if ( pszTemp != NULL )
{
// prepare the next line
FORMAT_STRING_EX( szBuffer, _T( "%s" ), _T( " " ),
dwMaxColumnLen + 2, FALSE );
DISPLAY_MESSAGE( fp, _T( "\n" ) );
DISPLAY_MESSAGE( fp, szBuffer );
}
}
// display the next line character seperation b/w two fields
DISPLAY_MESSAGE( fp, _T( "\n" ) );
}
// display the new line character ... seperation b/w two records
// NOTE: do this only if there are some more records
if ( i + 1 < dwCount )
{
DISPLAY_MESSAGE( fp, _T( "\n" ) );
}
}
}
// ***************************************************************************
// Routine Description:
// Displays the arrData in CSV form.
//
// Arguments:
// [ in ] fp : Output Device
// [ in ] dwColumns : no. of columns
// [ in ] pColumns : Header strings
// [ in ] dwFlags : flags
// [ in ] arrData : data to be shown
//
// Return Value:
// NONE
//
// ***************************************************************************
VOID __ShowAsCSV( FILE* fp, DWORD dwColumns,
PTCOLUMNS pColumns, DWORD dwFlags, TARRAY arrData )
{
// local variables
DWORD dwCount = 0; // holds the count of all records
DWORD i = 0, j = 0; // looping variables
DWORD dwTempWidth = 0;
BOOL bNeedComma = FALSE;
TARRAY arrRecord = NULL;
__STRING_4096 szValue = NULL_STRING;
// check whether header has to be displayed or not
if ( ! ( dwFlags & SR_NOHEADER ) )
{
//
// header needs to be displayed
// first display the columns ... with comma seperated
bNeedComma = FALSE;
for ( i = 0; i < dwColumns; i++ )
{
// check whether user wants to display this column or not
if ( pColumns[ i ].dwFlags & SR_HIDECOLUMN )
continue; // user doesn't want this column to be displayed .. skip
// check whether we need to display ',' or not and then display
if ( bNeedComma == TRUE )
{
// ',' has to be displayed
DISPLAY_MESSAGE( fp, _T( "," ) );
}
// display the column heading
DISPLAY_MESSAGE1( fp, szValue, _T( "\"%s\"" ), pColumns[ i ].szColumn );
// inform that from next time onwards we need to display comma before data
bNeedComma = TRUE;
}
// new line character
DISPLAY_MESSAGE( fp, _T( "\n" ) );
}
//
// start displaying the data
// get the total no. of records available
dwCount = DynArrayGetCount( arrData );
// get the total no. of records available
for( i = 0; i < dwCount; i++ )
{
// get the pointer to the current record
arrRecord = DynArrayItem( arrData, i );
if ( arrRecord == NULL )
continue;
// traverse thru the columns and display the values
bNeedComma = FALSE;
for ( j = 0; j < dwColumns; j++ )
{
// clear the existing value
lstrcpy( szValue, NULL_STRING );
// check whether user wants to display this column or not
if ( pColumns[ j ].dwFlags & SR_HIDECOLUMN )
continue; // user doesn't want this column to be displayed .. skip
// get the value of the column
dwTempWidth = pColumns[ j ].dwWidth; // save the current width
pColumns[ j ].dwWidth = SIZE_OF_ARRAY( szValue ); // change the width
__GetValue( &pColumns[ j ], j, arrRecord, szValue, _T( "," ) );
pColumns[ j ].dwWidth = dwTempWidth; // restore the original width
// check whether we need to display ',' or not and then display
if ( bNeedComma == TRUE )
{
// ',' has to be displayed
DISPLAY_MESSAGE( fp, _T( "," ) );
}
// print the value
DISPLAY_MESSAGE( fp, _T( "\"" ) );
DISPLAY_MESSAGE( fp, szValue );
DISPLAY_MESSAGE( fp, _T( "\"" ) );
// inform that from next time onwards we need to display comma before data
bNeedComma = TRUE;
}
// new line character
DISPLAY_MESSAGE( fp, _T( "\n" ) );
}
}
//
// public functions ... exposed to external world
//
// ***************************************************************************
// Routine Description:
//
// Arguments:
//
// Return Value:
//
// ***************************************************************************
VOID ShowResults( DWORD dwColumns, PTCOLUMNS pColumns, DWORD dwFlags, TARRAY arrData )
{
// just call the main function ... with stdout
ShowResults2( stdout, dwColumns, pColumns, dwFlags, arrData );
}
// ***************************************************************************
// Routine Description:
// Show the resuls (arrData) on the screen.
//
// Arguments:
// [ in ] dwColumns : No. of Columns to be shown
// [ in ] pColumns : Columns header
// [ in ] dwFlags : Required format
// [ in ] arrData : Data to be displayed.
//
// Return Value:
// NONE
//
// ***************************************************************************
VOID ShowResults2( FILE* fp, DWORD dwColumns, PTCOLUMNS pColumns, DWORD dwFlags, TARRAY arrData )
{
// local variables
//
// Display the information in the format specified
//
switch( dwFlags & SR_FORMAT_MASK )
{
case SR_FORMAT_TABLE:
{
// show the data in table format
__ShowAsTable( fp, dwColumns, pColumns, dwFlags, arrData );
// switch case completed
break;
}
case SR_FORMAT_LIST:
{
// show the data in table format
__ShowAsList( fp, dwColumns, pColumns, dwFlags, arrData );
// switch case completed
break;
}
case SR_FORMAT_CSV:
{
// show the data in table format
__ShowAsCSV( fp, dwColumns, pColumns, dwFlags, arrData );
// switch case completed
break;
}
default:
{
// invalid format requested by the user
break;
}
}
// flush the memory onto the file buffer
fflush( fp );
}