/*******************************************************************************
*                                                                              *
*                                   Viewmol                                    *
*                                                                              *
*                              M O U S E C B . C                               *
*                                                                              *
*                 Copyright (c) Joerg-R. Hill, October 2003                    *
*                                                                              *
********************************************************************************
*
* $Id: mousecb.c,v 1.6 2003/11/07 11:07:55 jrh Exp $
* $Log: mousecb.c,v $
* Revision 1.6  2003/11/07 11:07:55  jrh
* Release 2.4
*
* Revision 1.5  2000/12/10 15:13:11  jrh
* Release 2.3
*
* Revision 1.4  1999/05/24 01:26:47  jrh
* Release 2.2.1
*
* Revision 1.3  1999/02/07 21:53:43  jrh
* Release 2.2
*
* Revision 1.2  1998/01/26 00:48:52  jrh
* Release 2.1
*
* Revision 1.1  1996/12/10  18:42:34  jrh
* Initial revision
*
*/
#include<X11/Intrinsic.h>
#include<X11/extensions/XInput.h>
#include<Xm/Xm.h>
#include<Xm/PushBG.h>
#include<Xm/RowColumn.h>
#include<GL/glu.h>
#include "viewmol.h"

void processInput(Widget, caddr_t, XmDrawingAreaCallbackStruct *);
void processSpaceballEvent(XEvent *);
void doMenu(Widget, Widget, XmDrawingAreaCallbackStruct *);

extern void setMenuItem(int, int);
extern Widget makeMenu(Widget, int, char *, struct MenuItem *);
extern void redraw(int);
extern void drawSpectrum(Widget, caddr_t, XmDrawingAreaCallbackStruct *);
extern void drawHistory(Widget, caddr_t, XmDrawingAreaCallbackStruct *);
extern void drawMODiagram(Widget, caddr_t, XmDrawingAreaCallbackStruct *);
extern void viewerMouseAction(XEvent *, int);
extern void spectrumMouseAction(XmDrawingAreaCallbackStruct *, int);
extern void historyMouseAction(unsigned int, int, int, int);
extern void MODiagramMouseAction(XmDrawingAreaCallbackStruct *, int);
extern void viewerKeyAction(KeySym);
extern void spectrumKeyAction(KeySym);
extern void historyKeyAction(KeySym);
extern void MODiagramKeyAction(KeySym);
extern void getTranslation(int, int, int);
extern void getRotation(int, int, int, int);
extern void getEnlargement(int, int);
extern void zoomIn(Widget, XmDrawingAreaCallbackStruct *);
extern void redraw(int);
extern void switchPointerDevice(void);

extern struct WINDOW windows[];
extern float *transObject, *rotObject;
extern int lines, label, showForces;
extern int rotateXY, rotateZ;
extern int showMenu, primitive, selectAtom, iwavef;
extern int picking, swapBuffers, moveItem, simplify;
extern int spaceballButtonPress, spaceballMotionNotify;
extern int sensitivity, pythonInterrupt;
extern Widget bfMenu;

void processInput(Widget w, caddr_t client_data,
                  XmDrawingAreaCallbackStruct *data)
{
  KeySym keysym;
  XComposeStatus status;
  static int primitiveSave;
  char buffer[2];

  if (data->reason == XmCR_INPUT)
  {
    switch (data->event->type)
    {
      case ButtonPress:   if (w == windows[VIEWER].widget)
                          {
                            if (data->event->xbutton.button != Button3 &&
                                simplify && (moveItem & 0x7fffffff) > WORLD)
                            {
                              primitiveSave=primitive;
                              primitive=GLU_LINE;
                            }
                            if (data->event->xbutton.button == Button3)
                            {
                              if (showMenu)
                                doMenu(w, windows[VIEWER].menu, data);
                              else
                                viewerMouseAction(data->event, TRUE);
                            }
                            else
                            {
                              getRotation(data->event->xmotion.x,
                                          data->event->xmotion.y,
                                          data->event->xmotion.x, 2);
                              viewerMouseAction(data->event, TRUE);
                            }
                          }
                          else if (w == windows[SPECTRUM].widget)
                          {
                            if (data->event->xbutton.button == Button3)
                              doMenu(w, windows[SPECTRUM].menu, data);
                            else
                              spectrumMouseAction(data, TRUE);
                          }
                          else if (w == windows[HISTORY].widget)
                          {
                            if (data->event->xbutton.button == Button3)
                              doMenu(w, windows[HISTORY].menu, data);
                            else
                              historyMouseAction(data->event->xbutton.button,
                                                 TRUE, data->event->xbutton.x,
                                                 data->event->xbutton.y);
                          }
                          else if (w == windows[MO].widget)
                          {
                            if (data->event->xbutton.button == Button3)
                              doMenu(w, windows[MO].menu, data);
                            else
                              MODiagramMouseAction(data, TRUE);
                          }
                          break;
      case ButtonRelease: if (w == windows[VIEWER].widget)
                          {
                            if (data->event->xbutton.button != Button3 &&
                                simplify && moveItem > WORLD)
                              primitive=primitiveSave;
                            viewerMouseAction(data->event, FALSE);
                            rotateXY=rotateZ=0;
/*                          return; */
                          }
                          else if (w == windows[SPECTRUM].widget)
                            spectrumMouseAction(data, FALSE);
                          else if (w == windows[HISTORY].widget)
                            historyMouseAction(data->event->xbutton.button,
                                               FALSE, data->event->xbutton.x,
                                               data->event->xbutton.y);
                          else if (w == windows[MO].widget)
                            MODiagramMouseAction(data, FALSE);
                          break;
      case KeyPress:      buffer[0]=buffer[1]='\0';
                          XLookupString((XKeyEvent *)data->event, buffer, 2,
                                        &keysym, &status); 
                          if ((int)(buffer[0]) == 3)
                            pythonInterrupt=TRUE;
                          if (w == windows[VIEWER].widget)
                            viewerKeyAction(keysym);
                          if (w == windows[SPECTRUM].widget)
                            spectrumKeyAction(keysym);
                          else if (w == windows[HISTORY].widget)
                            historyKeyAction(keysym);
                          else if (w == windows[MO].widget)
                            MODiagramKeyAction(keysym);
                          break;
      case MotionNotify:  if (data->event->xmotion.state & Button1Mask)
                          {
                            if (w == windows[VIEWER].widget)
                            {
                              if (data->event->xmotion.state & ShiftMask)
                                getTranslation(data->event->xmotion.x,
                                               data->event->xmotion.y, 2);
                              else
                                getRotation(data->event->xmotion.x,
                                            data->event->xmotion.y, -1, 0);
                            }
                            else if (w == windows[HISTORY].widget)
                            {
                              historyMouseAction(Button1, TRUE,
                                                 data->event->xmotion.x,
                                                 data->event->xmotion.y);
                            }
                          }
                          else if (data->event->xmotion.state & Button2Mask)
                          {
                            if (w == windows[VIEWER].widget)
                              if (data->event->xmotion.state & ShiftMask)
                                getEnlargement(data->event->xmotion.x, 2);
                              else
                                getRotation(-1, -1, data->event->xmotion.x, 0);
                            else
                            {
                              zoomIn(w, data);
                              return;
                            }
                          }
                          else
                            return;
                          break;
      default:            break;
    }
    if (w == windows[VIEWER].widget)
    {
      windows[VIEWER].mouseX=data->event->xmotion.x;
      windows[VIEWER].mouseY=data->event->xmotion.y;
    }
    redraw(VIEWER);
    if (w == windows[SPECTRUM].widget)
    {
      windows[SPECTRUM].mouseX=data->event->xmotion.x;
      windows[SPECTRUM].mouseY=data->event->xmotion.y;
      drawSpectrum(w, client_data, data);
    }
    else if (w == windows[HISTORY].widget)
    {
/*    windows[HISTORY].mouseX=data->event->xmotion.x;
      windows[HISTORY].mouseY=data->event->xmotion.y; */
      drawHistory(w, client_data, data);
    }
    else if (w == windows[MO].widget)
    {
      windows[MO].mouseX=data->event->xmotion.x;
      windows[MO].mouseY=data->event->xmotion.y;
      drawMODiagram(w, client_data, data);
    }
  }
}

