#ifdef REV_INFO
#ifndef lint
static char SCCSID[] = "OSF/Motif: @(#)motifburger.c	1.7 90/04/02";   
#endif /* lint */
#endif /* REV_INFO */
/******************************************************************************
*******************************************************************************
*
*  (c) Copyright 1989, 1990, OPEN SOFTWARE FOUNDATION, INC.
*  (c) Copyright 1989, DIGITAL EQUIPMENT CORPORATION, MAYNARD, MASS.
*  ALL RIGHTS RESERVED
*         
*  	THE INFORMATION IN THIS SOFTWARE IS SUBJECT TO CHANGE WITHOUT
*  NOTICE AND SHOULD NOT BE CONSTRUED AS A COMMITMENT BY OPEN SOFTWARE
*  FOUNDATION, INC. OR ITS THIRD PARTY SUPPLIERS  
*  
*  	OPEN SOFTWARE FOUNDATION, INC. AND ITS THIRD PARTY SUPPLIERS,
*  ASSUME NO RESPONSIBILITY FOR THE USE OR INABILITY TO USE ANY OF ITS
*  SOFTWARE .   OSF SOFTWARE IS PROVIDED "AS IS" WITHOUT WARRANTY OF ANY
*  KIND, AND OSF EXPRESSLY DISCLAIMS ALL IMPLIED WARRANTIES, INCLUDING
*  BUT NOT LIMITED TO THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
*  FITNESS FOR A PARTICULAR PURPOSE.
*  
*  Notice:  Notwithstanding any other lease or license that may pertain to,
*  or accompany the delivery of, this computer software, the rights of the
*  Government regarding its use, reproduction and disclosure are as set
*  forth in Section 52.227-19 of the FARS Computer Software-Restricted
*  Rights clause.
*  
*  (c) Copyright 1989, 1990, Open Software Foundation, Inc.  Unpublished - all
*  rights reserved under the Copyright laws of the United States.
*  
*  RESTRICTED RIGHTS NOTICE:  Use, duplication, or disclosure by the
*  Government is subject to the restrictions as set forth in subparagraph
*  (c)(1)(ii) of the Rights in Technical Data and Computer Software clause
*  at DFARS 52.227-7013.
*  
*  Open Software Foundation, Inc.
*  11 Cambridge Center
*  Cambridge, MA   02142
*  (617)621-8700
*  
*  RESTRICTED RIGHTS LEGEND:  This computer software is submitted with
*  "restricted rights."  Use, duplication or disclosure is subject to the
*  restrictions as set forth in NASA FAR SUP 18-52.227-79 (April 1985)
*  "Commercial Computer Software- Restricted Rights (April 1985)."  Open
*  Software Foundation, Inc., 11 Cambridge Center, Cambridge, MA  02142.  If
*  the contract contains the Clause at 18-52.227-74 "Rights in Data General"
*  then the "Alternate III" clause applies.
*  
*  (c) Copyright 1989, 1990, Open Software Foundation, Inc.
*  ALL RIGHTS RESERVED 
*  
*  
* Open Software Foundation is a trademark of The Open Software Foundation, Inc.
* OSF is a trademark of Open Software Foundation, Inc.
* OSF/Motif is a trademark of Open Software Foundation, Inc.
* Motif is a trademark of Open Software Foundation, Inc.
* DEC is a registered trademark of Digital Equipment Corporation
* DIGITAL is a registered trademark of Digital Equipment Corporation
* X Window System is a trademark of the Massachusetts Institute of Technology
*
*******************************************************************************
******************************************************************************/
/*
 * A sample program which uses UIL and MRM to create the interface.
 */

#include <stdio.h>                              /* For printf and so on. */
#include <stdlib.h> 	    	    	    	/* needed for fopen */

#include <Xm/Text.h>      
#include <Mrm/MrmAppl.h>      
#include <DXm/DXmHelpB.h>      
#include <DXm/DXmPrint.h>      
#include <X11/Xlib.h>      
#include <X11/Xutil.h>      
#include <DXm/DXmColor.h>   
#include <DXm/DECspecific.h>
#include <X11/decwcursor.h>

/*
 * These numbers are matched with corresponding numbers in the DECburger
 * UIL module.
 */

#define	k_create_order		1
#define	k_order_pdme		2
#define	k_file_pdme		3
#define	k_edit_pdme		4
#define	k_nyi			5
#define	k_ok			6	    /* NOTE: ok, apply, reset, cancel */
#define	k_apply			7	    /* must be sequential */
#define	k_reset			8
#define	k_cancel		9
#define	k_cancel_order		10
#define	k_submit_order		11
#define	k_order_box		12
#define k_burger_min		13
#define	k_burger_rare		13
#define	k_burger_medium		14
#define	k_burger_well		15
#define	k_burger_ketchup	16
#define	k_burger_mustard	17
#define	k_burger_onion		18
#define	k_burger_mayo		19
#define	k_burger_pickle		20
#define k_burger_max		20
#define	k_burger_quantity	21
#define	k_fries_tiny		22
#define	k_fries_small		23
#define	k_fries_medium		24
#define	k_fries_large		25
#define	k_fries_huge		26
#define	k_fries_quantity	27
#define	k_drink_list		28
#define	k_drink_add		29
#define	k_drink_sub		30
#define	k_drink_quantity	31
#define	k_total_order		32
#define	k_burger_label		33
#define	k_fries_label		34
#define	k_drink_label		35
#define	k_menu_bar		36
#define	k_file_menu		37
#define	k_edit_menu		38
#define	k_order_menu		39
#define	k_help_pdme		40
#define	k_help_menu		41
#define	k_help_overview		42
#define	k_help_about		43
#define	k_help_onhelp		44
#define	k_help_sensitive	45
#define	k_print			46
#define	k_options_pdme		47
#define	k_options_menu		48
#define	k_create_options	49
#define	k_fries_optionmenu	50

#define k_max_widget            50


#define MAX_WIDGETS (k_max_widget + 1)

#define NUM_BOOLEAN (k_burger_max - k_burger_min + 1)

#define k_burger_index   0
#define k_fries_index    1
#define k_drinks_index   2
#define k_index_count    3

