[net.micro.att] UNIX PC Application Integration

daemon@houligan.UUCP (04/06/86)

To establish my credentials, I have written a calendar application to work 
under both the User Agent and Bourne shell. I wrote it mainly because at the
time (6/85) there was no such application and also to learn how to use the
UNIX PC specific libraries. It took three months and it wasn't a dull process.
I submitted it to AT&T's Vendor Involvement Program for evaluation, and it has
been accepted for listing in their catalog.

First, the theory. Basically, there are two levels at which you can access the
window manager. The lowest level is described in window(7). At this level,
windows are treated as file descriptors and manipulated with ioctl's. Built on
top of this is the highest level, described in tam(3). This essentially
provides you with more convenient although less flexible access to the window
manager. You can, and in many cases will, have to mix the two. Neither is
device-independent by any means. Built on top of tam, several utility functions
are provided, the most important being menu(), form(), message(), track(), 
wind(), and exhelp(). Although they could be improved and expanded, these are
very useful and save a lot of development time, so I highly recommend them.
In summary, the basic strategy is to use tam for bread and butter window
manipulation and I/O, while employing the higher level utilities where you 
need them, and delving into ioctl's only when absolutely necessary.

Now, the practice. By way of background, I found early on that I cannot stand
the User Agent, so I quickly deleted 'exec /usr/bin/ua' from my .profile. This
was the beginning of a long and continuing effort to find ways to eliminate the
need for the User Impediment and also my problems with the tam library. I guess
I'm just too set in my ways to appreciate the User Agent. 

The first problem is that the tam functions for creating a new window would 
shrink my login Bourne shell window and put a border around it, permanently
until logout. I think the tam functions to create a new window expect an open 
window to be supplied via 'open("/dev/window",...' and attached to the standard
file descriptors before they are called the first time inside a process. 
This is what the User Agent will do by default before running an application 
(see ua(4)). So the solution was to always do 'open("/dev/window",...' before 
calling these functions and also tell the User Agent through the Suffixes file 
to not open a window before running the application.

The next problem appeared when attempting to follow the mouse to move a 
highlighted area in my main window. I first tried to use track(). It
didn't work. Period. So I chalked this up to new software, and attempted to
use wreadmouse() in tam. Now, in all honesty, this function and its ioctl
counterpart are really not designed for you to track the mouse by constantly
sampling its position. They want you to restrict mouse reports by specifying
when you are interested in its position relative to a rectangle or changes in
the buttons. However, you can, in theory, sample the position by specifying
the rectangle as the interior of the window. So, I set up a tight loop waiting
on a mouse report with the current position, and based on this update the
window with the new highlighted area. As soon as the mouse touched the inside
of the window, a system trap occurred, which dumps half a screen full of 
information to the screen, most of which is decipherable only by the machine's
designer, except for a plain English message "Unexpected DMA Page Fault" and
a prompt to reset the machine, which I did. Unfortunately, when it got to the
point of booting from the hard disk, it wouldn't. It displayed the half tone
pattern on the screen, displayed the working icon, the head started seeking,
then silence. After passing all diagnostics, and rebuilding the disk, I tried
it again. Same behavior. This is pure conjecture, but what must have happened
is that the loader area on the hard disk was blown away by page swapping 
activity gone awry. Needless to say, this cooled my enthusiasm for tracking 
the mouse,  and I have never attempted to track the mouse in a tight loop
with screen updating again. Fortunately, menu() allows you to supply an already
open window for the menu through the M_USEWIN flag. As my main window could be
structured as a menu of text items, albeit a dynamic one, this was an acceptable
solution for this particular application.

As a side note, if you use the ioctl for tracking the mouse, you will have to 
put the tty driver into cbreak and no echo mode, which tam does automatically 
inside winit(). If you don't, you won't receive a mouse report until you press 
return and it will be echo'd on the display.

Now, some miscellaneous notes and bugs. If you want to use message() to display
a status line icon, don't use ST_CAL, this prints nothing and reports no error.
This applies to 3.0, and is apparently because ST_CAL is reserved for use by
the Personal Calendar application.

If you use exhelp() directly or indirectly through message(), it will for some 
reason not wait on its child, so that the next time you do a wait() on one of 
your child processes, it will fall through immediately because of the dead,
unwaited for help child. You will have to use the return value of wait() to 
check if the correct process terminated. This applies to 2.0 and possibly 3.0. 
Apart from this, exhelp() works perfectly as described, although debugging 
syntax errors in the help file is a pain, and under 2.0, if help was accessed 
through message(), the text of the message would be displayed below the help 
window and could not be erased except through a clear screen.

If you want a child process to run after the parent dies and you have a window 
attached to the standard file descriptors of the parent, the window will 
remain on the screen after the parent dies unless you close the standard file 
descriptors in the child. Under 2.0 at least, if you wound up logged onto to 
anything other than '/dev/w1', no status icons would be displayed until you 
did log onto the '/dev/w1'. I don't remember how I got into that state on a 
single user system.

Both menu() and form() work perfectly under 2.0, but under 3.0 the user cannot 
drag the highlighted bar with the mouse. You can see this in the 
Administration menus and forms. As I said before, track() did not work under 
2.0, it may under 3.0 or possibly I was just missing something. 

If you want to run vi as a child process in a window you created in the 
parent, you will have to modify the value of the lines and columns 
capabilities in the TERMCAP variable in the environment to reflect the 
interior dimensions of the window. If you're only running under the User
Agent, this is unnecessary. You will have to place 'eval `tset -s -Q`' in
/etc/profile to set the TERMCAP variable after TERM is set. 

The process of installation and preparing an installation disk(s) works
exactly as documented in the UNIX PC Interface Specification and ua(4).
I found no bugs, problems, or inconsistencies with the procedures applicable
to my application.

There are probably several other bugs that I found but don't remember and
more that I never encountered.

All in all, it is a fairly good system of libraries that work for the most
part or have work arounds. The utility functions do reduce the work involved
significantly. However, if you want to write an application that adheres to
the Interface Specification, it is a worthwhile investment of time to write
your own utilities for menus, forms, and error reporting that implement
sections of the specification regarding item selection, keyboard conventions,
and error messages. Another timesaver that I created was a translator from
small specifications to the declarations and initialization required for
menu() and form(), which can get very large and are in a form which makes
it difficult to visualize their appearance on the screen.

--

Jeff Lohman                             ...!{brl-bmd,pur-ee,sun}!gould!jlohman
Gould, Computer Systems Division
6901 W. Sunrise Blvd.  
Ft. Lauderdale, FL  33310-4499
(305) 587-2900 x5237