/* Copyright (C) 2000 Damir Zucic */

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

				docking_window.c

Purpose:
	Prepare docking window,  docking icon and  storage required for
	docking.

Input:
	(1) Pointer to RuntimeS structure.
	(2) Pointer to GUIS structure.

Output:
	(1) Docking window created or mapped.

Return value:
	(1) Positive on success.
	(2) Zero if docking window was created before.
	(3) Negative on failure.

Notes:
	(1) The index of exposed atom is of the type int, though size_t
	    is used elsewhere. The reason is that int may have negative
	    value,  while size_t is unsigned on many systems.  Negative
	    values are used  to signal that data stored  to a given box
	    are obsolete.

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

#include <stdio.h>

#include <string.h>
#include <stdlib.h>

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

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

#include "docking.xpm"

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

void		ErrorMessage_ (char *, char *, char *,
			       char *, char *, char *, char *);
int             MakePixmap_ (WindowS *, GUIS *, char **);

/*======prepare docking window:==============================================*/

int PrepareDockingWindow_ (RuntimeS *runtimeSP, GUIS *guiSP)
{
XSetWindowAttributes	docking_attribS;
unsigned long		docking_value_mask;
XSetWindowAttributes	docking_icon_attribS;
unsigned long		docking_icon_value_mask;
static char		docking_win_titleA[SHORTSTRINGSIZE];
char			*docking_win_titleP;
static char		docking_icon_titleA[SHORTSTRINGSIZE];
char			*docking_icon_titleP;
XTextProperty		docking_win_titleS, docking_icon_titleS;
XSizeHints		*size_hintsSP;
XWMHints		*wm_hintsSP;
XClassHint		*class_hintsSP;
long			event_mask;
int			width;
size_t			elementsN, int_size;
size_t			exposed_polar_size;

/* If docking window was created before, just make it visible: */
if (guiSP->docking_window_createdF)
	{
	if (guiSP->docking_window_mappedF == 0)
		{
		XMapWindow (guiSP->displaySP, guiSP->docking_winS.ID);
		}
	return 0;
	}

/*------create docking window:-----------------------------------------------*/

/* Docking window width and height: */
guiSP->docking_winS.width  = guiSP->screen_width / 3;
guiSP->docking_winS.height = guiSP->docking_winS.width;

/* Position of the top left corner: */
guiSP->docking_winS.x0 = (int) guiSP->docking_winS.width  - 20;
guiSP->docking_winS.y0 = (int) guiSP->docking_winS.height - 20;

/* Set window attributes: */
docking_attribS.border_pixel = guiSP->main_winS.fg_colorID;
docking_attribS.background_pixel = guiSP->main_winS.bg_colorID;
docking_attribS.cursor = guiSP->main_winS.cursorID;
docking_attribS.colormap = guiSP->colormapID;
docking_value_mask = CWBorderPixel | CWBackPixel | CWCursor | CWColormap;
guiSP->docking_winS.border_width = 1;

/* Border width: */
guiSP->docking_winS.border_width = guiSP->main_winS.border_width;

/* Create docking window (root window is the parent) and set flag: */
guiSP->docking_winS.ID = XCreateWindow (
                guiSP->displaySP, DefaultRootWindow (guiSP->displaySP),
                guiSP->docking_winS.x0, guiSP->docking_winS.y0,
                guiSP->docking_winS.width, guiSP->docking_winS.height,
                guiSP->docking_winS.border_width, guiSP->depth,
                InputOutput, guiSP->visualSP,
                docking_value_mask, &docking_attribS);
guiSP->docking_window_createdF = 1;

/* Prepare docking window name: */
strcpy (docking_win_titleA, "Docking");
docking_win_titleP = docking_win_titleA;

/* Set docking window name: */
if (!XStringListToTextProperty (&docking_win_titleP, 1, &docking_win_titleS))
	{
	ErrorMessage_ ("garlic", "PrepareDockingWindow_", "",
		"XStringListToTextProperty failed!\n",
		"", "", "");
	return -1;
	}

/*------docking icon window:-------------------------------------------------*/

/* Create docking icon pixmap: */
if (MakePixmap_ (&guiSP->docking_icon_winS, guiSP, docking_xpm) < 0) return -2;

/* Set icon window attributes: */
docking_icon_attribS.border_pixel = BlackPixel (guiSP->displaySP,
						guiSP->screenID);
docking_icon_attribS.background_pixmap = guiSP->docking_icon_winS.pixmapID;
docking_icon_attribS.colormap = guiSP->colormapID;
docking_icon_value_mask = CWBorderPixel | CWBackPixmap | CWColormap;
guiSP->docking_icon_winS.x0 = 440;
guiSP->docking_icon_winS.y0 = 50;
guiSP->docking_icon_winS.border_width = 1;

/* Create docking icon window: */
guiSP->docking_icon_winS.ID = XCreateWindow (
		guiSP->displaySP, DefaultRootWindow (guiSP->displaySP),
		guiSP->docking_icon_winS.x0, guiSP->docking_icon_winS.y0,
		guiSP->docking_icon_winS.width,
		guiSP->docking_icon_winS.height,
		guiSP->docking_icon_winS.border_width, guiSP->depth,
		InputOutput, guiSP->visualSP,
		docking_icon_value_mask, &docking_icon_attribS);

/* Set docking icon window colormap: */
XSetWindowColormap (guiSP->displaySP,
		    guiSP->docking_icon_winS.ID,
		    guiSP->colormapID);

/* Prepare docking icon window name: */
strcpy (docking_icon_titleA, "Docking");
docking_icon_titleP = docking_icon_titleA;

/* Set docking icon window name: */
if (!XStringListToTextProperty (&docking_icon_titleP, 1, &docking_icon_titleS))
        {
        ErrorMessage_ ("garlic", "PrepareDockingWindow_", "",
		"Failed to allocate storage for XTextProperty structure!\n",
		"", "", "");
	return -3;
	}

/*------set window manager properties:---------------------------------------*/

/* Allocate and set size hints: */
size_hintsSP = XAllocSizeHints ();
if (!size_hintsSP)
	{
	ErrorMessage_ ("garlic", "PrepareDockingWindow_", "",
		"Failed to allocate storage for size hints!\n",
		"", "", "");
	return -4;
	}
size_hintsSP->flags = PPosition | PSize | PMinSize;
size_hintsSP->min_width  = 100;
size_hintsSP->min_height = 100;

/* Allocate and set window manager hints: */
wm_hintsSP = XAllocWMHints ();
if (!wm_hintsSP)
	{
	ErrorMessage_ ("garlic", "PrepareDockingWindow_", "",
		"Failed to allocate storage for window manager hints!\n",
		"", "", "");
	return -5;
	}
wm_hintsSP->initial_state = NormalState;
wm_hintsSP->input = True;
wm_hintsSP->icon_pixmap = guiSP->docking_icon_winS.pixmapID;
wm_hintsSP->flags = StateHint | IconPixmapHint | InputHint;

/* Allocate and set class hints: */
class_hintsSP = XAllocClassHint ();
if (!class_hintsSP)
	{
	ErrorMessage_ ("garlic", "PrepareDockingWindow_", "",
		"Failed to allocate storage for class hints!\n",
		"", "", "");
	return -6;
	}
class_hintsSP->res_name = "docking";
class_hintsSP->res_class = "Garlic";

/* Set window manager properties: */
XSetWMProperties (guiSP->displaySP, guiSP->docking_winS.ID,
		  &docking_win_titleS, &docking_icon_titleS,
		  NULL, 0, 
		  size_hintsSP, wm_hintsSP, class_hintsSP);

/*------select events:-------------------------------------------------------*/

event_mask = ExposureMask |
	     KeyPressMask | KeyReleaseMask |
	     StructureNotifyMask;       /* Selects ConfigureNotify event */

XSelectInput (guiSP->displaySP, guiSP->docking_winS.ID, event_mask);

/*------allocate storage required to project two structures:-----------------*/

/* The total number of cells across docking area: */
width = runtimeSP->docking_matrix_width;

/* The number  of elements  in the array  which  contains */
/* indices of exposed atoms and size of a single element: */
elementsN = width * width;
int_size = sizeof (int);

/* Allocate the array reserved for the first complex (bottom molecule): */
runtimeSP->exposed_atom1IP = (int *) calloc (elementsN, int_size);
if (!runtimeSP->exposed_atom1IP)
	{
	ErrorMessage_ ("garlic", "PrepareDockingWindow_", "",
		"Failed to allocate storage for exposed_atom1IP!\n",
		"", "", "");
	return -7;
	}

/* Allocate the array for the second complex (top molecule): */
runtimeSP->exposed_atom2IP = (int *) calloc (elementsN, int_size);
if (!runtimeSP->exposed_atom2IP)
	{
	ErrorMessage_ ("garlic", "PrepareDockingWindow_", "",
		"Failed to allocate storage for exposed_atom2IP!\n",
		"", "", "");
	return -8;
	}

/*------allocate storage for two lists of exposed polar residues:------------*/

/* The size of ExposedResidueS structure: */
exposed_polar_size = sizeof (ExposedResidueS);

/* Allocate the storage for the exposed polar residues (bottom complex): */
runtimeSP->exposed_polar1SP =
		(ExposedResidueS *) calloc (MAX_EXPOSED_RESIDUES,
					    exposed_polar_size);
if (runtimeSP->exposed_polar1SP == NULL)
	{
	ErrorMessage_ ("garlic", "PrepareDockingWindow_", "",
		       "Failed to allocate memory",
		       " for exposed polar residues (bottom complex)!\n",
		       "", "");
	return -9;
	}

/* Allocate the storage for the exposed polar residues (top complex): */
runtimeSP->exposed_polar2SP =
		(ExposedResidueS *) calloc (MAX_EXPOSED_RESIDUES,
					    exposed_polar_size);
if (runtimeSP->exposed_polar2SP == NULL)
	{
	ErrorMessage_ ("garlic", "PrepareDockingWindow_", "",
		       "Failed to allocate memory",
		       " for exposed polar residues (top complex)!\n",
		       "", "");
	return -10;
	}

/*------map docking window:--------------------------------------------------*/

/* Map docking window and set flag: */
XMapWindow (guiSP->displaySP, guiSP->docking_winS.ID);
guiSP->docking_window_mappedF = 1;

/*---------------------------------------------------------------------------*/

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

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


