/* This file is part of `mogul'
 * Copyright (c) 1995 David Deaven
 *
 * In the following, "you" and "You" refer to any entity other than 
 * the Microsoft corporation and its subsidiaries.  All rights are
 * reserved by the author in connection with Microsoft and its
 * subsidiaries.  The Microsoft Network is explicity denied the right
 * to copy, reproduce, or transmit this software.
 *
 *   This program is free software; you can redistribute it and/or modify
 *   it under the terms of the GNU General Public License as published by
 *   the Free Software Foundation; either version 2 of the License, or
 *   (at your option) any later version.
 *
 *   This program is distributed in the hope that it will be useful,
 *   but WITHOUT ANY WARRANTY; without even the implied warranty of
 *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *   GNU General Public License for more details.
 *
 *   You should have received a copy of the GNU General Public License
 *   along with this program; if not, write to the Free Software
 *   Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
 *
 * $Author: deaven $
 * $Id: rendermenu.c,v 2.1 1996/07/11 18:39:57 deaven Exp deaven $
 */

#include <stdio.h>
#include <string.h>
#include <X11/Intrinsic.h>
#include <X11/StringDefs.h>

#include <X11/Xaw/Form.h>
#include <X11/Xaw/Command.h>
#include <X11/Xaw/AsciiText.h>
#include <X11/Xaw/Text.h>
#include <X11/Xaw/SimpleMenu.h>
#include <X11/Xaw/MenuButton.h>
#include <X11/Xaw/SmeBSB.h>
#include <X11/Xaw/SmeLine.h>
#include "dmd/memory.h"
#include "dmd/geometry.h"
#include "xmogul.h"

enum menu_options {
	menu_parse,
	menu_rulepanel,
	menu_nothing
};

struct menu_widget {
	Widget button;	/* The menu button that pops this up */
	Widget shell;	/* The popup shell */
	Widget w;	/* The top-level widget in the shell */
};

struct callback_option {
	MogulPanel mp;
	int option;
};

struct RendermenuRec {
	Widget button;	/* Render menu heading */
	struct menu_widget parse;
	struct menu_widget rulepanel;
};

static void parse_callback(Widget widget,
  XtPointer client_data, XtPointer call_data)
{
	MogulPanel mp = (MogulPanel) client_data;
	String program;

	XtVaGetValues(mp->rendermenu->parse.w, 
	  XtNstring, &program, NULL);

	MPSetProgram(mp, program);
}

static void load_script_callback(Widget widget,
  XtPointer client_data, XtPointer call_data)
{
	int n, len = 0;
	MogulPanel mp = (MogulPanel) client_data;
	String program = NULL, fn;
	char buf[64];
	FILE *f;

	fn = MPGetFilenameDialog(mp->app, mp->frame, "Load script", "", "*.mogulrc");
	if(fn && (f = fopen(fn, "r")))
	{
	  while((n = fread(buf, sizeof(*buf), 64, f)) > 0)
	  {
	    program = ResizePointerArray(program, len + n);
	    bcopy(buf, program + len, n);
	    len += n;
	  }
	  fclose(f);
	  program = ResizePointerArray(program, len + 1);
	  program[len] = '\0';
	  XtVaSetValues(mp->rendermenu->parse.w, XtNstring, program, NULL);
	  MPSetProgram(mp, program);
	}
}

static void save_script_callback(Widget widget,
  XtPointer client_data, XtPointer call_data)
{
	MogulPanel mp = (MogulPanel) client_data;
	String fn, program;
	char buf[FILENAME_MAX + 64];
	FILE *f;

	fn = MPGetFilenameDialog(mp->app, mp->frame, "Save script", "", "*.mogulrc");
	if(fn) {
	  if((f = fopen(fn, "r")))
	  {
	    fclose(f);
	    sprintf(buf, "Overwrite existing script \"%s\"?", fn);
	    if(!MPVerifyDialog(mp->app, mp->frame, buf)) return;
	  }
	  if((f = fopen(fn, "w")))
	  {
	    XtVaGetValues(mp->rendermenu->parse.w, XtNstring, &program, NULL);
	    fprintf(f, "%s", program);
	    fclose(f);
	  }
	}
}

/* Make the shell and widget for the parse popup.
 */
