/* ########################################################################

			      chars_cmds.c

   File: chars_cmds.c
   Path: /home/fournigault/c/X11/xcoral-2.31/chars_cmds.c
   Description: 
   Created: Fri Jan 27 10:52:41 MET 1995
   Author: Lionel Fournigault
   Modified: Fri Jan 27 10:52:42 MET 1995
   Last maintained by: Lionel Fournigault

   RCS $Revision$ $State$
   

   ########################################################################

   Note: 

   ########################################################################

   Copyright (c) : Lionel Fournigault

   This program is free software; you can redistribute it and/or modify
   it under the terms of the GNU General Public License as published by
   the Free Software Foundation; either version 2, or (at your option)
   any later version.

   This program is distributed in the hope that it will be useful,
   but WITHOUT ANY WARRANTY; without even the implied warranty of
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   GNU General Public License for more details.

   You should have received a copy of the GNU General Public License
   along with this program; if not, write to the Free Software
   Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.

   ######################################################################## */


#include <stdio.h>
#include <X11/Xlib.h>
#include <X11/cursorfont.h>
#include <X11/Xutil.h>
#include <X11/Xatom.h>
#include <X11/keysym.h>
#include <ctype.h>
#include <signal.h>
#include <sys/types.h>

#if HAVE_STRING_H
#include <string.h>
#else
#include <strings.h>
#endif

#if STDC_HEADERS
#  include <stdlib.h>
#else
#  if HAVE_MALLOC_H
#    include <malloc.h>
#  endif
#endif

#if HAVE_UNISTD_H
#  include <unistd.h>
#endif

#if HAVE_POLL
#  include <stropts.h>
#  include <poll.h>
#endif

#if TIME_WITH_SYS_TIME
#  include <sys/time.h>
#  include <time.h>
#else
#  if HAVE_SYS_TIME_H
#    include <sys/time.h>
#  else
#    include <time.h>
#  endif
#endif

#include "main_text.h"
#include "chars_cmds.h"
#include "text_cursor.h"
#include "mark_reg.h"
#include "page.h"
#include "kill_buf.h"
#include "list_box.h"
#include "ie_func.h"
#include "get_file.h"
#include "selection.h"

extern Display *dpy;
static int toggle_del = 0;
extern char *ie_call_function();

FCT (static RETSIGTYPE, donothing, () );

static char *cut_buffer = 0;
static int n_cb = 0;

/*
**	Function name : CheckModifAndFilename
**
**	Description : 
**	Input : 
**	Ouput :
*/
void CheckModifAndFilename ( text )
    Text *text;
{
  if ( (text -> modif == False) && (strcmp(text -> filename,"NoName")==0) ) {
    text -> modif = True; 
    if ( text -> swin == 0 )
      return;
    SetScrollLine ( text -> swin , 1 );
    ShowScrollFrame ( dpy, text -> swin );
  }
}

/*
**	Function name : f_impc
**
**	Description : Imprime un caractere ( position courante ). 
**	Input : Le caractere.
**	Ouput :
*/
void f_impc ( text, ch )
    Text *text;
    int ch;
{
  char c = (char) ch;

  if (text -> selection -> select == True)
    ClearSelection(text, True);
  
  TextCursorOff ( text );
  (void) UpdateMark ( text, 1, 0 );
  InsertNchar ( text -> buf, &c, 1 );
  
/*  CheckModifAndFilename ( text ); */
  
  /* Pour le Undo */
  if ( text -> u_todo == True )
    (void) StoreInUndo ( text, &c, (char *) 0, 1, 0, U_STD );

  /* Pour la couleur */
  if ( text -> current_ce != 0 )
    (void) UpdateColorList ( text, 1 );
  
  SetCurrentLine ( text ); 
  TextCursorOn ( text );
  SetTextModif ( text );
}

/*
**	Function name : f_tab
**
**	Description : Tabulation.
**	Input : Le text courant. 
**	Ouput :
*/
void f_tab ( text )
    Text *text;
{
  if (text -> selection -> select == True)
    ClearSelection(text, True);

  TextCursorOff ( text );
  
  UpdateMark ( text, 1, 0 );	
  InsertNchar ( text -> buf, "\t", 1 );
  if ( text -> u_todo == True )
    (void) StoreInUndo ( text, "\t", (char *) 0, 1, 0, U_STD );
  
  /* Pour la couleur */

  if ( text -> current_ce != 0 )
    (void) UpdateColorList ( text, 1 );

  ClipOn ( text, 0 );
  SetCurrentLine ( text );
  ClipOff ( text );
  TextCursorOn ( text );
  SetTextModif ( text );
}


