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

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

				parse_options.c

Purpose:
	Parse options which require connection to X server: geometry string,
	font name,  cursor name and  color specifications.  These  arguments
	were available before, but connection to X server was required prior
	to parsing.

Input:
	(1) Pointer to GUIS structure, where data will be stored.
	(2) Pointer to ConfigS structure, with configuration data.

Output:
	(1) Some data stored to GUIS structure.
	(2) Return value.

Return value:
	(1) Positive on success.
	(2) Negative on failure.

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

#include <stdio.h>

#include <string.h>

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

#include <X11/cursorfont.h>

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

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

void		ErrorMessage_ (char *, char *, char *,
			       char *, char *, char *, char *);
FILE		*CreateLogFile_ (char *);
int		LoadFont_ (WindowS *, Display *, char *);
Cursor		PrepareCursor_ (GUIS *, char *);
int		ParseColor_ (RGBS *, unsigned long *, GUIS *, char *, char *);

/*======parse the remaining options:=========================================*/

int ParseOptions_ (GUIS *guiSP, ConfigS *configSP)
{
size_t		rgb_struct_size;
int		flags;
int		x0, y0;
unsigned int	wx, wy;
RGBS		rgbS;
int		n;
unsigned long	dummyID;

/* The size of RGBS structure: */
rgb_struct_size = sizeof (RGBS);

/* Create (open) the log file, if requested: */
if (configSP->log_fileF)
	{
	configSP->log_fileP = CreateLogFile_ (configSP->log_file_nameA);
	if (configSP->log_fileP == NULL)
		{
		ErrorMessage_ ("garlic", "ParseArgs_",
				configSP->log_file_nameA,
				"Unable to create the log file!\n",
				"", "", "");
		configSP->log_fileF = 0;
		return -1;
		}
	}

/* Main window geometry: */

/** If default geometry should be used: **/
if (strstr (configSP->geometryA, "default"))
	{
	guiSP->main_winS.x0     = configSP->main_margin_left;
	guiSP->main_winS.y0     = configSP->main_margin_top;
	n = (int) guiSP->screen_width - (int) configSP->main_margin_left -
	    (int) configSP->main_margin_right;
	if (n >= 0) guiSP->main_winS.width  = (unsigned int) n;
	n = (int) guiSP->screen_height - (int) configSP->main_margin_top -
	    (int) configSP->main_margin_bottom;
	if (n >= 0) guiSP->main_winS.height = (int) n;
	}

/** If geometry string was specified through **/
/** .garlicrc  file or through command line: **/
else
	{
	/*** Parse geometry string: ***/
	flags = XParseGeometry (configSP->geometryA, &x0, &y0, &wx, &wy);

	/*** Main window width: ***/
	if (WidthValue & flags) guiSP->main_winS.width = wx;

	/*** Main window height: ***/
	if (HeightValue & flags) guiSP->main_winS.height = wy;

	/*** Main window x offset: ***/
	if (XValue & flags)
		{
		if ((XNegative & flags) == 0) guiSP->main_winS.x0 = x0;
		else guiSP->main_winS.x0 = guiSP->screen_width -
					   guiSP->main_winS.width + x0;
		}

	/*** Main window y offset: ***/
	if (YValue & flags)
        	{
        	if ((YNegative & flags) == 0) guiSP->main_winS.y0 = y0;
        	else guiSP->main_winS.y0 = guiSP->screen_height -
					   guiSP->main_winS.height + y0;
        	}
	}

/* Main window background color: */
ParseColor_ (&guiSP->main_winS.bg_rgbS, &guiSP->main_winS.bg_colorID,
	     guiSP, configSP->bg_colorA, "black");

/* Main window foreground color: */
ParseColor_ (&guiSP->main_winS.fg_rgbS, &guiSP->main_winS.fg_colorID,
	     guiSP, configSP->fg_colorA, "white");

/* Text background color: */
ParseColor_ (&guiSP->input_winS.bg_rgbS, &guiSP->input_winS.bg_colorID,
	     guiSP, configSP->text_bg_colorA, "black");

/** Don't forget the output window, it uses the same background color: **/
memcpy (&guiSP->output_winS.bg_rgbS,
	&guiSP->input_winS.bg_rgbS, rgb_struct_size);
guiSP->output_winS.bg_colorID = guiSP->input_winS.bg_colorID;

/* Text foreground color: */
ParseColor_ (&guiSP->input_winS.fg_rgbS, &guiSP->input_winS.fg_colorID,
             guiSP, configSP->text_fg_colorA, "white");

/** The same color is used for output window and control window: **/
memcpy (&guiSP->output_winS.fg_rgbS,
	&guiSP->input_winS.fg_rgbS, rgb_struct_size);
guiSP->output_winS.fg_colorID  = guiSP->input_winS.fg_colorID;
guiSP->control_winS.fg_colorID = guiSP->input_winS.fg_colorID;

/* Default colors for atoms and bonds: */
for (n = 0; n < MAXCOLORSURFACES; n++)
	{
	/** Left color: **/
	ParseColor_ (&rgbS, &dummyID,
		     guiSP, configSP->left_colorAA[n], "white");
	configSP->left_rgbSA[n].red   = rgbS.red;
	configSP->left_rgbSA[n].green = rgbS.green;
	configSP->left_rgbSA[n].blue  = rgbS.blue;

	/** Middle color: **/
	ParseColor_ (&rgbS, &dummyID,
		     guiSP, configSP->middle_colorAA[n], "white");
	configSP->middle_rgbSA[n].red   = rgbS.red;
	configSP->middle_rgbSA[n].green = rgbS.green;
	configSP->middle_rgbSA[n].blue  = rgbS.blue;

	/** Right color: **/
	ParseColor_ (&rgbS, &dummyID,
		     guiSP, configSP->right_colorAA[n], "black");
	configSP->right_rgbSA[n].red    = rgbS.red;
	configSP->right_rgbSA[n].green  = rgbS.green;
	configSP->right_rgbSA[n].blue   = rgbS.blue;
	}

/* Prepare main font: */

/** Load font: **/
n = LoadFont_ (&guiSP->main_winS, guiSP->displaySP, configSP->font_nameA);
if (n < 0)
	{
	ErrorMessage_ ("garlic", "ParseArgs_", "",
		"Failed to load font (after five attempts), exiting ...\n",
		"", "", "");
	return -2;
	}

/** Set this font to all GC's: **/
XSetFont(guiSP->displaySP, guiSP->theGCA[0], guiSP->main_winS.fontSP->fid);
XSetFont(guiSP->displaySP, guiSP->theGCA[1], guiSP->main_winS.fontSP->fid);
XSetFont(guiSP->displaySP, guiSP->theGCA[2], guiSP->main_winS.fontSP->fid);
XSetFont(guiSP->displaySP, guiSP->theGCA[3], guiSP->main_winS.fontSP->fid);
XSetFont(guiSP->displaySP, guiSP->theGCA[4], guiSP->main_winS.fontSP->fid);
XSetFont(guiSP->displaySP, guiSP->theGCA[5], guiSP->main_winS.fontSP->fid);
XSetFont(guiSP->displaySP, guiSP->theGCA[6], guiSP->main_winS.fontSP->fid);
XSetFont(guiSP->displaySP, guiSP->theGCA[7], guiSP->main_winS.fontSP->fid);
XSetFont(guiSP->displaySP, guiSP->theGCA[8], guiSP->main_winS.fontSP->fid);
XSetFont(guiSP->displaySP, guiSP->theGCA[9], guiSP->main_winS.fontSP->fid);

/** Initialize font heights: **/
n = guiSP->main_winS.fontSP->ascent + guiSP->main_winS.fontSP->descent;

/*** Main window: ***/
guiSP->main_winS.quarter_font_height   = (n + 3) / 4;
guiSP->main_winS.half_font_height      = (n + 1) / 2;
guiSP->main_winS.font_height           = n;
guiSP->main_winS.text_line_height      = guiSP->main_winS.font_height +
					 guiSP->main_winS.quarter_font_height;

/*** Output window: ***/
guiSP->output_winS.quarter_font_height = guiSP->main_winS.quarter_font_height;
guiSP->output_winS.half_font_height    = guiSP->main_winS.half_font_height;
guiSP->output_winS.font_height         = guiSP->main_winS.font_height;
guiSP->output_winS.text_line_height    = guiSP->main_winS.text_line_height;

/*** Input window: ***/
guiSP->input_winS.quarter_font_height  = guiSP->main_winS.quarter_font_height;
guiSP->input_winS.half_font_height     = guiSP->main_winS.half_font_height;
guiSP->input_winS.font_height          = guiSP->main_winS.font_height;
guiSP->input_winS.text_line_height     = guiSP->main_winS.text_line_height;

/* Prepare main window cursor (hope it will work properly): */
guiSP->main_winS.cursorID = PrepareCursor_ (guiSP, configSP->cursor_nameA);
guiSP->main_winS.cursorF = 1;

/* Control window cursor: */
guiSP->control_winS.cursorID = XCreateFontCursor (guiSP->displaySP, XC_hand2);
guiSP->control_winS.cursorF = 1;

/* Input window cursor: */
guiSP->input_winS.cursorID = XCreateFontCursor (guiSP->displaySP, XC_pencil);
guiSP->input_winS.cursorF = 1;

/* Output window cursor: */
guiSP->output_winS.cursorID = XCreateFontCursor (guiSP->displaySP,
						 XC_X_cursor);
guiSP->output_winS.cursorF = 1;

/* Prepare eighteen auxiliary colors: */
ParseColor_ (&rgbS, &guiSP->black_colorID,
	     guiSP, "black", "black");
ParseColor_ (&rgbS, &guiSP->gray_colorID,
	     guiSP, "gray", "white");
ParseColor_ (&rgbS, &guiSP->dark_gray_colorID,
	     guiSP, "RGB:8888/8888/8888", "white");
ParseColor_ (&rgbS, &guiSP->white_colorID,
	     guiSP, "white", "white");
ParseColor_ (&rgbS, &guiSP->red_colorID,
	     guiSP, "red", "white");
ParseColor_ (&rgbS, &guiSP->dark_red_colorID,
	     guiSP, "RGB:8888/0000/0000", "black");
ParseColor_ (&rgbS, &guiSP->green_colorID,
	     guiSP, "green", "white");
ParseColor_ (&rgbS, &guiSP->dark_green_colorID,
	     guiSP, "RGB:0000/8888/0000", "black");
ParseColor_ (&rgbS, &guiSP->blue_colorID,
	     guiSP, "blue", "white");
ParseColor_ (&rgbS, &guiSP->dark_blue_colorID,
	     guiSP, "RGB:0000/0000/8888", "black");
ParseColor_ (&rgbS, &guiSP->yellow_colorID,
	     guiSP, "yellow", "white");
ParseColor_ (&rgbS, &guiSP->dark_yellow_colorID,
	     guiSP, "RGB:8888/8888/0000", "black");
ParseColor_ (&rgbS, &guiSP->cyan_colorID,
	     guiSP, "cyan", "white");
ParseColor_ (&rgbS, &guiSP->dark_cyan_colorID,
	     guiSP, "RGB:0000/8888/8888", "black");
ParseColor_ (&rgbS, &guiSP->magenta_colorID,
	     guiSP, "magenta", "white");
ParseColor_ (&rgbS, &guiSP->dark_magenta_colorID,
	     guiSP, "RGB:8888/0000/8888", "black");
ParseColor_ (&rgbS, &guiSP->orange_colorID,
	     guiSP, "orange", "white");
ParseColor_ (&rgbS, &guiSP->dark_orange_colorID,
	     guiSP, "RGB:8888/4444/0000", "black");

/* Return positive value on success: */
return 1;
}

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


