/* Copyright (C) 2000-2002 Damir Zucic */

/*=============================================================================

				extract_args.c

Purpose:
	Extract command line arguments. Xlib resource manager could be used,
	but I prefer my own function.  Parsing will be done after connecting
	to X server, because color specifications  cannot  be parsed  before
	connection. Geometry could be parsed  now, but it is left for later.

Input:
	(1) Pointer to ConfigS structure, where config. data will be stored.
	(2) Pointer to GUIS structure, where display name will be stored.
	(3) Pointer to the input molecular file name.
	(4) Number of command line arguments.
	(5) Command line arguments.

Output:
	(1) Some data stored to ConfigS structure.
	(2) Display name stored to GUIS structure.
	(3) Input molecular file name stored.
	(4) Return value.

Return value:
	(1) Number of arguments on success (zero or positive).
	(2) Negative on failure (one or more arguments not recognized).

========includes:============================================================*/

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <X11/Xlib.h>
#include <X11/Xutil.h>
#include <X11/Xos.h>
#include <X11/Xatom.h>

#include "defines.h"
#include "typedefs.h"

/*======function prototypes:=================================================*/

void		ErrorMessage_ (char *, char *, char *,
			       char *, char *, char *, char *);
int		ExtractInteger_ (char *);
FILE		*OpenFileForReading_ (char *);
int		ExtractIndex_ (char *);

/*======extract command line arguments:======================================*/

