[comp.sources.misc] v04i131: curses-based widget library and dem.

rac@gec-rl-hrc.co.uk (rac) (10/22/88)

Posting-number: Volume 4, Issue 131
Submitted-by: "rac" <rac@gec-rl-hrc.co.uk>
Archive-name: curses-widgets

--------------------------- CUT HERE ------------------------------
#! /bin/sh
# This is a shell archive. To extract the files type 'sh file'
# This archive created on Fri Oct 14 13:28:51 BST 1988

export PATH; PATH=/bin:$PATH
echo 'Shar: extracting 'README' ( 1974 characters)'
if test -f 'README'
then
    echo "Shar: will not overwrite existing file 'README'"
else
    cat << \SHAR_EOF > 'README'
/*****************************************************************************
/*  FILE:		README
/*  DATE:		August 1988.
/*  AUTHOR:		Richard A. Culshaw.
/* DISCLAIMER:		This file is deemed to be public-domain, on the simple
/*			provisos that this section remains in this file and
/*			that code using it do not do so for monetary gain.
/*			Neither the author, nor the authors employees at the
/*			time of developing this code, accept any liability or
/*			responsibility for the use, abuse or misuse of this
/*			code.
/*****************************************************************************/

	Widgetlib is a standard C library which allows the user to define
and interact with widgets (window gadget). The files provided are:

-rw-r--r--   1 pjs      net         1960 Oct 14 13:25 README
-rw-r--r--   1 pjs      net         1144 Oct 14 13:23 makefile
-rw-r--r--   1 pjs      net         2752 Oct 14 13:15 widget.h
-rw-r--r--   1 pjs      net        10946 Oct 14 12:18 widget.ms
-rw-r--r--   1 pjs      net        34817 Oct 14 13:15 widgetlib.c
-rw-r--r--   1 pjs      net         3218 Oct 14 13:14 wpage.c

1) widgetlib.c       (the actual code)
2) widget.h	     (the header file which is needed in programs intending
		      to incorporate the library)
3) widget.ms	     (an explanation of the library and how to use it)
4) wpage.c	     (a little example of the library in use)
5) makefile          (compiles everything together)

Compiling things
================

Type 'make' within the directory which contains the files.
This creates a local library within the directory, and creates the 
executable 'wpage' (a demo for you to play with).

For general use 'widget.h' must be placed in the standard include directory
and the library 'widgetlib.a' must go in a globally accessable place such
as /usr/lib.

Printing doc
============

'widget.ms' was created using the ms macros and can printed using something like
'nroff -ms widget.ms'


Have fun. Richard C.
SHAR_EOF
if test 1974 -ne `wc -c < 'README'`
then
    echo 'Shar: error transmitting 'README' (should have been  1974 charcaters)'
fi
fi
echo 'Shar: extracting 'makefile' ( 1144 characters)'
if test -f 'makefile'
then
    echo "Shar: will not overwrite existing file 'makefile'"
else
    cat << \SHAR_EOF > 'makefile'
/*****************************************************************************
/*  FILE:		makefile
/*  DATE:		August 1988.
/*  AUTHOR:		Richard A. Culshaw.
/* DISCLAIMER:		This file is deemed to be public-domain, on the simple
/*			provisos that this section remains in this file and
/*			that code using it do not do so for monetary gain.
/*			Neither the author, nor the authors employees at the
/*			time of developing this code, accept any liability or
/*			responsibility for the use, abuse or misuse of this
/*			code.
/*****************************************************************************/

# Use -g if you want large, but sdb-,gdb-,dbx-able objects.
OPTIONS= -O

# BSD systems, in particular, will want -lcurses -ltermcap.
CURSES=  -lcurses

# SYS5 systems, in particular, do not have ranlib(1) for their libraries.
# So define this as, for example, touch, if you don't have ranlib.
RANLIB= touch

WDGTLIB= widgetlib.a

all: wpage

widgetlib.a: widgetlib.o widget.h
	ar crv $@ widgetlib.o
	${RANLIB} $@
	rm -f widgetlib.o

wpage: widgetlib.a wpage.o
	cc ${OPTION} -o $@ wpage.o ${WDGTLIB} ${CURSES}

clean:
	rm -f wpage *.o *.a
SHAR_EOF
if test 1144 -ne `wc -c < 'makefile'`
then
    echo 'Shar: error transmitting 'makefile' (should have been  1144 charcaters)'
fi
fi
echo 'Shar: extracting 'widget.h' ( 2752 characters)'
if test -f 'widget.h'
then
    echo "Shar: will not overwrite existing file 'widget.h'"
else
    cat << \SHAR_EOF > 'widget.h'
/*****************************************************************************
/*  FILE:		widget.h
/*  DATE:		August 1988.
/*  AUTHOR:		Richard A. Culshaw.
/*  DESCRIPTION:	Contains the definitions of the widget structures.
/*			It should be included by all programs that want to
/*			use the widget library.
/* DISCLAIMER:		This file is deemed to be public-domain, on the simple
/*			provisos that this section remains in this file and
/*			that code using it do not do so for monetary gain.
/*			Neither the author, nor the authors employees at the
/*			time of developing this code, accept any liability or
/*			responsibility for the use, abuse or misuse of this
/*			code.
/*****************************************************************************/

#include <curses.h>

/* definition for command widget entry in linked list */
struct    cmdwid{
    		WINDOW		*widget;
    		int		id;
    		char		msg[100];
    		char		acpt;
    		int		(*func)();
    		int		length;	
    		int		x,y;
		int		active;
    		struct cmdwid	*next;
    	} *cmdlist;

/* definition for label widget entry in linked list */
struct    lblwid{
    		WINDOW		*widget;
    		int		id;
    		char		msg[100];
    		char		pos;
    		int		length;	
		int		difference;
    		int		x,y;
    		struct lblwid	*next;
    	} *lbllist;

/* definition for togle widget entry in linked list */
struct     tglwid{
    		WINDOW		*widget;
    		int		id;
    		char		msg[100];
    		char		tgl[10][20];
    		char		toggle;
    		int		cur;
	 	int 		total;
    		int		length;
    		int 		xtgl;
    		int		x,y;
		int		active;
    		struct tglwid	*next;
    	} *tgllist;

/* definition for input widget entry in linked list */
struct inpwid{
    		WINDOW		*widget;
    		int 		id;
		char		msg[100];
    		char		acpt;
    		char		*input;
		int		sofi;
		int		exec;
    		int		lofs;
    		int		length;
    		int		x,y;
		int		active;
    		struct inpwid	*next;
    	} *inplist;
    
/* linked list of characters used for activating widgets */	
struct chentry {
    		char		  ch;
    		int	 	  type;
    		int		  id;
		struct chentry    *next;
    	} *actlist;

/* null entries in the various linked list */
#define NULLCMD		(struct cmdwid *)NULL
#define NULLLBL 	(struct lblwid *)NULL
#define NULLTGL 	(struct tglwid *)NULL
#define NULLINP 	(struct inpwid *)NULL
#define NULLCH 		(struct chentry *)NULL

/* part of the specifications for label widgets */
#define CENTRE		1
#define	LEFTJUST	2
#define RIGHTJUST	4
#define NOHIGH		8

/* the types of the widgets */
#define CMD		1
#define TGL		2
#define LBL		3
#define INP		4

#define BLANK		1
#define NOBLANK		0

#define NULLWIDGET	0

#define EXEC		1
#define NOEXEC		0

#define VERTICAL	1
#define HORIZONTAL	2

typedef int WIDGET;
typedef int WIDGETTYPE;

SHAR_EOF
if test 2752 -ne `wc -c < 'widget.h'`
then
    echo 'Shar: error transmitting 'widget.h' (should have been  2752 charcaters)'
fi
fi
echo 'Shar: extracting 'widget.ms' ( 10946 characters)'
if test -f 'widget.ms'
then
    echo "Shar: will not overwrite existing file 'widget.ms'"
