v01i018: ify - a program to iconify MGR windows, Part01/02

comp.sources.3b1 dhb at uunet.UU.NET
Sun Apr 7 14:45:39 AEST 1991


Submitted-by: pyuxd!scj (Steven C. Johnson)
Posting-number: Volume 1, Issue 18
Archive-name: ify/part01

[ This posting was accompanied by a copy of the binaries.  I have placed ]
[ the binaries on OSU in the file 'att7300/ify_bin.Z'.  Should I have    ]
[ posted them?                                                           ]
[ Dave.                                                                  ]

I am submitting this for posting to comp.sources.3b1 in two parts, three
mailings:

     1.  The sources that I modified from the SPARC ify distribution (2
         shar files).
     2.  The ify binary and the complement binary, setname for those who
         do not have a development package and do not have the gnu c compiler
         (required since the stock 3b1 cc barfs on ify.c). (1 shar file).

A README is the included as the first file of the ify_src mail.  Sorry,
I don't have cshar, let me know if this is a problem (and where to get
source for cshar).

---- Cut Here and unpack ----
#!/bin/sh
# This is volume01/ify_src, a shell archive (shar 3.21)
# made 03/29/1991 14:50 UTC by scj at curly
# Source directory /usr/mgr/src/demo/ify
#
# existing files will NOT be overwritten
#
# This shar contains:
# length  mode       name
# ------ ---------- ------------------------------------------
#   2856 -rw-r--r-- README
#   8182 -rw-r--r-- icondata.c
#   3524 -rw-r--r-- ify.1
#  30040 -rw-r--r-- ify.c
#    556 -rw-r--r-- ify.icon
#   1096 -rw-r--r-- makefile
#     21 -rw-r----- patchlevel.h
#   1001 -rw-r--r-- setname.1
#   3635 -rw-r--r-- setname.c
#
if touch 2>&1 | fgrep '[-amc]' > /dev/null
 then TOUCH=touch
 else TOUCH=true
fi
# ============= README ==============
if test X"$1" != X"-c" -a -f 'README'; then
	echo "File already exists: skipping 'README'"
else
echo "x - extracting README (Text)"
sed 's/^X//' << 'SHAR_EOF' > README &&
XThis README describes the first release (to my knowledge) of ify for the
XAT&T 3b1 running the MGR port. Although ify is distributed with at least
Xthe SPARC MGR release, I didn't see ify included with either MGR fix
X3 or 4 for the 3b1 (I'm running MGR based on fix 4).  Thanks to Eric
XKrohn for pointing out the availability of ify in the SPARC MGR
Xdistribution.  Ify's rightful source installation home is under
X~mgr/src/demo/ify, binaries in ~mgr/bin.
X
XSetname, included, provides the user a way to assign meaningful names to the
Xiconified window(s).
X
XOriginal Author:
X   Jim Blandy - July, 1989 - Bell Communications Research
X   *** Modified for the AT&T 3B1 by Steve Johnson - March, 1991 ***
X
XAll original Bell Communications Research MGR distribution and copying
Xpolicies apply to Bellcore-original code.  You may do what you wish with
Xmy additions.
X
XI am running a somewhat different MGR in that mine is "write BLACK,"
Xi.e., I compiled MGR to place black characters on a white (green)
Xbackground instead of the default white characters on a black background. 
XIf this causes problems with ify on your system, please contact me so I
Xcan help work out a solution.  I believe that I have covered this
Xdifference with a new ify runtime switch, -i, for inversion of the color
Xsense of the displayed icon.
X
XWhat is an iconifier?
X
XIfy allows the MGR user to "close and shrink" a MGR window, suspending
Xthe session running in that window.  The closest analogue to ify that
Xmany 3b1 users will understand is the (excellent) 3b1tools iconifier
Xuseful under the UA.  Read the ify man page, because the user interface
Xfor ify is different than 3b1tools.  Ify makes for a more tidy "desktop"
Xsince we suffer with the small screen on our machines :^}.  I can now start
Xup several MGR sessions, but display those sessions only when needed.
X
XSince I had to reverse engineer the compiled, default SPARC ify icon, I
Xhave included ify.icon, which can be, but is not required to be, installed
Xin the 3b1 MGR icon directory.  Although I have been running ify on my 3b1
X(curly) for over two months without any functional problems, I must admit
Xthat the ify binary posted has some "bugs" in the default icon display:
X
X     1.  I cannot guarantee that the icon is *identical* to the SPARC
X         icon.
X
X     2.  I used zoom to add the "IFY" label in the upper left corner of
X         my reverse-engineered icon.
X
X     3.  There are some glitches in the shading of the central square of
X         the default icon that are not present in a zoom'd presentation of
X         ify.icon.  I think this bug surfaces somewhere in my port of icontoc,
X         which I'll post soon if I can find the bug, later if I can't.
X
X-
XSteven C. Johnson [...![bcr]|[bellcore]!pyuxd!scj | scj at pahasapa.bellcore.com]
Xbus. (908) 699-5514                                <scj at 128.96.131.41        >
SHAR_EOF
$TOUCH -am 0329094991 README &&
chmod 0644 README ||
echo "restore of README failed"
set `wc -c README`;Wc_c=$1
if test "$Wc_c" != "2856"; then
	echo original size 2856, current size $Wc_c
fi
fi
# ============= icondata.c ==============
if test X"$1" != X"-c" -a -f 'icondata.c'; then
	echo "File already exists: skipping 'icondata.c'"
