/* $Log: callbacks.c,v $
 * Revision 1.11  1995/03/20  14:53:34  martenl
 * *** empty log message ***
 *
 * Revision 1.10  1995/03/12  14:30:38  martenl
 * Added new type of boundaries
 *
 * Revision 1.9  1995/03/11  13:52:32  martenl
 * fixed new state stuff for multiple modules
 *
 * Revision 1.8  1995/03/10  08:12:13  martenl
 * *** empty log message ***
 *
 * Revision 1.7  1995/03/09  17:01:21  martenl
 * redisplay:
 * 	added a info message
 *
 * Revision 1.6  1995/03/08  09:04:53  martenl
 * infoRedisplay:
 * 	changed logo
 *
 * Revision 1.5  1995/03/07  14:54:07  martenl
 * *** empty log message ***
 *
 * Revision 1.4  1995/03/02  19:45:37  martenl
 * doPlotting:
 * 	added new logic to fix a better display of equation data
 *
 * Revision 1.3  1995/02/23  14:31:17  martenl
 * Added two a new state HAVE_BCDATA to enable the splitting of eqdata
 * and boundary conditions to two separate events
 *
 * Revision 1.2  1995/02/23  10:27:10  martenl
 * doPlotting:
 * 	Added a call to plotIsolinesofEqData
 *
 * Revision 1.1  1995/02/21  07:53:52  martenl
 * Initial revision
 *
 * Revision 1.6  1994/10/25  09:14:37  martenl
 * Major cleanup
 *
 * Revision 1.5  1994/10/17  08:50:47  martenl
 * Removed obsolete flags
 *
 * Revision 1.4  1994/10/14  14:08:22  martenl
 * *** empty log message ***
 *
 * Revision 1.3  1994/10/14  13:21:36  martenl
 * (file): Change loading function to readSolution
 * */

#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <string.h>
#include "libsx.h"             /* gets us in the door with libsx          */
#include "globals.h"
#include "io.h"
#include "geodata.h"
#include "freq.h"
#include "graph.h"
#include "plot.h"
#include "grid.h"
#include "boundary.h"
#include "kraftwerk.h"
#include "solve.h"
#include "crosshair.h"
#include "mesh.h"
#include "fortran.h"
#include "workarea.h"
#include "module.h"
#define min(x, y)                     (((x) < (y)) ? (x) : (y))
#define max(x, y)                     (((x) > (y)) ? (x) : (y))

char  showElementNo[] = "NO ";
char  showNodeNo[] = "NO ";
char  showIsoLabels[] = "YES";
char  filledIsoLines[] = "YES";
char  colorPS[] = "NO ";


void  KeyPressFunc(Widget w, char *input, int up_or_down, void *data)
{
/*  printf("%s\n", input); */
}
 

void sbarfcn(Widget w, float new_val, void *data)
{
  int hh = 0, ww = 0;
  maxarrwscl = new_val/100.;
  redisplay(w, hh, ww, data);
}
void sbarfcn1(Widget w, float new_val, void *data)
{
  int hh = 0, ww = 0;
  minscalarX = new_val / 100.;
  redisplay(w, hh, ww, data);
}
void sbarfcn2(Widget w, float new_val, void *data)
{
  int hh = 0, ww = 0;
  maxscalarX = new_val / 100.;
  redisplay(w, hh, ww, data);
}
/*
 *
 * +-------------------+
 * | The quit function |
 * +-------------------+
 *
 */
void quit(Widget w, void *data)
{
  exit(0);
}
/*
 *
 * +------------------------+
 * | Display a wait message |
 * +------------------------+
 *
 */
void pleaseWait()
{
  int width, height;

  ClearDrawArea();               /* start with a clean slate */
  FreeAllColors();
  GetDrawAreaSize(&width, &height);
  DrawText("F   E   M   L   A   B", width/3, height/2);
  DrawText("Standby for the most recent result in the world...",
	   width/3, height/2+30);
  SyncDisplay();

}

/*
 *
 * +--------------------------------------+
 * | This function is called every        |
 * | the drawing area needs to be redrawn |
 * +--------------------------------------+
 *
 */
