version 1.28, 2004/07/08 21:28:06 |
version 1.29, 2004/07/22 01:25:24 |
|
|
/* $OpenBSD$ */ |
/* $OpenBSD$ */ |
|
|
/* |
/* |
* Echo line reading and writing. |
* Echo line reading and writing. |
* |
* |
|
|
|
|
#include <stdarg.h> |
#include <stdarg.h> |
|
|
static int veread(const char *, char *buf, int, int, va_list); |
static char *veread(const char *, char *, size_t, int, va_list); |
static int complt(int, int, char *, int); |
static int complt(int, int, char *, size_t, int); |
static int complt_list(int, int, char *, int); |
static int complt_list(int, int, char *, int); |
static void eformat(const char *, va_list); |
static void eformat(const char *, va_list); |
static void eputi(int, int); |
static void eputi(int, int); |
|
|
int |
int |
eyesno(const char *sp) |
eyesno(const char *sp) |
{ |
{ |
int s; |
char buf[64], *rep; |
char buf[64]; |
|
|
|
#ifndef NO_MACRO |
#ifndef NO_MACRO |
if (inmacro) |
if (inmacro) |
return TRUE; |
return TRUE; |
#endif /* !NO_MACRO */ |
#endif /* !NO_MACRO */ |
s = ereply("%s? (yes or no) ", buf, sizeof(buf), sp); |
rep = ereply("%s? (yes or no) ", buf, sizeof(buf), sp); |
for (;;) { |
for (;;) { |
if (s == ABORT) |
if (rep == NULL) |
return ABORT; |
return ABORT; |
if (s != FALSE) { |
if (rep[0] != '\0') { |
#ifndef NO_MACRO |
#ifndef NO_MACRO |
if (macrodef) { |
if (macrodef) { |
LINE *lp = maclcur; |
LINE *lp = maclcur; |
|
|
free((char *)lp); |
free((char *)lp); |
} |
} |
#endif /* !NO_MACRO */ |
#endif /* !NO_MACRO */ |
if ((buf[0] == 'y' || buf[0] == 'Y') && |
if ((rep[0] == 'y' || rep[0] == 'Y') && |
(buf[1] == 'e' || buf[1] == 'E') && |
(rep[1] == 'e' || rep[1] == 'E') && |
(buf[2] == 's' || buf[2] == 'S') && |
(rep[2] == 's' || rep[2] == 'S') && |
(buf[3] == '\0')) |
(rep[3] == '\0')) |
return TRUE; |
return TRUE; |
if ((buf[0] == 'n' || buf[0] == 'N') && |
if ((rep[0] == 'n' || rep[0] == 'N') && |
(buf[1] == 'o' || buf[0] == 'O') && |
(rep[1] == 'o' || rep[0] == 'O') && |
(buf[2] == '\0')) |
(rep[2] == '\0')) |
return FALSE; |
return FALSE; |
} |
} |
s = ereply("Please answer yes or no. %s? (yes or no) ", |
rep = ereply("Please answer yes or no. %s? (yes or no) ", |
buf, sizeof(buf), sp); |
buf, sizeof(buf), sp); |
} |
} |
/* NOTREACHED */ |
/* NOTREACHED */ |
|
|
* completion, and the return is echoed as such. |
* completion, and the return is echoed as such. |
*/ |
*/ |
/* VARARGS */ |
/* VARARGS */ |
int |
char * |
ereply(const char *fmt, char *buf, int nbuf, ...) |
ereply(const char *fmt, char *buf, size_t nbuf, ...) |
{ |
{ |
va_list ap; |
va_list ap; |
int i; |
char *rep; |
|
|
va_start(ap, nbuf); |
va_start(ap, nbuf); |
i = veread(fmt, buf, nbuf, EFNEW | EFCR, ap); |
rep = veread(fmt, buf, nbuf, EFNEW | EFCR, ap); |
va_end(ap); |
va_end(ap); |
return i; |
return rep; |
} |
} |
|
|
/* |
/* |
|
|
* (autocomplete), or EFCR (echo the carriage return as CR). |
* (autocomplete), or EFCR (echo the carriage return as CR). |
*/ |
*/ |
/* VARARGS */ |
/* VARARGS */ |
int |
char * |
eread(const char *fmt, char *buf, int nbuf, int flag, ...) |
eread(const char *fmt, char *buf, size_t nbuf, int flag, ...) |
{ |
{ |
int i; |
|
va_list ap; |
va_list ap; |
|
char *rep; |
|
|
va_start(ap, flag); |
va_start(ap, flag); |
i = veread(fmt, buf, nbuf, flag, ap); |
rep = veread(fmt, buf, nbuf, flag, ap); |
va_end(ap); |
va_end(ap); |
return i; |
return rep; |
} |
} |
|
|
static int |
static char * |
veread(const char *fp, char *buf, int nbuf, int flag, va_list ap) |
veread(const char *fp, char *buf, size_t nbuf, int flag, va_list ap) |
{ |
{ |
int cpos; |
int cpos, dynbuf = (buf == NULL); |
int i; |
int i; |
int c; |
int c; |
|
|
#ifndef NO_MACRO |
#ifndef NO_MACRO |
if (inmacro) { |
if (inmacro) { |
|
if (dynbuf) { |
|
if ((buf = malloc(maclcur->l_used + 1)) == NULL) |
|
return NULL; |
|
} else if (maclcur->l_used >= nbuf) |
|
return NULL; |
bcopy(maclcur->l_text, buf, maclcur->l_used); |
bcopy(maclcur->l_text, buf, maclcur->l_used); |
buf[maclcur->l_used] = '\0'; |
buf[maclcur->l_used] = '\0'; |
maclcur = maclcur->l_fp; |
maclcur = maclcur->l_fp; |
return TRUE; |
return buf; |
} |
} |
#endif /* !NO_MACRO */ |
#endif /* !NO_MACRO */ |
cpos = 0; |
cpos = 0; |
|
|
eputc(' '); |
eputc(' '); |
eformat(fp, ap); |
eformat(fp, ap); |
if ((flag & EFDEF) != 0) { |
if ((flag & EFDEF) != 0) { |
|
if (buf == NULL) |
|
return NULL; |
eputs(buf); |
eputs(buf); |
cpos += strlen(buf); |
cpos += strlen(buf); |
} |
} |
|
|
for (;;) { |
for (;;) { |
c = getkey(FALSE); |
c = getkey(FALSE); |
if ((flag & EFAUTO) != 0 && (c == ' ' || c == CCHR('I'))) { |
if ((flag & EFAUTO) != 0 && (c == ' ' || c == CCHR('I'))) { |
cpos += complt(flag, c, buf, cpos); |
cpos += complt(flag, c, buf, nbuf, cpos); |
continue; |
continue; |
} |
} |
if ((flag & EFAUTO) != 0 && c == '?') { |
if ((flag & EFAUTO) != 0 && c == '?') { |
|
|
/* FALLTHROUGH */ |
/* FALLTHROUGH */ |
case CCHR('M'): /* return, done */ |
case CCHR('M'): /* return, done */ |
if ((flag & EFFUNC) != 0) { |
if ((flag & EFFUNC) != 0) { |
if ((i = complt(flag, c, buf, cpos)) == 0) |
if ((i = complt(flag, c, buf, nbuf, cpos)) == 0) |
continue; |
continue; |
if (i > 0) |
if (i > 0) |
cpos += i; |
cpos += i; |
|
|
if (macrodef) { |
if (macrodef) { |
LINE *lp; |
LINE *lp; |
|
|
if ((lp = lalloc(cpos)) == NULL) |
if ((lp = lalloc(cpos)) == NULL) { |
return FALSE; |
static char falseval[] = ""; |
|
/* XXX hackish */ |
|
if (dynbuf && buf != NULL) |
|
free(buf); |
|
return falseval; |
|
} |
lp->l_fp = maclcur->l_fp; |
lp->l_fp = maclcur->l_fp; |
maclcur->l_fp = lp; |
maclcur->l_fp = lp; |
lp->l_bp = maclcur; |
lp->l_bp = maclcur; |
|
|
eputc(CCHR('G')); |
eputc(CCHR('G')); |
(void)ctrlg(FFRAND, 0); |
(void)ctrlg(FFRAND, 0); |
ttflush(); |
ttflush(); |
return ABORT; |
return NULL; |
case CCHR('H'): /* rubout, erase */ |
case CCHR('H'): /* rubout, erase */ |
case CCHR('?'): |
case CCHR('?'): |
if (cpos != 0) { |
if (cpos != 0) { |
|
|
case CCHR('Q'): /* quote next */ |
case CCHR('Q'): /* quote next */ |
c = getkey(FALSE); |
c = getkey(FALSE); |
/* FALLTHROUGH */ |
/* FALLTHROUGH */ |
default: /* all the rest */ |
default: |
|
/* all the rest */ |
|
if (dynbuf && cpos + 1 >= nbuf) { |
|
void *newp; |
|
size_t newsize = cpos + cpos + 16; |
|
|
|
if ((newp = realloc(buf, newsize)) == NULL) { |
|
ewprintf("Out of memory"); |
|
free(buf); |
|
return NULL; |
|
} |
|
buf = newp; |
|
nbuf = newsize; |
|
} |
if (cpos < nbuf - 1) { |
if (cpos < nbuf - 1) { |
buf[cpos++] = (char)c; |
buf[cpos++] = (char)c; |
eputc((char)c); |
eputc((char)c); |
|
|
} |
} |
} |
} |
done: |
done: |
return buf[0] != '\0'; |
return buf; |
} |
} |
|
|
/* |
/* |
* do completion on a list of objects. |
* do completion on a list of objects. |
*/ |
*/ |
static int |
static int |
complt(int flags, int c, char *buf, int cpos) |
complt(int flags, int c, char *buf, size_t nbuf, int cpos) |
{ |
{ |
LIST *lh, *lh2; |
LIST *lh, *lh2; |
LIST *wholelist = NULL; |
LIST *wholelist = NULL; |
|
|
*/ |
*/ |
if (nxtra < 0 && nhits > 1 && c == ' ') |
if (nxtra < 0 && nhits > 1 && c == ' ') |
nxtra = 1; |
nxtra = 1; |
for (i = 0; i < nxtra; ++i) { |
for (i = 0; i < nxtra && cpos < nbuf; ++i) { |
buf[cpos] = lh2->l_name[cpos]; |
buf[cpos] = lh2->l_name[cpos]; |
eputc(buf[cpos++]); |
eputc(buf[cpos++]); |
} |
} |