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

    MODUL
	cursor.c

    DESCRIPTION
	All routines that only move the cursor.

    NOTES

    BUGS

    TODO

    EXAMPLES

    SEE ALSO

    INDEX

    HISTORY
	04. Oct 1992	ada created

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

/**************************************
		Includes
**************************************/
#include <defs.h>


/**************************************
	    Globale Variable
**************************************/
Prototype void do_up		      (void);
Prototype void do_scrolldown	      (void);
Prototype void do_scrollup	      (void);
Prototype void do_down		      (void);
Prototype void do_page		      (void);
Prototype void do_downadd	      (void);
Prototype void do_left		      (void);
Prototype void do_right 	      (void);
Prototype void do_tab		      (void);
Prototype void do_backtab	      (void);
Prototype void do_top		      (void);
Prototype void do_bottom	      (void);
Prototype void do_firstcolumn	      (void);
Prototype void do_firstnb	      (void);
Prototype void do_lastcolumn	      (void);
Prototype void do_goto		      (void);
Prototype void do_screentop	      (void);
Prototype void do_screenbottom	      (void);
Prototype void do_wleft 	      (void);
Prototype void do_wright	      (void);
Prototype void do_col		      (void);
Prototype void do_scrollleft	      (void);
Prototype void do_scrollright	      (void);
Prototype void do_match 	      (void);
Prototype void do_ping		      (void);
Prototype void do_pong		      (void);
Prototype void do_undo		      (void);
Prototype int  get_pong 	      (int);
Prototype void escapecomlinemode      (void);
Prototype void do_esc		      (void);
Prototype void do_recall	      (void);
Prototype void markerkill	      (ED *);

Prototype char	* HistoBuff[];
Prototype short   NumHistoLines;
Prototype short   HistoLine;


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


/**************************************
	    Interne Variable
**************************************/
static struct TextMarker marker[PINGDEPTH];

/* TODO: replace define by function for infinite history */

#define MaxHistoLines	    40

/* HistoBuff is filled [0..NumHistoLines-1], NumHistoLines is in
   [0..MaxHistoLines], HistoLine is in [0..NumHistoLines]. If NumHistoLines
   is 0, then the HistoryBuffer is empty. */

char * HistoBuff[MaxHistoLines];
short  NumHistoLines;
short  HistoLine;


/**************************************
	   Interne Prototypes
**************************************/



void do_up (void)
{
    ED * ep = Ep;
    RP * rp = ep->Win->RPort;

    if (!Comlinemode) {
	if (ep->Line) {
	    text_sync ();
	    ep->Line --;
	    text_load ();

	    if (Ep->Line < Ep->Topline) {
		if (Nsu == 0) {
		    ScrollRaster (rp, 0, -Ysize, COL(0), ROW(0), Xpixs, Ypixs);
		    ep->Topline --;
		    text_displayseg (0, 1);
		}
	    }
	} else {
	    Abortcommand = 1;
	}
    } else {
	if (HistoLine) {
	    HistoLine --;

	    strcpy (Current, HistoBuff[HistoLine]);

	    Clen = strlen (Current);

	    while (ep->Column > Clen)
		Current[Clen ++] = ' ';

	    Current[Clen] = 0;

	    text_redisplaycurrline ();
	}
    }
} /* do_up */


void do_scrolldown (void)
{
    ED * ep = Ep;
    RP * rp = ep->Win->RPort;

    if (ep->Topline + Rows < ep->Lines) {
	if (Nsu == 0) {
	    text_sync ();

	    ScrollRaster (rp, 0, Ysize, COL(0), ROW(0), Xpixs, Ypixs);

	    ep->Topline ++;
	    ep->Line ++;

	    text_load ();

	    text_displayseg (Rows-1, 1);
	}
    } else
	Abortcommand = 1;
} /* do_scrolldown */


void do_scrollup (void)
{
    ED * ep = Ep;
    RP * rp = ep->Win->RPort;

    if (ep->Topline) {
	if (Nsu == 0) {
	    text_sync ();

	    ScrollRaster (rp, 0, -Ysize, COL(0), ROW(0), Xpixs, Ypixs);

	    ep->Topline --;
	    ep->Line --;

	    text_load ();
	    text_displayseg (0, 1);
	}
    } else
	Abortcommand = 1;
} /* do_scrollup */


