#include <stdio.h>
#include <malloc.h>
#include <string.h>
#include <X11/Xlib.h>
#include <X11/Xutil.h>
#include <X11/Xos.h>
#include <X11/keysym.h>

#include "g_visu.h"
#include "v_view.h"
#include "v_extern.h"
#include "e_edit.h"

list_ligne *E_debut;
list_ligne *E_page_courant;
list_ligne *E_ligne_courant;
list_ligne *E_ligne_inter;
list_ligne *E_NEXT;
list_ligne *E_BufferSauve = NULL;
int E_mode = INSERT;	/* insertion ou indentation*/
int E_scroll_up = FALSE;
int E_scroll_down = FALSE;
int E_maxligne = 5;
int E_nbre_ligne = 0;
int E_numligne_debbloc = 0;
int E_numligne_finbloc = 0;
int E_numligne = 0;
int E_offnum = 0;
int E_strtxt = 0;

extern BOOL commande;
extern int E_dx_win, E_dy_win;

int E_NumeroLigne();
void init_ligne();
list_ligne *alloc_ligne();
void E_affiche_page();
void affiche_rc();
void aff_indent();
void aff_insert();
void E_aff_curseur();
void E_init_var();
void insertion();
void indentation();
void suppression();
void add_space();
void zero();
void droite();
void gauche();
void haut();
void bas();
void E_backspace();
void E_homekey();
void E_endkey();
void E_delkey();
void E_inskey();
void E_rightkey();
void E_leftkey();
void E_upkey();
void E_downkey();
void E_pgupkey();
void E_pgdnkey();
void E_returnkey();
void E_traitement();
void E_delinekey();
void E_insert_ligne();
void E_cleoln();
void E_del_curseur();
list_ligne *E_LectFic();
list_ligne *OpenFic();
void E_delbloc();
void E_ClearBuffer();
void E_CopyBlocToLine();
int E_Effacer();
int E_SauveFic();
int E_BreakPoint();
void cercle();
void clear_break();
void clear_attribVideo();
void clear_attribBreak();
void E_EndText();
int gotoline();
void E_BlocToBuffer();
void E_Printatlinenumber();
int E_Ligne();

void
	E_backspace()
{
	E_del_curseur();
	if (E_pos_x > 0) {
		gauche();
		suppression(E_pos_x, E_ligne_inter);
		aff_insert(E_pos_x, E_ligne_inter);
	}
	E_aff_curseur();
}

void
	E_homekey()
{
	E_del_curseur();
	zero();
	E_aff_curseur();
}

void
	E_endkey()
{
int i,l  = strlen(E_ligne_inter->prem_mot);

	E_del_curseur();
	E_pos_x = 0;
	for (i = 0; i < l; i++)
		droite();
	E_aff_curseur();
}

void
	E_end()
{
	E_del_curseur();
	E_pos_x = strlen(E_ligne_inter->prem_mot) + 1;
	E_del_curseur();
}

void
	E_delkey()
{
	E_del_curseur();
	suppression(E_pos_x, E_ligne_inter);
	aff_insert(E_pos_x, E_ligne_inter);
	E_aff_curseur();
}

void
	E_inskey()
{
	E_del_curseur();
	E_mode = ~E_mode;
	E_aff_curseur();
}

void
	E_rightkey()
{
	E_del_curseur();
	droite();
	E_aff_curseur();
}

void
	E_leftkey()
{
	E_del_curseur();
	gauche();
	E_aff_curseur();
}

void
	E_upkey()
{
	E_del_curseur();
	if (E_pos_y != 0)
		haut();
	else
		E_scroll_up = TRUE;

	if (E_ligne_courant->pt_prec != NULL) {
		E_ligne_courant = E_ligne_courant->pt_prec;
		E_ligne_inter = E_ligne_courant;
	}
	if (E_scroll_up == TRUE && E_page_courant->pt_prec != NULL)
		affiche_rc();
	E_scroll_up = FALSE;
	E_aff_curseur();
}

void
	E_downkey()
{
	E_del_curseur();
	if (E_pos_y != E_maxligne - 1 && E_ligne_courant->pt_suiv != NULL)
		bas();
	else
		E_scroll_down = TRUE;
	if (E_ligne_courant->pt_suiv != NULL) {
		E_ligne_courant = E_ligne_courant->pt_suiv;
		E_ligne_inter = E_ligne_courant;
	} else
		E_scroll_down = FALSE;
	if (E_scroll_down == TRUE && E_page_courant->pt_suiv != NULL)
		affiche_rc();
	E_scroll_down = FALSE;
	E_aff_curseur();
}

void
	E_pgupkey()
{
int i;

	XClearArea(display, E_window, 0, ORIGINEY * E_interligne, 
						E_dx_win, E_dy_win, False);
	for (i = 0; i < E_maxligne && E_page_courant->pt_prec != NULL; i++) {
		E_page_courant = E_page_courant->pt_prec;
		E_ligne_courant = E_ligne_courant->pt_prec;
	}
	if (E_page_courant == E_debut) {
		E_ligne_courant = E_debut;
		zero();
		E_pos_y = 0;
	}
	E_ligne_inter = E_ligne_courant;
	E_affiche_page(E_page_courant, 0);
	E_aff_curseur();
}

