/*
 *  File:        math_panel.C
 *  Purpose:     Mathed GUI for lyx
 *  Author:      Alejandro Aguilar Sierra <asierra@servidor.unam.mx>
 *  Created:     March 28, 1996
 * 
 *  Dependencies: Xlib, Xpm, XForms, Lyx
 *
 *  Copyright: (c) 1996, Alejandro Aguilar Sierra 
 *
 *   You are free to use and modify it under the terms of
 *   the GNU General Public Licence version 2 or later.
 */

#include "config.h"

#include "forms.h"
#include <stdio.h>
#include <stdlib.h>

#include "math_panel.h"
#include "symbol_def.h"
#include "formula.h"
#include "keybind.h"

/* Bitmaps */
#include "delim.xbm"
#include "delim0.xpm"
#include "delim.xpm"
#include "deco.xbm"
#include "deco.xpm"
#include "space.xpm"
#include "sqrt.xpm"
#include "frac.xpm"
#include "matrix.xpm"
#include "equation.xpm"

static FD_panel *fd_panel;
static FD_delim *fd_delim;
static FD_deco  *fd_deco;
static FD_space  *fd_space;
static FD_matrix *fd_matrix;

int delim_code[] = {   
   '(', ')', LM_lceil,  LM_rceil,  LM_uparrow,  LM_Uparrow,
   '[', ']', LM_lfloor,  LM_rfloor,  LM_updownarrow, LM_Updownarrow,
   '{', '}',  '/', LM_backslash,  LM_downarrow,  LM_Downarrow,
   LM_langle,  LM_rangle, '|', LM_Vert, '.', 0
};

static char *deco_code[] = {
   "widehat", "widetilde", "overbrace", "overleftarrow", "overrightarrow", 
   "overline","underbrace", "underline"
};

static char h_align_str[80] = "ccc";

/* callbacks for form panel */
void button_cb(FL_OBJECT *ob, long data)
{   
   extern void free_symbols_form();
   switch (data)  {
    case MM_GREEK:
    case MM_VARSIZE:
    case MM_BRELATS:
    case MM_ARROW:
    case MM_BOP:
    case MM_MISC: 
      {	   
	 BitmapMenu *menu = (BitmapMenu *)ob->u_vdata;
	 menu->Show();  
	 break;
      }
    case MM_FRAC:
      DispatchFunction(LFUN_INSERT_MATH, "frac");
      break;
    case MM_SQRT:
      DispatchFunction(LFUN_INSERT_MATH, "sqrt");
      break;
    case MM_DELIM:
      fl_show_form(fd_delim->delim,FL_PLACE_MOUSE,FL_FULLBORDER,"Delimiter");
      break;
    case MM_DECO:
      fl_show_form(fd_deco->deco,FL_PLACE_MOUSE,FL_FULLBORDER,"Decoration");
      break;
    case MM_SPACE:
      fl_show_form(fd_space->space,FL_PLACE_MOUSE,FL_FULLBORDER,"Spacing");
      break;
    case MM_MATRIX:
      fl_show_form(fd_matrix->matrix,FL_PLACE_MOUSE,FL_FULLBORDER,"Matrix");
      break;
    case MM_EQU:
      DispatchFunction(LFUN_MATH_DISPLAY, NULL);
      break;
    case 100:
      free_symbols_form();
      break;
   }
}


/* callbacks for form delim */
void delim_cb(FL_OBJECT *, long data)
{
   static int left=0, right=1;
   int side=(fl_get_button(fd_delim->right)!=0);
   Pixmap p1, p2;
   
   switch (data) {
    case MM_APPLY:
    case MM_OK:
      {
	 char s[80];
	 sprintf(s, "%d %d", delim_code[left], delim_code[right]); 
	 DispatchFunction(LFUN_MATH_DELIM, s);
	 if (data==MM_APPLY) break;
      }
    case MM_CLOSE: fl_hide_form(fd_delim->delim); break;
    case 2: 
      {
	  int i = fl_get_bmtable(fd_delim->menu);
	  if (i>=0) {
	      if (side) 
		right = i;
	      else
		left = i;
	  }
	  p1 = fl_get_pixmap_pixmap(fd_delim->pix, &p1, &p2);
	  fl_draw_bmtable_item(fd_delim->menu,left,p1,0,0);
	  fl_draw_bmtable_item(fd_delim->menu,right,p1,16,0);
	  fl_redraw_object(fd_delim->pix);
	  break;
      }
    case 3: break;
    case 4: break;
   }
}