void redisplay(Widget w, int new_width, int new_height, void *data)
{
/*
  Display        *dpy;
  XEvent report;
*/
  int width, height, i, h;
/*
  dpy = (Display *) XtDisplay(drawWindow);
  XPeekEvent(dpy, &report);
  if( report.type == Expose){
    while(report.xexpose.count != 0){
      XNextEvent(dpy, &report);
      printf("Event no: %i\n",report.xexpose.count);
    } 
  }
*/
  set_menu_state();
  mySetColor(WHITE);
  ClearDrawArea();               /* start with a clean slate */
  doPlotting();
  redisplayCrossHair();
  /*  XSync(dpy, TRUE);*/

  if( state == HAVE_NOTHING){
    GetDrawAreaSize(&width, &height);
    h = FontHeight(GetWidgetFont(drawWindow));
    i = 0;
    DrawText("F   E   M   L   A   B   version 1.1"                  , width/4, height/3 + i*h); i++;
    DrawText("Copyright (C) 1995 Chalmers University of Technology" , width/4, height/3 + i*h);i++;
    DrawText("Marten Levenstam, Peter Hansbo & Claes Johnson."      , width/4, height/3 + i*h);i++;
    DrawText("FEMLAB comes with ABSOLUTELY NO WARRANTY."             , width/4, height/3 + i*h);i++;
    DrawText("This is free software, and you are welcome"           , width/4, height/3 + i*h);i++;
    DrawText("to redistribute it under certain conditions,"         , width/4, height/3 + i*h);i++;
    DrawText("see the file COPYING for more information."           , width/4, height/3 + i*h);i++;i++;
    DrawText("For more information about FEMLAB go to our WWW-site:", width/4, height/3 + i*h);i++;
    DrawText("http://www.math.chalmers.se/femlab"                   , width/4, height/3 + i*h);i++;i++;
    DrawText("Send bugs and comments to: femlab@math.chalmers.se"    , width/4, height/3 + i*h);i++;i++;

    DrawText("+-----------------------------------------------------------------+", width/4, height/3 + i*h);i++;
    DrawText("| This program is distributed in the hope that it will be useful, |" , width/4, height/3 + i*h);i++;
    DrawText("| but WITHOUT ANY WARRANTY; without even the implied warranty of  |" , width/4, height/3 + i*h);i++;
    DrawText("| MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.            |" , width/4, height/3 + i*h);i++;
    DrawText("+-----------------------------------------------------------------+", width/4, height/3 + i*h);i++;
     

  }
}
/*
 *
 * +------------------------------------------------+
 * | This function is called everytine the logowind |
 * | is to be redrawn                               |
 * +------------------------------------------------+
 *
 */
void inforedisplay(Widget w, int new_width, int new_height, void *data)
{

  SetDrawArea(logoWindow);

  SetBgColor(logoWindow, GetNamedColor("skyblue3"));
  SetFgColor(logoWindow, GetNamedColor("skyblue3"));
  SetColor(GetNamedColor("skyblue3"));
  ClearDrawArea();     

  SetFgColor(logoWindow, GetNamedColor("red"));
  SetWidgetFont(logoWindow, GetFont("-adobe-helvetica-bold-r-normal--20-140-100-100-p-103-iso8859-1"));
  DrawText("F   E   M   L   A   B", 15, 25);
  SetFgColor(logoWindow, GetNamedColor("black"));
  SetWidgetFont(logoWindow, GetFont("-adobe-helvetica-medium-o-normal--10-100-75-75-p-57-iso8859-1"));
/*  DrawText("The  choice  of  a  new  generation", 15, 45);*/
  DrawText("The  choice  of  generation  X", 15, 38);
  DrawText("Chalmers University of Technology", 15, 55);
/*  DrawText("v 0.8", 165, 25); */

 
}
/*
 *
 * +----------------------------+
 * | The zoom callback function |
 * +----------------------------+
 *
 */
void zoom(Widget w, void* data)
{
  SetButtonDownCB(drawWindow, zoomMouseDown);
  SetButtonUpCB(drawWindow, zoomMouseUp);
  infoHandler("Mark zoom box with mousebutton down");
}
void unzoom(Widget w, void* data)
{
  int hh = 0, ww = 0;
  flags.zoom = 0;
  zoomActive = FALSE;
  redisplay(w, hh, ww, data);
}

/*
 *
 * +-------------------------------------------+
 * | Connads to handle the input of boundaries |
 * +-------------------------------------------+
 *
 */