/*
 * Global data
 */


/* Book file for help system */  

#define decburger_help  "decw$examples:decburger_help.decw$book"  

/* Global help system context */  

Opaque  help_context;                       
                                                       


static Cursor watch = 0;

static Widget
    toplevel_widget = (Widget)NULL,	/* Root widget ID of our application. */
    main_window_widget = (Widget)NULL,	/* Root widget ID of main MRM fetch   */
    widget_array[MAX_WIDGETS],		/* Place to keep all other widget IDs */
    main_help_widget = (Widget)NULL,	/* Primary help widget		      */
    help_widget[MAX_WIDGETS],		/* Array of help widgets	      */
    help_array[MAX_WIDGETS],	        /* Array of help widgets for Toolkit  */
    print_widget = (Widget)NULL,	/* Print widget			      */
    color_widget = (Widget)NULL;	/* Color Mix widget		      */
  
static Screen	*the_screen;		/* Pointer to screen data*/
static Display	*the_display;		/* Pointer to display data */
static XColor  savecolor;  



static int help_num = 0;                /* make sure they start zero */   
static int low_num = 0;
  
static char toggle_array[NUM_BOOLEAN];	/* Our TRUTH about the state */
					/* of user interface toggles. */

static XmString
	current_drink,			/* Last selected drink name. */
	current_fries,			/* Last selected fries size. */
	name_vector[k_index_count];	/* Miscellaneous names gotten from */
					/* various widgets. */

static int quantity_vector[k_index_count];      /* Current quantities of */
                                                /* burger, fries, drinks. */

static long status;
static long bc;

static XmString latin_create;		/* Variables for */
static XmString latin_dismiss;		/* compound strings. */
static XmString latin_space;
static XmString latin_zero;
static MrmHierarchy s_MrmHierarchy;	/* MRM database hierarchy ID */
static MrmType *dummy_class;		/* and class variable. */
static char *db_filename_vec[] =	/* Mrm.heirachy file list. */
	{"decburger.uid"		/* There is only one UID file for */
	};				/* this application. */
static int db_filename_num =
	(sizeof db_filename_vec / sizeof db_filename_vec [0]);

/*
 * Forward declarations
 */

static void s_error();
static void help_error();
static void get_something();
static void set_something();

static void activate_proc();
static void create_proc();
static void list_proc();
static void exit_proc();
static void pull_proc();
static void scale_proc();
static void show_hide_proc();
static void show_label_proc();
static void toggle_proc();
static void create_help();
static void tracking_help(); 
static void sens_help_proc();    
static void help_system_proc();    
static void create_print(); 
static void activate_print(); 
static void create_color();   
static void ok_color_proc(); 
static void apply_color_proc();   
static void cancel_color_proc();   
static void xmstring_append();
static void start_watch();
static void stop_watch();
static int    init_application();

/* The names and addresses of things that Mrm has to bind.  The names do
 * not have to be in alphabetical order.  */

static MrmRegisterArg reglist[] = {
    {"activate_proc", (XtPointer) activate_proc}, 
    {"create_proc", (XtPointer) create_proc}, 
    {"list_proc", (XtPointer) list_proc}, 
    {"pull_proc", (XtPointer) pull_proc}, 
    {"exit_proc", (XtPointer) exit_proc}, 
    {"scale_proc", (XtPointer) scale_proc}, 
    {"show_hide_proc", (XtPointer) show_hide_proc}, 
    {"show_label_proc", (XtPointer) show_label_proc}, 
    {"toggle_proc", (XtPointer) toggle_proc},
    {"sens_help_proc", (XtPointer) sens_help_proc},
    {"help_system_proc", (XtPointer) help_system_proc},
    {"cancel_color_proc", (XtPointer) cancel_color_proc},
    {"apply_color_proc", (XtPointer) apply_color_proc},
    {"ok_color_proc", (XtPointer) ok_color_proc}
};

static int reglist_num = (sizeof reglist / sizeof reglist [0]);
static font_unit = 400;

/*
 * OS transfer point.  The main routine does all the one-time setup and
 * then calls XtMainLoop.
 */

static String fallback[] = {
    "DECburger.title: DECburger\nDECburger.x: 100\nDECburger.y: 100",
    NULL
};

unsigned int main(argc, argv)
    unsigned int argc;                  /* Command line argument count. */
    char *argv[];                       /* Pointers to command line args. */
{
    XtAppContext app_context; 

    MrmInitialize();			/* Initialize MRM before initializing */
					/* the X Toolkit. */

    DXmInitialize();			/* Initialize DXm widgets */    

    /* If we had user-defined widgets, we would register them with Mrm.here. */


    /* Initialize the X Toolkit. We get back a top level shell widget. */

    toplevel_widget = XtAppInitialize(
	&app_context,			/* App. context is returned */
	"DECburger",			/* Root class name. */
	NULL,				/* No option list. */
	0,				/* Number of options. */
	(int *) &argc,			/* Address of argc */
	argv,				/* argv */
	fallback,			/* Fallback resources */
	NULL,				/* No override resources */
	0);				/* Number of override resources */

    /* Open the UID files (the output of the UIL compiler) in the hierarchy */

    if (MrmOpenHierarchy(
	db_filename_num,		/* Number of files. */
	db_filename_vec,		/* Array of file names.  */
	NULL,				/* Default OS extenstion. */
	&s_MrmHierarchy)		/* Pointer to returned MRM ID */
      !=MrmSUCCESS)
	s_error("can't open hierarchy");

    init_application();

    /* Register the items MRM needs to bind for us. */

    MrmRegisterNames(reglist, reglist_num);


    /* Go get the main part of the application. */
    if (MrmFetchWidget(s_MrmHierarchy, "S_MAIN_WINDOW", toplevel_widget,
      &main_window_widget, &dummy_class) != MrmSUCCESS)
        s_error("can't fetch main window");

    /* Save some frequently used values */
    the_screen = XtScreen(toplevel_widget); 
    the_display = XtDisplay(toplevel_widget);
    

    /* If it's a color display, map customize color menu entry */
 
    if ((XDefaultVisualOfScreen(the_screen))->class == TrueColor 
        ||  (XDefaultVisualOfScreen(the_screen))->class == PseudoColor
        ||  (XDefaultVisualOfScreen(the_screen))->class == DirectColor
        ||  (XDefaultVisualOfScreen(the_screen))->class == StaticColor)
                                    
          XtSetMappedWhenManaged(widget_array[k_options_pdme], TRUE);
                                

    /* Manage the main part and realize everything.  The interface comes up
     * on the display now. */

    XtManageChild(main_window_widget); 
    XtRealizeWidget(toplevel_widget);


    /* Set up Help System environment */
              
/*    DXmHelpSystemOpen(&help_context, toplevel_widget, decburger_help, 
                            help_error, "Help System Error");      */
     

    /* Sit around forever waiting to process X-events.  We never leave
     * XtAppMainLoop. From here on, we only execute our callback routines. */
    XtAppMainLoop(app_context);
}
         
                  


