home *** CD-ROM | disk | FTP | other *** search
- From: rob@mtdiablo.Concord.CA.US (Rob Bernardo)
- Newsgroups: alt.sources
- Subject: DMM (Data entry and Menu screen Manager) - version 1.1 part 1/2
- Message-ID: <1991Jun18.012151.10052@mtdiablo.Concord.CA.US>
- Date: 18 Jun 91 01:21:51 GMT
-
-
- From the README file:
-
- DMM is a set of C library functions that provide a fairly object-oriented
- front end to curses for the management of data entry and menu screens.
- It requires the System V version of curses.
-
- The sources for these functions are in dmm.c and dmm.h. A make file is
- provided. The make file and sources compile as is under SUN 0S 4.03, 4.1
- and 4.1.1. They may need minor modifications for compilation on other
- flavors of UNIX.
-
- A section 3 manual page is included; it details the use of the functions
- as well as the look and feel of the screens they produce.
-
- A demo program is included and can be compiled using the make file.
- Using DMM effectively can be complex and the demo program demonstrates
- various DMM facilities and points out highlights of the demo sources.
-
- #!/bin/sh
- # shar: Shell Archiver (v1.22)
- #
- # This is part 1 of a multipart archive
- # do not concatenate these parts, unpack them in order with /bin/sh
- #
- # Run the following text with /bin/sh to create:
- # Makefile
- # README
- # dmm.3
- # dmm.c
- # dmm.h
- # dmmdemo.h
- # dmmdemo1.c
- # dmmdemo2.c
- # dmmdemo3.c
- # dmmdemo4.c
- # dmmdemo5.c
- # dmmdemo6.c
- #
- if test -r s2_seq_.tmp
- then echo "Must unpack archives in sequence!"
- next=`cat s2_seq_.tmp`; echo "Please unpack part $next next"
- exit 1; fi
- echo "x - extracting Makefile (Text)"
- sed 's/^X//' << 'SHAR_EOF' > Makefile &&
- X# @(#)Makefile 1.1 Copyright (c) 1991 Robert Bernardo, rob@mtdiablo.Concord.CA.US,
- X# an employee of Pande, Inc. Permission to use granted only if this
- X# notice is not removed from this make file produced from it.
- X
- XCC = /usr/5bin/cc
- X
- X
- XDEMOOBJS = dmmdemo1.o dmmdemo2.o dmmdemo3.o dmmdemo4.o dmmdemo5.o dmmdemo6.o
- Xdmmdemo: $(DEMOOBJS) dmm.o
- X $(CC) $(DEMOOBJS) dmm.o -lcurses -o dmmdemo
- X
- Xdmm: dmm.o
- X
- Xclean:
- X rm -f *.o dmmdemo core
- X
- Xlint:
- X lint -I/usr/5include *.c
- SHAR_EOF
- chmod 0444 Makefile || echo "restore of Makefile fails"
- set `wc -c Makefile`;Sum=$1
- if test "$Sum" != "462"
- then echo original size 462, current size $Sum;fi
- echo "x - extracting README (Text)"
- sed 's/^X//' << 'SHAR_EOF' > README &&
- XThis is the 1.1 version of DMM. It is a beta version. Bugs, fixes,
- Xcomments and suggestions should be sent to Robert Bernardo, at
- Xrob@mtdiablo.Concord.CA.US.
- X
- XDMM is a set of C library functions that provide a fairly object-oriented
- Xfront end to curses for the management of data entry and menu screens.
- XIt requires the System V version of curses.
- X
- XThe sources for these functions are in dmm.c and dmm.h. A make file is
- Xprovided. The make file and sources compile as is under SUN 0S 4.03, 4.1
- Xand 4.1.1. They may need minor modifications for compilation on other
- Xflavors of UNIX.
- X
- XA section 3 manual page is included; it details the use of the functions
- Xas well as the look and feel of the screens they produce.
- X
- XA demo program is included and can be compiled using the make file.
- XUsing DMM effectively can be complex and the demo program demonstrates
- Xvarious DMM facilities and points out highlights of the demo sources.
- X
- X@(#)README 1.1 Copyright (c) 1991 Robert Bernardo,
- Xrob@mtdiablo.Concord.CA.US, an employee of Pande, Inc. Permission to
- Xuse DMM granted only if the copyright notice is not removed from any of
- Xthe component files nor from any binaries produced from them.
- SHAR_EOF
- chmod 0444 README || echo "restore of README fails"
- set `wc -c README`;Sum=$1
- if test "$Sum" != "1183"
- then echo original size 1183, current size $Sum;fi
- echo "x - extracting dmm.3 (Text)"
- sed 's/^X//' << 'SHAR_EOF' > dmm.3 &&
- X.\ @(#)dmm.3 1.1
- X.TH DMM 3 6/13/91
- X.SH NAME
- XdmmRun, dmmReview, dmmInit, dmmClose, dmmPutMsgs, dmmPutMsgsTimer, dmmPutMsgsHit, dmmPutMsgsNext, dmmClear, dmmRmMsgs, dmmGetNumLines - manage data entry and menu screens
- X.SH SYNOPSIS
- X.nf
- X.B #include <dmm.h>
- X.PP
- X.B extern DMMRETTYPE dmmRetType;
- X.PP
- X.B int dmmRun(startField, screen, menu, drawFlag, valFlag)
- X.B int startField;
- X.B DMMSCREEN screen;
- X.B DMMMENU menu;
- X.B DMMDRAWFLAG drawFlag;
- X.B DMMVALFLAG valFlag;
- X.PP
- X.B int dmmReview(screen)
- X.B DMMSCREEN screen;
- X.PP
- X.B void dmmInit()
- X.PP
- X.B void dmmClose()
- X.PP
- X.B void dmmPutMsgs(mesgblock)
- X.B DMMMESGBLK mesgblock;
- X.PP
- X.B void dmmPutMsgsTimer(mesgblock, duration)
- X.B DMMMESGBLK mesgblock;
- X.B unsigned duration;
- X.PP
- X.B void dmmPutMsgsHit(mesgblock)
- X.B DMMMESGBLK mesgblock;
- X.PP
- X.B void dmmPutMsgsNext(mesgblock)
- X.B DMMMESGBLK mesgblock;
- X.PP
- X.B void dmmClear()
- X.PP
- X.B void dmmRmMsgs(removetype)
- X.B DMMREMOVETYPE removetype;
- X.PP
- X.B int dmmGetNumLines()
- X.fi
- X.SH DESCRIPTION
- X.IR "Data entry and Menu Manager" ", " DMM ,
- Xis a set of functions that
- Xprovide a fairly object-oriented interface to
- X.I curses
- Xand enforce a particular look and feel in managing data entry and
- Xmenu screens.
- XThe next two subsections describe this look and feel; subsequent subsections
- Xdescribe the use of the functions.
- X.SS Screen appearance
- X.PP
- XThe screen consists of three
- X.I curses
- Xwindows.
- X.PP
- XThe top line is an instruction window that displays a general user instruction
- Xthat varies with the state that the screen is in.
- X.PP
- XThe next two lines are used by the menu.
- XThe menu is presented as a ring menu.
- XA scrollable list of typically one-word menu items is
- Xdisplayed horizontally on the first of the two lines.
- XWhen the menu is active, one menu item is considered current and is highlighted.
- XThe second line of the menu window is used to display a longer description
- Xof the current menu item.
- XThrough input keystrokes, the user can make a particular menu item current,
- Xand then with a particular keystroke can confirm the
- Xcurrently selected menu item as the choice made.
- X.PP
- XThe rest of the screen is the data entry window. Visually, this window appears
- Xto consist of two sorts of items: editable fields and static, non-editable
- Xphrases (used for headings and for labels of the editable fields).
- XTypically the two are displayed with different attributes (e.g. editable
- Xfields displayed highlighted and the static fields displayed plain).
- XWhen the data entry window is active, one editable field is considered
- Xcurrent, and the cursor is placed inside it.
- XTypically the current editable field is displayed with a different
- Xhighlighting attribute from the other editable fields.
- XThe user can edit the current field, or move to another field,
- Xmaking it current.
- XWhen the user enters a keystroke to move to another field, the value of
- Xthe then-current field may be audited and,
- Xif found in error, an error message displayed and the cursor
- Xis moved to its first character position;
- Xotherwise the cursor is moved to first character position of that other field,
- Xwhich is made current.
- X.PP
- XWhile the screen is interactive,
- Xeither the menu or the data entry window will be active.
- XThrough a particular keystroke, the user can switch between these two states.
- XTypically, a screen consists of both a menu and a data entry window (though
- Xonly one of the two are required) and starts with the data entry window
- Xactive and a program-specified field current.
- XThe user may enter data in the editable fields and then go to the menu
- Xto select an action to happen, such as to go forward with the data as entered,
- Xor perhaps to ignore the data and just pop back up to a higher menu.
- X.PP
- XIn either menu or data entry state, the user can enter a keystroke that
- Xdisplays help information.
- X.SS User input
- X.PP
- XThe following user input keystrokes have similar effects
- Xin both menu and data entry states:
- X.PD 0
- X.TP 20
- Xcontrol-g
- XToggles between the menu and data entry states.
- X.TP 20
- Xcontrol-h
- XDisplays a screen giving this keystroke-effect information.
- X.TP 20
- Xcontrol-r
- XRedraws the entire screen.
- X.TP 20
- Xtab, control-n
- XMakes the next editable field or menu item current.
- X.TP 20
- Xcontrol-p
- XMakes the preceding editable field or menu item current.
- X.PD
- X.PP
- XThe following user input keystrokes are particular to the menu state:
- X.PD 0
- X.TP 20
- Xcarriage return
- XChoses the current menu item.
- X.TP 20
- Xalpha character
- XMakes current the single menu item that begins with the alpha character.
- XIf there is not exactly one such menu item, the screen is flashed.
- X.PD
- X.PP
- XThe following user input keystrokes are particular to the data entry state:
- X.PD 0
- X.TP 20
- Xcontrol-c
- XClears current editable field from current position to end of field and makes
- Xthe next editable field current.
- X.TP 20
- Xcarriage return
- XMakes the the next editable field current.
- X.TP 20
- Xarrow key
- XMoves the cursor in the indicated direction within the current editable field
- Xif possible.
- X.TP 20
- Xdelete
- XErases the character to the left of the cursor, i.e.
- Xreplaces it with a blank and moves the cursor left,
- Xif not in the first character position in the current editable field.
- XIf it is in the last character position, and the last character is not blank,
- Xit erases the character under the cursor and leaves the cursor there.
- X.TP 20
- Xprinting character
- XInserts the character in the current editable field at the cursor position
- X(and advances the cursor within the field
- Xif not at the last character position of the field)
- X.PD
- X.PP
- XAny other keystroke will flash the screen.
- X.SS Screen specification
- X.PP
- XAn invocation of the function
- X.B dmmRun
- Xmanages the display and operation of a screen
- Xand engages the user in interaction with the screen.
- X.PP
- XThe layout of the data entry window is specified by
- X.IR screen ,
- Xa null terminated array of pointers to DMMFIELD structures, defined in
- X.IR dmm.h .
- X.PP
- XEach DMMFIELD describes one data entry field. Its elements describe
- Xtwo parts of the data entry field. The label elements describe the
- Xconstant part of the field, which may be used for display of headings,
- Xdata or a label for the editable part. The input elements describe the editable
- Xpart, a field on the screen where the user can move the cursor and input data.
- XThe editable part of a field is realized as a (nearly) rectangular area within
- Xthe window.
- X.TP 20
- XlabelValue
- XA non-editable string to be displayed.
- XA NULL value indicates no string to display.
- X.TP 20
- X.PD 0
- XlabelCol,
- X.TP 20
- X.PD
- XlabelLine
- XThe coordinates in the data entry window where the first character of
- X.I labelValue
- Xis displayed.
- XA negative line number represents lines from the bottom
- Xof the window, the bottom line represented with -1.
- X.TP 20
- XlabelAttrib
- XThe attributes with which the label is displayed, given as the logical
- X.IR or -ing
- Xof the attribute constants given in <curses.h>, or 0L for no attributes.
- X.TP 20
- XinputLength
- XThe number of data characters to accept from the user for editable part of
- Xthe field.
- XThis governs the total size of the rectangular input area.
- XIf 0,
- Xthe field is considered to have no editable part;
- Xthis is useful for the presentation of display-only data on the screen,
- Xe.g. headings.
- X.TP 20
- XinputEditValue
- XA buffer of length
- X.I inputLength
- X+ 1 (for the terminating null) used to store the data as entered or
- Xedited by the user.
- X.TP
- XinputInitValue
- XA string with an initial value to be copied to inputEditValue before user
- Xinteraction.
- X(This is dependent on the value of
- X.I valFlag
- X- see below.)
- XThe string must no be longer than
- X.I inputLength.
- XA NULL value is treated the same as a zero-length string.
- X.TP 20
- X.PD 0
- XinputCol,
- X.TP 20
- X.PD
- XinputLine
- XThe coordinates in the data entry window where the upper left corner
- Xof the input area is displayed.
- XA negative column value designates a column position that
- Xis that many intervening columns to the right of the last character of
- X.IR labelValue .
- XA negative line number represents lines from the bottom
- Xof the window, the bottom line represented with -1.
- X.TP 20
- XinputMaxCols
- XThe width of the rectangular input area. If smaller than
- X.I inputLength
- Xthe rectangular area will be more than one line in height.
- XIf 0,
- Xthe width is taken from
- X.IR inputLength ,
- Xi.e. the rectangular area will be exactly one line.
- X.TP
- X.PD 0
- XinputFullLines,
- X.TP 20
- X.PD
- XinputShortCols
- XTo be left unset by the calling function and calculated by
- X.BR dmmRun .
- XThey represent the number of lines of full width in the rectangular area
- Xand the number of columns in the last ``remainder'' line of the rectangular
- Xarea, respectively.
- XActually, because of the ``remainder'' line, the rectangular area is not
- Xalways an exact rectangle.
- X.TP 20
- XinputAttrib
- XThe attributes with which the rectangular area is displayed when
- Xthe field is not current.
- XSee
- X.I labelAttrib
- Xfor a description of possible values.
- X.TP 20
- XinputEditAttrib
- XThe attributes with which the rectangular area is displayed when the field
- Xis current.
- XSee
- X.I labelAttrib
- Xfor a description of possible values.
- XThe value A_INVIS can be used for such things as password fields.
- XDespite the warning in <curses.h> that this value is not supported,
- Xit is safe to use because its realization within
- X.I DMM
- Xis independent of that of
- X.IR curses .
- X.TP 20
- XinputInstructVec
- XA null terminated array of string pointers which should contain detailed
- Xinstructions to the user on how to edit the field.
- XThey are displayed, when the field is current,
- Xat the bottom of the screen, one string per line.
- XA NULL value indicates no instructions to display.
- X.TP
- XinputNumInstructs
- XTo be left unset by the calling function and calculated by
- X.B dmmRun
- Xas the number of strings in
- X.IR inputInstructVec .
- X.TP 20
- XinputAudit
- XA pointer to a function that returns an
- X.IR int .
- XIt is invoked with
- X.I inputEditValue
- Xas its single argument
- Xwhen the user enters a keystroke that would make the field non-current.
- XThis function is useful for auditing the value of
- X.I inputEditValue
- Xand displaying audit error messages to the user (using the message display
- Xfunctions described below).
- XIf NULL, it is not invoked.
- XThe function must accept a single
- X.I char *
- Xargument and must return one of the following DMMAUDITRETURN values, defined in
- X.IR dmm.h :
- X.RS 20
- X.TP 20
- XdmmAuditOkay
- XWhen returned the cursor is advanced to the appropriate editable field.
- XUseful when the value of
- X.I inputEditValue
- Xis okay.
- X.TP 20
- XdmmAuditBad
- XWhen returned the cursor is moved to the first position of the current input
- Xfield.
- XUseful when the value of
- X.I inputEditValue
- Xis needs correction by the user.
- X.TP 20
- X.PD 0
- XdmmAuditReturnOkay,
- X.TP 20
- X.PD
- XdmmAuditReturnBad
- XUseful when an inter-field audit needs to be performed.
- XThese two values cause
- X.B dmmRun
- Xto return with
- X.B dmmRetType
- Xset to
- X.I dmmOkayField
- Xor
- X.IR dmmBadField ,
- Xrespectively, and the return value of
- X.B dmmRun
- Xset to the number of the current editable field.
- XThe calling function can then do its inter-field audit, such as might be
- Xnecessary when the two fields are month-of-year and day-of-month, where
- Xlegal values are interdependent and then reinvoke
- X.BR dmmRun .
- XSee the discussion of
- X.I startField
- Xbelow for further details on reinvocations of
- X.B dmmRun
- Xafter an inter-field audit.
- X.RE
- X.TP 20
- X.PD 0
- XnextInField,
- X.TP 20
- X.PD
- XprevInField
- XTo be left unset by the calling function and calculated by
- X.BR dmmRun .
- X.PP
- XSome user keystrokes cause the next or preceding editable field to
- Xbecome current.
- XThe order of editable fields is taken from the order of the DMMFIELD
- Xstructures in
- X.IR screen ;
- Xthis list is considered circular,
- Xe.g. the editable field that comes next after the
- Xlast editable field is the first editable field in the
- X.I screen
- Xarray.
- X.PP
- XIf there are no fields to display, i.e. if this is a menu-only screen,
- X.I screen
- Xshould be NULL.
- X.PP
- XThe menu window is specified by
- X.IR menu ,
- Xa null terminated array of pointers to DMMENUITEM structures, defined in
- X.IR dmm.h .
- X.PP
- XEach DMMMENUITEM describes one menu item, the elements of which are as follows:
- X.TP 20
- Xlabel
- XA short string to be displayed in the menu item list.
- X.TP 20
- Xdescript
- XA longer, more explanatory string that is displayed on the
- Xsecond line of the menu window when
- Xthe menu item is current.
- X.TP 20
- X.PD 0
- Xcol,
- X.TP 20
- X.PD
- Xpage
- XTo be left unset by the calling function and calculated by
- X.BR dmmRun .
- X.PP
- XIf there is to be no menu for the screen,
- X.I menu
- Xshould be NULL.
- X.PP
- XThe value of
- X.I drawFlag
- Xdetermines whether internal window drawing and calculations need to
- Xtake place.
- XPermissible values are:
- X.TP 20
- XdmmNew
- XUsed when a screen is displayed for the first time
- Xor when a screen is redisplayed after intervening call to
- X.B dmmRun
- Xhas displayed another screen.
- X.TP 20
- XdmmOld
- XUsed when
- X.B dmmRun
- Xis to display the same screen as when it was last called.
- XNothing about the
- X.I screen
- Xor
- X.I menu
- Xstructures nor the values that they point to may have been changed
- Xsince the last call because the screen in this case is repainted
- Xby a simple
- X.I wrefresh
- Xwith no internal window redrawing or recalculations.
- X.PP
- XThe value of
- X.I valFlag
- Xdetermines the initial values of the editable fields.
- XPermissible values are:
- X.TP 20
- XdmmInitVal
- Xcauses the value of
- X.I inputInitValue
- Xto be copied to
- X.I inputEditValue
- Xbefore the screen is displayed and user interaction begun.
- XThis is useful when a certain screen is to be displayed more than oncer
- Xper execution of the program and some of those times it should
- Xstart off with certain default values instead of with the edited values.
- XThe default value of each field should be placed in the
- X.I inputInitVal
- Xparameter for the field.
- X.TP 20
- XdmmEdVal
- Xcauses no such copying.
- XThe values displayed are those that are already in the
- X.I inputEditValue
- Xparameters for each field.
- X.PP
- XThe value of
- X.I startField
- Xdetermines which field is made current when user interaction is begun;
- Xit must be the index in
- X.I screen
- Xof a DMMFIELD that is editable, i.e. one that has a non-zero
- X.IR inputLength .
- XThe special value of -1 has a significance according to the value of
- X.IR drawFlag .
- XIf
- X.I drawFlag
- Xis
- X.IR dmmNew ,
- Xthe starting editable field will be the
- Xfirst editable field (not necessarily the first field) in
- X.IR screen .
- XIf
- X.I drawFlag is
- X.IR dmmOld ,
- Xthe starting editable field depends upon the state of affairs when
- Xlast invocation of
- X.B dmmRun
- Xreturned.
- XIf it returned due to a menu selection
- Xthe starting editable field will be the last current field.
- XIf it returned because an
- X.I inputAudit
- Xfunction returned
- X.I dmmAuditReturnOkay
- Xor
- X.IR dmmAuditReturnBad ,
- Xthe starting editable field will be either the next or preceding editable
- Xfield (depending upon whether the user keystroke that invoked the audit
- Xwas for moving to the next or preceding field).
- XAs described above, this is useful after an inter-field edit has taken place
- Xfor a seamless appearance to the separate invocations of
- X.BR dmmRun .
- XIf the inter-field audit showed valid editable field values, it is useful
- Xto reinvoke
- X.B dmmRun
- Xwith an
- X.I drawFlag
- Xvalue of
- X.I dmmOld
- Xand a
- X.I startField
- Xvalue of -1.
- XIf the inter-field audit indicates that an editable field value needs
- Xcorrection by the user,
- Xan error message should be displayed and
- X.B dmmRun
- Xshould be reinvoked with an
- X.I drawFlag
- Xvalue of
- X.I dmmOld
- Xand
- X.I startField
- Xset to the index of the offending field.
- X.PP
- X.B dmmRun
- Xreturns typically when a user choses a menu item (i.e. enters a carriage
- Xreturn while in the menu state), but also when an
- X.I inputAudit
- Xfunction returns
- X.I dmmAuditReturnOKay
- Xor
- X.IR dmmAuditReturnBad .
- XIn the former case,
- X.B dmmRun
- Xreturns the index of the menu item chosen, and sets
- X.B dmmRetType
- Xto
- X.IR dmmMenu .
- XIn the latter cases, it returns the index of the associated editable field;
- X.B dmmRetType
- Xis set to
- X.I dmmOkayField
- Xor
- X.I dmmBadField
- Xdepending upon whether the audit function returned
- X.I dmmAuditReturnOKay
- Xor
- X.IR dmmAuditReturnBad ,
- Xrespectively.
- XA menuless screen must therefore have an
- X.I inputAudit
- Xfunction that unconditionally returns either
- X.I dmmAuditReturnOkay
- Xor
- X.IR dmmAuditReturnBad ;
- Xotherwise there will be nothing the user can input that will cause
- X.B dmmRun
- Xto return!
- X.SS Terminal initialization and cleanup
- X.PP
- XThe function
- X.B dmmRun
- Xprovides normal
- X.I curses
- Xinitialization (e.g. puts the terminal in raw mode) and creates the various
- Xwindows needed for its work.
- XWhen all
- X.I curses
- Xinteraction is finished in the program, whether through
- X.I DMM
- Xfunctions
- Xor though other functions, the program should invoke
- X.B dmmClose
- Xto clean up and return the terminal to its previous state.
- XThe function
- X.B dmmInit
- Xprovides the same initialization functionality as
- X.B dmmRun
- Xwithout the presentation of a screen.
- XThis is useful when the program needs to do
- X.I curses
- Xwork (such as display of data on the screen using any of the message
- Xdisplay function described below) prior to the first call of
- X.BR dmmRun .
- XIf initialization has already been done,
- X.B dmmRun
- Xwill not do it again (unless, of course, there has been an intervening
- Xinvocation of
- X.BR dmmClose ).
- X.SS Non-interactive display of data
- X.PP
- XData, such as error messages, may be displayed in the data entry window
- Xwithout the user-interaction of a screen.
- XThis is useful not only between invocations of
- X.B dmmRun
- X(or
- X.B dmmInit
- Xand
- X.BR dmmRun ),
- Xbut also within the
- X.I inputAudit
- Xfunctions to display messages to the user when the user needs to correct
- Xan editable field.
- X.B dmmPutMsgs
- Xis the simplest of the message display functions; it adds a block of
- Xmessages to the existing data entry window and leaves them there.
- X.I mesgblock
- Xis a null-terminated array of DMMMESSAGE structures, defined in
- X.IR dmm.h .
- XEach DMMMESSAGE describes one message string,
- Xthe elements of which are as follows:
- X.TP 20
- Xvalue
- XThe string to be displayed.
- X.TP 20
- X.PD 0
- Xcol,
- X.TP 20
- X.PD
- Xline
- XThe coordinates in the data entry window where the first character of
- X.I value
- Xis displayed.
- XA negative value for
- X.I line
- Xrepresents lines from the bottom
- Xof the window, the bottom line represented with -1.
- X.TP 20
- Xattrib
- XThe attributes with which
- X.I value
- Xis displayed.
- XSee
- X.IR labelAttrib ,
- Xabove, for a description of possible values.
- X.PP
- XMessages are cleared from the window with the next invocation of
- X.B dmmRun
- Xor with an invocation of
- X.BR dmmRmMsgs .
- XIf
- X.I removetype
- Xis
- X.IR dmmRemoveAll ,
- Xall message displayed since the last invocation of
- X.B dmmRun
- Xor
- X.B dmmInit
- Xare removed from the window.
- XIf
- X.I removetype
- Xis
- X.IR dmmRemoveLast
- Xonly the messages displayed with the last invocation of
- X.B dmmPutMsgs
- Xare removed.
- X.PP
- X.B dmmPutMsgsTimer
- Xdisplays the messages described by
- X.IR mesgblock ,
- Xsleeps for
- X.I duration
- Xseconds, removes them and returns.
- X.PP
- X.B dmmPutMsgsHit
- Xdisplays the messages described by
- X.IR mesgblock ,
- Xdisplays an instruction in the instruction window for the user to press
- Xany key to continue, and when the user enters a keystroke, the messages
- Xare removed and the function returns.
- X.PP
- X.B dmmPutMsgsNext
- Xdisplays the messages described by
- X.I mesgblock
- Xand removes them upon the next user keystroke entered under an invocation of
- X.B dmmRun
- X(unless removed first by a call to
- X.IR dmmRmMsgs ).
- XThe keystroke is interpreted by
- X.B dmmRun
- Xas it would normally rather than discard it as it is under an invocation of
- X.BR dmmPutMsgsHit .
- X.PP
- X.B dmmClear
- Xclears everything from the data entry window,
- Xall messages and any display from the last call of
- X.BR dmmRun .
- XThis is useful prior to using
- X.RI non- DMM
- Xfunctions for screen manipulation and after a call to
- X.B dmmRun
- Xwhen you don't want the data entry portion of the screen displayed any longer.
- X.PP
- X.B dmmGetNumLines
- Xreturns the number of lines in the data entry window.
- XThis is useful, for example, when displaying tabular data as a set of messages,
- Xand one needs to know how many lines of the table can be displayed in a single
- Xscreenful.
- X.SS Non-interactive auditing of editable field values
- XAs mentioned above, a field's input value is audited under
- X.B dmmRun
- Xonly when the user input a keystroke that would change the field from current
- Xto non-current.
- XConsequently, fields that the user doesn't traverse go unaudited under
- X.BR dmmRun ,
- Xa problem with fields whose initial input value (see discussion
- Xof
- X.I valFlag
- Xabove) is not a valid value;
- X(this is often the case,
- Xe.g. when there is no default value to give for a field's
- X.I initVal
- Xbut a value for the field is required nontheless.)
- XThe solution is to call
- X.BR dmmReview ,
- Xwhich invokes the
- X.I inputAudit
- Xfunction of each editable field and
- Xreturning the index of the first editable field whose
- X.I inputAudit
- Xreturns either
- X.I dmmAuditBad
- Xor
- X.I dmmAuditReturnBad
- Xand by setting
- X.B dmmRetType
- Xto
- X.IR dmmBadField .
- XIf no editable fields have invalid values, it returns -1 and sets
- X.B dmmRetType
- Xto
- X.IR dmmOkayField .
- XTherefore, if a screen has initial editable field values that are not valid,
- Xit is recommended that the call to
- X.B dmmRun
- Xthat presents the screen be followed by a call to
- X.B dmmReview
- X(given an appropriate return value of
- X.BR dmmRun ).
- X.SS Data structures as function arguments
- X.I dmm.h
- X.I typedefs
- Xa number of data structures for use with these functions:
- X.PD 0
- X.PP
- X.nf
- X typedef struct dmmField DMMFIELD, *DMMSCREEN[], **DMMSCREEN2;
- X typedef struct dmmMenuItem DMMMENUITEM, *DMMMENU[], **DMMMENU2;
- X typedef struct dmmMessage DMMMESSAGE, *DMMMESGBLK[], **DMMMESGBLK2;
- X.fi
- X.PP
- XThe first of each triplet are the basic structures used, and the second
- Xare the array-of-pointers data types used above as arguments to the
- X.I DMM
- Xfunctions.
- XHowever, sometimes it is useful (and syntactically equivalent in some contextss)
- Xto use a pointer pointer instead of an array of pointers for the argument of
- Xthe called function, as are the third of each triplet.
- XAn example of a situation in which the pointer pointers are
- Xuseful is as follows:
- X.PD
- X.PP
- X.nf
- X int startField = -1;
- X DMMDRAWFLAG drawFlag = dmmNew;
- X DMMVALFLAG valFlag = dmmInitVal;
- X /* initialization of the DMMSCREENs and DMMMENUs
- X * omitted in this example for brevity
- X */
- X DMMSCREEN normal_screen, root_screen;
- X DMMSCREEN2 screen_to_use;
- X DMMMENU normal_menu, root_menu;
- X DMMMENU2 menu_to_use;
- X ...
- X if(getuid() == 0) {
- X ...
- X screen_to_use = root_screen;
- X menu_to_use = root_menu;
- X ...
- X } else {
- X ...
- X screen_to_use = normal_screen;
- X menu_to_use = normal_menu;
- X ...
- X }
- X ...
- X dmmRun(startField, screen_to_use, menu_to_use, drawFlag, valFlag);
- X.fi
- X.SH EXAMPLE
- X.PP
- XThe sources for a demo program that illustrates good use of
- X.I DMM
- Xare included with the
- X.I DMM
- Xsources.
- XNotice how the declaration of the various
- X.I DMM
- Xdata structures as static variables enables easy initialization.
- X.SH DIAGNOSTICS
- X.PP
- X.B dmmRun
- Xreturns -1 if the screen is faulty,
- X(e.g. a label or input portion of a field or a menu item
- Xdoes not fit on the screen,
- Xeach menu item label does not begin with a unique alphabetic character,
- X.I startField
- Xis not the index of an editable field,
- Xthere is no menu and the data entry portion has no editable fields,
- Xetc.), and
- Xa diagnostic message is displayed on the screen.
- XNon-error return values for
- X.B dmmRun
- Xand
- X.B dmmReview
- Xare described above.
- X.SH SEE ALSO
- X.PP
- X.IR curses (3V)
- X.SH AUTHOR
- X.PP
- XCopyright \(co 1991, Robert Bernardo, rob@mtdiablo.Concord.CA.US,
- Xan employee of Pande, Inc.
- XPermission to use granted only if this
- Xnotice is not removed from this manual page.
- SHAR_EOF
- chmod 0444 dmm.3 || echo "restore of dmm.3 fails"
- set `wc -c dmm.3`;Sum=$1
- if test "$Sum" != "23153"
- then echo original size 23153, current size $Sum;fi
- echo "x - extracting dmm.c (Text)"
- sed 's/^X//' << 'SHAR_EOF' > dmm.c &&
- X#ifndef LINT
- Xstatic char dmm_c_id[] = {"@(#)dmm.c 1.1 \
- XCopyright (c) 1991 Robert Bernardo, rob@mtdiablo.Concord.CA.US, \
- Xan employee of Pande, Inc. \
- XPermission to use granted only if this notice is not removed from \
- Xthis source file nor from any binaries produced from it."};
- X#endif
- X
- X#include <ctype.h>
- X#include <curses.h>
- X#include <string.h>
- X#include <signal.h>
- X#include <term.h>
- X#include <sys/ttychars.h>
- X#include "dmm.h"
- X
- X/* see man page for description */
- XDMMRETTYPE dmmRetType;
- X
- X/* enum for type of cursor change */
- Xenum change {
- X previous, stayput, movecursor, next
- X};
- X
- X/* error message data structures */
- Xstatic char errorMsgBuf[BUFSIZ];
- Xstatic DMMMESSAGE errorMsg = {errorMsgBuf, 0, 0, A_REVERSE};
- Xstatic DMMMESGBLK errorMsgBlk = {&errorMsg, 0};
- X
- X#define CNVRT_LN_NUM(lnnum) (lnnum < 0 ? LFLINE+lnnum+1 : lnnum)
- X#define DISP_ERROR_0(mesg) {strcpy(errorMsg.value,mesg); \
- X dmmPutMsgsHit(errorMsgBlk);}
- X#define DISP_ERROR_1(fmt,arg) {sprintf(errorMsg.value,fmt,arg); \
- X dmmPutMsgsHit(errorMsgBlk);}
- X#define DISP_ERROR_2(fmt,a,b) {sprintf(errorMsg.value,fmt,a,b); \
- X dmmPutMsgsHit(errorMsgBlk);}
- X#define DISP_ERROR_3(fmt,a,b,c) {sprintf(errorMsg.value,fmt,a,b,c); \
- X dmmPutMsgsHit(errorMsgBlk);}
- X
- X/* special command input character symbols */
- X#define TAB '\t'
- X#define RETURN '\r'
- X#define DELETE CERASE
- X
- X/* menu scroll symbols */
- X#define LEFT_SCROLL_SYMBOL "<<"
- X#define RIGHT_SCROLL_SYMBOL ">>"
- X
- X/* parameters of the windows */
- X/* - number of lines in each window */
- X#define MLINES 2 /* menu window */
- X#define ILINES 1 /* instruct window */
- X#define FLINES (LINES - MLINES - ILINES) /* field window */
- X
- X/* - menu line functions */
- X#define MENU_LABEL_LINE 0
- X#define MENU_DESCRIPT_LINE 1
- X
- X/* - line number of first line of windows */
- X
- X#define FILINE 0 /* instruct window */
- X#define FMLINE (FILINE + ILINES) /* menu window */
- X#define FFLINE (FMLINE + MLINES) /* field window */
- X
- X/* - line number of last line of windows in window (not in screen) */
- X#define LFLINE (FLINES - 1) /* field window */
- X
- X#define MENUI_SPACING 2 /* number of spaces between */
- X
- X/* string constants */
- X/* - general instruction messages */
- X#define MENU_INSTRUCT "Cursor to desired item and enter RETURN. Press control-h for help."
- X#define GOTO_MENU_INSTRUCT "Press control-g to enter menu. Press control-h for help."
- X#define NULL_MENU_INSTRUCT "Press control-h for help."
- X#define ANY_KEY_INSTRUCT "Press any key to continue."
- X
- X/* - diagnostic error messages */
- X#define BAD_FIELDNUM "Program error! Target field %d beyond max %d.\n"
- X#define NO_INPUT_MSG "Program error! No input fields nor menu items.\n"
- X#define NOT_IFIELD "Program error! Target field %d not an input field.\n"
- X#define WIDE_LABEL "Program error! Menu label %d too wide for screen.\n"
- X#define NON_ALPHA "Program error! Menu item %d doesn't begin with an alphabetic character."
- X#define LABEL_NO_FIT "Program error! Label for field %d won't fit on screen.\n"
- X#define IP_NO_FIT "Program error! Input part of field %d won't fit on screen.\n"
- X
- X#define DMMWATTRSET(win, attrib) wattrset(win, attrib&~A_INVIS)
- X#define DMMWATTRON(win, attrib) wattron(win, attrib&~A_INVIS)
- X#define DMMWATTROFF(win, attrib) wattroff(win, attrib&~A_INVIS)
- X
- X
- X/* global variables */
- X/* general information discoverd about a screen */
- Xstatic int numFields, /* number of fields */
- X numInputParts, /* number of fields with input parts */
- X numMenuItems, /* number of menu items */
- X numMenuPages, /* number of menu pages */
- X curMenuItem, /* current menu item */
- X firstInputFld; /* first field with input part */
- X/* flags needed to manage the removal of messages displayed with
- X * dmmPutMsgsNext() when not called under a call to dmmRun(), e.g. not
- X * under an inputAudit function.
- X */
- Xstatic int interactive, /* set when dmm is interactive */
- X wantNextClear, /* set when next keystroke should clear
- X * messages from screen */
- X needAddMsgs; /* set when need to add messages from a
- X * dmmPutMsgsNext() called when dmm was not
- X * interactive */
- XPMNmsgsWereLast; /* set when the last messages added were
- X * added by dmmPutMsgsNext(). This is needed
- X * because if dmmRmMsgs() is called to remove
- X * just the last messages, the need to clear
- X * the dmmPutMsgsNext() is removed and need
- X * not be done on the next user keystroke
- X * under dmmRun(). */
- X
- X/* global variables for parameters so they don't have to be passed all over */
- Xstatic DMMSCREEN2 dupeScreen; /* field vector */
- Xstatic DMMMENU2 dupeMenu; /* menu vector */
- X/* windows */
- Xstatic WINDOW *fieldWin, /* field window */
- X *fieldWinCopy, /* saved window between dmmRun() calls */
- X *fieldWinPreMsg, /* saved window before messages */
- X *mesgWin, /* overlay window of messages */
- X *instructWin, /* general instruction window */
- X *instructWinCopy,/* copy of instruction window */
- X *menuWin, /* menu window */
- X *menuWinCopy; /* copy menu window */
- X/* miscellaneous */
- Xstatic int isOpen; /* 0 if dmmInit needs to be performed */
- X
- Xstatic int menuIndex[(int) ('z' - 'a' + 1)]; /* index by letter into
- X * menu by initial
- X * letters of menu
- X * labels. */
- X/* structures for help screens */
- X#define KEY_COLUMN 5
- X#define EFFECT_COLUMN 22
- X#define INTRO_LINE 0
- X#define HELP_LINE (INTRO_LINE + 2)
- X#define REDRAW_LINE (HELP_LINE + 1)
- X#define NEXT_LINE (REDRAW_LINE + 1)
- X#define PREV_LINE (NEXT_LINE + 1)
- X#define RETURNS_LINE (PREV_LINE + 1)
- X#define RETURNM_LINE (RETURNS_LINE + 1)
- X#define DELETE_LINE (RETURNM_LINE + 1)
- X#define ARROW_LINE (DELETE_LINE + 1)
- X#define CLEAR_LINE (ARROW_LINE + 1)
- X#define GOTO_LINE (CLEAR_LINE + 1)
- X#define NORMALS_LINE (GOTO_LINE + 1)
- X#define NORMALM_LINE (NORMALS_LINE + 1)
- X
- Xstatic DMMMESSAGE introHelpKey =
- X{"Key", KEY_COLUMN, INTRO_LINE, A_REVERSE};
- Xstatic DMMMESSAGE helpHelpKey =
- X{"control-h", KEY_COLUMN, HELP_LINE};
- Xstatic DMMMESSAGE redrawHelpKey =
- X{"control-r", KEY_COLUMN, REDRAW_LINE};
- Xstatic DMMMESSAGE nextHelpKey =
- X{"control-n/tab", KEY_COLUMN, NEXT_LINE};
- Xstatic DMMMESSAGE prevHelpKey = {"control-p", KEY_COLUMN, PREV_LINE};
- Xstatic DMMMESSAGE returnHelpKey = {"return", KEY_COLUMN, RETURNS_LINE};
- Xstatic DMMMESSAGE deleteHelpKey = {"delete", KEY_COLUMN, DELETE_LINE};
- Xstatic DMMMESSAGE arrowHelpKey = {"arrow key", KEY_COLUMN, ARROW_LINE};
- Xstatic DMMMESSAGE clearHelpKey = {"control-c", KEY_COLUMN, CLEAR_LINE};
- Xstatic DMMMESSAGE gotoHelpKey = {"control-g", KEY_COLUMN, GOTO_LINE};
- Xstatic DMMMESSAGE normalHelpKey =
- X{"`normal' keys", KEY_COLUMN, NORMALS_LINE};
- X
- Xstatic DMMMESSAGE introEffectKey =
- X{"Effect", EFFECT_COLUMN, INTRO_LINE, A_REVERSE};
- Xstatic DMMMESSAGE helpEffectKey =
- X{"display help (this screen)", EFFECT_COLUMN, HELP_LINE};
- Xstatic DMMMESSAGE redrawEffectKey =
- X{"redraw screen", EFFECT_COLUMN, REDRAW_LINE};
- Xstatic DMMMESSAGE nextEffectKey =
- X{"go to next data field or menu item", EFFECT_COLUMN, NEXT_LINE};
- Xstatic DMMMESSAGE prevEffectKey =
- X{"go to previous data field or menu item", EFFECT_COLUMN, PREV_LINE};
- Xstatic DMMMESSAGE returnScreenEffectKey =
- X{"if in data entry, go to next data field or,", EFFECT_COLUMN, RETURNS_LINE};
- Xstatic DMMMESSAGE returnMenuEffectKey =
- X{"if in menu, accept menu choice", EFFECT_COLUMN, RETURNM_LINE};
- Xstatic DMMMESSAGE deleteEffectKey =
- X{"erase preceding character in current data field", EFFECT_COLUMN, DELETE_LINE};
- Xstatic DMMMESSAGE arrowEffectKey =
- X{"move within current data field", EFFECT_COLUMN, ARROW_LINE};
- Xstatic DMMMESSAGE clearEffectKey =
- X{"clear to end of current data field and go to next",
- XEFFECT_COLUMN, CLEAR_LINE};
- Xstatic DMMMESSAGE gotoEffectKey =
- X{"move from data entry to menu or vice versa", EFFECT_COLUMN, GOTO_LINE};
- Xstatic DMMMESSAGE normalScreenEffectKey =
- X{"if in data entry, input letter into data field or,",
- XEFFECT_COLUMN, NORMALS_LINE};
- Xstatic DMMMESSAGE normalMenuEffectKey =
- X{"if in menu, highlight menu item with same first letter",
- XEFFECT_COLUMN, NORMALM_LINE};
- X
- Xstatic DMMMESGBLK helpMsgVec =
- X{&introHelpKey, &helpHelpKey, &redrawHelpKey, &nextHelpKey,
- X &prevHelpKey, &returnHelpKey, &deleteHelpKey, &arrowHelpKey, &clearHelpKey,
- X &gotoHelpKey, &normalHelpKey, &introEffectKey,
- X &helpEffectKey, &redrawEffectKey, &nextEffectKey, &prevEffectKey,
- X &returnScreenEffectKey, &deleteEffectKey, &returnMenuEffectKey,
- X &arrowEffectKey, &clearEffectKey, &gotoEffectKey, &normalScreenEffectKey,
- X&normalMenuEffectKey, 0};
- X/* dmmInit() put the terminal in the right mode and set up curses with
- X * the right windows.
- X */
- Xvoid
- XdmmInit ()
- X{
- X initscr ();
- X raw ();
- X nonl ();
- X noecho ();
- X
- X /* get terminal in right mode */
- X putp (init_1string);
- X putp (init_2string);
- X putp (init_3string);
- X putp (cursor_visible); /* blinking cursor */
- X
- X /* create windows */
- X fieldWin = newwin (FLINES, COLS, FFLINE, 0);
- X fieldWinCopy = newwin (FLINES, COLS, FFLINE, 0);
- X fieldWinPreMsg = newwin (FLINES, COLS, FFLINE, 0);
- X mesgWin = newwin (FLINES, COLS, FFLINE, 0);
- X instructWin = newwin (ILINES, COLS, FILINE, 0);
- X instructWinCopy = newwin (ILINES, COLS, FILINE, 0);
- X menuWin = newwin (MLINES, COLS, FMLINE, 0);
- X menuWinCopy = newwin (MLINES, COLS, FMLINE, 0);
- X
- X /* leave cursor where code says to */
- X leaveok (instructWin, FALSE);
- X leaveok (fieldWin, FALSE);
- X leaveok (menuWin, FALSE);
- X
- X /* treat escape sequences as single characters */
- X keypad (fieldWin, TRUE);
- X keypad (menuWin, TRUE);
- X
- X /* set attributes of windows fixed at a single attribute */
- X DMMWATTRSET (instructWin, A_REVERSE);
- X
- X isOpen = 1;
- X
- X return;
- X}
- X
- X
- X/* redraw() unconditionally redraw the entirety of each window.
- X */
- Xstatic void
- Xredraw ()
- X{
- X clearok (fieldWin, TRUE);
- X clearok (instructWin, TRUE);
- X clearok (menuWin, TRUE);
- X wnoutrefresh (fieldWin);
- X wnoutrefresh (instructWin);
- X wnoutrefresh (menuWin);
- X doupdate ();
- X return;
- X}
- X
- X
- X/* dmmClose() cleanup dmm and close down curses */
- Xvoid
- XdmmClose ()
- X{
- X delwin (fieldWin);
- X delwin (fieldWinCopy);
- X delwin (fieldWinPreMsg);
- X delwin (mesgWin);
- X delwin (instructWin);
- X delwin (instructWinCopy);
- X delwin (menuWin);
- X delwin (menuWinCopy);
- X isOpen = 0;
- X clear ();
- X refresh ();
- X endwin ();
- X putp (cursor_normal);
- X return;
- X}
- X
- X
- X/* dmmGetNumLines return the number of lines in fieldWin */
- Xint
- XdmmGetNumLines ()
- X{
- X return FLINES;
- X}
- X
- X/* outOfTheWay put the cursor in a place where it's not distracting */
- Xvoid
- XoutOfTheWay()
- X{
- X wmove (instructWin, 0, COLS - 1);
- X wnoutrefresh (instructWin);
- X return;
- X}
- X
- X
- X/* dmmRmMsgs() remove messages displayed */
- Xvoid
- XdmmRmMsgs (removeType)
- XDMMREMOVETYPE removeType;
- X{
- X /*
- X * remove residue of dmmPutMsgsNext type of messages as appropriate to
- X * whether they were last or wether we are clearing all messages not just
- X * the last messages
- X */
- X if ((removeType == dmmRemoveAll) || (PMNmsgsWereLast)) {
- X wclear (mesgWin);
- X needAddMsgs = 0;
- X wantNextClear = 0;
- X }
- X /* remove proper "layer" of messages */
- X overwrite ((removeType == dmmRemoveAll ? fieldWinCopy : fieldWinPreMsg),
- X fieldWin);
- X wnoutrefresh (fieldWin);
- X outOfTheWay();
- X doupdate();
- X return;
- X}
- X
- X
- X/* wGetCh() like wgetch(), but clears any messages displayed by
- X * dmmPutMesgsNext()
- X */
- Xstatic int
- XwGetCh (win)
- XWINDOW *win;
- X{
- X int keystroke;
- X /* get keystroke */
- X keystroke = wgetch (win);
- X
- X /* if need to clear messages, do so */
- X if (wantNextClear) {
- X dmmRmMsgs (dmmRemoveLast);
- X wantNextClear = 0;
- X }
- X /* if mesgWin was used, clear it so stale messages don't get reused */
- X if (needAddMsgs) {
- X werase (mesgWin);
- X needAddMsgs = 0;
- X }
- X return keystroke;
- X}
- X
- X
- X/* addMsgs() add messages to the indicated window */
- Xstatic void
- XaddMsgs (win, mesgBlock)
- XWINDOW *win;
- XDMMMESGBLK mesgBlock;
- X{
- X /* display each item in the message array */
- X while (*mesgBlock) {
- X DMMWATTRON (win, (*mesgBlock)->attrib);
- X mvwaddstr (win, CNVRT_LN_NUM ((*mesgBlock)->line),
- X (*mesgBlock)->col, (*mesgBlock)->value);
- X DMMWATTROFF (win, (*mesgBlock)->attrib);
- X mesgBlock++;
- X }
- X wnoutrefresh (win);
- X return;
- X}
- X
- X
- X/* doPutMsgs() see comments for dmmPutMsgs, if save is set, write
- X * messages as well to mesgWin
- X */
- Xstatic void
- XdoPutMsgs (mesgBlock, save)
- XDMMMESGBLK mesgBlock;
- Xint save;
- X{
- X
- X /* save copy of window as it currently is */
- X overwrite (fieldWin, fieldWinPreMsg);
- X
- X /* display messages on fieldWin, and on mesgWin as needed */
- X addMsgs (fieldWin, mesgBlock);
- X if (save)
- X addMsgs (mesgWin, mesgBlock);
- X PMNmsgsWereLast = 0; /* may be set by outer call to
- X * dmmPutMsgsNext() */
- X outOfTheWay();
- X doupdate ();
- X}
- X
- X
- X/* dmmPutMsgsNext() remove messages displayed until a key is input
- X * under dmmRun or until explicitly removed
- X */
- Xvoid
- XdmmPutMsgsNext (mesgBlock)
- XDMMMESGBLK mesgBlock;
- X{
- X wantNextClear = mesgBlock ? 1 : 0;
- X if (!interactive)
- X needAddMsgs = 1;
- X doPutMsgs (mesgBlock, needAddMsgs);
- X PMNmsgsWereLast = 1;
- X return;
- X}
- X
- X
- X/* dmmPutMsgs() display messages */
- Xvoid
- XdmmPutMsgs (mesgBlock)
- XDMMMESGBLK mesgBlock;
- X{
- X doPutMsgs (mesgBlock, 0);
- X return;
- X}
- X
- X/* dmmClear() clear everything irretrievably from fieldWin */
- Xvoid
- XdmmClear()
- X{
- X wclear(mesgWin);
- X wnoutrefresh(mesgWin);
- X wclear(fieldWin);
- X wnoutrefresh(fieldWin);
- X wclear(fieldWinCopy);
- X wnoutrefresh(fieldWinCopy);
- X outOfTheWay();
- X doupdate();
- X return;
- X}
- X
- X
- X/* dmmPutMsgsTimer() display messages for a certain number of secs */
- Xvoid
- XdmmPutMsgsTimer (mesgBlock, duration)
- XDMMMESGBLK mesgBlock;
- Xunsigned duration;
- X{
- X /* display messages */
- X dmmPutMsgs (mesgBlock);
- X
- X /* sleep and then redisplay the original window without the messages */
- X (void) sleep (duration);
- X dmmRmMsgs (dmmRemoveLast);
- X
- X return;
- X}
- X
- X
- X/* dispInstruct() display a message in the general instruction window */
- Xstatic void
- XdispInstruct (msg)
- Xchar *msg;
- X{
- X mvwaddstr (instructWin, 0, 0, msg);
- X wclrtoeol (instructWin);
- X wnoutrefresh (instructWin);
- X return;
- X}
- X
- X
- X/* doPutMsgsHit() display the messages indicated by mesgBlock
- X * until the user enters a keystroke
- X */
- Xvoid static
- XdoPutMsgsHit (mesgBlock, restoreThem)
- XDMMMESGBLK mesgBlock;
- Xint restoreThem;
- X{
- X register int x;
- X overwrite (instructWin, instructWinCopy);
- X if (restoreThem) {
- X overwrite (fieldWin, fieldWinCopy);
- X overwrite (menuWin, menuWinCopy);
- X wclear (fieldWin);
- X wclear (menuWin);
- X wnoutrefresh (menuWin);
- X }
- X dispInstruct (ANY_KEY_INSTRUCT);
- X flushinp ();
- X dmmPutMsgs (mesgBlock);
- X wgetch (fieldWin);
- X flushinp ();
- X if (restoreThem) {
- X overwrite (fieldWinCopy, fieldWin);
- X overwrite (menuWinCopy, menuWin);
- X wnoutrefresh (fieldWin);
- X wnoutrefresh (menuWin);
- X } else
- X dmmRmMsgs (dmmRemoveLast);
- X overwrite (instructWinCopy, instructWin);
- X
- X /* That last overwrite makes the whole window inverse video including
- X * trailing blanks, not just the message part, so we have to clear
- X * the trailing spaces while in normal attributes.
- X */
- X DMMWATTROFF (instructWin, A_REVERSE);
- X x = instructWin->_maxx;
- X while(x--) {
- X if((mvwinch(instructWin, 0, x) & A_CHARTEXT) != ' ') {
- X x++;
- X break;
- X }
- X }
- X wmove(instructWin, 0, x);
- X wclrtoeol(instructWin);
- X DMMWATTRON (instructWin, A_REVERSE);
- X wnoutrefresh (instructWin);
- X doupdate ();
- X return;
- X}
- X
- X
- X/* dmmPutMsgsHit() display a message until the user presses any key */
- Xvoid
- XdmmPutMsgsHit (mesgBlock)
- XDMMMESGBLK mesgBlock;
- X{
- X doPutMsgsHit (mesgBlock, 0);
- X return;
- X}
- X
- X
- X/* dispInField() display the input part of the specified field
- X * with the specified attributes.
- X */
- Xstatic void
- XdispInField (fldPtr, attrib)
- Xregister DMMFIELD *fldPtr;
- Xlong attrib;
- X{
- X register int charNum; /* counter of characters output */
- X int doNulls, /* set if characters run out */
- X len; /* length of field */
- X if (fldPtr->inputLength) {
- X DMMWATTRON (fieldWin, attrib);
- X charNum = 0;
- X doNulls = (attrib & A_INVIS) ? 1 : 0;
- X for (charNum = 0, len = fldPtr->inputLength; charNum < len; charNum++) {
- X if (fldPtr->inputEditValue[charNum] == '\0')
- X doNulls = 1; /* we got to end of string, from here to end
- X * output blanks */
- X mvwaddch (fieldWin,
- X fldPtr->inputLine + (charNum / fldPtr->inputMaxCols),
- X fldPtr->inputCol + (charNum % fldPtr->inputMaxCols),
- X doNulls ? ' ' : fldPtr->inputEditValue[charNum]);
- X }
- X DMMWATTROFF (fieldWin, attrib);
- X }
- X return;
- X}
- X
- X
- X/* calcDflts() calculate line and column numbers for the label
- X * and input part of data fields; a negative line
- X * number represents lines from the window bottom,
- X * with -1 being the bottom; a negative column for
- X * the input part of the field indicates the number
- X * of columns separating it and the end of the label part;
- X * calculate the number of full length lines and
- X * the length of the last line (if not full length)
- X * of the input part.
- X */
- Xstatic void
- XcalcDflts (fldPtr)
- Xregister DMMFIELD *fldPtr;
- X{
- X
- X /* calculate line numbers */
- X fldPtr->labelLine = CNVRT_LN_NUM (fldPtr->labelLine);
- X fldPtr->inputLine = CNVRT_LN_NUM (fldPtr->inputLine);
- X
- X /* calculate input part column number */
- X if (fldPtr->inputCol < 0)
- X fldPtr->inputCol = fldPtr->labelCol
- X + strlen (fldPtr->labelValue) - fldPtr->inputCol - 1;
- X
- X /* calculate dimensions of lines of input part from length; if
- X * inputMaxCols is 0, field will be one line of inputLength chars
- X */
- X if (fldPtr->inputMaxCols) {
- X fldPtr->inputFullLines = fldPtr->inputLength / fldPtr->inputMaxCols;
- X fldPtr->inputShortCols = fldPtr->inputLength % fldPtr->inputMaxCols;
- X } else {
- X fldPtr->inputMaxCols = fldPtr->inputLength;
- X fldPtr->inputFullLines = 1;
- X fldPtr->inputShortCols = 0;
- X }
- X
- X return;
- X}
- X
- X
- X/* calcMenu() calculate page and column for each menu item
- X * and create index for menu; return -1 if
- X * more than one item label begin with the same
- X * letter, else 0.
- X */
- Xstatic int
- XcalcMenu ()
- X{
- X int letter,
- X thisPage,
- X nextCol,
- X scrollSymSize = strlen (LEFT_SCROLL_SYMBOL),
- X numScrollSymbols,
- X itemLen,
- X itemNum = 0;
- X /* initialize menu index */
- X for (letter = 0; letter < (int) ('z' - 'a' + 1); letter++)
- X menuIndex[letter] = -1;
- X
- X /* get count of menu items */
- X while (dupeMenu[itemNum++]);
- X numMenuItems = itemNum - 1;
- X
- X /* start on first column of first page */
- X thisPage = 0;
- X nextCol = 0;
- X itemNum = 0;
- X while (dupeMenu[itemNum]) {
- X
- X /* register item in index */
- X letter = (int) *(dupeMenu[itemNum]->label);
- X if (!(isascii (letter) && isalpha (letter))) {
- X DISP_ERROR_1 (NON_ALPHA, itemNum);
- X return -1;
- X }
- X if (isupper (letter))
- X letter = tolower (letter);
- X letter -= (int) 'a'; /* start from 0, not 'a' */
- X if (menuIndex[letter] == -1)
- X menuIndex[letter] = itemNum;
- X else
- X menuIndex[letter] = -2;;
- X
- X itemLen = strlen (dupeMenu[itemNum]->label);
- X
- X /* check to see that label isn't wider than the window itself if this
- X * menu has only one item, then we don't need to worry about fitting
- X * in any scroll symbols; if we are already beyond the first page and
- X * there are no more items, we need to worry about only one scroll
- X * symbol also fitting; if we are already beyond the first page and
- X * there are more items, we need to worry about two scroll symbols
- X * also fitting.
- X */
- X if (numMenuItems == 1)
- X numScrollSymbols = 0;
- X else if ((thisPage > 0) && ((itemNum + 1) == numMenuItems))
- X numScrollSymbols = 1;
- X else
- X numScrollSymbols = 2;
- X if ((itemLen +
- X (numScrollSymbols * (scrollSymSize + MENUI_SPACING))) > COLS) {
- X DISP_ERROR_1 (WIDE_LABEL, itemNum);
- X return -1;
- X }
- X
- X /* check to see if it will fit on this page; if not the last item we
- X * need to make sure on scrolling symbol will fit as well.
- X */
- X numScrollSymbols = ((itemNum + 1) == numMenuItems) ? 0 : 1;
- X if ((itemLen + nextCol +
- X (numScrollSymbols * (scrollSymSize + MENUI_SPACING))) > COLS) {
- X
- X /* won't fit on this page, start new page */
- X thisPage++;
- X nextCol = scrollSymSize + MENUI_SPACING;
- X }
- X
- X /* assign its col and page */
- X dupeMenu[itemNum]->col = nextCol;
- X dupeMenu[itemNum]->page = thisPage;
- X nextCol += (itemLen + MENUI_SPACING);
- X
- X itemNum++;
- X }
- X
- X /* Set global menu variables; hmm ... numMenuItems already set above */
- X numMenuPages = thisPage + 1;
- X return 0;
- X}
- X
- X
- X/* dispMenuItem() display menu item highlighted or not
- X * and display description field if highlighted
- X */
- Xstatic void
- XdispMenuItem (mitemPtr, highlight)
- XDMMMENUITEM *mitemPtr;
- Xint highlight;
- X{
- X if (mitemPtr) {
- X if (highlight)
- X DMMWATTRON (menuWin, A_REVERSE);
- X mvwaddstr (menuWin, MENU_LABEL_LINE, mitemPtr->col,
- X mitemPtr->label);
- X if (highlight) {
- X DMMWATTROFF (menuWin, A_REVERSE);
- X mvwaddstr (menuWin, MENU_DESCRIPT_LINE, 0, mitemPtr->descript);
- X wclrtoeol (menuWin);
- X }
- X }
- X return;
- X}
- X
- X
- X/* dispMenuPage() display page of menu items containing the
- X * item indicated; if highlight is TRUE
- X * highlight the menu item; if force is TRUE,
- X * redisplay from scratch.
- X */
- Xstatic void
- XdispMenuPage (itemNum, highlight, dmmRenew)
- Xint itemNum,
- X highlight,
- X dmmRenew;
- X{
- X static int lastPageDisplayed = -1,
- X lastItemHighlighted = -1;
- X int itemIndex,
- X pageNum;
- X
- X /* if page is current only redisplay old item unhighlighted and new item
- X * highlighted, else display whole page from scratch adding right and
- X * left scrolling symbols as needed
- X */
- X
- X if (!dmmRenew && (dupeMenu[itemNum]->page == lastPageDisplayed)) {
- X
- X if (itemNum != lastItemHighlighted)
- X if (lastItemHighlighted != -1)
- X dispMenuItem (dupeMenu[lastItemHighlighted], 0);
- X dispMenuItem (dupeMenu[itemNum], highlight);
- X
- X } else {
- X
- X werase (menuWin);
- X pageNum = dupeMenu[itemNum]->page;
- X for (itemIndex = 0; itemIndex < numMenuItems; itemIndex++)
- X if (dupeMenu[itemIndex]->page == pageNum)
- X dispMenuItem (dupeMenu[itemIndex],
- X ((itemIndex == itemNum) && highlight));
- X
- X if (pageNum)
- X mvwaddstr (menuWin, MENU_LABEL_LINE, 0, LEFT_SCROLL_SYMBOL);
- X if (pageNum + 1 < numMenuPages)
- X mvwaddstr (menuWin, MENU_LABEL_LINE,
- X COLS - sizeof (RIGHT_SCROLL_SYMBOL), RIGHT_SCROLL_SYMBOL);
- X
- X lastPageDisplayed = pageNum;
- X }
- X lastItemHighlighted = itemNum;
- X wnoutrefresh (menuWin);
- X return;
- X}
- X
- X
- X/* layout() do layout and calculations for the first display */
- Xstatic int
- Xlayout ()
- X{
- X register int fldNum = 0; /* number of current field */
- X register DMMFIELD *fieldPtr;
- X int inputPartCnt = 0, /* number of input fields so far */
- X lastInFieldNum = -1,
- X firstInFieldNum;
- X
- X /* indicate first input field not yet discovered */
- X firstInputFld = -1;
- X
- X /* erase previous contents of windows */
- X werase (fieldWin);
- X werase (instructWin);
- X werase (menuWin);
- X
- X /* draw field window */
- X if (dupeScreen) {
- X while (dupeScreen[fldNum]) {
- X fieldPtr = dupeScreen[fldNum];
- X
- X /* check that label fits on screen */
- X if (fieldPtr->labelValue &&
- X ((fieldPtr->labelCol + strlen (fieldPtr->labelValue) > COLS)) ||
- X ((fieldPtr->labelLine + 1> FLINES))) {
- X DISP_ERROR_1 (LABEL_NO_FIT, fldNum);
- X return -1;
- X }
- X
- X /* display label, if any */
- X if (fieldPtr->labelValue && *fieldPtr->labelValue) {
- X DMMWATTRON (fieldWin, fieldPtr->labelAttrib);
- X mvwaddstr (fieldWin, fieldPtr->labelLine,
- X fieldPtr->labelCol, fieldPtr->labelValue);
- X DMMWATTROFF (fieldWin, fieldPtr->labelAttrib);
- X }
- X
- X /* if there is an input part, display it */
- X if (fieldPtr->inputLength) {
- X
- X /* calculate number of instruction lines */
- X fieldPtr->inputNumInstructs =
- X cntInstructs (fieldPtr);
- X
- X /* set the first input field if not yet found */
- X if (firstInputFld == -1)
- X firstInputFld = fldNum;
- X
- X /* calculate defaults */
- X calcDflts (fieldPtr);
- X
- X /* check that input part of field fits on screen */
- X if ((fieldPtr->inputCol + fieldPtr->inputMaxCols > COLS) ||
- X (fieldPtr->inputLine + fieldPtr->inputFullLines +
- X (fieldPtr->inputShortCols ? 1 : 0) > FLINES)) {
- X DISP_ERROR_1 (IP_NO_FIT, fldNum);
- X return -1;
- X }
- X
- X /* display edited value */
- X dispInField (fieldPtr, fieldPtr->inputAttrib);
- X
- X /* set last input field's next pointer to this field and this
- X * field's prev pointer to last input field
- X */
- X if (lastInFieldNum != -1) {
- X dupeScreen[lastInFieldNum]->nextInField = fldNum;
- X fieldPtr->prevInField = lastInFieldNum;
- X } else
- X firstInFieldNum = fldNum;
- X
- X lastInFieldNum = fldNum;
- X inputPartCnt++;
- X }
- X fldNum++;
- X }
- X if ((firstInFieldNum != -1) && (lastInFieldNum != -1)) {
- X dupeScreen[firstInFieldNum]->prevInField = lastInFieldNum;
- X fieldPtr->nextInField = firstInFieldNum;
- X }
- X }
- X
- X /* set globals to values of local register variables */
- X numFields = fldNum;
- X numInputParts = inputPartCnt;
- X
- X /* display menu items and determine menu instruction */
- X if (dupeMenu) {
- X
- X /* do menu calculations */
- X if (calcMenu ())
- X return -1;
- X
- X /* display menu page that contains first item; no item highlighted */
- X dispMenuPage (curMenuItem = 0, 0, 1);
- X }
- X return 0;
- X}
- X
- X
- X/* copyInFields() copy all initial values to edited values of
- X * input parts of fields and display; a null
- X * initial value is equivalent to a zero-length
- X * string.
- X */
- Xstatic void
- XcopyInFields ()
- X{
- X int fldNum; /* counter of field */
- X DMMFIELD *fldPtr;
- X for (fldNum = 0; fldNum < numFields; fldNum++) {
- X fldPtr = dupeScreen[fldNum];
- X if (fldPtr->inputLength) {
- X strncpy (fldPtr->inputEditValue,
- X fldPtr->inputInitValue ? fldPtr->inputInitValue : "",
- X fldPtr->inputLength);
- X fldPtr->inputEditValue[fldPtr->inputLength] = '\0';
- X dispInField (fldPtr, fldPtr->inputAttrib);
- X }
- X }
- X return;
- X}
- X
- X
- X/* insane() check the sanity of things, where fldNum is the number
- X * of the selected starting input field,
- X * returning 0 if okay, else writing a diagnostic message
- X * to stderr and returning non-zero.
- X */
- Xstatic int
- Xinsane (fldNum)
- Xint fldNum;
- X{
- X /* is the starting field within the proper range? */
- X if (fldNum > numFields - 1) {
- X DISP_ERROR_2 (BAD_FIELDNUM, fldNum + 1, numFields);
- X return 1;
- X }
- X
- X /* does the starting field have an input part */
- X if (numInputParts) {
- X if (dupeScreen[fldNum]->inputLength < 1) {
- X DISP_ERROR_1 (NOT_IFIELD, fldNum + 1);
- X return 1;
- X }
- X }
- X
- X /* is there at least one field with an input part or one menu item */
- X if (!(numInputParts || numMenuItems)) {
- X DISP_ERROR_0 (NO_INPUT_MSG);
- X return 1;
- X }
- X
- X return 0;
- X}
- X
- X
- X/* dmmReview() audit all input fields */
- Xint
- XdmmReview (screen)
- XDMMSCREEN screen;
- X{
- X register int fldNum; /* field index */
- X register DMMFIELD *fldPtr;
- X DMMAUDITRETURN auditReturnVal; /* return value of the audit function */
- X
- X for (fldNum = 0; screen[fldNum]; fldNum++) {
- X fldPtr = screen[fldNum];
- X if (fldPtr->inputLength) {
- X auditReturnVal = fldPtr->inputAudit (fldPtr->inputEditValue);
- X if ((auditReturnVal == dmmAuditBad)
- X || (auditReturnVal == dmmAuditReturnBad)) {
- X dmmRetType = dmmBadField;
- X return fldNum;
- X }
- X }
- X }
- X dmmRetType = dmmOkayField;
- X return -1;
- X}
- X
- X
- X/* cntInstructs(fldPtr) return the number of instruction lines for
- X * the specified field number
- X */
- Xstatic int
- XcntInstructs (fldPtr)
- XDMMFIELD *fldPtr;
- X{
- X register int numInstruct = 0, /* number of instruction lines */
- X instructNum = 0; /* index in inputInstructVec */
- X
- X if (fldPtr->inputInstructVec) {
- X while (fldPtr->inputInstructVec[instructNum++]) {
- X numInstruct++;
- X }
- X }
- X return numInstruct;
- X}
- X
- X
- X/* arriveInField() display the input field of the specified
- X * number with the edit attributes and display the
- X * instructions for that input field
- X */
- Xstatic void
- XarriveInField (fldPtr)
- XDMMFIELD *fldPtr;
- X{
- X register int numInstructs, /* number of instructions left to
- X * display */
- X instructLine; /* line number for displaying next
- X * instr */
- X
- X /* display field in appropriate attributes */
- X dispInField (fldPtr, fldPtr->inputEditAttrib);
- X
- X /* display instruction lines in reverse order, bottom up */
- X numInstructs = fldPtr->inputNumInstructs;
- X instructLine = LFLINE;
- X while (numInstructs--)
- X mvwaddstr (fieldWin,
- X instructLine--, 0, fldPtr->inputInstructVec[numInstructs]);
- X return;
- X}
- X
- X
- X/* leaveInField() display the input field of the specified
- X * number with the normal attributes and erase
- X * the instructions for that input field
- X */
- Xstatic void
- XleaveInField (fldPtr)
- XDMMFIELD *fldPtr;
- X{
- X register int numInstructs, /* number of instructions left to
- X * display */
- X instructLine; /* line number for displaying next
- X * instr */
- X /* display field in appropriate attributes */
- X dispInField (fldPtr, fldPtr->inputAttrib);
- X
- X /* erase instruction lines starting with the bottom */
- X numInstructs = fldPtr->inputNumInstructs;
- X instructLine = LFLINE;
- X while (numInstructs--) {
- X wmove (fieldWin, instructLine--, 0);
- X wclrtoeol (fieldWin);
- X }
- X return;
- X}
- X
- X
- X/* chgInField() change to the first position of a (perhaps
- X * input field; old is the last input field,
- X * and delta specifies what the change is to the
- X * new input field; return the number of the new
- X * input field.
- X */
- Xstatic int
- XchgInField (old, delta)
- Xint old;
- Xenum change delta;
- X{
- X int new; /* number of the new input field */
- X
- X
- X /* determine new field */
- X new = ((delta != stayput) ?
- X (delta == next ?
- X dupeScreen[old]->nextInField : dupeScreen[old]->prevInField)
- X : old);
- X
- X /* if field actually changed, leave old field and arrive at new field */
- X if (new != old)
- X leaveInField (dupeScreen[old]);
- X arriveInField (dupeScreen[new]);
- X
- X /* move cursor to first position in new field */
- X wmove (fieldWin, dupeScreen[new]->inputLine, dupeScreen[new]->inputCol);
- X
- X return new;
- X}
- X
- X
- X/* adjustFld() convert trailing blanks of an edited
- X * field value to nulls and intermediate nulls to blanks.
- X */
- Xstatic void
- XadjustFld (fldPtr)
- Xregister DMMFIELD *fldPtr;
- X{
- X register int charCnt = fldPtr->inputLength; /* counter for
- X * characters output */
- X enum location {
- X internal, external
- X }; /* whether before or after the terminating
- X * null of inputEditValue */
- X register enum location state;
- X
- X state = external;
- X while (charCnt--) {
- X switch (state) {
- X case external:
- X
- X switch (fldPtr->inputEditValue[charCnt]) {
- X case '\0':
- X break;
- X case ' ':
- X fldPtr->inputEditValue[charCnt] = '\0';
- X break;
- X default:
- X state = internal;
- X break;
- X }
- X break;
- X
- X case internal:
- X if (fldPtr->inputEditValue[charCnt] == '\0')
- X fldPtr->inputEditValue[charCnt] = ' ';
- X break;
- X }
- X }
- SHAR_EOF
- echo "End of part 1"
- echo "File dmm.c is continued in part 2"
- echo "2" > s2_seq_.tmp
- exit 0
- --
- Rob Bernardo Mt. Diablo Software Solutions
- email: rob@mtdiablo.Concord.CA.US phone: (415) 827-4301
-