292 lines
5.4 KiB
C
Executable File
292 lines
5.4 KiB
C
Executable File
#ident "@(#)editlib.c 1.3 93/06/08 SMI" /* From AT&T Toolchest */
|
|
|
|
/*
|
|
* Miscellaneous routine needed for standalone library for edit modes
|
|
*/
|
|
|
|
#include "io.h"
|
|
#include "terminal.h"
|
|
#include "history.h"
|
|
#include "edit.h"
|
|
#ifdef TIOCLBIC
|
|
# undef TIOCLBIC
|
|
# ifdef _sys_ioctl_
|
|
# include <sys/ioctl.h>
|
|
# endif /* _sys_ioctl_ */
|
|
#endif /* TIOCLBIC */
|
|
#undef read
|
|
|
|
#define e_create "cannot create"
|
|
|
|
extern char *strrchr();
|
|
extern char *getenv();
|
|
char opt_flag;
|
|
char ed_errbuf[IOBSIZE+1];
|
|
struct fileblk *io_ftable[NFILE];
|
|
static struct fileblk outfile = { ed_errbuf, ed_errbuf, ed_errbuf+IOBSIZE, 2, IOWRT};
|
|
static int editfd;
|
|
static int output = 0;
|
|
static char beenhere;
|
|
|
|
#if 0 /* almost always false. Makes a good block comment */
|
|
**********************************************************************
|
|
* There are two scenarios here.
|
|
*
|
|
* 1) We ALWAYS want ksh-editing on the terminal input.
|
|
* 2) We SOMETIMES want ksh-editing on the terminal input.
|
|
*
|
|
* If you are running with case 1, then just call read() in the usual
|
|
* manner and be happy.
|
|
*
|
|
* If you want to only have line-editing sometimes, and the very first
|
|
* read() is not one of those times, then you must perform the
|
|
* initialization first, turn OFF editing, perform your read(), and
|
|
* so forth. An example of this is in a curses application in which
|
|
* single characters are read in RAW mode and acted upon immediately.
|
|
* Line editing here will not work.
|
|
*
|
|
* Do the following:
|
|
* edit_Init();
|
|
* SAVopt_flag = set_edit(0,0); /* fd=0 set to NO editing */
|
|
* read(0,buffer,1); /* do your single char read */
|
|
* set_edit(0,SAVopt_flag); /* restore editing on fd=0 */
|
|
**********************************************************************
|
|
#endif /* 0 */
|
|
|
|
int edit_Init()
|
|
{
|
|
register char *sp;
|
|
if(!beenhere)
|
|
{
|
|
beenhere = 1;
|
|
hist_open();
|
|
if(!(sp = getenv("VISUAL")))
|
|
sp = getenv("EDITOR");
|
|
if(sp)
|
|
{
|
|
if(strrchr(sp,'/'))
|
|
sp = strrchr(sp,'/')+1;
|
|
if(strcmp(sp,"vi") == 0)
|
|
opt_flag = EDITVI;
|
|
else if(strcmp(sp,"emacs")==0)
|
|
opt_flag = EMACS;
|
|
else if(strcmp(sp,"gmacs")==0)
|
|
opt_flag = GMACS;
|
|
}
|
|
}
|
|
return(1);
|
|
}
|
|
/*
|
|
* read routine with edit modes
|
|
*/
|
|
|
|
int read(fd,buff,n)
|
|
char *buff;
|
|
{
|
|
register int r, flag;
|
|
if(fd==editfd && !beenhere)
|
|
edit_Init();
|
|
flag = (fd==editfd?opt_flag&EDITMASK:0);
|
|
switch(flag)
|
|
{
|
|
case EMACS:
|
|
case GMACS:
|
|
tty_set(-1);
|
|
r = emacs_read(fd,buff,n);
|
|
break;
|
|
|
|
case VIRAW:
|
|
case EDITVI:
|
|
tty_set(-1);
|
|
r = vi_read(fd,buff,n);
|
|
break;
|
|
default:
|
|
#ifdef SYSCALL
|
|
r = syscall(3,fd,buff,n);
|
|
#else
|
|
r = rEAd(fd,buff,n);
|
|
#endif /* SYSCALL */
|
|
}
|
|
if(fd==editfd && hist_ptr && (opt_flag&NOHIST)==0 && r>0)
|
|
{
|
|
/* write and flush history */
|
|
int c = buff[r];
|
|
buff[r] = 0;
|
|
hist_eof();
|
|
p_setout(hist_ptr->fixfd);
|
|
p_str(buff,0);
|
|
hist_flush();
|
|
buff[r] = c;
|
|
}
|
|
return(r);
|
|
}
|
|
|
|
|
|
/*
|
|
* enable edit mode <mode> on file number <fd>
|
|
* the NOHIST bit can also be set to avoid writing the history file
|
|
* <fd> cannot be file two
|
|
*/
|
|
|
|
int set_edit(fd,mode)
|
|
{
|
|
int retval = opt_flag;
|
|
opt_flag = mode;
|
|
if(fd==2)
|
|
return(-1);
|
|
editfd = fd;
|
|
return(retval);
|
|
}
|
|
|
|
/*
|
|
* flush the output queue and reset the output stream
|
|
*/
|
|
|
|
void p_setout(fd)
|
|
register int fd;
|
|
{
|
|
register struct fileblk *fp;
|
|
if(!io_ftable[fd])
|
|
io_ftable[fd] = &outfile;
|
|
fp = io_ftable[fd];
|
|
fp->last = fp->base + IOBSIZE;
|
|
fp->flag &= ~(IOREAD|IOERR|IOEOF);
|
|
if(output==fd)
|
|
return;
|
|
if(io_ftable[fd]==io_ftable[output])
|
|
p_flush();
|
|
output = fd;
|
|
}
|
|
|
|
/*
|
|
* flush the output if necessary and null terminate the buffer
|
|
*/
|
|
|
|
void p_flush()
|
|
{
|
|
register struct fileblk *fp = io_ftable[output];
|
|
register int count;
|
|
if(fp && (count=fp->ptr-fp->base))
|
|
{
|
|
if(write(output,fp->base,count) < 0)
|
|
fp->flag |= IOERR;
|
|
/* leave previous buffer as a null terminated string */
|
|
*fp->ptr = 0;
|
|
fp->ptr = fp->base;
|
|
}
|
|
}
|
|
|
|
/*
|
|
* print a given character
|
|
*/
|
|
|
|
void p_char(c)
|
|
register int c;
|
|
{
|
|
register struct fileblk *fp = io_ftable[output];
|
|
if(fp->ptr >= fp->last)
|
|
p_flush();
|
|
*fp->ptr++ = c;
|
|
}
|
|
|
|
/*
|
|
* print a string optionally followed by a character
|
|
*/
|
|
|
|
void p_str(string,c)
|
|
register char *string;
|
|
int c;
|
|
{
|
|
register struct fileblk *fp = io_ftable[output];
|
|
register int cc;
|
|
while(1)
|
|
{
|
|
if((cc= *string)==0)
|
|
cc = c,c = 0;
|
|
else
|
|
string++;
|
|
if(cc==0)
|
|
break;
|
|
if(fp->ptr >= fp->last)
|
|
p_flush();
|
|
*fp->ptr++ = cc;
|
|
}
|
|
}
|
|
|
|
/*
|
|
* copy string a to string b and return pointer to end of string b
|
|
*/
|
|
|
|
char *ed_movstr(a,b)
|
|
register const char *a;
|
|
register char *b;
|
|
{
|
|
while(*b++ = *a++);
|
|
return(--b);
|
|
}
|
|
|
|
/*
|
|
* print and error message and exit
|
|
*/
|
|
|
|
ed_failed(name,message)
|
|
char *name,*message;
|
|
{
|
|
p_setout(ERRIO);
|
|
p_str(name,' ');
|
|
p_char(':');
|
|
p_char(' ');
|
|
p_str(message,'\n');
|
|
exit(2);
|
|
}
|
|
|
|
|
|
#ifndef F_DUPFD
|
|
# define F_DUPFD 0
|
|
static int fcntl(f1,type,arg)
|
|
register int arg;
|
|
{
|
|
struct stat statbuf;
|
|
if(type==F_DUPFD)
|
|
{
|
|
register int fd;
|
|
/* find first non-open file */
|
|
while(arg < NFILE && (fstat(arg,&statbuf)>=0))
|
|
arg++;
|
|
if(arg >= NFILE)
|
|
return(-1);
|
|
fd = dup2(f1, arg);
|
|
return(fd);
|
|
}
|
|
else
|
|
return(0);
|
|
}
|
|
#endif /* F_DUPFD */
|
|
|
|
/*
|
|
* print a prompt
|
|
*/
|
|
void pr_prompt(string)
|
|
register char *string;
|
|
{
|
|
register int c;
|
|
register char *dp = editb.e_prbuff;
|
|
#ifdef TIOCLBIC
|
|
int mode;
|
|
mode = LFLUSHO;
|
|
ioctl(ERRIO,TIOCLBIC,&mode);
|
|
#endif /* TIOCLBIC */
|
|
p_setout(ERRIO);
|
|
while(c= *string++)
|
|
{
|
|
if(dp < editb.e_prbuff+PRSIZE)
|
|
*dp++ = c;
|
|
p_char(c);
|
|
}
|
|
*dp = 0;
|
|
if (!(opt_flag&EDITMASK))
|
|
p_flush();
|
|
|
|
}
|
|
|