void
	E_pgdnkey()
{
int i, j = 0;

	XClearArea(display, E_window, 0, ORIGINEY * E_interligne, 
						E_dx_win, E_dy_win, False);
	for (i = 0; i < E_maxligne && E_page_courant->pt_suiv != NULL; i++) {
		E_page_courant = E_page_courant->pt_suiv;
		if (E_ligne_courant->pt_suiv != NULL) {
			E_ligne_courant = E_ligne_courant->pt_suiv;
			j++;
		}
	}
	E_affiche_page(E_page_courant, 0);
	if (j != i) {
		for (E_ligne_courant = E_page_courant, j = 0; 
				E_ligne_courant->pt_suiv != NULL; 
				E_ligne_courant = E_ligne_courant->pt_suiv, j++);
		zero();
		E_pos_y = j;
	}
	E_ligne_inter = E_ligne_courant;
	E_aff_curseur();
}

void
	E_returnkey()
{
int	taille, i;

	E_del_curseur();
	taille = strlen(E_ligne_inter->prem_mot);
	if (E_mode == INSERT) {
	int j = 0, pos = E_pos_x;
		E_NEXT = E_ligne_courant->pt_suiv;
		E_ligne_courant->pt_suiv = alloc_ligne();
		E_ligne_courant->pt_suiv->prem_mot = (char *)mbkalloc(MAXCAR + 1);
		init_ligne(E_ligne_courant->pt_suiv, MAXCAR + 1);
		E_ligne_courant->pt_suiv->pt_suiv = E_NEXT;
		E_ligne_courant->pt_suiv->pt_prec = E_ligne_courant;
		for (i = pos; i <= taille; i++) {
			E_ligne_courant->pt_suiv->prem_mot[j++] =
			    E_ligne_inter->prem_mot[i];
			E_ligne_inter->prem_mot[i] = '\0';
		}
		E_ligne_courant->prem_mot = E_ligne_inter->prem_mot;
		E_ligne_courant->pt_suiv->attribut = E_ligne_courant->attribut & 0x01;
		E_ligne_courant = E_ligne_courant->pt_suiv;
		E_ligne_inter = E_ligne_courant;
		if (E_NEXT != NULL)
			E_ligne_courant->pt_suiv->pt_prec = E_ligne_courant;
		affiche_rc();
		if (E_pos_y != E_maxligne - 1)
			E_pos_y++;
		zero();
		E_aff_curseur();
	} else if (E_mode == INDENT) {
		if (E_ligne_courant->pt_suiv != NULL) {
			E_ligne_courant = E_ligne_courant->pt_suiv;
			E_ligne_inter = E_ligne_courant;
			affiche_rc();
			if (E_pos_y != E_maxligne - 1)
				E_pos_y++;
			zero();
			E_aff_curseur();
		} else {
			for (i = 0; i <= taille; i++)
				E_ligne_courant->prem_mot[i] = E_ligne_inter->prem_mot[i];
			E_ligne_courant->prem_mot[taille] = '\0';
			E_ligne_courant->pt_suiv = alloc_ligne();
			E_ligne_courant->pt_suiv->prem_mot = (char *)mbkalloc(MAXCAR + 1);
			E_ligne_courant->pt_suiv->pt_prec = E_ligne_courant;
			E_ligne_courant->pt_suiv->pt_suiv = NULL;
			E_ligne_courant->pt_suiv->attribut = E_ligne_courant->attribut & 0x01;
			E_ligne_courant = E_ligne_courant->pt_suiv;
			init_ligne(E_ligne_courant, MAXCAR + 1);
			E_ligne_inter = E_ligne_courant;
			affiche_rc();
			if (E_pos_y != E_maxligne - 1)
				E_pos_y++;
			zero();
			E_aff_curseur();
		}
	}
}

void
	E_traitement(carac)
int	carac;
{
int pos;

	E_del_curseur();
	pos = E_pos_x;
	if (E_mode == INDENT) {
		if (E_ligne_inter->prem_mot[E_pos_x] == '\0')
			add_space(pos, E_ligne_inter);
		indentation(carac, pos, E_ligne_inter);
		aff_indent(pos, E_ligne_inter);
		if (E_pos_x == MAXCAR - 1) {
			E_Printatlastline("Line too long");
			E_aff_curseur();
			return;
		} else {
			droite();
			E_aff_curseur();
		}
	} else {
		E_ligne_courant = E_ligne_inter;
		if (E_ligne_courant->prem_mot[E_pos_x] == '\0')
			add_space(pos, E_ligne_courant);
		if (strlen(E_ligne_courant->prem_mot) >= MAXCAR) {
			E_Printatlastline("Line too long");
			E_aff_curseur();
			return;
		} else {
			insertion(carac, pos, E_ligne_inter);
			aff_insert(pos, E_ligne_inter);
			droite();
			E_aff_curseur();
		}
	}
}

void
	init_ligne(line, nbre)
list_ligne *line;
int nbre;
{
int i;

	line->attribut = NORMAL;
	for (i = nbre - 1; i >= 0; i--)
		line->prem_mot[i] = '\0';
}