else
    cat << \SHAR_EOF > 'widget.ms'
.ND
.LP
.nr PS 12
.nr VS 13
.LP
.nh
.RP
.TL
A Window based Interactive Programming Utility On Unix:
A Library Package for C programmers
.AU
Richard A. Culshaw
.AI
GEC Hirst Research Centre
Data Systems Division
East Lane
Wembley
Middlesex HA9 7PP
.ND
.KS
.SH
INTRODUCTION

.PP
A Widget is a user definable 
.B "window gadget."
 They allow the user to interact with the program in specifying operations to be carried out. Widgetlib is a set of library functions which allows the user to create and interact with 
.B widgets.
A widget can be one of four types :
.LP
      1) 
.B Command 
Widget 
      2) 
.B Label 
Widget
      3) 
.B Toggle 
Widget
      4) 
.B Input 
Widget

.SH
Command Widgets
.PP
A command widget allows the user to select a function to be carried out, e.g in a paging program one such command could be 'Next Page'. In creating a command widget the programmer must pass it the function to be carried out when the widget is selected (activated). The widget is activated using a unique 'activation' character which is displayed in the widget for easy reference.

.SH
Label Widgets
.PP
A label widget is simply a widget which holds a character string such as a heading, which can be changed at will later. The programmer can supply parameters which can either left justify (default), right justify, or centre the message within the widget (which has a user definable width) as well as highlight (default) or dehighlight it.

.SH
Toggle Widgets
.PP
A toggle widget contains a message which indicates the current value of an entity which can be more than one value e.g, Yes/No/Don't-Know. The value is toggled when a given character is pressed. The activation character is also displayed in the widget. At any point the programmer can enquire as to the the current toggle value.

.SH
Input Widgets
.PP
An input widget allows the user to enter information into the program in the form of a string, e.g in a paging program one might want to supply a file name. There are two types of input widgets :

a) The widget is activated immediately on creation therefore an activation character is not required. E.g in a paging program one might have a command widget which activates this type of input widget in order to get a file name.
.LP
b) The widget has an associated activation character so therefore it may be activated at any point after creation. The character is displayed in the widget.

For ease of use the input widgets contain character strings which can explain
there use within the program.
.KE
.bp
.SH
Text Window
.PP
The library also allows the user to define a text window into which the program may report information. On creation the program has to pass a parameter which specifies how much room to leave before the top of the text window. E.g 0 means place the window immediately below the lowest widget, 1 means allow room for one more row of widgets before placing the window. The text window always stretches to the bottom of the screen. The window can be bordered on any 2 opposite sides or on all 4 (effectively boxing 




it).

.SH
Widget Placement
.PP
The library maintains the current X,Y coordinate of the last widget created. When a new widget is created the program must pass a parameter 0 or 1. A 0 means put the new widget on the current row if possible, else go onto the next row. A 1 forces the new widget onto the next row. This means that widgets can only go after preceding ones and not before. But however widgets can be placed over widgets which have previously been destroyed.

.SH
Compiling Things
.PP
In order to use the library, it is necessary to have certain types and variables defined. Therefore, the program must have the line:
.PP
.B "#include <widgets.h>"
.LP
at the top of the source. The header file includes <curses.h>, <sgetty.h>, <stdio.h> so you don't have to include them also. Also compilations should have the following form:
.PP
.B "cc [flags] file ... -lwidgets -lcurses"

.SH
Type Definitions
.LP
The functions which create widgets return a type 
.B WIDGET
which is used for later identification of the widget.
.LP
If a function is required to return a widget identifier, then it will return 
.B NULLWIDGET
upon error.

.SH
Screen Refresh
.LP
The library supports a standard screen refresh invoked by ^L.
.KE
.bp
.KS
.SH
                                              USAGE
.SH
Getting Started
.LP
The first thing to do when using the library is set up the windowing system by calling 
.LP
.in 0.5i
initialisewidgets()
.in 0

.SH
Creating Widgets
.LP
.br

.in 0.5i
WIDGET mkcmdwidget (message, ch, function, row)
.br 
char message[];
.br 
char ch;
.br 
int 
(*func)();
.br 
int line;
.in 0
.LP
Creates a new command widget. message holds the message to be displayed in the command widget. ch is the activation character on which function is executed. row specifies where to place the widget (as described above). The returned value is the widget identifier for later use.

.LP
.in 0.5i
WIDGET mklblwidget (message, position, space, row)
.br
char message[];
.br
int  position, space, row;
.in 0
.LP
Creates a new label widget. Message holds the contents of the label, position specifies how the message is to appear. Using the constants CENTRE, LEFTJUST, RIGHTJUST, NOHIGH, pass a combination to position e.g CENTRE or LEFTJUST|NOHIGH etc.space indicates how large the label widget is to be. A positive value is the absolute length of the widget, whereas value <= 0 specifies how far the widget is to be from the righthand edge of the screen. row specifies where to place the widget (as described above). The r




eturned value is the widget identifier for later use.

.LP
.in 0.5i
WIDGET mktglwidget (message, number, tgl, tglch, row)
.br
char message[];
.br
int  number;
.br
char tgl[10][20];
.br
char tglch;
.br
int  row;
.in 0
.LP
Creates a new toggle widget. message contains a label for the widget, and number holds the number of toggle values. tgl is used for holding actual toggle values which are toggled between using the activation character tglch. At present there is a limit of 10 toggle values, each being a maximum length of 20 characters. row specifies where to place the widget (as described above). The returned value is the widget identifier for later use.
.LP
.KE
.bp
.KS
.in 0.5i
WIDGET mkinpwidget (message, character, input, lengthstr, lengthwid, row, exec)
.br
char message[], character, input[];
.br
int  lengthstr, lengthwid, row, exec; 
.in 0
.LP
Creates a new input widget. message contains the label for the widget, and character is the activation character for the widget. input is the variable in which the user wishes the data obtained from the input widget to be placed, lengthstr is the length of input. lengthwid specifies how big to make the widget. A positive value indicates the absolute length of the widget, where as a value <= 0 indicates how far from the righthand edge the widget is to be. exec is used to indicate whether the widget should b




e activated on creation by (passing EXEC), or should remain dormant until the activation character is used (passing NOEXEC). (n.b when passing EXEC an activation character is not needed therefore one could pass NULL for character.)

.SH
Text Window Management
.LP
.br

.in 0.5i
int opentextwindow (position, border)
.br
int position, border;
.in 0
.LP
Opens and displays the text window. position specifies where the window is to go. i.e position = 0 will place the window immediately below the lowest widget, position = 1 will allow room for 1 more row of widgets below the current lowest before placing the window etc. border is used to indicate whether the window should be bordered. i.e using the parameters VERTICAL & HORIZONTAL, one can specify whether the window should be bordered vertically (passing VERTICAL), horizontally (passing HORIZONTAL), both (pa




ssing VERTICAL|HORIZONTAL), or neither (passing 0). The function returns the number of lines within the window.

.in 0.5i
report (message)
.br
char *message;
.in 0
.LP
Displays the given message in the text window. Scrolling is done automatically when the bottom of the window is reached and is therefore of no concern for the user.

.in 0.5i
cleartextwindow ()
.in 0
.LP
Clears the text window and returns its cursor to the top lefthand corner. 

.in 0.5i
killtextwindow ()
.in 0
.LP
Destroys the text window. The text window can be redefined at a later date.

.SH
Killing Widgets

.LP
.br
.in 0.5i
int killwidget (ptr)
.br
WIDGET ptr;
.in 0
.LP
Kills the given widget. the function returns TRUE if successfull or FALSE if the widget doesn't exist.
.KE
.bp
.KS
.SH
Interaction

