/******************************************************************************

    MODUL
	edit.c

    DESCRIPTION
	Everything for editing like DEL, BS, INDENT, DELINE, INSLINE, ...

    NOTES

    BUGS

    TODO

    EXAMPLES

    SEE ALSO

    INDEX

    HISTORY
	14. Nov 1992	ada created

******************************************************************************/

/**************************************
		Includes
**************************************/
#include "defs.h"
#include "clipboard.h"


/**************************************
	    Globale Variable
**************************************/


/**************************************
      Interne Defines & Strukturen
**************************************/


/**************************************
	    Interne Variable
**************************************/


/**************************************
	   Interne Prototypes
**************************************/
Prototype void do_bs	     (void);
Prototype void do_del	     (void);
Prototype void do_remeol     (void);
Prototype void do_split      (void);
Prototype int  do_join	     (void);
Prototype void do_reformat   (int);
Prototype void do_insertmode (void);
Prototype void do_insline    (void);
Prototype void do_deline     (void);
Prototype void do_tlate      (void);
Prototype void do_justify    (void);
Prototype void do_unjustify  (void);
Prototype void do_indent     (void);
Prototype void do_inslines   (void);
Prototype void do_delete     (void);
Prototype void do_delines    (void);
Prototype void do_undeline   (void);
Prototype void do_space      (void);
Prototype void do_clipins    (void);
Prototype void do_return     (void);


void do_bs (void)
{
    ED	 * ep  = Ep;
    RP	 * rp  = ep->win->RPort;
    short  i,
	   col = ep->column;
    Column right;
    Bool   is_bs = (av[0][0] == 'b');

    if ((Current[col] && !is_bs) || (col && is_bs))
    {
	if (is_bs)
	{
	    movmem (Current + col, Current + col - 1, Clen - col + 1);

	    col --;
	    ep->column --;

	} else
	    movmem (Current + col + 1, Current + col, Clen - col);

	Clen --;

	i = ep->line;
	right = ep->topcolumn + Columns;

	if (!Nsu) {                         /* PATCH_NULL [09-Dec-92] : line added */
	    if (col < ep->topcolumn)
	    {
		text_adjust (FALSE);
	    } else
	    {
		if (is_inblock (i, right))
		{
		    SetAPen (rp, BLOCK_FPEN);
		    SetBPen (rp, BLOCK_BPEN);
		} else
		{
		    SetAPen (rp, TEXT_FPEN);
		    SetBPen (rp, TEXT_BPEN);
		}

		SetWrMsk (rp, BLOCK_MASK);

		i -= ep->topline;

		ScrollRaster(rp, Xsize, 0,
		    COL(col - ep->topcolumn),
		    ROW(i),
		    Xpixs,
		    ROW(i + 1) - 1
		);

		if (Clen >= right)
		{
		    right --;

		    Move (rp, COLT(right), ROWT(i));
		    Text (rp, Current + right, 1);
		}
	    }
	} /* if !Nsu */ 		    /* PATCH_NULL [09-Dec-92] : line added */

	if (!globalflags.Comlinemode && ep->config.wordwrap)
	    do_reformat(0);
    } else
    {
	globalflags.Abortcommand = 1;
    }
} /* do_bs */


void do_remeol (void)
{
    Current[Clen = Ep->column] = 0;

    text_sync ();
    text_redisplaycurrline ();
} /* do_remeol */


void do_split (void)              /* split line in two at cursor pos */
{
    ubyte buf[MAXLINELEN];
    ED	* ep		   = Ep;
    RP	* rp		   = ep->win->RPort;
    char  onLastLine;

    strcpy ((char *)buf, (char *)Current+ep->column);
    Current[Clen = ep->column] = '\0';

    text_sync ();

    SetAPen (rp, TEXT_BPEN);
    SetWrMsk (rp, -1);

    if (!Nsu)
	RectFill (rp, COL(0), ROW(ep->line-ep->topline),
	       Xpixs, ROW(ep->line-ep->topline+1)-1);

    SetAPen (rp, TEXT_FPEN);

    text_displayseg (ep->line - ep->topline, 1);

    onLastLine = (ep->line == ep->lines-1);
    do_downadd ();

    if (!onLastLine)
	do_insline ();

    strcpy ((char *)Current, (char *)buf);
    Clen = strlen ((char *)Current);

    text_sync ();
    text_displayseg (ep->line - ep->topline, 1);

    do_up ();
} /* do_split */