list_ligne *
	E_AllocBuf()
{
list_ligne *aloue;

	aloue = (list_ligne *)mbkalloc(sizeof(list_ligne));
	aloue->pt_suiv = aloue->pt_prec = NULL;	
	aloue->prem_mot = NULL;
	return aloue;
}

list_ligne *
	alloc_ligne()
{
list_ligne *aloue;

	E_nbre_ligne++;
	aloue = (list_ligne *)mbkalloc(sizeof(list_ligne)) ;
	aloue->pt_suiv = aloue->pt_prec = NULL;
	aloue->prem_mot = NULL;
	return aloue;
}

void
	clear_carac(position_x, position_y)
int position_x;
int position_y;
{
	XClearArea(display, E_window,
					(position_x + ORIGINEX + E_offnum + E_strtxt) * E_font_width,
					(((position_y + ORIGINEY - 1) * E_interligne) 
					+ 2 * E_font_descent), E_font_width, E_font_height, FALSE);
}

void
	E_cleoln(position_x, position_y)
int position_x;
int position_y;
{
	XClearArea(display, E_window,
					(position_x + ORIGINEX + E_offnum + E_strtxt) * E_font_width,
					(((position_y + ORIGINEY - 1) * E_interligne) 
					+ 2 * E_font_descent), 0, E_font_height, FALSE);
}

void
	E_affiche_page(initline, inity)
list_ligne *initline;
int inity;
{
list_ligne *param = initline;

	while ((inity + ORIGINEY + 1) * E_interligne <= E_dy_win) {
		XClearArea(display, E_window, 0,
		    (((inity + ORIGINEY - 1) * E_interligne) + 2 * E_font_descent),
		    0, E_font_height, FALSE);
		if (param != NULL) {
			if ((param->attribut & 0x01) == NORMAL)
				XCopyGC(display, C_gcText, (GCForeground | GCBackground), E_gc);
			else
				XCopyGC(display, C_gcIconTextInv, (GCForeground | GCBackground),
							E_gc);
			XDrawImageString(display, E_window, E_gc,
									(ORIGINEX + E_offnum + E_strtxt) * E_font_width,
									(inity + ORIGINEY) * E_interligne,
									param->prem_mot, strlen(param->prem_mot));
			if (((param->attribut) >> 4) == BREAKPOINT)
				cercle(inity);
			else
				clear_break(inity);
			if (E_offnum > 0 && E_strtxt == 0)
				E_Printatlinenumber(inity, E_NumeroLigne(param));
			param = param->pt_suiv;
		}
		inity++;
	}
}

void
	affiche_rc()
{
	if (E_pos_y == E_maxligne - 1 || E_scroll_down == TRUE) {
		E_page_courant = E_page_courant->pt_suiv;	/*scrolling haut*/
		E_affiche_page(E_page_courant, 0);	/*a partie de la ligne 0*/
	} else {
		if (E_scroll_up == TRUE) {
			E_page_courant = E_page_courant->pt_prec;
			E_affiche_page(E_page_courant, 0);
		} else {
			E_affiche_page(E_ligne_courant->pt_prec, E_pos_y);
		}
	}
}

void
	aff_indent(pos, line)
int pos;
list_ligne *line;
{
char lettre[2];

	lettre[0] = line->prem_mot[pos];
	lettre[1] = '\0';
	clear_carac(pos, E_pos_y);
	if ((line->attribut & 0x01) == NORMAL)
		XCopyGC(display, C_gcText, (GCForeground | GCBackground), E_gc);
	else
		XCopyGC(display, C_gcIconTextInv, (GCForeground | GCBackground), E_gc);
	XDrawImageString(display, E_window, E_gc,
							(ORIGINEX + E_offnum + E_strtxt + pos) * E_font_width,
							(E_pos_y + ORIGINEY) * E_interligne, lettre, 1);
	if (E_offnum > 0 && E_strtxt == 0)
		E_Printatlinenumber(E_pos_y, E_NumeroLigne(line));
}

void
	aff_insert(pos, line)
int pos;
list_ligne *line;
{
char	finligne[MAXCAR + 1];

	E_cleoln(pos, E_pos_y);
	strcpy(finligne, &line->prem_mot[pos]);
	if ((line->attribut & 0x01) == NORMAL)
		XCopyGC(display, C_gcText, (GCForeground | GCBackground), E_gc);
	else
		XCopyGC(display, C_gcIconTextInv, (GCForeground | GCBackground), E_gc);
	XDrawImageString(display, E_window, E_gc,
							((ORIGINEX + pos + E_offnum + E_strtxt) * E_font_width),
							(E_pos_y + ORIGINEY) * E_interligne, 
							finligne, strlen(finligne));
	if (((line->attribut) >> 4) == BREAKPOINT)
		cercle(E_pos_y);
	else
		clear_break(E_pos_y);
	if (E_offnum > 0 && E_strtxt == 0)
		E_Printatlinenumber(E_pos_y, E_NumeroLigne(line));
}

