#include <stdio.h>
#include <stdlib.h>
#include <X11/Xlib.h>
#include <Xm/XmAll.h>
#include <signal.h>
#include <device.h>
#include "menu.h"

/* locally globals variables */
static Widget root_shell = NULL;
static Widget form0 = NULL;
static Widget form1 = NULL;
static Widget current_form = NULL;
static XmStringCharSet char_set = XmSTRING_DEFAULT_CHARSET;
static XtAppContext context;
static int resolution[2];

void MakeRootShell(int argc, char *argv[], int width, int height)
{
  Arg args[2];
  Screen *scrn;

  /* create the root_shell */
  root_shell = XtAppInitialize(&context, "slick", NULL,0, &argc, argv, NULL, NULL, 0);
/*  root_shell = XtAppInitialize(&context, "slick", NULL,0, NULL, NULL, NULL, NULL, 0);*/

  /* resize root_shell */
  XtSetArg(args[0], XmNwidth,  width);
  XtSetArg(args[1], XmNheight, height);
  XtSetValues(root_shell, args, 2);

  XtSetArg(args[0], XmNscreen, &scrn);
  XtGetValues(root_shell, args, 1);

  resolution[0] = scrn->width;
  resolution[1] = scrn->height;

  /* create a form to hold all the widgets */
  form0 = XmCreateForm(root_shell, "form0", NULL, 0);
  MANAGE(form0);
  /*
  form1 = XmCreateFormDialog(root_shell, "form1", NULL, 0);
  MANAGE(form1);
  */

  /* set the current_form to the first form,
     every widget gets placed on current_form */
  current_form = form0;
}

void GetResolution(int *width, int *height)
{
  *width = resolution[0];
  *height = resolution[1];
}

void CurrentForm(int which)
{
  if (which == 1)
    current_form = form1;
  else
    current_form = form0;
}

void RemanageFormDialog()
{
}

Boolean GetDisplayRect(XRectangle *rect)
{
  Arg args[4];
  Position posx, posy;
  Dimension dimx, dimy;

  if (!root_shell)
    return False;

  XtSetArg(args[0], XmNx, &posx);
  XtSetArg(args[1], XmNy, &posy);
  XtSetArg(args[2], XmNwidth, &dimx);
  XtSetArg(args[3], XmNheight, &dimy);
  XtGetValues(root_shell, args, 4);

  rect->x = posx;
  rect->y = posy;
  rect->width = dimx;
  rect->height = dimy;

  return True;
}

void AddTimeOut(int timeout, TimeOutFunc timeout_func)
{
  XtAppAddTimeOut(context, timeout, (void *)timeout_func, "context");
}

XmStringCharSet *GetCharSet()
{
  return &char_set;
}

void RunMainLoop(int timeout, TimeOutFunc timeout_func)
{
  /* make sure the root_shell was created */
  if (!root_shell)
    return;

  XtRealizeWidget(root_shell);

  /* if a timeout function was specified, add the timeout */
  if (timeout_func)
    XtAppAddTimeOut(context, timeout, (void *)timeout_func, "context");
  XtAppMainLoop(context);
}

void SetWidgetFont(Widget *w, char *font_name)
{
  XFontStruct *font;
  XmFontList font_list;
  Arg args[1];

  /* set up fontlist resource */
  font = XLoadQueryFont(XtDisplay(current_form), font_name);
  font_list = XmFontListCreate(font, char_set);

  XtSetArg(args[0], XmNfontList, font_list);
  XtSetValues(*w, args, 1);
}

Widget MakeMessageDialog(char *msg,
			 CallbackFunc ok_func, char *ok_func_param,
			 CallbackFunc cancel_func, char *cancel_func_param)
{
  Arg args[1];
  Widget message_dialog;

  XtSetArg(args[0], XmNmessageString, XmStringCreateLtoR(msg, char_set));
  message_dialog = XmCreateMessageDialog(current_form, "dialog", args, 1);
  XtAddCallback(message_dialog, XmNokCallback, (void *)ok_func, ok_func_param);
  XtAddCallback(message_dialog, XmNcancelCallback, (void *)cancel_func, cancel_func_param);
  UNMANAGE(XmMessageBoxGetChild(message_dialog, XmDIALOG_HELP_BUTTON));

  return message_dialog;
}