int do_join (void)
{
    int   i = Clen, j;
    ED * ep = Ep;

    /* Check if there is a line below and the length of both lines */
    if (ep->line + 1 < ep->lines &&
		LINELEN(ep,ep->line+1)+i <= MAXLINELEN-2)
    {
	/* Add a space */
	if (i && Current[i-1] != ' ')
	    Current[i++] = ' ';

	/* Copy the line */
	strcpy((char *)Current+i, GETTEXT(ep,ep->line+1));

	/* Find first nonspace */
	for (j = i; Current[j] == ' '; ++j);
	/* Find last space */
	for (; i >= 0 && Current[i] == ' '; --i);

	/* Too many spaces ? */
	if (j > i+2)
	    movmem (Current+j, Current+i+2, strlen((char *)Current+j)+1);

	/* new length */
	Clen = strlen ((char *)Current);

	/* redisplay */
	text_sync ();
	text_displayseg (ep->line - ep->topline, 1);

	i = text_lineno ();

	do_down ();
	do_deline ();

	if (i != text_lineno ())
	    do_up ();

	return(1);
    }

    return(0);
} /* do_join */


/*
 * n == -1  :	force reformat entire paragraph
 * n ==  0  :	only until line equalizes (from text_write())
 *
 * What is a paragraph?   A paragraph ends whenever the left justification
 * gets larger, or on a blank line.
 */