.LP
.br
.in 0.5i
WIDGET widgetinput ()
.in 0
.LP
Wait for input from widgets. Program control is passed back when :-
.br
a) A Command widget is activated and control is passed to its associated function.
.br
b) An input widget is activated and after subsequent input, control is passed to the calling function with the widget pointer of the activated input widget.
.br
Activating a toggle widget just toggles the widget, control is only passed back upon one of the above conditions.

.LP
.br
.in 0.5i
int tsttglwidget (ptr)
.br
WIDGET ptr;
.in 0
.LP
Returns the index value of the current state of the given toggle widget (0 < index < number toggle values - 1). Returns FALSE if the given widget does not exist.

.LP
.br
.in 0.5i
int activate (ptr)
.br
WIDGET ptr;
.in 0
.LP
Reactivates a widget which was previously deactivated. Returns TRUE if successful otherwise FALSE.

.LP
.br
.in 0.5i
int deactivate (ptr, blank)
.br
WIDGET ptr;
.br
int    blank;
.in 0
.LP
Deactivates the given active widget. The widget remains on screen but it cannot be activated. blank can be BLANK or NOBLANK which indicates whether the contents of the widget should be blanked out or not while it is inactive. The function returns TRUE if successful or FALSE if the given widget does not exist.

.LP
.br
.in 0.5i
int highlight (ptr)
.br
WIDGET ptr;
.in 0
.LP
Highlights the given widget. Returns TRUE if successful else FALSE if the widget does not exist.

.LP
.br
.in 0.5i
int dehighlight (ptr)
.br
WIDGET ptr;
.in 0
.LP
Turns off the highlighting of the given widget. Returns TRUE if successful else FALSE if the widget does not exist.

.LP
.br
.in 0.5i
int changelblwidget (ptr, message, position)
.br
WIDGET ptr;
.br
char   message[];
.br
int    position;
.in 0
.LP
Changes the contents of the given label widget to that given in message. position specifies how the message is to appear (see mklblwidget). The function returns TRUE if successful else FALSE.
.KE
.KS
.LP
.br
.in 0.5i
WIDGETTYPE widgettype (ptr)
.br
WIDGET ptr;
.in 0
.LP
Returns the type of widget pointed too by ptr. The returned type value is one of CMD, LBL, TGL, INP or FALSE if the widget does not exist.

.SH
Finishing Up

.LP
.br
.in 0.5i
endwidgets ()
.in 0
.LP
Closes down the windowing system and should be used at the end. This function is also automatically called on an interrupt (e.g ^C).
.KE
SHAR_EOF
if test 10946 -ne `wc -c < 'widget.ms'`
then
    echo 'Shar: error transmitting 'widget.ms' (should have been  10946 charcaters)'
fi
fi
echo 'Shar: extracting 'widgetlib.c' ( 34817 characters)'
if test -f 'widgetlib.c'
then
    echo "Shar: will not overwrite existing file 'widgetlib.c'"
else
    cat << \SHAR_EOF > 'widgetlib.c'
/*****************************************************************************
/*  FILE:		widgetlib.c
/*  DATE:		August 1988.
/*  AUTHOR:		Richard A. Culshaw.
/*  DESCRIPTION:	Contains the code to manipulate the widget structures
/*			and the i/o. It forms a single library that should
/*			be linked in with all code using these widgets.
/* DISCLAIMER:		This file is deemed to be public-domain, on the simple
/*			provisos that this section remains in this file and
/*			that code using it do not do so for monetary gain.
/*			Neither the author, nor the authors employees at the
/*			time of developing this code, accept any liability or
/*			responsibility for the use, abuse or misuse of this
/*			code.
/*****************************************************************************/

#include <widget.h>

extern char     *malloc();
int		textwindowdefined = FALSE;
int    		widx, widy;	
int		maxwidy;
int    		scry;
int    		curid;
int		sizescreg;
int		screenborder = 0;

WINDOW    *screen;
WINDOW    *screenbox;
WINDOW    *edge1;
WINDOW	  *edge2;


initialisewidgets ()
/* sets up screen and initialises global variables */
{
    int i, endwidgets();

    widx = widy = scry = 0;
    curid = 1;
    maxwidy = LINES - 3;
    initscr ();
    crmode ();
    noecho ();
    cmdlist = NULLCMD;
    lbllist = NULLLBL;
    tgllist = NULLTGL;
    inplist = NULLINP;
    actlist = NULLCH;
    for (i=0; i<18; i++)
	signal (i, endwidgets);
}

drawtextwindow (y)
/* draws the text window and draws a box around it */
int y;
{
    int i;

    if ((screenborder & VERTICAL) && (screenborder & HORIZONTAL)) {
        box (screenbox, '|', '-');
    	mvwaddch (screenbox, 0, 0, '.');
    	mvwaddch (screenbox, 0, COLS-2, '.');
    	mvwaddch (screenbox, LINES-y-1, 0, '`');
    	mvwaddch (screenbox, LINES-y-1, COLS-2, '\'');
    	touchwin (screenbox);
        wrefresh (screenbox);
    }
    else if (screenborder & HORIZONTAL) {
	waddstr (edge1, "-------------------------------------------------------------------------------");
        waddstr (edge2, "-------------------------------------------------------------------------------");
	wrefresh (edge1);
	wrefresh (edge2);
    }
    else if (screenborder & VERTICAL) {
	for (i=0; i<=sizescreg; i++) {
	    mvwaddch (edge1, i, 0, '|');
	    mvwaddch (edge2, i, 0, '|');
   	}
	wrefresh (edge1);
	wrefresh (edge2);
    }
    touchwin (screen);
    wrefresh (screen);
}

int opentextwindow (position, border)
/* define the text window from current position down + position * widget depth*/
int    position;
int    border;
{
    if ((position >= 0) && (!textwindowdefined) && (widy + 3*position < 21)) {
    	maxwidy = widy + position * 3 + 3;
	if ((border & VERTICAL) && (border & HORIZONTAL)) {
            screenbox = newwin (LINES-maxwidy, COLS-1, maxwidy, 0);
	    screen = newwin (LINES-2-maxwidy, COLS-3, maxwidy+1, 1);
	    sizescreg = LINES-2-maxwidy;
        }
	else if (border & HORIZONTAL) {
	    screen = newwin (LINES-2-maxwidy, COLS-1, maxwidy+1, 0);
    	    edge1 = newwin (1, COLS-1, maxwidy, 0);
            edge2 = newwin (1, COLS-1, LINES-1, 0);
	    sizescreg = LINES-2-maxwidy;
        }
	else if (border & VERTICAL) {
	    screen = newwin (LINES-maxwidy, COLS-3, maxwidy, 1);
	    edge1 = newwin (LINES-maxwidy, 1, maxwidy, 0);
	    edge2 = newwin (LINES-maxwidy, 1, maxwidy, COLS-2);
	    sizescreg = LINES-maxwidy;
        }
	else {
	    screen = newwin (LINES-maxwidy, COLS-1, maxwidy, 0);
	    sizescreg = LINES-maxwidy;
        }
        screenborder = border;
        scrollok (screen, TRUE);
	drawtextwindow (maxwidy);
        wmove (screen, scry, 0);
	wrefresh (screen);
	textwindowdefined = 1;
	return sizescreg;
    }
}

int addtochlist (ch, id, type)
/* add a new character to array of activation chars.
 * returns TRUE if successful (char not already in list) else FALSE
 */
char   	    ch;
int    	    id;
WIDGETTYPE  type;	
{
    struct chentry  *chlist;
    struct chentry  *newentry;
    /* search list to see char already entered in the list */	
    chlist = actlist;
    if (chlist != NULLCH) {
	while (chlist -> next != NULLCH) 
	   if (chlist -> ch == ch)
		return FALSE;           /* char exists => error */
	    else
		chlist = chlist -> next;
    	newentry = (struct chentry*)malloc((unsigned)sizeof(struct chentry));
	chlist -> next = newentry;
    }
    else {
    	newentry = (struct chentry*)malloc((unsigned)sizeof(struct chentry));
	actlist = newentry;
    }
    /* char not there so add to list */
    newentry -> ch = ch;
    newentry -> id = id;
    newentry -> type = type;
    newentry -> next = NULLCH;
    return TRUE;
}