void do_down (void)
{
    ED * ep = Ep;
    RP * rp = ep->Win->RPort;

    if (!Comlinemode) {
	if (ep->Line + 1 < ep->Lines) {
	    text_sync ();

	    ep->Line ++;

	    text_load ();

	    if (ep->Line - ep->Topline >= Rows) {
		if (Nsu == 0) {
		    ScrollRaster (rp, 0, Ysize, COL(0), ROW(0), Xpixs, Ypixs);

		    ep->Topline ++;

		    text_displayseg (Rows-1, 1);
		}
	    }
	} else
	    Abortcommand = 1;
    } else { /* Comlinemode */
	if (HistoLine < NumHistoLines) {
	    HistoLine ++;

	    if (HistoLine != NumHistoLines)
		strcpy (Current, HistoBuff[HistoLine]);
	    else
		*Current = 0;

	    Clen = strlen (Current);

	    while (ep->Column > Clen)
		Current[Clen ++] = ' ';

	    Current[Clen] = 0;

	    text_redisplaycurrline ();
	}
    } /* if (!Comlinemode) */
} /* do_down */


/*
    PAGEUP
    PAGEDOWN
    PAGELEFT
    PAGERIGHT
    PAGESET n	(n = 0 to 100 for percentage of #rows to scroll, minimum 1)
		can be > 100.
*/

void do_page (void)
{
    ED	 * ep = Ep;
    ushort n,
	   t;

    switch(av[0][4]) {
	case 'u':
	    if (!ep->Topline && !ep->Line) return;

	    text_sync ();

	    if (ep->Line != ep->Topline) {
		ep->Line = ep->Topline;

		text_load ();
		return;
	    }

	    n = Rows * PageJump / 100;

	    if (ep->Topline < n)
		n = ep->Topline;

	    ep->Line -= n;
	    ep->Topline -= n;

	    text_load ();

	    scroll_display (0, -n, 0, ep->Topline, MAXLINELEN,
		ep->Topline + Rows);
	    break;

	case 'd':
	    if (ep->Topline + Rows >= ep->Lines &&
			ep->Line == ep->Lines -1)
		return;

	    text_sync ();

	    if (ep->Line != ep->Topline + Rows -1) {
		ep->Line = ep->Topline + Rows -1;

		if (ep->Line >= ep->Lines)
		    ep->Line = ep->Lines -1;

		text_load ();
		return;
	    }

	    n = Rows * PageJump / 100;

	    ep->Line	+= n;
	    ep->Topline += n;

	    if (ep->Line >= ep->Lines)
		ep->Line = ep->Lines - 1;

	    text_load ();

	    scroll_display (0, n, 0, ep->Topline, MAXLINELEN,
		ep->Topline + Rows);
	    break;

	case 'l':
	    if (!ep->Topcolumn && !ep->Column) return;

	    t = firstns (Current);

	    if (ep->Column != ep->Topcolumn) {
		if (t > ep->Topcolumn && ep->Column != t)
		    ep->Column = t;
		else
		    ep->Column = ep->Topcolumn;

		text_sync ();
		return;
	    }

	    n = Columns * PageJump / 100;

	    if (ep->Topcolumn < n)
		n = ep->Topcolumn;

	    if (t < ep->Column && t > ep->Column - n)
		ep->Column = t;
	    else
		ep->Column -= n;
	    ep->Topcolumn -= n;

	    text_sync ();

	    scroll_display (-n, 0, 0, ep->Topline, MAXLINELEN,
		ep->Topline + Rows);
	    break;

	case 'r':
	    if (ep->Topcolumn + Columns >= MAXLINELEN &&
			ep->Column == MAXLINELEN-1)
		return;

	    text_sync ();

	    t = strlen (ep->List[ep->Line]);

	    if (ep->Column != ep->Topcolumn + Columns -1) {
		if (t < ep->Topcolumn + Columns && t != ep->Column)
		    ep->Column = t;
		else
		    ep->Column = ep->Topcolumn + Columns -1;

		if (ep->Column >= MAXLINELEN)
		    ep->Column = MAXLINELEN - 1;

		text_sync ();
		return;
	    }

	    n = Columns * PageJump / 100;

	    if (t > ep->Column && t < ep->Column + n)
		ep->Column = t;
	    else
		ep->Column    += n;
	    ep->Topcolumn += n;

	    if (ep->Column >= MAXLINELEN)
		ep->Column = MAXLINELEN - 1;

	    text_sync ();

	    scroll_display (n, 0, 0, ep->Topline, MAXLINELEN,
		ep->Topline + Rows);
	    break;

	case 's':
	    PageJump = atoi ((char *)av[1]);

	    if (PageJump > 100)
		PageJump = 100;
	    else if (PageJump < 1)
		PageJump = 1;

	    break;
    }
} /* do_page */


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

    if (ep->Line + 1 == ep->Lines) {
	ep->Modified = 1;

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

	    ep->List[ep->Lines] = ptr;
	    ep->Lines ++;
	} else {
	    nomemory ();
	}
    }

    do_down ();
} /* do_downadd */


