[comp.sources.misc] v05i033: 3b1tools - windows and icons management for the Unix-pc

benten@tigger.UUCP (Muhammad S. Benten) (11/07/88)

Posting-number: Volume 5, Issue 33
Submitted-by: "Muhammad S. Benten" <benten@tigger.UUCP>
Archive-name: 3b1tools

[Aside from some wishful thinking wrt. process stopping via ptrace (BSD,
anyone? ;-) it almost makes me wish I hadn't sold the 3B1....  ++bsa]

            This posting contains the sources for a tool for the
AT&T Unix-pc.  It is called "3b1tools". It will allow Unix-pc users  
to do less! than what Sun users do with suntools.   Thanks.


   ============================================================================ 
   || Muhammad S. Benten                                                      |
   || Elect. & Comp. Eng. Dept.                                               |
   || University of Colorado, Boulder                                         |
   ||                                                                         |
   || email   ---->      benten@boulder.Colorado.EDU                          |
   ||        or        ..{ncar|nbires}!boulder!benten                         |
   ============================================================================ 


----------------------------Cut here----------------------------------------
#! /bin/sh
#
# Wrapped by tigger!benten on Tue Nov  1 14:07:53 MST 1988
#
# This is a shell archive, meaning:
# 1. Remove everything above the #! /bin/sh line.
# 2. Save the resulting text in a file.
# 3. Execute the file with /bin/sh (not csh) to create the files:
#
# Contents:  3b1tools.c 3b1tools.doc 3b1tools.h Makefile README nkbd.c.patch
# picture.c tools.c
 
echo x - 3b1tools.c
sed 's/^@//' > "3b1tools.c" <<'@//E*O*F 3b1tools.c//'
/* 3b1tools.c - This file parses the command argument and performs
**              all "windy" related processing. It will then call
**              the icon handler.
**
** Copyright (C) 1988 by Muhammad S. Benten.
**                       benten@boulder.colorado.edu
**
**
** Permission to use, copy, modify, and distribute this software and its
** documentation for any purpose and without fee is hereby granted, provided
** that the above copyright notice appear in all copies and that both that
** copyright notice and this permission notice appear in supporting
** documentation.  This software is provided "as is" without express or
** implied warranty.
**
**
**    A major portion of this file is extracted from the program windy
**    which is available from "The STORE" with its sources.
**    It will preserve most of windy's arguments.
*/
#include "3b1tools.h"
#define        NA      0xffff

struct uwdata xuw = {
       NA, NA, NA, NA, NA};
struct utdata xut[WTXTNUM];
int bflag = 0;
int Kflag = 0;
char blot[81];
char *ttyname();
char * filenam;
extern struct termio argg;
extern char *optarg;
extern int optind;

main(ac,av)
int ac;
char **av;
{
       int nflag = 0;
       char avname[256];
       char *env,cavname[256];
       int i, c,rows,cols,pid;
       FILE * ifd;
       ioctl(Wn,TCGETA,&argg);
       cols = 0;
       rows = 0;
       maxw = 672;
       maxh = 288;
       invert = 0;
       iconopen = 0;
       transpose = 0;

       if ( ac == 1 ) { /* no argument, get commands */
          strcat(avname,".3b1tool");
          if ( (ifd = fopen( avname, "r" )) != NULL) {
                  startup(ifd,av);
                  exit(0);} else {
          strcpy(avname,getenv("HOME"));
          strcat(avname,"/.3b1tool");
          if ( (ifd = fopen( avname, "r" )) != NULL) {
                  startup(ifd,av);
                  exit(0);}
        else {
           printf("3b1tools: File .3b1tool doesn't exist\n3b1tools: Use 3b1tools -S for full screen shell\n");
           exit(1);
       }}}

       else {
       ifd = (FILE *) -1;
       while((c = getopt(ac, av, "robSRTp:c:l:u:1:2:n:f:h:w:x:y:K:X:Y:I:W:H:")) != EOF) {
               switch(c) {
               case 'b':{
                       bflag++;
                       break;}
               case 'h':{
                       xuw.uw_height = atoi(optarg);
                    break;}
               case 'w':{
                       xuw.uw_width = atoi(optarg);
                       break;}
               case 'x':{
                       xuw.uw_x = atoi(optarg);
                       break;}
               case 'y':{
                       xuw.uw_y = atoi(optarg);
                       break;}
               case 'f':{
                       xuw.uw_uflags = htoi(optarg);
                       xuw.uw_uflags &= ~NOSETUFLAGS;
                       break;}
               case 'p':
                       utset(WTXTPROMPT, optarg);{
                       break;}
               case 'c':{
                       utset(WTXTCMD, optarg);
                       break;}
               case 'l':{
                       utset(WTXTLABEL, optarg);
                       break;}
               case 'n':
               case 'u':{
                       nflag = 1;
                       utset(WTXTUSER, optarg);
                       break;}
               case '1':{
                       utset(WTXTSLK1, optarg);
                       break;}
               case '2':{
                       utset(WTXTSLK2, optarg);
                       break;}
               case '?':{
                       fprintf(stderr, "usage: 3b1tools [args] [command-args]\n");
                       exit(2);}
               case 'K':{
                       strncpy(blot, optarg, 80);
                       Kflag ++;
                       break;}

               case 'I': {  /*  image file name */
                         if ( optarg[0] == '-' ) {
                            ifd = stdin;}
                         else {
                         ifd = fopen( optarg, "r" );
                         if ( ifd == NULL )
	                 {
	                     fprintf( stderr, "Image %s: can't open.\n", optarg);
	                     exit( 1 ); }
                             filenam = optarg;}
                             break;}
                case 'W': { /* overwrite image height */
                          cols = atoi(optarg);
                          break;}
                case 'H': { /* overwrite image width */
                          rows = atoi(optarg);
                          break;}
                case 'X': { /* icon width */
                          maxw = atoi(optarg);
                          if (maxw > 672 )
                             maxw = 672;
                          break;}
                 case 'Y': { /* icon height */
                           maxh = atoi(optarg);
                           if (maxh > 288 )
                              maxh = 288;
                           break;}
                 case 'R': { /* reverse image */
                           invert++;
                           break;}
                 case 'o': { /* start with an open window */
                           iconopen++;
                           break;}
                 case 'r': { /* start with an open window */
                           normal++;
                           break;}
                  case 'S':{
                           xuw.uw_x = 0;
                           xuw.uw_y = 12;
                           xuw.uw_width = 720;
                           xuw.uw_height = 288;
                           xuw.uw_uflags = 0x1;
                           break;}
                 case 'T': { /* transpoe icon */
                           transpose++;
                           break;}}

       }}
       /*
        * if gave command args, put it in a new window
        * if gave window args, or no args at all, change window params
        */
       if(optind < ac) {
               if( bflag)
                  newwind();
               avname[0] = 0;
               for(i=optind; i<ac; i++) {
                       strcat(avname, av[i]);
                       strcat(avname, " ");
               }
               if( bflag)
                 if(!nflag)
                       utset(WTXTUSER, avname);
       }
       fixwind();
               
               if(bflag) {
                       pid = fork();
                       if(pid > 0)
                               exit(1);
                       else if(pid == 0) {
                               setpgrp();
                               ioctl(0, WIOCPGRP);
                       }
               }
               icon_exec(av,rows,cols,ifd);
       exit(0);
}
utset(n, s)
char *s;
{
       xut[n].ut_num = 1;
       strncpy(xut[n].ut_text, s, WTXTLEN);
}
newwind() {
       char name[10];
       struct termio t;
       int bad = 0, i, fd;

       if (!isatty(0)) return;
       if(strncmp("/dev/w", ttyname(0), 6)!=0 ) return;

       if (ioctl(0, TCGETA, &t) < 0) {
               perror("getting tty chars");
               bad = 1;
       }
       fd = open("/dev/window",2);
       if (fd < 0) {
               perror("opening window");
               return;
       }
       if(bflag) {
               ioctl(fd, WIOCSELECT);
               sprintf(name, "[w%d]\n", ioctl(fd, WIOCGCURR));
               write(0, name, strlen(name));
       }

       close(0);
       dup(fd);
       close(1);
       dup(fd);
       close(2);
       dup(fd);
       close(fd);
       /* Set in the previous edit characters to the new window */
       if (!bad && ioctl(0, TCSETAF, &t) < 0)
               perror("setting tty chars");
       for (i=0; environ[i]; ++i) {
               if (!strncmp(environ[i],"TERMCAP=",8)) {
                       environ[i] = "TERMCAP=/etc/termcap";
               }
               if (!strncmp(environ[i],"TERM=",5)) {
                       environ[i] = "TERM=s4";
               }
       }
}
fixwind() {
       struct uwdata uw;
       int i;

       if(Kflag) {
               xut[WTXTSLK1].ut_num = WTXTSLK1;
               xut[WTXTSLK2].ut_num = WTXTSLK2;
               keyfix(xut[WTXTSLK1].ut_text);
               keyfix(xut[WTXTSLK2].ut_text);
       }
       for(i=0; i<WTXTNUM; i++) {
               if(xut[i].ut_num) {
                       xut[i].ut_num = i;
                       ioctl(0, WIOCSETTEXT, &xut[i]);
               }
       }
       ioctl(0, WIOCGETD, &uw);
       if(xuw.uw_x != NA) {uw.uw_x = xuw.uw_x;new_wind++;}
       if(xuw.uw_y != NA) {uw.uw_y = xuw.uw_y;new_wind++;}
       if(xuw.uw_width != NA) {uw.uw_width = xuw.uw_width;new_wind++;}
       if(xuw.uw_height != NA) {uw.uw_height = xuw.uw_height;new_wind++;}
       if(xuw.uw_uflags != NA) {uw.uw_uflags = xuw.uw_uflags;new_wind++;}
       ioctl(0, WIOCSETD, &uw);
}
keyfix(s)
char *s;
{
       int c, i;

       for(i=0; i<80; i++) {
               c = s[i] & 0177;
               if(c == 0) c = ' ';
               switch(blot[i]) {
               case ' ':
               case 0:
                       c = ' ';
                       break;
               case 'r':
               case 'R':
                       c |= 0200;
                       break;
               }
               s[i] = c;
       }
}
char *utname[] = {
       "Prompt line",
       "Command line",
       "Label",
       "User",
       "SLK1",
       "SLK2",
};
report(s)
char *s;
{
       struct uwdata uw;
       struct utdata ut;
       int i;

       printf("%s:  ", s);
       ioctl(0, WIOCGETD, &uw);
       uwshow(&uw, (char *)0);

       for(i=0; i<WTXTNUM; i++) {
               ut.ut_num = i;
               ioctl(0, WIOCGETTEXT, &ut);
               if(ut.ut_text[0]) {
                       printf("%s=<%.81s>\n", utname[i], ut.ut_text);
               }
       }
}
uwshow(p, s)
struct uwdata *p;
char *s;
{
       printf("(x,y)=(%d,%d)  ", p->uw_x, p->uw_y);
       printf("(width,height)=(%d,%d)  ", p->uw_width, p->uw_height);
       printf("flags=%x\n  ", p->uw_uflags);
       printf("(hs,vs)=(%d, %d)[RO]  ", p->uw_hs, p->uw_vs);
       printf("baseline=%d[RO]  ", p->uw_baseline);
       printf("(cx,cy)=(%d, %d)[RO]\n", p->uw_cx, p->uw_cy);
}
htoi(s)
char *s;
{
       int x = NA;

       sscanf(s, "%x", &x);
       return x;
}


startup(ifi,argv)
int ifi;
char *argv;
{
   char cavname[256],avname[256],*sy;

   while ( fgets(avname,256,ifi) != 0 ) {
      cavname[0] =0;
      strcat(cavname,avname);
      sy = (char *) strtok(avname," ");
      if ( sy[0] != 0 )
      if ( strncmp(sy,"3b1tools",5)  !=0 ) {
      avname[0] =0;
      strcat(avname,cavname);
      strcpy(cavname , "3b1tools -b "); 
      strcat(cavname,avname);
      system(cavname);} else{
      printf("3b1tools: error in .3b1tool file\n");
      printf("3b1tools: in %s\n",avname);
      printf("3b1tools: only arguments to 3b1tools are specified\n");}}
   close(ifi);
}
@//E*O*F 3b1tools.c//
chmod u=rw,g=r,o=r 3b1tools.c
 
echo x - 3b1tools.doc
sed 's/^@//' > "3b1tools.doc" <<'@//E*O*F 3b1tools.doc//'




3b1tools                     1                         draft


Name:   3b1tools -  A Unix-pc windowing environment and image
                     display tool.
                     Copyright (c) 1988 by Muhammad S. Benten.

Author: Muhammad S. Benten
        University Of Colorado
        Electrical & Computer Engineering
        Boulder, Co 80309

Usage:  3b1tools [-b] [-S] [-o] [-I <icon>]  [-R] [-T] [-X nnn] [-Y nnn]
                [-H nnn]  [-W nnn] [-x nnn] [-y nnn] [-h nnn] [-w nnn]
                [-n <string>]  [-1 <string>] [-2 <string>] [-p <string>]
                [-c <string>]  [-f <hex>]  [-l <string>]  [-K <string>]
                [ <command> [ <arguments>]]

Description:
         3b1tools is a general purpose windowing program designed
         to utilize the capabilities of the Unix-pc. It replaces the
         functionality of the program "windy", and can also be used as
         a general purpose image and icon display tool. The borders of 
         a displayed icon, can be toggled on/off by the middle mouse button,
         B2. It can also be toggled by the function keys F2 or F7. You
         can open an icon by using the left mouse button B1, or using
         the functions keys F1 or F6. To exit and destroy an icon, you
         can use the right mouse button B3, or the function keys, F3 or F8.
         A confirmation will be requested when you destry an icon.
         Icons displayed using 3b1tools can be scrolled up, down,
         left and right using the scroll indicators on the icon borders.
         The size of the icon can also be controlled by the user through
         the -X and -Y options .  A closed icon is either idle
         or stopped.  A stopped icon can be resumed by the function key
         F1 in which case the screen would be restored and execution of
         the stopped command continues.  Opening an idle icon would
         restore the screen to its last state before the icon was
         either created or closed and the execution of the command
         argument is attempted.  This execution can be stopped at any
         point by the stop key ( CTRL-Z ). In this case the execution
         of the command would stop and the icon will close in a stopped
         state.
         

         There are five modes of operation in 3b1tools which can be specified 
         by the options used to invoke 3b1tools.  These modes are:


     mode-1:  no command argument and no -b option

         In this mode, 3b1tools will close the invoking window saving
         its contents and display an icon as specified by the  -I
         option. It will display a default icon if no icon is specfied.
         Note that the -S option must be specified if no argument is
         given to 3b1tools.
         Example:

                 3b1tools  -I girls


     mode-2:  no -b option but a command and its arguments are supplied

         In this mode, 3b1tools will close the invoking window saving
         its contents and display an icon as specified by the  -I option.
         It will display a default icon if no icon is specfied. Upon
         exiting the executing command, the window will be closed and
         the icon is displayed again. You can also start with an open
         window executing the command argument by specifying the -o










3b1tools                     2                         draft


         option which will be iconified when the command terminates.
         Example:

                 3b1tools  -I office  ua


     mode-3:  no command argument and a -b option

         This is similar to mode-1, except that the original window
         is left intact and the icon is displayed in a new window.
         Example:

                 3b1tools -b -I girls


     mode-4:  with a command argument and a -b option

         This is similar to mode-2, except that the original window
         is left intact and the icon and its execution window will
         occupy a new window.
         Example:

                 3b1tools -b -I moon vi


     mode-5: no arguments at all.

         In this mode, 3b1tools will search for the file ./.3b1tool.
         If this file doesn't exist it searches for the file $HOME/3b1tool.
         If this file is not found 3b1tools will terminate with an error
         message.  In this mode, 3b1tools expects the lines of either
         of these files to conain arguments for 3b1tools that will
         be executed with the -b option.
         Example:

           command:  3b1tools

           The file .3b1tool contain:

                     -I horse ls -l
                     -I dog   ua

options:

   -b
         dettach the new icon-window from the parent process.
         3b1tools will create a new window.

   -S
         This flag is usefull only if it is the only argument
         to 3b1tools. It will  expand the current window into full screen
         without executing commands from ~/.3b1tool or .3b1tool.











3b1tools                     3                         draft


   -o
         This option will instruct 3b1tools to start with an opened
         window. 3b1tools will default to a closed window (iconified).

   -I  <icon>
         Use the file <icon> as the image file for the icon when
         the window is closed.a If <icon> is in a cbm (compact
         bitmap) format, height and width are taken from the file,
         if it isn't, they must be specified by the -H -W option.

   -R
         Reverse the bits in the displayed icon.

   -T
         Transpose the image of the icon. (not implemented).

   -X  nnn
         Let the displayed width of the icon be nnn.

   -Y  nnn
         Let the displayed height of the icon window be nnn.

   -W  nnn
         Override the picture pixcell width to be nnn.

   -H  nnn
         Override the picture pixcell height to be nnn.

   -w  nnn
         Let the displayed width of the execution window be nnn.

   -h  nnn
         Let the displayed height of the execution window window be nnn.

   -x  nnn
         Position the icon and its execution window at x=nnn

   -y  nnn
         Position the icon and its execution window at y=nnn

   -n  <string>
         Use <string> as the name of the window as displayed
         by the window manager.

   -l  <string>
         Use <string> as the window label.

   -1  <string>
         Use <string> as the string that will appear in the first
         line of the function keys lables.

   -2  <string>
         Use <string> as the string that will appear in the second










3b1tools                     4                         draft


         line of the function keys lables.

   -K  <string>
         Use <string> as the pattern for the function keys lables.
         An "r" in <string> means reverse vedio at that position.

   -c  <string>
         Display <string> in the command line.

   -p  <string>
         Display <string> in the prompt line.

   -f  <hex>
         Use <hex> as the flag that control the shape of the
         execution window.


   command [<arguments>]
         Any unix command and its arguments that will be executed
         when the icon is opened.
@//E*O*F 3b1tools.doc//
chmod u=rw,g=r,o=r 3b1tools.doc
 
echo x - 3b1tools.h
sed 's/^@//' > "3b1tools.h" <<'@//E*O*F 3b1tools.h//'
#include <termio.h>
#include <sys/window.h>
#include <stdio.h>

extern int maxw,maxh;
extern int invert;
extern int transpose;
extern int iconopen;
extern int normal;
extern int new_wind;
extern int Wn;
extern char **environ;
@//E*O*F 3b1tools.h//
chmod u=rw,g=r,o=r 3b1tools.h
 
echo x - Makefile
sed 's/^@//' > "Makefile" <<'@//E*O*F Makefile//'

MAKEINC=/usr/include
include $(MAKEINC)/Makepre.h


OBJ=tools.o picture.o 3b1tools.o 

all: $(OBJ)
	$(LD) $(LDFLAGS) $(SHAREDLIB) $(OBJ) $(LIBM) -o 3b1tools  


include $(MAKEINC)/Makepost.h



@//E*O*F Makefile//
chmod u=rw,g=rw,o=rw Makefile
 
echo x - README
sed 's/^@//' > "README" <<'@//E*O*F README//'


/* 3b1tools
**
**
**
** Copyright (C) 1988 by Muhammad S. Benten.
**                       benten@boulder.colorado.edu
**
**
** Permission to use, copy, modify, and distribute this software and its
** documentation for any purpose and without fee is hereby granted, provided
** that the above copyright notice appear in all copies and that both that
** copyright notice and this permission notice appear in supporting
** documentation.  This software is provided "as is" without express or
** implied warranty.
**
**
** 
**
*/

This program was originally written to display AT&T demo graphics on 
the Unix-pc.  It was later on modified to display Compact BitMap (CBM)
files, which opened the machine to a huge number of icon editors and
raytracers.  The program close.c triggered the idea of closing windows
to a graphical icon.  This idea was then modified to start with this
program that can be opened to an executing window. It used to be invoked
with "windy" for the purpose of detaching it from the invoking shell.
With the availability of windy's sources I couldn't resist incorporating
the whole shpang as a single tool that I called "pctools". Due to
a name conflict, this was then renamed "3b1tools".  The posting of
the executable of this program provided me with great suggestions
about the user interface and the choice of interaction keys.  With
some head knocking I decided to search for a way to suspend windows.
I then wrote my own primitive keyboard device driver, which I then
realized that it will interfere with both CAPSCTRL loadable
device driver and the "keyfix" programs.  I then though of using
Ditto's kbd driver with minimal changes to support the interception
of the suspend key and passing it to 3b1tools.

The program as it stands now works fine and does most of what
Sun's  suntools (c)  does.  However, some minor problems may
result from the way processes are suspended. This program suspends
processes executing in 3b1tools windows in a trace mode (ptrace(2)).
These processes when resumed will report their status to their
parents through the wait(2) call.  Thus, parent processes that
call wait(2) and only check for signals wakeup otherwise they
assume the child is dead will be executing with their children
when the child is resumed.  In this situation both the parent
and its child will be competing for the keybord input.  If the
child wins this should present no problem, however, if the
parent wins you may want to do something about.


Enjoy using this tool and I'll try to respond to questions and
bug reports. I also would like to hear about any modifications
or enhancement to 3b1tools.  It was my baby, but it has grown
enough to fight its way by itself.

You will need -=> Ford <=- CAPCTRL sources to be able to use the
suspension feature of 3b1tools.  The patches to the file nkbd.c
are included in the file nkbd.c.patch.

** Copyright (C) 1988 by Muhammad S. Benten.
**                       benten@boulder.colorado.edu
**
**
** Permission to use, copy, modify, and distribute this software and its
** documentation for any purpose and without fee is hereby granted, provided
** that the above copyright notice appear in all copies and that both that
** copyright notice and this permission notice appear in supporting
** documentation.  This software is provided "as is" without express or
** implied warranty.
@//E*O*F README//
chmod u=rw,g=r,o=r README
 
echo x - nkbd.c.patch
sed 's/^@//' > "nkbd.c.patch" <<'@//E*O*F nkbd.c.patch//'
78a79
> 
516,524d516
< 
<    /* changes required for 3b1tools */ 
<     if (  tp->t_cc[7] == 253 ) 
<        if  (  ch == 26 ) {
<           tp->t_cc[7] = 254;
<           return;
<     }
<    /* end changes required for 3b1tools */ 
< 
@//E*O*F nkbd.c.patch//
chmod u=rw,g=r,o=r nkbd.c.patch
 
echo x - picture.c
sed 's/^@//' > "picture.c" <<'@//E*O*F picture.c//'
/* picture.c - reads a compact bitmap and converts it into the Unix-pc
**             format.
**
** Copyright (C) 1988 by Muhammad S. Benten.
**                       benten@boulder.colorado.edu
**
**
** Permission to use, copy, modify, and distribute this software and its
** documentation for any purpose and without fee is hereby granted, provided
** that the above copyright notice appear in all copies and that both that
** copyright notice and this permission notice appear in supporting
** documentation.  This software is provided "as is" without express or
** implied warranty.
*/

#include <stdio.h>

/* default icon */

short deflt[]={
-1, -1, 1, -32768, -63, -30721, 1729, -27136, 193, -27136, 193,
-27136, 193, -27136, 193, -27136, 193, -27136, 193, -27136, 193,
-27136, 193, -29184, -159, -29185, -127, -30721, 16385, -32760,
32705, -24592, -31, -24577, -31, -28673, -31, -28673, 1, -32768, 1,
-32768, 1, -32768, 1, -32768, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1
};

extern char * filenam;

extern int transpose;

icon_exec(comm,rows,cols,ifd)
char **comm;
FILE *ifd;
int rows, cols;
    {
    char engl[256];
    char *bits;
    char tst,cbm;
    int i,index1, row, col,byte1,cols1,rows1;

    /*
      Was there an icon file specified?
    */

    if (ifd != ((FILE *) -1) ) {

    /*
      Oh, yeh!  Is it a Compact BitMap?
    */


    if ( (tst = getc( ifd ) ) == 42 ){
      if ( getc( ifd ) == 23 )
	{
          cbm = 1;
          cols1 = getc( ifd ) << 8;
          cols1 += getc( ifd );
          rows1 = getc( ifd ) << 8;
          rows1 += getc( ifd );
          if (cols == 0)
             cols = cols1;
          if (rows == 0)
             rows = rows1;
          cols = cols /8;
        }}  
        else

    /*
      Or is it Unix-pc  raw BitMap?
    */

        {
          cbm = 0;
          if ( ( rows == 0) || (cols == 0)){
             printf("3b1tools: You must specify width and height. This is a raw icon!");
             exit(1);}
          cols = cols/8;
        }
        rows = (rows/8)*8;

        bits = (char *) malloc(cols*rows) ;

        for (col = 0; col <= cols ; col++)
          for(row = 0; row < rows ; row += 2)

	    /* handle CBM format ===> Unix-pc */

            if  (cbm == 1)  {
	    byte1 = 0;
	    tst = getc( ifd );

	    /* flip the high byte */

	    if (tst & 0x1)
	       byte1 |=  0x80;
	    if (tst & 0x2)
	       byte1 |=  0x40;
	    if (tst & 0x4)
	       byte1 |=  0x20;
	    if (tst & 0x8)
	       byte1 |=  0x10;
	    if (tst & 0x10)
	       byte1 |=  0x8;
	    if (tst & 0x20)
	       byte1 |=  0x4;
	    if (tst & 0x40)
	       byte1 |=  0x2;
	    if (tst & 0x80)
	       byte1 |=  0x1;
	     bits[col*rows + (row+1)] =  byte1;
	    byte1 = 0;
	    tst = getc( ifd );

	    /* flip the the low byte */

	    if (tst & 0x1)
	    	byte1 |=  0x80;
	    if (tst & 0x2)
	       	byte1 |=  0x40;
	    if (tst & 0x4)
	       	byte1 |=  0x20;
	    if (tst & 0x8)
	       	byte1 |=  0x10;
	    if (tst & 0x10)
	       byte1 |=  0x8;
	    if (tst & 0x20)
	       byte1 |=  0x4;
	    if (tst & 0x40)
	       byte1 |=  0x2;
	    if (tst & 0x80)
	       byte1 |=  0x1;

	    bits[col*rows + row] =  byte1;}
        else 

	   /*  It is already in Unix-pc format */

            if ( col == 0 && row == 0) {
	       bits[1] =  tst;
	       bits[0] =  getc(ifd);
            } 
            else {
	       bits[col*rows + (row+1)] =  getc(ifd);
	       bits[col*rows + row] =  getc(ifd);
            }
       fclose(ifd);
        }
     else

      /*  use the built in (default) icon */

     {  
        cols = 4;
        rows = 32;
        bits = (char *) deflt;
        }

     /*
       transpose the bitmap
     */

     if ( transpose ) {

        /* Not implemented. 

	   A1:Why? 		
	   A2:very slooow.
	   A1:But only for big pictures, isn't it?
	   A2:Any way, who wants to transpose a small icon?
	   A1:I do. 
	   A2:Go ahead and do it then.

	transpose_bits ( bits , rows , cols);
        i = rows/8;
        rows = cols*8;
        cols = i;

	*/
     }
    
    /* invoke the window manager in tools.c */

        windowinit( comm,bits, cols , cols*8 ,rows);

    exit( 0 );
    }


@//E*O*F picture.c//
chmod u=rw,g=r,o=r picture.c
 
echo x - tools.c
sed 's/^@//' > "tools.c" <<'@//E*O*F tools.c//'
/* tools.c -   Displays, opens, closes and resumes an icon.
**
**
** Copyright (C) 1988 by Muhammad S. Benten.
**                       benten@boulder.colorado.edu
**
**
** Permission to use, copy, modify, and distribute this software and its
** documentation for any purpose and without fee is hereby granted, provided
** that the above copyright notice appear in all copies and that both that
** copyright notice and this permission notice appear in supporting
** documentation.  This software is provided "as is" without express or
** implied warranty.
**
**   
*/
# include 	<sys/ioctl.h>
# include 	<signal.h>
# include       <sys/mouse.h>
# include       <kcodes.h>
# include 	<message.h>
# include       "3b1tools.h"

#define up		196
#define down		197
#define left		190
#define right		204
#define xdelta		40
#define ydelta		20
#define XMAX1    	uwidth
#define YMAX1  	 	uheight

/* inside the window */

#define XMAX    uw.uw_width                     /* in pixels            */
#define YMAX    uw.uw_height                    /* in pixels            */
#define BPERBY  8                               /* bits per byte        */
#define XMAXB   ((XMAX+(BPERBY-1))/BPERBY)      /* in bytes             */
#define YMAXB   YMAX                            /* same as pixels       */
extern unsigned short patwhite[];

int Wn=1; 
int new_wind1;
int new_wind;
int maxw;
int maxh;
int transpose;
int invert;
int bord_flag;
int iconopen=0;
int normal=0;
unsigned isig=0;
short done=0;
int statch;

struct uwdata   uw;             /* current window data */
struct uwdata   Suw;            /* Saved window data */
struct uwdata   Puw;            /* Saved window data */
struct uwdata   suw;            /* Saved window data */
struct urdata urt;
unsigned short Bitmap[ 15660 ];             /* Saved screen */
unsigned short Bitmap1[ 15660 ];            /* Saved screen */
struct umdata mouse;
struct umdata mouse1;
struct termio argg;
struct termio argg1;
struct termio argg2;
struct termcb argcb;
int xstart,ystart,width,height,uwidth,uheight;
struct 	utdata sut[6];
struct 	utdata suti[6];
int  	(*intsig)(),(*quitsig)();
int 	closeit();
int 	sendit();
int 	frk=1;
int 	pid=-9;
int 	pppid,ppid;
extern 	char *optarg;
extern 	int optind;


/*
**   save the window state and close window
**   then go and wait for user response
*/

windowinit(comm,ico,wid,wid1,hit1)
char * ico, **comm;
int wid,wid1,hit1;
{
    int i;
    /* save original parameters */
    if ( ioctl( Wn, WIOCGETD, &uw) != 0 )
    {
        fprintf(stderr, "Can't close a non-window.\n");
        exit(1);
    }
    
    winit();
    keypad(0,1);


    /* save the bitmap */

    new_wind = wrastop(Wn, 0,0, Bitmap, XMAXB, 0,0, 0,0, XMAX, YMAX,
        SRCSRC, DSTSRC, 0 );
    new_wind1 = wrastop(Wn, 0,0, Bitmap1, XMAXB, 0,0, 0,0, XMAX, YMAX,
        SRCSRC, DSTSRC, 0 );

    /* save the window state */
    Suw = uw;
    Puw = uw;
    suw = uw;


    /*  save USER  texts */
    for ( i=0; i<6 ; i++) {
        sut[i].ut_num=i;
        suti[i].ut_num=i;
        ioctl(Wn,WIOCGETTEXT,&sut[i]);
        ioctl(Wn,WIOCGETTEXT,&suti[i]);
    }

    sprintf(suti[WTXTCMD].ut_text,"Press CTRL-Z to close window");

    /* Turn cursor off */
    fprintf(stderr, "\033[=1C" );

    /* set up function keys */
	wslk(Wn, 0, "   OPEN    TOGGLE   EXIT                             B1 TO    B2 TO    ",
		    "           BORDER                                    OPEN     TOGGLE   EXIT");

    /* set icon limits */

    xstart=0;
    ystart=0;
    width = wid1;
    height = hit1;
    if (wid1 > maxw )
       wid1 = maxw;
    if (hit1 > maxh )
       hit1 = maxh;
    uwidth = wid1;
    uheight = hit1;
    bord_flag = 1;

    /* close window */

    iconify(ico,wid,wid1,hit1);

    ioctl(Wn, WIOCGETMOUSE, &mouse);
    ioctl(Wn, WIOCGETMOUSE, &mouse1);
    mouse.um_flags = MSDOWN;
    ioctl(Wn, WIOCSETMOUSE, &mouse);
           
    manage_window(ico,wid,comm); 
}




/*
** Turn the window into an "icon".
*/

iconify(ico,wid,wid1,hit1)
char * ico;
int wid,wid1,hit1;
{
 int i;
 
    
    uw = suw;
    if (done != 1) {
    if ( bord_flag ) { 
       uw.uw_uflags |= NBORDER ;
    } 
    else {
          uw.uw_uflags &= ~(NBORDER);
          uw.uw_uflags |=  BORDHSCROLL ;
          uw.uw_uflags |=  BORDVSCROLL ;
    }
    uw.uw_height = hit1;
    uw.uw_width = wid1;
    ioctl( Wn, WIOCSETD, &uw );
    done=1;}

    urt.ur_srcbase = (unsigned short *) ico;
    urt.ur_srcwidth = wid;
    urt.ur_height = 1;
    urt.ur_width = wid1;
    urt.ur_srcx = xstart;
    if (invert)  {
       urt.ur_srcop = SRCXOR;
       urt.ur_pattern = patwhite;
    }

    for (i =0 ; i < hit1 ; i++) {
        urt.ur_srcy = ystart+i;
        urt.ur_dsty = i;
        ioctl( Wn, WIOCRASTOP, &urt ) ;}

}



/*
** Restore the window to the saved size and state.
*/

restore_window(restore)
int restore;
{
    int i;
    if (restore) {
      uw = Suw;
      ioctl( Wn, WIOCSETD, &uw );
        
      if (new_wind >= 0)
      wrastop(Wn, Bitmap, XMAXB, 0,0, 0,0, 0,0, XMAX, YMAX,
            SRCSRC, DSTSRC, 0 );

      /* position cursor and turn it on */

      fprintf(stderr, "\033[10;8H\033[=0C");
    }

    /*  restore USER  texts */
    for (i=0; i<6;i++) {
        sut[i].ut_num=i;
        ioctl(Wn,WIOCSETTEXT,&sut[i]);
    }

    if (restore) {
       if ( pid > 0 )
          kill(pid,9);
       kill(pppid,9);
       wexit( 0 );
    }
}



manage_window(ico, wid,com1)
unsigned short *ico;
int wid;
char **com1;
{
    int c,cc;
    int x,y,b,r,io,i;
    ppid = getpid();
    ioctl(Wn,TCGETA,&argg1);
    intsig =  signal ( SIGINT , sendit );
    quitsig=  signal ( SIGQUIT , sendit );
    (void) signal ( SIGTRAP , SIG_IGN );
    (void) signal ( SIGUSR2 , sendit );


    /* spawn a daemon process that would tell us
       if a CTRL-Z is caught
    */

    if ( (pppid =fork()) == 0 ) {
         (void) signal ( SIGUSR2 , closeit );

         /* It should have no control over the window */

         setpgrp();
loop:
         /* sleep until the window is opened */

         pause();

         /* take short naps until a suspend key is pressed */

         ioctl(0,TCGETA,&argg);
         while ( argg.c_cc[7] != 254 )  {
               sleep(1);
               ioctl(0,TCGETA,&argg);
         }
 
         /* tell the parent about it 
            and go back to sleep
         */
         argg.c_cc[7] = 0;
         ioctl(0,TCSETA,&argg);
         kill ( ppid , SIGUSR2 );
         goto loop;
    }

    /* the paraent should loop forever
    */

    for (;;)
    {
        if ( iconopen  ) {
          iconopen=0;
          c = F1;
        } else
           c = wgetc(Wn);

        ioctl( Wn, WIOCGETD, &suw );
        
        /* is it an exit command */

        if ( c == Exit || c == Cancl || c == s_Cancl || 
             c == F3 || c == F8 || c == EOF ) {
             if ( frk == 1 ) {
                confirm();
                iconify(ico,wid,XMAX1,YMAX1);
             }
        }
        else
        
        /* is it a scroll left command */

        if ( c == left ) {
            if ( xstart != 0 ) 
                 if ( (xstart - xdelta ) > 0 ) 
                      {xstart = xstart - xdelta; } else
                 xstart =0;
        iconify(ico,wid,XMAX1,YMAX1);
        } else

        
        /* is it a scroll right command */

        if ( c == right )  {
           if ((xstart + xdelta + XMAX1) < width ) {
               xstart = xstart + xdelta; }
           else
               xstart = width - XMAX1;
        iconify(ico,wid,XMAX1,YMAX1);
        } else
                
        
        /* is it a scroll down command */

        if ( c == down ){
            if ( ystart != 0 ) 
                 if ( (ystart - ydelta ) > 0 )
                      {ystart = ystart - ydelta; } else
                  ystart =0;
        iconify(ico,wid,XMAX1,YMAX1);
        } else
               
        
        /* is it a scroll up command */

        if ( c == up ){
           if ((ystart + ydelta + YMAX1) < height ) 
              { ystart = ystart + ydelta; }
           else
               ystart = height - YMAX1;
        iconify(ico,wid,XMAX1,YMAX1);
        } else


        if ( c == Mouse || c == F1 || c == F2 || c == F6 || c == F7) {
          b=0;
          if ( c == Mouse )
             wreadmouse(Wn,&x,&y,&b,&r);
        
          /* is it open or resume command */

          if ( b == 4 || c == F1 || c == F6) {
             uw = Puw;
             ioctl( Wn, WIOCSETD, &uw );
             ioctl(Wn, WIOCSETMOUSE, &mouse1);
             if ( (new_wind >= 0) || (new_wind1 >= 0))
                wrastop(Wn, Bitmap1, XMAXB, 0,0, 0,0, 0,0, XMAX
                               , YMAX, SRCSRC, DSTSRC, 0 );
             for ( i=0; i<6 ; i++) {
                 suti[i].ut_num=i;
                 ioctl(Wn,WIOCSETTEXT,&suti[i]);
             }
             fprintf(stderr, "\033[24;1H\033[=0C");
             /*fprintf(stderr, "\033[=0C");
             ioctl(0,LDSETT,argcb);*/
             if ( frk  == 1 ) {

                /* execute the user command */
                /* the suspend key sould be in effect */

                argg.c_cc[7] = 253;
                ioctl(0,TCSETA,&argg);
                frk = 0;
                if ( (pid=fork()) == 0 ) {

                   /* I should have no control over the window */
                   /* my parent should, Hmmmm  */

                   setpgrp();
                   
                   (void) signal ( SIGINT , intsig );
                   (void) signal ( SIGQUIT , quitsig );
                   (void) signal ( SIGUSR2 , SIG_IGN );
                   ptrace(0,0,0,0);
                   com1 +=optind;
                   execvp(com1[0],com1);
                   perror(com1[0]);
                   exit(2);
                 }
             } else {
                   argg2.c_cc[7] = 253;
                   ioctl(0,TCSETA,&argg2);
             }

             /* wakeup the daemon child */

             kill (pppid , SIGUSR2 );

             /* wakeup the executing child */

             if ( isig != 0 )
                ptrace(7, pid ,1,0);
wait_it:
             /* uuuuh, it is my turn to sleep */

             if ((wait(&statch)) == -1 ) {

             /* uuuuh, what is this noise? */

                  goto wait_it;
             } else {
             if  ( (statch & 0xff) != 0x7f ) {
                 isig = 0;
                 pid = -1;
                 frk = 1; } 
              else {
                 isig = statch >> 8;  
                 if ( isig != SIGUSR2 ) {

                    /* wakeup son, it is no time to sleep */

                    ptrace(7,pid,1,isig);
                    goto wait_it;
                  }
              }
              }

             /* Oh, I'm late..
                I should be working by now
             */

             ioctl(0,TCGETA,&argg2);
             ioctl( Wn, WIOCGETD, &Puw );
             for ( i=0; i<6 ; i++) {
                 suti[i].ut_num=i;
                 ioctl(Wn,WIOCGETTEXT,&suti[i]);
             }
             wcmd(Wn,0);
              
             /* set up function keys */
             if ( frk == 0 ) {
	     wslk(Wn, 0, "  RESUME   TOGGLE                                    B1 TO    B2 TO",
		    "           BORDER                                   RESUME    TOGGLE       "); } else
	     wslk(Wn, 0, "   OPEN    TOGGLE   EXIT                             B1 TO    B2 TO    B3 TO",
		    "           BORDER                                    OPEN     TOGGLE   EXIT");
             new_wind1 = wrastop(Wn, 0,0, Bitmap1, XMAXB, 0,0, 0,0, XMAX
                               , YMAX, SRCSRC, DSTSRC, 0 );
             ioctl(Wn,TCSETA,&argg1);
             keypad(0,1);
             ioctl(Wn, WIOCGETMOUSE, &mouse1);
             ioctl(Wn, WIOCSETMOUSE, &mouse);
             done = 0;
             bord_flag = 1;
             fprintf(stderr, "\033[=1C" );
             /*ioctl(0,LDGETT,argcb);*/

             iconify(ico,wid,XMAX1,YMAX1);
         
        } else
        
        /* is it toggle border command */

        if ( b == 2 || c == F2 || c == F7) {
            done = 0;
            if ( bord_flag )
               {bord_flag = 0;}
            else
               bord_flag = 1;
            iconify(ico,wid,XMAX1,YMAX1);
        } else

        if ( b == 1 )
        if ( frk == 1 ) {
             confirm();
             iconify(ico,wid,XMAX1,YMAX1);
       }
      }

           
    }
}


confirm()
{
int c,i,j,k,l;

   done=0;
   uw.uw_uflags = 0;
   uw.uw_height = 64;
   uw.uw_width = 140;
   ioctl( Wn, WIOCSETD, &uw );
   wlabel(Wn,"CONFIRM EXIT");
   wprompt(Wn,"Do you want to exit?             (Y/N  or  Enter/Cancel)");
   wcmd(Wn,"Touch Enter to continue          Cancel to STOP\n");
   c= wgetc(Wn);
   if( (c == Return) || (c == Enter) || 
       (c == 'y') || (c == 'Y') ) {
         wlabel(Wn,0);
         wprompt(Wn,0);
         wcmd(Wn,0);
         restore_window(1);
   }
   if (c == Mouse)
      wreadmouse(Wn,&i,&j,&k,&l);
      if ( k == 4 ) {
         wlabel(Wn,0);
         wprompt(Wn,0);
         wcmd(Wn,0);
         restore_window(1);
   }
   wlabel(Wn,0);
   wprompt(Wn,0);
   wcmd(Wn,0);
}


sendit(sig)
int sig;
{
    (void) signal ( sig , sendit );
    kill ( (0 - pid ) , sig );
}

closeit()
{
   (void) signal ( SIGUSR2 , closeit );
}
@//E*O*F tools.c//
chmod u=rw,g=r,o=r tools.c
 
exit 0