/****************************************************************************/
/*                                                                          */
/*  VolVis is a volume visualization system for investigating, manipulating */
/*  and rendering geometric and volumetric data.                            */
/*                                                                          */
/*  Copyright (C) 1993 by the Research Foundation of the State University   */
/*                            of New York                                   */
/*                                                                          */
/*  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 1, 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.               */
/*                                                                          */
/*  For information on VolVis, contact us at:                               */
/*                                                                          */
/*                volvis@cs.sunysb.edu                         (email)      */
/*                                                                          */
/*                Lisa Sobierajski & Ricardo Avila             (US Mail)    */
/*                Department of Computer Science                            */
/*                State University of New York at Stony Brook               */
/*                Stony Brook, New York  11794-4400                         */
/*                                                                          */
/****************************************************************************/



/*
 *                  File: MOTIF_ide_selection.c
 *                  Author: He, Taosong
 *                  Date: 1/19/93 
 *           Description: The MOTIF routines of selection queue operations
 *  Modification History:
 *
 *         who?         when?           why?
 *    -----------------------------------------------------------
 *
 */

/******************************************************************/
/*               The MOTIF include file                           */
/******************************************************************/

#include <X11/StringDefs.h>
#include <X11/Intrinsic.h>
#include <Xm/Xm.h>
#include <Xm/PanedW.h>
#include <Xm/DrawingA.h>
#include <Xm/Label.h>
#include <Xm/PushB.h>
#include <Xm/RowColumn.h>
#include <Xm/BulletinB.h>
#include <Xm/DialogS.h>
#include <X11/Xutil.h>

/******************************************************************/
/*                The standard C include file                     */
/******************************************************************/

#include <varargs.h>
#include <stdio.h>

/******************************************************************/
/*                  VolVis include file                           */
/******************************************************************/

#include "C_ide.h"
#include "MOTIF_windefs.h"

/*
 *        Procedure Name: C_get_select
 *          Return Value: A selection number.
 *       Input Variables: drawingarea
 *      Output Variables:
 *      Update Variables:
 *      Global Variables:
 *           Description: This function will return a selection number. 
 *                        The system keeps a selection queue for each 
 *                        drawingarea (must be initialized first.) When 
 *                        this function is called, the system return 
 *                        the head of the queue.
 */

int C_get_select(drawingarea)
Widget drawingarea;
{
  extern void X_get_window_index();
  extern int  C_get_select_number();

  int  window_index;

  X_get_window_index(XtWindow(drawingarea), &window_index);

  return(C_get_select_number(window_index, 0) );
}

/*
 *        Procedure Name: C_flush_select
 *          Return Value: 
 *       Input Variables: drawingarea
 *      Output Variables:
 *      Update Variables:
 *      Global Variables:
 *           Description: This function flush the selection queue 
 *                        for the specific drawingarea.
 */

void C_flush_select(drawingarea)
  Widget      drawingarea;
{
  while (C_get_select(drawingarea) >=0 );
}

/*
 *        Procedure Name:  C_get_window
 *          Return Value:
 *       Input Variables:  drawingarea
 *      Output Variables:
 *      Update Variables:
 *      Global Variables:
 *           Description:  This function will return a window_event.
 *                         The system keeps a window event queue for each 
 *                         drawingarea (must be initialized first.) When 
 *                         this function is called, the system return the 
 *                         head of the queue.
 */

int C_get_window(drawingarea)
Widget drawingarea;
{
  extern int  C_get_window_c();
  extern void X_get_window_index();

  int  window_index;

  X_get_window_index(XtWindow(drawingarea), &window_index);

  return(C_get_window_c(window_index));

}

/*
 *        Procedure Name: C_flush_window
 *          Return Value:
 *       Input Variables: drawingarea
 *      Output Variables:
 *      Update Variables:
 *      Global Variables:
 *           Description: This function flush the window event queue 
 *                        for the specific drawingarea.
 */

void C_flush_window(drawingarea)
  Widget         drawingarea;
{
  while (C_get_window(drawingarea)>=0);
}

