/* This file is part of
* ======================================================
* 
*           LyX, the High Level Word Processor
* 	 
*	    Copyright (C) 1995 Matthias Ettrich
*
*======================================================*/

#include "config.h"

#include <ctype.h>
#include <unistd.h>
#include <signal.h>
#include <string.h>
#include <stdlib.h>

#include "lyxparameters.h"
#include "lyxrc.h"
#include "file.h"
#include "lyx.h"
#include "layout_forms.h"
#include "print_form.h"
#include "form1.h"
#include "spellchecker.h"
#include "lyxserver.h"
#include "version.h"
#include "lyx_cb.h"
#include "docu.h"
#include "credits.h"
#include "figinset.h"
#include "paths.h"
#include "buffer.h"
#include "toolbar.h"
#include "keybind.h"
#include "latex.h"
#include "lyxfont.h"
#include "lastfiles.h"
#include "minibuffer.h"
#include "combox.h"

extern Combox *combo_language;
extern void show_symbols_form(void);
extern FD_form_main *fd_form_main;
extern FD_form_title *fd_form_title;
extern FD_form_paragraph *fd_form_paragraph;
extern FD_form_search *fd_form_search;
extern FD_form_character *fd_form_character;
extern FD_form_document *fd_form_document;
extern FD_form_quotes *fd_form_quotes;
extern FD_form_preamble *fd_form_preamble;
extern FD_form_table *fd_form_table;
extern FD_form_print *fd_form_print;
extern FD_form_figure *fd_form_figure;
extern FD_form_screen *fd_form_screen;
extern FD_form_toc *fd_form_toc;
extern FD_form_ref *fd_form_ref;
extern FD_LaTeXOptions *fd_latex_options;

extern void DeleteSimpleCutBuffer(); /* for the cleanup when exiting */
extern void LyxDefaultKeyBindings();
extern int WorkAreaKeyPress(FL_OBJECT *ob,
			    Window win,
			    int w, int h,
			    XEvent *ev, void *d);

//extern void sigchldhandler(int sig,...); //... added to please Sun's CC (JMarc)
extern void sigchldhandler(int sig);

extern LyXTextParameters* autocorrparameters;

// the MiniBuffer object
MiniBuffer minibuffer;

// can't be static since keybind.C wants it.
int work_area_height = 0;
static int work_area_width = 0;

static long current_scrollbar_value = 0;
static int current_layout = 0;
static char current_textclass = 255;

// this should be static, but I need it in buffer.C
bool quitting = false;	// flag, that we are quitting the program

char * system_lyxdir = NULL;
char * system_tempdir = NULL;
char * document_path = NULL;
static char ascii_type; /* for selection notify callbacks */

bool BindFileSet = false; // should this be parh of lyxrc?

bool work_area_active = true;
bool scrolling = false;

char updatetimer = 0;

/* wether the work area should get callbacks */ 
static bool input_prohibited = false;

/* the selection possible is needed, that only motion events are 
* used, where the bottom press event was on the drawing area too */
bool selection_possible = false;

void InsertCorrectQuote();


static
void SetXtermCursor(Window win)
{
  static Cursor cursor;
  static char cursor_undefined = 1;
  if (cursor_undefined){
    cursor = XCreateFontCursor(fl_display, XC_xterm);
    cursor_undefined = 0;
  }
  XDefineCursor(fl_display, win, cursor);
}


/* 
   This is the inset locking stuff needed for mathed --------------------

   an inset can simple call LockInset in it's edit call and *ONLY* in it's
   edit call.
   Inset::Edit() can only be called by the main lyx module.

   Then the inset may modify the menu's and/or iconbars. 

   Unlocking is either done by LyX or the inset itself with a UnlockInset-call

   During the lock, all button and keyboard events will be modified
   and send to the inset through the following inset-features. Note that
   Inset::InsetUnlock will be called from inside UnlockInset. It is meant
   to contain the code for restoring the menus and things like this.

   
   virtual void InsetButtonPress(int x, int y, int button);
   virtual void InsetButtonRelease(int x, int y, int button);
   virtual void InsetKeyPress(XKeyEvent *ev);
   virtual void InsetMotionNotify(int x, int y, int state);
   virtual void InsetUnlock();

   If a inset wishes any redraw and/or udpate it just has to call
   UpdateInset(this).
   It's is completly irrelevant, where the inset is. UpdateInset will
   find it in any paragraph in any buffer. 
   Of course the_locking_inset and the insets in the current paragraph/buffer
   are checked first, so no performance problem should occur.
   
   Hope that's ok for the beginning, Alejandro,
   sorry that I needed so much time,

                  Matthias
   */

void UpdateInset(Inset* inset, bool mark_dirty = true);
/* these functions return 1 if an error occured, 
   otherwise 0 */
// Now they work only for updatable insets. [Alejandro 080596]
int LockInset(UpdatableInset* inset);
void ToggleLockedInsetCursor(long x, long y, int asc, int desc);
void FitLockedInsetCursor(long x, long y, int asc, int desc);
int UnlockInset(UpdatableInset* inset);
void LockedInsetStoreUndo(int);

struct InsetUpdateStruct {
  Inset* inset;
  InsetUpdateStruct* next;
};

/* this is for asyncron updating. UpdateInsetUpdateList will be called
   automatically from LyX. Just insert the Inset into the Updatelist */
void UpdateInsetUpdateList();
void PutInsetIntoInsetUpdateList(Inset* inset);

static InsetUpdateStruct *InsetUpdateList = NULL;


/*
  -----------------------------------------------------------------------
 */

/* some function prototypes */ 
int WorkAreaButtonPress(FL_OBJECT *ob,
			Window win,
			int w, int h,
			XEvent *ev, void *d);
int WorkAreaButtonRelease(FL_OBJECT *ob,
			  Window win,
			  int w, int h,
			  XEvent *ev, void *d);
int WorkAreaMotionNotify(FL_OBJECT *ob,
			 Window win,
			 int w, int h,
			 XEvent *ev, void *d);
int ResizeCurrentBuffer(FL_OBJECT*);
void ResizeCurrentBufferPseudoExpose();
void GotoError();
void GotoNote();
void OpenStuff();
void ToggleFloat();
void MenuUndo();
void MenuRedo();
void HyphenationPoint();
void HFill();
void Newline();
void ProtectedBlank();
void CopyCB();
void LoadLyXFile(const char*);
int RunLaTeX();
int RunLinuxDoc(int, const char *);
void MenuWrite(Buffer* buf);
void CloseBuffer(); 
void MenuPreview();
void MenuPreviewPS();
void MenuLayoutCharacter();
void MenuLayoutParagraph();
void MenuLayoutDocument();
void MenuLayoutQuotes();
void MenuLayoutPreamble();

//void error_handler(int err_sig,...); //... added to please Sun's CC (JMarc)
void error_handler(int err_sig); //... added to please Sun's CC (JMarc)


char GetCurrentTextClass()
{
	return current_textclass;
}


/*     Opens the visible menu of given name, or simply does noting when
       the name is not known. 
       NOTE THE EXTREMELY STUPID IMPLEMENTATION! :-)
       There are probably hundred ways to do this better, for instance,
       by scanning the menu objects and testing for the given name.
       I leave this as an exercise for an experienced GG (GUI Guy/Girl).
       RVDK_PATCH_5. */
void MenuOpenByName( const char *menuName )
{
  if (!menuName)
    return; 

       if ( !strcmp(menuName, "File") )
	       ShowFileMenu( fd_form_main->menu_file, 0 );
       else if ( !strcmp(menuName, "Edit") )
	       ShowEditMenu( fd_form_main->menu_edit, 0 );
       else if ( !strcmp(menuName, "Layout") )
	       ShowLayoutMenu( fd_form_main->menu_layout, 0 );
       else if ( !strcmp(menuName, "Insert") )
	       ShowInsertMenu( fd_form_main->menu_insert, 0 );
       else if ( !strcmp(menuName, "Math") )
	       ShowMathMenu( fd_form_main->menu_math, 0 );
       else if ( !strcmp(menuName, "Options") )
	       ShowOptionsMenu( fd_form_main->menu_options, 0 );
       else if ( !strcmp(menuName, "Documents") )
	       ShowBufferMenu( fd_form_main->menu_buffer, 0 );
       else if ( !strcmp(menuName, "Help") )
	       ShowHelpMenu( fd_form_main->menu_help, 0 );
}


void MenuPasteSelection(char at)
{
  if (!bufferlist.current()->screen)
    return;

  ascii_type = at;
  
  Atom data_prop = XInternAtom(fl_display, 
			       "LyX_Primary",
			       False);
  XConvertSelection(fl_display,
		    XA_PRIMARY, XA_STRING, data_prop, 
		    fd_form_main->form_main->window, 0);
}


void UpdateLayoutChoice()
{
	/* update the layout display */
	if (!toolbar.combox) return;
	
	if (current_textclass !=
	    bufferlist.current()->parameters.textclass) {
		toolbar.combox->clear();
		for (int i = 0;
		     !StringEqual(lyxstyle.NameOfLayout
				  (bufferlist.current()->
				   parameters.textclass, i),"@@end@@"); i++) {
		  char* tmp = lyxstyle.NameOfLayout
		    (bufferlist.current()->
		     parameters.textclass, i);
		  // Obsolete Layouts
		  if (StringEqual(tmp, "Formula"))
		      tmp = "(obsolete) Formula";
		  if (StringEqual(tmp, "NumberedFormula"))
		      tmp = "(obsolete) NumberedFormula";
		  toolbar.combox->addline(tmp);
		}
		current_textclass =
			bufferlist.current()->parameters.textclass;
		current_layout = 0;
	}
	
	if (!bufferlist.current()->text) return;
	
	char layout = bufferlist.current()->text->cursor.par->GetLayout();
	
	if (layout !=  current_layout){
		toolbar.combox->select(layout + 1);
		current_layout = layout;
	}
}


void InvalidateLayoutChoice()
{
	current_textclass = 255;
}


void UpdateDocumentClassChoice()
{
   /* update the document class display */
	int i;
	if (fd_form_document) {
		fl_clear_choice(fd_form_document->choice_class);
		for (i = 0; !StringEqual(lyxstyle.NameOfClass (i),"@@end@@"); i++) {
				fl_addto_choice(fd_form_document->choice_class,
						lyxstyle.NameOfClass(i));
		}
	}
	//this is unfinished dabn100
	//we need to check textclass name against loaded textclasses
        //and possibly put the document in a new textclass
	//char textclass = bufferlist.current()->parameters.textclass;
	//if (!bufferlist.current()->text)
	//	return;
	//if (textclass !=  current_textclass){
	//	fl_set_choice(fd_form_document->choice_class, textclass + 1);
	//	current_textclass = textclass;			
	// 	}
}


void ProhibitInput()
{
   input_prohibited = true;
   if (bufferlist.current()->screen)
     bufferlist.current()->screen->HideCursor();

   static Cursor cursor;
   static char cursor_undefined = 1;
   
   if (cursor_undefined){
     cursor = XCreateFontCursor(fl_display, XC_watch);
     cursor_undefined = 0;
   }
   
   /* set the cursor to the watch for for all forms and the canvas */ 
   XDefineCursor(fl_display, fd_form_main->form_main->window, cursor);
   if (fd_form_paragraph->form_paragraph->visible)
     XDefineCursor(fl_display, fd_form_paragraph->form_paragraph->window, cursor);
   if (fd_form_character->form_character->visible)
     XDefineCursor(fl_display, fd_form_character->form_character->window, cursor);

   XFlush(fl_display);
   fl_deactivate_all_forms();
}


void AllowInput()
{
   input_prohibited = false;

   /* reset the cursor from the watch for all forms and the canvas */
   
    XUndefineCursor(fl_display, fd_form_main->form_main->window);
    if (fd_form_paragraph->form_paragraph->visible)
      XUndefineCursor(fl_display, fd_form_paragraph->form_paragraph->window);
    if (fd_form_character->form_character->visible)
      XUndefineCursor(fl_display, fd_form_character->form_character->window);
    if (fd_form_main->work_area->belowmouse)
      SetXtermCursor(fd_form_main->form_main->window);

    XFlush(fl_display);
    fl_activate_all_forms();
}


void WriteAlert(const char* s1, const char* s2, const char* s3)
{
   ProhibitInput();
   minibuffer.Set(s1, s2, s3);
   fl_show_alert(s1, s2,
		s3, 0);
   AllowInput();
}


void FreeUpdateTimer()
{
   /* a real free timer would be better but I don't know 
    * how to do this with xforms */
   updatetimer = 0;
}


void SetUpdateTimer()
{
   fl_set_timer(fd_form_main->timer_update, 0.5);
   updatetimer = 1;
}


void BeforeChange()
{
   bufferlist.current()->screen->ToggleSelection();
   bufferlist.current()->text->ClearSelection();
   FreeUpdateTimer();
}


int IsLinuxDoc()
{
   /* checks for right textclass */
   int textclass = bufferlist.current()->parameters.textclass;

   if (!StringEqual(lyxstyle.NameOfClass(textclass), "linuxdoc")) return 0;
   else return 1;
}


void UpdateScrollbar()
{
   /* if the text is smaller then the working area, the scrollbar
    * maximum must be the working area height. No scrolling will 
    * be possible */
   static long max2 = 0;
   static long height2 = 0;

   long cbth = 0;
   long cbsf = 0;

   if (bufferlist.current()->text)
     cbth = bufferlist.current()->text->height;
   if (bufferlist.current()->screen)
     cbsf = bufferlist.current()->screen->first;
   if (max2 == cbth &&
       height2 == work_area_height &&
       current_scrollbar_value == cbsf)
     return;			       /* no update necessary */
   max2 = cbth;
   height2 = work_area_height;
   current_scrollbar_value = cbsf;
   
   long maximum_height = work_area_height * 3/4;
   long value = 0;

   if (bufferlist.current()->text)
      maximum_height += bufferlist.current()->text->height;
   if (bufferlist.current()->screen)
      value = bufferlist.current()->screen->first;
   /* set the scrollbar */
   double hfloat = work_area_height;
   double maxfloat = maximum_height;
   
   fl_set_slider_value(fd_form_main->scrollbar, value);
   fl_set_slider_bounds(fd_form_main->scrollbar, 0, maximum_height - work_area_height);
   /* fl_set_slider_step(fd_form_main->scrollbar, 1); */
   if (maxfloat>0){
     if ((hfloat/maxfloat) * (float) height2 < 3)
       fl_set_slider_size(fd_form_main->scrollbar, 3/(float)height2);
     else
       fl_set_slider_size(fd_form_main->scrollbar, hfloat/maxfloat);
   }
   else
      fl_set_slider_size(fd_form_main->scrollbar, hfloat);
   fl_set_slider_precision(fd_form_main->scrollbar, 0);
}


void Update(signed char f)
{
	UpdateLayoutChoice();

	if (!bufferlist.current()->text->selection && f > -3)
		bufferlist.current()->text->sel_cursor = 
			bufferlist.current()->text->cursor;

	bufferlist.current()->text->FullRebreak();
	bufferlist.current()->screen->Update();
	bufferlist.current()->screen->FitCursor();
	UpdateScrollbar();
       
	if (f==1 || f==-1) {
		if (bufferlist.current()->isLyxClean()) {
			//bufferlist.current()->lyx_current = false;
			//bufferlist.current()->bak_current = false;
			//bufferlist.current()->dvi_current = false;
			bufferlist.current()->markDirty();
			minibuffer.setTimer(4);
		}
		else {
			//bufferlist.current()->lyx_current = false;
			//bufferlist.current()->bak_current = false;
			//bufferlist.current()->dvi_current = false;
			bufferlist.current()->markDirty();
		}
	}
}


void SmallUpdate(signed char f)
{
  bufferlist.current()->screen->SmallUpdate();
  if (bufferlist.current()->screen->TopCursorVisible()
      != bufferlist.current()->screen->first){
    Update(f);
    return;
  }

   bufferlist.current()->screen->FitCursor();
   UpdateScrollbar();
   
   if (!bufferlist.current()->text->selection)
     bufferlist.current()->text->sel_cursor = 
       bufferlist.current()->text->cursor;

   if (f==1 || f==-1) {
      if (bufferlist.current()->isLyxClean()) {
	   //bufferlist.current()->lyx_current = false;
	   //bufferlist.current()->bak_current = false;
	   //bufferlist.current()->dvi_current = false;
	   bufferlist.current()->markDirty();
	 minibuffer.setTimer(4);
      }
      else {
	      //bufferlist.current()->lyx_current = false;
	      //bufferlist.current()->bak_current = false;
	      //bufferlist.current()->dvi_current = false;
	      bufferlist.current()->markDirty();
      }
   }
}


int ResizeCurrentBuffer(FL_OBJECT *ob)
{
     /* if there is no text loaded, I do not have to resize anything */
   if (!bufferlist.current()->parameters.paragraph) {
	   // Try to get rid of `black hole'. Was: LyXGetCopyGC().
	   XFillRectangle(fl_display, FL_ObjWin(ob), LyXGetLightedGC(), ob->x, ob->y,ob->w,ob->h);
	   UpdateScrollbar();
	   return 0;
   }
   XFillRectangle(fl_display, FL_ObjWin(ob), LyXGetLightedGC(), ob->x, ob->y,ob->w,ob->h);
   LyXParagraph *par = NULL;
   LyXParagraph *selstartpar = NULL;
   LyXParagraph *selendpar = NULL;
   int pos = 0;
   int selstartpos = 0;
   int selendpos = 0;
   int selection = 0;
   int mark_set = 0;

   ProhibitInput();

   minibuffer.Set("Resizing...");   

   if (bufferlist.current()->text) {
      par = bufferlist.current()->text->cursor.par;
      pos = bufferlist.current()->text->cursor.pos;
      selstartpar = bufferlist.current()->text->sel_start_cursor.par;
      selstartpos = bufferlist.current()->text->sel_start_cursor.pos;
      selendpar = bufferlist.current()->text->sel_end_cursor.par;
      selendpos = bufferlist.current()->text->sel_end_cursor.pos;
      selection = bufferlist.current()->text->selection;
      mark_set = bufferlist.current()->text->mark_set;
      delete bufferlist.current()->text;
   }
   
   bufferlist.current()->text = new LyXText(ob->w,
					    &bufferlist.current()->parameters);
   if (bufferlist.current()->screen)
      delete bufferlist.current()->screen;
   bufferlist.current()->screen = new LyXScreen(ob, bufferlist.current()->text);
   
   if (par) {
      bufferlist.current()->text->selection = True;  /* at this point just
						      * to avoid the Delete-
						      * Empty-Paragraph
						      * Mechanism when
						      * setting the cursor */
      bufferlist.current()->text->mark_set = mark_set;
      if (selection) {
	 bufferlist.current()->text->SetCursor(selstartpar, selstartpos);
	 bufferlist.current()->text->sel_cursor = bufferlist.current()->text->cursor;
	 bufferlist.current()->text->SetCursor(selendpar, selendpos);
	 bufferlist.current()->text->SetSelection();
	 bufferlist.current()->text->SetCursor(par, pos);
      }
      else {
	 bufferlist.current()->text->SetCursor(par, pos);
	 bufferlist.current()->text->sel_cursor = bufferlist.current()->text->cursor;
	 bufferlist.current()->text->selection = False;
      }
      
   }
   bufferlist.current()->screen->first  = 
   bufferlist.current()->screen->TopCursorVisible(); /* this will scroll the
							* screen that the
							* cursor becomes
							* visible */ 
   UpdateScrollbar();
   bufferlist.current()->screen->Redraw();
   
   minibuffer.Init();
   AllowInput();

   // now if the title form still exist kill it
   TimerCB(NULL,0);
   
   return 0;
}