void do_reformat (int n)
{
    char * str;
    ED	 * ep = Ep;
    RP	 * rp = ep->win->RPort;
    int    nlok;   /* Next Line ok ? */
    int    lnsc;   /* LastNS of Current */
    int    fnst;   /* FirstNS of next Line */
    int    fnsc;    /* FirstNS of Current */
    int    column  = ep->column;
    int    srow    = ep->line;
    int    crow    = srow;
    int    erow    = srow;
    short  dins    = 0; 	/* relative insert lines/delete lines	*/
    char   moded   = 0; 	/* any modifications done at all?	*/
    char   checked = 0; 	/* for cursor positioning.		*/

    if (ep->config.margin == 0)
	ep->config.margin = 75;

    Nsu ++;

    for (;;)
    {
	str = GETTEXT(ep,ep->line+1);
	fnst = 0;
	fnsc = firstns((char *)Current);
	nlok = (ep->line + 1 < ep->lines && fnsc >= (fnst=firstns(str)));
	if (ep->config.wwcol >= 0)
	    fnst = fnsc = ep->config.wwcol;
	if (nlok && str[0] == 0)
	    nlok = 0;
	lnsc = lastns((char *)Current);
	if (lnsc < ep->config.margin)
	{    /* space at end of line for marg-lnsc-2 letter word   */
	    if (nlok == 0)        /* but no more data to joinup   */
		break;		  /* done */
	    if (ep->config.margin - lnsc - 2 >= wordlen(str+fnst))
	    {
		ep->column = 0;
		Clen = lastns((char *)Current);
		if (Current[Clen])
		    ++Clen;
		moded = 1;
		--dins;
		if (do_join())
		    continue;
		++dins;

		error ("reformat:\nMargin too big");
		break;
	    }
	    if (n == 0)        /* if couldn't mod line, and text_write, don't update any more */
		break;
	    do_down ();
	    erow = ep->line;
	    continue;
	}
				/* no space, need to split	*/
				/* find start of prev word	*/
	for (;;)
	{
	    int i = lnsc;
	    while (i && Current[i] != ' ')
		--i;
	    lnsc = i;
	    if (i >= ep->config.margin)
	    {
		while (i && Current[i] == ' ')
		    --i;
		if (i < ep->config.margin)
		    break;
		lnsc = i;
	    } else
		break;
	}

	/* Word too long */
	if (wordlen((char *)Current+lnsc) >= ep->config.margin)
	{
	    error ("reformat:\nWord too long");
	    break;
	}

	if (lnsc)
	{	      /* ok to split at word	      */
	    ++lnsc;
	    ++dins;
	    ep->column = lnsc;
	    do_split (); /* Split at point LNSC          */
	    do_down ();          /* must insert proper amount?   */
	    {
		int indent = (nlok == 0) ? fnsc : fnst;
		if (ep->config.wwcol >= 0)
		    indent = ep->config.wwcol;
		if (!checked)
		{
		    checked = 1;
		    if (lnsc <= column)
		    {	/* if split before cursor   */
			column = column - ep->column + indent;
			++crow;
		    }
		}
		if (Clen + indent < 253)
		{
		    movmem(Current, Current + indent,
			    strlen((char *)Current)+1);
		    setmem(Current, indent, ' ');
		    Clen += indent;
		}
	    }
	    erow = ep->line;
	    continue;
	}

	if (n == 0)
	    break;

	do_down ();
    }

    if (column < 0 || column > 200)
	column = 0;
    if (srow >= ep->lines)
    {
	srow = ep->lines - 1;
	goto ra;
    }
    if (dins || srow < ep->topline || srow >= ep->topline + Lines)
    {
ra:
	text_sync ();

	Nsu --;

	ep->line = crow;
	ep->column = column;
	text_load ();

	text_adjust (TRUE);
    } else
    {
	text_sync ();

	Nsu --;

	ep->line = crow;
	ep->column = column;

	text_load ();

	if (erow != srow)
	{
	    if (!text_adjust (FALSE))
	    {
		erow ++;

		if (erow - ep->topline > Lines)
		    erow = ep->topline + Lines;

		SetAPen(rp, TEXT_BPEN);
		SetWrMsk (rp, -1);

		RectFill(rp, COL(0), ROW(srow - ep->topline),
		    Xpixs, ROW(erow - ep->topline)-1);

		SetAPen(rp, TEXT_FPEN);

		text_displayseg(srow - ep->topline, erow - srow);
	    }
	} else
	{
	    text_sync ();

	    if (moded)
		text_redisplaycurrline ();
	}
    }
    if (column > Clen)
    {
	setmem(Current+Clen, column - Clen, ' ');
	Current[column] = 0;
    }
    ep->column = column;
} /* do_reformat */


void do_insline (void)
{
    ubyte *ptr;
    ED *ep = Ep;

    ep->modified = 1;

    text_sync ();

    if (makeroom (32))
    {
	ptr = allocline (1);

	bmovl(ep->list+ep->line, ep->list+ep->line+1,ep->lines-ep->line);
	GETTEXT(ep,ep->line) = ptr;

	ep->lines ++;

	if (ActualBlock.ep == ep)
	{
	    if (ep->line <= ActualBlock.start_line)
		ActualBlock.start_line ++;
	    if (ep->line <= ActualBlock.end_line)
		ActualBlock.end_line ++;
	}
    } else
    {
	nomemory ();
    }

    text_load ();

    if (Nsu == 0)
    {
	scroll_display (0, -1, 0, ep->line, MAXLINELEN, ep->topline+Lines);
	text_displayseg (ep->line - ep->topline, 1);
    }
} /* do_insline */