void inputBoundary(Widget w, void *data)
{
  int hh = 0, ww = 0;

  if(state == HAVE_NOTHING)
    getBoundaryScale(w, data);
/*
  dd = data;
  boundaryType = *dd;
*/
  state = HAVE_BOUNDARY;

  redisplay(w, hh, ww, data);

  SetButtonDownCB(drawWindow, boundaryMouseDown);
  SetMouseMotionCB(drawWindow, boundaryMouseMotion);   
/*
  infoHandler("Define boundary with mouse clicks, Outer boundary clockwise, Inner boundary counterclockwise");
 */
/*    boundarywindow(); */

}
/*
 *
 * +--------------------------------------------+
 * | Handles the adjustnent of a boundary point |
 * +--------------------------------------------+
 *
 */
void moveBoundary(Widget w, void *data)
{
  int hh = 0, ww = 0;
  state = HAVE_BOUNDARY;
  redisplay(w, hh, ww, data);

  SetButtonDownCB(drawWindow, boundaryMoveMouseDown);
  SetMouseMotionCB(drawWindow, boundaryMoveMouseMotion);
  infoHandler("Click on point to move, then drag and drop");
}
/*
 *
 * +-----------------------+
 * | Load a file from disk |
 * +-----------------------+
 *
 */
void file(Widget w, void* data)
{
  int hh = 0, ww = 0;
  char *fname="area.scratch";

  fname = GetFile(NULL);
  if(fname){
    loadFromFile(fname);
  }
  redisplay(w, hh, ww, data);
}
/*
 *
 * +-------------------------+
 * | Save everything to disk |
 * +-------------------------+
 *
 */
void save(Widget w, void* data)
{
  int hh = 0, ww = 0;
  char *fname="area.scratch";

  fname = GetFile(NULL);
  if(fname){
    saveToFile(fname);
  }
  redisplay(w, hh, ww, data);
}
/*
 *
 * +--------------------------------------------+
 * | Handles all co ands for the esh generation |
 * +--------------------------------------------+
 *
 */
void mesh(Widget w, void* d)
{
  int *data;
  char *ptr;
  char cmd[100];
  int hh = 0, ww = 0;
  int i;
  BND_NODE *s;
  GEO_NODE *g;
  PTS_NODE *p;

  data = d;
  if(*data == 1){
    pleaseWait();

    i = 1;
    FOR_ALL_POINTS(p){
      p->id = i;
      i++;
    }
    i = 1;
    FOR_ALL_BOUNDARIES( g ){
      FOR_ALL_SEGMENTS(g, s){
	s->seg->id = i;
	i++;
      }
    }

    saveToFile("area.scratch"); 
    ptr = NULL;
    ptr = (char *) getenv("FEMLAB_HOME");
    if(ptr == NULL)
      errorHandler("FEMLAB_HOME environment variable not set");
    else{
      setAction(WAITING);
      SetWidgetState(drawWindow, FALSE);
      sprintf(cmd, "%s/bin/meshgen", ptr);
      system(cmd);
      SetWidgetState(drawWindow, TRUE);
      state = HAVE_MESH;
      loadFromFile("area.scratch");
      state = HAVE_MESH;
      module[currentModule].state = state; /* Ugly hack to fix bug in f-code*/
      setAction(NORMAL);
    }
  }
  else if( *data == 0){
    meshsize();
  }
  redisplay(w, hh, ww, data);
}

/*
 *
 * +------------------------------------------------+
 * | Called if the users selects a plotting command |
 * +------------------------------------------------+
 *
 */
void draw(Widget w, void *d)
{
  int *data;
  int i, hh = 0, ww = 0;
  data = d;
/*
  for( i = 0; i < plotMenu.noItems; i++)
      SetMenuItemChecked(plotMenu.item[i], FALSE);
*/
  if(GetMenuItemChecked(plotMenu.item[*data]) == TRUE)
      SetMenuItemChecked(plotMenu.item[*data], FALSE);
  else
    SetMenuItemChecked(plotMenu.item[*data], TRUE);  

  redisplay(w, hh, ww, data);
}

void check(Widget w, void *d)
{
  int *data;
  int i, hh = 0, ww = 0;
  data = d;

  for( i = 0; i < solverMenu.noItems; i++)
    SetMenuItemChecked(solverMenu.item[i], FALSE);

  SetMenuItemChecked(solverMenu.item[*data], TRUE);  
  state = module[*data].state;
  redisplay(w, hh, ww, NULL);

}
int getCheck()
{
  int i;

  for( i = 0; i < solverMenu.noItems; i++){
    if(GetMenuItemChecked(solverMenu.item[i]) == TRUE)
      return i;
  }
  return -1;
}