/*
 * One-time initialization of application data structures.
 */

static int init_application()
{
    int k;
    int i;
    MrmCode data_type;
    XmString value;

    /* Initialize the application data structures. */
    for (k = 0; k < MAX_WIDGETS; k++)
        widget_array[k] = NULL;
    for (k = 0; k < NUM_BOOLEAN; k++)
        toggle_array[k] = FALSE;


    /* Initialize CS help widgets. */   

    for (i = 0; i < MAX_WIDGETS; i++)
        help_widget[i] = NULL;          
 

    /* Initialize help widgets for Toolkit creation. */   
           
    for (i = 0; i < MAX_WIDGETS; i++)
         help_array[i] = NULL;          
     

    /* Initialize print widgets. */   
        
    print_widget = NULL;                  
                                   

    /* Initialize color mix widget. */   
                        
    color_widget = NULL;                  



    /*  Set the medium 'hamburger doneness' toggle button so that the 
     *  radio box has one toggle button ON at startup. */

    toggle_array[k_burger_medium - k_burger_min] = TRUE;

    if (MrmFetchLiteral (s_MrmHierarchy, "k_drink_init",
		XtDisplay (toplevel_widget), &value, &data_type) == MrmSUCCESS){
	current_drink = XmStringCopy (value);
    }
    if (MrmFetchLiteral (s_MrmHierarchy, "k_fries_init",
		XtDisplay (toplevel_widget), &value, &data_type) == MrmSUCCESS){
	current_fries = XmStringCopy (value);
    }
    if (MrmFetchLiteral (s_MrmHierarchy, "k_create_init",
		XtDisplay (toplevel_widget), &value, &data_type) == MrmSUCCESS){
	latin_create = XmStringCopy (value);
    }
    if (MrmFetchLiteral (s_MrmHierarchy, "k_dismiss_init",
		XtDisplay (toplevel_widget), &value, &data_type) == MrmSUCCESS){
	latin_dismiss = XmStringCopy (value);
    }

    /* Set up the compound strings that we need. */
    latin_space = DXmCvtFCtoCS(" ", &bc, &status);
    latin_zero = DXmCvtFCtoCS(" 0", &bc, &status);
}
                    
/***************************************************************************
 *
 * These are some little utilities used by the callback routines.
 */

                  
/*
 * All errors are fatal.
 */

static void s_error(problem_string)
    char    *problem_string;
{       
    printf("%s\n", problem_string);
    exit(0);
}           

/*
 * Help System errors are also fatal.
 */
                       
static void help_error(problem_string, status)
    char    *problem_string;               
    int     status;

{
    printf("%s, %x\n", problem_string, status);
    exit(0);
}


/*
 * Simplified SET VALUE routine to use only when changing a single attribute.
 * If we need to change more than one, all new values should be put 
 * into one arglist and we should make one XtSetValues call (which is MUCH 
 * more efficient).
 */

static void set_something(w, resource, value)
    Widget	w;
    char	*resource, *value;
{
    Arg al[1]; 

    XtSetArg(al[0], resource, value);
    XtSetValues(w, al, 1);
}


/*
 * Simplified GET VALUE routine to use only when retrieving a single attribute.
 * If we need to retrieve more than one, all values should be put 
 * into one arglist and we should make one XtGetValues call (which is MUCH 
 * more efficient).
 */

static void get_something(w, resource, value)
    Widget	w;
    char	*resource, *value;
{
    Arg al[1];
    
    XtSetArg(al[0], resource, value);
    XtGetValues(w, al, 1);
}


/*
 * Keep our boolean array current with the user interface toggle buttons.
 */

static void set_boolean(i, state)
    int	    i;			    /* Widget ID index. */
    int	    state;
{
    toggle_array[i - k_burger_min] = state;

    XmToggleButtonSetState(widget_array[i], 
                                        /* Which widget */
      state,                            /* state it should have. */
      FALSE);                           /* Do not call me back now. */
}



/*
 * Format and update the drink quantity widget.
 */

static void update_drink_display()
{
    char	drink_txt[4];
    XmString	label;

    sprintf(drink_txt, "%2.2d", quantity_vector[k_drinks_index]);
    label = DXmCvtFCtoCS(drink_txt, &bc, &status);
    set_something(widget_array[k_drink_quantity], XmNlabelString, label);
    XmStringFree(label);
}





/* Creates an instance of the help widget for the push buttons in the help
pull-down menu and for context-sensitive help callbacks. */

static void create_help (help_topic)
    XmString	help_topic;
                        
{                  
    Arg             arglist[1];
                          
    start_watch();
    if (!main_help_widget) {                                    
 	if (MrmFetchWidget (s_MrmHierarchy, "main_help", toplevel_widget,
		  	    &main_help_widget, &dummy_class) != MrmSUCCESS)
	s_error ("can't fetch help widget");     
    }      


    if (XtIsManaged(main_help_widget)) {   
       
        if (MrmFetchWidget (s_MrmHierarchy, "main_help", toplevel_widget,
	    	  	    &help_widget[help_num], &dummy_class) != MrmSUCCESS)
	s_error ("can't fetch help widget");
           
        XtSetArg (arglist[0], DXmNfirstTopic, help_topic);
        XtSetValues (help_widget[help_num], arglist, 1);       
        XtManageChild(help_widget[help_num]);    
        help_num++;   
    	stop_watch();
        return; 
    }   
      
    XtSetArg (arglist[0], DXmNfirstTopic, help_topic);
    XtSetValues (main_help_widget, arglist, 1);
    XtManageChild(main_help_widget);     
    stop_watch();
}              
      