void do_deline (void)
{
    int delline, eline;
    ED *ep = Ep;

    /* store line for later UNDO */
    strcpy ((char *)Deline, (char *)Current);

    if (ep->lines > 1)
    {
	ep->modified = 1;

	text_sync ();

	/* remove line */
	freeline (GETTEXT(ep,ep->line));
	bmovl (ep->list+ep->line+1, ep->list+ep->line, ep->lines-ep->line-1);

	/* adjust block */
	if (ActualBlock.ep == ep)
	{
	    if (ep->line < ActualBlock.start_line)
		ActualBlock.start_line --;

	    if (ep->line <= ActualBlock.end_line)
		ActualBlock.end_line --;
	}

	/* remember line we deleted */
	delline = ep->line;

	/* line was last one */
	if (ep->line >= --ep->lines)
	{
	    /* move up one line */
	    --ep->line;

	    /* get the line into current */
	    text_load ();

	    /* line now below topline ? */
	    if (ep->line < ep->topline)
	    {
		/* update screen if allowed */
		if (!Nsu)
		{
		    /* find new position */
		    ep->topline = ep->line - (Lines>>1);

		    if (ep->topline < 0)
			ep->topline = 0;

		    text_redisplay ();
		}

		return;
	    }
	}

	/* get line */
	text_load ();

	/* update display */
	if (!Nsu)
	{
	    eline = ep->lines +1;
	    scroll_display (0, 1, 0, delline, MAXLINELEN, eline);
	}
    } else
    {
	/* no more lines in the text */
	do_firstcolumn ();
	do_remeol ();
	ep->modified = 0;
    }
} /* do_deline */


void do_tlate (void)
{
    ubyte * ptr = av[1];
    ED	  * ep	= Ep;
    ubyte   c	= Current[ep->column];

    if (c == 0)
	c = ' ';

    switch (*ptr)
    {
	case '+':
	    c += strtol ((char *)ptr+1, NULL, 0);
	    break;

	case '-':
	    c -= strtol ((char *)ptr+1, NULL, 0);
	    break;

	case '"':
	    c = ptr[1];
	    break;

	case 'u':
	case 'U':
	    c = toupper (c);
	    break;

	case 'l':
	case 'L':
	    c = tolower (c);
	    break;

	default:
	    c = strtol ((char *)ptr, NULL, 0);
    }

    if (c)
    {
	if (Current[ep->column] == 0)
	{
	    Clen = ep->column + 1;
	    Current[Clen] = 0;
	}

	Current[ep->column] = c;

	if (!Nsu)
	{
	    LINE * text_line;

	    /* get the actual line */

	    text_line = GETLINE(ep,ep->line);

	    /* if the char fits into the line, just copy it (ie. avoid
	       text_sync(). Else call text_sync() */

	    if (ep->column < LENGTH(text_line))
		(CONTENTS(text_line))[ep->column] = c;
	    else
		text_sync ();

	    /* Delete the character on screen. First, find the color
	       we need for this operation, then draw over it */

	    if (is_inblock (ep->line, ep->column) & BP_INSIDE)
		SetAPen (ep->win->RPort, BLOCK_BPEN);
	    else
		SetAPen (ep->win->RPort, TEXT_BPEN);

	    SetWrMsk (ep->win->RPort, -1);
	    RectFill (ep->win->RPort, COL(ep->column), ROW(ep->line),
			    COL(ep->column+1)-1, ROW(ep->line+1)-1);

	    /* redraw that character */

	    redraw_textlineseg (ep->line, ep->column, ep->column + 1);
	}
    }
} /* do_tlate */


void do_justify (void)
{
    ED *ep = Ep;
    short firstnb, lastnb, i, n, fill, c, sp;
    short changed = FALSE;

    switch(av[1][0])
    {
	case 'c':
	break;

	case 'f':
	    firstnb = firstns((char *)Current);
	    lastnb = lastns((char *)Current);
	    if (firstnb < lastnb && ep->config.margin < MAXLINELEN-1)
	    {
		n = 0;
		i = firstnb;
		while (i <= lastnb)
		{
		    while ((c = Current[i]) && c != ' ')
			i++;
		    if (i <= lastnb)
		    {
			n++;
			while (Current[i] == ' ')
			    i++;
		    }
		}
		fill = ep->config.margin - lastnb - 1;
		i = firstnb;
		Current[lastnb + 1] = 0;
		if (n > 0 && fill > 0)
		    changed = TRUE;
		while (n > 0 && fill > 0 && Current[i])
		{
		    while ((c = Current[i]) && c != ' ')
			i++;
		    sp = fill / n;
		    movmem (&Current[i], &Current[i + sp],
			    strlen((char *)&Current[i]) + 1);
		    memset ((char *)&Current[i], ' ', sp);
		    while (Current[i] == ' ')
			i++;
		    fill -= sp;
		    n--;
		}
	    }
	break;

	default:
	break;
    }

    if (changed)
    {
	text_sync ();
	text_redisplaycurrline ();
    }
} /* do_justify */


