/*
 *			e d t b u f . c
 */

/*)LIBRARY
*/

#ifdef	DOCUMENTATION

title	edtbuf	Edit a Buffer on Screen
index		Edit a buffer on screen

synopsis

	int
	edtbuf(buf,len,startcol,row,col)
	 char *buf;	/* buffer to edit 		*/
	 int len;	/* length of buf (bytes)	*/
	 int startcol;	/* column to start editing	*/
	 int row;	/* row position to place the buffer on screen */
	 int col;	/* column position to place the buffer on screen */

description

	Edtbuf() places the buffer on the screen at the specified position,
	and places the cursor at the specified column {startcol}, for the
	operator to edit, via the numeric keypad on a vt100/220.
	Before edtbuf() can be used, zbegin() must be called.
	Edit commnads :
		<cr>		terminates editing
		<esc>   	aborts editing
		<delete>	erases the previous character
		<left-arrow>	moves cursor back one character
		<backspace>	moves cursor back one character
		<right-arrow>	moves cursor on one character
		<,>		erases the character under the cursor
		<->		erases to end of buffer

	Returns The line terminator, used to exit editing mode.

bugs

author

	Machiavelli Systems

#endif

#include "vt100.h"


int	edtbuf(buf,len,startcol,row,col)
				/* return '\r' or terminator */
				/* input up to 'len' chars to 'buf'
				   never go outside buf */
				/* allow auto-insert */
				/* do cursor positioning */
char	*buf;
int	len;			/* length of buf (chars) */
int	startcol;		/* starting column in field */
int	row;			/* glass co-ords of 1st char to edit */
int	col;			/*	"	"	"	"    */
{int	c;			/* character */
 char	*p;			/* points to character under cursor */
				/* the following identifier 'ennd' is chosen
				   because some Cs (eg BDS) use 'end' to mean
				   '}' */
 char	*ennd;			/* points to 1st char we mustn't touch */
 char	*q;
 char	*last;
 ennd = (p=buf) + len;
 if	(startcol>=len)	startcol = len-1;
 if	(startcol<0)	startcol=0;
 zsrowcol(row,col);
 while	(startcol--)
	{if	(!*p)	*p=' ';
	 zsputchar(*p++);
	}
 ;
 while	(c=zsnatch()
	, (c!='\r' && c>=0 && c!='\033') || c==LEFT_ARROW || c==RIGHT_ARROW || c==GOBBLE || c==ALLGOBBLE
	)
	{
	 if	(c==GOBBLE && p<ennd)
		{if	(!*p)	*p = ' ';	/* free blank */
		 zsputchar(*p++);
		 c = DELETE;
		}
	 ;
	 if	(c==DELETE)
		{if	(p>buf)
			{if	(ennd-p)
				{copy(p-1,p,ennd-p);
				}
			 ;
			 ennd[-1] = ' ';
			 if	(!*--p)	*p = ' ';
			 zsrowcol(row,col+p-buf);
			 for	(last=p; *last && last<ennd; last++)
			 ;
			 /* last points to 1 past what we would like to display */
			 while	(last>p && *--last==' ')
				{/* forget trailing blanks */
				}
			 ;
			 /* last points to last char to display */
			 /* last >=p so will redisplay the old char under the
			    new cursor position */
			 for	(q=p;	q<=last;	q++)
				{zsputchar(*q);
				}
			 ;
			 if	(q<ennd)
				{/* we must space out the old trailing character */
				 zsputchar(' ');
				}
			 ;
			 zsrowcol(row,col+p-buf);
			}
		 ;
		}
	 else
		{if	(c>=' '&&c<=127)
			{if	(p<ennd)
				{
				 for	(q=ennd-1;	q>p;	q--)
					{q[0] = q[-1];
					}
				 ;
				 *p = c;
				 for	(last=p; *last && last<ennd; last++)
				 ;
				 /* last points to 1 past what we would like to display */
				 while	(last>p && *--last==' ')
					{/* forget trailing blanks */
					}
				 ;
				 /* last points to last char to display */
				 for	(q=p;	q<=last;	q++)
					{zsputchar(*q);
					}
				 ;
				 p++;
				 zsrowcol(row,col+p-buf);
				}
			 else
				{zbeep();	/* too many chars */
				}
			 ;
			}
		 else
			{if	(c=='\b' || c==LEFT_ARROW)
				{if	(p>buf)
					{p--;
					 zsputs("\b");
					}
				 ;
				}
			 else
				{if	(c==RIGHT_ARROW)
					{if	(p<ennd)
						{if	(!*p)	*p=' ';	/* free spaces at right edge of buf */
						 zsputchar(*p++);
						}
					 ;
					}
				 else
					{if	(c==ALLGOBBLE)
						{if	(p<ennd)
							{for	(last=p; *last && last<ennd; last++)
							 ;
							 /* last points to 1 past what we would like to display */
							 while	(last>p && *--last==' ')
								{/* forget trailing blanks */
								}
							 ;
							 /* last points to last char to display */
							 zero(p,ennd-p);
							 for	(q=p;	q<=last;	q++)
								{zsputchar(' ');
								}
							 ;
							 zsrowcol(row,col+p-buf);
							}
						 ;
						}
					 else
						{zbeep();	/* what? */
						}
					 ;
					}
				 ;
				}
			 ;
			}
		 ;
		}
	 ;
	}
 ;
 return(c);
}