/* Switches DECburger into context-sensitive mode and calls the selected
** widget's context-sensitive help callback
*/

static void tracking_help()
{          
      DXmHelpOnContext(toplevel_widget, FALSE);	
}


    


/* Print Widget Creation */

static void create_print() 
{                  
    unsigned int	ac;
    Arg			arglist[10];         
    XtCallbackRec	callback_arg[2];
    
    start_watch();
    
    if (!print_widget) {
                      
	if (MrmFetchWidget (s_MrmHierarchy, "main_print", toplevel_widget,
		  	    &print_widget, &dummy_class) != MrmSUCCESS)
   	s_error ("can't fetch print widget");
            
        callback_arg[0].callback = activate_print;
        callback_arg[0].closure = 0;
        callback_arg[1].callback = NULL;
        callback_arg[1].closure = NULL;
 
        ac = 0;                       
        XtSetArg (arglist[ac], XmNokCallback, callback_arg);ac++;
        XtSetArg (arglist[ac], DXmNsuppressOptionsMask, 
                DXmSUPPRESS_DELETE_FILE | DXmSUPPRESS_OPERATOR_MESSAGE); ac++;
        XtSetValues (print_widget, arglist, ac);      
    }      

    XtManageChild(print_widget);   
    stop_watch();
}                                     
            
     

        
/* Color Mixing Widget Creation.*/

static void create_color()                   
{                                         

    XColor		newcolor;   
    unsigned int	ac;
    Arg			arglist[10];  

    start_watch();

    if (!color_widget) {        
                      
	if (MrmFetchWidget (s_MrmHierarchy, "main_color", toplevel_widget,
			    &color_widget, &dummy_class) != MrmSUCCESS)
	s_error ("can't fetch color mix widget");

	XtSetArg(arglist[0], XmNbackground, &newcolor.pixel);
	XtGetValues(main_window_widget, arglist, 1);
     
	XQueryColor(the_display,
		    XDefaultColormapOfScreen(the_screen), &newcolor);
           
	ac = 0;                          
	XtSetArg (arglist[ac], DXmNorigRedValue, newcolor.red); ac++;		
	XtSetArg (arglist[ac], DXmNorigGreenValue, newcolor.green); ac++; 
	XtSetArg (arglist[ac], DXmNorigBlueValue, newcolor.blue); ac++;
	XtSetValues(color_widget, arglist, ac);     

	savecolor.red = newcolor.red;
	savecolor.green = newcolor.green;
	savecolor.blue = newcolor.blue;
	savecolor.pixel = newcolor.pixel;
    
    } else {

        XtSetArg(arglist[0], XmNbackground, &savecolor.pixel);
        XtGetValues(main_window_widget, arglist, 1);
      
        XQueryColor(the_display,
		    XDefaultColormapOfScreen(the_screen), &savecolor);
    }
                            
    XtManageChild(color_widget);    
    stop_watch();
}                                     

                    
                                  
            
/***************************************************************************
 *
 * This section contains callback routines.
 */     
        
                                   
       
/*
 * Reset the user interface and the application to a known state.
 */

static void reset_values()
{
    int i;

    /*  Reset the toggle buttons and our boolean array. */
    for (i = k_burger_min; i <= k_burger_max; i++) {
                    
        /* The radio box requires that one button be set; we choose medium. */

        set_boolean(i, (i == k_burger_medium));
    }

    /* Reset the burger quantity scale widget and global value. */
    set_something(widget_array[k_burger_quantity], XmNvalue, 0);
    quantity_vector[k_burger_index] = 0;

    /* Reset the fries option menu */
    set_something(widget_array[k_fries_optionmenu], XmNmenuHistory,
		    widget_array[k_fries_medium]);

    /* Reset the fries quantity text widget.  We do not have a global for this.
     * We read the widget whenever we need to know the quantity. */
    XmTextSetString(widget_array[k_fries_quantity], " 0");

    /* Reset the drinks quantity text widget and global value. */
    set_something(widget_array[k_drink_quantity], XmNlabelString, latin_zero);
    quantity_vector[k_drinks_index] = 0;
}


static void apply_values()
{
    char	list_buffer[20];
    XmString	txt, list_txt;
    char	*fries_text;       
    int		i, fries_num;

/*  Take the current settings and write them into the list box.  */

/* Burgers */

    if (quantity_vector[k_burger_index] > 0) {

	/* Put burger quantity in the display string. */
	sprintf(list_buffer, "%d ", quantity_vector[k_burger_index]);
	list_txt = DXmCvtFCtoCS(list_buffer, &bc, &status);

	/* Collect hambuger attributes that are ON. */
	for (i = k_burger_min; i <= k_burger_max; i++)
	    if (toggle_array[i - k_burger_min]) {

		/*  Get the name of the qualifier from the widget and
		 *  add to the display string.
		 */
		get_something(widget_array[i], XmNlabelString, &txt);
		xmstring_append(&list_txt, txt);
		XmStringFree(txt);
		xmstring_append(&list_txt, latin_space);
	    }
                                   
	/* Add hamburger name and add to the display string. */
	xmstring_append(&list_txt, name_vector[k_burger_index]);

	XmListAddItem(widget_array[k_total_order], list_txt, 0);
	XmStringFree(list_txt);
    }                                

/* Fries */
    /*  Text widget does not have a callback.  So we query the widget
     *  now to determine what its value is.  Convert to an integer.
     */
    fries_num = 0;
    fries_text = XmTextGetString(widget_array[k_fries_quantity]);
    sscanf(fries_text, "%d", &fries_num);

    if (fries_num != 0) {    

	/* Put the fries quantity in the display string. */
	sprintf(list_buffer, "%d ", fries_num);
	list_txt = DXmCvtFCtoCS(list_buffer, &bc, &status);

	/*  Get all the qualifiers for the fries. */
	xmstring_append(&list_txt, current_fries);
	xmstring_append(&list_txt, latin_space);

	/* Add fries name and display. */
	xmstring_append(&list_txt, name_vector[k_fries_index]);

	XmListAddItem(widget_array[k_total_order], list_txt, 0);
    }                                

/* Drinks */
    if (quantity_vector[k_drinks_index] > 0) {

	/* Put drinks quantity into the display string. */
	sprintf(list_buffer, "%d ", quantity_vector[k_drinks_index]);
	list_txt = DXmCvtFCtoCS(list_buffer, &bc, &status);

	/*  Now get the qualifiers for the drinks. */
	xmstring_append(&list_txt, current_drink);
	xmstring_append(&list_txt, latin_space);

	/* Add the drink name to the display string. */

	xmstring_append(&list_txt, name_vector[k_drinks_index]);

	XmListAddItem(widget_array[k_total_order], list_txt, 0);
    }
}