void do_unjustify (void)
{
    short i, j, waswhite = FALSE;
    ubyte c;

    for (i = 0; Current[i] == ' '; i++);

    for (j = i; Current[i]; i++)
    {
	c = Current[j] = Current[i];

	if (c != ' ' || !waswhite)
	    j++;

	waswhite = (c == ' ');
    }

    Current[j] = 0;

    if (i != j)
    {
	text_sync ();
	text_redisplaycurrline ();
    }
} /* do_unjustify */


void do_indent (void)
{
    Line   start,
	   end;
    Column column;
    int    indent,
	   dir,
	   align,
	   len,
	   curr_indent,
	   leading,
	   trailing,
	   t;
    char * ptr;
    RP	 * rp;
    LINE * linelist;

    /* decode range */
    ptr = av[1];

    start = end = -1;

    while (*ptr)
    {
	if (*ptr == '.')
	{
	    start = end = Ep->line;
	    break;
	} else if (isdigit(*ptr))
	{
	    if (start == -1)
		start = atoi (ptr);
	    else end = atoi (ptr);

	    while (isdigit(*ptr)) ptr ++;

	    ptr --;
	} else if (*ptr == '$')
	{
	    if (start == -1)
		start = get_pong (*ptr - '0');
	    else
		end = get_pong (*ptr - '0');
	} else if (*ptr == 'b')
	{
	    if (!block_ok())
	    {
		error ("indent block:\nNo block specified");
		return ;
	    }

	    if (!ptr[1])
	    {
		start = ActualBlock.start_line;
		end = ActualBlock.end_line;
	    } else
	    {
		ptr ++;

		if (*ptr == 's')
		    indent = ActualBlock.start_line;
		else
		    indent = ActualBlock.end_line;

		if (start == -1)
		    start = indent;
		else
		    end = indent;
	    }
	} else if (*ptr == 't')
	{
	    start = 1;
	    end = Ep->lines;
	} else if (*ptr == '_')
	{
	    if (start == -1)
		start = Ep->lines;
	    else
		end = Ep->lines;
	}

	ptr ++;
    } /* while (*ptr) */

    if (start == -1)
    {
	error ("indent:\ncannot evaluate start-line");
	return ;
    }

    if (end == -1) end = start;

    if (start > end)
    {
	start ^= end;	    /* Swap ! 8-O */
	end   ^= start;
	start ^= end;
    }

    /* Now find out how to indent */

    ptr = av[2];

    dir = 1;		/* indent, i.e. insert spaces */
    align = 0;		/* just insert `indent' spaces */
    indent = -1;
    column = 0;

    while (*ptr)
    {
	if (*ptr == '-')
	    dir = -1;		/* outdent line, i.e. delete spaces */
	else if (*ptr == '.')
	    align = 1;		/* align line to a multiple of `indent' */
	else if (*ptr == 't')
	    indent = Ep->config.tabstop;
	else if (isdigit(*ptr))
	{
	    indent = atoi (ptr);

	    while (isdigit(*ptr)) ptr++;
	    ptr --;
	} else if (*ptr == 'c')
	    column = Ep->column;

	ptr ++;
    } /* while (*ptr) */

    if (indent == -1)
    {
	error ("indent:\nCannot evaluate indent-amount");
	return ;
    }

    text_sync ();

    /* Note : If the line contains less spaces than indent specifies and
       the user wants to outdent, the line is left-aligned, i.e. no chars
       except spaces are deleted ! This is also true for indent, i.e. no
       chars are moved over the right border (MAXLINELEN chars). */

    linelist = Ep->list + start;

    for (t=start; t <= end; t ++, linelist ++)
    {
	strcpy (Current, linelist[0]);
	Clen = strlen (Current);

	if (Clen <= column) continue;

	ptr = Current + column;

	while (*ptr == ' ') ptr ++;

	if (!*ptr) continue;          /* Empty line */

	leading  = (int)ptr - (int)Current;
	trailing = MAXLINELEN-1 - Clen;

	/* Should I align the line to a multiple of indent or just
	    insert/delete indent spaces ? */
	if (align)
	{
	    /* use appropriate difference */
	    if (dir > 0)
		curr_indent = indent - (leading % indent);
	    else
	    {
		curr_indent = leading % indent;

		if (!curr_indent)
		    curr_indent = indent;
	    }
	} else curr_indent = indent;

	len = strlen (ptr) + 1;

	if (dir > 0)
	{
	    if (trailing < curr_indent)
		curr_indent = trailing;

	    if (!curr_indent) continue;

	    movmem (ptr, ptr+curr_indent, len);
	    setmem (ptr, curr_indent, ' ');
	} else
	{
	    if (leading < curr_indent)
		curr_indent = leading;

	    if (!curr_indent) continue;

	    movmem (ptr, ptr-curr_indent, len);
	}

	Clen = strlen (Current);
	len  = strlen (linelist[0]);

#ifdef DEBUG
printf ("Old len %d  New Len %d     BlenOld %d  BlenNew %d\n",
	len, Clen, ((len + 8) & ~7), ((Clen + 8) & ~7));
#endif

	/* Find out if we have to allocate new memory */
	/* Clen is total length in bytes while len is only strlen() */
	/* TODO: Ain't work yet */
	/*if ((((Clen + 8) & ~7) != ((len + 8) & ~7)))
	{*/
	    ptr = allocline (Clen + 1);

	    if (!ptr)
	    {
		nomemory ();
		globalflags.Abortcommand = 1;
		break;
	    }

	    freeline (linelist[0]);
	    linelist[0] = ptr;
	/*}*/

	strcpy (ptr, Current);
    } /* for (t = start; t <= end; t ++, linelist ++) */

    Ep->modified = 1;

    text_load ();

    /* Don't display if there is nothing to display */
    if (end < Ep->topline)
	return;

    if (start < Ep->topline)
    {
	start = 0;
	t = end - Ep->topline +1;
    } else
    {
	t = end - start +1;
	start -= Ep->topline;

	if (start >= Lines)
	    return;
    }

    if (t > Lines)
	t = Lines;

    if (!Nsu)
    {
	rp = Ep->win->RPort;

	end = start + t-1;

	/* only clear area, if there is a line outside the block */
	if (!is_inblock (start, -1) || !is_inblock (end, -1))
	{
	    SetAPen (rp, TEXT_BPEN);
	    SetWrMsk (rp, BLOCK_MASK);
	    RectFill (rp, Xbase, ROW(start), Xpixs, ROW(start+t)-1);
	}

	if (!text_sync ())
	    text_displayseg (start, t);
    }
} /* do_indent */


