/***************************** LICENSE START ***********************************

 Copyright 2012 ECMWF and INPE. This software is distributed under the terms
 of the Apache License version 2.0. In applying this license, ECMWF does not
 waive the privileges and immunities granted to it by virtue of its status as
 an Intergovernmental Organization or submit itself to any jurisdiction.

 ***************************** LICENSE END *************************************/

#include <stdio.h>
#include <math.h>

#include  <X11/Intrinsic.h>
#include  <X11/IntrinsicP.h>
#include  <X11/StringDefs.h>
#include  <X11/CoreP.h>
#include  <X11/CompositeP.h>
#include  <X11/ConstrainP.h>
#include  <Xm/XmP.h>
#include  <Xm/DrawingAP.h>
#include  "Line.h"
#include  "LineP.h"

#ifndef MAX
#define   MAX(a,b) ((a) > (b) ? (a) : (b))
#endif
#ifndef MIN
#define   MIN(a,b) ((a) < (b) ? (a) : (b))
#endif

static void             Initialize();
static void             Resize();
static void             Destroy();
static Boolean          SetValues();
static XtGeometryResult GeometryManager();
static void             ChangeManaged();
static void             new_layout();
static void 			get_row_col();
#ifdef NO_STRING_TABLE_CVT
static void				Initialize_class();
#endif

#define DEBUG(a) printf("%s\n",a);

static XtResource resources[] = {
	{XtNsizes,XtCSizes, XmRStringTable,sizeof(String*),
	XtOffset(LineWidget,line.sizes), XtRString,(XtPointer)"50,50,50" },
};

#ifndef USE_MANAGER
#define USE_MANAGER
#endif


LineClassRec lineClassRec = {
	{
	/* core_class fields  */
	(WidgetClass) &xmDrawingAreaClassRec,/* superclass         */
#if 0
	(WidgetClass) &constraintClassRec,/* superclass         */
#endif
	"Line",                           /* class_name         */
	sizeof(LineRec),                /* widget_size        */
#ifdef NO_STRING_TABLE_CVT
	Initialize_class,                 /* class_init         */
#else
	NULL,                             /* class_init         */
#endif
	NULL,                             /* class_part_init    */
	FALSE,                            /* class_inited       */
	Initialize,                       /* initialize         */
	NULL,                             /* initialize_hook    */
	XtInheritRealize,                 /* realize            */
	NULL,                             /* actions            */
	0,                                /* num_actions        */
	resources,                        /* resources          */
	XtNumber(resources),              /* num_resources      */
	NULLQUARK,                        /* xrm_class          */
	TRUE,                             /* compress_motion    */
	TRUE,                             /* compress_exposure  */
	TRUE,                             /* compress_enterleave*/
	TRUE,                             /* visible_interest   */
	Destroy,                          /* destroy            */
	Resize,                           /* resize             */
	(XtExposeProc)_XmRedisplayGadgets,/* expose             */
	SetValues,                        /* set_values         */
	NULL,                             /* set_values_hook    */
	XtInheritSetValuesAlmost,         /* set_values_almost  */
	NULL,                             /* get_values_hook    */
	NULL,                             /* accept_focus       */
	XtVersion,                        /* version            */
	NULL,                             /* callback_private   */
	XtInheritTranslations,            /* tm_table           */
	NULL,                             /* query_geometry     */
	XtInheritDisplayAccelerator,      /* display_accelerator*/
	NULL,                             /* extension          */
	},
	{
	/* composite_class fields */
	GeometryManager,                 /* geometry_manager    */
	ChangeManaged,                   /* change_managed      */
	XtInheritInsertChild,            /* insert_child        */
	XtInheritDeleteChild,            /* delete_child        */
	NULL ,                           /* extension           */
	},
	{ 
	/* constraint_class fields */
	NULL,                             /* subresources        */
	0,                                /* subresource_count   */
	0,                                /* constraint_size     */
	NULL,                             /* initialize          */
	NULL,                             /* destroy             */
	NULL,                             /* set_values          */
	NULL,                             /* extension           */
	},
	{
	XtInheritTranslations,   /* default translations */
	NULL,                    /* syn_resources          */
	0,               /* num_syn_resources      */
	NULL,                        /* syn_cont_resources     */
	0,                           /* num_syn_cont_resources */
	XmInheritParentProcess,  /* parent_process */
	NULL,                        /* extension              */

	},
	{
	NULL,
	},
	{
	/* Line class fields */
	0,                               /* ignore              */
	}
};





WidgetClass lineWidgetClass = (WidgetClass) &lineClassRec;

#ifdef NO_STRING_TABLE_CVT

#define SKIP_BLANKS { while(*p && isspace(*p)) p++; }

/* Some motif has no converter */

static void CvtStringToStringTable(args,num_args,from,to)
XrmValuePtr args;
Cardinal    *num_args;
XrmValuePtr from,to;
{
    char   *p = (char*)from->addr;
	char   *q;
	char buf[1024];
	String  s[1024];
	int i;
	int n=0;
	static String  *table = NULL;

    if(!from->addr) return;


    SKIP_BLANKS;
	while(*p)
	{
		i = 0;
		while(*p && *p != ',') buf[i++] = *p++;
		buf[i] = 0;
		if(i)
		{
			q = buf+i-1;
			while(q != buf && isspace(*q)) *q-- = 0;
		}
		s[n++] = XtNewString(buf);

		if(*p && *p ==',') p++;
        SKIP_BLANKS;
	}

	table = (String*)XtCalloc(sizeof(String),n+1);
	for(i=0;i<n;i++)
		table[i] = s[i];


    to->addr = (caddr_t)&table;
    to->size = sizeof(caddr_t);

}