void
	E_aff_curseur()
{
	if (commande == TRUE)
		XDrawLine(display, E_window, E_gcc,
						(E_pos_x + ORIGINEX + E_offnum + E_strtxt) * E_font_width,
						(E_pos_y + ORIGINEY) * E_interligne + E_font_descent + 1,
						(E_pos_x + ORIGINEX + E_offnum + E_strtxt + 1) * E_font_width,
						(E_pos_y + ORIGINEY) * E_interligne + E_font_descent + 1);
	else 
		XDrawLine(display, E_window, E_gci,
						(E_pos_x + ORIGINEX + E_offnum + E_strtxt) * E_font_width,
						(E_pos_y + ORIGINEY) * E_interligne + E_font_descent + 1,
						(E_pos_x + ORIGINEX + E_offnum + E_strtxt + 1) * E_font_width,
						(E_pos_y + ORIGINEY) * E_interligne + E_font_descent + 1);
}

void
	E_del_curseur()
{
	XClearArea(display, E_window,
					(E_pos_x + ORIGINEX + E_offnum + E_strtxt) * E_font_width - 1,
					(E_pos_y + ORIGINEY) * E_interligne + E_font_descent - 1,
					0, 4, FALSE);
}

void
	E_init_var()
{
	E_nbre_ligne = 0;
	E_ligne_inter = alloc_ligne();
	E_ligne_inter->prem_mot = (char *)mbkalloc(MAXCAR + 1);
	init_ligne(E_ligne_inter, MAXCAR + 1);
	E_page_courant = E_ligne_inter;
	E_debut = E_ligne_inter;
	E_ligne_courant = E_ligne_inter;
	E_ligne_inter->pt_suiv = NULL;
	E_ligne_inter->pt_prec = NULL;
	zero();
	E_pos_y = 0;
}

void
	insertion(c, position, line)
char c;
int position;
list_ligne *line;
{
int i;

	for (i = MAXCAR - 1; i > position; i--)
		line->prem_mot[i] = line->prem_mot[i - 1];
	line->prem_mot[position] = c;
}

void
	indentation(carac, position, line)
char carac;
int position;
list_ligne *line;
{
	line->prem_mot[position] = carac;
}


void
	suppression(position, line)
int position;
list_ligne *line;
{
int i;

	for (i = position; i < MAXCAR; i++)
		line->prem_mot[i] = line->prem_mot[i + 1];
}

void
	add_space(pos, line)
int pos;
list_ligne *line;
{
int i;

	for (i = pos - 1; line->prem_mot[i] == '\0' && pos >= 0; i--)
		line->prem_mot[i] = SPACE;

	if ((line->attribut & 0x01) == NORMAL)
		XCopyGC(display, C_gcText, (GCForeground | GCBackground), E_gc);
	else
		XCopyGC(display, C_gcIconTextInv, (GCForeground | GCBackground), E_gc);
	XDrawImageString(display, E_window, E_gc,
							(ORIGINEX + E_offnum + E_strtxt) * E_font_width,
							(E_pos_y + ORIGINEY) * E_interligne,
							line->prem_mot, strlen(line->prem_mot));
	if (((line->attribut) >> 4) == BREAKPOINT)
		cercle(E_pos_y);
	else
		clear_break(E_pos_y);
}

void
	zero()
{
	E_pos_x = 0;
	if (E_strtxt != 0) {
		E_strtxt = 0;
		E_affiche_page(E_page_courant, 0);
	}
}

void
	droite()
{
	if (E_pos_x >= MAXCAR - 1) {
		E_Printatlastline("Line too long");
		return;
	}
	E_pos_x++;
	if ((E_pos_x - E_strtxt)%(((90 * E_dx_win)/(100 * E_font_width)) + 1) == 0) {
		E_strtxt -= (50 * E_dx_win)/(100 * E_font_width);
		E_affiche_page(E_page_courant, 0);
	}
}

void
	gauche()
{
	if (E_pos_x > 0) {
		E_pos_x--;
		if ((E_pos_x + E_strtxt)%((90 * E_dx_win)/(100 * E_font_width)) == 0) {
			E_strtxt += (50 * E_dx_win)/(100 * E_font_width);
			if (E_strtxt > 0) 
				E_strtxt = 0;
			E_affiche_page(E_page_courant, 0);
		}
	}
}

void
	haut()
{
	if (E_pos_y > 0)
		E_pos_y--;
}

void
	bas()
{
	if (E_pos_y < E_maxligne - 1)
		E_pos_y++;
}

void
	E_insert_ligne()
{
	E_ligne_inter = alloc_ligne();
	E_ligne_inter->prem_mot = (char *)mbkalloc(MAXCAR + 1);
	init_ligne(E_ligne_inter, MAXCAR + 1);
	E_ligne_inter->pt_prec = E_ligne_courant->pt_prec;
	E_ligne_inter->pt_suiv = E_ligne_courant;
	E_ligne_courant->pt_prec->pt_suiv = E_ligne_inter;
	E_ligne_courant->pt_prec = E_ligne_inter;
	E_ligne_courant = E_ligne_inter;
	E_affiche_page(E_ligne_courant, E_pos_y);
	zero();
	E_aff_curseur();
}

list_ligne *
	E_LectFic(nomf)
