/*
** XmgMacro.c for  in 
** 
** Made by vianney rancurel
** Login   <vianney@epita.fr>
** 
** Started on  Wed Aug 25 14:14:35 1999 vianney rancurel
** Last update Thu Oct 28 20:22:28 1999 
*/
/*
 * Copyright Olivier Raoul (C) 1995
 */

#include <stdio.h>
#include <X11/Xlib.h>
#include <X11/Intrinsic.h>
#include <X11/IntrinsicP.h>
#include <X11/StringDefs.h>
#if XtSpecificationRelease > 4
# include <X11/Xmu/Editres.h>
#endif
#include "XmgMacro.h"
#include "XmgI.h"

t_vec		*xmg_macro_widget_stack = NULL;

/* initalizes the widget stack.
   
   See also: XtMacro package from the internet, copyright Olivier Raoul */
t_status	XmgMacroInit(VOID_DECL)
{
  t_status	status;

  if ((xmg_macro_widget_stack = XMG_VEC_NEW(&status)) == NULL)
    return (status);
  return (0);
}

/* destroys the widget stack. */
VOID_FUNC	XmgMacroDestroy(VOID_DECL)
{
  vec_delete(xmg_macro_widget_stack);
}

#ifdef HAVE_STDARG_H
VOID_FUNC	XmgMacroPushChild(Widget w,...)
#else
VOID_FUNC	XmgMacroPushChild(w,va_alist)
Widget		w;
va_dcl
#endif
{
  t_status	status;

  if ((status = stack_push(xmg_macro_widget_stack,w)) != 0)
    {
      err_print(status,"stack_push");
      exit(1);
    }
}

Widget		XmgMacroLookupChild(VOID_DECL)
{
  t_status	status;
  Widget	w;	

  if ((status = stack_lookup(xmg_macro_widget_stack,(VOID_PTR *)(&w))) != 0)
    {
      err_print(status,"stack_lookup");
      exit(1);
    }
  return (w);
}

VOID_FUNC	XmgMacroPopChild(VOID_DECL)
{
  t_status	status;
  Widget	w;	

  if ((status = stack_pop(xmg_macro_widget_stack,(VOID_PTR *)(&w))) != 0)
    {
      err_print(status,"stack_pop");
      exit(1);
    }
}

#ifndef PROGRAM_CPROTO
int		XmgMacroNothing()
{
  return (0);
}
#endif

Widget			XmgMacroVaCreateWidget(f,
					       name,
					       widget_class,
					       parent,
					       var,
					       count)
Widget			(*f)();
String			name;
WidgetClass		widget_class;
Widget			parent;
va_list			var;
int			count;
{
  Widget		widget;
  VOID_PTR		typed_args;
  Cardinal		num_args;
    
  typed_args = NULL;
  _XtVaToTypedArgList(var,count,&typed_args,&num_args);
  widget = (*f)(name,widget_class,parent,(ArgList)NULL, 
		(Cardinal)0,typed_args,num_args);
  if (typed_args != NULL)
    {
      XtFree((XtPointer)typed_args);
    }    
    return (widget);
}

#ifdef HAVE_STDARG_H
Widget		XmgMacroCreateWidget(char *name,
				     WidgetClass widget_class,
				     ...)
#else
Widget		XmgMacroCreateWidget(name,widget_class,va_alist)
char		*name;
WidgetClass	widget_class;
va_dcl
#endif
{
  va_list	var;
  Widget	widget;
  int		total_count;
  int		typed_count;

#ifdef DEBUG
  if (XMG_VERB(VERB_XMG_MACRO))
    fprintf(stderr,"+macro+ widget %s\n",name);
#endif  
#ifdef HAVE_STDARG_H
  va_start(var,widget_class);
#else
  va_start(var);
#endif
  _XtCountVaList(var,&total_count,&typed_count);
  va_end(var);
#ifdef HAVE_STDARG_H
    va_start(var,widget_class);
#else
    va_start(var);
#endif
    if (XtIsSubclass(XmgMacroLookupChild(),compositeWidgetClass) == False)
      {
	err_print(1,"XmgMacroCreateWidget","",
		  "Warning: widget `%s' is not a composite",
		  XtName(XmgMacroLookupChild()));
	return (NULL);
      }
    widget = XmgMacroVaCreateWidget(_XtCreateWidget,
				    name,
				    widget_class, 
				    XmgMacroLookupChild(),
				    var,
				    total_count);
    XmgMacroPushChild(widget);
    XtManageChild(widget);
    va_end(var);
    return (widget);
}