else
echo "x - extracting icondata.c (Text)"
sed 's/^X//' << 'SHAR_EOF' > icondata.c &&
X/*   *** Modified for the AT&T 3B1 by Steve Johnson - March, 1991 ***
X*/
X#include "term.h"
X#include "dump.h"
X#include "patchlevel.h"
X#ifdef BBB1
Xchar iconbits[] = {
X/* bitmap icon 80x55x1*/
X	0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0xff, 0xfe, 0x00, 0x00,
X	0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0xff, 0xfe, 0x00, 0x00,
X	0x77, 0x50, 0x00, 0x00, 0x00, 0x06, 0x00, 0x06, 0x00, 0x00,
X	0x24, 0x50, 0x00, 0x00, 0x0b, 0xbe, 0x00, 0x06, 0x00, 0x00,
X	0x26, 0x20, 0x00, 0x00, 0x08, 0x06, 0x00, 0x06, 0x00, 0x00,
X	0x24, 0x20, 0x00, 0x00, 0x08, 0x06, 0x00, 0x06, 0x00, 0x00,
X	0x74, 0x20, 0x02, 0x22, 0x22, 0x27, 0xff, 0xfe, 0x00, 0x00,
X	0x00, 0x00, 0x00, 0x00, 0x08, 0x07, 0xff, 0xfe, 0x00, 0x00,
X	0x00, 0x00, 0x02, 0x00, 0x08, 0x00, 0x00, 0x90, 0x00, 0x00,
X	0x00, 0xff, 0xfd, 0xff, 0xff, 0xff, 0xfc, 0x00, 0x00, 0x00,
X	0x03, 0x80, 0x02, 0x00, 0x00, 0x00, 0x04, 0x90, 0x00, 0x00,
X	0x05, 0x80, 0x00, 0x00, 0x08, 0x00, 0x04, 0x10, 0x00, 0x00,
X	0x0b, 0x80, 0x02, 0x00, 0x08, 0x00, 0x04, 0x90, 0x00, 0x00,
X	0x05, 0x80, 0x00, 0x00, 0x08, 0x00, 0x04, 0x00, 0x00, 0x00,
X	0x0b, 0x80, 0x02, 0x00, 0x00, 0x00, 0x04, 0x90, 0x00, 0x00,
X	0x05, 0x80, 0x00, 0x00, 0x08, 0x00, 0x04, 0x10, 0x00, 0x00,
X	0x0b, 0x80, 0x02, 0x00, 0x0d, 0xdd, 0xdf, 0x70, 0x00, 0x00,
X	0x05, 0x80, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00,
X	0x0b, 0x80, 0x02, 0x00, 0x00, 0x00, 0x04, 0x80, 0x00, 0x00,
X	0x05, 0x80, 0x00, 0x00, 0x00, 0x00, 0x07, 0xff, 0xff, 0x00,
X	0x0b, 0x80, 0x02, 0x00, 0x00, 0x00, 0x04, 0x00, 0x01, 0x00,
X	0x05, 0x80, 0x00, 0x00, 0x00, 0x00, 0x04, 0x80, 0x01, 0x00,
X	0x0b, 0x80, 0x02, 0x00, 0x00, 0x00, 0x04, 0x00, 0x01, 0x00,
X	0x05, 0x80, 0x00, 0x00, 0x00, 0x00, 0x04, 0x80, 0x01, 0x00,
X	0x0b, 0x80, 0x02, 0x00, 0x00, 0x00, 0x04, 0x00, 0x01, 0x00,
X	0x05, 0x80, 0x00, 0x00, 0x00, 0x00, 0x04, 0x80, 0x01, 0x00,
X	0x0b, 0x80, 0x02, 0x00, 0x00, 0x00, 0x04, 0x00, 0x01, 0x00,
X	0x05, 0x80, 0x00, 0x00, 0x00, 0x00, 0x04, 0x80, 0x01, 0x00,
X	0x0b, 0x80, 0x02, 0x22, 0x22, 0x22, 0x22, 0x00, 0x01, 0x00,
X	0x05, 0x80, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x01, 0x00,
X	0x0b, 0x80, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x01, 0x00,
X	0x05, 0x80, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x01, 0x00,
X	0x0b, 0x80, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x01, 0x00,
X	0x05, 0x80, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x01, 0x00,
X	0x0b, 0x80, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x01, 0x00,
X	0x05, 0x80, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x01, 0x00,
X	0x0b, 0x80, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x01, 0x00,
X	0x05, 0x80, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x01, 0x00,
X	0x0b, 0x80, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x01, 0x00,
X	0x05, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfc, 0x00, 0x01, 0x00,
X	0x0b, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf8, 0x00, 0x01, 0x00,
X	0x05, 0x55, 0x55, 0x5d, 0x55, 0x55, 0x50, 0x00, 0x01, 0x00,
X	0x0a, 0xaa, 0xaa, 0xb8, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00,
X	0x05, 0x55, 0x55, 0x58, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00,
X	0x00, 0x00, 0x00, 0x38, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00,
X	0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00,
X	0x00, 0x00, 0x00, 0x38, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00,
X	0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00,
X	0x00, 0x00, 0x00, 0x38, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00,
X	0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00,
X	0x00, 0x00, 0x00, 0x38, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00,
X	0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00,
X	0x00, 0x00, 0x00, 0x38, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00,
X	0x00, 0x00, 0x00, 0x1f, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00,
X	0x00, 0x00, 0x00, 0x3f, 0xff, 0xff, 0xff, 0xff, 0xfe, 0x00,
X#else /* SPARC */
Xchar iconbits[] = {
X/* bitmap icon 96x55x1*/
X	0x00, 0x7f, 0xff, 0xe0, 0x00, 0x00, 0x00, 0x00, 0x0f, 0x90, 0x00, 0x00,
X	0x00, 0x7f, 0xff, 0xe0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
X	0x00, 0x60, 0x00, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00,
X	0x00, 0x60, 0x00, 0x7d, 0xd0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
X	0x00, 0x60, 0x00, 0x60, 0x10, 0x00, 0x00, 0x00, 0x00, 0x0a, 0x00, 0x00,
X	0x00, 0x60, 0x00, 0x60, 0x10, 0x00, 0x00, 0x00, 0x0f, 0xff, 0x00, 0x00,
X	0x00, 0x7f, 0xff, 0xe4, 0x44, 0x44, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00,
X	0x00, 0x7f, 0xff, 0xe0, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
X	0x00, 0x09, 0x00, 0x00, 0x10, 0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00,
X	0x00, 0x00, 0x3f, 0xff, 0xff, 0xff, 0xbf, 0xff, 0x00, 0x00, 0x00, 0x00,
X	0x00, 0x09, 0x20, 0x00, 0x00, 0x00, 0x40, 0x01, 0xc0, 0x02, 0x00, 0x00,
X	0x00, 0x08, 0x20, 0x00, 0x10, 0x00, 0x00, 0x01, 0xa0, 0x20, 0x00, 0x00,
X	0x00, 0x09, 0x20, 0x00, 0x10, 0x00, 0x40, 0x01, 0xd0, 0xd4, 0x00, 0x00,
X	0x00, 0x00, 0x20, 0x00, 0x10, 0x00, 0x00, 0x01, 0xa0, 0x49, 0x00, 0x00,
X	0x00, 0x09, 0x20, 0x00, 0x00, 0x00, 0x40, 0x01, 0xd0, 0x00, 0x00, 0x00,
X	0x00, 0x08, 0x20, 0x00, 0x10, 0x00, 0x00, 0x01, 0xa9, 0x50, 0x00, 0x00,
X	0x00, 0x0e, 0xfb, 0xbb, 0xb0, 0x00, 0x40, 0x01, 0xd0, 0x01, 0x00, 0x00,
X	0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x00, 0x01, 0xa0, 0x28, 0x00, 0x00,
X	0x00, 0x01, 0x20, 0x00, 0x00, 0x00, 0x40, 0x01, 0xd0, 0x00, 0x00, 0x00,
X	0xff, 0xff, 0xe0, 0x00, 0x00, 0x00, 0x00, 0x01, 0xa0, 0x60, 0x00, 0x00,
X	0x80, 0x00, 0x20, 0x00, 0x00, 0x00, 0x40, 0x01, 0xdf, 0xff, 0x00, 0x00,
X	0x80, 0x01, 0x20, 0x00, 0x00, 0x00, 0x00, 0x01, 0xa0, 0x28, 0x00, 0x00,
X	0x80, 0x00, 0x20, 0x00, 0x00, 0x00, 0x40, 0x01, 0xd0, 0xe2, 0x00, 0x00,
X	0x80, 0x01, 0x20, 0x00, 0x00, 0x00, 0x00, 0x01, 0xa0, 0x00, 0x00, 0x00,
X	0x80, 0x00, 0x20, 0x00, 0x00, 0x00, 0x40, 0x01, 0xd0, 0x44, 0x00, 0x00,
X	0x80, 0x01, 0x20, 0x00, 0x00, 0x00, 0x00, 0x01, 0xa0, 0x14, 0x00, 0x00,
X	0x80, 0x00, 0x20, 0x00, 0x00, 0x00, 0x40, 0x01, 0xd0, 0x00, 0x00, 0x00,
X	0x80, 0x01, 0x20, 0x00, 0x00, 0x00, 0x00, 0x01, 0xa0, 0x14, 0x00, 0x00,
X	0x80, 0x00, 0x44, 0x44, 0x44, 0x44, 0x40, 0x01, 0xd0, 0x80, 0x00, 0x00,
X	0x80, 0x00, 0x20, 0x00, 0x00, 0x00, 0x00, 0x01, 0xa0, 0x14, 0x00, 0x00,
X	0x80, 0x00, 0x20, 0x00, 0x00, 0x00, 0x00, 0x01, 0xd0, 0x88, 0x00, 0x00,
X	0x80, 0x00, 0x20, 0x00, 0x00, 0x00, 0x00, 0x01, 0xa0, 0x14, 0x00, 0x00,
X	0x80, 0x00, 0x20, 0x00, 0x00, 0x00, 0x00, 0x01, 0xd0, 0x80, 0x00, 0x00,
X	0x80, 0x00, 0x20, 0x00, 0x00, 0x00, 0x00, 0x01, 0xa0, 0x8c, 0x00, 0x00,
X	0x80, 0x00, 0x20, 0x00, 0x00, 0x00, 0x00, 0x01, 0xd0, 0x00, 0x00, 0x00,
X	0x80, 0x00, 0x20, 0x00, 0x00, 0x00, 0x00, 0x01, 0xa0, 0x00, 0x00, 0x00,
X	0x80, 0x00, 0x20, 0x00, 0x00, 0x00, 0x00, 0x01, 0xd0, 0x61, 0x00, 0x00,
X	0x80, 0x00, 0x20, 0x00, 0x00, 0x00, 0x00, 0x01, 0xa0, 0x64, 0x00, 0x00,
X	0x80, 0x00, 0x20, 0x00, 0x00, 0x00, 0x00, 0x01, 0xd0, 0xd6, 0x00, 0x00,
X	0x80, 0x00, 0x3f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xa0, 0x61, 0x00, 0x00,
X	0x80, 0x00, 0x1f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xd6, 0x6f, 0x00, 0x00,
X	0x80, 0x00, 0x0a, 0xaa, 0xaa, 0xba, 0xaa, 0xaa, 0xa0, 0x00, 0x00, 0x00,
X	0x80, 0x00, 0x00, 0x00, 0x00, 0x1d, 0x55, 0x55, 0x56, 0x03, 0x00, 0x00,
X	0x80, 0x00, 0x00, 0x00, 0x00, 0x1a, 0xaa, 0xaa, 0xa0, 0x2a, 0x00, 0x00,
X	0x80, 0x00, 0x00, 0x00, 0x00, 0x1c, 0x00, 0x00, 0x03, 0x75, 0x00, 0x00,
X	0x80, 0x00, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
X	0x80, 0x00, 0x00, 0x00, 0x00, 0x1c, 0x00, 0x00, 0x00, 0xa1, 0x00, 0x00,
X	0x80, 0x00, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0x7c, 0x00, 0x00,
X	0x80, 0x00, 0x00, 0x00, 0x00, 0x1c, 0x00, 0x00, 0x09, 0x30, 0x00, 0x00,
X	0x80, 0x00, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x04, 0x02, 0x00, 0x00,
X	0x80, 0x00, 0x00, 0x00, 0x00, 0x1c, 0x00, 0x00, 0x00, 0x34, 0x00, 0x00,
X	0x80, 0x00, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x0c, 0x65, 0x00, 0x00,
X	0x80, 0x00, 0x00, 0x00, 0x00, 0x1c, 0x00, 0x00, 0x0a, 0x61, 0x00, 0x00,
X	0xff, 0xff, 0xff, 0xff, 0xff, 0xf8, 0x00, 0x00, 0x0a, 0x08, 0x00, 0x00,
X	0x7f, 0xff, 0xff, 0xff, 0xff, 0xfc, 0x00, 0x00, 0x00, 0x2a, 0x00, 0x00,
X#endif
X};
X
Xloadicon(n, w, h)
X     int n, *w, *h;
X{
X    int s, old_mode, new_mode;
X
X    m_flush();
X
X#ifdef BSD
X    ioctl(fileno(m_termout),TIOCLGET,&old_mode);
X    new_mode = old_mode | LLITOUT;
X    ioctl(fileno(m_termout),TIOCLSET,&new_mode);
X#endif /* BSD */
X
X    m_bitdestroy(n);
X
X#ifdef BBB1
X    m_bitldto(*w=68,*h=55,0,0,n,s=B_SIZE16(80,55,1));
X#else
X    m_bitldto(*w=68,*h=55,0,0,n,s=B_SIZE32(68,55,1));
X#endif /* BBB1 */
X
X    fwrite(iconbits,s,1,m_termout);
X    m_flush();
X
X#ifdef BSD
X    ioctl(fileno(m_termout),TIOCLSET,&old_mode);
X#endif /* BSD */
X}
SHAR_EOF
$TOUCH -am 0328153691 icondata.c &&
chmod 0644 icondata.c ||
echo "restore of icondata.c failed"
set `wc -c icondata.c`;Wc_c=$1
if test "$Wc_c" != "8182"; then
	echo original size 8182, current size $Wc_c
fi
fi
# ============= ify.1 ==============
if test X"$1" != X"-c" -a -f 'ify.1'; then
	echo "File already exists: skipping 'ify.1'"
else
echo "x - extracting ify.1 (Text)"
sed 's/^X//' << 'SHAR_EOF' > ify.1 &&
X.TH ify 1L "July 25, 1989"
X.SH NAME
Xify \- Iconify MGR windows
X.SH SYNOPSIS
X.B ify
X[ \fB\-s\fP ] [\fB\-i\fP ]
X.SH DESCRIPTION
X\fBIfy\fP lets the user iconify \fBMGR\fP windows.  When run,
X\fBify\fP shrinks its window and displays its icon.  If started with
Xthe \fB\-s\fP option, \fBify\fP does not reshape its window to fit the
Xicon.  If started with the \fB\-i\fP option, \fBify\fP reverses the
Xcolor sense of the displayed ify icon.
X.PP
XWhile \fBify\fP's window is active, the user can iconify or de-iconify
Xwindows by clicking on them with the right mouse button.  To iconify a
Xwindow, \fBify\fP shrinks it and buries it in an unoccupied portion of the
Xscreen.  To de-iconify a window, \fBify\fP restores the window's size,
Xposition, contents and settings.  Iconified windows cannot handle
Xinput or output; programs doing output to iconified windows will
Xblock.  If an application has opened several subwindows on the screen,
Xthe user may click on any of the windows to iconify the whole group;
Xclicking on any of the iconified windows de-iconfies the whole group.
X.PP
XThe middle mouse button displays a pop-up menu listing the currently
Xclosed windows; selecting a window from the menu opens it.  The menu
Xalso contains a \fIquit\fP item, which exits \fBify\fP, and a
X\fIremake menu\fP item, which causes \fBify\fP to re-examine the
Xdisplay for closed windows and update its list.
X.PP
X\fBIfy\fP titles an iconified window with its \fBNOTIFY\fP string,
Xpossibly followed by its window id in parenthesis, if it is a
Xsubwindow.  The \fBNOTIFY\fP string can be set from within C programs
Xusing a statement of the form
X.RS
Xm_setevent(NOTIFY, "\fItitle\fP");
X.RE
Xor from the shell using the \fBsetname\fP program, possibly as part of
Xthe .mgrc file.  If a window has no \fBNOTIFY\fP event set, \fBify\fP
Xtitles it with the name of its tty.
X.PP
XTo find its icon, \fBify\fP searches \fBMGR\fP's current directory
X(usually the user's home directory) for a file called \fB.ify.icon\fP,
Xand then searches the standard \fBMGR\fP icon directory for a file
Xcalled \fBify.icon\fP.  If neither of those files exists, it despairs
Xand downloads its own icon.
X.PP
XIf there are no free spots on the screen, \fBify\fP starts stacking windows
Xgoing down the left side of the screen.
X.SH NOTES
X\fBIfy\fP runs more smoothly when \fBMGR\fP has its setuid bit turned
Xon.  If \fBMGR\fP is not running with the setuid bit on, the
Xpseudo-ttys for the windows end up being owned by root, not by the
Xuser.  In this situation, since \fBify\fP can't turn off general write
Xpermission to its tty, its internal operations become a little less
Xrobust; it may start behaving strangely when the system becomes
Xheavily loaded, or if an application has opened many windows.
X.SH SEE ALSO
Xmgr(1L), close(1), setname(1L)
X.SH DIAGNOSTICS
XIf \fBify\fP encounters an unexpected error from a system call, it prints the
Xerror message and exits.  These messages are usually not very helpful to
Xthe end user, and probably indicate bugs in \fBify\fP itself.
X.SH BUGS
XIf a program has several windows open, de-iconifying the group may leave
Xthe wrong window selected.
X.PP
XSome programs push their event strings without establishing a new
X\fBNOTIFY\fP string, so iconification leaves them untitled.
X.PP
X\fBIfy\fP stores information in a window's \fBNOTIFY\fP string while
Xthe window is iconified; if this information is corrupted, \fBify\fP
Xmight not be able to reopen the window.  To get around this, select
Xthe iconified window and press control-Q.
X.SH AUTHOR
XJim Blandy
SHAR_EOF
$TOUCH -am 0328163891 ify.1 &&
chmod 0644 ify.1 ||
echo "restore of ify.1 failed"
set `wc -c ify.1`;Wc_c=$1
if test "$Wc_c" != "3524"; then
	echo original size 3524, current size $Wc_c
fi
fi
# ============= ify.c ==============
if test X"$1" != X"-c" -a -f 'ify.c'; then
	echo "File already exists: skipping 'ify.c'"
else
echo "x - extracting ify.c (Text)"
sed 's/^X//' << 'SHAR_EOF' > ify.c &&
X/* ify.c - iconify an mgr window
X   Jim Blandy - July, 1989 - Bell Communications Research
X   *** Modified for the AT&T 3B1 by Steve Johnson - March, 1991 ***
X
XThis program is designed to replace the 'close' program that comes
Xwith MGR - ify doesn't require you to stop the program running in a
Xwindow and start up another one, like close does.
X
XWhen you first click on a window, ify finds out which pseudo-tty that
Xwindow is attached to, finds all the other windows attached to that
Xpsuedo-tty, and closes them by sending the appropriate escape codes to
Xthe pseudo-tty, changing the window's NOTIFY string to
X"CLOSED:<tty>:<old notify name>", using the window's original NOTIFY
Xas a title for the closed window, and then doing a TIOCSTOP ioctl on
Xit, basically equivalent to a ^S.  After sending the ^S, ify sends the
Xescape codes to restore the window's position and content; since the
Xtty has been ^S'ed, these don't take effect yet.
X
XWhen you click on a closed window, ify notices that the window is
Xalready closed by looking at its NOTIFY string, opens the window's
Xptty, and does a TIOCSTART ioctl on it (equivalent to a ^Q).  This
Xlets MGR see the escape codes ify queued up when the window was
Xclosed, so MGR opens the window.
X
XThe list of closed windows displayed on the menu is obtained by asking
XMGR for everyone's NOTIFY strings, and selecting those windows whose
XNOTIFY strings start with "CLOSED:".  This menu is refreshed when a
Xwindow is closed or opened.
X
XNote that MGR divides its attention among several ttys; if you send
Xdata to someone else's tty, as ify does, MGR takes its own sweet time
Xto notice what you've sent; you have to wait for it to take effect.
XAfter sending the codes to close up a group of windows, ify sends a
Xm_sendto() message to itself; when it gets the message, it knows that
Xthe window is all done.  It pulls the same trick when opening windows,
Xin order to keep the menu up to date.  The only kink in this setup is
Xthat, in order to receive m_sendto() messages, ify needs to be able to
Xturn off general write permission to its tty, which means it needs to
Xown its tty.  This can only happen if you're running MGR with the
Xsetuid bit on.  If ify can't change its tty, it gives up on the
Xmessage-passing strategy and just sleeps a bit (see the WAITTIME
Xconstant) after each operation.
X					-JimB
X*/
X
X#include <sys/ioctl.h>		/* for ioctl(): TIOCSTOP & TIOCSTART */
X#include <sys/types.h>		/* these two for fstat() */
X#include <sys/stat.h>		/* ... also for fstat() */
X#include <signal.h>		/* signal-catching stuff */
X
X#ifdef BSD
X#include <strings.h>		/* for strchr() */
X#endif /* BSD */
X
X#include <string.h>		/* for other stuff */
X#include <ctype.h>		/* for isspace() */
X#include "term.h"		/* for MGR declarations */
X#include "patchlevel.h"
X
X/* compatibility with different versions of MGR */
X#ifdef OLDMGR
X#define m_setcursor(s)
X#undef m_whatsat
X#define m_whatsat(x,y) \
X	(fprintf(m_termout,"%c%d,%d%c",m_escchar,x,y,E_GETINFO),m_flush())
X/* older version of m_whatsat() forgets to send the y co-ord */
X#endif /* OLDMGR */
X
X/* general tty mashing stuff: */
X#define TTYSUFFIXLEN (3)	/* length of ptty suffix + 1 */
X#define TTYPREFIX "/dev/ttym"	/* prefix for pttys */
X#define TTYPREFIXLEN (sizeof(TTYPREFIX)+1) /* length of TTYPREFIX+1 */
Xchar ttytemp[TTYPREFIXLEN+TTYSUFFIXLEN];	/* for FULLTTYNAME() */
X#define FULLTTYNAME(suff)	/* make full name from suffix - temporary! */\
X       (strcat(strcpy(ttytemp, TTYPREFIX), suff))
X
X/* notify string stuff: */
Xchar closednotify[] = "CLOSED:"; /* notify prefix for closed windows */
X#define CLNLEN (7)		/* length of above */
X
X/* ify's icon stuff: */
X#define LOCALICONNAME "./.ify.icon" /* name for local icon */
X#define MGRICONNAME "ify.icon"	/* name for global mgr icon */
X#define ICONBITMAP 1		/* scratch bitmap for icon's image */
Xint icon_w, icon_h;		/* size of icon */
Xint icon_x, icon_y;		/* position of icon within window */
X
X/* ify window position stuff: */
X#define MINW (50)		/* minimum window size */
X#define MINH (font_h)		/* minimum height */
Xint wind_x, wind_y;		/* position of our window on the screen */
Xint wind_w, wind_h;		/* desired width & height */
Xint shapetofit = 1;		/* should we shape to fit? */
X
X#ifdef BBB1
Xint inverticon = 0;             /* should we invert icon? */
Xtypedef unsigned short u_short; /* ain't standards fun? */
X#endif
X
X/* stuff for figuring out where to put closed windows: */
Xint disp_w, disp_h;		/* display size */
Xint font_w, font_h;		/* font size */
Xint border;			/* border thickness */
Xstruct window_data layout[200];	/* space for list of windows on the screen */
Xint layoutlen;			/* # of windows in layout */
X#define Max(x,y)	((x)>(y)?(x):(y))
X#define XSLOP (6)		/* extra horizontal space around window */
X#define YSLOP (2)		/* extra vertical space around window */
X
X/* error reporting stuff: */
Xchar *progname;			/* name of this program */
Xextern int errno, sys_nerr;
Xextern char *sys_errlist[];
Xchar errtemp[100];		/* space for THEERROR() */
X#define THEERROR(msg)\
X  (strcat(strcpy(errtemp, msg),\
X    (errno<sys_nerr?sys_errlist[errno]:"unknown error")))
X
X
X#define iocuddle ioctl		/* to be cute */
X
X/* stuff for changing our general write permission: */
Xchar ourtty[TTYPREFIXLEN+TTYSUFFIXLEN];	/* the tty we're running on */
Xint windowpid;			/* process id representing this window */
X#define WAITTIME (2)		/* # of seconds to wait for MGR to finish */
X				/* closing windows.  Not used if we can */
X				/* change the protection on our ptty. */
Xu_short oldmode;		/* protection bits of the tty when the
X				   program started */
X
X/* debugging error messages & stuff: */
X#define dprintf			/* define dprintf or eprintf to be fprintf */
X#define eprintf			/* to turn on debugging messages */
X
X/* Note that the dupkey we use for this program is ^E, written here
X   as \005.  I didn't bother defining it, since it appears in strings
X   and it's a pain to include a constant in a string with a non-ANSI
X   compiler. */
X#define DUPKEYON { if (dupkeyokay) m_dupkey('\005'); }
X#define DUPKEYOFF { if (dupkeyokay) m_clearmode(M_DUPKEY); }
Xint dupkeyokay, hasdupkey();	/* is dupkey available? */
X
X#define CNULL ((char *) 0)
X
Xchar usage[] = "\
XWhile this program's window is active, click on windows with the right\n\
Xbutton to open or close.  The middle button's menu lets you quit or choose\n\
Xa closed window to open.\n";
X
Xmain(argc, argv)
X     int argc;
X     char **argv;
X{
X    int catchint();
X#   define BUFLEN (80)
X    char buf[BUFLEN+1];		/* space for info from MGR */
X    
X    /* ==================== process arguments ==================== */
X    progname = argv[0];
X    for (argc--, argv++; argc>0; argc--,argv++)
X      if ((*argv)[0] == '-')
X	switch((*argv)[1]) {
X	  case 's':
X	    shapetofit = 0;
X	    break;
X#ifdef BBB1
X          case 'i':
X            inverticon = 1;
X            break;
X#endif
X	  default:
X	    fprintf(stderr, "%s: unrecognized option: %s\n",
X		    progname, *argv);
X	    /* fall through */
X	  case '\0':
X	    fprintf(stderr, "Usage: %s\n%s", progname, usage);
X	    exit(1);
X	}
X      else {
X	  fprintf(stderr, "Usage: %s\n%s", progname, usage);
X	  exit(1);
X      }
X
X    /* ==================== Generic Initialization ==================== */
X
X    m_setup(M_FLUSH);
X    dupkeyokay = hasdupkey();
X    m_ttyset();
X    m_push(P_EVENT | P_FLAGS | P_MENU | P_POSITION);
X    signal(SIGINT, catchint);
X    DUPKEYOFF;
X    m_setmode(M_ABS);
X    m_setmode(M_NOWRAP);
X    m_setcursor(9);
X
X#ifdef BBB1
X    if (inverticon)
X        m_func(B_COPYINVERTED);
X    else
X#endif
X    m_func(B_SRC);
X
X    m_flush();
X
X    {
X	char *ttyname();
X	char *t = ttyname(2);	/* get tty attached to stderr */
X
X	if (t == CNULL)
X#ifdef BSD
X	    shutdown("Can't find name of tty");
X#else /* SYSV */
X	{
X	    fprintf(stderr, "Can't find name of tty");
X	    exit(-1);
X	}
X#endif /* BSD */
X
X	strcpy(ourtty, t);	/* make a copy of ttyname()'s value */
X    }
X
X    /* turn off general write permission to the tty, so we can accept
X       m_sendme() messages */
X    {
X	struct stat ttymode;
X
X	if (stat(ourtty, &ttymode) == -1)
X	  closedown(THEERROR("ourtty stat: "));
X	oldmode = ttymode.st_mode; /* get the old protection bits */
X    }
X
X    /* Can we use m_sendto messages? */
X    if ((oldmode & 077) == 0 || chmod(ourtty, 00600) != -1)
X      windowpid = getwid();
X    else {
X	static char mesg[] =
X	  "Ify runs better if MGR has its setuid bit on.";
X
X	windowpid = 0;
X	m_clear();
X	m_push(P_POSITION);
X	m_size(sizeof(mesg)-1, 1);
X	m_printstr(mesg);
X	m_flush();
X	sleep(5);
X	m_pop();
X	m_flush();
X    }
X
X    get_param(NULL, &disp_w, &disp_h, &border);
X    get_font(&font_w, &font_h);
X    DUPKEYON;
X
X    /* ==================== try to read in icon file ==================== */
X    m_bitfromfile(ICONBITMAP, LOCALICONNAME); /* try to find local icon */
X    skipgarbage(); m_gets(buf);
X    eprintf(stderr, "buf: \"%s\"\n", buf);
X    if (buf[0] == '\n') {	/* did we get the file? */
X	m_bitfromfile(ICONBITMAP, MGRICONNAME); /* no - try global icon */
X	skipgarbage(); m_gets(buf);
X	eprintf(stderr, "buf: \"%s\"\n", buf);
X	if (buf[0] == '\n')	/* no go there either? */
X	  loadicon(ICONBITMAP, &icon_w, &icon_h);
X    }
X    if (buf[0] != '\n')		/* unless we used our built-in icon... */
X      sscanf(buf, "%d %d", &icon_w, &icon_h); /* get the icon size */
X    /* now we've got the icon in ICONBITMAP, and its size in icon_[wh]. */
X    DUPKEYOFF;
X    get_size(&wind_x, &wind_y, &wind_w, &wind_h);
X    DUPKEYON;
X    if (shapetofit) {
X	wind_w = Max(MINW, icon_w);
X	wind_h = Max(MINH, icon_h);
X    }
X    icon_x = (wind_w - icon_w)/2;
X    icon_y = (wind_h - icon_h)/2;
X    wind_w += 2*border;
X    wind_h += 2*border;
X    if (shapetofit) {
X    	m_shapewindow(wind_x, wind_y, wind_w, wind_h);
X    }
X    m_clear();
X    m_bitcopyto(icon_x, icon_y, icon_w, icon_h, 0, 0, 0, ICONBITMAP);
X    m_flush();
X/*     m_bitsave(ICONBITMAP, "./ify/ify.icon"); */
X
X    eprintf(stderr, "icon: %dx%d\n", icon_w, icon_h);
X    eprintf(stderr, "buf: \"%s\"\n", buf);
X
X    /* ==================== set up events ==================== */
X
X    /* clicked on a window */
X    m_setevent(BUTTON_1, "\005b%p,%n\\r");
X
X    /* screen is being redrawn */
X    m_setevent(REDRAW, "\005r\\r");
X
X    /* window was reshaped */
X    m_setevent(RESHAPE, "\005s\\r");
X
X    /* a window is done with being opened - rebuild the menu */
X    m_setevent(ACCEPT, "\005n\\r");
X
X    /* This window's name */
X    m_setevent(NOTIFY, "== Ify ==");
X
X    /* build the initial menu */
X    makemenu();
X
X    /* ==================== main event loop ==================== */
X    for (;;) {
X
X	skipgarbage();
X	if (fgets(buf, BUFLEN, m_termin) == CNULL) /* end of file? */
X	  closedown(CNULL);
X	buf[strlen(buf)-1] = '\0'; /* zap the newline */
X
X	switch(buf[0]) {
X
X	  case 'q':		/* quit program */
X	    closedown(CNULL);
X	    break;
X
X	  case 'b':		/* button pressed */
X	    {
X		int x, y;
X		char *notify;
X		
X		/* extract information from the event string */
X		sscanf(buf+1, "%d %d", &x, &y);
X		if ((notify = strchr(buf, ',')) == CNULL)
X		  closedown("no comma in button event!");
X		notify++;
X		clickon(x, y, notify);
X	    }
X	    break;
X
X	  case 's':		/* they've reshaped the window - unshape it */
X	    DUPKEYOFF;
X	    get_size(&wind_x, &wind_y, NULL, NULL);
X	    DUPKEYON;
X	    m_shapewindow(wind_x, wind_y, wind_w, wind_h);
X	    /* fall through to redraw */
X
X	  case 'r':		/* redraw the screen */
X	    m_clear();
X	    m_bitcopyto(icon_x, icon_y, icon_w, icon_h, 0, 0, 0, ICONBITMAP);
X	    m_flush();
X	    break;
X
X	  case 'n':		/* remake the menu */
X	    makemenu();
X	    m_flush();
X	    break;
X
X	  case 'm':		/* window selected from menu */
X	    openwindows(buf+1);	/* open the windows attached to the given */
X				/* ptty */
X	    break;
X
X	  default:		/* something we weren't expecting */
X	    {
X		char errtmp[BUFLEN*2];
X		sprintf(errtmp, "unrecognized event: %s", buf);
X		closedown(errtmp);
X		break;
X	    }
X	    break;
X	}
X    }
X}
X
X
X/* =============== get our events and only our events =============== */
X
Xskipgarbage()
X/* scan the input stream until we find a ^E followed by a non-
X   ^E character.  Skip any spaces or tabs.  The first non-space/tab
X   is pushed back into the input stream. */
X{
X    int c;
X    
X    m_flush();
X    
X    if (dupkeyokay) {
X	do {
X	    while ((c = m_getchar()) != EOF && c != '\005')
X	      ;
X	    if (c != EOF)
X	      c = m_getchar();
X	} while (c == '\005');
X	
X	while (isspace(c) && c != '\n')
X	  c = m_getchar();
X	
X	if (c != EOF)
X	  ungetc(c, m_termin);
X    }
X    else {
X	if ((c = m_getchar()) != '\005')
X	  ungetc(c, m_termin);
X    }
X}
X
X
X/* ===================== Exit Cleanly ==================== */
X
Xcatchint()
X/* function to call on interrupt - exit with error status */
X{
X    signal(SIGINT, SIG_DFL);	/* turn off interrupt catching */
X    closedown("");
X}
X
Xclosedown(msg)
X     char *msg;
X/* Clean up window, restore window to its original shape.  If msg == NULL,
X   shut down with no error status.  If msg == "", exit with an error
X   status.  Otherwise, print <progname>: <msg>\n and exit with an error. */
X{
X    m_popall();
X    m_setcursor(CS_BLOCK);
X    m_clear();
X    m_flush();
X    m_ttyreset();
X
X    /* restore old protection, if we ever changed it */
X    if ((oldmode & 077) != 0 && windowpid && chmod(ourtty, oldmode) == -1)
X      msg = THEERROR("chmod ourtty II: ");
X
X    if (msg == CNULL)
X      exit(0);
X
X    if (msg[0] != '\0')
X	fprintf(stderr, "%s: %s\n", progname, msg);
X    exit(2);
X}
X
X
X/* ==================== Open or close a window ==================== */
X
Xclickon(x, y, notify)
X     int x, y;
X     char *notify;
X/* deal with a click on the given position - we get the notify string at
X   that position for free */
X{
X    char tty[TTYSUFFIXLEN];	/* the tty for that window */
X    int win, pid;		/* alternate window #, pid */
X    void foreachwindow();	/* iterate over some windows */
X    void dontnotice();		/* mark window to be ignored */
X    void shapeclose();		/* reshape & relabel a window as closed */
X    void queueopen();		/* send the escape codes to re-open a
X				   window when the output is re-enabled */
X
X    DUPKEYOFF;
X    get_size(&wind_x, &wind_y, NULL, NULL); /* where are we? */
X    DUPKEYON;
X
X    x += wind_x; y += wind_y;	/* adjust click location to display */
X				/* co-ordinates */
X
X    /* what did the user click on? */
X    if (get_whatsat(x, y, tty, &win, &pid) != 0) {
X	if (strncmp(notify, closednotify, CLNLEN) == 0)
X	  openwindows(tty);
X	else {
X	    /* get a handle on their tty */
X	    FILE *ttyfp, *oldtermout;
X	    int ttyfd;
X
X	    if ((ttyfp = fopen(FULLTTYNAME(tty), "w")) == NULL)
X	      closedown(THEERROR("open tty II: "));
X	    ttyfd = fileno(ttyfp);
X
X	    /* disconnect the menu - the menu isn't going to be valid
X	       until this process completes */
X	    m_nomenu();
X	    m_flush();
X
X	    DUPKEYOFF;
X	    layoutlen = get_all(layout); /* get list of all the windows */
X	    DUPKEYON;
X	    
X	    /* make sure that the window isn't currently ^S-ed */
X#ifdef BSD
X	    if (iocuddle(ttyfd, TIOCSTART) == -1)
X	      closedown(THEERROR("iocuddle TIOCSTART II: "));
X#else /* SYSV */
X	    if (iocuddle(ttyfd, TCXONC, 1) == -1)
X	      closedown(THEERROR("iocuddle TCXONC 1: "));
X#endif /* BSD */
X
X	    /* don't notice the windows that haven't been closed yet */
X	    foreachwindow(layout, layoutlen, tty, dontnotice, CNULL);
X
X	    /* close the windows attached to this tty */
X	    foreachwindow(layout, layoutlen, tty, shapeclose, notify);
X
X	    /* We need to know when MGR is finished interpreting all those
X	       commands we've queued up there so we don't iocuddle too soon
X	       and freeze the tty before MGR has read the commands.  If we
X	       succeeded in turning off general write permission up at the
X	       top, we can have the closee send the closer a message with
X	       the m_sendto()/ACCEPT mechanism.  Otherwise, we'll just wait
X	       an arbitrary amount of time for MGR to finish up, and then
X	       iocuddle.  windowpid is set iff we could set up the tty to have
X	       write permission turned off. */
X		
X	    if (windowpid != 0) {
X		/* have mgr tell me when it's finished with all that
X		   stuff */
X		m_push(P_EVENT);
X		m_setevent(ACCEPT, "\005done!\\r");
X		m_flush();
X		oldtermout = m_termout; m_termout = ttyfp;
X		m_sendto(windowpid, "fini!");
X		m_flush();
X		m_termout = oldtermout;
X		skipgarbage();
X		while (m_getchar() != '\n')
X		  ;
X		m_pop();
X		m_flush();
X	    }
X	    else
X	      sleep(WAITTIME);
X
X	    /* stop all output to that ptty */
X#ifdef BSD
X	    if (iocuddle(ttyfd, TIOCSTOP) == -1)
X	      closedown(THEERROR("iocuddle TIOCSTOP: "));
X#else /* SYSV */
X	    if (iocuddle(ttyfd, TCXONC, 0) == -1)
X	      closedown(THEERROR("iocuddle TCXONC 0: "));
X#endif /* BSD */
X	    
X	    /* queue escape codes to re-open them when output is
X	       re-enabled */
X	    foreachwindow(layout, layoutlen, tty, queueopen, CNULL);
X
X	    fclose(ttyfp);	/* close the tty - we're done */
X
X	    makemenu();		/* refresh the menu's view of life */
X	}
X    }
X}
X
X
X/* =============== the nitty-gritty of opening and closing =============== */
X
X/*ARGSUSED*/
Xvoid
Xdontnotice(t, w)
X     FILE *t;
X     struct window_data *w;
X/* mark *w as a window for find_spot to ignore */
X{
X    if (w->w > 0) w->w = -w->w;
X}
X
Xvoid
Xshapeclose(t, w, notify)
X     FILE *t;
X     struct window_data *w;
X     char *notify;
X/* reshape, retitle, reposition, and renotify the given window.  Use
X   layout[] to find a nice position for the closed window, and ignore
X   windows with negative widths in layout[] - these are windows that
X   will be closed, but haven't been dealt with yet.  Once we've closed
X   this window, record its new position in layout[]. */
X{
X    int width, height;
X    int new_x, new_y;
X    char title[BUFLEN*2];	/* space for window's title */
X
X    /* quick hack for positioning windows on a full screen */
X    static int next_x, next_y, widest;
X
X    if (w->num == 0)
X      sprintf(title, "%-5s",
X	      (notify[0] == '\0' ? FULLTTYNAME(w->tty) : notify));
X    else
X      sprintf(title, "%-5s(%d)",
X	      (notify[0] == '\0' ? FULLTTYNAME(w->tty) : notify),
X	      w->num);
X
X    width = strlen(title)*font_w + 2*border;
X    height = font_h + 2*border;
X    if (find_spot(width, height, layout, layoutlen, &new_x, &new_y) == 0) {
X
X	/* quick hack to position a window on a full screen */
X	new_x = next_x; new_y = next_y;
X	width += XSLOP;
X	height += YSLOP;
X	if (width > widest) widest = width;
X	if ((next_y += height) > disp_h - height) {
X	    next_y = 0;
X	    next_x += widest;
X	    widest = 0;
X	}
X    }
X
X    {
X	FILE *oldtermout = m_termout;
X	char newnotify[500];
X	m_termout = t;
X
X	/* build up the new notify string: CLOSED:<tty>:<window title> */
X	sprintf(newnotify, "%s%s:%s", closednotify, w->tty, title);
X    
X	m_selectwin(w->num);
X	m_push(P_CURSOR|P_EVENT|P_FLAGS|P_FONT|P_POSITION|P_TEXT|P_WINDOW);
X				/* push window state */
X	m_envcount--;		/* that push isn't OUR push */
X	m_font(0);		/* use the default font */
X	m_size(strlen(title),1); /* resize it to display message */
X	m_movewindow(new_x, new_y); /* move it to a good place */
X	m_setevent(NOTIFY,newnotify); /* mark window as closed */
X	m_setmode(M_NOWRAP);	/* turn off line wrap */
X	m_clearmode(M_ACTIVATE); /* and bury the window */
X	m_clear();		/* make it blank */
X	m_printstr(title);	/* print new label */
X	m_flush();
X
X	m_termout = oldtermout;
X    }
X
X    /* record this window's new size and shape in layout[], and thus
X       mark it as something to be considered in subsequent find_spot()s */
X    w->x = new_x; w->y = new_y;
X    w->w = width; w->h = height;
X}
X
Xvoid
Xqueueopen(t, w)
X     FILE *t;
X     struct window_data *w;
X/* queue an m_selectwin and an m_pop for this window */
X{
X    FILE *oldtermout = m_termout;
X
X    m_termout = t;
X
X    m_selectwin(w->num);
X    m_envcount++;		/* that pop's not OUR pop */
X    m_pop();
X    m_flush();
X
X    m_termout = oldtermout;
X}
X
X
Xopenwindows(tty)
X     char *tty;
X/* Do the stuff to open a window- do a TIOCSTART iocuddle to let the
X   commands sent by queueopen() take effect, and tell ify when it's done. */
X{
X    FILE *oldtermout, *ttyfp;
X    int ttyfd;
X    
X    if ((ttyfp = fopen(FULLTTYNAME(tty), "r+")) == NULL)
X      closedown(THEERROR("open tty: "));
X    ttyfd = fileno(ttyfp);
X    
X    /* disconnect the menu - the menu isn't going to be valid
X       until this process completes */
X    m_nomenu();
X    m_flush();
X
X    /* re-enable output to that ptty */
X#ifdef BSD
X    if (iocuddle(ttyfd, TIOCSTART) == -1)
X      closedown(THEERROR("iocuddle TIOCSTART: "));
X#else /* SYSV */
X    if (iocuddle(ttyfd, TCXONC, 1) == -1)    
X      closedown(THEERROR("iocuddle TCXONC 1: "));
X#endif /* BSD */
X
X    /* queue escape codes to let us know when they're all
X       opened, if we can */
X    if (windowpid != 0) {
X	oldtermout = m_termout;
X	m_termout = ttyfp;
X	m_sendto(windowpid, "fini!");
X	m_flush();
X	m_termout = oldtermout;
X    }
X    else {
X	sleep(WAITTIME);	/* just wait for it to finish */
X	makemenu();		/* make a new menu */
X    }
X
X    fclose(ttyfp);
X}
X
X
X/* =============== What's on the screen here? =============== */
X
Xint
Xget_whatsat(x, y, tty, win, pid)
X     int x, y;
X     char *tty;
X     int *win, *pid;
X/* find the window under position x, y, and return the suffix of its tty
X   in tty and its pid in *pid.  If there is no window at (x, y), or
X   if the window there is one of our own, return 0.  Otherwise, return 1. */
X{
X    char buf[80];		/* space for the reply */
X    char fulltty[TTYPREFIXLEN + TTYSUFFIXLEN];
X
X    m_whatsat(x, y);		/* send the request */
X    m_flush();
X    skipgarbage(); m_gets(buf);	/* read the response */
X
X    if (buf[0] == '\n')		/* empty line?  Nothing there */
X      return 0;
X
X    /* old MGR gives you "/dev/ttyxx win pid", newer mgr gives you
X       "xx yy win pid", where xx and yy are tty suffixes.  Deal with
X       both. */
X    sscanf(buf, "%s", fulltty);
X    if (fulltty[0] == '/') {	/* full tty name? */
X	sscanf(buf, "/dev/tty%s %d %d", tty, win, pid);
X	return(windowpid == 0 || windowpid != *pid);
X    }
X    else {
X	sscanf(buf, "%s %s %d %d", fulltty, tty, win, pid);
X	if (windowpid == 0)
X	  return(strcmp(fulltty, tty) != 0);
X	else
X	  return(windowpid != *pid);
X    }
X}
X
X
X/* =============== Iteration over a list of windows =============== */
X
Xvoid
Xforeachwindow(win, count, tty, func, data)
X     struct window_data win[];
X     int count;
X     char *tty;
X     void (*func)();
X     char *data;
X/* find every window in win[0..count-1] attached to the given tty, and
X   apply func to a file pointer to the tty and the window's parameters.
X   if tty==NULL, apply func to all the windows.  tty should be just the
X   suffix of the pseudo-tty's name.
X
X   func is unsigned long (*func)(FILE *t, struct window_data *w,
X                                 char *data),
X   where t is the window's tty, w is a pointer to the window's parameters,
X   and data is the same value passed to foreachwindow(). */
X{
X    FILE *ttyfp = NULL;
X    char *lastttyopened = "";
X    int i;
X
X    if (tty && (ttyfp = fopen(FULLTTYNAME(tty), "r+")) == NULL)
X      closedown(THEERROR("open tty foreachwindow: "));
X    
X    for (i = 0; i < count; i++) {
X	
X	/* if the user didn't specify a particular tty and the next window
X	   is attached to the one different from the one we've already
X	   opened, open the new one. */
X	if (!tty && strcmp(win[i].tty, lastttyopened)!=0) {
X	    if (ttyfp)
X	      fclose(ttyfp);
X	    if ((ttyfp = fopen(FULLTTYNAME(win[i].tty), "r+")) == NULL)
X	      closedown(THEERROR("open tty foreachwindow II: "));
X	    lastttyopened = win[i].tty;
X	}
X
X	/* apply the function to the window and its stuff */
X	if (!tty || strcmp(tty, win[i].tty)==0)
X	  (*func)(ttyfp, &win[i], data);
X    }
X
X    if (ttyfp)
X      fclose(ttyfp);
X}
X
X
X/* ==================== Put the window someplace nice ==================== */
X
X
Xint
Xfind_spot(wide, high, coords, count, newx, newy)
X     int wide,high;		/* minimum spot size */
X     struct window_data coords[]; /* current screen layout */
X     int count;			/* # of entries in coords[] */
X     int *newx, *newy;		/* put resulting co-ords here */
X/* scan the screen (as described in coords[]) for a free spot of the given
X   size (wide x high).  Place the resulting co-ordinates in *newx and
X   *newy.  Ignore entries in coords whose widths are negative.
X   
X   =============== This Code Was Stolen From Steve Uhler. ===============
X                                       (credit where credit is due dept.)*/
X{
X    register int c, intersection, x, y, nexty;
X    static int in_win();
X    
X    dprintf(stderr,"found %d windows\n", count);
X    
X    wide += XSLOP;
X    high += YSLOP;
X
X    /* Find the best spot.  We want to avoid too exhaustive a search.
X       We march through the screen, trying to fit the moving window into
X       spaces.  Any time we collide with a window, we skip to the right edge
X       of that window and note if it's top edge is the lowest one we've seen
X       which is still above where we are.  This allows us to skip over the
X       larger areas of occupied screen quickly. */
X    for( y = disp_h-high;  y >= 0;  y = nexty - 1 ) {
X	nexty = 0;
X	for( x = disp_w-wide;  x >= 0;  x -= 1 ) {
X	    intersection = 0;
X	    dprintf(stderr,"  - Checking %d,%d\n",x,y);
X	    for( c = 0;  c < count;  c++ ) {
X		if( coords[c].w < 0 )
X		  continue;
X		if( in_win( coords+c, x, y, x + wide, y + high ) ) {
X		    intersection = 1;
X		    nexty = Max(nexty, coords[c].y - high);   
X		    x = coords[c].x - wide;
X		    break;
X		}
X	    }
X	    if( !intersection ) {
X		dprintf(stderr,"going to %d, %d\n", x, y);
X		*newx = x+XSLOP/2; *newy = y+YSLOP/2;
X		return( 1 );
X	    }
X	}
X    }
X    dprintf(stderr,"no openings\n");
X    return( 0 );
X}
X
X
X/* check for window-rectangle intersection */
X
Xstatic int
Xin_win(list,x0,y0,x1,y1)
X     register struct window_data *list;	/* window coordinates */
X     register int x0,y0,x1,y1;	/* rectangle coordinates */
X{
X    return((list->x + list->w < x0  ||  x1 < list->x ||
X	    list->y + list->h < y0  ||  y1 < list->y)
X	   ?  0  :  1);
X}
X
X/* ==================== get window id ==================== */
X
Xgetwid()
X{
X    char name[80], buf[80];
X
X    /* establish a unique notify name */
X    sprintf(name, "getwid %d", getpid());
X    m_push(P_EVENT);
X    m_setevent(NOTIFY, name);
X    m_getinfo(G_NOTIFY);
X    /* skipgarbage() would go here, but this gets called with no dupkey. */
X    for (;;) {
X	m_gets(buf);
X	if (buf[0] == '\n')
X	  break;
X	buf[strlen(buf)-1] = '\0'; /* wipe out newline */
X	if (strcmp(buf+strlen(buf)-strlen(name), name) == 0) {
X	    int wid = atoi(buf);
X	    do
X	      m_gets(buf);
X	    while (buf[0] != '\n');
X	    m_pop();
X	    return(wid);
X	}
X    }
X
X    m_pop();
X    return(0);
X}
X
X
X/* ==================== build the menu ==================== */
X
X#define MAXITEMS (500)
X#define MAXTEXTLEN (80)
X#define MAXEVENTLEN (30)
X
Xmakemenu()
X/* Look at the list of NOTIFY-ing windows and build a menu listing
X   the closed windows, where the event string for each item provides
X   the name of the ptty running the window. */
X{
X    static char toptext[] = "don't quit,quit,remake menu,";
X    static char topevents[] = ",\005q\\r,\005n\\r,";
X
X    char data[80]; 		/* hold a line of data */
X    char text[MAXITEMS*MAXTEXTLEN]; /* text of menu items */
X    char events[MAXITEMS*MAXEVENTLEN]; /* text of events */
X    static char all[MAXITEMS*(MAXTEXTLEN+MAXEVENTLEN)]; /* the whole menu */
X
X    char *textend, *eventend;	/* free space at end of text[] and event[] */
X    char *windowname;		/* name of the window within data[] */
X
X    static char line[] = "------------------------------";
X    char *partline;
X    int longesttext = 11;	/* length of the longest menu item */
X
X    DUPKEYOFF;			/* turn dupkey off, since m_getinfo(G_NOTIFY)
X				   won't work with dupkey on (MGR bug! Poor
X				   Steve!) */
X
X    textend = text;
X    eventend = events;
X    text[0] = events[0] = '\0';
X
X    /* Get the list of available windows, store their ttys in ttys[],
X       and use their names to build up the text of the menu */
X    m_push(P_EVENT);
X    m_nomenu();
X    m_clearmenu(1);
X    m_getinfo(G_NOTIFY);	/* ask for the data */
X    m_flush();
X    for (;;) {
X	if (fgets(data, sizeof(data), m_termin) == NULL)
X	  break;
X	if (data[0] == '\n')
X	  break;
X	
X	data[strlen(data)-1] = '\0';
X	
X	/* Is this a valid G_NOTIFY info string?  Check delimiters.*/
X	{
X	    char *p;
X	    if ((p = strchr(data, '.')) == NULL ||
X		(p = strchr(p+1, ' ')) == NULL ||
X		(p = strchr(p+1, ' ')) == NULL)
X	      continue;
X	    
X	    windowname = p+1;
X	    if ((p = strchr(p+1, ':')) == NULL ||
X		(p = strchr(p+1, ':')) == NULL)
X	      continue;
X	}
X	
X	/* do we want to include this menu item in the list?  Does its
X	   name start with closednotify[]? */
X	if (strncmp(windowname, closednotify, CLNLEN) == 0) {
X	    
X	    /* zap all occurrences of the menu separator */
X	    {
X		char *p;
X		
X		for (p = windowname; p = strchr(p, ',');)
X		  *p = ' ';
X	    }
X	    
X	    strcat(eventend, "\005m"); eventend += strlen(eventend);
X	    sscanf(windowname, "CLOSED:%[^:]:%[^:]", eventend, textend);
X	    if (strlen(textend) > longesttext)
X	      longesttext = strlen(textend);
X	    strcat(textend, ",");
X	    strcat(eventend, "\\r,");
X	    
X	    textend += strlen(textend);
X	    eventend += strlen(eventend);
X	}
X    }
X    
X    /* build up a dividing line with the appropriate length */
X    if (longesttext > sizeof(line)-1)
X      longesttext = sizeof(line)-1;
X    partline = line+(sizeof(line)-1-longesttext);
X
X    /* now put all the pieces together */
X    sprintf(all, ",%s%s,%s%s,%s",
X	    toptext,partline,text,topevents, events);
X
X    m_pop();
X    m_loadmenu(1, all);
X    m_selectmenu(1);
X    DUPKEYON;
X    m_flush();
X}
X
X
X/* ==================== Does this MGR have a dupkey? ==================== */
X
Xint
Xhasdupkey()
X{
X    int c, gotdupkey;
X
X    m_push(P_FLAGS);
X    m_dupkey('\005');		/* turn on dupkey mode (maybe) */
X    m_ttyset();
X    m_getinfo(G_WINSIZE);	/* ask for something innocuous */
X    
X    /* examine what we got back and see if we got a dupkey with it */
X    gotdupkey = 0;
X    while ((c = getchar()) != '\n')
X      if (c == '\005')
X	gotdupkey = 1;
X    m_ttyreset();
X    m_pop();
X
X    return gotdupkey;
X}
X
X
Xprint(s)
X     char *s;
X{
X    write(2, s, strlen(s));
X}
SHAR_EOF
$TOUCH -am 0328161791 ify.c &&
chmod 0644 ify.c ||
echo "restore of ify.c failed"
set `wc -c ify.c`;Wc_c=$1
if test "$Wc_c" != "30040"; then
	echo original size 30040, current size $Wc_c
fi
fi
# ============= ify.icon ==============
if test X"$1" != X"-c" -a -f 'ify.icon'; then
	echo "File already exists: skipping 'ify.icon'"
else
echo "x - extracting ify.icon (Binary)"
sed 's/^X//' << 'SHAR_EOF' | uudecode &&
Xbegin 600 ify.icon
XM>GHA,"!7```````'__X`````````!__^``!W4`````8`!@``)%````N^``8`
XM`"8@```(!@`&```D(```"`8`!@``="`"(B(G__X````````(!__^``````(`
XM"```D````/_]_____`````.``@````20```%@```"``$$```"X`"``@`!)``
XM``6````(``0````+@`(````$D```!8````@`!!````N``@`-W=]P```%@```
XM```$````"X`"````!(````6```````?__P`+@`(````$``$`!8``````!(`!
XM``N``@````0``0`%@``````$@`$`"X`"````!``!``6```````2``0`+@`(`
XM```$``$`!8``````!(`!``N``B(B(B(``0`%@``````$``$`"X``````!``!
XM``6```````0``0`+@``````$``$`!8``````!``!``N```````0``0`%@```
XM```$``$`"X``````!``!``6```````0``0`+@``````$``$`!?_______``!
XM``O_______@``0`%555=5550``$`"JJJN``````!``5555@``````0`````X
XM``````$`````&``````!`````#@``````0`````8``````$`````.``````!
XM`````!@``````0`````X``````$`````&``````!`````#@``````0`````?
X0______\`````/______^````
X`
Xend
SHAR_EOF
$TOUCH -am 0328153691 ify.icon &&
chmod 0644 ify.icon ||
echo "restore of ify.icon failed"
set `wc -c ify.icon`;Wc_c=$1
if test "$Wc_c" != "556"; then
	echo original size 556, current size $Wc_c
fi
fi
echo "End of part 1, continue with part 2"
exit 0

-- 
David H. Brierley
Home: dave at galaxia.newport.ri.us; Work: dhb at quahog.ssd.ray.com
Send comp.sources.3b1 submissions to comp-sources-3b1 at galaxia.newport.ri.us
%% Can I be excused, my brain is full. **



More information about the Comp.sources.3b1 mailing list