//-----------------------------------------------------------------------------
// Copyright © 2003 - Philip Howard - All rights reserved
//
// This program is free software; you can redistribute it and/or
// modify it under the terms of the GNU General Public License
// as published by the Free Software Foundation; either version 2
// of the License, or (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.	 See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program; if not, write to the Free Software
// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
//-----------------------------------------------------------------------------
// package	libh/io
// homepage	http://libh.slashusr.org/
//-----------------------------------------------------------------------------
// author	Philip Howard
// email	libh at ipal dot org
// homepage	http://phil.ipal.org/
//-----------------------------------------------------------------------------
// This file is best viewed using a fixed spaced font such as Courier
// and in a display at least 120 columns wide.
//-----------------------------------------------------------------------------

#include "io_lib.h"

__PROTO_BEGIN__
//-----------------------------------------------------------------------------
// function	put_config_item
//
// purpose	Put a config item (name and data strings) to an output file.
//
// arguments	1 (const char *) pointer to name string
//		2 (size_t) length of name string
//		3 (const char *) pointer to data string
//		4 (size_t) length of name string
//		5 (FILE *) pointer to open file to write to
//
// returns	(int) == -3 : error
//		(int) ==  0 : config item written OK
//-----------------------------------------------------------------------------
#define PUT_CONFIG_NEST_BEGIN	0x0001
#define PUT_CONFIG_NEST_END	0x0002
int
put_config_item (
    const char *	arg_name_ptr
    ,
    size_t		arg_name_len
    ,
    const char *	arg_data_ptr
    ,
    size_t		arg_data_len
    ,
    FILE *		arg_file
    )
__PROTO_END__
{
    static const signed char	control_one	[128]	= {
	'\\', '^', '^', '^', '^', '^', '^','\\','\\','\\','\\','\\','\\','\\', '^', '^',
	 '^', '^', '^', '^', '^', '^', '^', '^', '^', '^', '^','\\', '^', '^', '^', '^',
	   0,   0,'\\',   0,   0,   0,   0,'\\',   0,   0,   0,   0,   0,   0,   0,   0,
	   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
	   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
	   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,'\\',   0,'\\',   0,
	   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
	   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
    };
    static const signed char	control_two	[128]	= {
	 'z', 'a', 'b', 'c', 'd', 'e', 'f', 'a', 'b', 't', 'n', 'v', 'f', 'r', 'n', 'o',
	 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z', 'e','\\', ']', '^', '_',
	   0,   0, '"',   0,   0,   0,   0,'\'',   0,   0,   0,   0,   0,   0,   0,   0,
	   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
	   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
	   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,'\\',   0, '^',   0,
	   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
	   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
    };
    static const signed char	code_tab	[16]	= {
	 '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f'
    };

    const unsigned char *	this_ptr	;
    const unsigned char *	this_end	;
    const unsigned char *	quote_ptr	;

    int				ch		;
    int				state		;


    //-----------------
    // Check arguments.
    //-----------------
    if ( ! arg_file ) arg_file = stdin;
    if ( ! arg_name_ptr || ! arg_data_ptr ) return -3;

    //----------------------------------
    // Determine length if not provided.
    //----------------------------------
    if ( arg_name_len == ~ (size_t) 0 ) arg_name_len = strlen( arg_name_ptr );
    if ( arg_data_len == ~ (size_t) 0 ) arg_data_len = strlen( arg_data_ptr );

    //----------------------------
    // Loop through name and data.
    //----------------------------
    for ( state = 1; state <= 2; ++ state ) {

	//-------------------------------
	// Determine which string to use.
	//-------------------------------
	if ( state == 1 ) {
	    if ( ! ( this_ptr = (const unsigned char *) arg_name_ptr ) ) break;
	    this_end = this_ptr + arg_name_len;
	} else if ( state == 2 ) {
	    if ( ! ( this_ptr = (const unsigned char *) arg_data_ptr ) ) break;
	    this_end = this_ptr + arg_data_len;
	    fprintf( arg_file, " = " );
	} else break;

	//---------------------------------------------
	// Determine if this string needs to be quoted.
	// If 2 spaces in a row, then do quoted.
	//---------------------------------------------
	quote_ptr = this_ptr;
	ch = -1;
	while ( quote_ptr < this_end ) {
	    if ( ch == ' ' && ch == * quote_ptr ) break;
	    ch = * quote_ptr;
	    ++ quote_ptr;
	}

	//------------------------------------
	// If quoted, then output first quote.
	//------------------------------------
	if ( quote_ptr < this_end ) {
	    fputc( '"', arg_file );
	}

	//-------------------
	// Output the string.
	//-------------------
	while ( this_ptr < this_end ) {
	    ch = * this_ptr;
	    if ( ch < 127 ) {
		if ( control_one[ch] != 0 ) {
		    fputc( control_one[ch], arg_file );
		    fputc( control_two[ch], arg_file );
		} else {
		    fputc( ch, arg_file );
		}
	    } else {
		fputc( '%', arg_file );
		fputc( code_tab[ ( ch >> 4 ) & 0xf ], arg_file );
		fputc( code_tab[ ch & 0xf ], arg_file );
	    }
	    ++ this_ptr;
	}

	//-----------------------------------
	// If quoted, then output last quote.
	//-----------------------------------
	if ( quote_ptr < this_end ) {
	    fputc( '"', arg_file );
	}

    }

    //--------------------
    // Output end of line.
    //--------------------
    fputc( '\n', arg_file );

    return 0;
}

