326 lines
9.2 KiB
C
326 lines
9.2 KiB
C
|
/* ELLE - Copyright 1982, 1987 by Ken Harrenstien, SRI International
|
|||
|
* This software is quasi-public; it may be used freely with
|
|||
|
* like software, but may NOT be sold or made part of licensed
|
|||
|
* products without permission of the author.
|
|||
|
*/
|
|||
|
/* EEQUES - Handle queries and status displays
|
|||
|
*/
|
|||
|
#include "elle.h"
|
|||
|
|
|||
|
/*
|
|||
|
* Ask -- ask the user for some input on the lowest line of the screen
|
|||
|
*
|
|||
|
* The arg is a string in printf form, followed by up to three args
|
|||
|
* for the printf string
|
|||
|
*
|
|||
|
* The string is read into a sort of mini buffer, only the
|
|||
|
* last line of which is visible on the screen. All editing
|
|||
|
* features are available to the user to edit the input string.
|
|||
|
* When the delim character is typed, input is terminated and
|
|||
|
* The input string is passed back to the caller.
|
|||
|
* The delim is either an escape or a cr.
|
|||
|
* IT IS UP TO THE CALLER TO FREE THIS MEMORY.
|
|||
|
*
|
|||
|
* Note that the actual length of the returned string can be found
|
|||
|
* in the global variable ask_len. This is a crock but allows
|
|||
|
* callers to hack nulls in arg strings if they want to.
|
|||
|
*/
|
|||
|
|
|||
|
int chg_win();
|
|||
|
struct window *make_mode();
|
|||
|
|
|||
|
static int ask_lin; /* Saved cursor location when ask is done */
|
|||
|
static int ask_blen; /* Non-zero if buffer contains something */
|
|||
|
static int ask_cnt; /* Incremented by ask(), cleared by askclr() */
|
|||
|
|
|||
|
/* Table of allowed functions during ASK */
|
|||
|
static char askftab[] = {
|
|||
|
FN_PFXMETA, FN_INSSELF, FN_BEGLINE, FN_ENDLINE, FN_BCHAR, FN_FCHAR,
|
|||
|
FN_DCHAR, FN_BDCHAR, FN_TCHARS, FN_QUOTINS, FN_UARG, FN_BKPT,
|
|||
|
FN_DEBUG,
|
|||
|
FN_GOBEG, FN_GOEND, FN_FWORD, FN_BWORD, FN_KWORD, FN_BKWORD,
|
|||
|
FN_UCWORD, FN_LCWORD, FN_UCIWORD, FN_ARGDIG, FN_NEWWIN, FN_KLINE,
|
|||
|
FN_UNKILL, FN_BKLINE,
|
|||
|
0
|
|||
|
};
|
|||
|
|
|||
|
char *
|
|||
|
ask (string, arg1, arg2, arg3)
|
|||
|
char *string, *arg1, *arg2, *arg3;
|
|||
|
|
|||
|
{ register int i, c;
|
|||
|
register char *s;
|
|||
|
struct window *oldwin;
|
|||
|
char *newline; /* where output line goes */
|
|||
|
char cbuf[200]; /* For prompt string creation */
|
|||
|
int p_length; /* length of prompt */
|
|||
|
chroff anslen; /* Length of answer */
|
|||
|
int funnum; /* Crock stuff */
|
|||
|
#if FX_FILLMODE
|
|||
|
extern int fill_mode;
|
|||
|
int ofillmode = fill_mode; /* Gotta turn this one off */
|
|||
|
fill_mode = 0;
|
|||
|
#endif /*FX_FILLMODE*/
|
|||
|
|
|||
|
oldwin = cur_win;
|
|||
|
chg_win (ask_win);
|
|||
|
ed_reset(); /* Flush contents & request redisp */
|
|||
|
ask_lin = cur_win->w_pos; /* Set here in case never redisp */
|
|||
|
ask_cnt++; /* Bump # of times called */
|
|||
|
|
|||
|
/* copy 'string' into line */
|
|||
|
cbuf[0] = 0;
|
|||
|
asklp: sprintf (&cbuf[strlen(cbuf)], string, arg1, arg2, arg3);
|
|||
|
p_length = strlen(cbuf); /* Find how long it is */
|
|||
|
|
|||
|
/* now let the user type in */
|
|||
|
for(;;)
|
|||
|
{
|
|||
|
if ((rd_type & (RDS_WINFLGS|RD_MODE)) && tinwait () == 0)
|
|||
|
{
|
|||
|
e_gobob(); /* Gross crock: insert prompt */
|
|||
|
e_sputz(cbuf); /* Ugh, bletch */
|
|||
|
cur_dot += p_length; /* Temporarily update loc */
|
|||
|
redp(RD_WINRES); /* Do complete re-crunch */
|
|||
|
upd_wind((struct window *)0); /* Don't interrupt */
|
|||
|
/* Ensure mode line is spiffy too. This should
|
|||
|
** only have to be invoked the first time ask_win
|
|||
|
** redisplay is done, and never thereafter.
|
|||
|
*/
|
|||
|
if(rd_type&RD_MODE) /* If mode also needs it, */
|
|||
|
fupd_wind(make_mode(user_win)); /* do it */
|
|||
|
|
|||
|
upd_curs(cur_dot);
|
|||
|
rd_type &= ~(RDS_WINFLGS|RD_MODE);
|
|||
|
ask_lin = curs_lin; /* Remember line cursor on */
|
|||
|
tbufls();
|
|||
|
|
|||
|
e_gobob(); /* More crock: Remove prompt */
|
|||
|
sb_deln((SBBUF *)cur_buf,(chroff)p_length); /* Ugh etc. */
|
|||
|
cur_dot -= p_length; /* Restore loc */
|
|||
|
e_gocur();
|
|||
|
}
|
|||
|
exp = 1;
|
|||
|
exp_p = 0;
|
|||
|
cont: this_cmd = 0;
|
|||
|
c = cmd_read();
|
|||
|
|
|||
|
if (
|
|||
|
#if !(ICONOGRAPHICS)
|
|||
|
c == ESC ||
|
|||
|
#endif /*-ICONOGRAPHICS*/
|
|||
|
c == LF || c == CR)
|
|||
|
break;
|
|||
|
if (c == BELL) /* ^G means punt.. */
|
|||
|
{ chg_win(oldwin);
|
|||
|
ask_blen = 1; /* Assume buffer has something */
|
|||
|
ding((char *)0); /* Clear echo window */
|
|||
|
ask_cnt = 0; /* Nothing for askclr to do */
|
|||
|
#if FX_SKMAC
|
|||
|
km_abort();
|
|||
|
#endif /*FX_SKMAC*/
|
|||
|
#if FX_FILLMODE
|
|||
|
fill_mode = ofillmode;
|
|||
|
#endif /*FX_FILLMODE*/
|
|||
|
return(0); /* Return 0 to indicate we quit */
|
|||
|
}
|
|||
|
/* This censoring section is a real crock! */
|
|||
|
funnum = cmd_idx(c); /* Map key to command */
|
|||
|
while(funnum == FN_PFXMETA) /* Allow META prefix */
|
|||
|
funnum = cmd_idx(c = CB_META|cmd_read());
|
|||
|
for(s = askftab; (i = *s&0377); ++s)
|
|||
|
if(funnum == i) break;
|
|||
|
switch(i)
|
|||
|
{ default: /* Permissible function */
|
|||
|
cmd_xct(c);
|
|||
|
break;
|
|||
|
case FN_NEWWIN: /* Wants redisplay, do specially */
|
|||
|
clear_wind(ask_win);
|
|||
|
break;
|
|||
|
case 0: /* Illegal function */
|
|||
|
ring_bell();
|
|||
|
#if FX_SKMAC
|
|||
|
km_abort();
|
|||
|
#endif /*FX_SKMAC*/
|
|||
|
continue;
|
|||
|
}
|
|||
|
if(this_cmd == ARGCMD)
|
|||
|
goto cont;
|
|||
|
}
|
|||
|
|
|||
|
if((anslen = e_blen()) > 255) /* Ridiculously long? */
|
|||
|
{ strcpy(cbuf,"Huh? Try again - ");
|
|||
|
#if FX_SKMAC
|
|||
|
km_abort();
|
|||
|
#endif /*FX_SKMAC*/
|
|||
|
goto asklp;
|
|||
|
}
|
|||
|
i = anslen;
|
|||
|
e_gobob(); /* Go to start of buffer */
|
|||
|
e_sputz(cbuf); /* Re-insert prompt so buffer == screen */
|
|||
|
ask_blen = i + 1; /* Say buffer has something in it */
|
|||
|
|
|||
|
s = memalloc((SBMO)(i + 1)); /* Allocate fixed loc for answer */
|
|||
|
newline = s; /* Return ptr to allocated string */
|
|||
|
ask_len = i; /* And return (via global) length of string */
|
|||
|
if(i) do { *s++ = e_getc(); }
|
|||
|
while(--i);
|
|||
|
*s = '\0'; /* make sure string terminated */
|
|||
|
chg_win(oldwin);
|
|||
|
#if FX_FILLMODE
|
|||
|
fill_mode = ofillmode;
|
|||
|
#endif /*FX_FILLMODE*/
|
|||
|
return (newline); /* return pointer to data */
|
|||
|
}
|
|||
|
|
|||
|
/* ASKCLR - Clears the echo area (but not immediately) if the last thing
|
|||
|
** done to it was an ask() call. Note that invoking a SAY routine
|
|||
|
** specifically causes this to be a no-op; SAYCLR must be done instead.
|
|||
|
*/
|
|||
|
askclr()
|
|||
|
{
|
|||
|
if(ask_cnt) sayclr(); /* Zap if need be */
|
|||
|
}
|
|||
|
|
|||
|
/* SAY - put up some text on bottom line.
|
|||
|
* Does this intelligently; text stays up until next SAY or
|
|||
|
* screen refresh.
|
|||
|
* SAYNOW - like SAY but forces display right away
|
|||
|
* SAYTOO - adds to existing stuff
|
|||
|
* SAYNTOO - ditto but forces output right away.
|
|||
|
* DING - Ring_bell then SAYNOW
|
|||
|
* DINGTOO - is to DING as SAYNTOO is to SAYNOW.
|
|||
|
* SAYCLR - Clears echo area (but not immediately)
|
|||
|
*/
|
|||
|
#define SAY_NOW 01 /* Force display immediately */
|
|||
|
#define SAY_TOO 02 /* Add to existing stuff */
|
|||
|
#define SAY_BEL 04 /* Ding bell prior to text */
|
|||
|
#define SAY_LEN 010 /* String length specified by 3rd arg */
|
|||
|
|
|||
|
say(str) char *str; { sayall(str, 0); }
|
|||
|
saynow(str) char *str; { sayall(str, SAY_NOW); }
|
|||
|
saytoo(str) char *str; { sayall(str, SAY_TOO); }
|
|||
|
sayntoo(str) char *str; { sayall(str, SAY_NOW|SAY_TOO); }
|
|||
|
ding(str) char *str; { sayall(str, SAY_NOW|SAY_BEL); }
|
|||
|
dingtoo(str) char *str; { sayall(str, SAY_NOW|SAY_TOO|SAY_BEL); }
|
|||
|
saylntoo(str,n) char *str; { sayall(str, SAY_NOW|SAY_TOO|SAY_LEN, n); }
|
|||
|
sayclr() { sayall((char *)0, 0); }
|
|||
|
|
|||
|
sayall(str,flags,len)
|
|||
|
char *str;
|
|||
|
int flags, len;
|
|||
|
{ register struct window *w;
|
|||
|
register f;
|
|||
|
|
|||
|
f = flags;
|
|||
|
w = cur_win;
|
|||
|
|
|||
|
ask_cnt = 0; /* Always reset this */
|
|||
|
if(str == 0 && ask_blen == 0) /* If clearing, and buff empty */
|
|||
|
return; /* nothing to do. */
|
|||
|
chg_win(ask_win);
|
|||
|
if(f&SAY_TOO)
|
|||
|
e_goeob(); /* Add to end of existing stuff */
|
|||
|
else e_reset(); /* Flush previous stuff if any */
|
|||
|
if(str)
|
|||
|
{ if(f&SAY_LEN) /* Insert string to post up */
|
|||
|
ed_nsins(str,len);
|
|||
|
else e_sputz(str);
|
|||
|
}
|
|||
|
ask_blen = e_dot(); /* Remember whether buffer has something */
|
|||
|
|
|||
|
e_setcur(); /* and remember to set dot */
|
|||
|
if(f&SAY_NOW)
|
|||
|
{ if(f&SAY_BEL)
|
|||
|
ring_bell();
|
|||
|
redp(RD_WINRES);
|
|||
|
upd_wind((struct window *)0);
|
|||
|
tbufls();
|
|||
|
}
|
|||
|
else redp(RD_WINRES); /* Set for this window */
|
|||
|
chg_win(w); /* Back to previous window */
|
|||
|
|
|||
|
/* redisplay() does a special check for ask_win->w_redp, so we
|
|||
|
** don't need to set a global flag like RD_CHKALL.
|
|||
|
*/
|
|||
|
}
|
|||
|
|
|||
|
/* YELLAT -- post string on specified line of screen, immediately.
|
|||
|
* Differs from SAYNOW and SAYNTOO in that NO buffer
|
|||
|
* manipulation is done; screen image is hacked directly.
|
|||
|
*/
|
|||
|
|
|||
|
yellat(str, line)
|
|||
|
char *str;
|
|||
|
register int line;
|
|||
|
{ register struct scr_line *s;
|
|||
|
|
|||
|
s = scr[line];
|
|||
|
strncpy(s->sl_nlin, str, scr_wd0);
|
|||
|
s->sl_ncol = strlen(str);
|
|||
|
#if IMAGEN
|
|||
|
s->sl_flg |= SL_REDO;
|
|||
|
#endif
|
|||
|
upd_line(line);
|
|||
|
tbufls();
|
|||
|
}
|
|||
|
|
|||
|
/* YELLTOO -- Append string to previous echo line of screen, immediately.
|
|||
|
** Uses the ask_lin variable which is set by ask().
|
|||
|
** Currently this function is only needed for srchint() in EESRCH.
|
|||
|
*/
|
|||
|
yelltoo(str)
|
|||
|
char *str;
|
|||
|
{ register int i;
|
|||
|
register struct scr_line *s;
|
|||
|
char nstr[MAXLINE];
|
|||
|
|
|||
|
s = scr[ask_lin];
|
|||
|
i = s->sl_col;
|
|||
|
nstr[0] = 0;
|
|||
|
strncat(strncat(nstr, s->sl_line, i), /* Make new string */
|
|||
|
str, MAXLINE - i);
|
|||
|
yellat(nstr, ask_lin); /* Post it */
|
|||
|
}
|
|||
|
|
|||
|
/* BARF - output a message on the bottom line of the screen,
|
|||
|
** bypassing everything (window, buffer, screen image).
|
|||
|
** Does NOT know about SAY's stuff and does not update it!
|
|||
|
** Use only in dire straits...
|
|||
|
** ERRBARF - same but uses a standard error-message prefix.
|
|||
|
*/
|
|||
|
|
|||
|
errbarf(str)
|
|||
|
char *str;
|
|||
|
{
|
|||
|
barf("\007ELLE Internal Error: ");
|
|||
|
tputz(str);
|
|||
|
tbufls();
|
|||
|
}
|
|||
|
|
|||
|
barf(str)
|
|||
|
char *str;
|
|||
|
{
|
|||
|
ask_cnt = 0; /* Ensure askclr() disabled */
|
|||
|
t_curpos(scr_ht - ECHOLINES, 0); /* goto echo area */
|
|||
|
t_cleol();
|
|||
|
tputz(str);
|
|||
|
tbufls();
|
|||
|
curs_col = -1000; /* Say we dunno where cursor is now */
|
|||
|
}
|
|||
|
|
|||
|
#if IMAGEN
|
|||
|
/* Same, but do it far from harm's way */
|
|||
|
barf2(str)
|
|||
|
char *str;
|
|||
|
{
|
|||
|
t_curpos (scr_ht - 1, scr_wid - strlen(str) - 8);
|
|||
|
t_cleol ();
|
|||
|
tputz(str);
|
|||
|
tputz(" --M--");
|
|||
|
tbufls();
|
|||
|
tgetc(); /* Read any char & discard */
|
|||
|
curs_col = -1000; /* Say we dunno where cursor is now */
|
|||
|
}
|
|||
|
#endif /*IMAGEN*/
|