/*
 * Clear the order display area in the main window.
 */

static void clear_order()
{                               
    Arg arglist[5];
    int ac = 0;

    XtSetArg(arglist[ac], XmNitemCount, 0);
    ac++;

    XtSetArg(arglist[ac], XmNitems, NULL);
    ac++;

    XtSetArg(arglist[ac], XmNselectedItemCount, 0);
    ac++;

    XtSetArg(arglist[ac], XmNselectedItems, NULL);
    ac++;

    XtSetValues(widget_array[k_total_order], arglist, ac);       
}


/*
 * All push buttons in this application call back to this routine.  We
 * use the tag to tell us what widget it is, then react accordingly.
 */

static void activate_proc(w, tag, reason)
    Widget		w;
    int			*tag;
    XmAnyCallbackStruct *reason;
{
    int		widget_num = *tag;	/* Convert tag to widget number. */
    int		i, value;
    XmString	topic;    

    switch (widget_num) {
        case k_nyi: 
            /* The user activated a 'not yet implemented' push button.  Send
             * the user a message. */
            if (widget_array[k_nyi] == NULL) {
		/* The first time, fetch from the data base. */
                if (MrmFetchWidget(s_MrmHierarchy, "nyi", toplevel_widget,
                  &widget_array[k_nyi], &dummy_class) != MrmSUCCESS) {
                    s_error("can't fetch nyi widget");
                }
            }
            /*  Put up the message box saying 'not yet implemented'. */
            XtManageChild(widget_array[k_nyi]);
            break;
                
        case k_submit_order: 
            /*  This would send the order off to the kitchen. In this case,
             *  we just pretend the order was submitted. */
            clear_order();
            break;

        case k_cancel_order: 
            /*  Clear out the order display. */
            clear_order();
            break;

	case k_ok:
	    /* Set the values and bring down the control box */
	    XtUnmanageChild(widget_array[k_order_box]);
	    apply_values();
	    break;

	case k_apply:
	    /* Set the values, leave the box up */
	    apply_values();
	    break;

        case k_reset: 
	    /* Reset the values, leave the box up */
            reset_values();
            break;

        case k_cancel: 
            /* Reset the values, take the box down */
            XtUnmanageChild(widget_array[k_order_box]);
	    reset_values();
	    break;


        case k_fries_tiny:
        case k_fries_small: 
        case k_fries_medium: 
        case k_fries_large: 
        case k_fries_huge: 

            /*  Some fries size push button was activated, so get the string 
             *  from the interface.  Helps with internationalization. */
	    XmStringFree(current_fries);
            get_something(w, XmNlabelString, &current_fries);
            break;

        case k_drink_add: 

            /*  Increment the drink quantity and update the display. */
            quantity_vector[k_drinks_index]++;
            update_drink_display();
            break;

        case k_drink_sub: 

            /*  Decrement drink quantity, but do not let it go below zero. */
            if (quantity_vector[k_drinks_index] > 0)
                quantity_vector[k_drinks_index]--;
            update_drink_display();
            break;
            
         case k_help_overview:
            topic = DXmCvtFCtoCS("overview", &bc, &status);
            create_help(topic);
	    XmStringFree(topic);
	    break;      
          
          case k_help_about:
            topic = DXmCvtFCtoCS("about", &bc, &status);   
            create_help(topic);
	    XmStringFree(topic);
	    break;      
          
          case k_help_onhelp:
            topic = DXmCvtFCtoCS("onhelp", &bc, &status);
            create_help(topic);          
	    XmStringFree(topic);
     	    break;   
            
          case k_help_sensitive:
            tracking_help(); 
     	    break;      
                  
         case k_print:
            create_print();
     	    break;              
            
         case k_create_options:
            create_color();
     	    break;                  

         default: 
            break;
    }
}




/*
 * The toggle buttons which control the 'hamburger doneness' and toppings
 * call back to this procedure when they change state.  Use the
 * tag to index into the boolean array.  Just keep the booleans current
 * with the user interface.
 */

static void toggle_proc(w, tag, toggle)
    Widget w;
    int *tag;
    XmToggleButtonCallbackStruct *toggle;
{
    toggle_array[*tag - k_burger_min] = toggle->set;
}




/*
 * The drink selection list box calls back to this procedure whenever the
 * user selects a drink.  Just keep the global current drink up to date.
 */

static void list_proc(w, tag, list)
    Widget w;
    int *tag;
    XmListCallbackStruct *list;
{
    XmStringFree(current_drink);
    current_drink = XmStringCopy(list->item);
}



/*
 * The hamburger quantity scale widget will call back to this procedure whenever
 * the user changes it.  Just keep the global hamburger quantity up to date.
 */

static void scale_proc(w, tag, scale)
    Widget w;
    int *tag;
    XmScaleCallbackStruct *scale;
{
    quantity_vector[k_burger_index] = scale->value;
}





/*
 * The next two procedures put up and take down the order box and change
 * the label in the pulldown menu from Create to Dismiss.
 */