/*
**	Function name : f_return
**
**	Description : Retour chariot.
**	Input : Le text courant.
**	Ouput :
*/
void f_return ( text )
    Text *text;
{
  if (text -> selection -> select == True)
    ClearSelection(text, True);

  TextCursorOff ( text );
  
  if ( text -> n2 == 0 ) 
    CurrentLineToMiddle ( text );
  
  UpdateMark ( text, 1, 1 );
  InsertNchar ( text -> buf, "\n", 1 );
  text -> n1 ++;
  text -> n2 --;
  text ->  no_current_line ++;
  text -> lines_in_buf ++;
  if ( text -> u_todo == True )
    (void) StoreInUndo ( text, "\n", (char *) 0, 1, 0, U_STD );

  /* Pour la couleur */
  if ( text -> current_ce != 0 )
    (void) UpdateColorList (text, 1);

  
  SetLinesTable ( text );
  ClipOn ( text, text -> n1 -1);
  RefreshPage ( text );
  ClipOff ( text );
  
  SetScrollLine ( text -> swin , text -> lines_in_buf );
  ShowScrollFrame ( dpy, text -> swin );
  (void) MoveScrollBar ( dpy, text -> swin, 
			CURRENT, text -> no_current_line - text -> n1 - 1 );

  TextCursorOn ( text );
  SetTextModif ( text );

}

/*
**	Function name : OpenSpace
**
**	Description : 
**	Input : 
**	Ouput :
*/
void OpenSpace ( text )
    Text *text;
{
  f_return ( text );
  TextCursorOff ( text );			
  BackwardChar ( text );
  
}

/*
**	Function name : f_delete
**
**	Description : Delete ou backspace.
**	Input : Le text courant.
**	Ouput :
*/
void f_delete ( text )
    Text *text;
{
  char c;
  int mark = 0;
  
  if ((TextInBuf ( text ) == False) 
      || (text -> buf -> l_cur == TopBuf(text ->buf))) {
    klaxon ();
    return;
  }
/*  
  if (text -> selection -> select == True)
    ClearSelection(text, True);
*/
  if (text -> selection -> select == True) {
     DeleteBytesFromCutBuffer (text);
     return;
  }
  
  TextCursorOff ( text );
  GetPrevChar ( text -> buf, &c );
  
  if ( c == '\n' ) {
    if ( text -> n1 == 0 ) 
      CurrentLineToMiddle ( text );
    mark = UpdateMark ( text, -1, -1 );
    DeleteNchar ( text -> buf, 1 );
    if ( mark ) 
      UpdateMarkPos ( text );
    text -> n1 --;
    text -> n2 ++;
    text -> no_current_line--;
    text -> lines_in_buf --;
    SetLinesTable ( text );
    ClipOn ( text, text -> n1 );
    RefreshPage ( text );
    ClipOff ( text );
    SetScrollLine ( text -> swin , text -> lines_in_buf );
    ShowScrollFrame ( dpy, text -> swin );
    if ( text -> no_current_line == 1 ) {
      (void) MoveScrollBar ( dpy, text -> swin, FIRST, 0 );
    }
    else
      (void) MoveScrollBar ( dpy, text -> swin, 
			    CURRENT, text -> no_current_line - text -> n1 - 1 );
  }
  else {
    UpdateMark ( text, -1, 0 );
    DeleteNchar ( text -> buf, 1 );
    ClipOn ( text, 0 );
    SetCurrentLine ( text );
    ClipOff ( text );
  }

  SetTextModif ( text );
  if ( text -> u_todo == True )
    (void) StoreInUndo ( text, &c, (char *) 0, -1, 0, U_STD );
    
    /* Pour la couleur */
  if ( text -> current_ce != 0 ) {
    (void) UpdateColorList ( text, -1 );
    ClipOn ( text, 0 );
    RefreshPage ( text );
    ClipOff ( text );
  }
  TextCursorOn ( text );
}


