[comp.sources.misc] v07i015: my_wgetstr

allbery@uunet.UU.NET (Brandon S. Allbery - comp.sources.misc) (06/04/89)

Posting-number: Volume 7, Issue 15
Submitted-by: mott@ucscb.UCSC.EDU (Hung H. Le)
Archive-name: my_wgetstr

	my_wgetstr() is equipvalent to wgetstr() in "curses" but
with line editing feature. Will recognize erase, kill and 
control-w as editing characters.
------------------------------------------------------------
Hung H. Le
mott@ucscb.ucsc.edu           ...!ucbvax!ucscc!ucscb!mott
mott@ucscd.BITNET            #include <std_disclaimer>
------------------------------------------------------------

--- Include shar file --
#! /bin/sh
# This is a shell archive, meaning:
# 1. Remove everything above the #! /bin/sh line.
# 2. Save the resulting text in a file.
# 3. Execute the file with /bin/sh (not csh) to create the files:
#	README
#	example.c
#	makefile
#	my_wgetstr.c
#	my_wgetstr.h
# This archive created: Sun May 21 10:46:51 1989
# By:	Hung H. Le (Uncle Charlie Summer Camp)
export PATH; PATH=/bin:$PATH
echo shar: extracting "'README'" '(1427 characters)'
if test -f 'README'
then
	echo shar: will not over-write existing file "'README'"
else
sed 's/^	X//' << \SHAR_EOF > 'README'
	X
	X	I wrote my_wgetstr() as a replacement for wgets() in curses.
	X
	XWhat my_getstr() does that wgets() does not?
	X	. line editing as in csh. Erase char, kill char, control-w
	X	are recognized.
	X	. check for overflow. Two possible actions can be taken
	X		1. returns immediately
	X		2. bell() to let user know that buffer is full
	X			only newline and editing chars are passed through at
	X			this point
	X
	XWhat my_getstr() does not do that wgets() does?
	X	. does not check for illegal scrolling.
	X
	XHeader file:
	X	remember to include "my_wgetstr.h"
	X	my_getstr(), RET and NO_RET are defined in there.
	X
	XUsage:
	X	n = my_wgetstr(WINDOW *win, char *str, int size, int ret);
	X	win: the concerned window 
	X	str: storage for input chars
	X	size: my_wgetstr() will get at most (size - 1) chars.
	X	ret: what to do when buffer is full
	X		0: bell()
	X		1: returns
	X	you can use NO_RET or RET
	X	n: number of characters actually gets
	X
	X	my_getstr(char *str, int size, int ret);
	X	is a macro defined as
	X#define my_getstr(str, size) my_wgetstr(stdscr, str, size)
	X	in "my_wgetstr.h"
	X
	Xmy_wgetstr() returns if 
	X	. input is a newline
	X	. if ( (strlen(str) == (size - 1)) and (ret) )
	X
	Xmy_wgetstr() DOES NOT check for illegal scrolling so it is the
	Xprogrammer's job to take care of that.
	X
	XAfter unpack this package. Type "make" to make "example".
	XTry out "example".
	X
	Xwritten by Hung Le 
	Xmott@ucscb.ucsc.edu
	X...!ucbvax!ucscc!ucscb!mott
	X
	X          This code is placed in Public Domain.
	X
SHAR_EOF
if test 1427 -ne "`wc -c < 'README'`"
then
	echo shar: error transmitting "'README'" '(should have been 1427 characters)'
fi
fi # end of overwriting check
echo shar: extracting "'example.c'" '(2271 characters)'
if test -f 'example.c'
then
	echo shar: will not over-write existing file "'example.c'"