/*
 * The user selected the Order push button in the control pulldown menu.
 * We just change the state of the order box.  If the order box is 
 * currently displayed (managed), then remove (unmanage) it.  Otherwise,
 * we manage the order box.
 */

static void show_hide_proc(w, tag, reason)
    Widget		w;
    int			*tag;
    XmAnyCallbackStruct	*reason;
{
    if (XtIsManaged(widget_array[k_order_box]))
        XtUnmanageChild(widget_array[k_order_box]);
    else {
	start_watch();
        XtManageChild(widget_array[k_order_box]);
	DXmFormSpaceButtonsEqually (widget_array[k_order_box],
				    &widget_array[k_ok], 4);
	stop_watch();
    }
}


/*
 * This callback runs as the control pulldown menu is about to be pulled down.
 * We use this opportunity to fetch the order box (if not done already)
 * and to make sure the push button displays the correct label.
 */

static void show_label_proc(w, tag, reason)
    Widget		w;
    int			*tag;  
    XmAnyCallbackStruct	*reason;
{
    if (widget_array[k_order_box] == NULL)
                                        /* The first time, fetch order box. */
      {        
        if (MrmFetchWidget(s_MrmHierarchy, "control_box", toplevel_widget,
          &widget_array[k_order_box], &dummy_class) != MrmSUCCESS) {
            s_error("can't fetch order box widget");
        }     
    }

    /* Now figure out what the label on the push button in the pulldown menu 
     * should be. */

    if (XtIsManaged(widget_array[k_order_box]))
        set_something(widget_array[k_create_order], XmNlabelString, latin_dismiss);
    else
        set_something(widget_array[k_create_order], XmNlabelString, latin_create);
}







/*
 * All widgets that are created call back to this procedure. We just log the 
 * ID in the global array.
 */

static void create_proc(w, tag, reason)
    Widget		w;
    int			*tag;
    XmAnyCallbackStruct	*reason;
{
    int widget_num = *tag;

    widget_array[widget_num] = w;

    /*  For internationalization ease, we capture a few strings from the
     *  widgets themselves.  We could go out and fetch them as needed but
     *  since we use these all the time, this method if more efficient.
     */
    switch (widget_num) {
        case k_burger_label: 
            get_something(w, XmNlabelString, &name_vector[k_burger_index]);
            break;

        case k_fries_label: 
            get_something(w, XmNlabelString, &name_vector[k_fries_index]);
            break;

        case k_drink_label: 
            get_something(w, XmNlabelString, &name_vector[k_drinks_index]);
            break;

	case k_nyi:
	    XtUnmanageChild((Widget)XmMessageBoxGetChild(w, XmDIALOG_CANCEL_BUTTON));
	    XtUnmanageChild((Widget)XmMessageBoxGetChild(w, XmDIALOG_HELP_BUTTON));
	    break;

        default: 
            break;
    }
}




/*
 * The user pushed the exit button, so the application exits.
 */
static void exit_proc(w, tag, reason)
    Widget		w;
    char		*tag;
    XmAnyCallbackStruct *reason;
{           
    if (tag != NULL) 
        printf("Exit - %s\n", tag);

     /* Close the Help System */  
/*    DXmHelpSystemClose(help_context, help_error, "Help System Error"); */

    exit(1);
}           



/*                   
 * Context sensitive help callback.
 */                               
static void sens_help_proc(w, tag, reason)
    Widget              w;
    XmString		tag;
    XmAnyCallbackStruct *reason;    
{
     create_help(tag);            
}




/* Creates a Help System session */
  

static void help_system_proc(w, tag, reason)
    Widget              w;
    int                 *tag;
    XmAnyCallbackStruct *reason; 
                        
{                               
/* DXmHelpSystemDisplay(help_context, decburger_help, "topic", tag,
                            help_error, "Help System Error"); */   
}                    

                         



/*
 * This callback runs just as a pulldown menu is about to be pulled down.
 * It fetches the menu if it is currently empty, and does other
 * special processing as required.
 * We use this opportunity to fetch the order box (if not done already)
 * and to make sure the push button displays the correct label.
 */

static void pull_proc(w, tag, reason)
    Widget		w;
    int			*tag;
    XmAnyCallbackStruct	*reason;
{
    int widget_num = *tag;

    switch (widget_num) {
        case k_file_pdme: 
            if (widget_array[k_file_menu] == NULL) {
                if (MrmFetchWidget(s_MrmHierarchy, "file_menu", widget_array[
                  k_menu_bar], &widget_array[k_file_menu], &dummy_class) != 
                  MrmSUCCESS)
                    s_error("can't fetch file pulldown menu widget");
                set_something(widget_array[k_file_pdme], XmNsubMenuId,
                  widget_array[k_file_menu]);
            }
            break;
    
        case k_edit_pdme: 
            if (widget_array[k_edit_menu] == NULL) {
                if (MrmFetchWidget(s_MrmHierarchy, "edit_menu", widget_array[
                  k_menu_bar], &widget_array[k_edit_menu], &dummy_class) !=
                  MrmSUCCESS)
                    s_error("can't fetch edit pulldown menu widget");
                set_something(widget_array[k_edit_pdme], XmNsubMenuId,
                  widget_array[k_edit_menu]);
            }
            break;
      
        case k_order_pdme:
	    start_watch();      

            if (widget_array[k_order_menu] == NULL) {
                if (MrmFetchWidget(s_MrmHierarchy, "order_menu", widget_array[
                  k_menu_bar], &widget_array[k_order_menu], &dummy_class) !=
                  MrmSUCCESS)
                    s_error("can't fetch order pulldown menu widget");
                set_something(widget_array[k_order_pdme], XmNsubMenuId,
                  widget_array[k_order_menu]);
            }

            /* Figure out what the label of the push button in the pulldown
             * menu should be. */

            if ( widget_array[k_order_box] == NULL )
                if (MrmFetchWidget (
                     s_MrmHierarchy,
                     "control_box",
                     toplevel_widget,
                     &widget_array [k_order_box],
                     &dummy_class) != MrmSUCCESS) 
                       s_error ("can't fetch order box widget");       
            if (XtIsManaged(widget_array[k_order_box]))
                set_something(widget_array[k_create_order], XmNlabelString,
                  latin_dismiss);
            else
                set_something(widget_array[k_create_order], XmNlabelString,
                  latin_create);

	    stop_watch();
            break;

    }

}
                                