void doPlotting()
{
  int width, height;
  int i;
  SetDrawArea(drawWindow);
  winid = 1;
  getDrawingScale();

  if(state == HAVE_BOUNDARY || state == HAVE_MESHSIZE || state == HAVE_EQDATA)
    plotBoundary();
  if(state == HAVE_EQDATA){
    if(substate == 0){
      plotBoundary();
      plotEquationData();
    }
    if(substate == 1){
      drawEquationData();
      plotEquationData();
    }
    if(substate == 2){
      plotMesh();
      drawEquationData();
    }
  }
  if(state == HAVE_BCDATA || state == HAVE_SOLVDATA){
    plotBoundary();
    drawBC();
  }
  if(state == HAVE_MESH){
    plotMesh();
    if(strcasecmp(showElementNo, "yes") == 0 )
      plotElementNumbers();
    if(strcasecmp(showNodeNo, "yes") == 0 )
      plotNodeNumbers();
  }
  if(state == HAVE_SOLUTION){
    if(GetMenuItemChecked(plotMenu.item[5]) == TRUE){
      plotMesh();
      plotPhysBoundary();
      if(strcasecmp(showElementNo, "yes") == 0 )
	plotElementNumbers();
      if(strcasecmp(showNodeNo, "yes") == 0 )
	plotNodeNumbers();
      winid = min(winid + 1, nwinx*nwiny);
    }
    for(i = 0; i < mySol[currentSolution].n; i++){
      if(GetMenuItemChecked(plotMenu.item[i+6]) == TRUE){
	if( mySol[currentSolution].type[i] == 1){
	  if(strcasecmp(filledIsoLines, "yes") == 0 )
	    plotIsoColorLines(i);
	  else{
	    plotIsolines(i);
	    if(strcasecmp(showIsoLabels, "yes") == 0 )
	      plotIsolineLabels(i);
	  }
	  winid = min(winid + 1, nwinx*nwiny);
	}
	else{
	  plotVectors(i);
	  winid = min(winid + 1, nwinx*nwiny);
	}
      }
    }

  }

  GetDrawAreaSize(&width, &height);
  SetDrawMode(GXcopy);
}

void print(Widget w, void *data)
{
  char *ptr;
  char printer[100];

  ptr = &printer[0];
/*
 * +----------------------------------------------------+
 * | If the user has specified a printer, get that name |
 * +----------------------------------------------------+
 */
  ptr = getenv("PRINTER");
  ptr = GetString("Give name of Printer:", ptr);

  if(ptr != NULL)
    psPrint(ptr, TO_PRINTER);
}


void print2file(Widget w, void *data)
{
  char *ptr;
  char printer[100];
  ptr = &printer[0];
  ptr = GetString("Give name of file:", "");
  if(ptr != NULL)
    psPrint(ptr, TO_FILE);
}

void plotprefs(Widget w, void *data)
{
  int hh = 0, ww = 0;
  TagList tags[] = {
    {TAG_WINDOW_LABEL,  "Plot Preferences    ", NULL    , TAG_INIT}, 
    {TAG_INT, "Number of colors:     ", &ncolor , TAG_INIT},
    {TAG_INT, "Number of isolines:   ", &nlev  , TAG_INIT},
    {TAG_STRING, "Show labels on the isolines:   ", &showIsoLabels  , TAG_INIT},
    {TAG_STRING, "Plot filled isolines:   ", &filledIsoLines  , TAG_INIT},
    {TAG_STRING, "Show element numbers:   ", &showElementNo  , TAG_INIT},
    {TAG_STRING, "Show node numbers:   ", &showNodeNo  , TAG_INIT},
    {TAG_FLOAT,  "Arrow scale:          ", &arrwscl, TAG_INIT}, 
    {TAG_INT, "Number of subplots in X:   ", &nwinx  , TAG_INIT},
    {TAG_INT, "Number of subplots in Y:   ", &nwiny  , TAG_INIT},
    {TAG_STRING, "Print using color postscript:   ", &colorPS  , TAG_INIT},
    {TAG_DONE,   NULL,           NULL,     TAG_NOINIT}
  };
  GetValues(tags);
  if(strcasecmp(colorPS, "yes") == 0 )
    color_ps = TRUE;
  else
    color_ps = FALSE;
  redisplay(w, hh, ww, data);

}


syntax highlighted by Code2HTML, v. 0.9.1