WIDGETTYPE widgettype (ptr)
/* given a widget pointer returns the type of widget.
 */
WIDGET    ptr;
{
    struct cmdwid    *clist;
    struct tglwid    *tlist;
    struct lblwid    *llist;
    struct inpwid    *ilist;

    /* is it a command widget ? */
    for (clist = cmdlist; clist != NULLCMD; clist = clist -> next)       
    	if ((clist != NULLCMD) && (clist -> id == ptr))
    		return CMD;

    /* is it a toggle widget ? */
    for (tlist = tgllist; tlist != NULLTGL; tlist = tlist -> next)       
    	if ((tlist != NULLTGL) && (tlist -> id == ptr))
    		return TGL;

    /* is it a label widget ? */
    for (llist = lbllist; llist != NULLLBL; llist = llist -> next)       
    	if ((llist != NULLLBL) && (llist -> id == ptr))
    		return LBL;

    /* is in an input widget ? */
    for (ilist = inplist; ilist != NULLINP; ilist = ilist -> next)       
    	if ((ilist != NULLINP) && (ilist -> id == ptr))
    		return INP;

    /* doesn't exist, return error */
    return FALSE;             
}

boxwidget (widget, length)
WINDOW	*widget;
int	length;
{
    int i;

    wmove (widget, 0, 1);
    for (i=1; i < length; i++)
       	waddch (widget, '-');
    wmove (widget, 2, 1);
    for (i=1; i < length; i++)
       	waddch (widget, '-');
    mvwaddch (widget, 1, 0, '|');
    mvwaddch (widget, 1, length, '|');
    mvwaddch (widget, 0, 0, '.');
    mvwaddch (widget, 0, length, '.');
    mvwaddch (widget, 2, 0, '`');
    mvwaddch (widget, 2, length, '\'');
}

drawcmdwidget (widget, info, ch, length, boolean)
WINDOW	*widget;
char	info[];
char	ch;
int	length;
int	boolean;
{
    boxwidget (widget, length-1);
    wmove (widget, 1, 1);
    wstandout (widget);
    waddch (widget, ch);
    if (!boolean)
        wstandend (widget);
    wprintw (widget, ":%s", info);
    if (boolean)
        wstandend (widget);
    wrefresh (widget);
}

drawlblwidget (widget, info, pos, difference, space, boolean)
WINDOW	*widget;
char	info[];
char	pos;
int	difference;
int	space;
int	boolean;
{
    boxwidget (widget, space+1);

    /* work out justification */
    if ((pos & LEFTJUST) || (difference == 0))
	wmove (widget, 1, 1);
    else if (pos & RIGHTJUST)
	wmove (widget, 1, 1+difference);
    else if (pos & CENTRE)
	wmove (widget, 1, difference / 2 + 1);
    if (boolean)
        wstandout (widget);
    wprintw (widget, "%s", info);
    if (boolean)
        wstandend (widget);
    wrefresh (widget);
}
  

drawtglwidget (widget, info, tgl, toggle, length, boolean)
WINDOW	*widget;
char	info[];
char	tgl[];
char	toggle;
int	length;
int	boolean;
{
    boxwidget (widget, length-1);
    wmove (widget, 1, 1);
    wstandout (widget);
    wprintw (widget, "%c", toggle);
    if (!boolean)
        wstandend (widget);
    wprintw (widget, ":%s:", info);
    if (!boolean)
    	wstandout (widget);
    wprintw (widget, "%s", tgl);
    wstandend (widget);
    wrefresh (widget);
}

drawinpwidget (widget, info, ch, length, boolean, exec)
WINDOW	*widget;
char	info[];
char	ch;
int	length;
int	boolean;
{
    boxwidget (widget, length-1);
    wmove (widget, 1, 1);
    if (boolean)
    	wstandout (widget);
    if (exec)
 	wprintw (widget, "%s", info);
    else
    	wprintw (widget, "%c:%s", ch, info);
    if (boolean)
    	wstandend (widget);
    waddch (widget, '>');
    wrefresh (widget);
}

screenrefresh ()
/* clear the screen and redraw all the widgets and the text screen if present */
{
    struct cmdwid *clist;
    struct lblwid *llist;
    struct tglwid *tlist;
    struct inpwid *ilist;

    /* clear the entire screen */
    clear();
    refresh();

    /* redraw all the command widgets */
    clist = cmdlist;
    while (clist != NULLCMD) {
	touchwin (clist -> widget);
	wrefresh (clist -> widget);
	clist = clist -> next;
    }

    /* redraw all the label widgets */
    llist = lbllist;
    while (llist != NULLLBL) {
	touchwin (llist -> widget);
	wrefresh (llist -> widget);
	llist = llist -> next;
    }

    /* redraw all the toggle widgets */
    tlist = tgllist;
    while (tlist != NULLTGL) {
	touchwin (tlist -> widget);
	wrefresh (tlist -> widget);
	tlist = tlist -> next;
    }

    /* redraw all the input widgets */
    ilist = inplist;
    while (ilist != NULLINP) {
	touchwin (ilist -> widget);
	wrefresh (ilist -> widget);
	ilist = ilist -> next;
    }

    /* redraw text window if present */
    if (textwindowdefined) {
	touchwin (screen);
	touchwin (screenbox);
    	wrefresh (screenbox);
    	wrefresh (screen);
    }
}

WIDGET widgetinput ()
/* scan standard input for chars and act on them */
{
    struct cmdwid *list;	
    struct chentry *chlist;
    char	  ch;
    int		  i;
    int		  j;

    for (;;)
    {
    	ch = getchar ();

	if (ch == '\014') {
	    screenrefresh ();
	    continue;
	}
    
	chlist = actlist;
	while ((chlist != NULLCH) && (chlist -> ch != ch))
	    chlist = chlist -> next; 
	
	if (chlist == NULLCH)
	    continue;

    	if (chlist -> type == 1) {  /* does char activate a command widget ? */
    	    for (list = cmdlist; list != NULLCMD; list = list->next)
    		if (list -> id == chlist -> id)
		    if (list -> active)
    	 	     	return (*(list -> func))();
    	}
    	else if (chlist -> type == 2) /* does char activate a toggle widget ?*/
    	    togglewidget (chlist -> id);
    	else 
    	    return (getinput (chlist -> id)); /* must activate input widget */	
    }
}

    
togglewidget (id)
/* toggle widget given its id */
WIDGET id;
{
    struct tglwid *list;
    int 	  i=0;
    int 	  x,y;
    int 	  pos;


    list = tgllist;	
    /* find toggle widget with given id */
    while (list -> id != id)
    	list = list -> next;

    if (!list -> active)
	return;

    /* increase its toggle value */
    pos = ++(list -> cur);
    if (pos == list -> total)   /* do we need to wrap round values */
    {	pos = 0;
    	list -> cur = 0;
    }

    /* output new toggle value */
    wstandout (list -> widget);
    mvwaddstr (list -> widget, 1, list -> xtgl, list -> tgl[pos]);
    wstandend (list -> widget);
    getyx (list -> widget, y, x);
    for (; x < list -> length-1; x++)
    	waddch (list -> widget, ' ');
    wrefresh (list -> widget);
    if (textwindowdefined)
    	wrefresh (screen);
}