static void Initialize_class (widget_class)
WidgetClass widget_class;
{
	XtAddConverter(XmRString,XmRStringTable,CvtStringToStringTable,NULL,0);
}

#endif






static void Initialize(request, new)
LineWidget request, new;
{
	/*
   * Make sure the widget's width and height are 
   * greater than zero.
   */
	if (request->core.width <= 0)
		new->core.width = 5;
	if (request->core.height <= 0)
		new->core.height = 5;

}

static void Destroy(w)
LineWidget w;
{
}

static void Resize(w)
LineWidget w;
{
	new_layout(w);
}


static Boolean SetValues(current, request, new)
LineWidget current, request, new;
{
	/* should do something */
	/* new_layout(new); */
	return (False);
}


static XtGeometryResult GeometryManager(w, request, reply)
Widget               w;
XtWidgetGeometry    *request;
XtWidgetGeometry    *reply;
{
	new_layout(XtParent(w));
	return (XtGeometryYes);
}

static void ChangeManaged(tw)
LineWidget tw;
{
	new_layout(tw);
}


static void new_layout(tw)
LineWidget   tw;
{

	int i;
	Dimension width  = 0;
	Dimension height = tw->core.height;
	Dimension ww;
	Position  x = 0;

	if(tw->line.sizes == NULL) return;

	for(i=0;tw->line.sizes[i];i++)
		width += atol(tw->line.sizes[i]);

	height = 5;

	for(i=0;i<tw->composite.num_children;i++)
	{
		Widget w = tw->composite.children[i];
		if(XtIsManaged(w))
			height = MAX(height,w->core.height);
	}

	x = 0;
	for(i=0;(i<tw->composite.num_children) && tw->line.sizes[i];i++)
	{
		Widget w = tw->composite.children[i];
		ww = atol(tw->line.sizes[i]);

		if(XtIsManaged(w))
			_XmConfigureObject((RectObj)w,x,0,ww,height,0);
		x += ww;

	}

	if(tw->core.width != width || tw->core.height != height)
	{
		Dimension           maxWidth = width, maxHeight = height;
		XtGeometryResult    result;
		Dimension           replyWidth = 0, replyHeight = 0;

		result = XtMakeResizeRequest(
		    (Widget)tw,
		    maxWidth,
		    maxHeight, 
		    &replyWidth, &replyHeight);

		if (result == XtGeometryAlmost)
			XtMakeResizeRequest (
			    (Widget)tw, 
			    replyWidth, 
			    replyHeight,NULL, NULL);
	}


}

Widget CreateLine(par,nam,al,ac)
Widget par;
char  *nam;
Arg   *al;
int   ac;
{
	return   XtCreateWidget(nam,lineWidgetClass,par,al,ac);
}

static void adjust(Widget w,int* size,int *n,int* h)
{

	int i;
	CompositeRec* c = (CompositeRec*)w;

	if(!XtIsComposite(w)) return;

	for(i = 0; i < c->composite.num_children; i++)
	{
		Widget w = c->composite.children[i];
		if(XtIsSubclass(w,lineWidgetClass))
		{
			LineWidget tw = (LineWidget)w;
			XtWidgetGeometry preferred;
			int j;
			if(tw->composite.num_children > *n)
				*n = tw->composite.num_children;

			for(j=0;j<tw->composite.num_children;j++)
			{
				Widget w = tw->composite.children[j];
				XtQueryGeometry(w,NULL,&preferred);
				if(preferred.width > size[j]) size[j] = preferred.width;
				if(preferred.height > *h) *h = preferred.height;
				if(tw->core.height  > *h) *h = tw->core.height;
			}
		}
		else adjust(w,size,n,h);
	}
}

static void resize(Widget w,int* size,int n,int h)
{

	int i;
	CompositeRec* c = (CompositeRec*)w;

	if(!XtIsComposite(w)) return;

	for(i = 0; i < c->composite.num_children; i++)
	{
		Widget w = c->composite.children[i];
		int j;
		int s;
		if(XtIsSubclass(w,lineWidgetClass))
		{
			LineWidget tw = (LineWidget)w;

			if(tw->line.sizes)
			{
				for(j=0;tw->line.sizes[j];j++)
					XtFree(tw->line.sizes[j]);
			}
			XtFree(tw->line.sizes);

			tw->line.sizes = (String*)XtCalloc(sizeof(String),n+1);
			s = 0;
			for(j=0;j<n;j++)
			{
				char buf[90];
				sprintf(buf,"%d",size[j]);
				tw->line.sizes[j] = XtNewString(buf);
				s += size[j];
			}

			XtVaSetValues(w,
				XmNwidth, (Dimension)s,
				XmNheight,(Dimension)h,0);

		}
		else resize(w,size,n,h);
	}
}

void LineAdjust(Widget rowcol)
{
	int i = 0;
	int size[100];
	int n = 0;
	int h = 5;

	for(i = 0; i < 100; i++) size[i] = 0;

	adjust(rowcol,size,&n,&h);
	resize(rowcol,size,n,h);

}