int WorkAreaSelectionNotify(FL_OBJECT *, Window win,
			    int /*w*/, int /*h*/, XEvent *event, void */*d*/)
{
  if (event->type != SelectionNotify)
    return 0;
  Atom tmpatom;
  unsigned long ul1;
  unsigned long ul2;
  unsigned char* uc = NULL;
  int tmpint;
  bufferlist.current()->screen->HideCursor();
  BeforeChange();
  if (event->xselection.type == XA_STRING
      && event->xselection.property) {
    
    XGetWindowProperty(
		       fl_display            /* display */,
		       win /* w */,
		       event->xselection.property                /* property */,
		       0                /* long_offset */,
		       0                /* long_length */,
		       False                /* delete */,
		       XA_STRING                /* req_type */,
		       &tmpatom               /* actual_type_return */,
		       &tmpint                /* actual_format_return */,
		       &ul1      /* nitems_return */,
		       &ul2      /* bytes_after_return */,
		       &uc     /* prop_return */
		       );

    if (uc){
      free(uc);
      uc = NULL;
    }

      XGetWindowProperty(
		       fl_display           /* display */,
		       win              /* w */,
		       event->xselection.property                /* property */,
		       0                /* long_offset */,
		       ul2/4+1                /* long_length */,
		       True                /* delete */,
		       XA_STRING                /* req_type */,
		       &tmpatom               /* actual_type_return */,
		       &tmpint                /* actual_format_return */,
		       &ul1      /* nitems_return */,
		       &ul2      /* bytes_after_return */,
		       &uc     /* prop_return */
		       );
        
    if (uc){
      if (!ascii_type)
	bufferlist.current()->text->InsertStringA((char*)uc);
      else
	bufferlist.current()->text->InsertStringB((char*)uc);
      free(uc);
      uc = NULL;
    }
    
    Update(1);
  }
  return 0;
}


int WorkAreaExpose(FL_OBJECT *ob, int data)
{

   if (!ob || !ob->form->visible) 
     return 1;

   if (data) {
     /* resize current buffer */ 
     ResizeCurrentBuffer(ob);
   }
   else if (ob->w != work_area_width || ob->h != work_area_height) {
      work_area_width = ob->w;
      work_area_height = ob->h;
      /* resize */ 

      // seems to be a xforms-bug with free object. Redraw form is necessary
      fl_redraw_form(ob->form);

      /* all buffers will need resize */
      bufferlist.resize();
      /* resize current buffer */ 
      ResizeCurrentBuffer(ob);
   }
   else {
     /* simple expose */
      if (bufferlist.current()->screen) 
      	bufferlist.current()->screen->LyXExpose(0,0,work_area_width,work_area_height);
      else {
		  // Try to get rid of `black hole'. Was: LyXGetCopyGC().
		  XFillRectangle(fl_display, FL_ObjWin(ob), LyXGetLightedGC(), ob->x, ob->y,ob->w,ob->h);
      }
   }
   UpdateLayoutChoice();
   return 0;
}


// changed semantic: only resize if necessary (Matthias 040696)
void ResizeCurrentBufferPseudoExpose()
{
  if (bufferlist.current()->screen){
    UpdateScrollbar();
    WorkAreaExpose(fd_form_main->work_area,0);
  }
  else
    /* resize current buffer through Pseudo-Expose*/
    WorkAreaExpose(fd_form_main->work_area,1);
}


void RedoCurrentBuffer()
{
   if (bufferlist.current()->text){
      if (bufferlist.current()->screen)
      	 delete bufferlist.current()->screen;
      bufferlist.current()->screen = NULL;
      ResizeCurrentBufferPseudoExpose();
   }
}


void MenuSearch()
{
  if (fd_form_search->form_search->visible) {
	  fl_raise_form(fd_form_search->form_search);
  } else 
    fl_show_form(fd_form_search->form_search,
		 FL_PLACE_MOUSE | FL_FREE_SIZE, FL_FULLBORDER,
		 "Find & Replace");											// RVDK_PATCH_5
}


void MenuQuit()
{
	ProhibitInput();

	bufferlist.QwriteAll();

   if (fl_show_question("", "Do you really want to quit LyX?", "")) {
      lastfiles->WriteFile(lyxrc.lastfiles);
      // set a flag that we do quitting from the program, so no refreshes
      // are necessary
      quitting = true;

      // close buffers first
      bufferlist.closeAll();

      // do any other cleanup procedures now
      if (lyx_debug_level & DEBUG_INIT) {
	      fprintf(stderr, "Deleting tmp dir `%s'\n", system_tempdir);
      }
      DestroyLyXTmpDir(system_tempdir);
      DeleteSimpleCutBuffer();
      exit(0);
   }
   AllowInput();
}


void QuitLyX()
{
	bufferlist.QwriteAll();

	lastfiles->WriteFile(lyxrc.lastfiles);
	
	// Set a flag that we do quitting from the program,
	// so no refreshes are necessary.
	quitting = true;

	// close buffers first
	bufferlist.closeAll();

	// do any other cleanup procedures now
	if (lyx_debug_level & DEBUG_INIT) {
		fprintf(stderr, "Deleting tmp dir `%s'\n", system_tempdir);
	}	DestroyLyXTmpDir(system_tempdir);
	DeleteSimpleCutBuffer();
	exit(0);
}


void MenuPrint()
{
   const char* filename = NULL;
   char * input_file;

   if (!bufferlist.current()->text) {
      filename = "No_File";
   }
   else
      filename = bufferlist.current()->filename;
   input_file = ChangeExtension (NULL, filename, lyxrc.print_file_extension, 1);
   if (lyxrc.printer)
      fl_set_input(fd_form_print->input_printer, lyxrc.printer);
   else
      fl_set_input(fd_form_print->input_printer, "lp");
   
   fl_set_input(fd_form_print->input_file, input_file);
   
   /* set the other default entries */ 
   fl_set_button(fd_form_print->radio_order_normal, 1);
   fl_set_button(fd_form_print->radio_all_pages, 1);
   fl_set_button(fd_form_print->radio_printer, 1);
   fl_set_button(fd_form_print->radio_file, 0);
   fl_set_button(fd_form_print->radio_odd_pages, 0);
   fl_set_button(fd_form_print->radio_even_pages, 0);
   fl_set_button(fd_form_print->radio_order_reverse, 0);

   if (fd_form_print->form_print->visible) {
	   fl_raise_form(fd_form_print->form_print);
   } else  
     fl_show_form(fd_form_print->form_print,
		  FL_PLACE_MOUSE | FL_FREE_SIZE, FL_FULLBORDER,
		  "Print");
   delete[] input_file;
}


void MenuRunLaTeX()
{
   int ret;

   if (IsLinuxDoc()) ret = RunLinuxDoc(1, bufferlist.current()->filename);
   else ret = RunLaTeX();
   
   if (ret == 0) {
      /* fl_show_message("","Compilation successfull!",""); */ 
   }
   else if (ret > 0) {
      char * s = new char [50];
      if (ret == 1)
      	 sprintf(s, "%d error detected",ret);
      else
      	 sprintf(s, "%d errors detected",ret);
      WriteAlert("LaTeX Error!", s, "");
      delete[] s;
   }
}


void AutoSave()
{
   char *fname;
   pid_t pid;

/* revise this dabn100 */
   if (bufferlist.current()->text) {
      if (!bufferlist.current()->isBakClean()) {
	 minibuffer.Set("Autosaving current document...");

	 /* create autosave filename */
	 fname = AddExtension (NULL, bufferlist.current()->filename, ".bak"); 
	 
	 /* make a backup */ 
	 char *s = AddExtension (NULL, fname, "~");
	 bufferlist.current()->parameters.cursor =
	   bufferlist.current()->text->cursor;
	 char* tmpname = StringCopy("lyxtmpXXXXXX");
	 char* tmp_ret = mktemp(tmpname);
	 signal(SIGCHLD, sigchldhandler);
	 pid = fork();
	 if (pid == 0 || pid == -1){
	   if (tmp_ret){
	     bufferlist.current()->parameters.writeFile(tmpname, 1);
	     rename(fname, s);
	     rename(tmp_ret, fname);
	   }
	   else {
	     rename(fname, s);
	     bufferlist.current()->parameters.writeFile(fname, 1);
	   }
	   if (pid == 0){
	     _exit(0);
	   }
	 }
	 //bufferlist.current()->bak_current = true;
	 bufferlist.current()->markBakClean();
	 delete[] s;
	 delete[] fname;
	 delete[] tmpname;
      }
      else {
	 minibuffer.Set("Autosave not necessary");
      }
   }
   
   if (lyxrc.autosave)
      fl_set_timer(fd_form_main->timer_autosave, lyxrc.autosave);
}


void MenuLoadAutoSave()
{
   char *fname;

   if (lyxrc.autosave)
      fl_set_timer(fd_form_main->timer_autosave, lyxrc.autosave);

   if (!bufferlist.current()->text)
      return;
   
   /* create autosave filename */
   fname = AddExtension (NULL, bufferlist.current()->filename, ".bak"); 
   
   minibuffer.Set("Opening autosave file",fname,"...");   
   
   if (!OpenAllFile(fname) && !OpenAllFile(bufferlist.current()->filename)) {
      WriteAlert("Operation not possible!", "No autosave file:",
		 fname);
   } else {
      
      LyXParagraph *par = bufferlist.current()->parameters.paragraph;
      LyXParagraph *tmppar = par;
      while(par){
	 tmppar = par->next;
	 delete par;
	 par = tmppar;
      }
      
      bufferlist.current()->parameters.readFile();
      bufferlist.current()->markDirty();
      CloseFile();

      bufferlist.current()->text->cursor =
	      bufferlist.current()->parameters.cursor;
      bufferlist.current()->text->ClearSelection();
      if (bufferlist.current()->text->cursor.par->footnoteflag ==
	  LYX_CLOSED_FOOTNOTE){
	      //LyXParagraph* tmppar = bufferlist.current()->text->cursor.par;
	tmppar = bufferlist.current()->text->cursor.par;
	while (tmppar->previous && 
	       tmppar->previous->footnoteflag == LYX_CLOSED_FOOTNOTE)
	  tmppar = tmppar->previous;
	while (tmppar && tmppar->footnoteflag == LYX_CLOSED_FOOTNOTE){
	  tmppar->footnoteflag = LYX_OPEN_FOOTNOTE;
	  tmppar = tmppar->next;
	}
      }
      
      /* use the backup as new autosave file */
      rename(fname, ".lyxtmp");
      char *s = AddExtension (NULL, fname, "~");
      rename(s, fname);
      rename(".lyxtmp", s);
      delete[] s;
      if (bufferlist.current()->screen) {
	 delete bufferlist.current()->screen;
	 bufferlist.current()->screen = NULL;
      }
      ResizeCurrentBufferPseudoExpose();
      minibuffer.Set("Autosave file opened");
   }
   
   delete[] fname;
}


void MenuOpen()
{
   const char *got_fname;

   ProhibitInput();

   got_fname = getFileFromDir("Document to Open", document_path, "*.lyx", "");
   if (document_path){
     delete[] document_path;
   }
   document_path = GetFSelDir(NULL);
   
   // flushes Xlib queue
   XFlush(fl_get_display());
   AllowInput();
   
   if (!got_fname)
      return;
   
   /* shorten the filename if it begins with the path */
   /* revise this: dabn100 */
   // do _not_ shorten path. We need absolute paths to ensure 
   // correct behaviour of buffer compares!
   char *fname = PathCopy (got_fname);
   
   if (fname == NULL) return;
 
   minibuffer.Set("Opening document",fname,"...");   

   LoadLyXFile(fname);
   ResizeCurrentBufferPseudoExpose();

   minibuffer.Set("Document",fname,"open");      
}


void LoadLyXFile(const char *filename)
{
	char *s;
	bool ro = false;
	// revise this: dabn100 
	// as soon as we have auto-allocating AbsPath and RelPath
	// make sure our path is absolute
	s = MakeAbsPath2 (NULL, filename);
	if (IsSGMLFilename(filename)) 
		if (!RunLinuxDoc(-1, filename)) {
			s = ChangeExtension (s, s, ".lyx", 0);
		}
   
	// file already open?
	if (bufferlist.exists(s)) {
		WriteAlert("Error!", "Document already open:", s);
		return;
	}
	switch (IsFileWriteable(s)) {
		case 1: break; //fine- it's r/w
		case 0: WriteAlert ("Warning!", "File is read-only:", s);
			ro = true;
			break;	     //temporary measure
		case -1: 
		  WriteAlert("Error!", "Cannot open specified file:", s);
		  return;
			 break;
	} 
	if (!OpenFile(s)) {
		WriteAlert("Error!", "Cannot open specified file:", s);
	} else {
		bufferlist.readFile(s, ro);

		// this is a crude temporary development hack 
		// (Matthias)
		// please do not remove, since we might need it in the future:
// 		if (StringEqual(filename, "AutoCorrection.lyx")){
// 		  printf("AutoCorrection File loaded \n");
// 		  printf("Warning: This is temporary: Killing the buffer will cause segfaults...\n");
// 		  autocorrparameters = &(bufferlist.current()->parameters);
// 		}
		

		CloseFile();
	 
		lastfiles->newfile(bufferlist.current()->filename);
	}
}


//
// (c) CHT Software Service GmbH
// Uwe C. Schroeder
//
// Insert a Lyxformat - file into current buffer
//
void InsertLyxFile(char *filen)
{
	char *filename=MakeAbsPath2 (NULL, filen);
	char c;
	extern FILE *myfile;
	
	if (!OpenAllFile(filename)) {
		WriteAlert("Error!", "Cannot open specified file:",filename);
	} else {
		if (work_area_active)
			bufferlist.current()->screen->HideCursor();
		BeforeChange();
		c = fgetc(myfile);
		if (c=='#') {
			printf("will read file with header -> c == %c\n",c);
			ungetc(c, myfile);
			bufferlist.current()->parameters.readFile();
		} else {
			printf("will read file without header -> c == %c\n",c);
			ungetc(c, myfile);
			bufferlist.current()->parameters.readLyXformat2(bufferlist.current()->text->cursor.par);
		}
		CloseFile();
		if (bufferlist.current()->screen) {
			delete bufferlist.current()->screen;
			bufferlist.current()->screen = NULL;
		}
		ResizeCurrentBufferPseudoExpose(); 
	}
}


//
// (c) CHT Software Service GmbH
// Uwe C. Schroeder
//
// create new file with template
// SERVERCMD !
//
void NewLyxFile(char *filename)
{
	char *name, *tmpname;
	name=(char *)strdup(filename);
	tmpname=(char *)strchr(name,':');
	*tmpname=0x00;
	tmpname++;
	fprintf(stderr,"Arg is %s\nname is %s\ntemplate is %s\n",
		filename,name,tmpname);
	ProhibitInput();
	// split argument by :
	
	AllowInput();
	
	// find a free buffer 
	bufferlist.newFile(name,tmpname);               
	ResizeCurrentBufferPseudoExpose();
	lastfiles->newfile(bufferlist.current()->filename);
}


// insert ascii file
void InsertAsciiFile(char flag)
{
   const char *fname;
   LyXParagraph *tmppar;
   
   if (!bufferlist.current()->screen)
     return;
   
   ProhibitInput();

   SetFSelButton(0, NULL, NULL);
   SetFSelButton(1, NULL, NULL);
   fname = SelectFile("File to Insert", "","*","");

   AllowInput();

   if (fname == NULL) return;
   if (!OpenAllFile(fname)) {
     WriteAlert("Error!", "Cannot open specified file:",
		fname);
      
   } else {
      tmppar = new LyXParagraph();
      tmppar->readSimpleWholeFile();
      
      // set the end of the string
      tmppar->InsertChar(tmppar->last-1,'\0');
      CloseFile();
      
      // insert the string
      bufferlist.current()->screen->HideCursor();
      
      // clear the selection
      BeforeChange();
      if (!flag)
      	bufferlist.current()->text->InsertStringA(tmppar->text);
      else
      	bufferlist.current()->text->InsertStringB(tmppar->text);
      delete tmppar;
      Update(1);
   }
}


const char *getFileFromDir(char *info, char *path,
			   char *filter, char* name)
{
  const char *fname;
  
  SetFSelButton(0, "Documents", document_path);
  SetFSelButton(1, "Templates", lyxrc.template_path);
  fname = SelectFile(info, path, filter, name);
  SetFSelButton(0, NULL, NULL);
  SetFSelButton(1, NULL, NULL);

  return fname;
}


/* revise this: dabn100 */
void MenuNew()
{
	const char *fname;

	char *s;
	ProhibitInput();
	// fname = fl_show_input("Enter filename for new document:", "newfile.lyx");
	fname = getFileFromDir("Enter Filename for new document", document_path, "*.lyx", "newfile");
	if (document_path){
	  delete[] document_path;
	}
	document_path = GetFSelDir(NULL);
	AllowInput();
	if (fname == NULL) return;

	char *absbuf;
	
	// get absolute path of file
	absbuf = MakeAbsPath2 (NULL, fname);
	
	// make sure the filename ends with .lyx
	if (!IsLyXFilename(absbuf)) {
		s = AddExtension (NULL, absbuf, ".lyx");
		delete[] absbuf;
	} else s = absbuf;

	if (bufferlist.exists(s)){
		WriteAlert("Error!", "Document already open:", s);
		delete[] s;
		return;
	}
	
	// check wether the file exists
	if (OpenFile(s)) {
		CloseFile();
		WriteAlert("Error!", "File already exists:", s);
		delete[] s;
	} else {
		// the template stuff
		ProhibitInput();

		fname = getFileFromDir("Choose template", lyxrc.template_path,
				       "*.lyx", "");
		
		AllowInput();

 		// find a free buffer 
		bufferlist.newFile(s,fname);
		
		ResizeCurrentBufferPseudoExpose();

		//		lastfiles->newfile(bufferlist.current()->filename);
	}      
}


void MenuWrite(Buffer* buf)
{
	bufferlist.write(buf);
	lastfiles->newfile(bufferlist.current()->filename);
}


