|
|
DataMuseum.dkPresents historical artifacts from the history of: DKUUG/EUUG Conference tapes |
This is an automatic "excavation" of a thematic subset of
See our Wiki for more about DKUUG/EUUG Conference tapes Excavated with: AutoArchaeologist - Free & Open Source Software. |
top - metrics - downloadIndex: T a
Length: 9258 (0x242a)
Types: TextFile
Names: »ask.c«
└─⟦a0efdde77⟧ Bits:30001252 EUUGD11 Tape, 1987 Spring Conference Helsinki
└─⟦this⟧ »EUUGD11/euug-87hel/sec1/jove/ask.c«
/************************************************************************
* This program is Copyright (C) 1986 by Jonathan Payne. JOVE is *
* provided to you without charge, and with no warranty. You may give *
* away copies of JOVE, including sources, provided that this notice is *
* included in all the files. *
************************************************************************/
#include "jove.h"
#include "termcap.h"
#include "ctype.h"
#include <signal.h>
#include <varargs.h>
#ifdef F_COMPLETION
# include <sys/stat.h>
#endif
int Asking = NO;
char Minibuf[LBSIZE];
private Line *CurAskPtr = 0; /* points at some line in mini-buffer */
private Buffer *AskBuffer = 0; /* Askbuffer points to actual structure */
/* The way the mini-buffer works is this: The first line of the mini-buffer
is where the user does his stuff. The rest of the buffer contains
strings that the user often wants to use, for instance, file names, or
common search strings, etc. If he types C-N or C-P while in ask(), we
bump the point up or down a line and extract the contents (we make sure
is somewhere in the mini-buffer). */
static Buffer *
get_minibuf()
{
if (AskBuffer) { /* make sure ut still exists */
register Buffer *b;
for (b = world; b != 0; b = b->b_next)
if (b == AskBuffer)
return b;
}
AskBuffer = do_select((Window *) 0, "*minibuf*");
AskBuffer->b_type = B_SCRATCH;
return AskBuffer;
}
/* Add a string to the mini-buffer. */
minib_add(str, movedown)
char *str;
{
register Buffer *saveb = curbuf;
SetBuf(get_minibuf());
LineInsert(1);
ins_str(str, NO);
if (movedown)
CurAskPtr = curline;
SetBuf(saveb);
}
static char *
real_ask(delim, d_proc, def, prompt)
char *delim,
*def,
*prompt;
int (*d_proc)();
{
static int InAsk = 0;
jmp_buf savejmp;
int c,
prompt_len;
Buffer *saveb = curbuf;
int abort = 0,
no_typed = 0;
data_obj *push_cmd = LastCmd;
int o_exp = exp,
o_exp_p = exp_p;
if (InAsk)
complain((char *) 0);
push_env(savejmp);
InAsk++;
SetBuf(get_minibuf());
if (!inlist(AskBuffer->b_first, CurAskPtr))
CurAskPtr = curline;
prompt_len = strlen(prompt);
ToFirst(); /* Beginning of buffer. */
linebuf[0] = '\0';
modify();
makedirty(curline);
if (setjmp(mainjmp))
if (InJoverc) { /* this is a kludge */
abort++;
goto cleanup;
}
for (;;) {
exp = 1;
exp_p = NO;
last_cmd = this_cmd;
init_strokes();
cont: s_mess("%s%s", prompt, linebuf);
Asking = curchar + prompt_len;
c = getch();
if ((c == EOF) || index(delim, c)) {
if (d_proc == 0 || (*d_proc)(c) == 0)
goto cleanup;
} else switch (c) {
case CTL(G):
message("[Aborted]");
abort++;
goto cleanup;
case CTL(N):
case CTL(P):
if (CurAskPtr != 0) {
int n = (c == CTL(P) ? -exp : exp);
CurAskPtr = next_line(CurAskPtr, n);
if (CurAskPtr == curbuf->b_first && CurAskPtr->l_next != 0)
CurAskPtr = CurAskPtr->l_next;
(void) ltobuf(CurAskPtr, linebuf);
modify();
makedirty(curline);
Eol();
this_cmd = 0;
}
break;
case CTL(R):
if (def)
ins_str(def, NO);
else
rbell();
break;
default:
dispatch(c);
break;
}
if (curbuf != AskBuffer)
SetBuf(AskBuffer);
if (curline != curbuf->b_first) {
CurAskPtr = curline;
curline = curbuf->b_first; /* with whatever is in linebuf */
}
if (this_cmd == ARG_CMD)
goto cont;
}
cleanup:
pop_env(savejmp);
LastCmd = push_cmd;
exp_p = o_exp_p;
exp = o_exp;
no_typed = (linebuf[0] == '\0');
strcpy(Minibuf, linebuf);
SetBuf(saveb);
InAsk = Asking = Interactive = NO;
if (!abort) {
if (!charp()) {
Placur(ILI, 0);
flusho();
}
if (no_typed)
return 0;
} else
complain(mesgbuf);
return Minibuf;
}
/* VARARGS2 */
char *
ask(def, fmt, va_alist)
char *def,
*fmt;
va_dcl
{
char prompt[128];
char *ans;
va_list ap;
va_start(ap);
format(prompt, sizeof prompt, fmt, ap);
va_end(ap);
ans = real_ask("\r\n", (int (*)()) 0, def, prompt);
if (ans == 0) { /* Typed nothing. */
if (def == 0)
complain("[No default]");
return def;
}
return ans;
}
/* VARARGS1 */
char *
do_ask(delim, d_proc, def, fmt, va_alist)
char *delim,
*def,
*fmt;
int (*d_proc)();
va_dcl
{
char prompt[128];
va_list ap;
va_start(ap);
format(prompt, sizeof prompt, fmt, ap);
va_end(ap);
return real_ask(delim, d_proc, def, prompt);
}
/* VARARGS2 */
yes_or_no_p(fmt, va_alist)
char *fmt;
va_dcl
{
char prompt[128];
int c;
va_list ap;
va_start(ap);
format(prompt, sizeof prompt, fmt, ap);
va_end(ap);
for (;;) {
message(prompt);
Asking = strlen(prompt); /* so redisplay works */
c = getch();
Asking = NO;
switch (Upper(c)) {
case 'Y':
return YES;
case 'N':
return NO;
case CTL(G):
complain("[Aborted]");
default:
add_mess("[Type Y or N]");
SitFor(10);
}
}
/* NOTREACHED */
}
#ifdef F_COMPLETION
static char *fc_filebase;
char BadExtensions[128] = ".o";
static
bad_extension(name, bads)
char *name,
*bads;
{
char *ip;
int namelen = strlen(name),
ext_len,
stop = 0;
do {
if (ip = index(bads, ' '))
*ip = 0;
else {
ip = bads + strlen(bads);
stop++;
}
if ((ext_len = ip - bads) == 0)
continue;
if ((ext_len < namelen) &&
(strcmp(&name[namelen - ext_len], bads) == 0))
return YES;
} while ((bads = ip + 1), !stop);
return NO;
}
f_match(file)
char *file;
{
int len = strlen(fc_filebase);
return ((len == 0) ||
(strncmp(file, fc_filebase, strlen(fc_filebase)) == 0));
}
static
isdir(name)
char *name;
{
struct stat stbuf;
char filebuf[FILESIZE];
PathParse(name, filebuf);
return ((stat(filebuf, &stbuf) != -1) &&
(stbuf.st_mode & S_IFDIR) == S_IFDIR);
}
static
fill_in(dir_vec, n)
register char **dir_vec;
{
int minmatch = 0,
numfound = 0,
lastmatch = -1,
i,
the_same = TRUE, /* After filling in, are we the same
as when we were called? */
is_ntdir; /* Is Newly Typed Directory name */
char bads[128];
for (i = 0; i < n; i++) {
strcpy(bads, BadExtensions);
/* bad_extension() is destructive */
if (bad_extension(dir_vec[i], bads))
continue;
if (numfound)
minmatch = min(minmatch,
numcomp(dir_vec[lastmatch], dir_vec[i]));
else
minmatch = strlen(dir_vec[i]);
lastmatch = i;
numfound++;
}
/* Ugh. Beware--this is hard to get right in a reasonable
manner. Please excuse this code--it's past my bedtime. */
if (numfound == 0) {
rbell();
return;
}
Eol();
if (minmatch > strlen(fc_filebase)) {
the_same = FALSE;
null_ncpy(fc_filebase, dir_vec[lastmatch], minmatch);
Eol();
makedirty(curline);
}
is_ntdir = ((numfound == 1) &&
(curchar > 0) &&
(linebuf[curchar - 1] != '/') &&
(isdir(linebuf)));
if (the_same && !is_ntdir) {
add_mess(n == 1 ? " [Unique]" : " [Ambiguous]");
SitFor(7);
}
if (is_ntdir)
Insert('/');
}
extern int alphacomp();
/* called from do_ask() when one of "\r\n ?" is typed. Does the right
thing, depending on which. */
static
f_complete(c)
{
char dir[FILESIZE],
**dir_vec;
int nentries,
i;
if (c == CR || c == LF)
return 0; /* tells ask to return now */
if ((fc_filebase = rindex(linebuf, '/')) != 0) {
char tmp[FILESIZE];
null_ncpy(tmp, linebuf, (++fc_filebase - linebuf));
if (tmp[0] == '\0')
strcpy(tmp, "/");
PathParse(tmp, dir);
} else {
fc_filebase = linebuf;
strcpy(dir, ".");
}
if ((nentries = scandir(dir, &dir_vec, f_match, alphacomp)) == -1) {
add_mess(" [Unknown directory: %s]", dir);
SitFor(7);
return 1;
}
if (nentries == 0) {
add_mess(" [No match]");
SitFor(7);
} else if (c == ' ' || c == '\t')
fill_in(dir_vec, nentries);
else {
/* we're a '?' */
int maxlen = 0,
ncols,
col,
lines,
linespercol;
TOstart("Completion", FALSE); /* false means newline only on request */
Typeout("(! means file will not be chosen unless typed explicitly)");
Typeout((char *) 0);
Typeout("Possible completions (in %s):", dir);
Typeout((char *) 0);
for (i = 0; i < nentries; i++)
maxlen = max(strlen(dir_vec[i]), maxlen);
maxlen += 4; /* pad each column with at least 4 spaces */
ncols = (CO - 2) / maxlen;
linespercol = 1 + (nentries / ncols);
for (lines = 0; lines < linespercol; lines++) {
for (col = 0; col < ncols; col++) {
int isbad,
which;
char bads[128];
which = (col * linespercol) + lines;
if (which >= nentries)
break;
strcpy(bads, BadExtensions);
isbad = bad_extension(dir_vec[which], bads);
Typeout("%s%-*s", isbad ? "!" : NullStr,
maxlen - isbad, dir_vec[which]);
}
Typeout((char *) 0);
}
TOstop();
}
freedir(&dir_vec, nentries);
return 1;
}
#endif
char *
ask_file(prmt, def, buf)
char *prmt,
*def,
*buf;
{
char *ans,
prompt[128],
*pretty_name = pr_name(def);
if (prmt)
sprintf(prompt, prmt);
else {
if (def != 0 && *def != '\0')
sprintf(prompt, ": %f (default %s) ", pretty_name);
else
sprintf(prompt, ProcFmt);
}
#ifdef F_COMPLETION
ans = real_ask("\r\n \t?", f_complete, pretty_name, prompt);
if (ans == 0 && (ans = pretty_name) == 0)
complain("[No default file name]");
#else
ans = ask(pretty_name, prompt);
#endif
PathParse(ans, buf);
return buf;
}