#ifdef HAVE_STDARG_H
Widget			XmgMacroCreateShellWidget(char *name,
						  WidgetClass widget_class,
						  ...)
#else
Widget			XmgMacroCreateShellWidget(name,
						  widget_class,
						  va_alist)
char			*name;
WidgetClass		widget_class;
va_dcl
#endif
{
    va_list		var;
    Widget		widget;
    int		 	total_count;
    int			typed_count;
    
#ifdef DEBUG
  if (XMG_VERB(VERB_XMG_MACRO))
    fprintf(stderr,"+macro+ shell %s\n",name);
#endif  
#ifdef HAVE_STDARG_H
    va_start(var,widget_class);
#else
    va_start(var);
#endif
    _XtCountVaList(var,&total_count,&typed_count);
    va_end(var);
#ifdef HAVE_STDARG_H
    va_start(var,widget_class);
#else
    va_start(var);
#endif
    widget = XmgMacroVaCreateWidget(_XtCreatePopupShell,
				    name,
				    widget_class,
				    XmgMacroLookupChild(),
				    var,
				    total_count);
    XmgMacroPushChild(widget);
    va_end(var);
    return (widget);
}

#ifdef HAVE_STDARG_H
Widget		XmgMacroAppInitialize(XtAppContext *app_context_return,
				      String application_class,
				      XrmOptionDescList options,
				      Cardinal num_options,
				      int *argc_in_out,
				      String *argv_in_out,
				      String *fallback_resources,
				      ...)
#else
Widget			XmgMacroAppInitialize(app_context_return,
					      application_class,
					      options,
					      num_options,
					      argc_in_out,
					      argv_in_out,
					      fallback_resources,
					      va_alist);
XtAppContext		*app_context_return,
String			application_class,
XrmOptionDescList	options,
Cardinal		num_options,
int			*argc_in_out,
String			*argv_in_out,
String			*fallback_resources,
va_dcl
#endif
{
  va_list		var;
  Widget		widget;
  int			total_count;
  int			typed_count;
  
#ifdef DEBUG
  if (XMG_VERB(VERB_XMG_MACRO))
    fprintf(stderr,"+macro+ app %s\n",application_class);
#endif  
#ifdef HAVE_STDARG_H
  va_start(var,fallback_resources);
#else
  va_start(var);
#endif
  _XtCountVaList(var,&total_count,&typed_count);
  va_end(var);
#ifdef HAVE_STDARG_H
  va_start(var,fallback_resources);
#else
  va_start(var);
#endif
  widget = XtAppInitialize(app_context_return,
			   application_class,
			   options,
			   num_options,
			   argc_in_out,
			   argv_in_out,
			   fallback_resources,
#if defined(__osf__) && defined(__alpha)
			   (ArgList)(var._a0),
#else
			   va_arg(var, ArgList),
#endif
			   total_count);
#if XtSpecificationRelease>4  
  XtAddEventHandler(widget,(EventMask)0,TRUE,_XEditResCheckMessages,NULL);
#endif
  XmgMacroPushChild(widget);
  va_end(var);
  return (widget);
}

VOID_FUNC		XmgMacroMethodProcessCallback(src,md,p)
Widget			src;
XmgMacroMethodDataRec		*md;
XtPointer		p;
{
  XtArgVal		val;
  
  XtVaGetValues(src,md->src_res,&val,NULL);
  XtVaSetValues(md->dst,md->dst_res,val,NULL);
}

VOID_FUNC		XmgMacroTraceProcessCallback(src,td,p)
Widget			src;
XmgMacroTraceDataRec		*td;
XtPointer		p;
{
  XtVaGetValues(src,
		td->res,
		td->var,
		NULL);
}

VOID_FUNC		XmgMacroMethodDestroyCallback(src,md,p)
Widget			src;
XmgMacroMethodDataRec		*md;
XtPointer		p;
{
  XMG_FREE_PROC(md,
		"",
		"*:md");
}