int getinput (id)
/* get input from an input widget and put value into given place */
WIDGET id;
{
    struct inpwid *list;	
    int 	  i = 0;
    int		 j;
    int		 cursor = 0;
    int		 index = 0;
    WINDOW 	 *widgy;
    int 	 max;
    char	 ch = '\0';
    int		 flag = 0;
    int		 sofi;

    highlight (id);
    list = inplist;
    /* find the input widget with the given id */
    while (list -> id != id)
    	list = list -> next;

    if (!list -> active)
	return;

    widgy = list -> widget;
    sofi = list -> sofi;
    max = list -> length - sofi - 1;
    wmove (widgy, 1, sofi);
    wrefresh (widgy);

    /* repeatidly get chars from stdin until carriage return is pressed */
    while ((ch = getchar()) != '\n') {
    	if ((ch > 31) || (ch == '\025') || (ch == '\014'))
    	{
    	switch (ch) {
	
	/* delete ? */
    	case '\177' : if ((!flag) && (cursor > 0)){ /* chars don't spill over */
    			   cursor -= 1;
    			   mvwaddch (widgy, 1, cursor + sofi, ' ');
    			   wmove (widgy, 1, cursor + sofi);
    			   index -= 1;
    			   wrefresh (widgy);
    			   break;
    		      }
    		      else if (cursor > 0){  /* chars spill over */
    		          index -= 1;
    			  if (index == max-1) {
    			      flag = 0;
    			      mvwaddch (widgy, 1, sofi-1, '>');
    			  }
    			  for (j=0; j < max-1; j++)
    			      mvwaddch (widgy, 1, j+sofi, list -> input [index-max+j+1]);
    			      wmove (widgy, 1, cursor + sofi);
    			      wrefresh (widgy);
    			      break;
    		      }

    		      else        /* nothing to delete ! */	
    			  break;

	/* ^U pressed (delete all) */
    	case '\025' : index = cursor = 0;
    		      wmove (widgy, 1, sofi);
    		      for (j=0; j < max; j++)
    			  waddch (widgy, ' ');
    		      mvwaddch (widgy, 1, sofi-1, '>');
    		      wrefresh (widgy);
    		      break;

	/* ^L pressed (screen refresh) */
	case '\014' : screenrefresh ();
    		      wmove (widgy,1,cursor+sofi);
		      wrefresh (widgy);
		      break;

	/* default = all other chars except remaining control chars */
    	default :    if (index < list -> lofs) {  /* space still remaining ? */
    			 list -> input [index++] = ch;
    	          	 if (cursor == (max-1)) { /* about to spill over ? */
    			    mvwaddch (widgy, 1, sofi-1, '<');
    			    for (j=0; j < max-2; j++)
    				mvwaddch (widgy, 1, j+sofi, list ->input [index-max+j+1]);
    			    mvwaddch (widgy, 1, cursor+sofi-1, ch);
    			    flag = 1;
    		  	  }			
    		  	  else    /* not spilt over */
    			      mvwaddch (widgy, 1, (cursor++) +sofi, ch);
    		  	  wrefresh (widgy);
    		  	  break;
    		          }
    		     else         /* no room left ! */
    			 break;
    		     }
    	}
        }		
    /* terminate input */
    list -> input [index] = '\0';

    /* clean up input line */
    wmove (widgy, 1, sofi);
    for (j=0; j < max; j++)
    	waddch (widgy, ' ');
    mvwaddch (widgy, 1, sofi-1, '>');
    wrefresh (widgy);
    if (textwindowdefined)
    	wrefresh (screen);
    dehighlight (id);
    return id;
}

WIDGET mkcmdwidget (info, acpt, func, line)
/* make a new command widget */
char    info[];
char    acpt;
int    (*func)();
int    line;
{
    struct cmdwid 	*list;
    struct cmdwid 	*temp;
    int 		length = 0;

    while (info [length++] != '\0')   /* work out length of command */
    	;	
    length += 3;
    if ((line == 1) || ((length + widx) > COLS-1) || widx == COLS-1)
    	if (widy + 3 == maxwidy) /* go onto next line */
    	    return NULLWIDGET;
	else {
    	    widy += 3;
    	    widx = 0;          
	}
    if (!addtochlist (acpt, curid, 1))  /* activation char in use ? */
    	return NULLWIDGET;
    
    /* find end of list and allocate memory for new entry */
    temp = cmdlist; 
    if (temp != NULLCMD) {
    	while (temp -> next != NULLCMD)
    	    temp = temp -> next;
    	list = (struct cmdwid *)malloc((unsigned)sizeof(struct cmdwid));
    	temp -> next = list;
    }
    else {
    	list = (struct cmdwid *)malloc((unsigned)sizeof(struct cmdwid));
    	cmdlist = list;
    }

    /* create and display new widget */
    list -> widget = newwin (3, length, widy, widx);

    drawcmdwidget (list -> widget, info, acpt, length, FALSE);

    /* assign information to be withheld */
    list -> x = widx;
    list -> y = widy;
    list -> id = curid;
    strcpy (list -> msg ,info);
    list -> func = func;
    list -> acpt = acpt;
    list -> length = length;
    list -> next = NULLCMD;
    list -> active = TRUE;
    curid += 1;
    widx += length;
    if (textwindowdefined)
    	wrefresh (screen);
    return (curid-1);
}

WIDGET mklblwidget (info, pos, space, line)
/* make a new label widget */
char    info[];
int     pos;
int     space;
int     line;
{
    struct lblwid	*list;
    struct lblwid	*temp;
    int 		length = 0;
    int 		difference;

    if (!((pos & CENTRE) || (pos & LEFTJUST) || (pos & RIGHTJUST)))
	pos = pos|LEFTJUST;

    /* calculate length of label widget */
    while (info [length++] != '\0')    
    	;	
    length -= 1;
    if ((space < length) && (space > 0))    /* not given enough room so error */
    	return NULLWIDGET; 
    
    if (space <= 0)
        if ((line == 1) || (widx == COLS-1))
	    space += COLS - 3;
	else
	    space += COLS - 3 - widx;

    difference = space - length;

    if ((line == 1) || ((space + 2 + widx) > COLS-1) || (widx == COLS-1))
    /* not enough room on existing line so go onto next */
    	if (widy + 3 == maxwidy)
    	    return NULLWIDGET;
	else {
	    widx = 0;
	    widy += 3;
 	}

    /* find end of list and alllocate memory for new entry */
    temp = lbllist;
    if (temp != NULLLBL) {
    	while (temp -> next != NULLLBL)
    	    temp = temp -> next;
    	list = (struct lblwid *)malloc((unsigned)sizeof(struct lblwid));
    	temp -> next = list;
    }
    else {
    	list = (struct lblwid *)malloc((unsigned)sizeof(struct lblwid));
    	lbllist = list;
    }

    /* create new and display new widget */
    list -> widget = newwin (3, space+2, widy, widx);

    drawlblwidget (list -> widget, info, pos, difference, space, !(pos & NOHIGH));

    /* assign information to be withheld */
    list -> x = widx;
    list -> y = widy;
    list -> id = curid;
    strcpy (list -> msg ,info);
    list -> pos = pos;
    list -> length = space+2;
    list -> difference = difference;
    list -> next = NULLLBL;
    curid += 1;
    widx += space+2;
    if (textwindowdefined)
        wrefresh (screen);
    return (curid - 1);
}