void MenuMakeLaTeX()
{
   if (bufferlist.current()->text) {
      
      /* get LaTeX-Filename */
      char *s = ChangeExtension (NULL, bufferlist.current()->filename, ".tex", 0);
      if (IsLinuxDoc())
	      RunLinuxDoc(0, bufferlist.current()->filename);
      else
	      bufferlist.current()->parameters.makeLaTeXFile(s, NULL, 65);

      minibuffer.Set("Nice LaTeX file saved as", s);
      delete[] s;
      //bufferlist.current()->dvi_current = false;
      bufferlist.current()->markDviDirty();
   }
   
}


void MenuMakeLinuxDoc()
{

   if (bufferlist.current()->text) {

      if (!IsLinuxDoc()) {
         WriteAlert("Error!", "Textclass must be linuxdoc.", "");
         return;
      }

      /* get LinuxDoc-Filename */
      char *s = ChangeExtension (NULL, bufferlist.current()->filename, ".sgml", 0);
      minibuffer.Set("Building LinuxDoc SGML file", s,"...");

      bufferlist.current()->parameters.makeLinuxDocFile(s, 65);
      minibuffer.Set("LinuxDoc SGML file", s,"build");
      delete[] s;
   }
}


void MenuWriteAs()
{
	const char *fname;
	
	char *s = NULL;

	if (!bufferlist.current()->text) return;
	
	ProhibitInput();
	fname = fl_show_input("Enter filename to save as:",
			      bufferlist.current()->filename);
	AllowInput();
	if (fname == NULL) return;
	
	/* make sure the filename ends with .lyx */
	if (!IsLyXFilename(fname)) {
		s = AddExtension (NULL, fname, ".lyx");
	} else s = PathCopy (fname);
	
	/* file already open? */
	if (bufferlist.exists(s)){
		WriteAlert("Error!", "Document already open:",
			   s);
		return;
	}

	/* check wether the file exists */
	if (OpenFile(s)) {
		CloseFile();
		WriteAlert("Error!", "File already exists:",
			   s);
		delete[] s;
	} else {
		// ok,change the name of the buffer
		  
		if (bufferlist.current()->filename)
			delete[] bufferlist.current()->filename;
	
		bufferlist.current()->filename = s;
		//bufferlist.current()->lyx_current = false;
		//bufferlist.current()->dvi_current = false;
		// why isn't bak_current marked as dirty?
		bufferlist.current()->markDirty();
		
		MenuWrite(bufferlist.current());
	}
}    


void MenuShowTableOfContents()
{
   TocUpdateCB(NULL, 0);
   if (fd_form_toc->form_toc->visible) {
	   fl_raise_form(fd_form_toc->form_toc);
   } else    
     fl_show_form(fd_form_toc->form_toc,
		  FL_PLACE_MOUSE | FL_FREE_SIZE, FL_FULLBORDER,
		  "Table Of Contents");
}


void MenuInsertLabel()
{
  ProhibitInput();
  char *tmp = StringCopy(fl_show_input("Enter new label to insert:",""));
  InsetLabel *new_inset = new InsetLabel(tmp);
  bufferlist.current()->text->InsertInset(new_inset);
  Update(-1);
  delete[] tmp;
  AllowInput();
}


void MenuInsertRef()
{
   RefUpdateCB(NULL, 0);
   fl_set_button(fd_form_ref->radio_ref, 1);
   fl_set_button(fd_form_ref->radio_pageref, 0);
   if (fd_form_ref->form_ref->visible) {
	   fl_raise_form(fd_form_ref->form_ref);
   } else    
     fl_show_form(fd_form_ref->form_ref,
		  FL_PLACE_MOUSE | FL_FREE_SIZE, FL_FULLBORDER,
		  "Insert Reference");
}


/* returns 1 if inset was hit. Coordinates are set relativly to the inset.
   otherwise coordinates doesn't change their values and 0 is returned.
 */
int CheckInsetHit(int &x, int &y)
{
  if (!bufferlist.current()->screen)
    return 0;
  
  int y_tmp = y + bufferlist.current()->screen->first;
  
  LyXCursor cursor = bufferlist.current()->text->cursor;
  if (cursor.pos 
      < cursor.par->Last() 
      && cursor.par->GetChar(cursor.pos) == LYX_META_INSET
      && cursor.par->GetInset(cursor.pos)
      && cursor.par->GetInset(cursor.pos)->Editable()) {

	  /* check wether the inset was really hit */
    Inset* tmpinset = cursor.par->GetInset(cursor.pos);
    LyXFont font = bufferlist.current()->text->GetFont(cursor.par, cursor.pos);
    if (x > cursor.x
	&& x < cursor.x + tmpinset->Width(font) 
	&& y_tmp > cursor.y - tmpinset->Ascent(font)
	&& y_tmp < cursor.y + tmpinset->Descent(font)){
      x = x - cursor.x;
      y = y_tmp - (cursor.y); //  - tmpinset->Ascent(font)); // now the origin of an inset
					      // is on the baseline (for mathed) (Matthias)
      return 1;
    }
  }
  return 0;
}


int WorkAreaButtonRelease(FL_OBJECT *ob, Window ,
			  int /*w*/, int /*h*/, XEvent *ev, void */*d*/)
{

  if (bufferlist.current()->screen && bufferlist.current()->the_locking_inset){
    int x = ev->xbutton.x - ob->x;
    int y = ev->xbutton.y - ob->y;

    /* we are in inset locking mode. */
    /* LyX does a kind of work-area grabbing for insets.
       only a ButtonPress Event outside the inset will 
       force a InsetUnlock */
    CheckInsetHit(x, y); /* just to adept the coordinates */
    bufferlist.current()->the_locking_inset->InsetButtonRelease(x, y, ev->xbutton.button);
    return 0;
  }
  
  selection_possible = false;
  return 0;
}


int WorkAreaButtonPress(FL_OBJECT *ob, Window,
			int /*w*/, int /*h*/, XEvent *ev, void */*d*/)
{
   work_area_active = True;
   if (!bufferlist.current()->screen)
     return 0 ;

   int x = ev->xbutton.x - ob->x;
   int y = ev->xbutton.y - ob->y;

   if (bufferlist.current()->the_locking_inset){
     /* we are in inset locking mode. */

     /* check wether the inset was hit. If not reset mode, otherwise
	give the event to the inset */
     
     if (CheckInsetHit(x, y)){ 
       bufferlist.current()->the_locking_inset->InsetButtonPress(x, y, ev->xbutton.button);
       return 0;
     }
     else {
       UnlockInset(bufferlist.current()->the_locking_inset);
     }
   }
   
   selection_possible = true;
   bufferlist.current()->screen->HideCursor(); 

   if (ev->xbutton.button == 3
       &&   bufferlist.current()->text->cursor.par->table) {
     char doit = 1;
     // only show the table popup if the hit is on the table, too

     if (!bufferlist.current()->text->HitInTable(bufferlist.current()->text->cursor.row,
					       ev->xbutton.x - ob->x))
       doit = 0; 
     
     // hit above or below the table ?
     if (doit){
       long y_tmp = ev->xbutton.y - ob->y + bufferlist.current()->screen->first;
       Row*  row =  bufferlist.current()->text->GetRowNearY(y_tmp);
       if (row->par != bufferlist.current()->text->cursor.par)
	 doit = 0;
     }
     
     if (doit){
       if (!bufferlist.current()->text->selection){
	 bufferlist.current()->screen->ToggleSelection();
	 bufferlist.current()->text->ClearSelection();
	 bufferlist.current()->text->FullRebreak();
	 bufferlist.current()->screen->Update();
	 UpdateScrollbar();
       }
       // popup table popup when on a table.
       // this is obviously temporary, since we should be ablte to 
       // popup various context-sensitive-menus with the
     // the right mouse. So this should be done more
       // general in the future. Matthias.
       selection_possible = false;
       ShowEditMenu(ob, 99);
       return 0;
     }
   }

   char paste_internally = False;
   if (ev->xbutton.button == 2 && !bufferlist.current()->the_locking_inset
       && bufferlist.current()->text->selection){
     CopyCB();
     paste_internally = True;
   }

   /* clear the selection */ 
   bufferlist.current()->screen->ToggleSelection();
   bufferlist.current()->text->ClearSelection();
   bufferlist.current()->text->FullRebreak();
   bufferlist.current()->screen->Update();
   UpdateScrollbar();


   if (ev->xbutton.button == 3
       &&   bufferlist.current()->text->cursor.par->footnoteflag == LYX_OPEN_FOOTNOTE) {
     selection_possible = false;
     ShowEditMenu(ob, 98);
     return 0;
   }

   if (ev->xbutton.button == 3){
     selection_possible = false;
     return 0;
   }

   
   bufferlist.current()->text->SetCursorFromCoordinates(ev->xbutton.x - ob->x,
							ev->xbutton.y - ob->y +
							bufferlist.current()->screen->first);
   bufferlist.current()->text->FinishUndo();
   bufferlist.current()->text->sel_cursor =
	   bufferlist.current()->text->cursor;
   bufferlist.current()->text->cursor.x_fix =
	   bufferlist.current()->text->cursor.x;
   

   /* this is a try for highly-editable-insets (like mathinsets).
      Just one click is enough now*/ 
   if (ev->xbutton.button == 1){
     int x2 = ev->xbutton.x - ob->x;
     int y2 = ev->xbutton.y - ob->y;
     if (CheckInsetHit(x2, y2)){
       if (bufferlist.current()->text->cursor.par->GetInset(bufferlist.current()->text->cursor.pos)->Editable() == 2){
	 selection_possible = false;
	 UpdateLayoutChoice();
	 minibuffer.Set(bufferlist.current()->text->cursor.par->GetInset(bufferlist.current()->text->cursor.pos)->EditMessage());
	 bufferlist.current()->text->cursor.par->GetInset(bufferlist.current()->text->cursor.pos)->Edit(x2, y2);
	 return 0;
       }
     }
     // the new way to close a float: click on the float-label
     if (bufferlist.current()->text->cursor.row->par->footnoteflag == LYX_OPEN_FOOTNOTE
	 && bufferlist.current()->text->cursor.pos == 0
	 && bufferlist.current()->text->cursor.row->previous &&
	 bufferlist.current()->text->cursor.row->previous->par->footnoteflag != LYX_OPEN_FOOTNOTE){
       LyXFont font = {
	 LYX_ROMAN_FAMILY,
	 LYX_MEDIUM_SERIES,
	 LYX_UP_SHAPE,
	 LYX_SIZE_SMALL, 
	 LYX_LATEX,
	 LYX_NO_BAR};
       int box_x = 20; // LYX_PAPER_MARGIN;
       box_x += LyXTextWidth(font, " margin ", 8);
       
       if (ev->xbutton.x - ob->x < box_x
	   && ev->xbutton.y - ob->y + bufferlist.current()->screen->first
	   > bufferlist.current()->text->cursor.y - bufferlist.current()->text->cursor.row->baseline
	   && ev->xbutton.y - ob->y + bufferlist.current()->screen->first
	   < bufferlist.current()->text->cursor.y - bufferlist.current()->text->cursor.row->baseline
	   + LyXMaxAscent(font)*1.2 + LyXMaxDescent(font)*1.2){
	 ToggleFloat();
	 selection_possible = false;
	 return 0;
       }
     }
   }
   
   /* i will use the middle button to edit insets or toggle footnotes */ 
//    if (ev->xbutton.button == 2) {
//      if (CheckInsetHit(x, y)){
//        selection_possible = false;
//        if (bufferlist.current()->text->cursor.par->GetInset(bufferlist.current()->text->cursor.pos)->Editable() != 2)
// 	 bufferlist.current()->text->SetCursorParUndo();
//        minibuffer.Set(bufferlist.current()->text->cursor.par->GetInset(bufferlist.current()->text->cursor.pos)->EditMessage());
//        bufferlist.current()->text->cursor.par->GetInset(bufferlist.current()->text->cursor.pos)->Edit(x, y);
//      }
//      else {
//        selection_possible = false;
//        bufferlist.current()->text->ToggleFootnote();
//      }
//      Update(-2);
//      return 0;
//    }

   UpdateLayoutChoice();
   if (bufferlist.current()->screen->FitCursor()){
     UpdateScrollbar();
     selection_possible = false;
   }

   // insert primary selection with middle mouse
   // if there is a local selection in the current buffer, insert this
   if (ev->xbutton.button == 2 && !bufferlist.current()->the_locking_inset){
     if (paste_internally)
       PasteCB();	
     else
       MenuPasteSelection(0);
     selection_possible = false;
   }

   return 0;
}


// can't be static since keybind.C wants it
void CursorPrevious()
{
  if (bufferlist.current()->text->cursor.row->previous){
    long y = bufferlist.current()->screen->first;
    long cursory = bufferlist.current()->text->cursor.y - y;
    Row* row = bufferlist.current()->text->GetRowNearY(y);
    Row* cursorrow = bufferlist.current()->text->cursor.row;
    y = y - work_area_height + row->height;
    bufferlist.current()->screen->Draw(y);
    bufferlist.current()->text->SetCursorFromCoordinates(bufferlist.current()->text->cursor.x_fix,
							   cursory + y);
    bufferlist.current()->text->FinishUndo();
    /* this is to allow jumping over large insets */
    if ((cursorrow == bufferlist.current()->text->cursor.row))
      bufferlist.current()->text->CursorUp();
    else{
      if (bufferlist.current()->screen->TopCursorVisible() < bufferlist.current()->screen->first)
	bufferlist.current()->text->CursorDown();
      else if (bufferlist.current()->screen->TopCursorVisible() > bufferlist.current()->screen->first)
	bufferlist.current()->text->CursorUp();
    }
  }
}


// can't be static since keybind.C wants it
void CursorNext()
{
  if (bufferlist.current()->text->cursor.row->next){
    long y = bufferlist.current()->screen->first;
    long cursory = bufferlist.current()->text->cursor.y - y;
    y += work_area_height;
    bufferlist.current()->text->GetRowNearY(y);
    bufferlist.current()->screen->Draw(y);
    Row* cursorrow = bufferlist.current()->text->cursor.row;
    bufferlist.current()->text->SetCursorFromCoordinates(bufferlist.current()->text->cursor.x_fix, cursory + y);
    bufferlist.current()->text->FinishUndo();
    /* this is to allow jumping over large insets */
    if ((cursorrow == bufferlist.current()->text->cursor.row))
      bufferlist.current()->text->CursorDown();
    else{
      if (bufferlist.current()->screen->TopCursorVisible() < bufferlist.current()->screen->first)
	bufferlist.current()->text->CursorDown();
      else if (bufferlist.current()->screen->TopCursorVisible() > bufferlist.current()->screen->first)
	bufferlist.current()->text->CursorUp();
    }
  }
}


int WorkAreaMotionNotify(FL_OBJECT *ob, Window, int /*w*/, int /*h*/,
			 XEvent *ev, void */*d*/)
{
	if (!bufferlist.current()->screen)
		return 0;
   
   /* check for inset locking */
   if (bufferlist.current()->the_locking_inset){
     LyXCursor cursor = bufferlist.current()->text->cursor;
     LyXFont font = bufferlist.current()->text->GetFont(cursor.par,
							cursor.pos);
     bufferlist.current()->the_locking_inset->InsetMotionNotify(ev->xbutton.x - ob->x - cursor.x,
					  ev->xbutton.y - ob->y -
					  (cursor.y -
					   bufferlist.current()->the_locking_inset->Ascent(font)),
					  ev->xbutton.state);
     return 0;
   }
   
   /* only use motion with button 1 */
   if (!ev->xmotion.state & Button1MotionMask)
     return 0; 
    
   
   /* the selection possible is needed, that only motion events are 
    * used, where the bottom press event was on the drawing area too */
   if (selection_possible) {
      
      bufferlist.current()->screen->HideCursor();
      /* bufferlist.current()->screen->ToggleSelection(); */

      bufferlist.current()->text->SetCursorFromCoordinates(ev->xbutton.x - ob->x,
						     ev->xbutton.y - ob->y +
						     bufferlist.current()->screen->first);
      
      if (!bufferlist.current()->text->selection)
      	Update(-3);       /* maybe an empty line was deleted  */
      
      bufferlist.current()->text->SetSelection();
      bufferlist.current()->screen->ToggleToggle();
      if (bufferlist.current()->screen->FitCursor())
      	UpdateScrollbar(); 
      bufferlist.current()->screen->ShowCursor();
   } 
   return 0;
}


int WorkAreaEnterNotify(FL_OBJECT *, Window, int /*w*/, int /*h*/,
			XEvent *, void */*d*/)
{
	work_area_active = True;

	if (bufferlist.current()->screen
	    && !input_prohibited
	    && !bufferlist.current()->the_locking_inset)
		bufferlist.current()->screen->ShowCursor();
	
	return 0;
}


int WorkAreaLeaveNotify(FL_OBJECT *, Window,
			int /*w*/, int /*h*/, XEvent *, void */*d*/)
{
   work_area_active = False;

   if (bufferlist.current()->screen) {
      bufferlist.current()->screen->HideCursor();
      bufferlist.current()->text->FullRebreak();
      bufferlist.current()->screen->Update();
      UpdateScrollbar();
   }
   
   return 0;
}


void CursorToggleCB(FL_OBJECT *ob, long)
{
  /* quite a nice place for asyncron Inset updating, isn't it? */
  if (InsetUpdateList) 
    UpdateInsetUpdateList();

  if (!bufferlist.current()->screen){
    fl_set_timer(ob, 0.4);
    return;
  }

  if (!bufferlist.current()->the_locking_inset){
    if (bufferlist.current()->screen->cursor_visible){
      bufferlist.current()->screen->CursorToggle();
      fl_set_timer(ob, 0.4);
      return;
    }
  }
  else {
    if (bufferlist.current()->the_locking_inset->cursor_visible){
      bufferlist.current()->the_locking_inset->ToggleInsetCursor();
      fl_set_timer(ob, 0.4);
      return;
    }
  }

  Window tmpwin;
  int tmp;
  XGetInputFocus(fl_display, &tmpwin, &tmp);
  if (fd_form_main->work_area->focus && tmpwin == fd_form_main->form_main->window){
    if (bufferlist.current()->the_locking_inset)
      bufferlist.current()->the_locking_inset->ToggleInsetCursor();
    else
      bufferlist.current()->screen->CursorToggle();
  }
   fl_set_timer(ob, 0.4);

}


void CloseBuffer()
{
  bufferlist.close(); // <- who removed that? This IS important. (Matthias)
	if (!quitting) { 
		ResizeCurrentBufferPseudoExpose();
	}
}