void do_left (void)
{
    ED * ep = Ep;

    if (ep->Column) {
	ep->Column --;

	if (ep->Column < ep->Topcolumn)
	    text_sync ();
    } else
	Abortcommand = 1;
} /* do_left */


void do_right (void)
{
    ED * ep = Ep;

    if (ep->Column != 254) {
	if (Current[ep->Column] == 0) {
	    Current[ep->Column] = ' ';
	    Current[ep->Column+1]= '\0';

	    Clen ++;
	}

	ep->Column ++;

	if (ep->Column - ep->Topcolumn >= Columns)
	    text_sync ();
    } else
	Abortcommand = 1;
} /* do_right */


void do_tab (void)
{
    short n;
    ED	* ep = Ep;

    /* TODO */
    for (n=ep->Tabstop-(ep->Column % ep->Tabstop); n>0; n--)
	do_right ();
} /* do_tab */


void do_backtab (void)
{
    short n;
    ED	* ep = Ep;

    n = ep->Column % ep->Tabstop;
    if (!n)
	n = ep->Tabstop;

    /* TODO */
    for (; n > 0; --n)
	do_left ();
} /* do_backtab */


void do_top (void)
{
    text_sync ();

    Ep->Line = 0;

    text_load ();
    text_sync ();
} /* do_top */


void do_bottom (void)
{
    text_sync ();

    Ep->Line = Ep->Lines - 1;

    text_load ();
    text_sync ();
} /* do_bottom */


void do_firstcolumn (void)
{
    if (Ep->Column) {
	Ep->Column = 0;
	text_sync ();
    }
} /* do_firstcolumn */


void do_firstnb (void)
{
    for (Ep->Column = 0; Current[Ep->Column] == ' '; Ep->Column ++);

    if (Current[Ep->Column] == 0)
	Ep->Column = 0;

    text_sync ();
} /* do_firstnb */


void do_lastcolumn (void)
{
    short i;

    text_sync ();

    i = (Comlinemode) ? Clen : strlen ((char *)Ep->List[Ep->Line]);

    if (i != Ep->Column) {
	Ep->Column = i;
	text_sync ();
    }
} /* do_lastcolumn */


/*
 * GOTO [+/-]N
 * GOTO BLOCK	start of block
 * GOTO START	start of block
 * GOTO END	end of block
 */

void do_goto (void)
{
    long   n,
	   i;
    char * ptr = (char *)av[1];

    i = 0;
    n = -1;

    switch (*ptr) {
	case 'b':
	case 's':
	    n = -1;

	    if (ActualBlock.type != BT_NONE && Ep == ActualBlock.ep)
		n = ActualBlock.start_line;
	break;

	case 'e':
	    n = -1;

	    if (ActualBlock.type != BT_NONE && Ep == ActualBlock.ep)
		n = ActualBlock.end_line;
	break;

	case '+':
	    i = 1;

	case '-':
	    n = Ep->Line;

	default:
	    n += atoi(ptr+i);
    } /* switch (*ptr) */

    if (n >= Ep->Lines)
	n = Ep->Lines - 1;

    if (n < 0) {
	error ("goto:\nCannot go to\nline `%s'", av[1]);
    } else {
	text_sync ();

	Ep->Line = n;

	text_load ();
	text_sync ();
    }
} /* do_goto */


void do_screentop (void)
{
    text_sync ();

    Ep->Line = Ep->Topline;

    text_load ();
    text_sync ();
} /* do_screentop */


void do_screenbottom (void)
{
    text_sync ();

    Ep->Line = Ep->Topline + Rows - 1;

    if (Ep->Line < 0 || Ep->Line >= Ep->Lines)
	Ep->Line = Ep->Lines - 1;

    text_load ();
    text_sync ();
} /* do_screenbottom */