/*
**	Function name : Controle_D
**
**	Description : Efface le caractere courant.
**	Input : Le text courant.
**	Ouput :
*/
void Control_D ( text )
    Text *text;
{
  if ( TextInBuf ( text ) == False ) {
      klaxon();
    return;
  }
  if ( ForwardChar ( text ) == True ) {
    f_delete ( text );
    SetTextModif ( text );
  }
}


/*
**	Function name : Control_K
**
**	Description : Delete une ou plusieurs lignes
**	Input : Le text courant.
**	Ouput : Le nb de lignes.
*/
void Control_K ( text, n )
    Text *text;
    int n;
{
  char *p;
  int mark = 0;
  int len, dn;

  if ( TextInBuf ( text ) == False ) {
      klaxon();
    return;
  }
  
  if (text -> selection -> select == True)
    ClearSelection(text, True);

  mark = UpdateMark ( text, 0, -(n -1) );
  p = (char *) DeleteLines ( text -> buf, n, &len, &dn );
  if ( mark ) 
    UpdateMarkPos (text );
  if ( len == 0 ) {
    klaxon ();
    return;
  }
  
  (void) StoreInUndo ( text, p, (char *) 0, -len ,dn, U_STD );
  
  /* Pour la couleur */
  if ( text -> current_ce != 0 )
    (void) UpdateColorList ( text, -len );

  StoreInKillBuf ( p, len, dn );
#ifdef DEBUG
  fprintf ( stderr, "n = %d Delete lines = %d len = %d\n", n, dn, len );
#endif
  SetLinesTable ( text );
  
  ClipOn ( text, text -> n1 );
  RefreshPage ( text );
  ClipOff ( text );
  
  if ( dn > 0 ) {
    text -> lines_in_buf = GetNumberOfLineInBuf ( text -> buf );
    SetScrollLine ( text -> swin , text -> lines_in_buf );
    ShowScrollFrame ( dpy, text -> swin );
    (void) MoveScrollBar ( dpy, text -> swin, 
			  CURRENT, text -> no_current_line - text -> n1 - 1 );
  }
  SetTextModif ( text );
}


/*
**	Function name : Control_Y
**
**	Description : Restore un portion de texte.
**	Input : Le text courant, le no a restorer.
**	Ouput :
*/
void Control_Y ( text, i )
    Text *text;
    int i;
{
  char *p;
  int len, dn;
  
  if (text -> selection -> select == True)
    ClearSelection(text, True);

  TextCursorOff ( text );
  p = (char *) RestoreKillBuf ( i, &len, &dn );
  
  if ( p == 0 ) {
    TextCursorOn ( text );
    return;
  }
#ifdef DEBUG
  fprintf ( stderr, "i = %d len = %d Restore lines = %d\n", i, len, dn );
  write ( 1, p, len );
#endif
  ClipOn ( text, 0 );
  SetTextModif ( text );
  
  if ( dn == 0 ) {
    if ( len == 1 && *p == '\n' ) {  /* ligne vide */
	  f_return ( text );
    }
    else {
      UpdateMark ( text, len, 0 );
      InsertNchar ( text -> buf, p, len );
      (void) StoreInUndo ( text, p, (char *) 0, len ,0, U_STD );    
      SetCurrentLine ( text );
    }
  }
  else {
    (void) InsertLines ( text, p, len, dn );
    (void) StoreInUndo ( text, p, (char *) 0, len ,dn, U_STD ); 
  }
  
    /* Pour la couleur */
  if ( text -> current_ce != 0 ) {
    (void) UpdateColorList ( text, len );
    ClipOn ( text, 0 );
    RefreshPage ( text );
  }

  TextCursorOn ( text );
  ClipOff ( text );
}


/*
**	Function name : DisplayKillBuffer
**
**	Description : Affiche la fenetre des choses tuees.
**		et restore eventuellement.
**	Input : Le text courant.
**	Ouput :
*/
void DisplayKillBuffer ( text ) 
    Text *text;
{
  char *str;
  
  ClearListBox ();
  KillBufferInList ();
  str = (char *) SelectFromListBox ( "Kill Buffers" );
  if ( str != 0 ) {
    /* str += 9; */
    /* On vire le "Select : " */
    /* On ne prend que les 2 premier caracteres */
    *(str+2) = 0;
    /* On restore la nieme entree */
    Control_Y ( text, atoi(str) - 1 );
    if ( str != 0 )
      (void) free ( str ); 
  }
  else
    DisplayMessage ( text -> mwin, "Abort" );
}