// this is necessary, since FL_FREE-Objects doesn't get all keypress events
// as FL_KEYBOARD events :-(   Matthias 280596
int work_area_KeyPressMask_raw_callback(FL_FORM *, void *xev){
  // funny. Even though the raw_callback is registered with KeyPressMask,
  // also KeyRelease-events are passed through:-(
  if (((XEvent*)xev)->type == KeyPress
      && fd_form_main->work_area->focus
      && fd_form_main->work_area->active)
    return WorkAreaKeyPress(fd_form_main->work_area, 0,0,0,(XEvent*)xev,NULL); 
  else
    return 0; // 0 means XForms should have a look at this event, too
}

   
int work_area_handler(FL_OBJECT * ob, int event, FL_Coord, FL_Coord ,
		      int /*key*/, void *xev)
{
  XEvent* ev = (XEvent*) xev;
  
  switch (event){   
  case FL_DRAW: WorkAreaExpose(ob, 0); break;
  case FL_PUSH: WorkAreaButtonPress(ob, 0,0,0,ev,NULL); break; 
  case FL_RELEASE: WorkAreaButtonRelease(ob, 0,0,0,ev,NULL); break;
  case FL_MOUSE: WorkAreaMotionNotify(ob, 0,0,0,ev,NULL); break;
    // done by the raw callback
    //  case FL_KEYBOARD: WorkAreaKeyPress(ob, 0,0,0,ev,NULL); break;
  case FL_FOCUS:
    if (!minibuffer.shows_no_match)
      minibuffer.Init();
    minibuffer.shows_no_match = false;
    break;
  case FL_UNFOCUS: 
    if (bufferlist.current()->screen)
      bufferlist.current()->screen->HideCursor();
    minibuffer.ExecCommand();
    break;
  case FL_ENTER:
    SetXtermCursor(fd_form_main->form_main->window);
    break;
  case FL_LEAVE: 
    if (!input_prohibited)
      XUndefineCursor(fl_display, fd_form_main->form_main->window);
    break;
  case FL_DBLCLICK: 
    if (!bufferlist.current()->the_locking_inset)
    {
      
      // check wether we want to open a float
      if (bufferlist.current()->text && 
	  bufferlist.current()->text->cursor.pos < bufferlist.current()->text->cursor.par->Last()){
	char c = bufferlist.current()->text->cursor.par->GetChar(bufferlist.current()->text->cursor.pos);
	if (c == LYX_META_FOOTNOTE || c == LYX_META_MARGIN
	    || c == LYX_META_FIG || c == LYX_META_TAB){
	  ToggleFloat();
	  break;
	}
      }

      // select a word 
      int x = ev->xbutton.x - ob->x;
      int y = ev->xbutton.y - ob->y;
      if (bufferlist.current()->screen && ev->xbutton.button == 1){
	bufferlist.current()->screen->HideCursor(); 
	if (CheckInsetHit(x, y)){
	  selection_possible = false;
	  bufferlist.current()->text->SetCursorParUndo();
	  minibuffer.Set(bufferlist.current()->text->cursor.par->GetInset(bufferlist.current()->text->cursor.pos)->EditMessage());
	  bufferlist.current()->text->cursor.par->GetInset(bufferlist.current()->text->cursor.pos)->Edit(x, y);
	  Update(-2);
	}
	else {
	  bufferlist.current()->screen->ToggleSelection(); 
	  bufferlist.current()->text->SelectWord();
	  bufferlist.current()->screen->ToggleSelection();
	  Update(0); /* this will fit the cursor on the screen
		      * if necessary */ 
	}
      }
    }
  break;
  case FL_TRPLCLICK:
    // select a line
      if (bufferlist.current()->screen && ev->xbutton.button == 1){
      bufferlist.current()->screen->HideCursor(); 
      bufferlist.current()->screen->ToggleSelection(); 
      bufferlist.current()->text->CursorHome();
      bufferlist.current()->text->sel_cursor =  bufferlist.current()->text->cursor;
      bufferlist.current()->text->CursorEnd();
      bufferlist.current()->text->SetSelection();
      bufferlist.current()->screen->ToggleSelection(); 
      Update(0); /* this will fit the cursor on the screen
		  * if necessary */ 
    }
    break;
  case FL_OTHER:
    WorkAreaSelectionNotify(ob, fd_form_main->form_main->window,0,0,ev,NULL); 
    break;
  }
  
  
  return 0;
}


void init(int argc, char **argv)
{
   // setup the default toolbar
   toolbar.init();
   
   UpdateDocumentClassChoice();
   
   /* activate the timer for the cursor */ 
   fl_set_timer(fd_form_main->timer_cursor, 0.4);
   
   /* read the rc file */ 
   const char* home = getenv("HOME");
   
   PathPush (home);
   
   const char * lyxdir = getenv ("LYX_DIR");
    if ((lyxdir != NULL)) { 
      system_lyxdir = PathCopy (lyxdir);
   }
   else {
      system_lyxdir = PathCopy (LYX_DIR);
   }

   if (!lyxrc.template_path[0]){
      lyxrc.template_path = AddPath (NULL, system_lyxdir, "templates");
   }
   
   if (!lyxrc.lastfiles){
      lyxrc.lastfiles = AddName (NULL, home, ".lyx_lastfiles");
   }
   
   LyxDefaultKeyBindings();

   if (lyx_debug_level & DEBUG_INIT)
	   fprintf(stderr,"Reading lyxrc...");
   
   if (lyxrc.Read(".lyxrc") < 0) { 
       WriteAlert ("LyX Warning!", "User has no .lyxrc file. Reading defaults from system.lyxrc in",
        system_lyxdir);
 
       PathPush (system_lyxdir);
      if (lyxrc.Read("system.lyxrc") < 0) {
         WriteAlert ("LyX Warning!", "Could not read"
		     " system.lyxrc. Using defaults.","");
      }
      PathPop(); // system_lyxdir
   }

   if (lyxrc.autosave)
      fl_set_timer(fd_form_main->timer_autosave, lyxrc.autosave);
   
   // Warn the user when no default bindings were
   //set in the lyxrc file. RVDK_PATCH_5
   if ( BindFileSet == false ) 
          WriteAlert("LyX Warning!",
		     "No bind file loaded! Use the \\bind_file"
		     " command in .lyxrc.", "");

   if (lyx_debug_level & DEBUG_INIT) {
	   fprintf(stderr,"done!\n");
	   lyxrc.Print();
   }
    system_tempdir = CreateLyXTmpDir(lyxrc.tempdir_path);
    if (lyx_debug_level & DEBUG_INIT) {
	    fprintf(stderr,"LyX tmp dir: `%s'\n", system_tempdir);
    }
    PathPop();
    
   /* load the layouts in the layout choice  */
   LyXSetStyle(lyxrc.lyx_layout_lib);


   SetZoom(lyxrc.default_zoom);

   /* set the textclass choice */
   InvalidateLayoutChoice();
   UpdateLayoutChoice();
   UpdateDocumentClassChoice();

   /* install the signal handlers */ // could these be installed earlier ?? 
   signal(SIGHUP, error_handler);
   signal(SIGFPE, error_handler);
   signal(SIGSEGV, error_handler);
   signal(SIGINT, error_handler);
   signal(SIGTERM, error_handler);
   
   /* install the file handlers */
   LyxServerInit();

   /* install the raw callback for keyboard events */ 
   fl_register_raw_callback(fd_form_main->form_main,
			    KeyPressMask,
			    work_area_KeyPressMask_raw_callback);

   // load the lastfiles mini-database
   lastfiles = new LastFiles(lyxrc.lastfiles);
   		   
   // load the files specified in the command line
   for (int argi = argc-1; argi >= 1; argi--) {
      LoadLyXFile(argv[argi]);
   }
   
   // This is OK now, since WorkAreaExpose takes care... 
   ResizeCurrentBufferPseudoExpose();
}

   
/* callbacks for form form_main */
void FootCB(FL_OBJECT*, long)
{
   if (bufferlist.current()->text) {
      minibuffer.Set("Inserting Footnote...");
      bufferlist.current()->screen->HideCursor();
      Update(-2);
      bufferlist.current()->text->InsertFootnoteEnvironment(LYX_FOOTNOTE);
      Update(1);
   }
}


void LayoutsCB(int sel)
{
	if (!bufferlist.current()->screen){
	  current_layout = sel;
	  return;
	}

	sel--; // sel 1..., but layout 0...
	
	bufferlist.current()->screen->HideCursor();
	Update(-2);

	if (current_layout != sel) {
		current_layout = sel;
		bufferlist.current()->text->SetLayout(current_layout);
	}
	Update(1);
}


void WorkAreaCB(FL_OBJECT *, long)
{
  /* fill-in code for callback */
  printf("WorkAreaCB \n");
}


void ScrollCB(FL_OBJECT *ob, long)
{
   current_scrollbar_value = (long)fl_get_slider_value(ob);
   if (current_scrollbar_value < 0)
      current_scrollbar_value = 0;
   
   if (!bufferlist.current()->screen)
     return;
   
   bufferlist.current()->screen->Draw(current_scrollbar_value);
}


/*
 * SGML support:
 * (flag == -1) import SGML file
 * (flag == 0) make TeX output
 * (flag == 1) make dvi output
 */
int RunLinuxDoc(int flag, const char *filename)
{
    int n;
    // TeXErrors errors; // unused
   
    char *name = NULL, *s2 = NULL, *path = NULL;
   char add_flags[3];

   if ((flag == -1) || (bufferlist.current()->text)) {
      ProhibitInput();
       n = strlen (filename);
       /* generate a path-less extension name */
       name = ChangeExtension (NULL, filename, ".sgml", 1);
      s2 = new char[n+100]; /* used to print command strings into */
       path = NameToPath (NULL, filename);
       if (lyxrc.use_tempdir || (IsDirWriteable(path) < 1)) {
	  	delete[] path;
	  	path = PathCopy (bufferlist.current()->tmppath);	 
       }
       PathPush (path);

      if (flag != -1)
	      bufferlist.current()->parameters.makeLinuxDocFile(name, 0);

      *add_flags = 0;
      if (lyxrc.parameters.papersize == PAPER_A4) strcpy(add_flags, "-a");

      switch (flag) {
      case -1:			/* Import file */
         minibuffer.Set("Importing LinuxDoc SGML file:", filename, "...");
         sprintf(s2, "sgml2lyx %s %s", lyxrc.sgml_extra_options, name);
         if (system(s2)) return 1;
         break;
      case 0:			/* TeX output asked */
         minibuffer.Set("Converting LinuxDoc SGML to TeX file...");   
         sprintf(s2, "sgml2latex %s %s %s", add_flags, 
		 lyxrc.sgml_extra_options, name);
         if (system(s2)) return 1;
         break;
      case 1:			/* dvi output asked */
         minibuffer.Set("Converting LinuxDoc SGML to dvi file...");   
         sprintf(s2, "sgml2latex %s -d %s %s", add_flags,
		 lyxrc.sgml_extra_options, name);
         if (system(s2)) return 1;
         //bufferlist.current()->dvi_current = true;
	 bufferlist.current()->markDviClean();
         break;
      default:			/* unknown output */
         break;
      }

      AllowInput();

      PathPop();
      delete[] path;
      delete[] name;
      delete[] s2;
   }

   /* reserved for future error handling */
   return 0;
}


/* build either TeX (flag = 0), dvi (flag = 1), ... output */
int RunLaTeX()
{
   int n;
   int a = 0;
   TeXErrors errors;
   
   char *name = NULL, *s2 = NULL, *path = NULL, *org_path = NULL;

   if (bufferlist.current()->text) {
      ProhibitInput();
      n = strlen (bufferlist.current()->filename);
      name = ChangeExtension (NULL, bufferlist.current()->filename,
                              ".tex", 1);
      s2 = new char[n+100]; /* used to print command strings into */
      path = NameToPath (NULL, bufferlist.current()->filename);
      org_path = StringCopy(path);
      if (lyxrc.use_tempdir || (IsDirWriteable(path) < 1)) {
	  delete[] path;
	  path = PathCopy (bufferlist.current()->tmppath);	 
      }
      PathPush(path);
      minibuffer.Set("Running LaTeX...");   

      /* get LaTeX-Filename */
            
      /*Remove all errors */

      LyXParagraph *par = bufferlist.current()->parameters.paragraph;

      LyXCursor cursor = bufferlist.current()->text->cursor;
      LyXCursor tmpcursor = cursor;
      cursor.par = tmpcursor.par->ParFromPos(tmpcursor.pos);
      cursor.pos = tmpcursor.par->PositionInParFromPos(tmpcursor.pos);

      a = 0;
      while (par) {
	if (par->AutoDeleteInsets()){
	  a++;
	  if (par->footnoteflag != LYX_CLOSED_FOOTNOTE){
	    /* this is possible now, since SetCursor takes
	       care about footnotes */
	    bufferlist.current()->text->SetCursorIntern(par, 0);
	    bufferlist.current()->text->RedoParagraphs(bufferlist.current()->text->cursor, bufferlist.current()->text->cursor.par->Next());
	    bufferlist.current()->text->FullRebreak();
	  }
	}
	par = par->next;
      }
      /* avoid forbidden cursor positions caused by error removing */ 
      if (cursor.pos > cursor.par->Last())
	cursor.pos = cursor.par->Last();
      bufferlist.current()->text->SetCursorIntern(cursor.par, cursor.pos);

      if (!bufferlist.current()->isDviClean() || a) {
	      // MakeLaTeXFile(name, bufferlist.current()->parameters, 0);
	      bufferlist.current()->parameters.makeLaTeXFile(name, org_path, 0);
	 
	      //bufferlist.current()->dvi_current = false;
	      bufferlist.current()->markDviDirty();
      }
      
      /* new stuff */ 
       sprintf(s2, "%s %s", lyxrc.latex_command, name);
      system(s2);
      //bufferlist.current()->dvi_current = true;
      bufferlist.current()->markDviClean();
   
       /* scanning errors */
       /* check for safety in self-reference case dabn100 */
       ChangeExtension (name, name, ".log", 0);

      minibuffer.Set("Scanning log-file...");   

      ScanLogFile(name, bufferlist.current()->text, &errors);

      minibuffer.Set("Done");
      
      if (a || errors.number_of_errors){
	   bufferlist.current()->screen->Redraw();
	   bufferlist.current()->screen->FitCursor();
	   UpdateScrollbar();
      }
       
      if (errors.status == NO_LOGFILE) {
          WriteAlert("LaTeX did not work!", "Missing log file:", name);
	  //bufferlist.current()->dvi_current = false;
	  bufferlist.current()->markDviDirty();
      }
      
      AllowInput();

       PathPop();
       delete[] name;
       delete[] s2;
       delete[] path;
   }
      
   return errors.number_of_errors;
}


/* 0 means print, 4 means print on file, 1-3 means preview */
/* 1 xdvi, 2 dvips, 3 ghostview */
// I really hate this usr of flags, this must be rewritten. Lgb
void RunScript(char flag, const char* command)
{
	int n;
	int ret = 0;
	char * path, *name, *s2; 
	if (bufferlist.current()->text) {
		
		n = strlen (bufferlist.current()->filename);
		/* get DVI-Filename */
		name = ChangeExtension (NULL, bufferlist.current()->filename, ".dvi", 
					1);
		s2 = new char[n + 100];
		path = NameToPath (NULL, bufferlist.current()->filename);
		if (lyxrc.use_tempdir || (IsDirWriteable(path) < 1)) {
			delete[] path;
			path = PathCopy (bufferlist.current()->tmppath);	 
		}
		PathPush (path);
		if (!bufferlist.current()->isDviClean())
			if (IsLinuxDoc()) ret= RunLinuxDoc(1, 
           bufferlist.current()->filename);
      	else ret = RunLaTeX();
		
		if (!OpenAllFile(name)) {
			if (flag && (flag != 4))
				WriteAlert("Error!",
					   "Cannot preview: No LaTeX-Output (dvi)","");
			else
				WriteAlert("Error!",
					   "Cannot print: No LaTeX-Output (dvi)","");
		}
		else {
			CloseFile();
		}
		
		if (ret > 0) {
			char *s3 = new char [50];
			if (ret == 1)
				sprintf(s3, "%d error detected",ret);
			else
				sprintf(s3, "%d errors detected",ret);
			WriteAlert("LaTeX Error!", s3, "");
			delete[] s3;
		}
		
		if (flag==3) {
			minibuffer.Set("Executing command:", command);
			sprintf(s2, "%s ", command);
		} else {
			minibuffer.Set("Executing command:", command, name);   
			
			if ((flag == 2) || (flag == 4))
				sprintf(s2, "%s %s ", command, name);
			else
				sprintf(s2, "%s %s &", command, name);
		}
		
		system(s2); 
		
		PathPop();
		delete[] path;
		delete[] s2;	
		delete[] name;
	}
}


void MenuPreviewPS()
{
   int n;

   if (!bufferlist.current()->text)
      return;

   ProhibitInput();
   /* calculate ps filename */ 
   n = strlen (bufferlist.current()->filename);
   char *ps = ChangeExtension (NULL, bufferlist.current()->filename,
                               ".ps_tmp", 1);
   char* paper = "a4";
   
   switch (bufferlist.current()->parameters.papersize) {
    case PAPER_USLETTER:
      paper = "letter";
      break;
    case PAPER_A5PAPER:
      paper = "a5";
      break;
    case PAPER_B5PAPER:
      paper = "b5";
      break;
    case PAPER_EXECUTIVEPAPER:
      paper = "foolscap";
      break;
    case PAPER_LEGALPAPER:
      paper = "legal";
      break;
   }

   char* orientationflag = "";
   if (bufferlist.current()->parameters.orientation == ORIENTATION_LANDSCAPE)
      orientationflag = "-t landscape";
   
   char *command = new char[n + 100];
   
   sprintf(command, "dvips -o %s -t %s %s", ps, paper, orientationflag);
   
   RunScript(2, command);
   sprintf(command, "ghostview -swap %s &", ps);
   RunScript(3, command);
   AllowInput();
   delete[] command;
   delete[] ps;
}


void MenuPreview()
{
   if (!bufferlist.current()->text)
      return;
   
   char* command = new char[50];
   
   char* paper = "a4";
   
   switch (bufferlist.current()->parameters.papersize) {
    case PAPER_USLETTER:
      paper = "us";
      break;
    case PAPER_A5PAPER:
      paper = "a5";
      break;
    case PAPER_B5PAPER:
      paper = "b5";
      break;
    case PAPER_EXECUTIVEPAPER:
      paper = "foolscap";
      break;
    case PAPER_LEGALPAPER:
      paper = "legal";
      break;
   }
   
   char* rotate ="";
   
   if (bufferlist.current()->parameters.orientation == ORIENTATION_LANDSCAPE)
      rotate ="r";
   
   sprintf(command, "xdvi -paper %s%s %s", paper, rotate, 
	   lyxrc.xdvi_extra_options);
   
   RunScript(1, command);
   
   delete[] command;
}