/* Print Widget OK Callback */
            
static void activate_print(w, tag, reason) 
     Widget                  w;
     int                     *tag;        
     XmAnyCallbackStruct     *reason;    
     
{     
    unsigned long int	l_status;		    
    XmString            file_pointer[1];
    int			l_num_names,l_i;
    char		at_buffer[30];
    FILE                *fp;

    if ((fp = fopen("order.txt", "w")) != NULL) {

     fprintf(fp, "Function Not Yet Implemented\n");
     fclose(fp);                  

     file_pointer[0] = XmStringCreateLtoR("order.txt", XmSTRING_OS_CHARSET);
             
     l_status = DXmPrintWgtPrintJob(print_widget, file_pointer, 1);

     printf("DXmPrintWgtPrintJob return status: %x\n",l_status);
                         
    }

}

   
    
/* Color Mix OK Callback */
               
static void ok_color_proc(widget_id, tag, reason)
   Widget                     widget_id;
   int                        *tag;        
   DXmColorMixCallbackStruct  *reason;
{                        
   int         ac;
   Arg         arglist[10];
   XColor      newcolor;
   
   newcolor.red = reason->newred;
   newcolor.green = reason->newgrn;
   newcolor.blue = reason->newblu;
        
   if (XAllocColor(the_display,
                  XDefaultColormapOfScreen(the_screen), &newcolor)) {

	ac = 0;                            
	XtSetArg (arglist[ac], XmNbackground, newcolor.pixel);ac++;   
	XtSetValues(widget_array[k_total_order], arglist, ac);
	XtSetValues(main_window_widget, arglist, ac);
    }         
            
    else 
        s_error ("can't allocate color cell");       
   
    XtUnmanageChild(color_widget);     

    ac = 0;                     
    XtSetArg (arglist[ac], DXmNorigRedValue, newcolor.red);ac++;	     	
    XtSetArg (arglist[ac], DXmNorigGreenValue, newcolor.green);ac++; 
    XtSetArg (arglist[ac], DXmNorigBlueValue, newcolor.blue);ac++;          
    XtSetValues(color_widget, arglist, ac);     
}
             

/* Color Mix Apply Callback */
                      
static void apply_color_proc(widget_id, tag, reason)
    Widget			widget_id;
    int				*tag;        
    DXmColorMixCallbackStruct	*reason;

{                        
    int		ac;
    Arg		arglist[10];
    XColor	newcolor;
  
    newcolor.red = reason->newred;
    newcolor.green = reason->newgrn;
    newcolor.blue = reason->newblu;
    
    if (XAllocColor(the_display,
                  XDefaultColormapOfScreen(the_screen), &newcolor)) {
	ac = 0;                            
	XtSetArg (arglist[ac], XmNbackground, newcolor.pixel);ac++;   
	XtSetValues(widget_array[k_total_order], arglist, ac);
	XtSetValues(main_window_widget, arglist, ac);
    }         

    else 
        s_error ("can't allocate color cell");       
             
}




/* Color Mix Cancel Callback */
               
static void cancel_color_proc(widget_id, tag, reason)
    Widget			widget_id;
    int				*tag;        
    DXmColorMixCallbackStruct	*reason;

{                        

    int         ac;
    Arg         arglist[10];

    XtUnmanageChild(color_widget);     
        
    ac = 0;                            
    XtSetArg (arglist[ac], XmNbackground, savecolor.pixel);ac++;   
    XtSetValues(widget_array[k_total_order], arglist, ac);
        
    XtSetValues(main_window_widget, arglist, ac);
  
}                   
                    

/* append string2 to string1 without losing memory */
static void xmstring_append (string1, string2)
    XmString	*string1;
    XmString	string2;
{
    XmString	xmtemp;

    xmtemp = XmStringConcat(*string1, string2);
    XmStringFree(*string1);
    *string1 = xmtemp;                            
}
        
static void start_watch()   
{
	if (watch == (Cursor)NULL)
	    watch = DXmCreateCursor(main_window_widget, decw$c_wait_cursor);
	XDefineCursor(  the_display, XtWindow(main_window_widget), watch );
	XFlush( the_display );
}


static void stop_watch()
{
	XUndefineCursor(the_display, XtWindow(main_window_widget));
}




/* Toolkit Print Widget Example.  Documented, but not needed   
 *  
 *    callback_arg[0].callback = activate_print;
 *    callback_arg[0].closure = 0;
 *    callback_arg[1].callback = NULL;
 *    callback_arg[1].closure = NULL;
 *
 *    num_copies = 2;        
 *
 *    ac = 0;                          
 *                                     
 *       XtSetArg (arglist[ac], DXmNnumberCopies, num_copies); ac++;  
 *       XtSetArg (arglist[ac], DXmNunmanageOnOk, TRUE); ac++;  
 *       XtSetArg (arglist[ac], DXmNunmanageOnCancel, TRUE); ac++;  
 *       XtSetArg (arglist[ac], XmNokCallback, callback_arg);ac++;
 *       XtSetArg (arglist[ac], DXmNsuppressOptionsMask,
 *            DXmSUPPRESS_DELETE_FILE | DXmSUPPRESS_OPERATOR_MESSAGE); ac++;
 *                          
 *       print_widget = DXmCreatePrintDialog (toplevel_widget,
 *	       		                "Print Widget",
 *   	       	       	                 arglist, ac);       
 *                   
 *       XtManageChild(print_widget);       
 *       return; 
 *
 *      }                                  
 */

        


/* Toolkit Color Mix Widget Example.  Documented, but not needed */  