char *nomf;
{
FILE *fichier;
int taille;
int FinLect = FALSE;
char buffer[BUFSIZ];
int point_buffer = 0;
int point_tab = 0;
int i;

	if (!(fichier = fopen(nomf, "r")))
		return NULL;
	E_ligne_inter = E_ligne_courant;
	while (FinLect != TRUE) {
		if ((taille = fread(buffer, 1, BUFSIZ, fichier)) < BUFSIZ)
			FinLect = TRUE;
		point_buffer = 0;
		while (point_buffer < taille) {
			if (point_tab == MAXCAR || buffer[point_buffer] == '\n' || 
					buffer[point_buffer] == '\r') {
				E_ligne_inter->pt_suiv = alloc_ligne();
				E_ligne_inter->pt_suiv->prem_mot = (char *)mbkalloc(MAXCAR + 1);
				init_ligne(E_ligne_inter->pt_suiv, MAXCAR + 1);
				E_ligne_inter->pt_suiv->pt_prec = E_ligne_inter;
				E_ligne_inter->pt_suiv->pt_suiv = NULL;
				E_ligne_inter = E_ligne_inter->pt_suiv;
				if (buffer[point_buffer] == '\n' || buffer[point_buffer] == '\r')
					point_buffer++;
				point_tab = 0;
			} else if (buffer[point_buffer] == '\t') {
			int j = point_tab % Larg_Tab;
				for (i = 0; i < Larg_Tab - j; i++)
					E_ligne_inter->prem_mot[point_tab++] = ' ';
				point_buffer++;
			} else {
				E_ligne_inter->prem_mot[point_tab++] = buffer[point_buffer++];
			}
		}
	}
	E_ligne_inter = E_ligne_courant;
	fclose(fichier);
	E_ClearBuffer();
	E_affiche_page(E_page_courant, 0);
	return E_debut;
}

list_ligne *
	OpenFic(nom)
char *nom;
{
	E_Effacer();
	return E_LectFic(nom);
}

int
	E_SauveFic(nmf)
char *nmf;
{
FILE *fichier;
list_ligne *deplace = E_debut;
char buffer[BUFSIZ];
int point_buffer = 0, point_tab = 0, size = 0;

	if (!(fichier = fopen(nmf, "w+"))) {
		E_Printatlastline("Cannot open the given file for writting");
		return -1;
	}
	while (deplace != NULL) {
		for (point_tab = 0; deplace->prem_mot[point_tab] != '\0';) {
			if (point_buffer != BUFSIZ)
				buffer[point_buffer++] = deplace->prem_mot[point_tab++];
			else {
				size += fwrite(buffer, sizeof(char), BUFSIZ, fichier);
				point_buffer = 0;
			}
		}
		if (point_buffer != BUFSIZ)
			buffer[point_buffer++] = '\n';
		else {
			size += fwrite(buffer, sizeof(char), BUFSIZ, fichier);
			buffer[0] = '\n';
			point_buffer = 1;
		}
		deplace = deplace->pt_suiv;	/*on passe a la ligne suivante*/
	}
	size += fwrite(buffer, sizeof(char), point_buffer, fichier);
	fclose(fichier);
	return 0;
}

void
	desalouer(line)
list_ligne *line;
{
	--E_nbre_ligne;
	mbkfree((void *)line->prem_mot);
	mbkfree((void *)line);
}

void
	E_delinekey()
{
list_ligne *lignedel = E_ligne_courant;

	E_del_curseur();
	/* Si 1 line */
	if (lignedel->pt_prec == NULL && lignedel->pt_suiv == NULL) {
		desalouer(lignedel);
		E_init_var();	/*creation de la premiere ligne*/
		E_cleoln(E_pos_x, E_pos_y);	/*efface la premiere ligne a l'ecran*/
		E_aff_curseur();
	} else {
		if (lignedel == E_debut)	/*premiere ligne du texte*/ {
			E_ligne_courant = E_ligne_courant->pt_suiv;
			E_debut = E_ligne_courant;
			E_ligne_courant->pt_prec = NULL;
			E_page_courant = E_debut;
			desalouer(lignedel);
			E_affiche_page(E_ligne_courant, 0);
			E_aff_curseur();
		} else if (lignedel->pt_suiv == NULL)	/*derniere ligne du texte*/ {
			E_ligne_courant = E_ligne_courant->pt_prec;
			E_ligne_courant->pt_suiv = NULL;
			desalouer(lignedel);
			haut();
			E_affiche_page(E_ligne_courant, E_pos_y);
			E_aff_curseur();
		} else {	/* ligne dans le texte */
			E_ligne_courant = E_ligne_courant->pt_suiv;
			E_ligne_courant->pt_prec = lignedel->pt_prec;
			lignedel->pt_prec->pt_suiv = E_ligne_courant;
			desalouer(lignedel);
			E_affiche_page(E_ligne_courant, E_pos_y);
			E_aff_curseur();
		}
	}
}

list_ligne *
	deline(line)