static void create_parse(MogulPanel mp)
{
	Widget form, w;

        mp->rendermenu->parse.shell =
	  XtVaCreatePopupShell("ParsePopup", shellWidgetClass, mp->rendermenu->button, NULL);

	form =
	  XtVaCreateManagedWidget("form", formWidgetClass, mp->rendermenu->parse.shell, NULL);

	mp->rendermenu->parse.w =
	  XtVaCreateManagedWidget("text", asciiTextWidgetClass, form,
	    XtNeditType, XawtextEdit,
	    XtNscrollVertical, XawtextScrollWhenNeeded,
	    XtNscrollHorizontal, XawtextScrollWhenNeeded,
	    NULL);

	w =
	  XtVaCreateManagedWidget("Apply", commandWidgetClass, form,
	    XtNfromVert, mp->rendermenu->parse.w,
	    NULL);
	XtAddCallback(w, XtNcallback, parse_callback, mp);

	w =
	  XtVaCreateManagedWidget("Dismiss", commandWidgetClass, form,
	    XtNfromVert, mp->rendermenu->parse.w,
	    XtNfromHoriz, w,
	    NULL);
	{ XtPopdownID id = NewPointer(id);
	  id->shell_widget = mp->rendermenu->parse.shell; 
	  id->enable_widget = mp->rendermenu->parse.button;
	  XtAddCallback(w, XtNcallback, XtCallbackPopdown, id);
	}

	w =
	  XtVaCreateManagedWidget("Load", commandWidgetClass, form,
	    XtNfromVert, mp->rendermenu->parse.w,
	    XtNfromHoriz, w,
	    NULL);
	XtAddCallback(w, XtNcallback, load_script_callback, mp);

	w =
	  XtVaCreateManagedWidget("Save", commandWidgetClass, form,
	    XtNfromVert, mp->rendermenu->parse.w,
	    XtNfromHoriz, w,
	    NULL);
	XtAddCallback(w, XtNcallback, save_script_callback, mp);
}

static void rulepanel_callback(Widget widget,
  XtPointer client_data, XtPointer call_data)
{
	MogulPanel mp = (MogulPanel) client_data;
	MPZoomZero(mp);
}

/* Make the shell and widget for the rule panel popup.
 */
static void create_rulepanel(MogulPanel mp)
{
	Widget w;

        mp->rendermenu->rulepanel.shell =
	  XtVaCreatePopupShell("RulePanelPopup", shellWidgetClass, mp->rendermenu->button,
	    NULL);

	mp->rendermenu->rulepanel.w =
	  XtVaCreateManagedWidget("form", formWidgetClass, mp->rendermenu->rulepanel.shell,
	    NULL);

	w =
	  XtVaCreateManagedWidget("dummy", commandWidgetClass, mp->rendermenu->rulepanel.w,
	    NULL);

	w =
	  XtVaCreateManagedWidget("Apply", commandWidgetClass, mp->rendermenu->rulepanel.w,
	    XtNfromHoriz, w,
	    NULL);
	XtAddCallback(w, XtNcallback, rulepanel_callback, mp);

	w =
	  XtVaCreateManagedWidget("Dismiss", commandWidgetClass, mp->rendermenu->rulepanel.w,
	    XtNfromHoriz, w,
	    NULL);
	{ XtPopdownID id = NewPointer(id);
	  id->shell_widget = mp->rendermenu->rulepanel.shell; 
	  id->enable_widget = mp->rendermenu->rulepanel.button;
	  XtAddCallback(w, XtNcallback, XtCallbackPopdown, id);
	}
}

static void menu_callback(Widget widget,
  XtPointer client_data, XtPointer call_data)
{
	struct callback_option *bi = (struct callback_option *) client_data;

	switch(bi->option) {
	  case menu_parse:
	    XtSetSensitive(bi->mp->rendermenu->parse.button, False);
	    { String current = MPGetProgram(bi->mp);
	      XtVaSetValues(bi->mp->rendermenu->parse.w, 
		XtNstring, current,
		XtNlength, strlen(current),
		NULL);
	    }
	    XtPopup(bi->mp->rendermenu->parse.shell, XtGrabNone);
	    XStoreName(XtDisplay(bi->mp->rendermenu->parse.shell),
		       XtWindow(bi->mp->rendermenu->parse.shell), "xmogul script");
	    break;

	  case menu_rulepanel:
	    XtSetSensitive(bi->mp->rendermenu->rulepanel.button, False);
	    XtPopup(bi->mp->rendermenu->rulepanel.shell, XtGrabNone);
	    XStoreName(XtDisplay(bi->mp->rendermenu->rulepanel.shell),
		       XtWindow(bi->mp->rendermenu->rulepanel.shell), "xmogul rule editor");
	    break;

	  case menu_nothing:
	  default:
	    break;
	}
}

static Widget menu_entry(String name, WidgetClass class,
	Widget shell, MogulPanel mp, enum menu_options option)
{
	Widget w;
	struct callback_option *bi;

	w = XtVaCreateManagedWidget(name, class, shell, NULL);

	if(option != menu_nothing) {
	  bi = NewPointer(bi);
	  bi->mp = mp;
	  bi->option = option;
	  XtAddCallback(w, XtNcallback, menu_callback, bi);
	}

	return w;
}

void MPCreateRenderMenu(Widget parent, MogulPanel mp)
{
	Widget shell;

	mp->rendermenu = NewPointer(mp->rendermenu);

	mp->rendermenu->button =
	  XtVaCreateManagedWidget("Render", menuButtonWidgetClass, parent,
	    XtNmenuName, "RenderMenu", NULL);

        shell =
	  XtVaCreatePopupShell("RenderMenu", simpleMenuWidgetClass, mp->rendermenu->button,
	    NULL);

	mp->rendermenu->parse.button =
	  menu_entry("Edit script", smeBSBObjectClass, shell, mp, menu_parse);
	create_parse(mp);

	mp->rendermenu->rulepanel.button =
	  menu_entry("Rule panel", smeBSBObjectClass, shell, mp, menu_rulepanel);
	create_rulepanel(mp);
}