else
sed 's/^	X//' << \SHAR_EOF > 'example.c'
	X/*
	X * Example program --
	X * A possible replacement for curses' wgetstr(). Allows
	X * limited editing. Recognizes the erase and kill chars.
	X *
	X * By Hung Le (mott@ucscb.ucsc.edu  ...!ucbvax!ucscc!ucscb!mott)
	X * History:
	X *	01/18/89 - Initial version 
	X *	03/20/89 - add control-w to delete word
	X *
	X * Release to Public Domain 
	X */
	X
	X#include <curses.h>
	X#include <signal.h>
	X/* REMEMBER to include "my_wgetstr.h" */
	X#include "my_wgetstr.h"
	X
	X/* test my_wgetstr() */
	Xmain()
	X{
	X	char buffer[30];
	X	static char *header[] =
	X	{
	X	 "INPUT WINDOW",
	X	 "Look Ma ... Line editing in curses",
	X	 "Erase char to erase, Kill char to delete the whole line",
	X	 "control-w to delete a word, empty input line to quit",
	X	};
	X	char ender[81], *name, *getlogin(), *getenv();
	X	int clean_up(), n;
	X	int x_pos, y_pos;
	X	WINDOW *inwin;
	X
	X	initscr();
	X	clear();
	X	refresh();
	X
	X	/* set up interupt handler */
	X	signal(SIGINT, clean_up);
	X
	X	/* set up input window */
	X	inwin = newwin(8, COLS, 3, 0);
	X	if (inwin == (WINDOW *) NULL)
	X		clean_up();
	X
	X	/* print out header */
	X	box(inwin, '|', '-');
	X	for (n = 0; n < 4; n++)
	X		mvwaddstr(inwin, n + 1, COLS / 2 - strlen(header[n]) / 2, header[n]);
	X	mvwaddstr(inwin, 6, 15, "Enter input --> ");
	X	/* get the prompt positions so we can return at later time */
	X	getyx(inwin, y_pos, x_pos);
	X	wrefresh(inwin);
	X
	X	/* now get string */
	X	do
	X	{
	X		/* clear last input */
	X		wmove(inwin, y_pos, x_pos);
	X		wclrtoeol(inwin);
	X		box(inwin, '|', '-');
	X		wrefresh(inwin);
	X
	X		/*
	X		 * get string. NO_RET=0 and RET=1 are defined in
	X		 * "my_wgetstr.h" 
	X		 */
	X		n = my_wgetstr(inwin, buffer, sizeof(buffer), NO_RET);
	X
	X		/* print out the result of my_wgetstr */
	X		move(15, 15);
	X		clrtoeol();
	X		mvprintw(15, 15, "Received %d chars -- \"%s\"", n, buffer);
	X		refresh();
	X
	X		/* move back to the input prompt */
	X		wmove(inwin, y_pos, x_pos);
	X		wrefresh(inwin);
	X	}
	X	while (n != 0);		/* while input is not empty */
	X
	X	name = getenv("NAME");
	X	if (name == (char *) NULL)	/* use login if NAME is not set */
	X		name = getlogin();
	X	/* say good bye */
	X	move(15, 15);
	X	clrtoeol();
	X	sprintf(ender, "GOOD BYE, \"%s\"", name);
	X	mvprintw(15, COLS / 2 - strlen(ender) / 2, "%s", ender);
	X
	X	/* move to last line ... looks cleaner this way */
	X	move(LINES - 1, 0);
	X	refresh();
	X	clean_up();
	X}
	X
	Xclean_up()
	X{
	X	endwin();
	X	exit();
	X}
SHAR_EOF
if test 2271 -ne "`wc -c < 'example.c'`"
then
	echo shar: error transmitting "'example.c'" '(should have been 2271 characters)'
fi
fi # end of overwriting check
echo shar: extracting "'makefile'" '(128 characters)'
if test -f 'makefile'
then
	echo shar: will not over-write existing file "'makefile'"
else
sed 's/^	X//' << \SHAR_EOF > 'makefile'
	XLIBS= -lcurses -ltermcap
	XOBJS= example.o my_wgetstr.o
	XCFLAGS= -s -O
	X
	Xexample: $(OBJS)
	X	cc $(CFLAGS) -o example $(OBJS) $(LIBS) 
SHAR_EOF
if test 128 -ne "`wc -c < 'makefile'`"
then
	echo shar: error transmitting "'makefile'" '(should have been 128 characters)'
fi
fi # end of overwriting check
echo shar: extracting "'my_wgetstr.c'" '(3993 characters)'
if test -f 'my_wgetstr.c'
then
	echo shar: will not over-write existing file "'my_wgetstr.c'"