/* callbacks for form matrix */
void matrix_cb(FL_OBJECT *, long data)
{
   int nx, ny;
   static char v_align_c[] = "tcb";
 
   switch (data) {
    case MM_APPLY:
    case MM_OK: 
      {
	 char s[80];
	 char c = v_align_c[fl_get_choice(fd_matrix->valign)-1];
	 const char *sh = fl_get_input(fd_matrix->halign);
	 nx = (int)(fl_get_slider_value(fd_matrix->columns)+0.5);
	 ny = (int)(fl_get_slider_value(fd_matrix->rows)+0.5);
	 sprintf(s, "%d %d %c%s", nx, ny, c, sh);      
	 if (data!=3) fl_hide_form(fd_matrix->matrix);
	 DispatchFunction(LFUN_INSERT_MATRIX, s);
	 break;
      }
    case MM_CLOSE: fl_hide_form(fd_matrix->matrix); break;
    case 2: 
      {
	 nx = (int)(fl_get_slider_value(fd_matrix->columns)+0.5);
	 for (int i=0; i<nx; i++) h_align_str[i] = 'c';
	 //memset(h_align_str, 'c', nx);
	 h_align_str[nx] = '\0';
//	 fl_freeze_form(fd_form_main->form_main);
//	fl_addto_form(fd_form_main->form_main);

	 fl_set_input(fd_matrix->halign, h_align_str);	
	 fl_redraw_object(fd_matrix->halign); 	 
	 break;
      }
   }
}

/* callbacks for form deco */
void deco_cb(FL_OBJECT *, long data)
{
   switch (data) {
    case MM_APPLY:
    case MM_OK:
      { 
	 int i = fl_get_bmtable(fd_deco->menu);
	 DispatchFunction(LFUN_INSERT_MATH, deco_code[i]);
	 if (data==MM_APPLY) break;
      }
    case MM_CLOSE: fl_hide_form(fd_deco->deco); break;
   }
}

/* callbacks for form space */
void space_cb(FL_OBJECT *, long data)
{
   static short sp=-1;
   extern char *latex_mathspace[];
   
   if (data>=0 && data<6) 
      sp = (short)data;
   else
   switch (data) {
    case MM_APPLY:
    case MM_OK:
      { 
	 if (sp>=0)
	   DispatchFunction(LFUN_INSERT_MATH, latex_mathspace[sp]);
	 if (data==MM_APPLY) break;
      }
    case MM_CLOSE: fl_hide_form(fd_space->space); break;
   }
}

int align_filter(FL_OBJECT *, const char *, const char *cur, int c)
{
   int n = (int)(fl_get_slider_value(fd_matrix->columns)+0.5) - strlen(cur);
   return ((c=='c'||c=='l'||c=='r') && n>=0) ? FL_VALID: FL_INVALID;
}

char** mathed_get_pixmap_from_icon(int d)
{
   switch (d) {
    case MM_FRAC: return frac;
    case MM_SQRT: return sqrt;
    case MM_DELIM: return delim;
    case MM_MATRIX: return matrix;
    case MM_EQU: return equation; 
    case MM_DECO: return deco; 
    case MM_SPACE: return space_xpm; 
    default: return NULL;
   }
}

FD_panel *create_math_panel( )
{
   fd_panel = create_form_panel();
   fd_delim = create_form_delim();
   fd_deco = create_form_deco();
   fd_space = create_form_space();
   fd_matrix = create_form_matrix();

   /* fill-in form initialization code */
   fl_set_button(fd_delim->left, 1);
   fl_set_pixmap_data(fd_delim->pix, delim0);
   fl_set_bmtable_data(fd_delim->menu,6,4,delim_width,delim_height,
		       (char*)delim_bits);
   fl_set_bmtable_maxitems(fd_delim->menu, 23);
   
   fl_set_pixmap_data(fd_panel->sqrt, sqrt);
   fl_set_pixmap_data(fd_panel->frac, frac);
   fl_set_pixmap_data(fd_panel->delim, delim);
   fl_set_pixmap_data(fd_panel->deco, deco);
   fl_set_pixmap_data(fd_panel->space, space_xpm);
   fl_set_pixmap_data(fd_panel->matrix, matrix);
   fl_set_pixmap_data(fd_panel->equation, equation);

   fl_addto_choice(fd_matrix->valign, "Top | Center | Bottom");
   fl_set_choice(fd_matrix->valign, 2);
   fl_set_input(fd_matrix->halign, h_align_str);
   fl_set_input_filter(fd_matrix->halign, align_filter);
   
   fl_set_bmtable_data(fd_deco->menu,3,3,deco_width,deco_height,
		       (char*)deco_bits);
   fl_set_bmtable_maxitems(fd_deco->menu, 8);
   
   return fd_panel;
}

