/* OPLIST.C - create an html <select> option list
 * Copyright 1998-2002 Stephen C. Grubb  (quisp.sourceforge.net) .
 * This code is covered under the GNU General Public License (GPL);
 * see the file ./Copyright for details. */

#include <ctype.h>
extern int atoi();

/* OPLIST - make an html option list.  

   This routine will be called multiple times with successive lines.
   It will build a <select> option list and write it to outfp.
   Caller should supply the opening <select > tag before invoking #optionlist,
   and closing </select> tag at the end.

   When </select> is encountered, this function returns SINTERP_END_BUT_PRINT;
    the caller should then write the line.

   Usage:

   #optionlist   [selected=commalist]  [options=commalist]  [maxlen=nn]  [always_selected]  [display_only]
   #selected
     value1
     value2
     ..etc..
   #options
     value1 	label words 1
     value2 	label words 2
   </select>

   Selected item(s) may be specified as a commalist or by specifying "#selected" followed by rows 
   each containing a value (only).
	
   Option(s) may be specified as a commalist or by specifying "#options" followed by rows each
   containing a value followed by a label string.  The value is taken as the first whitespace-delimited
   token on the line; the label is taken as the rest of the line.  If options are given as a commalist
   then the value and label are the same.
*/
#include "tdhkit.h"
#include "quispcgi.h"

static int inop = 0;
static int insel = 0;
static char slist[1024] = "";
static int ssize = 0;
static int maxlen = 95;
static int always_selected = 0;
static int display_only = 0;
static int longform = 1;
static int hidenulls = 0;

int
oplist( outfp, buf, ss )
FILE *outfp;
char *buf;
struct sinterpstate *ss;
{
int i, ix;
char tok[DATAMAXLEN], tok2[DATAMAXLEN];
int nullflag;

ix = 0;
strcpy( tok, GL_getok( buf, &ix ));

if( strcmp( tok, "#optionlist" )==0 ) {    /* first line */
	inop = 0;
	insel = 0;
	maxlen = 95;
	always_selected = 0;
	display_only = 0;
	hidenulls = 0;
	strcpy( slist, "" );
	ssize = 0;
	while( 1 ) {
		strcpy( tok, GL_getok( buf, &ix ));
		if( tok[0] == '\0' ) break;
		else if( strncmp( tok, "maxlen=", 7 ) ==0 ) maxlen = atoi( &tok[7] );
		else if( strncmp( tok, "always_selected", 15 ) ==0 ) always_selected = 1;
		else if( strncmp( tok, "display_only", 12 ) ==0 ) display_only = 1;
		else if( strncmp( tok, "hidenulls", 9 ) ==0 ) hidenulls = 1;
		else if( strncmp( tok, "selected=", 9 ) ==0 ) strcpy( slist, &tok[9] );
		else if( strncmp( tok, "options=", 8 ) ==0 ) {
			int ixx;
			/* options were specified as a list.. process them now.. */
			for( i = 0; slist[i] != '\0'; i++ ) if( slist[i] == ',' ) slist[i] = ' ';
			ixx = 8;
			while( 1 ) {
				GL_getseg( tok2, tok, &ixx, "," );
				if( tok2[0] == '\0' ) break;
				if( stricmp( tok2, DBNULL )==0 ) nullflag = 1;
				else nullflag = 0;
				if( GL_smember( tok2, slist ) || 
				   ( slist[0] == '\0' && always_selected ) || 
				   (slist[0] == '\0' && nullflag )) {
					if( display_only ) fprintf( outfp, "%s<br>\n", &buf[ix] );
					else fprintf( outfp, "<option value=\"%s\" selected>%s\n", tok2, (nullflag)?"":tok2 );
					}
				else if( !display_only ) fprintf( outfp, "<option value=\"%s\">%s\n", tok2, (nullflag)?"":tok2 );
				always_selected = 0;
				}
			longform = 0;
			}	
		}

	if( longform && !hidenulls ) ss->nullrep = 2;  /* in case a shell or sql retrieval will be used to fill list(s),
						  ensure that null fields don't get converted to "", as this will
						  mess us up here.. */

	return( SINTERP_END );
	}

else if( strnicmp( tok, "</select", 8 )==0 || strcmp( tok, "#endlist" )==0 ) {
	/* this means we're done.. */
	if( longform && !hidenulls ) ss->nullrep = 1;  /* restore */
        if( display_only ) { fprintf( outfp, "\n\n" );  return( SINTERP_END ); }
	else return( SINTERP_END_BUT_PRINT );
	}

else if( strncmp( tok, "#selected", 9 )==0 ) { insel = 1; return( SINTERP_END ); }

else if( strncmp( tok, "#options", 8 )==0 ) { inop = 1; return( SINTERP_END ); }

else if( insel ) {
	/* #selected: given as rows.. get next row.. */
	sscanf( buf, "%s", tok );
	strcpy( &slist[ssize], tok );
	ssize+= strlen( tok );
	strcpy( &slist[ssize], "," );
	ssize++;
	slist[ssize] = '\0';
	return( SINTERP_END );
	}

else if( inop ) {
	/* #options: given as rows.. get next row.. */
	for( i = 0; slist[i] != '\0'; i++ ) if( slist[i] == ',' ) slist[i] = ' ';
	ix = 0;
	strcpy( tok, GL_getok( buf, &ix ));
	while( isspace( (int) buf[ix++] ));
	ix--;
	if( stricmp( tok, DBNULL )==0 ) nullflag = 1;
	else nullflag = 0;
	if( GL_smember( tok, slist ) || 
	    (slist[0] == '\0' && always_selected ) ||
	    (slist[0] == '\0' && nullflag )) {
		if( display_only ) fprintf( outfp, "%s<br>\n", &buf[ix] );
		else fprintf( outfp, "<option value=\"%s\" selected>%s", tok, &buf[ix] );
		}
	else if( !display_only ) fprintf( outfp, "<option value=\"%s\">%s", tok, &buf[ix] );
	always_selected = 0;
	return( SINTERP_END );
	}

return( SINTERP_END ); /* (never) */
}