else
sed 's/^	X//' << \SHAR_EOF > 'my_wgetstr.c'
	X/*
	X * A possible replacement for curses' wgetstr(). Allows
	X * line editing as in csh. 
	X * Recognizes the erase, kill chars, word deleting.
	X *
	X * By Hung Le (mott@ucscb.ucsc.edu  ...!ucbvax!ucscc!ucscb!mott)
	X * History:
	X *	01/18/89 - Initial version 
	X *	03/20/89 - Add control-w to delete word
	X *  05/17/89 - add option to return immediately or to bell()
	X *			when buffer is full.
	X *
	X * Release to Public Domain 
	X */
	X#include <curses.h>
	X#include <sys/ioctl.h>
	X#include <sgtty.h>
	X
	X#define STD_INPUT 0		/* standard input */
	X#define NEWLINE '\n'
	X#define SPACE ' '
	X/* default for erase and kill characters */
	X#define ERASE '\010'
	X#define KILL '\025'
	X#define WORD '\027'
	X
	X/* You bugger !!! you did something wrong */
	X#define bell() fprintf(stderr,"%c", '\007')
	X
	X/*
	X * my_wgetstr(WINDOW *win, char *str, int size, int ret)
	X *	win: the concerned window
	X * 	str: buffer holding input
	X *	size: (size -1) is the maximum chars to get
	X *	ret: flag indicating what to do when (size -1) is reached
	X *		0: ring bell()
	X *		1: returns
	X *		two macros are defined in "my_wgetstr.h" as RET=1 and NO_RET=0
	X *
	X * works same as wgetstr() in curses but allows editing.
	X * Recognizes the erase character and the kill character and
	X * WORD as the word deleting char.
	X * Will try to get the erase and kill char from the terminal setting.
	X * If failed, will use the default ERASE and KILL definitions.
	X * Word char is set to WORD.
	X *
	X * DOES NOT check for illegal scrolling.
	X * Returns
	X *	. when received a new line character 
	X *	. if ( (strlen(str) == (size - 1)) and (ret) )		
	X *
	X * str[size - 1] must be set to '\0' to end the string properly 
	X * so my_wgetstr(errwin, str, 8) will get at most 7 characters.
	X *
	X * Returned value is the number of chars read. 
	X */
	X
	Xmy_wgetstr(win, str, size, ret)
	XWINDOW *win;
	Xchar *str;
	Xint size;
	Xint ret;
	X{
	X	struct sgttyb ttyb;
	X	char erase_char, kill_char;
	X	register int x_pos, y_pos, index, in;
	X
	X	if (ioctl(STD_INPUT, TIOCGETP, &ttyb) == -1)
	X	{
	X		/*
	X		 * failed to get terminal setting. Let's use the default
	X		 * ERASE and KILL 
	X		 */
	X		erase_char = ERASE;
	X		kill_char = KILL;
	X	}
	X	else
	X	{
	X		erase_char = ttyb.sg_erase;
	X		kill_char = ttyb.sg_kill;
	X	}
	X
	X	/*
	X	 * since we are going to set noecho() and crmode() let's be safe and
	X	 * save the current tty 
	X	 */
	X	savetty();
	X	noecho();
	X	crmode();
	X
	X	/* get current position */
	X	getyx(win, y_pos, x_pos);
	X	/* intializing */
	X	index = 0;
	X	str[index] = '\0';
	X
	X	/* while input char is not NEWLINE */
	X	while ((in = getch() & 0177) != NEWLINE)
	X	{
	X		/* if buffer is full (size -1) */
	X		if (index >= size - 1)
	X			if (ret)/* return flag set, return immediately */
	X				break;
	X			else	/* allows editing chars to pass through */
	X			if ((in != erase_char) && (in != kill_char) && (in != WORD))
	X			{
	X				/* warns user that buffer is full */
	X				bell();
	X				continue;
	X			}
	X
	X		if (in == erase_char)	/* ERASING */
	X		{
	X			if (index > 0)
	X			{
	X				mvwaddch(win, y_pos, --x_pos, SPACE);
	X				str[--index] = SPACE;
	X				wmove(win, y_pos, x_pos);
	X			}
	X			else
	X				bell();
	X		}
	X		else
	X		if (in == kill_char)	/* KILLING */
	X		{
	X			if (index > 0)
	X				while (index > 0)
	X				{
	X					mvwaddch(win, y_pos, --x_pos, SPACE);
	X					str[--index] = SPACE;
	X					wmove(win, y_pos, x_pos);
	X				}
	X			else
	X				bell();
	X		}
	X		else
	X		if (in == WORD)	/* WORD DELETING */
	X		{
	X			if (index > 0)
	X			{
	X				/* throw away all spaces */
	X				while ((index > 0) && (str[index - 1] == SPACE))
	X				{
	X					mvwaddch(win, y_pos, --x_pos, SPACE);
	X					str[--index] = SPACE;
	X					wmove(win, y_pos, x_pos);
	X				}
	X				/* move back until see another space */
	X				while ((index > 0) && (str[index - 1] != SPACE))
	X				{
	X					mvwaddch(win, y_pos, --x_pos, SPACE);
	X					str[--index] = SPACE;
	X					wmove(win, y_pos, x_pos);
	X				}
	X			}
	X			else
	X				bell();
	X		}
	X		else
	X		{
	X			mvwaddch(win, y_pos, x_pos++, in);
	X			str[index++] = in;
	X		}
	X		/* show result */
	X		wrefresh(win);
	X	}
	X	/* ends the string properly */
	X	str[index] = '\0';
	X	/* restore the tty */
	X	resetty();
	X	/* returns number of chars read */
	X	return (index);
	X}
SHAR_EOF
if test 3993 -ne "`wc -c < 'my_wgetstr.c'`"
then
	echo shar: error transmitting "'my_wgetstr.c'" '(should have been 3993 characters)'
fi
fi # end of overwriting check
echo shar: extracting "'my_wgetstr.h'" '(400 characters)'
if test -f 'my_wgetstr.h'
then
	echo shar: will not over-write existing file "'my_wgetstr.h'"
else
sed 's/^	X//' << \SHAR_EOF > 'my_wgetstr.h'
	X/*
	X * A possible replacement for curses' wgetstr(). Allows
	X * limited editing. Recognizes the erase and kill chars.
	X *
	X * By Hung Le (mott@ucscb.ucsc.edu  ...!ucbvax!ucscc!ucscb!mott)
	X * History:
	X *	05/18/89 - Initial version 
	X *
	X * Release to Public Domain 
	X */
	X
	X/* following the curses's convention */
	X#define my_getstr(str,size,ret) my_wgetstr(stdscr,str,size,ret)
	X#define RET 1
	X#define NO_RET 0
	X
SHAR_EOF
if test 400 -ne "`wc -c < 'my_wgetstr.h'`"
then
	echo shar: error transmitting "'my_wgetstr.h'" '(should have been 400 characters)'
fi
fi # end of overwriting check
#	End of shell archive
exit 0