void do_wleft ()
{
    ED * ep = Ep;
    int  i;

    for (;;) {
	i = ep->Column;

	if (i == 0)
	    goto prevline;

	i --;

	while (i && Current[i] == ' ')
	    i --;

	if (i == 0 && Current[0] == ' ') {
prevline:
	    if (Comlinemode || ep->Line == 0) {
		i = ep->Column;
		break;
	    }

	    text_sync ();

	    ep->Line --;

	    text_load ();

	    ep->Column = Clen;
	    continue;
	} /* while !SOL && isspace(Current[i]) */

	while (i && Current[i] != ' ')
	    i --;

	if (Current[i] == ' ')
	    i ++;

	break;
    } /* forever */

    ep->Column = i;

    text_sync ();
} /* do_wleft */


void do_wright()
{
    ED * ep = Ep;
    int  i;

    for (;;) {
	i = ep->Column;

	if (i == Clen)
	    goto nextline;

	while (i != Clen && Current[i] != ' ')  /* skip past current word */
	    i ++;

	while (i != Clen && Current[i] == ' ')  /* to beg. of next word   */
	    i ++;

	if (i == Clen) {
nextline:
	    if (Comlinemode || ep->Line == ep->Lines - 1) {
		i = ep->Column;
		break;
	    }

	    text_sync ();

	    ep->Line ++;

	    text_load ();

	    ep->Column = i = 0;

	    if (Current[0] != ' ')
		break;

	    continue;
	}

	break;
    } /* forever */

    ep->Column = i;

    text_sync ();
} /* do_wright() */


void do_col (void)
{
    int    col;
    char * ptr = (char *)av[1];

    switch(*ptr) {
	case '+':
	    col = text_colno() + atoi(ptr + 1);
	    if (col > 254)
		col = 254;
	break;

	case '-':
	    col = text_colno() + atoi(ptr);
	    if (col < 0)
		col = 0;
	break;

	default:
	    col = atoi(ptr) - 1;
	break;
    }

    if (col > 254 || col < 0) {
	Abortcommand = 1;
	return;
    }

    while (Clen < col)
	Current[Clen ++] = ' ';

    Current[Clen] = 0;

    Ep->Column = col;

    if (Ep->Column - Ep->Topcolumn >= Columns || Ep->Column < Ep->Topcolumn)
	text_sync ();
} /* do_col */


void do_scrollleft (void)
{
    ED	 * ep = Ep;
    RP	 * rp = ep->Win->RPort;
    short  t,
	x,
	y,
	topcol,
	n,
	line;
    LINE * ptr,
	hptr;

    if (ep->Topcolumn) {
	if (!Nsu) {
	    text_sync ();

	    n = Rows;

	    if (n > (ep->Lines - ep->Topline))
		n = ep->Lines - ep->Topline;

	    SetWrMsk (rp, BLOCK_MASK);

	    ScrollRaster (rp, -Xsize, 0, COL(0), ROW(0), Xpixs, ROW(n) -1);

	    ep->Topcolumn --;
	    ep->Column --;

	    x	   = COLT(0);
	    y	   = ROWT(0);
	    ptr    = ep->List + ep->Topline;
	    topcol = ep->Topcolumn;
	    line   = ep->Topline;

	    for (t=0; t<n; t++,ptr++,y+=Ysize,line++) {
		hptr = * ptr;

		if (strlen(hptr) > topcol) {
		    hptr += topcol;

		    if (*hptr != ' ') {
			setpen (line);
			Move (rp, x, y);
			Text (rp, hptr, 1);
		    }
		} /* len > 0 */
	    } /* for */

	    text_load ();

	    SetWrMsk (rp, -1);
	} /* if (!Nsu) */
    } else
	Abortcommand = 1;
} /* do_scrollleft */