/*
 * static void create_color()                   
 * {                                         
 *          unsigned int        ac;
 *          Arg                 arglist[10];         
 *          XtCallbackRec       ok_callback_arg[2];
 *          XtCallbackRec       apply_callback_arg[2];
 *          XtCallbackRec       cancel_callback_arg[2];
 *          XColor              newcolor;   
 *          Arg                 al[1];                     
 * 
 *          if (!color_widget) {
 *                               
 *          apply_callback_arg[0].callback = apply_color_proc;
 *          apply_callback_arg[0].closure = 0;     
 *          apply_callback_arg[1].callback = NULL;
 *          apply_callback_arg[1].closure = NULL;
 *      
 *          cancel_callback_arg[0].callback = cancel_color_proc;
 *          cancel_callback_arg[0].closure = 0;    
 *          cancel_callback_arg[1].callback = NULL;
 *          cancel_callback_arg[1].closure = NULL;
 *      
 *          ok_callback_arg[0].callback = ok_color_proc;
 *          ok_callback_arg[0].closure = 0;          
 *          ok_callback_arg[1].callback = NULL;
 *          ok_callback_arg[1].closure = NULL;
 * 
 * 
 *          XtSetArg(al[0], XmNbackground, &newcolor.pixel);
 *          XtGetValues(main_window_widget, al, 1);
 * 
 *     
 *          XQueryColor(XtDisplay(toplevel_widget), 
 *                   XDefaultColormapOfScreen(the_screen), &newcolor);
 *           
 *          ac = 0;                          
 *                  
 *          XtSetArg (arglist[ac], XmNcancelCallback, cancel_callback_arg);ac++;
 *          XtSetArg (arglist[ac], XmNokCallback, ok_callback_arg); ac++; 
 *          XtSetArg (arglist[ac], XmNapplyCallback, apply_callback_arg); ac++;
 *          XtSetArg (arglist[ac], DXmNorigRedValue, newcolor.red); ac++;		
 *          XtSetArg (arglist[ac], DXmNorigGreenValue, newcolor.green); ac++; 
 *          XtSetArg (arglist[ac], DXmNorigBlueValue, newcolor.blue); ac++;          
 *          XtSetArg (arglist[ac], DXmNcolorModel, DXmColorModelPicker); ac++;          
 *                                                 
 *          color_widget = DXmCreateColorMixDialog (toplevel_widget, 
 *                                                "Color Mix Widget",
 *       	       	       	                 arglist, ac);       
 *
 *          savecolor.red = newcolor.red;
 *          savecolor.green = newcolor.green;
 *          savecolor.blue = newcolor.blue;
 *
 *          XtManageChild(color_widget);       
 *          return;                    
 *       }                                  
 *                              
 *          XtSetArg(arglist[0], XmNbackground, &savecolor.pixel);
 *          XtGetValues(main_window_widget, arglist, 1);
 *     
 *          XQueryColor(XtDisplay(toplevel_widget), 
 *          XDefaultColormapOfScreen(the_screen), &savecolor);
 *
 *          XtManageChild(color_widget);   
 *
 *      }     
 * 
 */


/* Toolkit help creation routine.  Documented, but not needed. */ 

/*
 * static void create_help (topic)
 *           XmString   topic;
 * {
 *
 *   unsigned int    ac;
 *   Arg             arglist[10];
 *   XmString        appname, glossarytopic, overviewtopic, libspec;
 *   static Widget   help_widget = NULL;
 * 
 *
 *     if (!help_widget) {
 *     ac = 0;
 *     appname = XmStringCreateLtoR("Toolkit Help", XmSTRING_ISO8859_1);
 *     glossarytopic = XmStringCreateLtoR("glossary", XmSTRING_ISO8859_1);
 *     overviewtopic = XmStringCreateLtoR("overview", XmSTRING_ISO8859_1);
 *     libspec = XmStringCreateLtoR("decburger.hlb", XmSTRING_ISO8859_1);
 *          
 *     XtSetArg(arglist[ac], DXmNapplicationName, appname); ac++;
 *     XtSetArg(arglist[ac], DXmNglossaryTopic, glossarytopic); ac++;
 *     XtSetArg(arglist[ac], DXmNoverviewTopic, overviewtopic); ac++;
 *     XtSetArg(arglist[ac], DXmNlibrarySpec, libspec); ac++;
 *     XtSetArg(arglist[ac], DXmNfirstTopic, topic); ac++;
 *
 *     help_widget = DXmCreateHelpDialog (toplevel_widget,
 *                                        "Toolkit Help",
 *                                         arglist, ac);
 *     XmStringFree(appname);
 *     XmStringFree(glossarytopic);
 *     XmStringFree(overviewtopic);
 *     XmStringFree(libspec);
 *
 *     XtManageChild(help_widget);
 *
 *     return;
 *   }
 *
 *     if (XtIsManaged(help_widget)) {
 *     ac = 0;
 *     appname = XmStringCreateLtoR("Toolkit Help", XmSTRING_ISO8859_1);
 *     glossarytopic = XmStringCreateLtoR("glossary", XmSTRING_ISO8859_1);
 *     overviewtopic = XmStringCreateLtoR("overview", XmSTRING_ISO8859_1);
 *     libspec = XmStringCreateLtoR("decburger.hlb", XmSTRING_ISO8859_1);
 *
 *     XtSetArg(arglist[ac], DXmNapplicationName, appname); ac++;
 *     XtSetArg(arglist[ac], DXmNglossaryTopic, glossarytopic); ac++;
 *     XtSetArg(arglist[ac], DXmNoverviewTopic, overviewtopic); ac++;
 *     XtSetArg(arglist[ac], DXmNlibrarySpec, libspec); ac++;
 *     XtSetArg(arglist[ac], DXmNfirstTopic, topic); ac++;
 *
 *     help_array[low_num] = DXmCreateHelpDialog (toplevel_widget,
 *                                                "Toolkit Help",
 *                                                 arglist, ac);
 *     XmStringFree(appname);
 *     XmStringFree(glossarytopic);
 *     XmStringFree(overviewtopic);
 *     XmStringFree(libspec);
 *
 *     XtManageChild(help_array[low_num]);
 *     low_num++;
 *     return;
 *   }
 *
 *   ac = 0;
 *   XtSetArg (arglist[ac], DXmNfirstTopic, topic); ac++;
 *   XtSetValues (help_widget, arglist, ac);
 *   XtManageChild(help_widget);
 * }
 */

  

                 