/*            Global variable: msg_bulletin;
 *                             This is the information panel in the 
 *                             selction queue ontrol panel.
 */

static Widget msg_bulletin;

/*
 *        Procedure Name: get_select_proc
 *          Return Value:
 *       Input Variables: drawingarea
 *      Output Variables:
 *      Update Variables:
 *      Global Variables:
 *           Description: Call back function.
 *                        Get the header of  selection queue interactively.
 */

void get_select_proc (w,drawingarea, call_data)
  Widget w;
  Widget drawingarea;
  XmAnyCallbackStruct *call_data;
{
  extern void xs_wprintf();
  char        temp_str[20];
  int select;

  select = C_get_select(drawingarea);

  if ( select != -1)
       {
          sprintf(temp_str, "get Selection %d !!", select);
          xs_wprintf(msg_bulletin, temp_str);
       }
  else xs_wprintf(msg_bulletin," Selection Queue is EMPTY!!");
}

/*
 *        Procedure Name: flush_select_proc
 *          Return Value:
 *       Input Variables: drawingarea
 *      Output Variables:
 *      Update Variables:
 *      Global Variables:
 *           Description: Call back function. 
 *                        Flush selection queue interactively.
 */

void flush_select_proc(w,drawingarea,call_data)
  Widget w;
  Widget drawingarea;
  XmAnyCallbackStruct *call_data;
{
  extern void xs_wprintf();
  C_flush_select(drawingarea);
  xs_wprintf(msg_bulletin,"Flush Selection Queue!!");
}

/*
 *        Procedure Name: C_insert_window
 *          Return Value:
 *       Input Variables: drawingarea 
 *                        name of the window event: window_event
 *      Output Variables:
 *      Update Variables:
 *      Global Variables:
 *           Description:  An event handler. insert an window event to the
 *                         window event queue for the specific drawingarea.
 */

void C_insert_window(drawingarea, window_event, event)
  Widget drawingarea;
  int window_event;
  XEvent event;
{
  extern void X_get_window_index();

  int  window_index;

  X_get_window_index(XtWindow(drawingarea), &window_index);

  C_insert_window_c(window_index,window_event );
}


/*
 *        Procedure Name: get_event_proc
 *          Return Value:
 *       Input Variables: drawingarea
 *      Output Variables:
 *      Update Variables:
 *      Global Variables:
 *           Description: Call back function.
 *                        Get the header of  window event queue interactively.
 */

void get_event_proc (w,drawingarea, call_data)
  Widget w;
  Widget drawingarea;
  XmAnyCallbackStruct *call_data;
{
  extern void xs_wprintf();
   
  switch (C_get_window(drawingarea))
   {
         case C_WIN_EXPOSE: xs_wprintf(msg_bulletin,"get EXPOSE event!!");
              break;
         case C_WIN_RESIZE: xs_wprintf(msg_bulletin,"get RESIZE event!!");
              break;
         case C_WIN_ENTER: xs_wprintf(msg_bulletin,"get ENTER event!!");
              break;
         case C_WIN_LEAVE: xs_wprintf(msg_bulletin,"get LEAVE event!!");
              break;
         default: xs_wprintf(msg_bulletin," Event Queue is EMPTY!!");
              break;
     }
}

/*
 *        Procedure Name: flush_event_proc
 *          Return Value:
 *       Input Variables: drawingarea
 *      Output Variables:
 *      Update Variables:
 *      Global Variables:
 *           Description: Call back function.
 *                        Flush window event queue interactively.
 */

void flush_event_proc(w,drawingarea,call_data)
  Widget w;
  Widget drawingarea;
  XmAnyCallbackStruct *call_data;
{
  extern void xs_wprintf();

  C_flush_window(drawingarea);
  xs_wprintf(msg_bulletin,"Flush Win Event Queue!!");
}


/*        Global variable:   selection_pop_dialog
 *                            The selection queue control panel 
 */ 