void do_scrollright (void)
{
    ED	 * ep = Ep;
    RP	 * rp = ep->Win->RPort;
    short  t,
	x,
	y,
	topcol,
	n,
	line;
    LINE * ptr,
	hptr;

    if ((ep->Topcolumn + Columns) < MAXLINELEN) {
	if (!Nsu) {
	    text_sync ();

	    n = Rows;

	    if (n > (ep->Lines - ep->Topline))
		n = ep->Lines - ep->Topline;

	    SetWrMsk (rp, BLOCK_MASK);

	    ScrollRaster (rp, Xsize, 0, COL(0), ROW(0), Xpixs, ROW(n) -1);

	    ep->Topcolumn ++;
	    ep->Column ++;

	    x	   = COLT(Columns-1);
	    y	   = ROWT(0);
	    ptr    = ep->List + ep->Topline;
	    topcol = ep->Topcolumn + Columns -1;
	    line   = ep->Topline;

	    for (t=0; t<n; t++, ptr ++, y += Ysize, line ++) {
		hptr = *ptr;

		if (strlen(hptr) > topcol) {
		    hptr += topcol;

		    if (*hptr != ' ') {
			setpen (line);
			Move (rp, x, y);
			Text (rp, hptr, 1);
		    }
		} /* len > 0 */
	    } /* for */

	    text_load ();
	    SetWrMsk (rp, -1);
	} /* if (!Nsu) */
    } else
	Abortcommand = 1;
} /* do_scrollright */


void do_match (void)
{
    char   dec, 	/* char that indicates a "level_down"   */
	   inc; 	/*	    -""-         "level_up"     */
    char * line;	/* contents of the actual line		*/
    short  pos; 	/* position in that line		*/
    short  dir; 	/* direction of search			*/
    long   linnr;	/* actual line-number			*/
    short  level;	/* "level"                              */

    /* set start values */
    pos   = Ep->Column;
    line  = Current;
    linnr = Ep->Line;
    inc   = line[pos];

    /* Check for a known paren and select the search-direction accordingly. */
    switch (inc) {
	case '{':
	    dir = 1;
	    dec = '}';
	break;

	case '}':
	    dir = -1;
	    dec = '{';
	break;

	case '[':
	    dir = 1;
	    dec = ']';
	break;

	case ']':
	    dir = -1;
	    dec = '[';
	break;

	case '(':
	    dir = 1;
	    dec = ')';
	break;

	case ')':
	    dir = -1;
	    dec = '(';
	break;

	case '`':
	    dir = 1;
	    dec = '\'';
	break;

	case '\'':
	    dir = -1;
	    dec = '`';
	break;

	default:
	    dir = 0;
	break;
    }

    /* if there is no known paren, return */
    if (!dir)
	return;

    /* we start with level 0. Since we ARE on a paren, this is increased soon */
    level = 0;

    for (;;) {
	if (line[pos] == inc) { /* check for "inc-char" */
	    level ++;
	} else {
	    if (line[pos] == dec) { /* dito */
		level --;

		/* if we have reached the start-level, we are through */
		if (!level)
		    break;
	    }
	}

	/* next pos */
	pos += dir;

	if (pos <= 0) {
	    do {
		if (!linnr) {
		    warn ("match: No matching paren");
		    return;
		}

		linnr --;

		line = Ep->List[linnr];
		pos = strlen (line);

		if (pos) {
		    pos --;

		    break;
		}
	    } while (!pos);
	} else if (!line[pos]) {
	    linnr ++;

	    if (linnr >= Ep->Lines) {
		warn ("match: No matching paren");
		return;
	    }

	    line = Ep->List[linnr];
	    pos = 0;
	}
    }

    text_sync ();

    if (linnr >= Ep->Lines)
	linnr = Ep->Lines - 1;

    Ep->Line   = linnr;
    Ep->Column = pos;

    text_load ();
    text_sync ();
} /* do_match */


void do_ping (void)
{
    uword num = atoi (av[1]);

    if (num >= PINGDEPTH) {
	error ("ping:\n%ld out of range\n(max %ld)", num, PINGDEPTH);
	return;
    }

    marker[num].ep     = Ep;
    marker[num].column = Ep->Column;
    marker[num].line   = Ep->Line;

    title ("Position marked");
} /* do_ping */


void do_pong (void)
{
    short num = atoi (av[1]);

    text_sync ();

    if (num < 0 || num >= PINGDEPTH || !marker[num].ep) {
	error ("pong:\nrange error or\nyet nothing marked");
	return;
    }

    text_cursor (1);
    text_switch (marker[num].ep->Win);
    text_cursor (0);

    if (IntuitionBase->ActiveWindow != Ep->Win) {
	WindowToFront (Ep->Win);
	ActivateWindow (Ep->Win);
    }

    if ((Ep->Line = marker[num].line) >= Ep->Lines) {
	marker[num].line = Ep->Line = Ep->Lines - 1;
    }

    Ep->Column = marker[num].column;

    text_load ();
    text_sync ();
} /* do_pong */