list_ligne *line;
{
list_ligne *lignedel = line;
int modif = FALSE;

	E_del_curseur();
	if (lignedel->pt_prec == NULL && lignedel->pt_suiv == NULL) {/*1 line*/
		desalouer(lignedel);
		E_init_var();	/*creation de la premiere ligne*/
		return E_ligne_courant;
	} else {
		if (lignedel == E_debut)	/*premiere ligne du texte*/ {
			if (E_page_courant == E_debut)
				modif = TRUE;
			line = line->pt_suiv;
			E_debut = line;
			line->pt_prec = NULL;
			if (modif == TRUE)
				E_page_courant = E_debut;
			desalouer(lignedel);
			return line;
		} else if (lignedel->pt_suiv == NULL)	/*derniere ligne du texte*/ {
			if (lignedel == E_page_courant)
				E_page_courant = E_page_courant->pt_prec;
			line = line->pt_prec;
			line->pt_suiv = NULL;
			desalouer(lignedel);
			/* cas tres specifique du au test qui sera fait dans E_delbloc*/
			return NULL;
			/* permet de donner la bonne position du curseur a la derniere ligne*/
		} else {	/* ligne dans le texte */
			if (lignedel == E_page_courant)
				E_page_courant = E_page_courant->pt_prec;
			line = line->pt_suiv;
			line->pt_prec = lignedel->pt_prec;
			lignedel->pt_prec->pt_suiv = line;
			desalouer(lignedel);
			return line;
		}
	}
}

int
	E_NumeroLigne(pointeur)
list_ligne *pointeur;
{
list_ligne *deplace = E_debut;
int param = 1;

	while (deplace != pointeur) {
		deplace = deplace->pt_suiv;
		param++;
	}
	return param;
}

void
	clear_attribVideo()
{
list_ligne *chemin = E_debut;

	while (chemin != NULL) {
		chemin->attribut &= 0xf0;
		chemin = chemin->pt_suiv;
	}
}

void
	E_ClearBuffer()
{
	if (E_BufferSauve != NULL) {
		while (E_BufferSauve->pt_suiv != NULL) {
			E_BufferSauve = E_BufferSauve->pt_suiv;
			mbkfree((void *)E_BufferSauve->pt_prec->prem_mot);
			mbkfree((void *)E_BufferSauve->pt_prec);
		}
		mbkfree((void *)E_BufferSauve->prem_mot);
		mbkfree((void *)E_BufferSauve);
	}
	E_BufferSauve = NULL;
}

void
	E_delbloc()
{
list_ligne *point_ligne;
list_ligne *point_buffer;
list_ligne *sauvegarde;
int i, j;
int E_numlignepage;
int code_gestion = 0;
int offset;

	E_numligne = E_NumeroLigne(E_ligne_courant);
	if (E_numligne_debbloc != 0 && E_numligne_finbloc != 0) {
		point_ligne = E_debut;
		for (i = 1; i < E_numligne_debbloc; i++)
			point_ligne = point_ligne->pt_suiv;
		E_numlignepage = E_NumeroLigne(E_page_courant);
		/* test si le bloc est dans la fenetre */
		if (E_numligne_finbloc < E_numlignepage && 
				E_numligne_debbloc > E_numlignepage + E_maxligne - 1)
			code_gestion = 1;
		else {
			/* le bloc est contenu entierement dans la fenetre graphique */
			if (E_numligne_debbloc >= E_numlignepage &&
					E_numligne_finbloc <= E_numlignepage + E_maxligne - 1)
				code_gestion = 2;
			else
				code_gestion = 3;	/* le bloc chevauche notre fenetre */
		}
		E_ClearBuffer();
		for (i = E_numligne_debbloc; i <= E_numligne_finbloc; i++) {
			if (E_BufferSauve == NULL) {
				point_buffer = E_AllocBuf();
				point_buffer->prem_mot = (char *)mbkalloc(MAXCAR + 1);
				init_ligne(point_buffer, MAXCAR + 1);
				E_BufferSauve = point_buffer;
			} else {
				point_buffer->pt_suiv = E_AllocBuf();
				point_buffer->pt_suiv->prem_mot = (char *)mbkalloc(MAXCAR + 1);
				init_ligne(point_buffer->pt_suiv, MAXCAR + 1);
				point_buffer->pt_suiv->pt_prec = point_buffer;
				point_buffer = point_buffer->pt_suiv;
				point_buffer->pt_suiv = NULL;
			}
			for (j = 0; point_ligne->prem_mot[j] != '\0'; j++)
				point_buffer->prem_mot[j] = point_ligne->prem_mot[j];
			sauvegarde = point_ligne->pt_prec;
			/*l'affectation de la E_page_courante est faite ds deline*/
			point_ligne = deline(point_ligne);
		}
		switch (code_gestion) {
			case 1:
				break;
			case 2:
				if (E_numligne < E_numligne_debbloc) {
					/* le curseur est au dessus du bloc marque */
				} else if (E_numligne > E_numligne_finbloc) { 
					/* curseur sous le bloc */
					E_numligne = E_NumeroLigne(E_ligne_courant);
					E_numlignepage = E_NumeroLigne(E_page_courant);
					E_pos_y = E_numligne - E_numlignepage;
				} else {
				/* le curseur est dans le bloc marque */
				/* il reste des lignes non marquees en dessous du bloc */
					offset = 0;
					if (point_ligne == NULL)
						offset = 1;
				/* on teste si on est arrive sur la derniere ligne*/
					E_pos_y = E_numligne_debbloc - E_numlignepage - offset;
					if (offset == 0) {
						E_ligne_courant = point_ligne;
						E_ligne_inter = E_ligne_courant;
					} else {
						E_ligne_courant = sauvegarde;
						E_ligne_inter = E_ligne_courant;
					}
				}
				break;
			case 3:
				if ((E_numligne_finbloc >= E_numlignepage) &&
				    (E_numligne_finbloc < E_numlignepage + E_maxligne - 1)) {
				/* on regarde si la fin du bloc est dans notre fenetre */
					if (E_numligne <= E_numligne_finbloc) {
					/* le curseur est dans le bloc */
						E_pos_y = 0;
						E_ligne_courant = point_ligne;
						E_ligne_inter = point_ligne;
					} else {
						E_numlignepage = E_NumeroLigne(E_page_courant);
						E_numligne = E_NumeroLigne(E_ligne_courant);
						E_pos_y = E_numligne - E_numlignepage;
					}
				} else if ((E_numligne_debbloc > E_numlignepage) &&
					    (E_numligne_debbloc <= E_numlignepage + E_maxligne - 1)) {
				/* on regarde que le de but du bloc est dans notre fenetre */
					if (E_numligne >= E_numligne_debbloc) {
					/* le curseur est dans le bloc */
						E_ligne_courant = point_ligne;
						E_ligne_inter = point_ligne;
						E_numligne = E_NumeroLigne(E_ligne_courant);
						E_numlignepage = E_NumeroLigne(E_page_courant);
						E_pos_y = E_numligne - E_numlignepage;
					} else
						E_pos_y = E_numligne - E_numlignepage;
				} else {
					E_numlignepage = E_NumeroLigne(E_page_courant);
					E_ligne_courant = point_ligne;
					E_ligne_inter = E_ligne_courant;
					E_numligne = E_NumeroLigne(E_ligne_courant);
					E_pos_y = E_numligne - E_numlignepage;
				}
				break;
			default:
				break;
		}
		E_numligne_debbloc = 0;
		E_numligne_finbloc = 0;
		E_del_curseur();
		E_affiche_page(E_page_courant, 0);
		E_aff_curseur();
	}
}