void do_inslines (void)
{
     int lines = atoi (av[1]);

     if (lines <= 0) return;

     while (lines)
     {
	  do_insline ();
	  lines --;
     }

} /* do_inslines */


void do_delete (void)
{
    char * ptr, * hptr;

    hptr = ptr = Current + Ep->column;

    if (*hptr == ' ')
	while (*hptr == ' ') hptr ++;
    else while (*hptr != ' ') hptr ++;

    strcpy (ptr, hptr);

    text_sync ();
    text_redisplaycurrline ();
} /* do_delete */


void do_delines (void)
{
     int t;

     t = atoi (av[1]);

     for ( ; t >= 0; t--)
	  do_deline ();
} /* do_delines */


/*
 *  Commands submitted by Markus Wenzel
 */

void do_undeline (void)
{
   do_insline ();
   text_load ();

   strcpy((char *)Current, (char *)Deline);

   text_sync ();
   text_displayseg (Ep->line - Ep->topline, 1);
} /* do_undeline */


void do_clipins (void)
{
    struct IOClipReq * ior;
    struct cbbuf * buf;

    if (!(ior = CBOpen (0)) )
	return;

    if (CBQueryFTXT (ior))
    {
	buf = CBReadCHRS (ior);

	if (buf)
	{
	    text_write ((ubyte *)buf->mem);
	    CBFreeBuf (buf);
	}

	CBReadDone (ior);
    }

    CBClose (ior);
} /* do_clipins */