int get_pong (int num)
{
     if (num < 0 || num >= PINGDEPTH || !marker[num].ep) {
	  return (-1);
     }

     if (marker[num].line >= Ep->Lines)
	  return (marker[num].line = Ep->Lines-1);

     return (marker[num].line);
} /* get_pong */


/*
 * esc, escimm
 */

int Savetopline, Savecolumn, Savetopcolumn;

void do_recall (void)
{
    av[0] = "escimm";

    /* Copy last Histoline if possible */
    if (NumHistoLines)
	av[1] = HistoBuff[NumHistoLines - 1];
    else
	av[1] = "";

    do_esc ();

    if (NumHistoLines)
	HistoLine --;
} /* do_recall */


void do_esc (void)
{
    ED	* ep = Ep;
    RP	* rp = ep->Win->RPort;
    short y;

    if (Comlinemode) {
	escapecomlinemode ();
	return;
    }

    text_sync ();

    if (av[0][3] == 'i')
	strcpy ((char *)Current, (char *)av[1]);
    else
	Current[0] = 0;

    Clen = strlen ((char *)Current);
    Comlinemode = 1;

    returnoveride (1);

    Savetopline   = ep->Topline;
    Savecolumn	  = ep->Column;
    Savetopcolumn = ep->Topcolumn;

    ep->Column = Clen;

    if (ep->Column < Rows)
	ep->Topcolumn = 0;
    else {
	ep->Topcolumn = Clen - Clen % Rows;
    }

    ep->Topline   = ep->Line - Rows + 1;

    y = ROW (Rows-1);
    SetAPen (rp, TEXT_BPEN);
    RectFill (rp, COL(0), y, Xpixs, Ypixs);

    y --;
    SetAPen (rp, TEXT_FPEN);
    RectFill (rp, COL(0), y, Xpixs, y);

    text_displayseg (Rows - 1, 1);

    HistoLine = NumHistoLines;
} /* do_esc */


void escapecomlinemode (void)
{
    ED	 * ep = Ep;
    RP	 * rp = ep->Win->RPort;
    char * ptr;

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

    if (Comlinemode) {
	/* Don't add empty lines */
	if (*Current) {
	    ptr = Current + strlen (Current) -1;

	    while (*ptr == ' ' && ptr != (char *)Current)
		ptr --;

	    /* Set string-end after last char. Note that this code
	       removes histo-lines with length 1 (single chars) */
	    if (ptr != (char *)Current)
		ptr ++;

	    *ptr = 0;
	}

	/* If we are somewhere above and we didn't change anything,
	   we won't add a new history-line */
	/* If there is something to add */
	if (!(HistoLine != NumHistoLines && !strcmp (Current,
		HistoBuff[HistoLine])) && *Current) {
	    /* Check if buffer is full */
	    if (NumHistoLines == MaxHistoLines) {
		/* Free oldest line and shift buffer */
		free (HistoBuff[0]);

		movmem (HistoBuff + 1, HistoBuff,
			sizeof (char *) * (MaxHistoLines - 1));

		/* We have now space for one line */
		NumHistoLines --;
	    }

	    /* Allocate new line */
	    ptr = malloc (strlen (Current) + 1);

	    /* Copy new line if possible. Note that even if malloc()
	       failed we don't loose information. */
	    if (ptr) {
		strcpy (ptr, (char *)Current);

		/* Add line. At this point, NumHistoLines is ALWAYS
		   less than MaxHistoLines ! */
		HistoBuff[NumHistoLines ++] = ptr;
	    }
	}

	Comlinemode = 0;

	returnoveride (0);

	ep->Topline   = Savetopline;
	ep->Column    = Savecolumn;
	ep->Topcolumn = Savetopcolumn;

	text_load ();

	SetAPen (rp, TEXT_BPEN);
	RectFill (rp, COL(0), ROW(Rows-1)-1, Xpixs, Ypixs);

	SetAPen (rp, TEXT_FPEN);
	text_displayseg (Rows - 2, 2);
    }
} /* escapecomlinemode */


void markerkill (ED * ep)
{
    short i, j;

    for (i = 0; i < PINGDEPTH; ++i) {       /*  remove ping-pong marks  */
	if (marker[i].ep == ep)
	    marker[i].ep = NULL;
    }
} /* markerkill */


/******************************************************************************
*****  ENDE cursor.c
******************************************************************************/