Widget MakeFileSelectionDialog(char *msg,
			       CallbackFunc ok_func, char *ok_func_param,
			       CallbackFunc cancel_func, char *cancel_func_param)
{
  Arg args[1];
  Widget selection_dialog;

  XtSetArg(args[0], XmNselectionLabelString, XmStringCreateLtoR(msg, char_set));
  selection_dialog = XmCreateFileSelectionDialog(current_form, "dialog", args, 1);
  XtAddCallback(selection_dialog, XmNokCallback, (void *)ok_func, ok_func_param);
  XtAddCallback(selection_dialog, XmNcancelCallback, (void *)cancel_func, cancel_func_param);
  UNMANAGE(XmSelectionBoxGetChild(selection_dialog, XmDIALOG_HELP_BUTTON));

  return selection_dialog;
}

Widget MakeButton(char *name, CallbackFunc func, char *func_param)
{
  Arg args[1];
  Widget button;

  XtSetArg(args[0], XmNlabelString, XmStringCreate(name, char_set));
  button = XmCreatePushButton(current_form, "button", args, 1);
  XtAddCallback(button, XmNactivateCallback, (void *)func, func_param);
  MANAGE(button);

  return button;
}

Widget MakeToggle(char *name, CallbackFunc func, char *func_param, int toggle_on)
{
  Arg args[2];
  int arg_count;
  Widget toggle;

  arg_count = 0;
  XtSetArg(args[0], XmNlabelString, XmStringCreate(name, char_set));
  arg_count++;
  if (toggle_on)
    {
      XtSetArg(args[arg_count], XmNset, True);
      arg_count++;
    }
  toggle = XmCreateToggleButton(current_form, "toggle", args, arg_count);
  XtAddCallback(toggle, XmNvalueChangedCallback, (void *)func, func_param);
  MANAGE(toggle);

  return toggle;
}

/* creates a scrollbar ranging from min to max with
   a label name and manages it */
Widget MakeScrollbar(int horizontal, CallbackFunc func, char *func_param, int min, int max, int curr_value)
{
  Arg args[4];
  Widget scrollbar;

  XtSetArg(args[0], XmNorientation, (horizontal ? XmHORIZONTAL : XmVERTICAL));
  XtSetArg(args[1], XmNshowValue, False);
  XtSetArg(args[2], XmNminimum, min);
  XtSetArg(args[3], XmNmaximum, min+(max-min)/0.9);
  scrollbar = XmCreateScrollBar(current_form, "scroll", args, 4);
  XtAddCallback(scrollbar, XmNdragCallback, (void *)func, func_param);
  XtAddCallback(scrollbar, XmNvalueChangedCallback, (void *)func, func_param);
  XtVaSetValues(scrollbar, XmNvalue, curr_value, 0);
  MANAGE(scrollbar);

  return scrollbar;
}

/* creates a label with name and manages it */
Widget MakeLabel(char *name)
{
  Arg args[1];
  Widget label;

  XtSetArg(args[0], XmNlabelString, XmStringCreate(name, char_set));
  label = XmCreateLabel(current_form,"label", args, 1);
  MANAGE(label);

  return label;
}

Widget MakeSeparator()
{
  Widget separator;

  separator = XmCreateSeparator(current_form, "separator", NULL, 0);
  MANAGE(separator);

  return separator;
}


void WidgetLeftPosition(Widget *w, int left)
{
  Arg args[2];
  
  XtSetArg(args[0], XmNleftAttachment, XmATTACH_POSITION);
  XtSetArg(args[1], XmNleftPosition, left);

  XtSetValues(*w, args, 2);
}

void WidgetBottomPosition(Widget *w, int bottom)
{
  Arg args[2];

  XtSetArg(args[0], XmNbottomAttachment, XmATTACH_POSITION);
  XtSetArg(args[1], XmNbottomPosition, bottom);

  XtSetValues(*w, args, 2);
}