void processSpaceballEvent(XEvent *event)
{
  XDeviceMotionEvent *motionEvent;
  XDeviceButtonEvent *buttonEvent;
  static int sensitivity=4, i;

  if (event->type == spaceballMotionNotify)
  {
    motionEvent=(XDeviceMotionEvent *)event;
    getRotation(motionEvent->axis_data[3]/sensitivity,
                motionEvent->axis_data[4]/sensitivity,
                motionEvent->axis_data[5]/sensitivity, 1);
    rotateXY=rotateZ=1;
    getTranslation(motionEvent->axis_data[0]/(10*sensitivity),
                   -motionEvent->axis_data[2]/(10*sensitivity), 1);
    getEnlargement(-motionEvent->axis_data[1]/(10*sensitivity), 1);
    rotateXY=rotateZ=0;
  }
  else if (event->type == spaceballButtonPress)
  {
    buttonEvent=(XDeviceButtonEvent *)event;
    if (buttonEvent->button == Button1)
    {
      i=3*(windows[VIEWER].set+3);
      transObject[i]=transObject[i+1]=transObject[i+2]=0.0;
      redraw(VIEWER);
    }
    if (buttonEvent->button == Button2)
    {
      i=4*(windows[VIEWER].set+3);
      rotObject[i]=rotObject[i+1]=rotObject[i+2]=0.0;
      rotObject[i+3]=1.0;
      redraw(VIEWER);
    }
/*  if (buttonEvent->button == Button3)
    {
      switchPointerDevice();
      XmMenuPosition(windows[VIEWER].menu, (XButtonPressedEvent *)(event));
      XtManageChild(windows[VIEWER].menu);
      switchPointerDevice();
    } */
    if (buttonEvent->button == Button4) sensitivity+=2;
    if (buttonEvent->button == Button5) sensitivity-=2;
  }
}

void doMenu(Widget widget, Widget menu, XmDrawingAreaCallbackStruct *data)
{
  XmMenuPosition(menu, (XButtonPressedEvent *)(data->event));
  XtManageChild(menu);
}

void changeBoolean(Widget w, int *bool, XmDrawingAreaCallbackStruct *data)
{
  *bool=!(*bool);
  redraw(VIEWER);
}

void setModel(Widget w, caddr_t model, XmDrawingAreaCallbackStruct *data)
{
  setMenuItem((VIEWER_WIRE)+windows[VIEWER].mode-WIREMODEL, True);
  windows[VIEWER].mode=(int)model;
  setMenuItem((VIEWER_WIRE)+(int)model-WIREMODEL, False);
  if ((int)model != WIREMODEL)
    setMenuItem(VIEWER_RAYTRACING, True);
  else
    setMenuItem(VIEWER_RAYTRACING, False);
  redraw(VIEWER);
}

void setDiagram(Widget w, caddr_t diagram, XmDrawingAreaCallbackStruct *data)
{
  if (windows[MO].mode == DENSITY_OF_STATES)
    windows[MO].mode=ENERGY_LEVELS;
  else
    windows[MO].mode=DENSITY_OF_STATES;
  drawMODiagram((Widget)0, (caddr_t)0, (XmDrawingAreaCallbackStruct *)0);
}