/*
**	Function name : GetBytesFromCutBuffer
**
**	Description : Comme son nom l'indique.
**	Input : Le text courant.
**	Ouput :
*/
void GetBytesFromCutBuffer ( text )
    Text *text;
{
  int lines;
  char *s;
  int nbytes;
  
  s = Fetch_bytes (&nbytes);
  
  if (text -> selection -> select == True)
    ClearSelection(text, True);

  if ( (s != 0) && (nbytes != 0 )) {
    TextCursorOff ( text );
    ClipOn ( text, 0 );
    lines = GetNewLine ( s, nbytes);
    SetTextModif ( text );
    if ( lines == 0 ) {
      UpdateMark ( text, nbytes, 0 );
      InsertNchar ( text -> buf, s, nbytes);
      SetCurrentLine ( text );
    }
    else {
      (void) InsertLines ( text, s, nbytes, lines );
      RefreshScrollBar ( dpy, text -> swin );
    }
    (void) StoreInUndo ( text, s, (char *) 0, nbytes, lines, U_STD );
    
    /* Pour la couleur */
    if ( text -> current_ce != 0 ) {
      (void) UpdateColorList ( text, nbytes );
      ClipOn ( text, 0 );
      RefreshPage ( text );
    }

    TextCursorOn ( text );
    ClipOff ( text );
  }
}


/*
**	Function name : InsertLines
**
**	Description : Insere une ou plusieurs lignes.
**	Input : Le text courant, la chaine, sa longueur et
**		le nombre de lignes.
**	Ouput :
*/
void InsertLines ( text, s, nbytes, lines )
    Text *text;
    char *s;
    int nbytes;
    int lines;
{
  int mark = 0;
  
  mark = UpdateMark ( text, nbytes, lines );
  InsertNchar ( text -> buf, s, nbytes );      
  text -> no_current_line += lines;
  text -> lines_in_buf = GetNumberOfLineInBuf ( text -> buf );
  SetScrollLine ( text -> swin , text -> lines_in_buf );
  ShowScrollFrame ( dpy, text -> swin );
  
  if ( text -> n2 < lines ) {
    CurrentLineToMiddle ( text );
  }
  else {
    text -> n1 += lines;
    text -> n2 -= lines;
    SetLinesTable ( text );
    RefreshPage ( text );
    (void) MoveScrollBar ( dpy, text -> swin, 
			  CURRENT, text -> no_current_line - text -> n1 - 1 );
  }
  if ( mark ) 
    UpdateMarkPos (text );
}


/*
**	Function name : StoreBytesInCutBuffer
**
**	Description : Selection.
**	Input : Le text, la position du cursor.
**	Ouput :
*/
void StoreBytesInCutBuffer ( text, x, y )
    Text *text;
    int x, y;
{
  char *old_left = (char *) LeftBuf ( text -> buf );
  char *old_right = (char *) RightBuf ( text -> buf );
  char *new_left, *new_right;

  StartSelection(text);

  StorePosition ( text );
  if ( MoveToXYinTextWindow ( text, x, y ) == -1 ) {
    HoleToRight ( text -> buf );
    GotoLineNumber ( text, text -> lines_in_buf );
    SetPosition ( text );
    UpdatePage ( text );
  }
  
/*  (void) MoveToXYinTextWindow ( text, x, y ); */

  TextCursorOn ( text );
  XSync ( dpy, False );
  EndSelection(text);

  new_left = (char *) LeftBuf ( text -> buf );
  new_right = (char *) RightBuf ( text -> buf );

  if ( new_left > old_left )  { /* Deplacement vers la droite du curseur */
    Store_bytes ( old_left +1, new_left - old_left );
  }
  else {
    Store_bytes ( new_right, old_right - new_right );
  }
}