void WidgetRightPosition(Widget *w, int right)
{
  Arg args[2];

  XtSetArg(args[0], XmNrightAttachment, XmATTACH_POSITION);
  XtSetArg(args[1], XmNrightPosition, right);

  XtSetValues(*w, args, 2);
}

void WidgetTopPosition(Widget *w, int top)
{
  Arg args[2];

  XtSetArg(args[0], XmNtopAttachment, XmATTACH_POSITION);
  XtSetArg(args[1], XmNtopPosition, top);

  XtSetValues(*w, args, 2);
}

/* places a widget on the form */
void WidgetPosition(Widget *w, int left, int bottom, int right, int top)
{
  WidgetLeftPosition(w, left);
  WidgetBottomPosition(w, bottom);
  WidgetRightPosition(w, right);
  WidgetTopPosition(w, top);
}

void WidgetLeftAttachment(Widget *w, Widget *attach)
{
  Arg args[2];
  int arg_count;

  if (attach)
    {
      XtSetArg(args[0], XmNleftAttachment, XmATTACH_WIDGET);
      XtSetArg(args[1], XmNleftWidget, *attach);
      arg_count = 2;
    }
  else
    {
      XtSetArg(args[0], XmNleftAttachment, XmATTACH_NONE);
      arg_count = 1;
    }

  XtSetValues(*w, args, arg_count);
}

void WidgetBottomAttachment(Widget *w, Widget *attach)
{
  Arg args[2];
  int arg_count;

  if (attach)
    {
      XtSetArg(args[0], XmNbottomAttachment, XmATTACH_WIDGET);
      XtSetArg(args[1], XmNbottomWidget, *attach);
      arg_count = 2;
    }
  else
    {
      XtSetArg(args[0], XmNbottomAttachment, XmATTACH_NONE);
      arg_count = 1;
    }

  XtSetValues(*w, args, arg_count);
}

void WidgetRightAttachment(Widget *w, Widget *attach)
{
  Arg args[2];
  int arg_count;

  if (attach)
    {
      XtSetArg(args[0], XmNrightAttachment, XmATTACH_WIDGET);
      XtSetArg(args[1], XmNrightWidget, *attach);
      arg_count = 2;
    }
  else
    {
      XtSetArg(args[0], XmNrightAttachment, XmATTACH_NONE);
      arg_count = 1;
    }

  XtSetValues(*w, args, arg_count);
}

void WidgetTopAttachment(Widget *w, Widget *attach)
{
  Arg args[2];
  int arg_count;

  if (attach)
    {
      XtSetArg(args[0], XmNtopAttachment, XmATTACH_WIDGET);
      XtSetArg(args[1], XmNtopWidget, *attach);
      arg_count = 2;
    }
  else
    {
      XtSetArg(args[0], XmNtopAttachment, XmATTACH_NONE);
      arg_count = 1;
    }

  XtSetValues(*w, args, arg_count);
}

void WidgetAttachment(Widget *w,
		      Widget *attach_left, Widget *attach_bottom,
		      Widget *attach_right, Widget *attach_top)
{
  WidgetLeftAttachment(w, attach_left);
  WidgetBottomAttachment(w, attach_bottom);
  WidgetRightAttachment(w, attach_right);
  WidgetTopAttachment(w, attach_top);
}

void WidgetLeftAttachedToForm(Widget *w)
{
  Arg args[1];

  XtSetArg(args[0], XmNleftAttachment, XmATTACH_FORM);
  XtSetValues(*w, args, 1);
}

void WidgetBottomAttachedToForm(Widget *w)
{
  Arg args[1];

  XtSetArg(args[0], XmNbottomAttachment, XmATTACH_FORM);
  XtSetValues(*w, args, 1);
}

void WidgetRightAttachedToForm(Widget *w)
{
  Arg args[1];

  XtSetArg(args[0], XmNrightAttachment, XmATTACH_FORM);
  XtSetValues(*w, args, 1);
}

void WidgetTopAttachedToForm(Widget *w)
{
  Arg args[1];

  XtSetArg(args[0], XmNtopAttachment, XmATTACH_FORM);
  XtSetValues(*w, args, 1);
}