void AllFloats(char flag, char figmar)
{
   if (!bufferlist.current()->text)
      return;
   
   if (!flag && bufferlist.current()->text->cursor.par->footnoteflag !=
       LYX_NO_FOOTNOTE
       && (
	   (figmar 
	    &&
	    bufferlist.current()->text->cursor.par->footnotekind !=
	    LYX_FOOTNOTE 
	    &&
	    bufferlist.current()->text->cursor.par->footnotekind !=
	    LYX_MARGIN
	    )
	   ||
	   (!figmar
	    &&
	    bufferlist.current()->text->cursor.par->footnotekind !=
	    LYX_FIG 
	    &&
	    bufferlist.current()->text->cursor.par->footnotekind !=
	    LYX_TAB
	    )
	   )
	 ){
	   ToggleFloat();
   } else
	   BeforeChange();

   LyXCursor cursor = bufferlist.current()->text->cursor;
   LyXCursor tmpcursor = cursor;
   cursor.par = tmpcursor.par->ParFromPos(tmpcursor.pos);
   cursor.pos = tmpcursor.par->PositionInParFromPos(tmpcursor.pos);

   LyXParagraph *par = bufferlist.current()->parameters.paragraph;
   while (par) {
      if (flag) {
	if (par->footnoteflag == LYX_CLOSED_FOOTNOTE
	    && (
		(figmar 
		 &&
		 par->footnotekind != LYX_FOOTNOTE 
		 &&
		 par->footnotekind !=  LYX_MARGIN
		 )
		||
		(!figmar
		 &&
		 par->footnotekind != LYX_FIG 
		 &&
		 par->footnotekind != LYX_TAB
		 )
		)
	    ){
	  if (par->previous
	      && par->previous->footnoteflag !=
	      LYX_CLOSED_FOOTNOTE){ /* should be */ 
		  bufferlist.current()->text->SetCursorIntern(par->previous,
							      0);
		  bufferlist.current()->text->OpenFootnote();
	  }
	}
      }
      else  {
	if (par->footnoteflag == LYX_OPEN_FOOTNOTE
	    && (
		(figmar 
		 &&
		 par->footnotekind != LYX_FOOTNOTE 
		 &&
		 par->footnotekind !=  LYX_MARGIN
		 )
		||
		(!figmar
		 &&
		 par->footnotekind != LYX_FIG 
		 &&
		 par->footnotekind != LYX_TAB
		 )
		)
	    ){
	  bufferlist.current()->text->SetCursorIntern(par, 0);
	  bufferlist.current()->text->CloseFootnote();
	}
      }
      par = par->next;
   }

   bufferlist.current()->text->SetCursorIntern(cursor.par, cursor.pos);
   bufferlist.current()->screen->Redraw();
   bufferlist.current()->screen->FitCursor();
   UpdateScrollbar();
}


void MenuLayoutCharacter()
{
  if (fd_form_character->form_character->visible) {
	  fl_raise_form(fd_form_character->form_character);
  } else
    fl_show_form(fd_form_character->form_character,
		 FL_PLACE_MOUSE | FL_FREE_SIZE,FL_FULLBORDER,
		 "Character Layout");
}


void MenuLayoutParagraph()
{
      if (bufferlist.current()->text) {
	 fl_set_input(fd_form_paragraph->input_labelwidth,
		      bufferlist.current()->text->cursor.par->GetLabelWidthString());
	 fl_set_button(fd_form_paragraph->radio_align_right, 0);
	 fl_set_button(fd_form_paragraph->radio_align_left, 0);
	 fl_set_button(fd_form_paragraph->radio_align_center, 0);
	 fl_set_button(fd_form_paragraph->radio_align_block, 0);
	 int align = bufferlist.current()->text->cursor.par->GetAlign();
	 if (align == LYX_ALIGN_LAYOUT)
	   align = lyxstyle.Style(bufferlist.current()->parameters.textclass,
	         bufferlist.current()->text->cursor.par->GetLayout())->align;
	 
	 switch (align) {
	  case LYX_ALIGN_RIGHT:
		  fl_set_button(fd_form_paragraph->radio_align_right, 1);
		  break;
	  case LYX_ALIGN_LEFT:
		  fl_set_button(fd_form_paragraph->radio_align_left, 1);
		  break;
	  case LYX_ALIGN_CENTER:
		  fl_set_button(fd_form_paragraph->radio_align_center, 1);
		  break;
	  default:
		  fl_set_button(fd_form_paragraph->radio_align_block, 1);
		  break;
	 }
	 
	 fl_set_button(fd_form_paragraph->check_lines_top,
		       bufferlist.current()->text->cursor.par->FirstPhysicalPar()->line_top);
	 fl_set_button(fd_form_paragraph->check_lines_bottom,
		       bufferlist.current()->text->cursor.par->FirstPhysicalPar()->line_bottom);
	 fl_set_button(fd_form_paragraph->check_pagebreaks_top,
		       bufferlist.current()->text->cursor.par->FirstPhysicalPar()->pagebreak_top);
	 fl_set_button(fd_form_paragraph->check_pagebreaks_bottom,
		       bufferlist.current()->text->cursor.par->FirstPhysicalPar()->pagebreak_bottom);
	 fl_set_button(fd_form_paragraph->check_noindent,
		       bufferlist.current()->text->cursor.par->FirstPhysicalPar()->noindent);
	 fl_set_button(fd_form_paragraph->check_fill_top,
		       bufferlist.current()->text->cursor.par->FirstPhysicalPar()->fill_top);
	 fl_set_button(fd_form_paragraph->check_fill_bottom,
		       bufferlist.current()->text->cursor.par->FirstPhysicalPar()->fill_bottom);
	 fl_set_slider_value(fd_form_paragraph->slider_spaces_top,
		       bufferlist.current()->text->cursor.par->FirstPhysicalPar()->added_space_top);
	 fl_set_slider_value(fd_form_paragraph->slider_spaces_bottom,
		       bufferlist.current()->text->cursor.par->FirstPhysicalPar()->added_space_bottom);
	 fl_set_button(fd_form_paragraph->check_noindent,
		       bufferlist.current()->text->cursor.par->FirstPhysicalPar()->noindent);
      }
      
      if (fd_form_paragraph->form_paragraph->visible) {
	      fl_raise_form(fd_form_paragraph->form_paragraph);
      } else
	fl_show_form(fd_form_paragraph->form_paragraph,
		     FL_PLACE_MOUSE | FL_FREE_SIZE,FL_FULLBORDER,
		     "Paragraph Layout");
}


void MenuLayoutDocument()
{
	LyXTextParameters *param;
	if (bufferlist.current()->text) {
		param = &bufferlist.current()->parameters;
	} else {
		param = &lyxrc.parameters;
	}
   fl_set_choice_text(fd_form_document->choice_class, 
		      lyxstyle.NameOfClass(param->textclass));
//   fl_set_choice_text(fd_form_document->choice_language, 
//		      param->language);
   combo_language->select_text(param->language);
    
   fl_set_choice_text(fd_form_document->choice_fonts, 
		      param->fonts);
   fl_set_choice_text(fd_form_document->choice_inputenc, 
		      param->inputenc);
   fl_set_choice_text(fd_form_document->choice_epsfig, 
		      param->epsfig);
   fl_set_choice(fd_form_document->choice_fontsize, 
		 param->fontsize - 9);
   fl_set_choice(fd_form_document->choice_papersize,
		 param->papersize + 1);
   fl_set_choice(fd_form_document->choice_pagestyle,
		 param->pagestyle + 1);
   fl_set_button(fd_form_document->radio_indent, 0);
   fl_set_button(fd_form_document->radio_skip, 0);
   
   if (param->paragraph_separation ==
       LYX_PARSEP_INDENT)
	   fl_set_button(fd_form_document->radio_indent, 1);
   else
	   fl_set_button(fd_form_document->radio_skip, 1);
   
   fl_set_button(fd_form_document->radio_portrait, 0);
   fl_set_button(fd_form_document->radio_landscape, 0);
   
   if (param->orientation == ORIENTATION_LANDSCAPE)
	   fl_set_button(fd_form_document->radio_landscape, 1);
   else
	   fl_set_button(fd_form_document->radio_portrait, 1);
   
   fl_set_button(fd_form_document->radio_sides_one, 0);
   fl_set_button(fd_form_document->radio_sides_two, 0);
   
   if (param->sides == 2)
	   fl_set_button(fd_form_document->radio_sides_two, 1);
   else
	   fl_set_button(fd_form_document->radio_sides_one, 1);
   
   fl_set_button(fd_form_document->radio_columns_one, 0);
   fl_set_button(fd_form_document->radio_columns_two, 0);
   
   if (param->columns == 2)
	   fl_set_button(fd_form_document->radio_columns_two, 1);
   else
	   fl_set_button(fd_form_document->radio_columns_one, 1);
   
   fl_set_slider_value(fd_form_document->slider_baselinestretch, 
		       param->baseline);
   fl_set_slider_value(fd_form_document->slider_secnumdepth, 
		       param->secnumdepth);
   fl_set_slider_value(fd_form_document->slider_tocdepth, 
		       param->tocdepth);
   if (bufferlist.current()->parameters.float_placement != NULL) {
     fl_set_input(fd_form_document->input_float_placement,
                param->float_placement);
   } else {
     fl_set_input(fd_form_document->input_float_placement, StringCopy(""));
   }
   fl_set_input(fd_form_document->input_extra,
		param->options);
   
   if (fd_form_document->form_document->visible) {
	   fl_raise_form(fd_form_document->form_document);
   } else
     fl_show_form(fd_form_document->form_document,
		  FL_PLACE_MOUSE | FL_FREE_SIZE,FL_FULLBORDER,
		  "Document Layout");
}


void MenuLayoutQuotes()
{
     if (bufferlist.current()->text){
       fl_set_choice(fd_form_quotes->choice_quotes_language,
		     bufferlist.current()->parameters.quotes_language + 1);
       fl_set_button(fd_form_quotes->radio_single, 0);
       fl_set_button(fd_form_quotes->radio_double, 0);
       
       if (bufferlist.current()->parameters.quotes_times == 1)
	 fl_set_button(fd_form_quotes->radio_single, 1);
       else
	 fl_set_button(fd_form_quotes->radio_double, 1);
     }
     if (fd_form_quotes->form_quotes->visible) {
	     fl_raise_form(fd_form_quotes->form_quotes);
     } else
       fl_show_form(fd_form_quotes->form_quotes,
		    FL_PLACE_MOUSE | FL_FREE_SIZE,FL_FULLBORDER,
		    "Quotes");
}


void MenuLayoutPreamble()
{
   if (bufferlist.current()->text &&
       bufferlist.current()->parameters.preamble){
      fl_set_input(fd_form_preamble->input_preamble,
		     bufferlist.current()->parameters.preamble);
   } else {
	   if (lyxrc.parameters.preamble)
		   fl_set_input(fd_form_preamble->input_preamble,
				lyxrc.parameters.preamble);
	   else
		   fl_set_input(fd_form_preamble->input_preamble, "");
   }

   if (fd_form_preamble->form_preamble->visible) {
	   fl_raise_form(fd_form_preamble->form_preamble);
   } else
     fl_show_form(fd_form_preamble->form_preamble,
		  FL_PLACE_MOUSE | FL_FREE_SIZE,FL_FULLBORDER,
		  "LaTeX Preamble");
}


/* only usable from special cb!!! */ 
void InsertLaTeXTable(const char* table)
{
  // check for table/list in tables
  if (bufferlist.current()->text->cursor.par->table){
    WriteAlert("Impossible Operation!", "Cannot insert table/list in table.",
		"Sorry.");
    return;
  }
   bufferlist.current()->text->SetCursorParUndo(); 
   bufferlist.current()->text->FreezeUndo();

  BeforeChange();
  Update(-2);
   bufferlist.current()->text->BreakParagraph();
   Update(-1);
   
   if (bufferlist.current()->text->cursor.par->Last()) {
      bufferlist.current()->text->CursorLeft();
      
      bufferlist.current()->text->BreakParagraph();
      Update(-1);
   }
   
   bufferlist.current()->text->SetLayout(lyxstyle.NumberOfLayout(bufferlist.current()->parameters.textclass, "Standard"));
   
   bufferlist.current()->text->SetParagraph(0, 0,
						0, 0,
						0, 0,
						0, 0,
						LYX_ALIGN_LAYOUT, 
						NULL,
						0);
   Update(-1);
   
   bufferlist.current()->text->current_font.latex = LYX_NO_LATEX;
   
   InsetLatexDel *new_inset = new InsetLatexDel(table);
   bufferlist.current()->text->InsertInset(new_inset);
   Update(-1);
   
   bufferlist.current()->text->CursorRight();
   bufferlist.current()->text->UnFreezeUndo();
}


/* callbacks added for LinuxDoc support (Pascal André) : 
 *   - marks and cross references TeX macros
 *   - url display macros
 *   - htmlurl macros
 */

/* inserts an inset (used for LinuxDoc SGML related callbacks) */
void InsertLatexDelInset(const char *macro)
{
  InsetLatexDel *new_inset = new InsetLatexDel(macro);
  bufferlist.current()->text->InsertInset(new_inset);
  Update(-1);
}


/* inserts a cross reference mark skeleton */ 
void CrossMarkCB()
{
  InsertLatexDelInset("\\label{");
  InsertLatexDelInset("}");
  bufferlist.current()->text->InsertChar(' ');
}


/* inserts a cross reference skeleton */ 
void CrossReferenceCB()
{
  InsertLatexDelInset("\\ref{");
  InsertLatexDelInset("}{");
  InsertLatexDelInset("}");
  bufferlist.current()->text->InsertChar(' ');
}


/* inserts an url skeleton */ 
void UrlCB()
{
  InsertLatexDelInset("\\url{");
  InsertLatexDelInset("}{");
  InsertLatexDelInset("}");
  bufferlist.current()->text->InsertChar(' ');
}


/* inserts an html url skeleton */ 
void HtmlUrlCB()
{
  InsertLatexDelInset("\\htmlurl{");
  InsertLatexDelInset("}{");
  InsertLatexDelInset("}");
  bufferlist.current()->text->InsertChar(' ');
}

/* end of LinuxDoc SGML special CB */

void NoteCB()
{
   InsetInfo *new_inset = new InsetInfo();
   char string[200];
   char * userName;
   userName = getenv("LOGNAME");
   if (userName == NULL)
      userName = getenv("USER");
   if (userName == NULL)
      userName = "unknown";
   sprintf(string, "%s %s\n", userName, (char*)date());
   new_inset->Set(string);
   bufferlist.current()->text->InsertInset(new_inset);
   Update(-1);
}


void MakeBufferMenu(int pup)
{
	bufferlist.makePup(pup);
}


void HandleBufferMenu(int choice)
{
	bufferlist.switchBuffer(choice);
	ResizeCurrentBufferPseudoExpose();
}


void OpenStuff()
{
   if (bufferlist.current()->text) {
     minibuffer.Set("Open/Close...");
      bufferlist.current()->screen->HideCursor();
      BeforeChange();
      Update(-2);
      bufferlist.current()->text->OpenStuff();
      Update(0);
   }
}

void ToggleFloat()
{
   if (bufferlist.current()->text) {
     minibuffer.Set("Open/Close...");
      bufferlist.current()->screen->HideCursor();
      BeforeChange();
      Update(-2);
      bufferlist.current()->text->ToggleFootnote();
      Update(0);
   }
}


void MenuUndo()
{
   if (bufferlist.current()->the_locking_inset) {
     minibuffer.Set("Undo not yet supported in math mode");
     return;
   }
   
   if (bufferlist.current()->text) {
     minibuffer.Set("Undo");
     bufferlist.current()->screen->HideCursor();
     BeforeChange();
     Update(-2);
     if (!bufferlist.current()->text->TextUndo())
       minibuffer.Set("No further undo information");
     else
       Update(-1);
   }
}


void MenuRedo()
{
   if (bufferlist.current()->the_locking_inset) {
     minibuffer.Set("Redo not yet supported in math mode");
     return;
   }    
   
   if (bufferlist.current()->text) {
     minibuffer.Set("Redo");
     bufferlist.current()->screen->HideCursor();
     BeforeChange();
     Update(-2);
     if (!bufferlist.current()->text->TextRedo())
       minibuffer.Set("No further redo information");
     else
       Update(-1);
   }
}


void HyphenationPoint()
{
   if (bufferlist.current()->text)  {
      bufferlist.current()->screen->HideCursor();
      Update(-2);
      InsetLatexDel *new_inset = new InsetLatexDel("\\-");
      bufferlist.current()->text->InsertInset(new_inset);
      Update(-1);
   }
}


void Newline()
{
   if (bufferlist.current()->text)  {
      bufferlist.current()->screen->HideCursor();
      Update(-2);
      bufferlist.current()->text->InsertChar(LYX_META_NEWLINE);
      Update(-1);
   }
}


void ProtectedBlank()
{
   if (bufferlist.current()->text)  {
      bufferlist.current()->screen->HideCursor();
      Update(-2);
      bufferlist.current()->text->InsertChar(LYX_META_PROTECTED_SEPARATOR);
      Update(-1);
   }
}


void HFill()
{
   if (bufferlist.current()->text)  {
      bufferlist.current()->screen->HideCursor();
      Update(-2);
      bufferlist.current()->text->InsertChar(LYX_META_HFILL);
      Update(-1);
   }
}


/* -------> These CB's use ToggleFree() as the (one and only?) font-changer. 
			They also show the current font state. */

static void ToggleAndShow(LyXFont*, const char* stylename);


void FontSizeCB(FL_OBJECT *, long data)
{
	LyXFont font = { LYX_NO_FONT_CHANGE, LYX_NO_FONT_CHANGE,
			 LYX_NO_FONT_CHANGE, LYX_NO_FONT_CHANGE,
			 LYX_NO_FONT_CHANGE, LYX_NO_FONT_CHANGE };
	
	if ( data < 0 ) data = 0;
	if ( data > 7 ) data = 7;
	font.size = data;
	ToggleAndShow( &font, "FontSize");	
}


void EmphCB(FL_OBJECT *, long)
{
	LyXFont font = { LYX_NO_FONT_CHANGE, LYX_NO_FONT_CHANGE,
			 LYX_NO_FONT_CHANGE, LYX_NO_FONT_CHANGE,
			 LYX_NO_FONT_CHANGE, LYX_NO_FONT_CHANGE };
	
	font.shape = LYX_ITALIC_SHAPE;
	ToggleAndShow( &font, "Emphasize" );	
}


void NounCB(FL_OBJECT *, long)
{
	LyXFont font = { LYX_NO_FONT_CHANGE, LYX_NO_FONT_CHANGE,
			 LYX_NO_FONT_CHANGE, LYX_NO_FONT_CHANGE,
			 LYX_NO_FONT_CHANGE, LYX_NO_FONT_CHANGE };
	
	font.shape = LYX_SMALLCAPS_SHAPE;
	ToggleAndShow( &font, "Noun" );	
}


void BoldCB(FL_OBJECT *, long)
{
	LyXFont font = { LYX_NO_FONT_CHANGE, LYX_NO_FONT_CHANGE,
			 LYX_NO_FONT_CHANGE, LYX_NO_FONT_CHANGE,
			 LYX_NO_FONT_CHANGE, LYX_NO_FONT_CHANGE };
	
	font.series = LYX_BOLD_SERIES;
	ToggleAndShow( &font, "Bold" );	
}


void UnderlineCB(FL_OBJECT *, long)
{
	LyXFont font = { LYX_NO_FONT_CHANGE, LYX_NO_FONT_CHANGE,
			 LYX_NO_FONT_CHANGE, LYX_NO_FONT_CHANGE,
			 LYX_NO_FONT_CHANGE, LYX_NO_FONT_CHANGE };
	
	font.bar = LYX_UNDER_BAR;
	ToggleAndShow( &font, "Underline" );	
}