void
	E_CopyBlocToLine()
{
int i;
int po = 0;
int val = 0;
char data[80];
int j;
list_ligne *point_buffer = E_BufferSauve;
list_ligne *point_bloc = NULL;
list_ligne *tete;

	if (E_BufferSauve != NULL)	/* on teste si la copie est possible */ {
		while (point_buffer != NULL) {
			if (point_bloc == NULL)	/* on cree un bloc intermediaire */ {
				point_bloc = alloc_ligne();
				point_bloc->prem_mot = (char *)mbkalloc(MAXCAR + 1);
				init_ligne(point_bloc, MAXCAR + 1);
				point_bloc->pt_prec = NULL;
				tete = point_bloc;
			} else {
				point_bloc->pt_suiv = alloc_ligne();
				point_bloc->pt_suiv->prem_mot = (char *)mbkalloc(MAXCAR + 1);
				init_ligne(point_bloc->pt_suiv, MAXCAR + 1);
				point_bloc->pt_suiv->pt_prec = point_bloc;
				point_bloc = point_bloc->pt_suiv;
				point_bloc->pt_suiv = NULL;
			}
			/*remplissage de notre bloc*/
			for (j = 0; point_buffer->prem_mot[j] != '\0'; j++)
				point_bloc->prem_mot[j] = point_buffer->prem_mot[j];
			point_buffer = point_buffer->pt_suiv;
			val++;
		}
		point_bloc->pt_suiv = E_ligne_courant->pt_suiv;
		if (E_ligne_courant->pt_suiv != NULL)
			point_bloc->pt_suiv->pt_prec = point_bloc;
		E_ligne_courant->pt_suiv = tete;
		tete->pt_prec = E_ligne_inter = E_ligne_courant;
		E_del_curseur();
		E_affiche_page(E_page_courant, 0);
		E_downkey();
		E_aff_curseur();
		sprintf(data, "%d more %s", val, val <= 1 ? "line" : "lines");
		E_Printatlastline(data);
	}
}

int
	E_Effacer()
{
	E_numligne_debbloc = 1;
	E_numligne_finbloc = E_nbre_ligne;
	E_delbloc();
	return 0;
}

void
	cercle(pos)
int pos;
{
	XFillRectangle(display, E_window, E_gcc, 
						(ORIGINEX - 3) + 4,
						(pos + ORIGINEY - 1) * E_interligne 
						+ 2 * (E_font_descent - 1) + 4,
						(int)(1.5 * E_font_width) - 4, E_font_height - 4);
}

void
	clear_break(pos)
int pos;
{
	XClearArea(display, E_window, (ORIGINEX - 3) + 4,
					(pos + ORIGINEY - 1) * E_interligne 
					+ 2 * (E_font_descent - 1) + 4,
					(int)(1.5 * E_font_width) - 4, E_font_height - 4, FALSE);
}