/*
**	Function name : DeleteBytesFromCutBuffer
**
**	Description : Efface une slection.
**	Input : Le text courant.
**	Ouput :
*/
void DeleteBytesFromCutBuffer ( text )
    Text *text;
{
  int lines;
  char *s, *tmp = 0;
  int mark = 0;
  int nbytes;
  int markline = 0, markpos = 0;
  
  s = Fetch_bytes (&nbytes);

  if (text -> selection -> select == True)
    ClearSelection(text, True);
  else
    return;
  
  if ( (s != 0) && (nbytes != 0 )) {
    if ( (text -> modif == False) && (strcmp(text -> filename,"NoName")==0) )
      return;

    /* On sauve la marque si yen a une */
    if (text -> markline) {
      markline = text -> markline;
      markpos = text -> markpos;
    }
    
    /* On positionne une marque sur le debut de la selection */
    if (text -> selection -> start_line < text -> selection -> end_line) {
      text -> markline = text -> selection -> start_line;
      text -> markpos = text -> selection -> ncfl_sl;
    }
    else if (text -> selection -> start_line > text -> selection -> end_line){
      text -> markline = text -> selection -> end_line;
      text -> markpos = text -> selection -> ncfl_el;
    }
    else {
      /* selection sur une ligne; */
      if (text -> selection -> ncfl_sl < text -> selection -> ncfl_el) {
	text -> markline = text -> selection -> start_line;
	text -> markpos = text -> selection -> ncfl_sl;
      }
      else {
	text -> markline = text -> selection -> start_line;
	text -> markpos = text -> selection -> ncfl_el;
      }
    }
    
    (void) GotoTheMark (text);

    if(markline) {
      text -> markline = markline;
      text -> markpos = markpos;
    }
    else {
      text -> markline = 0;
      text -> markpos = 0;
    }

    if ( (RightBuf ( text -> buf ) + nbytes) > BottomBuf ( text -> buf ) ) {
      nbytes = BottomBuf ( text -> buf ) - RightBuf ( text -> buf );
      if ( nbytes <= 0 ) {
	klaxon ();
	return;
      }
    }
    tmp = (char *) malloc ( (unsigned) nbytes + 2 );
    (void) bcopy ( RightBuf ( text -> buf ), tmp, nbytes );
    
    TextCursorOff ( text );
    ClipOn ( text, 0 );
    
    lines = GetNewLine ( RightBuf ( text -> buf ), nbytes );
    (void) MoveHole ( text -> buf, nbytes );
    mark = UpdateMark ( text, -nbytes, -lines );
    DeleteNchar ( text -> buf, nbytes);
    if ( mark )
      UpdateMarkPos ( text );
    SetTextModif ( text );
    
    if ( lines == 0 ) {
      SetCurrentLine ( text );
    }
    else {
      text -> lines_in_buf = GetNumberOfLineInBuf ( text -> buf );
      SetScrollLine ( text -> swin , text -> lines_in_buf );
      ShowScrollFrame ( dpy, text -> swin );
      SetLinesTable ( text );
      RefreshPage ( text );
      (void) MoveScrollBar ( dpy, text -> swin, 
			    CURRENT, text -> no_current_line - text -> n1 - 1 );
      RefreshScrollBar ( dpy, text -> swin );
    }
    (void) StoreInUndo ( text, tmp, (char *) 0, -nbytes, lines, U_STD );
    (void) StoreInKillBuf ( tmp, nbytes, lines );
    
    /* Pour la couleur */
    if ( text -> current_ce != 0 ) {
      (void) UpdateColorList ( text, -nbytes );
      ClipOn ( text, 0 );
      RefreshPage ( text );
    }
    TextCursorOn ( text );
    ClipOff ( text );
    toggle_del = True;
    (void) free ( tmp );
  }
}
static int timer_expire = False;
static RETSIGTYPE donothing () { timer_expire = True; }


/*
**	Function name : SmallTime
**
**	Description : Un reveil
**	Input : Le temps.
**	Ouput :
*/
void SmallTime ( t )
    long t; /* micros-secondes */
{
#if HAVE_USLEEP
  usleep(t);

#elif HAVE_SELECT
  struct timeval delay;

  delay.tv_sec  = 0;
  delay.tv_usec = t;
  select(0, NULL, NULL, NULL, &delay);

#elif HAVE_NANOSLEEP
  struct timespec rqtp;

  rqtp.tv_sec  = t / (unsigned long)  1000000;
  rqtp.tv_nsec = (t % (unsigned long) 1000000) * 1000 ;
  nanosleep(&rqtp, NULL);

#else  /* Use default poll */
  struct pollfd unused;

  poll(&unused,0,(t / 1000)); 

#endif
}