static Widget                 selection_pop_dialog;

/*
 *        Procedure Name: C_selection_ui
 *          Return Value: void
 *       Input Variables: drawingarea
 *      Output Variables:
 *      Update Variables:
 *      Global Variables:
 *           Description: Create an selection queue control panel for the 
 *                        specific drawingarea.
 */

C_selection_ui(drawingarea)
  Widget drawingarea;
{

  Widget command,button[10];
  Arg args[10];
  int n=0;
  XmString  string;


  extern C_WindowDefs    window_defs;
  extern Widget          vv_toplevel;

  n = 0;
  XtSetArg( args[n], XmNautoUnmanage, False ); n++;
  C_Set_Color_Dialog( args, n, window_defs );
  selection_pop_dialog = XmCreateBulletinBoardDialog(vv_toplevel,
                           "Sel Control Panel", args, n);

  n = 0;
  XtSetArg( args[n], XmNx, 10 ); n++;
  XtSetArg( args[n], XmNy, 10 ); n++;
  string = XmStringCreate (" msg ", XmSTRING_DEFAULT_CHARSET);
  XtSetArg (args[n], XmNlabelString, string); n++;
  C_Set_Color_Label( args, n, window_defs );
  msg_bulletin=XmCreateLabel (selection_pop_dialog, " msg ", args, n);
  XmStringFree (string);

  n=0;
  XtSetArg( args[n], XmNx, 10 ); n++;
  XtSetArg( args[n], XmNy, 40 ); n++;
  XtSetArg(args[n],XmNorientation,XmHORIZONTAL);n++;
  XtSetArg(args[n],  XmNorientation,XmHORIZONTAL);n++;
  XtSetArg( args[n], XmNpacking, XmPACK_COLUMN); n++;
  XtSetArg( args[n], XmNnumColumns, 2); n++;
  C_Set_Color_RowColumn(args, n, window_defs );
  command=XmCreateRowColumn (selection_pop_dialog, "command", args, n);

  n =0;
  string = XmStringCreate ("Get_Window_Event", XmSTRING_DEFAULT_CHARSET);
  XtSetArg (args[n], XmNlabelString, string); n++;
  C_Set_Color_Button( args, n, window_defs );
  button[0]=XmCreatePushButton(command, "Get_Window_Event", args, n);
  XtAddCallback(button[0],XmNactivateCallback,get_event_proc,drawingarea);
  XmStringFree (string);

  n = 0;
  string = XmStringCreate ("Flush_Win_Event", XmSTRING_DEFAULT_CHARSET);
  XtSetArg (args[n], XmNlabelString, string); n++;
  C_Set_Color_Button( args, n, window_defs );
  button[1]=XmCreatePushButton(command, "Flush_Win_Event",args, n);
  XtAddCallback(button[1],XmNactivateCallback,flush_event_proc,drawingarea);
  XmStringFree (string);

  n = 0;
  string = XmStringCreate ("Get_Selection", XmSTRING_DEFAULT_CHARSET);
  XtSetArg (args[n], XmNlabelString, string); n++;
  C_Set_Color_Button( args, n, window_defs );
  button[2]=XmCreatePushButton(command, "Get_Selection",args, n);
  XtAddCallback(button[2],XmNactivateCallback,get_select_proc,drawingarea);
  XmStringFree (string);

  n =0;
  string = XmStringCreate ("Flush_Selection", XmSTRING_DEFAULT_CHARSET);
  XtSetArg (args[n], XmNlabelString, string); n++;
  C_Set_Color_Button( args, n, window_defs );
  button[3]=XmCreatePushButton(command, "Flush_Selection",args, n);
  XtAddCallback(button[3],XmNactivateCallback,flush_select_proc,drawingarea);
  XmStringFree (string);

  XtManageChildren(button, 4);
  XtManageChild(command);
  XtManageChild(msg_bulletin);
  XtManageChild(selection_pop_dialog);
}