VOID_FUNC		XmgMacroDoMethod(src,callback,src_res,dst,dst_res)
Widget			src;
String			callback;
String			src_res;
Widget			dst;
String			dst_res;
{
  XmgMacroMethodDataRec		*md;
  t_status		status;

  if ((md = XMG_ALLOC_PROC(sizeof (XmgMacroMethodDataRec),
			   "",
			   "XmgMacroDoMethod:md",
			   &status)) == NULL)
    {
      err_print(status,"XMG_ALLOC_PROC");
      exit(1);
    }
  md->dst = dst;
  md->src_res = src_res;
  md->dst_res = dst_res;
  XtAddCallback(src,
		callback,
		(XtCallbackProc)XmgMacroMethodProcessCallback,
		md);
  XtAddCallback(src,
		XtNdestroyCallback,
		(XtCallbackProc)XmgMacroMethodDestroyCallback,
		md);
}

VOID_FUNC		XmgMacroDoMethodDouble(src,
					       callback,
					       src_res,
					       dst,
					       dst_res)
Widget			src;
String			callback;
String			src_res;
Widget			dst;
String			dst_res;
{
  XmgMacroDoMethod(src,
		   callback,
		   src_res,
		   dst,
		   dst_res);
  XmgMacroDoMethod(dst,
		   callback,
		   src_res,
		   src,
		   dst_res);
}

VOID_FUNC		XmgMacroDoMethodTrace(src,callback,res,var)
Widget			src;
String			callback;
String			res;
XtPointer		var;
{
  XmgMacroTraceDataRec		*td;
  t_status		status;

  if ((td = XMG_ALLOC_PROC(sizeof (XmgMacroTraceDataRec),
			   "",
			   "XmgMacroDoMethodTrace:td",
			   &status)) == NULL)
    {
      err_print(status,"XMG_ALLOC_PROC");
      exit(1);
    }
  td->res = res;
  td->var = var;
  XtAddCallback(src,
		callback,
		(XtCallbackProc)XmgMacroTraceProcessCallback,
		td);
  XtAddCallback(src,
		XtNdestroyCallback,
		(XtCallbackProc)XmgMacroMethodDestroyCallback,
		td);
}

VOID_FUNC		XmgMacroMultiCallbackCallback(w,md,cbs)
Widget			w;
XmgMacroMultiDataRec		*md;
XtPointer		cbs;
{
  md->proc(w,md->args,cbs);
}

VOID_FUNC		XmgMacroMultiDestroyCallback(w,md)
Widget			w;
XmgMacroMultiDataRec		*md;
{
  vec_delete(md->args);
  XMG_FREE_PROC(md,
		"",
		"*:md");
}


#ifdef HAVE_STDARG_H
VOID_FUNC		XmgMacroAddMultiCallback(char *name,
						XmgMacroMultiCallbackProc proc,
						 ...)
#else
VOID_FUNC			XmgMacroAddMultiCallback(name,proc,va_alist)
char				*name;
XmgMacroMultiCallbackProc	proc;
va_dcl
#endif
{
  va_list			ap;
  XmgMacroMultiDataRec			*md;
  t_status			status;
  VOID_PTR			ptr;

#ifdef HAVE_STDARG_H
  va_start(ap,proc);
#else
  va_start(ap);
  va_arg(ap,char *);
  va_arg(ap,XmgMcallbackProc);
#endif
  if ((md = XMG_ALLOC_PROC(sizeof (XmgMacroMultiDataRec),
			   "",
			   "XmgMacroAddMultiCallback:md",
			   &status)) == NULL)
    {
      err_print(status,"XMG_ALLOC_PROC");
      exit(1);
    }
  if ((md->args = XMG_VEC_NEW(&status)) == NULL)
    {
      err_print(status,"XMG_VEC_NEW");
      exit(1);
    }
  md->proc = proc;
  while (ptr = va_arg(ap,VOID_PTR))
    {
      if ((status = vec_add(md->args,ptr)) != 0)
	{
	  err_print(status,"vec_add");
	  exit(1);
	}
    }
  va_end(ap);
  XtAddCallback(GETPARENT,
		name,
		(XtCallbackProc)XmgMacroMultiCallbackCallback,
		md);
  XtAddCallback(GETPARENT,
		XtNdestroyCallback,
		(XtCallbackProc)XmgMacroMultiDestroyCallback,
		md);
}