int ExtractArgs_ (ConfigS *configSP, GUIS *guiSP, char *mol_file_nameP,
		  int argc, char **argv)
{
int		args_foundN = 0;
int		i = 1, j, n;
FILE		*fileP;
int		surfaceI;

/* Initialize the input file name: */
*mol_file_nameP = '\0';

/* Initialize the log file name, flag and pointer: */
configSP->log_file_nameA[0] = '\0';
configSP->log_fileF = 0;
configSP->log_fileP = NULL;

/* Set the initial pointer to display name: */
guiSP->display_nameP = NULL;

/* Initialize the print_configF: */
configSP->print_configF = 0;

/* Initialize print_cursor_namesF: */
configSP->print_cursor_namesF = 0;

/* Scan all command line arguments and extract options: */
while ((j = i++) < argc)
	{

/*......options specific for garlic:.........................................*/

	/* Log file name: */
	if (strcmp (*(argv + j), "-log") == 0)
		{
		/*** Enough arguments? ***/
		if (i >= argc)
                        {
                        ErrorMessage_ ("garlic", "ExtractArgs_", "",
                                "Log file name missing!\n", "", "", "");
                        return -1;
                        }

		/*** Copy log file name: ***/
		n = sizeof (configSP->log_file_nameA) - 1;
		strncpy (configSP->log_file_nameA, argv[i], n);
		*(configSP->log_file_nameA + n) = '\0';

		/*** Set flag to indicate that log file should be used: ***/
		configSP->log_fileF = 1;

		/*** Update index and number of arguments: ***/
		i++;
		args_foundN++;
		continue;
		}

	/** Stereo flag (display stereo or mono image): **/
	if (strcmp (*(argv + j), "-stereo") == 0)
		{
		configSP->stereoF = 1;

		/*** Update the number of arguments; do not update i: ***/
		args_foundN++;
		continue;
		}

	/** Slab mode index (see typedefs.h for available modes): **/
	if (strcmp (*(argv + j), "-slab") == 0)
		{
		/*** Enough arguments? ***/
		if (i >= argc)
			{
			ErrorMessage_ ("garlic", "ExtractArgs_", "",
				"Slab mode specification missing!\n",
				"", "", "");
			return -2;
			}

		/*** Recognize the mode: ***/
		if (strncmp (argv[i], "off", 20) == 0)
			configSP->default_slab_modeI = 0;
		else if (strncmp (argv[i], "planar", 20) == 0)
			configSP->default_slab_modeI = 1;
		else if (strncmp (argv[i], "sphere", 20) == 0)
			configSP->default_slab_modeI = 2;
		else if (strncmp (argv[i], "half-sphere", 20) == 0)
			configSP->default_slab_modeI = 3;
		else if (strncmp (argv[i], "cylinder", 20) == 0)
			configSP->default_slab_modeI = 4;
		else if (strncmp (argv[i], "half-cylinder", 20) == 0)
			configSP->default_slab_modeI = 5;
		else
			{
			ErrorMessage_ ("garlic", "ExtractArgs_", "",
				"Slab mode \"", argv[i],
				"\" not supported.\n", "");
			return -3;
			}

		/*** Update index and the number of arguments: ***/
		i++;
		args_foundN++;
		continue;
		}

        /** Color fading mode index (see typedefs.h for available modes): **/
        if (strcmp (*(argv + j), "-fading") == 0)
                {
                /*** Enough arguments? ***/
                if (i >= argc)
                        {
                        ErrorMessage_ ("garlic", "ExtractArgs_", "",
                                "Fading mode specification missing!\n",
                                "", "", "");
                        return -4;
                        }
                /*** Recognize the mode: ***/
                if (strncmp (argv[i], "off", 20) == 0)
                        configSP->default_fading_modeI = 0;
                else if (strncmp (argv[i], "planar", 20) == 0)
                        configSP->default_fading_modeI = 1;
                else if (strncmp (argv[i], "sphere", 20) == 0)
                        configSP->default_fading_modeI = 2;
                else if (strncmp (argv[i], "half-sphere", 20) == 0)
                        configSP->default_fading_modeI = 3;
                else if (strncmp (argv[i], "cylinder", 20) == 0)
                        configSP->default_fading_modeI = 4;
                else if (strncmp (argv[i], "half-cylinder", 20) == 0)
                        configSP->default_fading_modeI = 5;
                else
                        {
                        ErrorMessage_ ("garlic", "ExtractArgs_", "",
                                "Fading mode \"", argv[i],
                                "\" not supported.\n", "");
                        return -5;
                        }

                /*** Update index and the number of arguments: ***/
                i++;
                args_foundN++;
                continue;
                }

	/** Default atom drawing style: **/
	if (strcmp (*(argv + j), "-as") == 0)
		{
		/*** Enough arguments? ***/
		if (i >= argc)
			{
			ErrorMessage_ ("garlic", "ExtractArgs_", "",
				       "Atom style specification missing!\n",
				       "", "", "");
			return -6;
			}

		/*** Extract atom style index: ***/
		n = ExtractInteger_ (argv[i]);

		/*** Check it: ***/
		if ((n < 0) || (n > MAXATOMSTYLEI))
			{
			ErrorMessage_ ("garlic", "ExtractArgs_", "",
				       "Bad atom style index!\n",
				       "", "", "");
			return -7;
			}

		/*** Copy the value: ***/
		configSP->default_atom_styleI = n;

		/*** Update index and number of arguments: ***/
		i++;
		args_foundN++;
		continue;
		}

	/** Default bond drawing style: **/
	if (strcmp (*(argv + j), "-bs") == 0)
		{
		/*** Enough arguments? ***/
		if (i >= argc)
			{
			ErrorMessage_ ("garlic", "ExtractArgs_", "",
				       "Bond style specification missing!\n",
				       "", "", "");
			return -8;
			}

		/*** Extract bond style index: ***/
		n = ExtractInteger_ (argv[i]);

		/*** Check it: ***/
		if ((n < 0) || (n > MAXBONDSTYLEI))
			{
			ErrorMessage_ ("garlic", "ExtractArgs_", "",
				       "Bad bond style index!\n",
				       "", "", "");
			return -9;
			}

		/*** Copy the value: ***/
		configSP->default_bond_styleI = n;

		/*** Update index and number of arguments: ***/
		i++;
		args_foundN++;
		continue;
		}

	/** Coordinate system flag: **/
	if (strcmp (*(argv + j), "-nosys") == 0)
		{
		configSP->show_coord_systemF = 0;

		/*** Update the number of arguments; do not update i: ***/
		args_foundN++;
		continue;
		}

	/** Control window flag: **/
	if (strcmp (*(argv + j), "-no-control") == 0)
		{
		configSP->show_control_windowF = 0;

		/*** Update the number of arguments; do no update i: ***/
		args_foundN++;
		continue;
		}

	/** Print (dump) configuration flag: **/
	if ((strcmp (*(argv + j), "-pc") == 0) ||
	    (strcmp (*(argv + j), "-print-config") == 0))
		{
		configSP->print_configF = 1;

		/*** Update the number of arguments; do not update i: ***/
		args_foundN++;
		continue;
		}

	/* Default number of color fading surfaces: */
	if (strcmp (*(argv + j), "-fs") == 0)
		{
                /*** Enough arguments? ***/
                if (i >= argc)
                        {
                        ErrorMessage_ ("garlic", "ExtractArgs_", "",
                                       "Number of fading surfaces missing!\n",
                                       "", "", "");
                        return -10;
                        }

                /*** Extract bond style index: ***/
                n = ExtractInteger_ (argv[i]);

                /*** Check it: ***/
                if ((n <= 0) || (n > MAXCOLORSURFACES))
                        {
                        ErrorMessage_ ("garlic", "ExtractArgs_", "",
                                       "Bad number of fading surfaces!\n",
                                       "", "", "");
                        return -11;
                        }

                /*** Copy the value: ***/
                configSP->default_surfacesN = n;

                /*** Update index and number of arguments: ***/
                i++;
                args_foundN++;
                continue;
		}

        /** Left color for a given surface: **/
        if (strstr (*(argv + j), "-lc") == *(argv + j))
                {
                /*** Enough arguments? ***/
                if (i >= argc)
                        {
                        ErrorMessage_ ("garlic", "ExtractArgs_", "",
                                       "Left color specification missing!\n",
                                       "", "", "");
                        return -12;
                        }

                /*** Extract and check  the surface index: ***/
                /*** (Note that leading minus is skipped!) ***/
                surfaceI = ExtractIndex_ (argv[j] + 1);
                if ((surfaceI < 0) || (surfaceI >= MAXCOLORSURFACES))
                        {
                        ErrorMessage_ ("garlic", "ExtractArgs_", "",
                                       "Bad fading surface index!\n",
                                       "", "", "");
                        return -13;
                        }

                /*** Copy left color specification: ***/
                n = SHORTSTRINGSIZE - 1;
                strncpy (configSP->left_colorAA[surfaceI], argv[i], n);
                configSP->left_colorAA[surfaceI][n] = '\0';

                /*** Update index and number of arguments: ***/
                i++;
                args_foundN++;
                continue;
                }

        /** Middle color for a given surface: **/
        if (strstr (*(argv + j), "-mc") == *(argv + j))
                {
                /*** Enough arguments? ***/
                if (i >= argc)
                        {
                        ErrorMessage_ ("garlic", "ExtractArgs_", "",
                                       "Middle color specification missing!\n",
                                       "", "", "");
                        return -14;
                        }

                /*** Extract and check  the surface index: ***/
                /*** (Note that leading minus is skipped!) ***/
                surfaceI = ExtractIndex_ (argv[j] + 1);
                if ((surfaceI < 0) || (surfaceI >= MAXCOLORSURFACES))
                        {
                        ErrorMessage_ ("garlic", "ExtractArgs_", "",
                                       "Bad fading surface index!\n",
                                       "", "", "");
                        return -15;
                        }

                /*** Copy middle color specification: ***/
                n = SHORTSTRINGSIZE - 1;
                strncpy (configSP->middle_colorAA[surfaceI], argv[i], n);
                configSP->middle_colorAA[surfaceI][n] = '\0';

                /*** Update index and number of arguments: ***/
                i++;
                args_foundN++;
                continue;
                }

        /** Right color for a given surface: **/
        if (strstr (*(argv + j), "-rc") == *(argv + j))
                {
                /*** Enough arguments? ***/
                if (i >= argc)
                        {
                        ErrorMessage_ ("garlic", "ExtractArgs_", "",
                                       "Right color specification missing!\n",
                                       "", "", "");
                        return -16;
                        }

                /*** Extract and check  the surface index: ***/
                /*** (Note that leading minus is skipped!) ***/
                surfaceI = ExtractIndex_ (argv[j] + 1);
                if ((surfaceI < 0) || (surfaceI >= MAXCOLORSURFACES))
                        {
                        ErrorMessage_ ("garlic", "ExtractArgs_", "",
                                       "Bad fading surface index!\n",
                                       "", "", "");
                        return -17;
                        }

                /*** Copy right color specification: ***/
                n = SHORTSTRINGSIZE - 1;
                strncpy (configSP->right_colorAA[surfaceI], argv[i], n);
                configSP->right_colorAA[surfaceI][n] = '\0';

                /*** Update index and number of arguments: ***/
                i++;
                args_foundN++;
                continue;
                }

/*......X11 options:.........................................................*/

	/** Display name: **/
	if (strcmp (*(argv + j), "-display") == 0)
		{
		/*** Enough arguments? ***/
		if (i >= argc)
			{
			ErrorMessage_ ("garlic", "ExtractArgs_", "",
				"Display name missing!\n", "", "", "");
			return -18;
			}

		/*** Copy display name: ***/
		n = sizeof (guiSP->display_nameA) - 1;
		strncpy (guiSP->display_nameA, argv[i], n);
		*(guiSP->display_nameA + n) = '\0';

		/** Refresh display name pointer: **/
		guiSP->display_nameP = guiSP->display_nameA;

		/*** Update index and the number of arguments: ***/
		i++;
		args_foundN++;
		continue;
		}

	/** Geometry string: **/
	if (strcmp (*(argv + j), "-geometry") == 0)
		{
		/*** Enough arguments? ***/
		if (i >= argc)
			{
			ErrorMessage_ ("garlic", "ExtractArgs_", "",
				"Geometry string missing!\n", "", "", "");
			return -19;
			}

		/*** Copy geometry string: ***/
		n = sizeof (configSP->geometryA) - 1;
		strncpy (configSP->geometryA, argv[i], n);
		*(configSP->geometryA + n) = '\0';

		/*** Update index and number of arguments: ***/
		i++;
		args_foundN++;
		continue;
		}

	/** Main window background color: **/
	if (strcmp (*(argv + j), "-bg") == 0)
		{
		/*** Enough arguments? ***/
		if (i >= argc)
			{
			ErrorMessage_ ("garlic", "ExtractArgs_", "",
				"Background color specification missing!\n",
				"", "", "");
			return -20;
			}

		/*** Copy background color specification: ***/
		n = sizeof (configSP->bg_colorA) - 1;
		strncpy (configSP->bg_colorA, argv[i], n);
		*(configSP->bg_colorA + n) = '\0';

		/*** Update index and number of arguments: ***/
		i++;
		args_foundN++;
		continue;
		}

	/** Main window foreground color: **/
	if (strcmp (*(argv + j), "-fg") == 0)
		{
		/*** Enough arguments? ***/
		if (i >= argc)
			{
			ErrorMessage_ ("garlic", "ExtractArgs_", "",
				"Foreground color specification missing!\n",
				"", "", "");
			return -21;
			}

		/*** Copy foreground color specification: ***/
		n = sizeof (configSP->fg_colorA) - 1;
		strncpy (configSP->fg_colorA, argv[i], n);
		*(configSP->fg_colorA + n) = '\0';

		/*** Update index and number of arguments: ***/
		i++;
		args_foundN++;
		continue;
		}

	/** Font name: **/
	if (strcmp (*(argv + j), "-fn") == 0)
		{
		/*** Enough arguments? ***/
		if (i >= argc)
			{
			ErrorMessage_ ("garlic", "ExtractArgs_", "",
				"Font name missing!\n", "", "", "");
			return -22;
			}

                /*** Copy font name: ***/
                n = sizeof (configSP->font_nameA) - 1;
                strncpy (configSP->font_nameA, argv[i], n);
                *(configSP->font_nameA + n) = '\0';

                /*** Update index and number of arguments: ***/
                i++;
		args_foundN++;
                continue;
                }

	/** Input window background color: **/
	if (strcmp (*(argv + j), "-tbg") == 0)
		{
		/*** Enough arguments? ***/
		if (i >= argc)
			{
			ErrorMessage_ ("garlic", "ExtractArgs_", "",
				"Text background color specification",
				" missing!\n", "", "");
			return -23;
			}

		/*** Copy text background color specification: ***/
		n = sizeof (configSP->text_bg_colorA) - 1;
		strncpy (configSP->text_bg_colorA, argv[i], n);
		*(configSP->text_bg_colorA + n) = '\0';

		/*** Update index and number of arguments: ***/
		i++;
		args_foundN++;
		continue;
		}

	/** Text color: **/
	if (strcmp (*(argv + j), "-tfg") == 0)
		{
		/*** Enough arguments? ***/
		if (i >= argc)
			{
			ErrorMessage_ ("garlic", "ExtractArgs_", "",
				"Text color specification missing!\n",
				"", "", "");
			return -24;
			}

		/*** Copy text color specification: ***/
		n = sizeof (configSP->text_fg_colorA) - 1;
		strncpy (configSP->text_fg_colorA, argv[i], n);
		*(configSP->text_fg_colorA + n) = '\0';

		/*** Update index and number of arguments: ***/
		i++;
		args_foundN++;
		continue;
		}

	/* Cursor name: */
	if (strcmp (*(argv + j), "-cursor") == 0)
		{
		/*** Enough arguments? ***/
		if (i >= argc)
			{
			ErrorMessage_ ("garlic", "ExtractArgs_", "",
				"Cursor name missing!\n", "", "", "");
			return -25;
			}

		/*** Copy cursor name: ***/
		n = sizeof (configSP->cursor_nameA) - 1;
		strncpy (configSP->cursor_nameA, argv[i], n);
		*(configSP->cursor_nameA + n) = '\0';

		/*** Update index and number of arguments: ***/
		i++;
		args_foundN++;
		continue;
		}

	/** Print cursor names flag: **/
	if (strcmp (*(argv + j), "-pcn") == 0)
		{
		configSP->print_cursor_namesF = 1;

		/*** Update the number of arguments; do not update i: ***/
		args_foundN++;
		continue;
		}

/*......file name:...........................................................*/

	/* If argument was not recognized up to here, check is it file name: */
	if ((fileP = OpenFileForReading_ (argv[j])) != NULL)
		{
		fclose (fileP);
		n = STRINGSIZE - 1;
		strncpy (mol_file_nameP, argv[j], n);
		args_foundN++;
		continue;
		}

/*......argument not recognized:.............................................*/

	/* If this point is reached, at least one argument is bad: */
	ErrorMessage_ ("garlic", "ExtractArgs_", "",
		"Command line argument \"", argv[j],
		"\" not recognized, exiting ...\n", "");
	return -26;
	}

/*...........................................................................*/

return args_foundN;
}

/*===========================================================================*/