void CodeCB(FL_OBJECT *, long)
{
	LyXFont font = { LYX_NO_FONT_CHANGE, LYX_NO_FONT_CHANGE,
			 LYX_NO_FONT_CHANGE, LYX_NO_FONT_CHANGE,
			 LYX_NO_FONT_CHANGE, LYX_NO_FONT_CHANGE };
	
	font.family = LYX_TYPEWRITER_FAMILY;
	ToggleAndShow( &font, "Code" );	
}


void SansCB(FL_OBJECT *, long)
{
	LyXFont font = { LYX_NO_FONT_CHANGE, LYX_NO_FONT_CHANGE,
			 LYX_NO_FONT_CHANGE, LYX_NO_FONT_CHANGE,
			 LYX_NO_FONT_CHANGE, LYX_NO_FONT_CHANGE };
	
	font.family = LYX_SANS_FAMILY;
	ToggleAndShow( &font, "Sans" );	
}

void RomanCB(FL_OBJECT *, long)
{
	LyXFont font = { LYX_NO_FONT_CHANGE, LYX_NO_FONT_CHANGE,
			 LYX_NO_FONT_CHANGE, LYX_NO_FONT_CHANGE,
			 LYX_NO_FONT_CHANGE, LYX_NO_FONT_CHANGE };
	
	font.family = LYX_ROMAN_FAMILY;
	ToggleAndShow( &font, "Sans" ); // Is this "sans" correct?	
}


void TexCB(FL_OBJECT *, long)
{
	LyXFont font = { LYX_NO_FONT_CHANGE, LYX_NO_FONT_CHANGE,
			 LYX_NO_FONT_CHANGE, LYX_NO_FONT_CHANGE,
			 LYX_NO_FONT_CHANGE, LYX_NO_FONT_CHANGE };
	
	font.latex = LYX_LATEX;
	ToggleAndShow( &font, "TeX" );	
}


void FormulaCB(FL_OBJECT *, long)
{
	LyXFont font = { LYX_NO_FONT_CHANGE, LYX_NO_FONT_CHANGE,
			 LYX_NO_FONT_CHANGE, LYX_NO_FONT_CHANGE,
			 LYX_NO_FONT_CHANGE, LYX_NO_FONT_CHANGE };
	
	font.latex = LYX_FORMULA_LATEX;
	ToggleAndShow( &font, "Math" );	
}


void StyleResetCB(FL_OBJECT *, long)
{
	LyXFont font = { LYX_NO_FONT_CHANGE, LYX_NO_FONT_CHANGE,
			 LYX_NO_FONT_CHANGE, LYX_NO_FONT_CHANGE,
			 LYX_NO_FONT_CHANGE, LYX_NO_FONT_CHANGE };
  
	font.family = LYX_LAYOUT_DEFAULT;
	font.series = LYX_LAYOUT_DEFAULT;
	font.shape  = LYX_LAYOUT_DEFAULT;
	font.bar    = LYX_LAYOUT_DEFAULT;
	font.latex  = LYX_LAYOUT_DEFAULT;
	font.size   = LYX_LAYOUT_DEFAULT;
	ToggleAndShow( &font, "Reset" );	
}


/* -------> Shows the current font state by printing a message. In the
 * future perhaps we could try to implement a callback to the button-bar.
 * That is, `light' the bold button when the font is currently bold, etc.
 */
void FontStateShowCB( FL_OBJECT *, long)
{
	char	 buf[120];
	char	 *sizeNaVc[]   = { "tiny ", "small ", "", "large ",
				   "larger ", "largest ", "huge ", "giant " };
	char	 *familyNaVc[] = { "roman", "sans-serif", "typewriter" };
	char	 *seriesNaVc[] = { "", "+ bold " };
	char	 *shapeNaVc[]  = { "", "+ emphasize ", " + noun " };
	char     *latexNaVc[]  = { "", "+ TeX ", "+ Math " };
	char	 *barNaVc[]    = { "", "+ underbar" };
    
	if ( bufferlist.current()->text ) { 
		LyXFont font = bufferlist.current()->text->real_current_font;
		sprintf( buf, "Font: %s%s %s%s%s%s",
				 sizeNaVc[font.size],
				 familyNaVc[font.family],
				 seriesNaVc[font.series],
				 shapeNaVc[font.shape],
				 barNaVc[font.bar],
				 latexNaVc[font.latex] );
		minibuffer.Set( buf);
	}
}


/* -------> Does the actual toggle job of the XxxCB() calls above.
 * Also shows the current font state.
 */
static void ToggleAndShow( LyXFont* font, const char* stylename)
{
	if (bufferlist.current()->text) { 
		bufferlist.current()->screen->HideCursor();
		Update(-2);
 		bufferlist.current()->text->ToggleFree( *font, stylename );
		Update(1);
	}
 	// removed since it overrides the ToggleFree Message about the style
 	// Since Styles are more "High Level" than raw fonts I think the user
 	// prefers it like this               Matthias
 	// FontStateShowCB( 0, 0 );
}


void MarginCB(FL_OBJECT *, long)
{
   if (bufferlist.current()->text) {
      minibuffer.Set("Inserting margin note...");
      bufferlist.current()->screen->HideCursor();
      Update(-2);
      bufferlist.current()->text->InsertFootnoteEnvironment(LYX_MARGIN);
      Update(1);
   }
}


void FigureCB(FL_OBJECT *, long)
{
   if (fd_form_figure->form_figure->visible) {
	   fl_raise_form(fd_form_figure->form_figure);
   } else
     fl_show_form(fd_form_figure->form_figure,
		  FL_PLACE_MOUSE, FL_FULLBORDER,
		  "Figure");
}


void TableCB(FL_OBJECT *, long)
{
   if (fd_form_table->form_table->visible) {
	   fl_raise_form(fd_form_table->form_table);
   } else
     fl_show_form(fd_form_table->form_table,
		  FL_PLACE_MOUSE | FL_FREE_SIZE, FL_FULLBORDER,
		  "Table");
}


void CopyCB()
{
  if (bufferlist.current()->text) {
     bufferlist.current()->text->CopySelection();
      minibuffer.Set("Copy");
   }
}


void CutCB()
{
   if (bufferlist.current()->text) {
      bufferlist.current()->screen->HideCursor();
      Update(-2);
      bufferlist.current()->text->CutSelection();
      Update(1);
      minibuffer.Set("Cut");
   }
}


void PasteCB()
{
   if (bufferlist.current()->text) {
      minibuffer.Set("Paste");
      bufferlist.current()->screen->HideCursor();
      /* clear the selection */ 
      bufferlist.current()->screen->ToggleSelection();
      bufferlist.current()->text->ClearSelection();
      Update(-2);
      
      /* paste */ 
      bufferlist.current()->text->PasteSelection();
      Update(1);
   }
}


void MeltCB(FL_OBJECT *, long)
{
   if (bufferlist.current()->text) {
      minibuffer.Set("Melt");
      bufferlist.current()->screen->HideCursor();
      BeforeChange();
      Update(-2);
      bufferlist.current()->text->MeltFootnoteEnvironment();
      Update(1);
   }
}


void DepthCB(FL_OBJECT *ob, long decInc)
{
   int button = 1;

   /* When decInc != 0, fake a mouse button. This allows us to
      implement depth-plus and depth-min commands. RVDK_PATCH_5. */
   /* check out wether ob is defined, too (Matthias) */ 
   if ( decInc < 0 )     button = 0;
   else if (!decInc && ob) {
     button = fl_get_button_numb(ob);
   }
  
   if (bufferlist.current()->text) {
      bufferlist.current()->screen->HideCursor();
      Update(-2);
      if (button == 1)
      	 bufferlist.current()->text->IncDepth();
      else
      	 bufferlist.current()->text->DecDepth();
      Update(1);
      minibuffer.Set("Changed environment depth"
		    " (in possible range, maybe not)");
   }
}


void FreeCB(FL_OBJECT *, long)
{
  minibuffer.Set("Toggle user style");

  LyXFont font = { LYX_NO_FONT_CHANGE, LYX_NO_FONT_CHANGE,
		   LYX_NO_FONT_CHANGE, LYX_NO_FONT_CHANGE,
		   LYX_NO_FONT_CHANGE, LYX_NO_FONT_CHANGE };
  
   int pos;
  
  pos = fl_get_choice(fd_form_character->choice_family);
  if (pos > 1) font.family = pos - 2;
  
  pos = fl_get_choice(fd_form_character->choice_series);
  if (pos > 1) font.series = pos - 2;
  
  pos = fl_get_choice(fd_form_character->choice_shape);
  if (pos > 1) font.shape = pos - 2;

  pos = fl_get_choice(fd_form_character->choice_bar);
  if (pos > 1) font.bar = pos - 2;
  
  pos = fl_get_choice(fd_form_character->choice_size);
  if (pos > 1) font.size = pos - 2; 
  // this is no more true! Yet tiny is available but without VISIBLE smallcaps
                                    /* heres a -1 because of the
				     * unaccesible tiny font, that I need
				     * for smallcaps in small font */
  
  if (bufferlist.current()->text) { 
     bufferlist.current()->text->ToggleFree(font, "User");
      Update(1);
    }
}


/* callbacks for form form_title */
void TimerCB(FL_OBJECT *, long)
{
   // only if the form still exists
   if (fd_form_title->form_title != NULL) {

      fl_hide_form(fd_form_title->form_title);
      fl_free_form(fd_form_title->form_title);
      fd_form_title->form_title = NULL;
   }
   // else fprintf(stderr,"TimerCB: title form already deleted!\n");   
}


extern void checkchildren();


void UpdateTimerCB(FL_OBJECT *, long)
{
   if (!bufferlist.current()->screen || !updatetimer)
     return;

   bufferlist.current()->screen->HideCursor();
   Update(-2);
   /* this update can happen, even when the work area has lost
    * the focus. So supress the cursor in that case */ 
   updatetimer = 0;
   // we will also use this routine for clean-up in case some children
   // are still waiting to be terminated
   checkchildren();
}


void AutosaveTimerCB(FL_OBJECT *, long)
{
   AutoSave();
}


/* callbacks for form form_paragraph */
void ParagraphApplyCB(FL_OBJECT *, long)
{
   if (!bufferlist.current()->text)
     return;
   
   char line_top, line_bottom;
   char pagebreak_top, pagebreak_bottom;
   float space_top, space_bottom;
   char fill_top, fill_bottom;
   char align;
   const char* labelwidthstring;
   char noindent;
   
   line_top = fl_get_button(fd_form_paragraph->check_lines_top);
   line_bottom = fl_get_button(fd_form_paragraph->check_lines_bottom);
   pagebreak_top = fl_get_button(fd_form_paragraph->check_pagebreaks_top);
   pagebreak_bottom = fl_get_button(fd_form_paragraph->check_pagebreaks_bottom);
   space_top = fl_get_slider_value(fd_form_paragraph->slider_spaces_top);
   space_bottom = fl_get_slider_value(fd_form_paragraph->slider_spaces_bottom);
   fill_top = fl_get_button(fd_form_paragraph->check_fill_top);
   fill_bottom = fl_get_button(fd_form_paragraph->check_fill_bottom);
   
   if (fl_get_button(fd_form_paragraph->radio_align_left))
     align = LYX_ALIGN_LEFT;
   else if (fl_get_button(fd_form_paragraph->radio_align_right))
     align = LYX_ALIGN_RIGHT;
   else if (fl_get_button(fd_form_paragraph->radio_align_center))
     align = LYX_ALIGN_CENTER;
   else 
     align = LYX_ALIGN_BLOCK;
   
   labelwidthstring = fl_get_input(fd_form_paragraph->input_labelwidth);
   noindent = fl_get_button(fd_form_paragraph->check_noindent);
   
   bufferlist.current()->text->SetParagraph(line_top, line_bottom,
				      pagebreak_top, pagebreak_bottom,
				      space_top, space_bottom,
				      fill_top, fill_bottom,
				      align, 
				      labelwidthstring,
				      noindent);
   Update(1);
   minibuffer.Set("Paragraph layout set");
}


void ParagraphCancelCB(FL_OBJECT *, long)
{
   fl_hide_form(fd_form_paragraph->form_paragraph);
}


void ParagraphOKCB(FL_OBJECT *ob, long data)
{
   ParagraphApplyCB(ob, data);
   ParagraphCancelCB(ob, data);
}


/* callbacks for form form_search */
void SearchCancelCB(FL_OBJECT *, long)
{
   fl_hide_form(fd_form_search->form_search);
}


void SearchReplaceCB(FL_OBJECT *, long)
{
   if (!bufferlist.current()->screen)
     return;
   if (!bufferlist.current()->text->selection){
     LyXBell();
     return;
   }
   char* replacestring = (char *) fl_get_input(fd_form_search->input_replace);
   bufferlist.current()->screen->HideCursor();
   Update(-2);
   /* clear the selection (if there is any) */ 
   bufferlist.current()->screen->ToggleSelection();
   bufferlist.current()->text->ReplaceSelectionWithString(replacestring);
   
   bufferlist.current()->text->SetSelectionOverString(replacestring);
   Update(1);
}


void SearchForwardCB(FL_OBJECT *, long)
{
   if (!bufferlist.current()->screen)
     return;
   
   bufferlist.current()->screen->HideCursor();
   Update(-2);
   char* searchstring = (char*) fl_get_input(fd_form_search->input_search);
   
   if (bufferlist.current()->text->selection) 
     bufferlist.current()->text->cursor =
	   bufferlist.current()->text->sel_end_cursor;
   
   if (!searchstring[0] ||
       bufferlist.current()->text->SearchForward(searchstring)) {
	   Update(-2);
	   /* clear the selection (if there is any) */ 
	   bufferlist.current()->screen->ToggleSelection();
	   bufferlist.current()->text->ClearSelection();
	   /* set the new selection */
	   bufferlist.current()->text->SetSelectionOverString(searchstring);
	   bufferlist.current()->screen->ToggleSelection();
   } else {
	   LyXBell();
   }
   
   if (work_area_active)
     if (fd_form_main->work_area->focus)
       bufferlist.current()->screen->ShowCursor();
}


void SearchBackwardCB(FL_OBJECT *, long)
{
   if (!bufferlist.current()->screen)
     return;
   
   char* searchstring = (char *) fl_get_input(fd_form_search->input_search);
   
   bufferlist.current()->screen->HideCursor();
   Update(-2);

   if (bufferlist.current()->text->selection) 
     bufferlist.current()->text->cursor =
	   bufferlist.current()->text->sel_start_cursor;

   if (!searchstring[0] ||
       bufferlist.current()->text->SearchBackward(searchstring)) {
	   Update(-2);
	   /* clear the selection (if there is any) */ 
	   bufferlist.current()->screen->ToggleSelection();
	   bufferlist.current()->text->ClearSelection();
	   /* set the new selection */
	   bufferlist.current()->text->SetSelectionOverString(searchstring);
	   bufferlist.current()->screen->ToggleSelection();
   } else {
	   LyXBell();
   }
   
   if (work_area_active)
     if (fd_form_main->work_area->focus)
       bufferlist.current()->screen->ShowCursor();
}


/* callbacks for form form_character */

void CharacterApplyCB(FL_OBJECT *, long)
{
  LyXFont font = { LYX_NO_FONT_CHANGE, LYX_NO_FONT_CHANGE,
		   LYX_NO_FONT_CHANGE, LYX_NO_FONT_CHANGE,
		   LYX_NO_FONT_CHANGE, LYX_NO_FONT_CHANGE };
  
   int pos;
  
  pos = fl_get_choice(fd_form_character->choice_family);
  if (pos > 1) font.family = pos - 2;
  
  pos = fl_get_choice(fd_form_character->choice_series);
  if (pos > 1) font.series = pos - 2;
  
  pos = fl_get_choice(fd_form_character->choice_shape);
  if (pos > 1) font.shape = pos - 2;
  
  pos = fl_get_choice(fd_form_character->choice_bar);
  if (pos > 1) font.bar = pos - 2;
  
  pos = fl_get_choice(fd_form_character->choice_size);
  if (pos > 1) font.size = pos - 2; 
  // this is no more true! Yet tiny is available but without VISIBLE smallcaps
                                     /* heres a -1 because of the
				     * unaccesible tiny font, that I need
				     * for smallcaps in small font */
  
   if (bufferlist.current()->text) { 
      bufferlist.current()->text->SetFont(font);
      Update(1);
      minibuffer.Set("Character layout set");
   }
}


void CharacterCancelCB(FL_OBJECT *, long)
{
   fl_hide_form(fd_form_character->form_character);
}


void CharacterOKCB(FL_OBJECT *ob, long data)
{
   CharacterApplyCB(ob,data);
   CharacterCancelCB(ob,data);
}


/* callbacks for form form_document */

void ChoiceClassCB(FL_OBJECT *ob, long)
{
   ProhibitInput();
   if (fl_show_question("Should I set the defaults of textclass",
			fl_get_choice_text(ob),
			"for Columns, Sides, Pagestyle and Extra Options?")) {
      
      fl_set_choice(fd_form_document->choice_pagestyle, 
		    lyxstyle.TextClass(fl_get_choice(ob) - 1)->pagestyle + 1);
      fl_set_button(fd_form_document->radio_sides_one, 0);
      fl_set_button(fd_form_document->radio_sides_two, 0);

      if (lyxstyle.TextClass(fl_get_choice(ob) - 1)->sides == 2)
      	 fl_set_button(fd_form_document->radio_sides_two, 1);
      else
      	 fl_set_button(fd_form_document->radio_sides_one, 1);
      
      fl_set_button(fd_form_document->radio_columns_one, 0);
      fl_set_button(fd_form_document->radio_columns_two, 0);

      if (lyxstyle.TextClass(fl_get_choice(ob) - 1)->columns == 2)
	   fl_set_button(fd_form_document->radio_columns_two, 1);
      else
	   fl_set_button(fd_form_document->radio_columns_one, 1);

      fl_set_input(fd_form_document->input_extra,
		   lyxstyle.TextClass(fl_get_choice(ob) - 1)->options);
   }
   AllowInput();
}