int
	E_BreakPoint()
{
	E_ligne_courant->attribut ^= 0x10;
	if (((E_ligne_courant->attribut) >> 4) == BREAKPOINT) {
		cercle(E_pos_y);
		return E_NumeroLigne(E_ligne_courant);
	}
	clear_break(E_pos_y);
	return 0;
}

void
	clear_attribBreak()
{
list_ligne *chemin = E_debut;

	while (chemin != NULL) {
		chemin->attribut &= 0x0f;
		chemin = chemin->pt_suiv;
	}
	E_del_curseur();
	E_affiche_page(E_page_courant, 0);
	E_aff_curseur();
}

void
	E_EndText()
{
list_ligne *deplace = E_debut;
int ligne_ecran;

	while (deplace->pt_suiv != NULL)
		deplace = deplace->pt_suiv;
	E_ligne_courant = deplace;
	E_ligne_inter = deplace;
	for (ligne_ecran = 0; 
			ligne_ecran < E_maxligne - 1 && deplace->pt_prec != NULL;
			ligne_ecran++)
		deplace = deplace->pt_prec;
	E_page_courant = deplace;
	E_del_curseur();
	zero();
	E_pos_y = ligne_ecran;
	E_affiche_page(E_page_courant, 0);
	E_aff_curseur();
}


int
	gotoline(num)
int num;
{
list_ligne *deplace = E_debut;
int i;

	if (num > E_nbre_ligne)
		return ;
	for (i = 0; i < num - 1; i++)
		deplace = deplace->pt_suiv;
	E_ligne_courant = E_ligne_inter = deplace;
	for (i = 0; i < (E_maxligne - 1) / 2 && deplace != E_debut; i++)
		deplace = deplace->pt_prec;
	E_page_courant = deplace;
	E_del_curseur();
	zero();
	E_pos_y = i;
	E_affiche_page(E_page_courant, 0);
	E_aff_curseur();
}

int
	E_Ligne(num)
int num;
{
list_ligne *deplace = E_debut;
static list_ligne *memorise;
extern BOOL D_FinInterp;
int i;

	if (num > E_nbre_ligne)
		return;
	if (memorise != NULL)
		memorise->attribut &= 0xF0; /* NORMAL */
	if (D_FinInterp == TRUE) {
		memorise = NULL;
		gotoline(num);
		return;
	}
	for (i = 0; i < num - 1; i++)
		deplace = deplace->pt_suiv;
	deplace->attribut |= 0x01; /* INVERSE */
	memorise = deplace;
	E_ligne_courant = E_ligne_inter = deplace;
	for (i = 0; i < (E_maxligne - 1) / 2 && deplace != E_debut; i++)
		deplace = deplace->pt_prec;
	E_page_courant = deplace;
	E_del_curseur();
	zero();
	E_pos_y = i;
	E_affiche_page(E_page_courant, 0);
	E_aff_curseur();
}

void
	E_BlocToBuffer()
{
int i;
int j;
list_ligne *point_ligne;
list_ligne *point_buffer;

	if (E_numligne_debbloc != 0 && E_numligne_finbloc != 0) {
		point_ligne = E_debut;
		for (i = 1; i < E_numligne_debbloc; i++)
			point_ligne = point_ligne->pt_suiv;
		E_ClearBuffer();
		for (i = E_numligne_debbloc; i <= E_numligne_finbloc; i++) {
			if (E_BufferSauve == NULL) {
				point_buffer = E_AllocBuf();
				point_buffer->prem_mot = (char *)mbkalloc(MAXCAR + 1);
				init_ligne(point_buffer, MAXCAR + 1);
				E_BufferSauve = point_buffer;
			} else {
				point_buffer->pt_suiv = E_AllocBuf();
				point_buffer->pt_suiv->prem_mot = (char *)mbkalloc(MAXCAR + 1);
				init_ligne(point_buffer->pt_suiv, MAXCAR + 1);
				point_buffer->pt_suiv->pt_prec = point_buffer;
				point_buffer = point_buffer->pt_suiv;
				point_buffer->pt_suiv = NULL;
			}
			for (j = 0; point_ligne->prem_mot[j] != '\0'; j++)
				point_buffer->prem_mot[j] = point_ligne->prem_mot[j];
			point_ligne = point_ligne->pt_suiv;
		}
	}
	clear_attribVideo();
	E_numligne_debbloc = 0;
	E_numligne_finbloc = 0;
	E_affiche_page(E_page_courant, 0);
	E_aff_curseur();
}


void
	E_Printatlinenumber(data, nbre)
int data;
int nbre;
{
char message[6];
int i;

	sprintf(message, "%-.4d", nbre);
	for (i = 0; message[i] == '0'; i++)
		message[i] = ' ';
	XDrawImageString(display, E_window, E_gc, ORIGINEX * E_font_width,
							(data + ORIGINEY) * E_interligne, 
							message, strlen(message));
}

void
	E_updateBp()
{
int i;
list_ligne *line;

	DelAllBp();
	for (line = E_debut, i = 1; line != NULL; line = line->pt_suiv, i++)
		if (((line->attribut) >> 4) == BREAKPOINT)
			AddBp(i);
}