WIDGET mktglwidget (info, num, tgl, toggle, line)
/* make a new toggle widget */
char  info[];
int   num;	
char  *tgl[10];
char  toggle;
int   line;
{
    int 		length = 0;
    struct tglwid	*list;
    struct tglwid	*temp;
    int 		xtgl;
    int 		max = 0;
    int 		i, j, x;
    
    /* calculate maximum length of toggle */
    for (i=0; i < num; i++)  
    	{
    	for (j=0, x=0; tgl[i][j] != '\0'; j++)
       	    x++;
    	if ((x-1)>max)
    	    max = x-1;
    	}
    
    while (info [length++] != '\0') 
    	;	
    xtgl = length + 3;
    length = length + max + 5;

    if ((line == 1) || ((length + widx) > COLS-1) || (widx == COLS-1))
        /* not enough room on existing line so go onto next */
    	if (widy + 3 == maxwidy)
    	    return NULLWIDGET;
	else {
	    widx = 0;
	    widy += 3;
	}

    /* add char to activation list if not already in use */
    if (!addtochlist (toggle, curid, 2)) 
    	return NULLWIDGET;

    /* find end of list and allocate memory for new entry */
    temp = tgllist;
    if (temp != NULLTGL) {
    	while (temp -> next != NULLTGL)
    	    temp = temp -> next;
    	list = (struct tglwid *)malloc((unsigned)sizeof(struct tglwid));
    	temp -> next = list;
    }
    else {
    	list = (struct tglwid *)malloc((unsigned)sizeof(struct tglwid));
    	tgllist = list;
    }

    /* create and display new widget */
    list -> widget = newwin (3, length, widy, widx);

    drawtglwidget (list -> widget, info, tgl[0], toggle, length, FALSE);

    /* assign information to be withheld */
    list -> x = widx;
    list -> y = widy;
    list -> id = curid;
    strcpy (list -> msg ,info);
    list -> xtgl = xtgl;
    list -> total = num;
    for (i=0; i<num; i++) 
	strcpy (list -> tgl[i], tgl[i]);
    list -> cur = 0;
    list -> toggle = toggle;
    list -> length = length;
    list -> next = NULLTGL;
    list -> active = TRUE;
    curid += 1;
    widx += length;
    if (textwindowdefined)
        wrefresh (screen);
    return (curid-1);
}

WIDGET mkinpwidget (info, acpt, input, lofs, length, line, exec)
/* make a new input widget */
char	info[];
char    acpt;
char    input[];
int     lofs;
int     length;
int     line;
int	exec;
{
    struct inpwid	*list;
    struct inpwid	*temp;
    int			count = 0;
    int			offset;

    if (exec)
      	offset = 3;
    else
	offset = 5;

    while (info [count++] != '\0')
	;

    if (length <= 0)
	if ((line == 1) || (widx == COLS-1))
	    length += COLS-offset-count;
	else
	    length += COLS-offset-widx-count;
    length += offset-1+count;
    if ((line == 1) || ((length + widx) > COLS-1) || (widx == COLS -1))
        /* if no room on existing line go onto next */
    	if (widy + 3 == maxwidy)
    	    return NULLWIDGET;
	else {
	    widx = 0;
	    widy += 3;
	}

    /* add activation char to list if not already in use */
    if (!addtochlist (acpt, curid, 3)) 
    	return NULLWIDGET;

    /* find end of list and allocate memory for new entry */
    temp = inplist;
    if (temp != NULLINP) {
    	while (temp -> next != NULLINP)
    	    temp = temp -> next;
    	list = (struct inpwid *)malloc((unsigned)sizeof(struct inpwid));
    	temp -> next = list;
    }
    else {
    	list = (struct inpwid *)malloc((unsigned)sizeof(struct inpwid));
    	inplist = list;
    }

    /* create and display new widget */
    list -> widget = newwin (3, length, widy, widx);

    drawinpwidget (list -> widget, info, acpt, length, FALSE, exec);

    /* assign information to be withheld */
    list -> x = widx;
    list -> y = widy;
    list -> id = curid;
    strcpy (list -> msg ,info);
    list -> acpt = acpt;
    list -> input = input;
    list -> lofs = lofs;

    if (exec)
	list -> sofi = count+1;
    else
    	list -> sofi = count+3;

    list -> length = length;
    list -> next = NULLINP;
    list -> exec = exec;
    list -> active = TRUE;
    curid += 1;
    widx += length;
    if (textwindowdefined)
    	wrefresh (screen);
    if (exec)
	getinput (curid-1);
    return (curid-1);
}

cleartextwindow ()
{
    werase (screen);
    wrefresh (screen);
    scry = 0;
}

report (info)
/* place given info into data screen */
char    *info;
{
    int i, count = 0;

    if (textwindowdefined) {
    	if (scry == sizescreg)    /* scroll window if reached bottom */
    	{
    	    scroll (screen);
    	    scry -= 1;
    	}
	for (i=0; info[i] != '\0'; i++)
	    if (info[i] == '\n')
		count += 1;

    	mvwaddstr (screen, scry, 0, info);
    	scry += 1+count;
    	wrefresh (screen);
    }
}

int tsttglwidget (ptr)
/* return the index value of the current state of the given toggle widget */
WIDGET ptr;
{
    struct tglwid *list;
    int		  i=0;

    /* locate the record of the given toggle widget pointer */
    list = tgllist;
    while ((list != NULLTGL) && (list -> id != ptr)) 
    	list = list -> next;

    /* if it exists return index value else return error FALSE */
    if (list -> id == ptr)
    	return list -> cur;
    else
    	return FALSE;
}

deletechentry (ch)
/* remove the entry from character list for killed widget */
char ch;
{
    struct chentry    *chlist;
    struct chentry    *previous;
   
    chlist = actlist;
    if (chlist -> ch == ch) {        /* is required entry at head of list ? */
	actlist = chlist -> next;    
	free ((char*)chlist);        /* deallocate memory for deleted entry */
    }
    else {
	while (chlist -> ch != ch) {  /* locate required entry in the list */
	    previous = chlist;
	    chlist = chlist -> next;
	}
	previous -> next = chlist -> next;  /* remove entry by skiping it */
	free ((char*)chlist);        /* deallocate memory for deleted entry */
    }
}

killcmdwidget (ptr)
/* kill a command widget given a valid pointer */
WIDGET ptr;
{
    struct cmdwid    *clist;
    struct cmdwid    *previous;

    clist = cmdlist;
    if (clist -> id == ptr) {         /* required widget at head of list ? */
	cmdlist = clist -> next;
	werase (clist -> widget);
	wrefresh (clist -> widget);
	delwin (clist -> widget);
	deletechentry (clist -> acpt);
	if ((clist -> x + clist -> length) == widx)   /* if last widget added */
		widx -= clist -> length;              /* pull back widx       */
	free ((char*)clist);
    }
    else {
	while (clist -> id != ptr) {    /* find widget in list */
	   previous = clist;
	   clist = clist -> next;
	}
	previous -> next = clist -> next;   /* skip unrequired widget in list */
	werase (clist -> widget);
	wrefresh (clist -> widget);
	delwin (clist -> widget);
	deletechentry (clist -> acpt);
	if ((clist -> x + clist -> length) == widx)   /* if last widget added */
		widx -= clist -> length;              /* pull back widx       */
	free ((char*)clist);
    }
}

killlblwidget (ptr)
/* kill label widget given a valid pointer */
WIDGET ptr;
{
    struct lblwid    *clist;
    struct lblwid    *previous;

    clist = lbllist;
    if (clist -> id == ptr) {         /* is widget at head of list ? */
	lbllist = clist -> next;
	werase (clist -> widget);
	wrefresh (clist -> widget);
	delwin (clist -> widget);
	if ((clist -> x + clist -> length) == widx)  /* pull back widx if */
		widx -= clist -> length;             /* last widget added */
	free ((char*)clist);
    }
    else {
	while (clist -> id != ptr) {    /* find widget in linked list */
	   previous = clist;
	   clist = clist -> next;
	}
	previous -> next = clist -> next;   /* skip widget in list */
	werase (clist -> widget);
	wrefresh (clist -> widget);
	delwin (clist -> widget);
	if ((clist -> x + clist -> length) == widx)  /* pull back widx if */
		widx -= clist -> length;             /* last widget added */
	free ((char*)clist);
    }
}