void do_space (void)
{
    ED * ep = Ep;
    int  insmode = ep->config.insertmode;

    ep->config.insertmode = 1;
    text_write (" ");
    ep->config.insertmode = insmode;
} /* do_space */


void do_return (void)
{
    char   buf[MAXLINELEN];
    char * partial;

    if (globalflags.Comlinemode)
    {
	strcpy (buf, (char *)Current);

	partial = esc_partial;	/* PATCH_NULL: P -> esc_p */
	esc_partial = NULL;	/* PATCH_NULL: P -> esc_p */

	escapecomlinemode ();

	if (partial)
	{
	    if (do_command (buf))
		do_command (partial);

	    free(partial);
	} else
	    do_command (buf);
    } else
    {
	if (Ep->config.autoindent)
	{   /* If user want's autoindent */
	    short  indent;  /* how much */
	    short  line;    /* Line-no. */
	    char * ptr;     /* pointer to Ep->list[line] */

	    text_sync ();   /* store actual line */

	    /* Start with current line */
	    indent = 0;
	    ptr = (char *)Current;

	    /* Find 1. nonspace ... */
	    while (isspace (*ptr))
	    {
		ptr ++;
		indent ++;
	    }

	    /* ... but not '\0'. In this case the line is empty and
	       indent is therefore 0 */
	    if (!*ptr)
		indent = 0;

	    /* Try on, if indent is zero, line is empty and there are more
	       lines on top */
	    if (!indent && !*ptr && Ep->line)
	    {
		line = Ep->line - 1;

		/* Until 1. line */
		while (line)
		{
		    /* Try every line */
		    ptr = GETTEXT(Ep,line);
		    indent = 0;

		    while (isspace (*ptr))
		    {
			ptr ++;
			indent ++;
		    }

		    if (indent || *ptr)
			break;

		    line --;
		}
	    }

	    /* Not at last position in line ? then we have to split and
	       indent the rest */
	    if (Ep->column != Clen)
	    {
		/* Split line, move to next line but shouldn't show this */
		do_split ();
		do_down ();

		/* Indent new line */
		if (indent > Ep->column)
		    indent -= indent - Ep->column;

		if (indent > 0)
		{
		    movmem (Current, Current+indent, Clen+1);
		    setmem (Current, indent, ' ');
		    Clen += indent;
		    Ep->column = indent;
		} else
		    Ep->column = 0;

		Current[Clen] = 0;

		/* and position cursor */
		text_sync ();

		/* Show result */
		text_redisplaycurrline ();
	    } else
	    {
		if (Ep->line != Ep->lines-1)
		{
		    do_down ();
		    do_insline ();

		    Ep->column = indent;
		    text_sync ();
		} else
		{
		    do_split ();
		    Ep->column = indent;
		    text_sync ();
		    do_down ();
		}
	    }
	} else
	{
	    Ep->column = 0;
	    text_sync ();
	    do_downadd ();
	}
    } /* !Comlinemode */
} /* do_return */


/******************************************************************************
*****  ENDE edit.c
******************************************************************************/