void DocumentApplyCB(FL_OBJECT *, long)
{
   char redo = 0;
   delete[] bufferlist.current()->parameters.language;
   delete[] bufferlist.current()->parameters.fonts;
   delete[] bufferlist.current()->parameters.inputenc;
   bufferlist.current()->parameters.language =
	   StringCopy(combo_language->getline());
//	   StringCopy(fl_get_choice_text(fd_form_document->choice_language));

   /* this shouldn't be done automatically IMO. For example I write german
    * documents with an american keyboard very often. Matthias */
   
   /* ChangeKeymap(bufferlist.current()->parameters.language, TRUE, FALSE,
	fl_get_choice(fd_form_document->choice_language)); */
   bufferlist.current()->parameters.fonts =
	   StringCopy(fl_get_choice_text(fd_form_document->choice_fonts));
   bufferlist.current()->parameters.inputenc =
	   StringCopy(fl_get_choice_text(fd_form_document->choice_inputenc));
   bufferlist.current()->parameters.fontsize =
	   9 + fl_get_choice(fd_form_document->choice_fontsize);
   bufferlist.current()->parameters.papersize =
	   -1 + fl_get_choice(fd_form_document->choice_papersize);
   bufferlist.current()->parameters.pagestyle =
	   -1 + fl_get_choice(fd_form_document->choice_pagestyle);
   bufferlist.current()->parameters.epsfig =
	   StringCopy(fl_get_choice_text(fd_form_document->choice_epsfig));
   
   if (!bufferlist.current()->text)
     return;

   char new_class = fl_get_choice(fd_form_document->choice_class) - 1;
   if (bufferlist.current()->parameters.textclass != new_class) {
      redo = 1;
      minibuffer.Set("Converting document to new textclass...");
      int ret = bufferlist.current()->
	      text->
	      SwitchLayoutsBetweenClasses(bufferlist.current()->
	                                    parameters.textclass,
	                                  new_class,
	                                  bufferlist.current()->
	                                    parameters.paragraph);
      
      if (ret){
	 char *s = new char[50];
	 sprintf(s, "%d paragraph(s) couldn't be converted", ret);
	 WriteAlert("Conversion Errors!",s,"into choosen textclass");
	 delete[] s;
      }
      
      bufferlist.current()->parameters.textclass = new_class;
   }

   char tmpsep = bufferlist.current()->parameters.paragraph_separation;
   if (fl_get_button(fd_form_document->radio_indent))
     bufferlist.current()->parameters.paragraph_separation = LYX_PARSEP_INDENT;
   else
      bufferlist.current()->parameters.paragraph_separation = LYX_PARSEP_SKIP;
   if (tmpsep != bufferlist.current()->parameters.paragraph_separation)
      redo = 1;
   
   if (fl_get_button(fd_form_document->radio_landscape))
      bufferlist.current()->parameters.orientation = ORIENTATION_LANDSCAPE;
   else
      bufferlist.current()->parameters.orientation = ORIENTATION_PORTRAIT;
   if (fl_get_button(fd_form_document->radio_columns_two))
      bufferlist.current()->parameters.columns = 2;
   else
      bufferlist.current()->parameters.columns = 1;
   if (fl_get_button(fd_form_document->radio_sides_two))
      bufferlist.current()->parameters.sides = 2;
   else
      bufferlist.current()->parameters.sides = 1;

   if (bufferlist.current()->parameters.baseline != fl_get_slider_value(fd_form_document->slider_baselinestretch))
      redo = 1;
   bufferlist.current()->parameters.baseline = fl_get_slider_value(fd_form_document->slider_baselinestretch);

   
   double tmpdouble =
	   fl_get_slider_value(fd_form_document->slider_secnumdepth);
   signed char tmpchar = 0;
   
   if (tmpdouble >= 0)
	   tmpchar = (signed char) (tmpdouble + 0.5);
   else
	   tmpchar = (signed char) (tmpdouble - 0.5);
      
   
   if (bufferlist.current()->parameters.secnumdepth != tmpchar)
      redo = 1;
   
   bufferlist.current()->parameters.secnumdepth = tmpchar;
   
   tmpdouble = fl_get_slider_value(fd_form_document->slider_tocdepth);
   
   if (tmpdouble >= 0)
      tmpchar = (signed char) (tmpdouble + 0.5);
   else
      tmpchar = (signed char) (tmpdouble - 0.5);
   
   bufferlist.current()->parameters.tocdepth = tmpchar;

   if (bufferlist.current()->parameters.float_placement)
      delete[] bufferlist.current()->parameters.float_placement;
   bufferlist.current()->parameters.float_placement = StringCopy(fl_get_input(fd_form_document->input_float_placement));

   // More checking should be done to ensure the string doesn't have spaces
   // or illegal placement characters in it. (thornley)
   if (bufferlist.current()->parameters.float_placement[0] == '\0') {
      delete[] bufferlist.current()->parameters.float_placement;
      bufferlist.current()->parameters.float_placement = NULL;
   }

//Move this here dabn100      
//   bufferlist.current()->parameters.quotes_language = fl_get_choice(fd_form_document->choice_quotes_language) - 1;
//   
//   if (fl_get_button(fd_form_document->radio_single))   
//     bufferlist.current()->parameters.quotes_times = 1;
//   else
//     bufferlist.current()->parameters.quotes_times = 2;
//we probably don't want to redo automatically as a result
   if (redo)
      RedoCurrentBuffer();
   
   minibuffer.Set("Document layout set");
   //bufferlist.current()->lyx_current = false;
   //bufferlist.current()->dvi_current = false;
   //bufferlist.current()->bak_current = false;
   bufferlist.current()->markDirty();

   if (bufferlist.current()->parameters.options)
      delete[] bufferlist.current()->parameters.options;
   bufferlist.current()->parameters.options = StringCopy(fl_get_input(fd_form_document->input_extra));
   
}


void DocumentCancelCB(FL_OBJECT *, long)
{
   fl_hide_form(fd_form_document->form_document);
}


void DocumentOKCB(FL_OBJECT *ob, long data)
{
   DocumentCancelCB(ob,data);
   DocumentApplyCB(ob,data);
}


void GotoError()
{
   if (!bufferlist.current()->screen)
     return;
   
   bufferlist.current()->screen->HideCursor();
   BeforeChange();
   Update(-2);
   LyXCursor tmp;
   
   if (!bufferlist.current()->text->GotoNextError()) {
      if (bufferlist.current()->text->cursor.pos 
	  || bufferlist.current()->text->cursor.par !=
	     bufferlist.current()->text->FirstParagraph())
      {
	      tmp = bufferlist.current()->text->cursor;
	      bufferlist.current()->text->cursor.par =
		      bufferlist.current()->text->FirstParagraph();
	      bufferlist.current()->text->cursor.pos = 0;
	      if (!bufferlist.current()->text->GotoNextError()) {
		      bufferlist.current()->text->cursor = tmp;
		      minibuffer.Set("No more errors");
		      LyXBell();
	      }
      } else {
	      minibuffer.Set("No more errors");
	      LyXBell();
      }
   }
   Update(0);
   bufferlist.current()->text->sel_cursor =
	   bufferlist.current()->text->cursor;
}


void GotoNote()
{
   if (!bufferlist.current()->screen)
     return;
   
   bufferlist.current()->screen->HideCursor();
   BeforeChange();
   Update(-2);
   LyXCursor tmp;
   
   if (!bufferlist.current()->text->GotoNextNote()) {
      if (bufferlist.current()->text->cursor.pos 
	  || bufferlist.current()->text->cursor.par !=
	  bufferlist.current()->text->FirstParagraph())
      {
	      tmp = bufferlist.current()->text->cursor;
	      bufferlist.current()->text->cursor.par =
		      bufferlist.current()->text->FirstParagraph();
	      bufferlist.current()->text->cursor.pos = 0;
	      if (!bufferlist.current()->text->GotoNextNote()) {
		      bufferlist.current()->text->cursor = tmp;
		      minibuffer.Set("No more notes");
		      LyXBell();
	      }
      } else {
	      minibuffer.Set("No more notes");
	      LyXBell();
      }
   }
   Update(0);
   bufferlist.current()->text->sel_cursor =
	   bufferlist.current()->text->cursor;
}


void InsertCorrectQuote()
{
   Inset *new_inset;
   char *s = new char[4];

   switch (bufferlist.current()->parameters.quotes_language) {
    case GERMAN:
      s[0]='g';
      break;
    case FRENCH:
      s[0]='f';
      break;
    default:
      s[0]='e';
      break;
   }
   
   
   /* first decide wether left or right */ 
   
   
   char c;
   if  (bufferlist.current()->text->cursor.pos )
     c = bufferlist.current()->text->cursor.par->GetChar(bufferlist.current()->text->cursor.pos -1);
   else c = ' ';
   
   if (c != ' ' &&
       c != '(' &&
       c != '{' &&
       c != '[' &&
       c != '-' &&
       c != ':' &&
       c != LYX_META_HFILL &&
       c != LYX_META_PROTECTED_SEPARATOR &&
       c != LYX_META_NEWLINE) 
     s[1]='r';  /* right quote */
   else
     s[1]='l';     /* left quote */ 
   
   
   if (bufferlist.current()->parameters.quotes_times == 1)
     s[2]='s';			       /* single */
   else
     s[2]='d';			       /* double */
   
   s[3]='\0';
   
   new_inset = new InsetQuotes(s);
   
   bufferlist.current()->text->InsertInset(new_inset);
   
}


/* callbacks for form form_quotes */

void QuotesApplyCB(FL_OBJECT *, long)
{
	if (bufferlist.current()->text) {
		minibuffer.Set("Quotes type set");
		bufferlist.current()->parameters.quotes_language =
			fl_get_choice(fd_form_quotes->choice_quotes_language) - 1;
   
		if (fl_get_button(fd_form_quotes->radio_single))   
			bufferlist.current()->parameters.quotes_times = 1;
		else
			bufferlist.current()->parameters.quotes_times = 2;
	}
}


void QuotesCancelCB(FL_OBJECT *, long)
{
  fl_hide_form(fd_form_quotes->form_quotes);
}


void QuotesOKCB(FL_OBJECT *ob, long data)
{
  QuotesApplyCB(ob, data);
  QuotesCancelCB(ob, data);
}



/* callbacks for form form_preamble */

void PreambleCancelCB(FL_OBJECT *, long)
{
  fl_hide_form(fd_form_preamble->form_preamble);
}


void PreambleApplyCB(FL_OBJECT *, long)
{
   if (bufferlist.current()->text) {
      if (bufferlist.current()->parameters.preamble)
      	 delete[] bufferlist.current()->parameters.preamble;
      bufferlist.current()->parameters.preamble =
	      StringCopy(fl_get_input(fd_form_preamble->input_preamble));
      //bufferlist.current()->lyx_current = false;
      //bufferlist.current()->bak_current = false;
      //bufferlist.current()->dvi_current = false;
      bufferlist.current()->markDirty();
      minibuffer.Set("LaTeX preamble set");
   }
}

   
void PreambleOKCB(FL_OBJECT *ob, long data)
{
  PreambleApplyCB(ob, data);
  PreambleCancelCB(ob, data);
}


/* callbacks for form form_table */

void TableApplyCB(FL_OBJECT *, long)
{
   int xsize,ysize;
   if (!bufferlist.current()->screen)
     return;
   
   // check for tables in tables
   if (bufferlist.current()->text->cursor.par->table){
     WriteAlert("Impossible Operation!", "Cannot insert table in table.",
 		"Sorry.");
     return;
   }
 
   minibuffer.Set("Inserting table...");

   ysize = (int)(fl_get_slider_value(fd_form_table->slider_columns) + 0.5);
   xsize = (int)(fl_get_slider_value(fd_form_table->slider_rows) + 0.5);
   
   
   bufferlist.current()->screen->HideCursor();
   BeforeChange();
   Update(-2);
   
   int i;
   
   bufferlist.current()->text->SetCursorParUndo(); 
   bufferlist.current()->text->FreezeUndo();

   bufferlist.current()->text->BreakParagraph();
   Update(-1);
   
   if (bufferlist.current()->text->cursor.par->Last()) {
      bufferlist.current()->text->CursorLeft();
      
      bufferlist.current()->text->BreakParagraph();
      Update(-1);
   }
   
   bufferlist.current()->text->current_font.latex = LYX_NO_LATEX;
   //if (!fl_get_button(fd_form_table->check_latex)){
     // insert the new wysiwy table
     bufferlist.current()->text->SetLayout(0); // standard layout
     if (bufferlist.current()->text->cursor.par->footnoteflag ==
	 LYX_NO_FOOTNOTE) {
       bufferlist.current()->
	 text->SetParagraph(0, 0,
			    0, 0,
			    0.3 * bufferlist.current()->
			    parameters.baseline,
			    0.3 * bufferlist.current()->
			    parameters.baseline,
			    0, 0,
			    LYX_ALIGN_CENTER,
			    NULL,
			    0);
     }
     else
       bufferlist.current()->text->SetParagraph(0, 0,
						0, 0,
						0, 0,
						0, 0,
						LYX_ALIGN_CENTER, 
						NULL,
						0);

     bufferlist.current()->text->cursor.par->table = new LyXTable(xsize, ysize);
     for (i=0; i<xsize * ysize - 1; i++)
       bufferlist.current()->text->cursor.par->InsertChar(0,LYX_META_NEWLINE);
     bufferlist.current()->text->RedoParagraph();
   
   bufferlist.current()->text->UnFreezeUndo();
     
   Update(1);
   minibuffer.Set("Table inserted");
}


void TableCancelCB(FL_OBJECT *, long)
{
   fl_hide_form(fd_form_table->form_table);
}


void TableOKCB(FL_OBJECT *ob, long data)
{
   TableApplyCB(ob,data);
   TableCancelCB(ob,data);
}


/* callbacks for form form_print */

void PrintCancelCB(FL_OBJECT *, long)
{
   fl_hide_form(fd_form_print->form_print);
}


void PrintApplyCB(FL_OBJECT *, long)
{
   if (!bufferlist.current()->text)
      return;

   int i;

   char* pageflag = "";
   if (fl_get_button(fd_form_print->radio_even_pages))
       pageflag = lyxrc.print_evenpage_flag;
   else if (fl_get_button(fd_form_print->radio_odd_pages))
       pageflag = lyxrc.print_oddpage_flag;
   
   char* reverseflag = "";
   if (fl_get_button(fd_form_print->radio_order_reverse))
      reverseflag = lyxrc.print_reverse_flag;
   
   char* orientationflag = "";
   if (bufferlist.current()->parameters.orientation == ORIENTATION_LANDSCAPE)
      orientationflag = lyxrc.print_landscape_flag;
   
   const char* ps_file = fl_get_input(fd_form_print->input_file);
   
   i = strlen (ps_file);

   char *command = new char[i+100]; 
   
   const char* printer = fl_get_input(fd_form_print->input_printer);
   
   if (printer) {
      if (lyxrc.printer)
      	 delete[] lyxrc.printer;
      lyxrc.printer = StringCopy(printer);
   }
   
   if (fl_get_button(fd_form_print->radio_file)){
      char* buf1 = NameToPath (NULL, bufferlist.current()->filename);
      char* abs_ps_file =  MakeAbsPath(NULL, ps_file, buf1);
      sprintf(command, "%s %s %s %s %s %s \"%s\"", lyxrc.print_command, 
             pageflag, reverseflag, orientationflag, lyxrc.print_extra_options, 
             lyxrc.print_to_file, abs_ps_file);
      delete [] buf1;
      delete [] abs_ps_file;
      }
   else if (*lyxrc.print_spool_cmd) 
      sprintf(command, "%s %s %s %s %s %s \"%s\"", lyxrc.print_command, 
             pageflag, reverseflag, orientationflag, lyxrc.print_extra_options, 
             lyxrc.print_to_file, ps_file);
   else {
      while (printer[0] == ' ')
      	 printer++;
      if (printer[0])
      	 sprintf(command, "%s %s %s %s %s %s%s", lyxrc.print_command, 
                 pageflag, reverseflag, orientationflag,
		 lyxrc.print_extra_options,
                 lyxrc.print_to_printer, printer);
      else
      	 sprintf(command, "%s %s %s %s %s", lyxrc.print_command, pageflag, 
                  reverseflag, orientationflag, 
                  lyxrc.print_extra_options);
   }
   fprintf (stderr, "command: %s\n", command);
   //RunScript(0, command);
   if (*lyxrc.print_spool_cmd) {
	   RunScript(4, command);
      while (printer[0] == ' ')
      	 printer++;
      if (printer[0])
      	 sprintf(command, "%s %s%s %s ", lyxrc.print_spool_cmd, 
                 lyxrc.print_to_printer, printer, ps_file);
      else
      	 sprintf(command, "%s %s ", lyxrc.print_spool_cmd, ps_file);

      RunScript(3, command);
   } else
	   RunScript(0, command);
   delete[] command;
}


void PrintOKCB(FL_OBJECT *ob, long data)
{
   PrintCancelCB(ob, data);  
   PrintApplyCB(ob,data);
}


/* callbacks for form form_figure */

void FigureApplyCB(FL_OBJECT *, long)
{
   if (bufferlist.current()->text) {
      minibuffer.Set("Inserting figure...");
      if (fl_get_button(fd_form_figure->radio_inline)
	  || bufferlist.current()->text->cursor.par->table) {
	  bufferlist.current()->text->InsertInset(new InsetFig(100, 20));
	  Update(-1);
          minibuffer.Set("Figure inserted");
	  return;
      }
      bufferlist.current()->screen->HideCursor();
      Update(-2);
      BeforeChange();
      
      bufferlist.current()->text->SetCursorParUndo(); 
      bufferlist.current()->text->FreezeUndo();

      bufferlist.current()->text->BreakParagraph();
      Update(-1);
      
      if (bufferlist.current()->text->cursor.par->Last()) {
	 bufferlist.current()->text->CursorLeft();
	 
	 bufferlist.current()->text->BreakParagraph();
	 Update(-1);
      }
      
      bufferlist.current()->text->SetLayout(lyxstyle.NumberOfLayout(bufferlist.current()->parameters.textclass, "Standard"));
      
      if (bufferlist.current()->text->cursor.par->footnoteflag ==
          LYX_NO_FOOTNOTE) {
	      bufferlist.current()->text->
		      SetParagraph(0, 0,
				   0, 0,
				   0.3 * bufferlist.current()->
				     parameters.baseline,
				   0.3 * bufferlist.current()->
				     parameters.baseline,
				   0, 0,
				   LYX_ALIGN_CENTER, 
				   NULL,
				   0);
      }
      else
	      bufferlist.current()->text->SetParagraph(0, 0,
						       0, 0,
						       0, 0,
						       0, 0,
						       LYX_ALIGN_CENTER, 
						       NULL,
						       0);
      
      Update(-1);
      
      Inset *new_inset = NULL;
      
      if (fl_get_button(fd_form_figure->radio_latex)) {
	bufferlist.current()->text->current_font.latex = LYX_LATEX;
	 new_inset = new InsetLatex("\\input ");
	 bufferlist.current()->text->InsertInset(new_inset);
      }
      else {
	 new_inset = new InsetFig(100, 100);
	 bufferlist.current()->text->InsertInset(new_inset);
      }
      
      Update(0);
      minibuffer.Set("Figure inserted");
      bufferlist.current()->text->UnFreezeUndo();
   }

}

   
void FigureCancelCB(FL_OBJECT *, long)
{
   fl_hide_form(fd_form_figure->form_figure);
}


void FigureOKCB(FL_OBJECT *ob, long data)
{
   FigureApplyCB(ob,data);
   FigureCancelCB(ob,data);
}