/*
**	Function name : FunctionHeader
**
**	Description : 
**	Input : 
**	Ouput :
*/
void FunctionHeader ( text )
    Text *text;
{
  char *msg;
  int nw = text->win_id;
  
  StorePosition ( text );
  msg = (char *) ie_call_function ( text, "function_header", 0, 0);
  text = update_cwd(nw);
  if ( msg != 0 )
    DisplayMessage ( text -> mwin, msg );
  ie_redisplay ( text );
}


/*
**	Function name : IncludeHeader
**
**	Description : 
**	Input : 
**	Ouput :
*/
void IncludeHeader ( text )
    Text *text;
{
  char *msg;
  int nw = text->win_id;
  
  StorePosition ( text );
  msg = (char *) ie_call_function ( text, "include_header", 0, 0) ;
  text = update_cwd(nw);
  if ( msg != 0 )
    DisplayMessage ( text -> mwin, msg );
  ie_redisplay ( text );
}

/*
**	Function name : ClassHeader
**
**	Description : 
**	Input : 
**	Ouput :
*/
void ClassHeader ( text )
    Text *text;
{
  char *msg;
  int nw = text->win_id;
    
  StorePosition ( text );
  msg = (char *) ie_call_function ( text, "class_header", 0, 0) ;
  text = update_cwd(nw);
  if ( msg != 0 )
    DisplayMessage ( text -> mwin, msg );
  ie_redisplay ( text );
}

/*
**	Function name : MethodHeader
**
**	Description : 
**	Input : 
**	Ouput :
*/
void MethodHeader ( text )
    Text *text;
{
  char *msg;
  int nw = text->win_id;

  StorePosition ( text );
  msg = (char *) ie_call_function ( text, "method_header", 0, 0) ;
  text = update_cwd(nw);
  if ( msg != 0 )
    DisplayMessage ( text -> mwin, msg );
  ie_redisplay ( text );
}

/*
**	Function name : ProgrammingUtil
**
**	Description :
**	Input :
**	Output :
*/
void ProgrammingUtil(text)
    Text *text;
{
  char *msg;
  int nw = text->win_id;

  StorePosition ( text );
  msg = (char *) ie_call_function ( text, "add_header", 0, 0) ;
  text = update_cwd(nw);
  if ( msg != 0 )
    DisplayMessage ( text -> mwin, msg );
  ie_redisplay ( text );
  if(TextInBuf(text)==False){
     TextCursorOff(text);
     ClearPage(text);
     TextCursorOn(text);
  }  
}

/*
**	Function name : RcsCommands
**
**	Description :
**	Input :
**	Output :
*/
void RcsCommands(text)
    Text *text;
{
  char *msg;
  int nw = text->win_id;

  StorePosition ( text );
  msg = (char *) ie_call_function ( text, "rcs_commands", 0, 0) ;
  text = update_cwd(nw);
  if ( msg != 0 )
    DisplayMessage ( text -> mwin, msg );
  ie_redisplay ( text );
  if(TextInBuf(text)==False){
     TextCursorOff(text);
     ClearPage(text);
     TextCursorOn(text);
  }  
}


/*
**	Function name : LatexMacros
**
**	Description :
**	Input :
**	Output :
*/
void LatexMacros(text)
    Text *text;
{
  char *msg;
  int nw = text->win_id;

  StorePosition ( text );
  msg = (char *) ie_call_function ( text, "latex_macros", 0, 0) ;
  text = update_cwd(nw);
  if ( msg != 0 )
    DisplayMessage ( text -> mwin, msg );
  ie_redisplay ( text );
  if(TextInBuf(text)==False){
     TextCursorOff(text);
     ClearPage(text);
     TextCursorOn(text);
  }  
}

/*
**	Function name : HtmlMacros
**
**	Description :
**	Input :
**	Output :
*/
void HtmlMacros(text)
    Text *text;
{
  char *msg;
  int nw = text->win_id;

  StorePosition ( text );
  msg = (char *) ie_call_function ( text, "html_macros", 0, 0) ;
  text = update_cwd(nw);
  if ( msg != 0 )
    DisplayMessage ( text -> mwin, msg );
  ie_redisplay ( text );
  if(TextInBuf(text)==False){
     TextCursorOff(text);
     ClearPage(text);
     TextCursorOn(text);
  }  
}