killtglwidget (ptr)
/* kill toggle widget given a valid pointer */
WIDGET ptr;
{
    struct tglwid    *clist;
    struct tglwid    *previous;

    clist = tgllist;
    if (clist -> id == ptr) {       /* is widget at head of list ? */
	tgllist = clist -> next;
	werase (clist -> widget);
	wrefresh (clist -> widget);
	delwin (clist -> widget);
	deletechentry (clist -> toggle);
	if ((clist -> x + clist -> length) == widx)  /* pull back widx if */
		widx -= clist -> length;             /* last widget added */
	free ((char*)clist);
    }
    else {
	while (clist -> id != ptr) {    /* find widget in linked list */
	   previous = clist;
	   clist = clist -> next;
	}
	previous -> next = clist -> next;   /* skip widget in list */
	werase (clist -> widget);
	wrefresh (clist -> widget);
	delwin (clist -> widget);
	deletechentry (clist -> toggle);
	if ((clist -> x + clist -> length) == widx)   /* pull back widx if */
		widx -= clist -> length;              /* last widget added */
	free ((char*)clist);
    }
}

killinpwidget (ptr)
/* kill an input widget given a valid pointer */
WIDGET ptr;
{
    struct inpwid    *clist;
    struct inpwid    *previous;

    clist = inplist;
    if (clist -> id == ptr) {        /* is widget at head of list ? */
	inplist = clist -> next;
	werase (clist -> widget);
	wrefresh (clist -> widget);
	delwin (clist -> widget);
	deletechentry (clist -> acpt);
	if ((clist -> x + clist -> length) == widx)   /* pull back widx if */
		widx -= clist -> length;              /* last widget added */
	free ((char*)clist);
    }
    else {
	while (clist -> id != ptr) {   /* locate widget in linked list */
	   previous = clist;
	   clist = clist -> next;
	}
	previous -> next = clist -> next;   /* skip entry in linked list */
	werase (clist -> widget);
	wrefresh (clist -> widget);
	delwin (clist -> widget);
	deletechentry (clist -> acpt);
	if ((clist -> x + clist -> length) == widx)   /* pull back widx if */
		widx -= clist -> length;              /* last widget added */
	free ((char*)clist);
    }
}
	
int killwidget (ptr)
/* kills the widget identified by ptr */
WIDGET ptr;
{
    switch (widgettype (ptr)) {
        case CMD : killcmdwidget (ptr);    /* command widget */
		 home ();
		 return TRUE;
	case TGL : killtglwidget (ptr);    /* toggle widget */
		 home ();
		 return TRUE;
	case LBL : killlblwidget (ptr);    /* label widget */
		 home ();
		 return TRUE;
	case INP : killinpwidget (ptr);    /* input widget */
		 home ();
		 return TRUE;
	case FALSE : return FALSE;           /* doesn't exist */
    }
}

int chactive (ptr, boolean, blank)
/* given a widget ptr and a boolean value will activate/deactivate a widget */
WIDGET ptr;
int boolean;
int blank;
{
    struct cmdwid *clist;
    struct tglwid *tlist;
    struct inpwid *ilist;
    int		  i;

    switch (widgettype (ptr)) {
	case CMD: for (clist = cmdlist; clist != NULLCMD; clist = clist -> next)
		  if ((clist != NULLCMD) && (clist -> id == ptr)) {
			if ((!boolean) && (blank)) {
			    wmove (clist->widget, 1, 1);
			    for (i=0; i < clist->length-2; i++)
				waddch (clist->widget, ' ');
			    wrefresh (clist->widget);
			}
		  	if (textwindowdefined)
	    		    wrefresh (screen);
			return(clist -> active = boolean);
		  }
		  break;
	case TGL: for (tlist = tgllist; tlist != NULLTGL; tlist = tlist -> next)
		  if ((tlist != NULLTGL) && (tlist -> id == ptr)) {
			if ((!boolean) && (blank)) {
			    wmove (tlist->widget, 1, 1);
			    for (i=0; i < tlist->length-2; i++)
				waddch (tlist->widget, ' ');
			    wrefresh (tlist->widget);
			}
		  	if (textwindowdefined)
	    		    wrefresh (screen);
			return(tlist -> active = boolean);
		  }
		  break;
	case INP: for (ilist = inplist; ilist != NULLINP; ilist = ilist -> next)
		  if ((ilist != NULLINP) && (ilist -> id == ptr)) {
			if ((!boolean) && (blank)) {
			    wmove (ilist->widget, 1, 1);
			    for (i=0; i < ilist->length-2; i++)
				waddch (ilist->widget, ' ');
			    wrefresh (ilist->widget);
			}
		  	if (textwindowdefined)
	    		    wrefresh (screen);
			return (ilist -> active = boolean);
		  }
		  break;
	default : return FALSE;
	}
}

int activate (ptr)
/* reactivate a widget given its ptr */
WIDGET ptr;
{
    int boolean;

    boolean = (chactive (ptr, TRUE));
    light (ptr, FALSE);
    return boolean;
}

int deactivate (ptr, blank)
/* deactivates a widget given its ptr */
WIDGET ptr;
int    blank;
{
    return (chactive (ptr, FALSE, blank));
}

int light (ptr, boolean)
/* will highlight or dehighlight a given widget */
WIDGET ptr;
int boolean;
{
    struct cmdwid *clist;
    struct tglwid *tlist;
    struct lblwid *llist;
    struct inpwid *ilist;

    switch (widgettype (ptr)) {
	case CMD: for (clist = cmdlist; clist != NULLCMD; clist = clist -> next)
		  if ((clist != NULLCMD) && (clist -> id == ptr)) {
		      if (clist -> active)
                  	drawcmdwidget (clist->widget,clist->msg,clist->acpt,clist->length,boolean);
		  if (textwindowdefined)
	    		wrefresh (screen);
		  return (clist -> active);
		  }
		  break;

	case TGL: for (tlist = tgllist; tlist != NULLTGL; tlist = tlist -> next)
		  if ((tlist != NULLTGL) && (tlist -> id == ptr)) {
		      if (tlist -> active)
    		  	  drawtglwidget (tlist->widget,tlist->msg,tlist->tgl[tlist->cur],tlist->toggle,tlist->length,boolean);
		  if (textwindowdefined)
	    		wrefresh (screen);
		  return (tlist -> active);
		  }
		  break;

	case LBL: for (llist = lbllist; llist != NULLLBL; llist = llist -> next)
		  if ((llist != NULLLBL) && (llist -> id == ptr))
    		  drawlblwidget (llist->widget,llist->msg,llist->pos,llist->difference,llist->length-2,boolean);
		  if (textwindowdefined)
	    		wrefresh (screen);
		  return TRUE;
		  break;

	case INP: for (ilist = inplist; ilist != NULLINP; ilist = ilist -> next)
		  if ((ilist != NULLINP) && (ilist -> id == ptr)) {
		      if (ilist -> active)
    		  	  drawinpwidget (ilist->widget,ilist->msg,ilist->acpt,ilist->length,boolean,ilist->exec);
		  if (textwindowdefined)
	    		wrefresh (screen);
		  return (ilist -> active);
		  }
		  break;

	}
	return FALSE;
}

int highlight (ptr)
/* highlights the given ACTIVE widget */
WIDGET ptr;
{
    return (light (ptr, TRUE));
}

int dehighlight (ptr)
/* dehighlights the given ACTIVE widget */
WIDGET ptr;
{
    return (light (ptr, FALSE));
}