// some other scheme must be thought of, this breaks the type checking of gcc
//void error_handler(int err_sig,...) //... added to please Sun's CC (JMarc)
void error_handler(int err_sig)
{
   switch (err_sig) {
    case SIGHUP:
      fprintf(stderr, "\nlyx: SIGHUP signal trapped\n");
      break;
   case SIGINT:
	   // no comments
	   break;
    case SIGFPE:
      fprintf(stderr, "\nlyx: SIGFPE signal trapped\n");
	break;
    case SIGSEGV:
	fprintf(stderr, "\nlyx: SIGSEGV signal trapped\n");
        fprintf(stderr, "(Sorry. If you can repeat this violation and have the current version of LyX,\n"
                       " please use a debugger to track down the bug, and then send a bug report.\n"
                       " Please tell us what version of LyX you are using. Thanks.)\n");
	break;
   case SIGTERM:
	   // no comments
	   break;
    }
   
   /* deinstall the signal handlers */ 
   signal(SIGHUP, SIG_DFL);
   signal(SIGINT, SIG_DFL);
   signal(SIGFPE, SIG_DFL);
   signal(SIGSEGV, SIG_DFL);
   signal(SIGTERM, SIG_DFL);

   bufferlist.emergencyWriteAll();

   fprintf(stderr, "Bye.\n");
   if(err_sig!=SIGHUP && getenv("LYXDEBUG"))
      abort();
   exit(0);
}


void ScreenApplyCB(FL_OBJECT *, long)
{
   roman_font_name = (char*) fl_get_input(fd_form_screen->input_roman);
   sans_font_name = (char*) fl_get_input(fd_form_screen->input_sans);
   typewriter_font_name = (char*) fl_get_input(fd_form_screen->input_typewriter);
   font_norm = (char*) fl_get_input(fd_form_screen->input_font_norm);
   
    font_sizes[LYX_SIZE_TINY] =
	    atoi(fl_get_input(fd_form_screen->intinput_tiny));
    font_sizes[LYX_SIZE_SMALL] =
	    atoi(fl_get_input(fd_form_screen->intinput_small));
    font_sizes[LYX_SIZE_NORMAL] =
	    atoi(fl_get_input(fd_form_screen->intinput_normal));
    font_sizes[LYX_SIZE_LARGE] =
	    atoi(fl_get_input(fd_form_screen->intinput_large));
    font_sizes[LYX_SIZE_LARGER] =
	    atoi(fl_get_input(fd_form_screen->intinput_larger));
    font_sizes[LYX_SIZE_LARGEST] =
	    atoi(fl_get_input(fd_form_screen->intinput_largest));
    font_sizes[LYX_SIZE_HUGE] =
	    atoi(fl_get_input(fd_form_screen->intinput_huge));
    font_sizes[LYX_SIZE_GIANT] =
	    atoi(fl_get_input(fd_form_screen->intinput_giant));

   lyxrc.default_zoom = atoi(fl_get_input(fd_form_screen->intinput_size));
   SetZoom(lyxrc.default_zoom);
   
   /* all buffers will need resize */
   bufferlist.resize();

   RedoCurrentBuffer();
   minibuffer.Set("Screen options set");
}


void ScreenCancelCB(FL_OBJECT *, long)
{
   fl_hide_form(fd_form_screen->form_screen);
}


void ScreenOKCB(FL_OBJECT *ob, long data)
{
   ScreenCancelCB(ob,data);
   ScreenApplyCB(ob,data);
}


void LaTeXOptions()
{
	if (!bufferlist.current()->text)
		fl_set_button(fd_latex_options->accents,
			      (int)lyxrc.allowAccents);
	else 
		fl_set_button(fd_latex_options->accents,
			      (int)bufferlist.current()->allowAccents);
	
	if (fd_latex_options->LaTeXOptions->visible) {
		fl_raise_form(fd_latex_options->LaTeXOptions);
	} else 
		fl_show_form(fd_latex_options->LaTeXOptions,
			     FL_PLACE_MOUSE | FL_FREE_SIZE, FL_FULLBORDER,
			     "LaTeX Options");
}


/* these functions are for the spellchecker */ 
char* NextWord(float &value)
{
	if (!bufferlist.current()->text){
		value = 1;
		return NULL;
	}
   
	char* string =  bufferlist.current()->text->SelectNextWord(value);

	return string;
}

  
void SelectLastWord()
{
   if (!bufferlist.current()->text)
      return;
   
   if (work_area_active)
      bufferlist.current()->screen->HideCursor();
   BeforeChange(); 
   bufferlist.current()->text->SelectSelectedWord();
   bufferlist.current()->screen->ToggleSelection();
   Update(0);
}


void EndOfSpellCheck()
{
   if (!bufferlist.current()->text)
      return;
   
   if (work_area_active)
      bufferlist.current()->screen->HideCursor();
   BeforeChange(); 
   bufferlist.current()->text->SelectSelectedWord();
   bufferlist.current()->text->ClearSelection();
   Update(0);
}


void ReplaceWord(const char* replacestring)
{
   if (!bufferlist.current()->screen)
      return;
   
   bufferlist.current()->screen->HideCursor();
   Update(-2);
   
   /* clear the selection (if there is any) */ 
   bufferlist.current()->screen->ToggleSelection();
   bufferlist.current()->text->
	   ReplaceSelectionWithString((char*) replacestring);
   
   bufferlist.current()->text->SetSelectionOverString((char*) replacestring);
   Update(1);
}


static int ScrollUpCB(long time)
{
   if (!bufferlist.current()->screen)
      return 0;
   
   double value= fl_get_slider_value(fd_form_main->scrollbar);
   
   if (value == 0)
      return 0;
   
   float add_value =  (bufferlist.current()->text->DefaultHeight()
		       + (float)(time) * (float)(time) * 0.125);
   
   if (add_value > work_area_height)
      add_value = (float) (work_area_height -
			   bufferlist.current()->text->DefaultHeight());
   
   value -= add_value;

   if (value < 0)
      value = 0;
   
   fl_set_slider_value(fd_form_main->scrollbar, value);
   
   ScrollCB(fd_form_main->scrollbar,0); 
   return 0;
}


static int ScrollDownCB(long time)
{
   if (!bufferlist.current()->screen)
      return 0;
   
   double value= fl_get_slider_value(fd_form_main->scrollbar);
   double min, max;
   fl_get_slider_bounds(fd_form_main->scrollbar, &min, &max);

   if (value == max)
      return 0;
   
   float add_value =  (bufferlist.current()->text->DefaultHeight()
		       + (float)(time) * (float)(time) * 0.125);
   
   if (add_value > work_area_height)
      add_value = (float) (work_area_height -
			   bufferlist.current()->text->DefaultHeight());
   
   value += add_value;
   
   if (value > max)
      value = max;
   
   fl_set_slider_value(fd_form_main->scrollbar, value);
   
   ScrollCB(fd_form_main->scrollbar,0); 
   return 0;
}


static void ScrollUpOnePageCB(long /*time*/)
{
   if (!bufferlist.current()->screen)
      return;
   
   long y = bufferlist.current()->screen->first;

   if (!y) return;
   
   Row* row = bufferlist.current()->text->GetRowNearY(y);
   y = y - work_area_height + row->height;
   bufferlist.current()->screen->Draw(y);
   UpdateScrollbar();
}


static void ScrollDownOnePageCB(long /*time*/)
{
   if (!bufferlist.current()->screen)
      return;
   
   double min, max;
   fl_get_slider_bounds(fd_form_main->scrollbar, &min, &max);
   long y = bufferlist.current()->screen->first;
   
   if (y > bufferlist.current()->text->height - work_area_height)
      return;
   
   y += work_area_height;
   bufferlist.current()->text->GetRowNearY(y);
   bufferlist.current()->screen->Draw(y);
   UpdateScrollbar();
}


void DownCB(FL_OBJECT *ob, long)
{
   const XEvent*ev2;
   static long time = 0;
   ev2 = fl_last_event();
   if (ev2->type == ButtonPress || ev2->type == ButtonRelease) 
     time = 0;
   int button = fl_get_button_numb(ob);
   switch (button) {
   case 2:
	   ScrollUpOnePageCB(time++); break;
   case 3:
	   ScrollDownOnePageCB(time++); break;
   default:
	   ScrollDownCB(time++); break;
   }
}


void UpCB(FL_OBJECT *ob, long)
{
   const XEvent*ev2;
   static long time = 0;
   ev2 = fl_last_event();
   if (ev2->type == ButtonPress || ev2->type == ButtonRelease) 
     time = 0;
   int button = fl_get_button_numb(ob);
   switch (button) {
   case 3:
	   ScrollUpOnePageCB(time++); break;
   case 2:
	   ScrollDownOnePageCB(time++); break;
   default:
	   ScrollUpCB(time++); break;
   }
}


struct TocList {
  char counter[6];
  TocList *next;
};


static TocList* toclist = NULL;


void TocSelectCB(FL_OBJECT *ob, long)
{
   if (!bufferlist.current()->text)
      return;
   
   TocList* tmptoclist = toclist;
   int i = fl_get_browser(ob);
   int a = 0;

   for (a=1; a<i && tmptoclist->next; a++){
     tmptoclist = tmptoclist->next;
   }

   if (!tmptoclist)
     return;
     

   LyXParagraph *par = bufferlist.current()->parameters.paragraph;
   while (par && 
	  (
	   par->GetCounter(0) != tmptoclist->counter[0] ||
	   par->GetCounter(1) != tmptoclist->counter[1] ||
	   par->GetCounter(2) != tmptoclist->counter[2] ||
	   par->GetCounter(3) != tmptoclist->counter[3] ||
	   par->GetCounter(4) != tmptoclist->counter[4] ||
	   par->GetCounter(5) != tmptoclist->counter[5]
	   )
	  ) {
      par = par->LastPhysicalPar()->Next();
   }
   
   if (par) {
      BeforeChange();
      bufferlist.current()->text->SetCursor(par, 0);
      bufferlist.current()->text->sel_cursor =
	      bufferlist.current()->text->cursor;
      Update(0);
   }
   else {
      WriteAlert("Error", "Couldn't find this label", "in current document.");
   }
	  
}


void TocCancelCB(FL_OBJECT *, long)
{
   fl_hide_form(fd_form_toc->form_toc);
}


void TocUpdateCB(FL_OBJECT *, long)
{
   static LyXParagraph* stapar = NULL;
   TocList *tmptoclist = NULL;
   
   /* deleted the toclist */ 
   if (toclist){
     while (toclist){
       tmptoclist = toclist->next;
       delete toclist;
       toclist = tmptoclist;
     }
   }
   toclist = NULL;
   tmptoclist = toclist;


   fl_clear_browser(fd_form_toc->browser_toc);
   if (!bufferlist.current()->text) {
      fl_add_browser_line(fd_form_toc->browser_toc, "*** No Document ***");
      return;
   }
   fl_hide_object(fd_form_toc->browser_toc);
   /* get the table of contents */ 
   LyXParagraph *par = bufferlist.current()->parameters.paragraph;
   char labeltype;
   char* line = new char[200];
   int i = 0;
   int pos = 0;
   unsigned char c;
   int topline = 0;
   
   if (stapar == par)
      topline = fl_get_browser_topline(fd_form_toc->browser_toc);
   stapar = par;
   
   while (par) {
      labeltype = lyxstyle.Style(bufferlist.current()->parameters.textclass, 
			par->GetLayout())->labeltype;
      
      if (labeltype >= LABEL_COUNTER_CHAPTER
	  && labeltype <= LABEL_COUNTER_CHAPTER +
	     bufferlist.current()->parameters.tocdepth)
      {
	      /* inset this into the table of contents */ 
	      /* first indent a little bit */ 

	 for (pos=0; 
	      pos < (labeltype - 
		     lyxstyle.TextClass(bufferlist.current()->
		         parameters.textclass)->maxcounter) * 4 + 2;
	      pos++)
		 line[pos] = ' ';
	 
	 /* then the labelstring */ 
	 i = 0;
	 if (par->labelstring) {
	    while (pos < 199 && par->labelstring[i]) {
	       line[pos] = par->labelstring[i];
	       i++;
	       pos++;
	    }
	 }
	 
	 line[pos] = ' ';
	 pos++;
	 
	 /* now the contents */ 
	 i = 0;
	 while (pos < 199 && i < par->last) {
	    c = par->GetChar(i);
	    if (isprint(c) || c >= 128) {
	       line[pos] = c;
	       pos++;
	    }
	    i++;
	 }
	 line[pos] = '\0';
	 fl_add_browser_line(fd_form_toc->browser_toc, line);
	 
	 /* make a toclist entry */
	 if (!tmptoclist){
	   tmptoclist = new TocList;
	   toclist = tmptoclist;
	 }
	 else {
	   tmptoclist->next = new TocList;
	   tmptoclist = tmptoclist->next;
	 }

	 tmptoclist->next = NULL;
	 int a = 0;
	 for (a=0; a<6; a++){
	   tmptoclist->counter[a] = par->GetCounter(a);
	 }
      }
      par = par->LastPhysicalPar()->Next();
	 
   }
   delete[] line;
   fl_set_browser_topline(fd_form_toc->browser_toc, topline);
   fl_show_object(fd_form_toc->browser_toc);
}


int AtCloseMainFormCB(FL_FORM *, void *)
{
  MenuQuit();
  return FL_IGNORE;
}


/* callbacks for form form_ref */
void RefSelectCB(FL_OBJECT *, long)
{
   int i;
   if (!bufferlist.current()->text)
      return;
   char * s = StringCopy(fl_get_browser_line(fd_form_ref->browser_ref,
					     fl_get_browser(fd_form_ref->
							    browser_ref)));
   if (!s)
     return;
   if (!StringEqual(lyxstyle.NameOfClass(current_textclass), "linuxdoc")) {
      char string[200];
      if (fl_get_button(fd_form_ref->radio_ref))
      	 sprintf(string, "\\ref{%s}", s);
      else
      	 sprintf(string, "\\pageref{%s}", s);
      InsertLatexDelInset(string);
   }
   else {
      /* special hack for linuxdoc sgml references */ 
      InsertLatexDelInset("\\ref{");
      for (i=0; s[i]; i++) 
	 bufferlist.current()->text->InsertChar(s[i]);
      InsertLatexDelInset("}{");
      InsertLatexDelInset("}");
      bufferlist.current()->text->InsertChar(' ');
   }
}


void RefUpdateCB(FL_OBJECT *, long)
{
	//int i;
  fl_clear_browser(fd_form_ref->browser_ref);
  if (!bufferlist.current()->text)
    return;

  LyXParagraph *par = bufferlist.current()-> parameters.paragraph;
  int pos;
  Inset* inset;
  while (par){
    pos = -1;
    while ((inset = par->ReturnNextInsetPointer(pos))){
	
    // Provisional hack to handle labels ale260796
	    //if (inset->GetLabel()) 
	    //fl_add_browser_line(fd_form_ref->browser_ref, 
	    //	      inset->GetLabel());
	    for (int i = 0; i < inset->GetNumberOfLabels(); i++)
	fl_add_browser_line(fd_form_ref->browser_ref, 
			    inset->GetLabel(i));
      pos++;
    } 
    par = par->next;
  }
  if (!fl_get_browser_maxline(fd_form_ref->browser_ref)){
    fl_add_browser_line(fd_form_ref->browser_ref, 
			"*** No labels found in document ***");
    fl_deactivate_object(fd_form_ref->browser_ref);
  }
  else {
    fl_select_browser_line(fd_form_ref->browser_ref, 1);
    fl_activate_object(fd_form_ref->browser_ref);
  }
}


void RefHideCB(FL_OBJECT *, long)
{
   fl_hide_form(fd_form_ref->form_ref);
}


void UpdateInset(Inset* inset, bool mark_dirty)
{
  if (!inset)
    return;

  /* very first check for locking insets*/
  if (bufferlist.current()->the_locking_inset == inset){
    if (bufferlist.current()->text->UpdateInset(inset)){
      bufferlist.current()->screen->Update();
      if (mark_dirty){
	if (bufferlist.current()->isLyxClean())
	  minibuffer.setTimer(4);
	bufferlist.current()->markDirty();
      }
      UpdateScrollbar();
      return;
    }
  }
  
  /* first check the current buffer */
  if (bufferlist.current()->text){
    bufferlist.current()->screen->HideCursor();
    BeforeChange();
    Update(-2);
    if (bufferlist.current()->text->UpdateInset(inset)){
      if (mark_dirty)
	Update(1);
      else 
	Update(2);
      return;
    }
  }
  
  // check all buffers
  bufferlist.updateInset(inset, mark_dirty);

}


/* these functions return 1 if an error occured, 
   otherwise 0 */
int LockInset(UpdatableInset* inset)
{
  if (!bufferlist.current()->the_locking_inset && inset){
    bufferlist.current()->the_locking_inset = inset;
    return 0;
  }
  return 1;
}

void ToggleLockedInsetCursor(long x, long y, int asc, int desc){
  if (bufferlist.current()->the_locking_inset && bufferlist.current()->screen){
//    x += bufferlist.current()->text->cursor.x;
    y += bufferlist.current()->text->cursor.y;
    bufferlist.current()->screen->DrawManualCursor(x, y, asc, desc);
  }
}

void FitLockedInsetCursor(long x, long y, int asc, int desc){
  if (bufferlist.current()->the_locking_inset && bufferlist.current()->screen){
//    x += bufferlist.current()->text->cursor.x;
    y += bufferlist.current()->text->cursor.y;
    if (bufferlist.current()->screen->FitManualCursor(x, y, asc, desc))
      UpdateScrollbar();
  }
}


int UnlockInset(UpdatableInset* inset)
{
  if (inset && bufferlist.current()->the_locking_inset == inset){
    inset->InsetUnlock();
    bufferlist.current()->the_locking_inset = NULL;
    bufferlist.current()->text->FinishUndo();
    return 0;
  }
  return bufferlist.unlockInset(inset);
}

void LockedInsetStoreUndo(int kind){
  if (!bufferlist.current()->the_locking_inset)
    return; // shouldn't happen
  if (kind == LYX_UNDO_EDIT) // in this case insets would not be stored!
    kind = LYX_UNDO_FINISH;
  bufferlist.current()->text->SetUndo(kind,
				      bufferlist.current()->text->cursor.par->
				      ParFromPos(bufferlist.current()->text->cursor.pos)->previous, 
				      bufferlist.current()->text->cursor.par->
				      ParFromPos(bufferlist.current()->text->cursor.pos)->next); 

}



void PutInsetIntoInsetUpdateList(Inset* inset)
{
  if (inset) {
    InsetUpdateStruct* tmp = new InsetUpdateStruct();
    tmp->inset = inset;
    tmp->next = InsetUpdateList;
    InsetUpdateList = tmp;
  }
}


void UpdateInsetUpdateList()
{
  InsetUpdateStruct *tmp = InsetUpdateList;
  while (tmp) {
    UpdateInset(tmp->inset, False); // "False" because no document change
    tmp = tmp->next;
  }
  
  /* delete the update list */
  while (InsetUpdateList) {
    tmp = InsetUpdateList;
    InsetUpdateList = InsetUpdateList->next;
    delete[] tmp;
  }
  InsetUpdateList = NULL;
}