/*
 *        Procedure Name: selection_panel_control
 *          Return Value:
 *       Input Variables: drawingarea;
 *                        window_index;
 *                        Event
 *      Output Variables:
 *      Update Variables:
 *      Global Variables: 
 *           Description: Check whether the next event is a special event.
 *                        If so, doing the correspondent action. If the
 *                        machine can not handle keyboard event for the 
 *                        drawingarea, this function first insert event in
 *                        the selection queue.
 */

void selection_panel_control(drawingarea, process_status, Event) 
Widget drawingarea;
int process_status;
Device_Event *Event;
{
   extern int   C_get_select_number();
   extern void  start_end_virtual_device();
   extern void  X_get_window_index();
   extern void  C_insert_select(); 

   extern C_IDE_window_information IDE_active_window_information;

   int window_index;

   window_index = IDE_active_window_information.window_index;
 
   switch (Event->type)
    {
     case KeyPress:
         C_insert_select(C_KEYBOARD, Event, window_index);
         break;
     case ButtonPress:
         C_insert_select(C_MOUSE, Event, window_index);
         break;
     case SPACEBALLBUTTON:
         C_insert_select(C_SPACEBALL, Event, window_index);  
       default:
           break; 
  }

   if (C_get_select_number(window_index,1) == C_MAX_SELECTION_NUMBER)
         start_end_virtual_device(drawingarea, process_status, window_index);
}



/*
 *        Procedure Name: C_activate_selection_queue
 *          Return Value:
 *       Input Variables: drawingarea
 *      Output Variables:
 *      Update Variables:
 *      Global Variables:
 *           Description: Activate window event queue
 */

void C_activate_selection_queue(drawingarea)
Widget drawingarea;
{
  XtAddEventHandler(drawingarea,EnterWindowMask,FALSE,
                    C_insert_window, C_WIN_ENTER);
  XtAddEventHandler(drawingarea,LeaveWindowMask,FALSE,
                    C_insert_window, C_WIN_LEAVE);
  XtAddEventHandler(drawingarea,ExposureMask,FALSE,
                    C_insert_window, C_WIN_EXPOSE);
  XtAddEventHandler(drawingarea,ResizeRedirectMask,FALSE,
                    C_insert_window, C_WIN_RESIZE);
}


void C_get_selection_fun(selection, drawingarea)
int *selection;
Widget drawingarea;
{
    extern int  IDE_vd_active[C_MAX_WINDOW_NUMBER];
    extern C_IDE_window_information IDE_active_window_information;

    extern XtAppContext     vv_app_context;

    XEvent theEvent;

    int window_index;

    XtInputMask mask;

    window_index = IDE_active_window_information.window_index;

/*
    while ( (XCheckWindowEvent(XtDisplay(drawingarea), XtWindow(drawingarea),
                            ButtonPressMask | EnterWindowMask |
                            LeaveWindowMask | KeyPressMask, &theEvent)) &&
            (IDE_vd_active[window_index]) )
     {
        if ((theEvent.type == KeyPress) || (theEvent.type == ButtonPress))
           {
             selection_panel_control(drawingarea, 1, &theEvent);
             XtDispatchEvent(&theEvent);
           }
     }
*/
    while ( (mask = XtAppPending(vv_app_context))
             && IDE_vd_active[window_index] )
      {
       if ( mask ==XtIMXEvent) 
        {
          XtAppNextEvent(vv_app_context, &theEvent);
          switch (theEvent.type)
            {
              case KeyPress:
                if ( theEvent.xkey.window == XtWindow(drawingarea))
                 selection_panel_control(drawingarea, 1, &theEvent);
                break;
              case ButtonPress:
                if (theEvent.xbutton.window == XtWindow(drawingarea))
                  selection_panel_control(drawingarea, 1, &theEvent);
                break;
              default:
                XtDispatchEvent(&theEvent);
                break;
             }
         }  
       else
           XtAppProcessEvent(vv_app_context, XtIMTimer | XtIMAlternateInput);
        
      }

     *selection = C_get_select_number(window_index, 0);
}
