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*/
 |