home ()
/* scans the current state of the screen and places the x,y cursor coordinates
   at the end of widget furthest down and to the right */
{
    struct cmdwid *clist = cmdlist;
    struct lblwid *llist = lbllist;
    struct tglwid *tlist = tgllist;
    struct inpwid *ilist = inplist;
    int           x, y;

    x = y = 0;

    /* look through command widgets */
    while (clist != NULLCMD) {
	if (clist -> y > y) {
	    y = clist -> y;
	    x = clist->x + clist->length;
	}
	else if ((clist->x + clist->length > x) && (clist -> y == y)) {
	    x = clist->x + clist->length;
}
   	clist = clist -> next;
    }

    /* look through toggle widgets */
    while (tlist != NULLTGL) {
	if (tlist -> y > y) {
	    y = tlist -> y;
	    x = tlist->x + tlist->length;
	}
	else if ((tlist->x + tlist->length > x) && (tlist -> y == y)) {
	    x = tlist->x + tlist->length;
}
	tlist = tlist -> next;
    }

    /* look through label widgets */
    while (llist != NULLLBL) {
	if (llist -> y > y) {
	    y = llist -> y;
	    x = llist->x + llist->length;
	}
	else if ((llist->x + llist->length > x) && (llist -> y == y)) {
	    x = llist->x + llist->length;
}
	llist = llist -> next;
    }

    /* look through input widgets */
    while (ilist != NULLINP) {
	if (ilist -> y > y) {
	    y = ilist -> y;
	    x = ilist->x + ilist->length;
	}
	else if ((ilist->x + ilist->length > x) && (ilist -> y == y)) {
	    x = ilist->x + ilist->length;
}
	ilist = ilist -> next;
    }
   
    /* update screen x,y coordinates */
    widx = x;
    widy = y;
}

int changelblwidget (ptr, info, pos)
WIDGET ptr;
char   info[];
int    pos;
{
    struct lblwid *list = lbllist;
    int		  length = 0;

    while ((list != NULLLBL) && (list->id != ptr))
	list = list -> next;

    if (list == NULLLBL)
	return FALSE;

    if (!((pos & CENTRE) || (pos & LEFTJUST) || (pos & RIGHTJUST)))
	pos = pos|LEFTJUST;

    /* calculate length of label widget */
    while (info [length++] != '\0')    
    	;	
    length -= 1;
    if (list->length-2 < length) /* not given enough room so error */
    	return FALSE;
    
    list -> difference = list->length-2 - length;

    strcpy (list -> msg, info);
    list -> pos = pos;
    werase (list->widget);
    drawlblwidget (list->widget,info,pos,list->difference,list->length-2,!(pos & NOHIGH));

    if (textwindowdefined)
	wrefresh (screen);
    return (TRUE);
}

endwidgets ()
/* tidy up at the end */
{
    struct cmdwid *clist = cmdlist;
    struct lblwid *llist = lbllist;
    struct tglwid *tlist = tgllist;
    struct inpwid *ilist = inplist;

    while (clist != NULLCMD) {
	killcmdwidget (clist -> id);
        clist = cmdlist;
    }

    while (llist != NULLLBL) {
	killlblwidget (llist -> id);
	llist = lbllist;
    }

    while (tlist != NULLTGL) {
	killtglwidget (tlist -> id);
	tlist = tgllist;
    }

    while (ilist != NULLINP) {
	killinpwidget (ilist -> id);
	ilist = inplist;
    }

    killtextwindow ();
    endwin ();
    exit (0);
}

killtextwindow ()
/* destroy screen and any borders */
{
    if (textwindowdefined) {
	werase (screen);
	wrefresh (screen);
	delwin (screen);
	textwindowdefined = FALSE;
	if ((screenborder & VERTICAL) && (screenborder & HORIZONTAL)) {
	    werase (screenbox);
	    wrefresh (screenbox);
	    delwin (screenbox);
 	}
	else if ((screenborder & VERTICAL) || (screenborder & HORIZONTAL)) {
	    werase (edge1);
	    werase (edge2);
	    wrefresh (edge1);
	    wrefresh (edge2);
	    delwin (edge1);
	    delwin (edge2);
        }
	maxwidy = LINES - 2;
	screenborder = 0;
    }
}
SHAR_EOF
if test 34817 -ne `wc -c < 'widgetlib.c'`
then
    echo 'Shar: error transmitting 'widgetlib.c' (should have been  34817 charcaters)'
fi
fi
echo 'Shar: extracting 'wpage.c' ( 3218 characters)'
if test -f 'wpage.c'
then
    echo "Shar: will not overwrite existing file 'wpage.c'"
else
    cat << \SHAR_EOF > 'wpage.c'
/*****************************************************************************
/*  FILE:		wpage.c
/*  DATE:		August 1988.
/*  AUTHOR:		Richard A. Culshaw.
/*  DESCRIPTION:	A small demonstration program using the widgets.
/* DISCLAIMER:		This file is deemed to be public-domain, on the simple
/*			provisos that this section remains in this file and
/*			that code using it do not do so for monetary gain.
/*			Neither the author, nor the authors employees at the
/*			time of developing this code, accept any liability or
/*			responsibility for the use, abuse or misuse of this
/*			code.
/*****************************************************************************/

#include <widget.h>

WIDGET	title, nlcmd, npcmd, qcmd, finput, gfile, frac;
char	filename[14];
char    string[20];
int	nolines;
int	filepresent;
FILE	*f;
long	size, ftell();

int readline ()
{
    int   i;
    int	  space;
    char  buffer [80];
    int   count;
    int   ch;

	count = 0;
  	while ((count < 79) && (ch = getc(f)) && (ch != '\n') && (ch != EOF))
	    if (ch == '\t') {
		space = 8 - count % 8;
		for (i=0; i<space; i++)
		    buffer [count++] = ' ';
 	    }
	    else
	    	buffer [count++] = ch;
        buffer [count] = '\0';
        if ((count > 0) || (ch == '\n'));
	    report (buffer);
	return (ch); 
}

changefrac ()
{
    long  cur;
    char  data[5];

    cur = ftell (f);
    sprintf (data, "%ld%%", cur*100L/size);
    changelblwidget (frac, data, RIGHTJUST|NOHIGH);
}


nextline ()
{
    int ch;

    highlight (nlcmd);
    ch = readline ();
    dehighlight (nlcmd);
    if (ch == EOF) {
	deactivate (npcmd, BLANK);
	deactivate (nlcmd, BLANK);
    }
    changefrac ();
    widgetinput ();
}

nextpage ()
{
    int   line  = 0;
    int	  ch;

    highlight (npcmd);
    cleartextwindow ();

    while ((line++ != nolines) && ((ch = readline()) != EOF)) 
	;
	
    dehighlight (npcmd);
    if (ch == EOF) {
	deactivate (npcmd, BLANK);
	deactivate (nlcmd, BLANK);
    }

    changefrac ();
    widgetinput ();
}

quit ()
{
    endwidgets ();
}

getfile ()
{
    int i;

    if (!filepresent) {
        highlight (gfile);
    	killwidget (title);
    	changelblwidget (frac, "", RIGHTJUST|NOHIGH);
    	finput = mkinpwidget ("file", NULL, filename, 14, 0, 0, EXEC);
    	killwidget (finput);
    }
    else
	filepresent = FALSE;
    for (i=5; i<=20; i++)
   	string [i] = filename [i-5]; 
    dehighlight (gfile);
    f = fopen (filename, "r");
    if (f == NULL) {
	cleartextwindow ();	
	report ("File does not exist. Try again");
	getfile ();
    }
    title = mklblwidget (string, CENTRE, 0, 0);
    fseek (f, 0L, 2);
    size = ftell (f);
    rewind (f);
    activate (nlcmd);
    activate (npcmd);
    nextpage ();
}

main (argc, argv)
int	argc;
char	*argv[];
{
    initialisewidgets ();
    if (argc > 1) {
	strcpy (filename, argv[1]);
	filepresent = TRUE;
    }
    strcpy (string, "File=");
    qcmd = mkcmdwidget ("Quit", 'q', quit, 0);
    nlcmd = mkcmdwidget ("Next line", 'n', nextline, 0);
    npcmd = mkcmdwidget ("Next page", 'N', nextpage, 0);
    gfile = mkcmdwidget ("Get file", 'f', getfile, 0);
    frac = mklblwidget ("", CENTRE, 4, 0);
    nolines = opentextwindow (0, HORIZONTAL);
    getfile ();
}	
SHAR_EOF
if test 3218 -ne `wc -c < 'wpage.c'`
then
    echo 'Shar: error transmitting 'wpage.c' (should have been  3218 charcaters)'
fi
fi