dhb@uunet.UU.NET ( comp.sources.3b1) (04/07/91)
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@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@pahasapa.bellcore.com] Xbus. (908) 699-5514 <scj@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@galaxia.newport.ri.us; Work: dhb@quahog.ssd.ray.com Send comp.sources.3b1 submissions to comp-sources-3b1@galaxia.newport.ri.us %% Can I be excused, my brain is full. **