/*
**	Function name : MiscCommands
**
**	Description :
**	Input :
**	Output :
*/
void MiscCommands(text)
    Text *text;
{
  char *msg;
  int nw = text->win_id;

  StorePosition ( text );
  msg = (char *) ie_call_function ( text, "misc_commands", 0, 0) ;
  text = update_cwd(nw);
  if ( msg != 0 )
    DisplayMessage ( text -> mwin, msg );
  ie_redisplay (text);
  if(TextInBuf(text)==False){
     TextCursorOff(text);
     ClearPage(text);
     TextCursorOn(text);
  }  
}

/*
**	Function name : UserCommands
**
**	Description :
**	Input :
**	Output :
*/
void UserCommands(text)
    Text *text;
{
  char *msg;
  int nw = text->win_id;

  StorePosition ( text );
  msg = (char *) ie_call_function ( text, "user_commands", 0, 0) ;
  text = update_cwd(nw);
  if ( msg != 0 )
    DisplayMessage ( text -> mwin, msg );
  ie_redisplay ( text );
  if(TextInBuf(text)==False){
     TextCursorOff(text);
     ClearPage(text);
     TextCursorOn(text);
  }  
}

/*
**	Function name : EdirWindow
**
**	Description :
**	Input :
**	Output :
*/
void EdirWindow(text)
    Text *text;
{
  char *msg;
  int nw = text->win_id;

  StorePosition ( text );
  msg = (char *) ie_call_function ( text, "edir", 0, 0) ;
  text = update_cwd(nw);
  if ( msg != 0 )
    DisplayMessage ( text -> mwin, msg );
  ie_redisplay ( text );
  if(TextInBuf(text)==False){
     TextCursorOff(text);
     ClearPage(text);
     TextCursorOn(text);
  }  
}


/*
**	Function name : QuotedChar
**
**	Description : Pour inserer un caractere de controle
**	Input :
**	Output :
*/
void QuotedChar( text )
    Text *text;
{
    char buf [32];
    KeySym ksym;
    XComposeStatus compose;
    XEvent ev;
    int n_bytes;
    
    bzero (buf, 32);
    DisplayMessage ( text -> mwin, "Enter quoted char" );
    
    for (;;) {
	XNextEvent ( dpy, &ev );
	switch ( ev.type ) {
	case LeaveNotify:
	case ButtonPress:
	  XPutBackEvent ( dpy, &ev );
	  DisplayMessage ( text -> mwin, " " );
	  return;
	case KeyPress:
	    n_bytes = XLookupString ( (XKeyEvent *) &ev, buf, 32, &ksym, &compose );
	    if ( (n_bytes != 0) && (buf[0] != 0) ) {
		if ( buf[0] == '\n' )
		  f_return ( text );
		else
		  f_impc ( text, (int) buf [0] );
		DisplayMessage ( text -> mwin, " " );
		return;
	    }
	    switch (ksym) {
	    case XK_Control_R:
	    case XK_Control_L:
	      for(;;) {
		  XNextEvent ( dpy, &ev );
		  switch ( ev.type ) {
		  case LeaveNotify:
		  case ButtonPress:
		      XPutBackEvent ( dpy, &ev );
		      DisplayMessage ( text -> mwin, " " );
		      return;
		  case KeyPress:
		      n_bytes = XLookupString ( (XKeyEvent *) &ev, buf, 32, &ksym, &compose );
		      if ( (n_bytes != 0) && (buf[0] != 0) ) {
			  if ( buf[0] == '\r' )
			    f_return ( text );
			  else
			    f_impc (text, (int) buf [0] );
		      }
		      DisplayMessage ( text -> mwin, " " );
		      return;
		  default:
		    break;
		  }
	      }
	    default:
	      break;
	    }
	}
    }
}

/*
**	Function name : Store_bytes
**
**	Description :
**	Input :
**	Output :
*/
void Store_bytes(s, n)
    char *s; int n;
{
  Clear_bytes();
  
  cut_buffer = (char *) malloc (n+2);
  bzero (cut_buffer, n+2);
  strncpy (cut_buffer, s, n);
  n_cb = n;
}

/*
**	Function name : Fetch_bytes
**
**	Description :
**	Input :
**	Output :
*/
char *Fetch_bytes(n)
    int *n;
{
  *n = n_cb;
  return cut_buffer;
}

/*
**	Function name : Clear_bytes
**
**	Description :
**	Input :
**	Output :
*/
void Clear_bytes()
{
  if (cut_buffer) {
    free (cut_buffer);
    n_cb = 0;
    cut_buffer = 0;
  }
}



