[comp.sys.amiga] Detabbing Print Utility

mark@unisec.UUCP (03/28/87)

Here's the print utility I mentioned earlier this week.  To get around my
concerns with posting a modified getfile (requester) package, I have
included an unmodified version, along with diffs that you can apply to
get the modifications I made (thanks for the suggestion, Kim!).  The diff
list is trivially small, so it shouldn't present a hardship.
-------------------snip here-----------------------------------------------
#! /bin/sh
# 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:
#	pr
# This archive created: Sat Mar 28 12:17:46 1987
export PATH; PATH=/bin:$PATH
if test ! -d 'pr'
then
	mkdir 'pr'
fi
cd 'pr'
if test ! -d 'getfile'
then
	mkdir 'getfile'
fi
cd 'getfile'
if test -f 'getfile.h'
then
	echo shar: will not over-write existing file "'getfile.h'"
else
cat << \SHAR_EOF > 'getfile.h'
/***************************************************
*  get_fname(window,screen,hail,ddef,ddir);
*
*   Displays a window/requester that
* gets a file name for device,directory,default file, extension
*
*   Calling args:
* window:   Window making the request
* screen:   Screen, if NULL assummed workbench
* hail:   Text prompt at top of requester
* ddef:   Input default file-name. Has NO DIRECTORY OR EXTENSION.
* ddir:   Directory of file, may be null
*
*  The basic call is:
*
*   getfile(Window,Screen,Hailing_string,file_name,directory_name);
*
* Where:
*   Window is a pointer to your window
*   Screen is a pointer to your screen ... or (long)NULL if workbench
*   Hailing_string is a prompt displayed in the requester
*   file_name is a text array which will be altered by getfile,
*   it returns the file name.
*   directory_name is a text array altered by getfile, it
*   is the directory.
*
*   The return value is either a pointer to your buffer, file_name,
*   or NULL if the user selected CANCEL.
*
*   You must reserve two text areas for file and directory like so:
*
* #define FNAME_SIZE 33
* TEXT   file_name[FNAME_SIZE + 1];
* TEXT   dir_name[FNAME_SIZE + 2]
**********************************************************************/

#ifndef GET_FNAME

#define GET_FNAME

#define FNAME_SIZE 33

extern char *get_fname();

#endif

SHAR_EOF
fi # end of overwriting check
if test -f 'getfile.c'
then
	echo shar: will not over-write existing file "'getfile.c'"
else
cat << \SHAR_EOF > 'getfile.c'
/************************************************************************
req.c
	This file contains a general-purpose <requester> that
will prompt the user for a filename input.
	The program actually uses a window instead of a 'Requester'
for greater flexibility. It will take control of your window's
IDCMP Port when called.

***	This material is copyright (c) 1986 by C. Heath of Microsmiths, Inc.
Permission is granted to use these files in any way with the following
exceptions:

1) The files shall not be posted on any telecommunications service, public
or private, except for BIX until January 15, 1987.

2) The files may only be distributed in archive format, with no modifications.
If you make any improvements on the file requester and would like to
generally distribute them, please contact "cheath" on BIX, or write to:
	Microsmiths Inc, PO Box 561, Cambridge, MA 02140

3) The requester may be used in any commercial product, but must be in
object code format.  You are free to make modifications for use in your
product.  Permission is granted to Lattice, Inc, and to Manx, Inc, to
include the source files in archive format.

	Thank you, and enjoy.
		...cheath

************************************************************************/

#include "standard.h"
#include "safeclose.h"

#define FAST register
#define NL NULL

extern char *dmore(), *dinit();

static struct FileLock      *pdir = NL;
static struct FileInfoBlock *dir_info;

static struct Window   *eW;		/* Parent Window. Uck	*/

static struct TextAttr MyFont = {"topaz.font",TOPAZ_EIGHTY,FS_NORMAL,FPF_ROMFONT };

/* FGAD requires a few unique gadget-ids, origined at FGAD	*/
/* In the unlikely event this conflicts with any of your gadgets, */
/* change this equate to allow 16 contiguous unique ID's	*/

#define FGAD	0x76c0L

#define FCHARS	32L	/* Number of chars allowed in file name	*/

#define DIR_SIZ	50L	/* Number of chars in a dir name...	*/
#define MAX_STR	DIR_SIZ+2L

#define DENTS	5L		/* Number of entries on screen   */
/* It's not as simple as changing 'DENTS'...      */

#define DSIZE	FCHARS+1L	/* Size of a directory entry   */

#define	DBUFSIZ	3000L	/* Number of bytes to allocate for all ents */

#define BCOL	1L	/* Background color	*/
#define FCOL	2L	/* Foreground color	*/

#define RHGHT	120L
#define RWDTH	320L

#define ZWDTH	270L

static char	ubuf[MAX_STR];		/* Undo buffer	*/

static struct dirent { struct dirent *next; BOOL isfile; char dE[DSIZE+2]; };
static struct dirent *FirstEntry;
static struct dirent *NextEntry;

static struct dirhead { struct dirent *next; };
static struct dirhead ListHead;

static long   curent,maxent;
static BOOL   more;

static struct Window	*wRq = NL;		/* Requester window   */
static struct RastPort	*wRp;

/* Requester "Hailing" prompt */
static struct IntuiText oTxt = {2,2,JAM1,10,11,NL, NL ,NL};

static struct IntuiText saydir = {0,1,JAM2,0,1,&MyFont,(UBYTE *)"(dir) ",NL};

static struct IntuiText rname[DENTS] = { /* File name list */
   {2,1,JAM2,48,1,NL,NL, NL},
   {2,1,JAM2,48,1,NL,NL, NL},
   {2,1,JAM2,48,1,NL,NL, NL},
   {2,1,JAM2,48,1,NL,NL, NL},
   {2,1,JAM2,48,1,NL,NL, NL} };

/* Display for file name ... */

static SHORT oXY2[] = {-2,-2, RWDTH-78,-2, RWDTH-78,9, -2,9, -2,-2};
static struct Border thebd = {0,0, 2,3,JAM1, 5,oXY2, NL};

static struct IntuiText otxt = {2,2,JAM1,-40,0,&MyFont,(UBYTE *)"file",NL};
static struct StringInfo osx = { NL ,ubuf, NL,DSIZE,NL,NL,NL,NL,NL,NL,NL,NL,NL};
static struct Gadget ogx = { NL, 60,RHGHT-35,RWDTH-80 ,10,     /* File name gadget */
   GADGHCOMP, RELVERIFY , STRGADGET,
   (APTR)&thebd,NL,&otxt,NL,(APTR)&osx, FGAD+11,NL };

static struct Gadget oga = { &ogx, 10,70, ZWDTH,10,   /* Gadgets For   */
   GADGHCOMP, RELVERIFY, BOOLGADGET,     /* Directory entries   */
   NL,NL, &rname[4] ,NL,NL, FGAD+10,NL };
static struct Gadget og9 = {&oga, 10,60, ZWDTH,10,
   GADGHCOMP, RELVERIFY, BOOLGADGET,
   NL,NL, &rname[3] ,NL,NL, FGAD+9,NL };
struct Gadget og8 = {&og9, 10,50, ZWDTH,10,
   GADGHCOMP, RELVERIFY, BOOLGADGET,
   NL,NL, &rname[2] ,NL,NL, FGAD+8,NL };
static struct Gadget og7 = {&og8, 10,40, ZWDTH,10,
   GADGHCOMP, RELVERIFY, BOOLGADGET,
   NL,NL, &rname[1] ,NL,NL, FGAD+7,NL };
static struct Gadget og6 = {&og7, 10,30, ZWDTH,10,
   GADGHCOMP, RELVERIFY, BOOLGADGET,
   NL,NL, &rname[0] ,NL,NL, FGAD+6,NL };


/* Gadjets for requester  */

static SHORT oXY3[] = {0,0, 50,0, 50,9, 0,9, 0,0};
static SHORT oXY4[] = {2,-2, 48,-2, 52,2, 52,7, 48,11, 2,11, -2,7, -2,2, 2,-2};
static struct Border obd2 = {0,0, 2,3,JAM1, 9,oXY4, NL};
static struct Border obd1 = {0,0, 3,2,JAM1, 5,oXY3, &obd2};  /* OTAY / CANCEL box */

static struct IntuiText ot1 = {0,0,JAM1,1,1,&MyFont,(UBYTE *)"  OK  ",NL};
static struct IntuiText ot2 = {0,0,JAM1,1,1,&MyFont,(UBYTE *)"Cancel",NL};

static struct IntuiText dtxt = {2,2,JAM1,-60,0,NL,(UBYTE *)"drawer",NL};
static struct StringInfo os5 = { NL ,ubuf, NL,DIR_SIZ,NL,NL,NL,NL,NL,NL,NL,NL,NL};
static struct Gadget og5 = { &og6, RWDTH/2-80,19,190,10,     /* Directory */
   GADGHCOMP, RELVERIFY, STRGADGET,
   NL,NL,&dtxt,NL,(APTR)&os5, FGAD+5,NL };

static struct Image   cc_img;
static struct PropInfo   cc_prop = {AUTOKNOB | FREEVERT, 0,0, 0,0x1000,0,0,0,0,0,0 };
static struct Gadget og3 = { &og5,RWDTH-39,20,20,60,      /* Scroll Bar   */
    GADGHCOMP,GADGIMMEDIATE | FOLLOWMOUSE, PROPGADGET,
    (APTR)&cc_img,NL,NL,NL,(APTR)&cc_prop,FGAD+3,NL };

static struct Gadget og2 = { &og3, RWDTH-70,RHGHT-20, 50,10,  /* CANCEL */
   GADGHCOMP,  RELVERIFY, BOOLGADGET,
   (APTR)&obd1,NL, &ot2,NL,NL, FGAD+2,NL };

static struct Gadget og1 = { &og2, 20,RHGHT-20, 50,10,      /* OTAY   */
   GADGHCOMP,		/* Flags	*/
   RELVERIFY,		/* Activation	*/
   BOOLGADGET,
   (APTR)&obd1,NL,	/* GadgetRender, SelectRender	*/
   &ot1,NL,NL,		/* IntuiText, MutualExclude,SpecialInfo   */
   FGAD+1,NL };		/* Gadget Id, UserData	*/

/* Open a requester "Window" */

static struct NewWindow NewFiles = {
   160, 30, RWDTH,RHGHT, BCOL,FCOL, NL, /* Fill in AFTER opening ... */
   SMART_REFRESH | ACTIVATE | RMBTRAP | WINDOWDRAG,
   &og1,NL,NL, NL,
   NL, RWDTH,RHGHT,RWDTH,RHGHT, WBENCHSCREEN };

IMPORT struct Library	*IntuitionBase;

/***************************************************
*  get_fname(window,screen,hail,ddef,ddir);
*
*   Displays a window/requester that
* gets a file name for device,directory,default file, extension
*
*   Calling args:
* window:   Window making the request
* screen:   Screen, if NULL assummed workbench
* hail:   Text prompt at top of requester
* ddef:   Input default file-name. Has NO DIRECTORY OR EXTENSION.
* ddir:   Directory of file, may be null

/* Set a file-requester with prompt 'hail'   */

char *get_fname(cW,screen,hail,ddef,ddir)
   struct Window *cW;		/* Calling Window   */
   struct Screen *screen;	/* screen .... if null assumed workbench */
   UBYTE	*hail;		/* Hailing prompt   */
   char		*ddef;		/* Proable file-name   */
   char		*ddir;		/* Directory in which to search   */
   {
   FAST struct IntuiMessage *imes;   /* Wait for message in HERE   */
   FAST struct Gadget	*igad;   /* Get Gadjet Mumbo Jumbo   */
   FAST long	i,class;
   FAST TEXT	*pnam;

   FAST char	*retval;
   FAST BOOL	dir_flag;
   FAST BOOL	keepon;

   if ( ! (eW = cW) )   return(NL);

   osx.Buffer = ddef;	/* Set default file name   */
   os5.Buffer = ddir;	/* Set default device name   */

   for ( i=0; i<DENTS; i++)
      {
      rname[i].IText = "";
      rname[i].NextText = NL;
      };

   NewFiles.Title = eW->Title;
   if ((dir_info = AllocMem((long)sizeof(struct FileInfoBlock),0L)) == NULL)
      return(NL);

   if (screen)		/* User supplied a screen */
      {
      NewFiles.Type = CUSTOMSCREEN;
      NewFiles.Screen = screen;
      }

   if ( ! (FirstEntry = (struct dirent *)AllocMem((long)DBUFSIZ,0L)) ||
        ! (wRq = (struct Window *)OpenWindow( &NewFiles )) )
      {
      if ( FirstEntry )   FreeMem(FirstEntry,(long)DBUFSIZ);
      /* notify("Can't Open Requester..."); */
      FreeMem(dir_info,(long)sizeof(struct FileInfoBlock));
      return(NL);
      }

   /* Set up directory, notify any errors...   */
   if ( pnam = (char *)dinit(ddir) )   notify(pnam);


   /* This optional line will activate a string gadget	*/
   if ( IntuitionBase->lib_Version > 32 )
	{
	ActivateGadget(&ogx,wRq,0L);
	}

   wRp = wRq->RPort;

   wRq->UserPort = eW->UserPort;
   ModifyIDCMP(wRq,(long)(MOUSEBUTTONS | GADGETDOWN | GADGETUP | MOUSEMOVE));

   SetAPen(wRp,1L);
   RectFill(wRp,4L,10L,(long)(RWDTH-5),(long)(RHGHT-4));

   oTxt.IText = hail;   /* Set calling arg   */
   oTxt.LeftEdge = (RWDTH - IntuiTextLength(&oTxt)) >> 1L;
   PrintIText(wRp,&oTxt,0L,0L);

   RefreshGadgets(&og1,wRq,(long)NL);
   for ( retval= NL, keepon=TRUE; keepon ; )
      {
      while ( ! (imes=(struct IntuiMessage *)GetMsg(wRq->UserPort)) )
      {
         if ( dir_flag )
            {
            i = (maxent-DENTS) * cc_prop.VertPot / MAXBODY;
            if ( i > (maxent-DENTS) )
            i = maxent-DENTS;
            if ( i <0 )   i = 0;
            curent = i;
            cxxx();
            dir_flag = FALSE;
            }
         if ( more )
            {
            if (pnam = (char *)dmore())   /* Continue to read the directory */
               notify(pnam);      /* Yucko error   */
            if ( maxent <= DENTS ) dir_flag = TRUE;
            }
         else    WaitPort(wRq->UserPort);
         }
      igad = (struct Gadget *)imes->IAddress;
      class = imes->Class;
      ReplyMsg(imes);

      switch (class)
         {
         case MOUSEMOVE:      dir_flag = TRUE;   break;
      
         case GADGETUP:
         case GADGETDOWN:
            switch ( i = igad->GadgetID)
            {
            case FGAD+6:
            case FGAD+7:
            case FGAD+8:
            case FGAD+9:
            case FGAD+10:       /* Replace file or directory name   */
               pnam = rname[i - (FGAD+6)].IText;
               if ( rname[igad->GadgetID - (FGAD+6)].NextText == NL )
                  {
                  RemoveGadget(wRq,&ogx);
                  for (i=0; i<DSIZE; i++)      ddef[i] = *pnam++;
                  AddGadget(wRq,&ogx,-1L);
                  RefreshGadgets(&ogx,wRq,(long)NL);
                  break;
                  }
                  else
                  {
                  RemoveGadget(wRq,&og5);
                  rfnam(ddir,pnam);
                  AddGadget(wRq,&og5,-1L);
                  RefreshGadgets(&og5,wRq,(long)NL);
                  }
            case FGAD+5:
               if ( pnam = (char *)dinit(ddir) )
                  notify(pnam);
            case FGAD+3:
               dir_flag = TRUE;
               break;

            case FGAD+11:      /* Name gadget, OTAY gadget   */
            case FGAD+1:
               retval = ddef;
            case FGAD+2:      /* Cancel gadget   */
               keepon = FALSE;
            }
         }
      }

      FreeMem(FirstEntry,(long)DBUFSIZ );
      FreeMem(dir_info,(long)sizeof(struct FileInfoBlock));
      free_pdir();

      CloseWindowSafely(wRq);
      return(retval);
   }

static free_pdir()
   {
   if ( pdir )
      {
      UnLock(pdir);
      pdir = NL;
      }
   }

/*****************************************************************
* dinit()
*   Initialize the fib for directory muck.  Null return
* is good, else return is a pointer to an error string      */

static char *dinit(subdir)
   char *subdir;
   {
   more = FALSE;
   curent = maxent = 0;

   NextEntry = FirstEntry;      /* Allocate from here   */
   ListHead.next = NL;          /* Clear the boogie     */

   free_pdir();   /* Unlock any old lock... */

   if (! (pdir=(struct FileLock *)Lock(subdir,(ULONG)ACCESS_READ)) )
      return("Wrong Diskette?");
   if ( ! Examine(pdir, dir_info) )   return("Wierd Disk Error");
   if ( dir_info->fib_DirEntryType < 0L )   return("Bizzare Alert!!");

   more = TRUE;
   return(dmore());
   }


static char *dmore()
   {
   FAST struct dirent   *p_D = NextEntry;
   FAST struct dirent   *ptr = (struct dirent *)&ListHead;
   FAST struct dirent   *plink;

   FAST   TEXT   *p_mung;

   FAST long    i;

   if ( ! more )   return(NL);

   if ( ExNext( pdir, dir_info ) )
      {


      if ( (ULONG)p_D >=
         ((ULONG)FirstEntry + (ULONG)DBUFSIZ - (ULONG)sizeof(struct dirent)) )
         {
         more = FALSE;
         return("Directory Truncated!");
         }


      /* Here you can add a file/directory filter   */
      /* filename text string is at &p_D->dE[0   */
      p_D->isfile = ( dir_info->fib_DirEntryType < 0L );

      p_mung = &p_D->dE[0];
      for ( i=0; i<FCHARS; i++)
         if ( ! (*p_mung++ = dir_info->fib_FileName[i]) )   break;

      i = (long)p_mung;
      NextEntry = (struct dirent *)( (i+5L) & ~3L );

      for ( i=maxent++; i>=0; i--)
         {
         if ( ! (plink = ptr->next)  )   break;
         if ( alpha_lower(p_D,plink) )   break;
         ptr = plink;
         }
      p_D->next = plink;
      ptr->next = p_D;

      return(NL);
      }
   else return ( IoErr() == ERROR_NO_MORE_ENTRIES) ?
       (char *)(more = (long)NL) : "Error Reading Directory!!!";
   }


/* dedicated alphabetizing function for dmore()   */

static alpha_lower(snew,sold)
   struct dirent *snew,*sold;
   {
   FAST struct dirent *pnew = snew;
   FAST TEXT *ps1,*ps2, c,d;

   if ( pnew->isfile == sold->isfile)
      {
      ps1 = &pnew->dE[0];
      ps2 = &sold->dE[0];
      while ( (c=*ps1++) )
         {
         if ( c > (d=*ps2++) )   return(FALSE);
         else if ( c < d )      break;
         }
      return(TRUE);
      }
   return(pnew->isfile);
   }   



/* Display directory stuff   */

static cxxx()
   {
   FAST long   i,new;
   FAST long   x,y;
   FAST struct dirent *ohboy = (struct dirent *)&ListHead;

   new = curent;
   for ( i=0; i<new; i++)   ohboy = ohboy->next;

   y = 20L;
   for (i=0; i<DENTS; i++)
      {
      y += (x=10);
      rname[i].NextText = NL;
      rname[i].IText = "";
      rname[i].LeftEdge = 0;
      if ( (new+i) < maxent )
         {
         ohboy = ohboy->next;
         rname[i].IText = &ohboy->dE[0];
         if ( ohboy->isfile )   PrintIText(wRp,&rname[i],10L,y);
         else
            {
            rname[i].LeftEdge = 48;
            PrintIText(wRp,&saydir,10L,y);
            PrintIText(wRp,&rname[i],10L,y);
            rname[i].NextText = &saydir;
            }
         x = wRp->cp_x;
         }
      if ( x < ZWDTH+10 )   RectFill(wRp,x,y,(long)(ZWDTH+10),(long)(y+8L));
      }
   }


/**************************************************
* rfnam()
*   Combines dir, plus name into dir   */

static rfnam(dir,fil_nam)
   char *dir,*fil_nam;
   {
   FAST char   *pdst = dir;
   FAST char   *psrc = fil_nam;
   FAST char   c = ':';

   while ( *pdst )
      c = *pdst++;
   if ( c != ':')   *pdst++ = '/';

   while ( *pdst++ = *psrc++ )
      ;
   }

static struct IntuiText b_txt = {0,1,JAM2, 5,20,NL,NL,    NL};
static struct IntuiText p_txt = {0,1,JAM2, 5,3,NL,"OK", NL};

/****************************************************************/
/* notify(txt)                     */
/*   Prompts for Yes/No response            */

static notify(txt)
   char *txt;
   {
   b_txt.IText = txt;
   AutoRequest(wRq,&b_txt,0L,&p_txt,0L,0L,
      (long)(IntuiTextLength(&b_txt)+50L),70L);
   }
SHAR_EOF
fi # end of overwriting check
if test -f 'makefile'
then
	echo shar: will not over-write existing file "'makefile'"
else
cat << \SHAR_EOF > 'makefile'
testing:	testing.o safeclose.o getfile.o ram:c.lib
	ln testing.o safeclose.o getfile.o ram:c.lib


ram:c.lib:
	copy df0:lib/c.lib ram:
SHAR_EOF
fi # end of overwriting check
if test -f 'readme'
then
	echo shar: will not over-write existing file "'readme'"
else
cat << \SHAR_EOF > 'readme'
ReadMe for GetFile.Arc			November 11, 1986

	This archive includes the files needed for the Heath/Aegis file name
requester.
	This material is copyright (c) 1986 by C. Heath of Microsmiths, Inc.
Permission is granted to use these files in any way with the following
exceptions:

1) The files shall not be posted on any telecommunications service, public
or private, except for BIX until January 15, 1987.

2) The files may only be distributed in archive format, with no modifications.
If you make any improvements on the file requester and would like to
generally distribute them, please contact "cheath" on BIX, or write to:
	Microsmiths Inc, PO Box 561, Cambridge, MA 02140

3) The requester may be used in any commercial product, but must be in
object code format.  Permission is granted to Lattice, Inc, and to
Manx, Inc, to include the source files in archive format.

4) These files are distributed "as is" and it is your sole responsibility
to determine their fitness for use.

	My apologies for the lousy program structure and the compile
time warnings - I didn't have time to clean things up.  Hope this doesn't
inconvenience too many folks.

	Thanks, and enjoy.
		...cheath
SHAR_EOF
fi # end of overwriting check
if test -f 'safeclose.c'
then
	echo shar: will not over-write existing file "'safeclose.c'"
else
cat << \SHAR_EOF > 'safeclose.c'
/* CloseWindowSafely()
*       This module should be used whenever you are sharing an IDCMP
* message port with more than one window.  Rather than calling CloseWindow(),
* you should use CloseWindowSafely().  This will keep Intuition from
* Guru Meditation, and thus is considered a good thing.  You should still
* use CloseWindow for the very last window you close.
*       The reason this is needed, is because Intuition will re-claim
* any outstanding messages for a window when the window is closed. But...
* it can't take them out of your message port. Thus, you will receive
* invalid messages and bad things will happen.  Very bad things.
*       This code is a slightly condensed version of the same routine
* written by Neil Katin of Amiga for the April '86 Commodore Developers
* Newsletter, Amiga Mail (tm).
*/

/*
#include <exec/types.h>
#include <exec/nodes.h>
#include <exec/lists.h>
#include <exec/ports.h>
#include <intuition/intuition.h>
#include <functions.h>
*/
#include "standard.h"

void CloseWindowSafely( p_wind )
   struct Window   *p_wind;
   {
   register struct IntuiMessage    *msg;
   register struct IntuiMessage    *succ;
   register struct Window          *win = p_wind;
   register struct MsgPort         *mp = (struct MsgPort *)win->UserPort;

   Forbid();

   msg = (struct IntuiMessage *)mp->mp_MsgList.lh_Head;

   while ( succ=(struct IntuiMessage *)msg->ExecMessage.mn_Node.ln_Succ )
      {
      if ( msg->IDCMPWindow == win )
         {
         Remove ( msg );
         ReplyMsg( msg );
         }
      msg = succ;
      }
   win->UserPort = NULL;
   ModifyIDCMP( win, 0L );
   Permit();
   CloseWindow( win );
   }


SHAR_EOF
fi # end of overwriting check
if test -f 'safeclose.h'
then
	echo shar: will not over-write existing file "'safeclose.h'"
else
cat << \SHAR_EOF > 'safeclose.h'
/* CloseWindowSafely()
*       This module should be used whenever you are sharing an IDCMP
* message port with more than one window.  Rather than calling CloseWindow(),
* you should use CloseWindowSafely().  This will keep Intuition from
* Guru Meditation, and thus is considered a good thing.  You should still
* use CloseWindow for the very last window you close.
*       The reason this is needed, is because Intuition will re-claim
* any outstanding messages for a window when the window is closed. But...
* it can't take them out of your message port. Thus, you will receive
* invalid messages and bad things will happen.  Very bad things.
*       This code is a slightly condensed version of the same routine
* written by Neil Katin of Amiga for the April '86 Commodore Developers
* Newsletter, Amiga Mail (tm).
*/

#ifndef SAFECLOSE

#define SAFECLOSE


/* CloseWindowSafely(window), window is pointer to struct Window */

extern void CloseWindowSafely();

#endif
SHAR_EOF
fi # end of overwriting check
if test -f 'standard.h'
then
	echo shar: will not over-write existing file "'standard.h'"
else
cat << \SHAR_EOF > 'standard.h'
#include <exec/types.h>
#include <exec/devices.h>
#include <intuition/intuition.h>

#include <libraries/dos.h>
#include <libraries/dosextens.h>
#include <functions.h>

SHAR_EOF
fi # end of overwriting check
if test -f 'testing.c'
then
	echo shar: will not over-write existing file "'testing.c'"
else
cat << \SHAR_EOF > 'testing.c'
#include <exec/types.h>
#include <intuition/intuition.h>

#include <libraries/dosextens.h>

#include <functions.h>

#define I_REV   31
#define G_REV   31

#define	EWDTH	640
#define	EHGHT	198

#define	NL	NULL


struct IntuitionBase *IntuitionBase;
struct GfxBase  { int b; } *GfxBase;

struct NewScreen TS = {
	0,0,640,200,2,
	1,2,
	HIRES,	WBENCHSCREEN,
	0L, 0L, 0L
	};

/* Used to open a Window   */
struct NewWindow EdWindow = {
    0,2,EWDTH,EHGHT-2,		/* LeftEdge,TopEdge,Width,Height */
    1,2,			/* DetailPen,BlockPen	*/
    MENUPICK | NEWSIZE | REFRESHWINDOW | ACTIVEWINDOW |
	MOUSEBUTTONS | RAWKEY | MOUSEMOVE,
    WINDOWDRAG | WINDOWSIZING | SIMPLE_REFRESH | ACTIVATE | WINDOWDEPTH,
    NL,NL,"Window",		/* FirstGadget, CheckMark, Title  */
    NL,				/* Screen ( Null)	*/
    NL,				/* BitMap		*/
    150,45,32767,32767,		/* MinW, MinH, MaxW, MaxH */
    CUSTOMSCREEN };		/* Type			*/


main()
{
struct Window	*eW;
struct Screen	*eS;

struct Process	*OurTask;
struct Window	*old_pr_WindowPtr;

static char	def_name[50] = "Meps";
static char	def_dir[50] = "df1:";

    if ( ! (IntuitionBase = (struct IntuitionBase *)
	OpenLibrary("intuition.library",(long)I_REV)) ||
	! (GfxBase =(struct GfxBase *)OpenLibrary("graphics.library",(long)G_REV)) )
	{
	printf("Can't open libraries\n");
	exit(20);
	}

    if ( ! (eS = (struct Screen *)OpenScreen(&TS)) )
	{
	printf("Can't Open Screen!!!!!\n");
	exit(22);
	}

    EdWindow.Screen = eS;

    if ( ! (eW =(struct Window *)OpenWindow(&EdWindow)) )
	{
	CloseScreen(eS);
	printf("Can't open window...\n");
	exit(21);
	}

    /* CAUTION!!! KNOW ABOUT pr_WindowPtr before you use it!!! */

    OurTask = (struct Process *)FindTask(0L);
    old_pr_WindowPtr = OurTask->pr_WindowPtr;
    OurTask->pr_WindowPtr = eW;

    get_fname(eW,eS,"Nicht",def_name,def_dir);

    printf("File name is :%s\n",def_name);
    printf("Directory is :%s\n",def_dir);

    /* ALWAYS RESTORE pr_WindowPtr BEFORE CLOSING THE WINDOW!!! */
    OurTask->pr_WindowPtr = old_pr_WindowPtr;

    CloseWindow(eW);
    CloseScreen(eS);
    
    CloseLibrary(GfxBase);
    CloseLibrary(IntuitionBase);
}

SHAR_EOF
fi # end of overwriting check
if test -f 'getfile.diffs'
then
	echo shar: will not over-write existing file "'getfile.diffs'"
else
cat << \SHAR_EOF > 'getfile.diffs'
0a1
> /* :ts=4,bk=0 */
4,7c5,8
< will prompt the user for a filename input.
< 	The program actually uses a window instead of a 'Requester'
< for greater flexibility. It will take control of your window's
< IDCMP Port when called.
---
> 	will prompt the user for a filename input.
> 	The program actually uses a window instead of a 'Requester'
> 	for greater flexibility. It will take control of your window's
> 	IDCMP Port when called.
16,19c17,21
< 2) The files may only be distributed in archive format, with no modifications.
< If you make any improvements on the file requester and would like to
< generally distribute them, please contact "cheath" on BIX, or write to:
< 	Microsmiths Inc, PO Box 561, Cambridge, MA 02140
---
> 2) The files may only be distributed in archive format, with no
>    modifications.
>    If you make any improvements on the file requester and would like to
>    generally distribute them, please contact "cheath" on BIX, or write to:
>    Microsmiths Inc, PO Box 561, Cambridge, MA 02140
198c200
<    FAST char	*retval;
---
>    FAST unsigned retval;
202c204
<    if ( ! (eW = cW) )   return(NL);
---
>    if ( ! (eW = cW) )   return(0);
215c217
<       return(NL);
---
>       return(0);
229c231
<       return(NL);
---
>       return(0);
255c257
<    for ( retval= NL, keepon=TRUE; keepon ; )
---
>    for ( retval = 0, keepon=TRUE; keepon ; )
319,321c321,327
<                retval = ddef;
<             case FGAD+2:      /* Cancel gadget   */
<                keepon = FALSE;
---
>                retval = 1;
> 			   keepon = FALSE;
> 			   break;
>             case FGAD+2:      /* Cancel gadget   */
>                keepon = FALSE;
> 			   retval = 0;
> 			   break;
SHAR_EOF
fi # end of overwriting check
cd ..
if test -f 'pr.c'
then
	echo shar: will not over-write existing file "'pr.c'"
else
cat << \SHAR_EOF > 'pr.c'
/* :ts=4 */
/*
   pr.c:  detabbing file printer for the Amiga

	  usage:  pr [-l] [-n#] [-t#] [-h] [file1] file2] ...
	  options:
			-h		do not print a page header
			-l		print with line numbers
			-L# 	set left margin to #
			-n# 	print # lines per page (4-line header xtra)
			-R# 	set right margin to #
			-s		print to stdout
			-t# 	set tab to # spaces (default 8)

	  Handles Un*x-style wildcarding.

	  Adapted from Software Tools by Chuck Allison - Apr 1985

	  This utility evolved from a public domain offering that I grabbed
	  from a local BBS some time ago.  I originally had conditional
	  compile stuff for Amiga / other-system code but decided to make
	  this an Amiga-only utility (let the other guys do the port for
	  a change :-) ).  Note that this utility assumes that it has complete
	  control over the left and right margins and that other print
	  characteristics are assumed to be controlled by the current
	  preferences settings.
	
	  I am offering this to the Amiga user community without restrictions.
	  If you make improvements, please re-release with source.	Enjoy!
										Mark R. Rinfret
										mark@unisec.USI.COM


	  03/28/87 -MRR- This is now an Amiga-only print utility.  Removed
					 the "exargs" (expand filename arguments) function
					 and replaced it with NextFile().  This allows
					 looping on the file requester when no filename
					 parameters are given.	Also, some general cleanup
					 prior to posting to the net ("...and make sure you're
					 wearing clean underwear...").

	  03/15/87 -MRR- Added C. Heath's file requester stuff - you can't
					 print from stdin now, but who cares?  I suppose
					 if you really wanted to, you could still print
					 stdin if xargc == 0 (cancel gadget selected),
					 but that's for someone else...

	  12/28/86 -MRR- redirect stderr to console
	  12/06/86 -MRR- embedded top-of-form ('\f') check
	  11/22/86 -MRR- added Amiga variations
*/

#define AMIGA
/* #define DEBUG */

#include <stdio.h>
#include <ctype.h>
#include <time.h>

#define VERSION "pr version 2.1, 03/28/87"

#define MAXLINE 	256
#define yes 		1
#define no			0

char    am_pm[3];
long    clock;
char    datestr[13];
FILE * f;
char   *filename;
unsigned    force_page;
unsigned    headers = yes;
unsigned    left_margin = 5;
unsigned    lineno;
unsigned    pageno;
unsigned    lines_per_page = 55;
char   *NextFile ();
unsigned    number = no;
FILE * printer;
static char *prtname = "prt:";
unsigned    right_margin = 80;
unsigned    srcline;
unsigned    tabspace = 4;
unsigned    tabstops[MAXLINE];
struct tm  *timeptr;
char    timestr[6];
unsigned    use_requester = no;
unsigned    use_stdout = no;
char    weekday[4];
unsigned    xargc;					/* arg count after option processing */
char  **xargv;						/* arg vector after option processing */

main (argc, argv)
int     argc; char *argv[];
{
	unsigned    i;
	char   *s;

/* Note: the freopen was added under Aztec C, version 3.20a.  It appeared
 * that stdout and stderr were the same thing.	This may no longer be
 * necessary, but it works, so...
 */

	freopen ("*", "w", stderr);		/* Note: "*" is the console name */

	fprintf (stderr, "\n%s\n", VERSION);
	++argv;							/* skip over program name arg */
	--argc;

 /* ..process switches.. */
	for (; *(s = *(argv)) == '-'; ++argv, --argc) {
		while (*++s)
			switch (tolower (*s)) {
				case '?': 
					usage ();

				case 'l': 
					number = yes;
					break;
				case 'L': 
					if ((left_margin = atoi (s + 1)) <= 0) {
						fprintf (stderr,
								"Bad left margin: %d\n", left_margin);
						exit (1);
					}
					break;
				case 'n': 
					lines_per_page = atoi (s + 1);
					break;
				case 'R': 
					if ((right_margin = atoi (s + 1)) <= 0 ||
							right_margin > MAXLINE) {
						fprintf (stderr,
								"Bad right margin: %d\n", right_margin);
						exit (1);
					}
					break;
				case 's': 
					use_stdout = yes;
					break;
				case 't': 
					if ((tabspace = atoi (s + 1)) <= 0) {
						fprintf (stderr,
								"bad tab specification: %d\n", tabspace);
						exit (1);
					}
					goto next_arg;
				case 'h': 
					headers = no;
					break;
				default: 
					usage ();
			}
next_arg:  /* ..cycle on outer for().. */ ;
	}

 /* Check a few argument combinations. */

	if (left_margin >= right_margin) {
		fprintf (stderr, "Unreasonable margins!\n");
		exit (1);
	}

	if (number)
		left_margin = 5;			/* no margins with numbering but numbers
									   use 5 columns */

 /* ..initialize tab settings.. */
	settabs ();

 /* ..get date and time.. */

	clock = time (NULL);
	timeptr = localtime (&clock);
	sprintf (datestr, "%2d/%02d/%02d",
			timeptr -> tm_mon + 1, timeptr -> tm_mday, timeptr -> tm_year);
	sprintf (timestr, "%2d:%02d",
			timeptr -> tm_hour, timeptr -> tm_min);

	if (use_stdout)
		printer = stdout;
	else
		if ((printer = fopen (prtname, "w")) == NULL) {
			fprintf (stderr, "\nFailed to open printer!\n");
			exit (1);
		}

 /* ..process files.. */

	xargv = argv;
	if ((xargc = argc) == 0)		/* if no filename args, use requester */
		use_requester = yes;

	while (filename = NextFile ()) {
		if ((f = fopen (filename, "r")) != NULL) {
			pr ();
			fclose (f);
		}
		else
			fprintf (stderr, "Can't open: %s\n", filename);
	}
}


/* Print one file. */

pr () {
	char    line[MAXLINE];

	force_page = pageno = srcline = 0;

	if (headers)
		lineno = lines_per_page;
	else
		lineno = 0;

	while (fgets (line, MAXLINE - 1, f) != NULL) {
		++srcline;					/* count input lines */

/* Note that top-of-form detection was a rather kludgy addition.  It only
 * works if the first character in the line is a ^L.
 */
		if (*line == '\f') {
			*line = ' ';			/* replace embedded ^L with blank */
			lineno = lines_per_page;/* force new page */
		}

		if (lineno >= lines_per_page)
			header ();
		detab (line);				/* ..output detabbed line.. */

	}
 /* ..form-feed after last page.. */
	putc ('\f', printer);
}

/* An attempt has been made to print a line past the right margin.
 * Force a new line and output a new left margin.  Also, if the page
 * line count has been exceeded, start a new page.
 */

break_line () {
	putc ('\n', printer);
	if (++lineno > lines_per_page)
		header ();
	do_left ();
}

/* Output spaces for the left margin, or source line number if requested. */

do_left () {
	unsigned    i;

	if (number)
		fprintf (printer, "%4d ", srcline);
	else
		for (i = 1; i < left_margin; ++i)
			fputc (' ', printer);
}

/* Force a new page and output a page header, if desired. */

header () {
	int     i;

	if (++pageno != 1)
		fprintf (printer, "\f\n");	/* eject if not first page */
	if (headers) {
		do_left ();
		for (i = left_margin; i < right_margin-5; ++i)
			putc ('-', printer);
		putc ('\n', printer);
		do_left ();

/* Note: there's room for improvement here.  A fancier algorithm would
 * attempt to distribute this information evenly over the current page
 * width.
 */
		fprintf (printer, "%s  %s  ", filename, datestr, timestr);
		fprintf (printer, "Page %4d  Line %4d\n    ", pageno, srcline);
		for (i = left_margin; i < right_margin-5; ++i)
			putc ('-', printer);
		fprintf (printer, "\n\n\n");
	}
	lineno = 0;
}


/* Replace embedded tab characters with the appropriate number of spaces,
 * outputting the results to the output device/file.
 * Called with:
 *		line:		string on which to do replacements
 * Returns:
 *		eventually :-)
 */

detab (line)
char   *line;
{
	int     eol = 0, i, col;

	do_left ();
	col = left_margin;

 /* Note: line[] has a terminating '\n' from fgets()...except if * the input
    line length exceeded MAXLINE. */
	for (i = 0; i < strlen (line); ++i)
		if (line[i] == '\t') {		/* ..tab.. */
			do {
				if (col == right_margin) {
					break_line ();
					break;
				}
				putc (' ', printer);
				++col;
			} while (!tabstops[col]);
		}

		else {
			if (line[i] == '\n')
				++eol;
			else
				if (col == right_margin)
					break_line ();
			putc (line[i], printer);
			++col;
		}
	if (!eol)
		putc ('\n', printer);		/* no end of line? */
	++lineno;
}

/* Initialize the tab settings for this file. */

settabs () {
	int     i;

	for (i = 0; i < MAXLINE; ++i)
		tabstops[i] = (i % tabspace == 1);
}


/* Display correct program usage, then exit. */

usage () {
	unsigned    i;
	char   *s;

	static char *usage_text[] = {
		"usage:  pr [-l] [-n#] [-t#] [-h] [file1] file2] ...\n",
		"\toptions:\n",
		"\t\t-h      do not print page headers\n\n",
		"\t\t-l      print with line numbers\n",
		"\t\t-L#     set left margin to #\n",
		"\t\t-n#     print # lines per page (4-line header xtra)\n",
		"\t\t-R#     set right margin to #\n",
		"\t\t-s      print to stdout instead of printer\n",
		"\t\t-t#     set tab to # spaces (default 4)\n",
		"Un*x-style wildcarding is supported.\n",
		(char *) NULL				/* last entry MUST be NULL */
	};

/* This IS nicer than 'n' discrete fprintf's, don't you think? */

	for (i = 0; s = usage_text[i]; ++i)
		fprintf (stderr, s);

	exit (1);
}

/* Test a file name for Un*x-style wildcard content.  Does not evaluate for
 * other forms of "wildness" :-) .
 *
 * Called with:
 *	   name:		file name string
 * Returns:
 *		yes =>		file name contains asterisk or question mark
 *		no	=>		just a vanilla filename
 */

unsigned    IsWild (name)
char   *name;
{
	char    c;
	char   *s;						/* copy of name */

	for (s = name; c = *s++;)
		if (c == '*' || c == '?')
			return yes;
	return no;
}


/* Get the next file name, either from the argument list or via a
 * requester.
 */

char   *NextFile () {
	static char *pattern = NULL;
	static char reqfile[101];		/* file returned by requester */

	unsigned    code;
	char   *name;
	char   *scdir ();

	if (use_requester) {
		if (ReqFile ("Detabbing Print Utility",
			"Select file to print:", reqfile, ":", "")) {
			return reqfile;
		}
		else
			return NULL;
	}

	while (pattern || xargc) {		/* have a pattern  or more args? */

/* If pattern is non-null, it was set up by a previous call.  That
 * being the case, we also know that it contains wildcarding.  We
 * make that distinction since calls to "scdir()" are expensive.
 */
		if (pattern) {				/* working old pattern */
			if (name = scdir (pattern))
				return name;		/* got another "hit" */
		}
		name = *xargv++;			/* get next name from args */
		--xargc;					/* one less arg to process */
		if (IsWild (name))
			pattern = name;
		else
			return name;
	}

	return NULL;					/* nothing left */
}
SHAR_EOF
fi # end of overwriting check
if test -f 'makefile'
then
	echo shar: will not over-write existing file "'makefile'"
else
cat << \SHAR_EOF > 'makefile'
# Makefile for the print file (pr) utility.
# GETFILE is expected to be the path to the directory where the
# file requester routines are kept.  Set it appropriately.

GETFILE=:getfile

REQOBJ=$(GETFILE)/getfile.o $(GETFILE)/safeclose.o $(GETFILE)/reqfile.o

OBJ=	pr.o $(REQOBJ)

pr:		$(OBJ)
		ln $(OBJ) -o pr -lc
SHAR_EOF
fi # end of overwriting check
if test -f 'readme.pr'
then
	echo shar: will not over-write existing file "'readme.pr'"
else
cat << \SHAR_EOF > 'readme.pr'

PR - a detabbing print utility for the Amiga
--------------------------------------------

I got the original version of this public domain program from a local
area bulletin board.  It apparently was based on a program in a book
called "Software Tools" by Chuck Allison.  I have almost totally
rewritten it and included some new features in the process.  PR is
invoked from the CLI with Un*x style command line parameters.  Un*x
style wildcarding of file names is supported.  All parameters, including
the file name(s) to be printed are optional.  In the case of formatting
options, a default is used if no option is given.  All options must
precede file names on the command line.  To see a list of options,
invoke PR with:

		pr -?

If no file names are passed on the command line, PR will put up a
file name requester.  Multiple files may be printed in this fashion,
terminating PR by pressing the CANCEL gadget on the requester.  The
requester was designed and written by C. Heath.  I have added some
modifications as well as a ReqFile() function which opens the necessary
libraries, window, etc.  Rather than post the modified version of
getfile (CHeath's requester package), I am posting a list of diff's
which you can apply (or not apply, as you see fit).  My changes were
fairly trivial, making getfile() return a boolean status to indicate
whether the CANCEL gadget was pressed.  

PR outputs a paginated listing, with or without headers.  The header lines
consist of line of information (filename, date, page and line number)
bracketed between two lines of dashes.  The user can set left and right
margins and enable line numbering.  If line numbering is used, the left
margin is set to 1 and any user-specified left margin is ignored.  PR
detects a top-of-form character (if it appears in column 1) and will
respond appropriately.  PR will also detect long lines, wrapping them
before the printer sees them and thus preserving pagination.  Oh - I
almost forgot PR's best feature - it expands tabs to spaces.  One of the
command line options is the number of spaces to substitute for a tab
character.

The current default values for PR are:

	left margin:		5
	right margin:		80
	tab spaces:			4
	headers:			enabled
	line numbers:		disabled

Of course, having the source (nice rhyme, eh?), you can change these so
that you don't have to constantly type in your favorite options.  One
thing - be sure that your margin settings in preferences don't interfere
with PR's behavior.  It expects that the left margin is set to 1 and
the right margin is at least as wide as what you specify.  I usually
set my preferences to 1, 255.  

There are lots of things that can be done with this program.  A 'copies'
option would be nice as well as options to support letter quality, draft,
characters per inch, etc.  The Amiga supports these things in a fairly
nice, generic way if you have the right printer driver.  That's about all
I have to say.  I hope you find this to be a useful addition to your
tool box.

											Mark Rinfret
											mark@unisec.USI.COM


p.s.  Move reqfile.c to the getfile directory after unshar-ing.
SHAR_EOF
fi # end of overwriting check
if test -f 'reqfile.c'
then
	echo shar: will not over-write existing file "'reqfile.c'"
else
cat << \SHAR_EOF > 'reqfile.c'
/* Originally named testing.c, this file adds a layer upon getfile.c
 * to open the necessary libraries, window, etc. to support get_fname.
 * It provides a simplistic interface for small, otherwise Intuition-free
 * applications which want to use a file requester.  The only callable
 * routine in this package is reqfile which returns the result code
 * (0 = cancelled, 1 = got file).  The calling application should
 * provide a return value string long enough to hold the largest fully-
 * qualified name expected (suggestion: 101 chars).
 * Original author:	C. Heath, Microsmiths, Inc. (I think).
 * Adaptation:		Mark R. Rinfret		Usenet: mark@unisec.USI.COM
 *								    	CPS:    72017,136
 */

#include <stdio.h>
#include <exec/types.h>
#include <intuition/intuition.h>

#include <libraries/dosextens.h>

#include <functions.h>
#include ":getfile/getfile.h"

#define I_REV   31					/* works with 33, also */
#define G_REV   31

#define	EWDTH	640
#define	EHGHT	198

#define	NL	NULL


struct IntuitionBase *IntuitionBase;
struct GfxBase  { int b; } *GfxBase;

struct NewScreen TS = {
	0,0,640,200,2,
	1,2,
	HIRES,	WBENCHSCREEN,
	0L, 0L, 0L
	};

/* Used to open a Window   */
struct NewWindow EdWindow = {
    0,2,EWDTH,EHGHT-2,		/* LeftEdge,TopEdge,Width,Height */
    1,2,			/* DetailPen,BlockPen	*/
    MENUPICK | NEWSIZE | REFRESHWINDOW | ACTIVEWINDOW |
	MOUSEBUTTONS | RAWKEY | MOUSEMOVE,
    WINDOWDRAG | WINDOWSIZING | SIMPLE_REFRESH | ACTIVATE | WINDOWDEPTH,
    NL,NL,"Window",		/* FirstGadget, CheckMark, Title  */
    NL,				/* Screen ( Null)	*/
    NL,				/* BitMap		*/
    150,45,32767,32767,		/* MinW, MinH, MaxW, MaxH */
    CUSTOMSCREEN };		/* Type			*/

/* Request file.
 * Called with:
 *	  window_name:	a name for the window that this routine creates
 *	  title:		file name prompt, appears in requester
 *	  result:		selected file name (set to null if abort)
 *    defnam:		default file name - if null, uses previous
 *	  defdir:		default directory - if null, uses previous
 */

unsigned ReqFile(window_name,title,result,defdir,defnam)
	char *window_name,*title,*result,*defdir,*defnam;
{
	unsigned code,leng;

struct Window	*eW;
struct Screen	*eS;

struct Process	*OurTask;
struct Window	*old_pr_WindowPtr;

static char	def_name[50] = "";
static char	def_dir[50] = ":";

	if (*defnam) strcpy(def_name,defnam);
	if (*defdir) strcpy(def_dir,defdir);

    if ( ! (IntuitionBase = (struct IntuitionBase *)
	OpenLibrary("intuition.library",(long)I_REV)) ||
	! (GfxBase =(struct GfxBase *)OpenLibrary("graphics.library",(long)G_REV)) )
	{
	fprintf(stderr,"Can't open libraries\n");
	exit(20);
	}

    if ( ! (eS = (struct Screen *)OpenScreen(&TS)) )
	{
	fprintf(stderr,"Can't Open Screen!!!!!\n");
	exit(22);
	}

    EdWindow.Screen = eS;
	EdWindow.Title = window_name;
    if ( ! (eW =(struct Window *)OpenWindow(&EdWindow)) )
	{
		CloseScreen(eS);
		fprintf(stderr,"Can't open window...\n");
		exit(21);
	}

    /* CAUTION!!! KNOW ABOUT pr_WindowPtr before you use it!!! */

    OurTask = (struct Process *)FindTask(0L);
    old_pr_WindowPtr = OurTask->pr_WindowPtr;
    OurTask->pr_WindowPtr = eW;

    if (code = get_fname(eW,eS,title,def_name,def_dir)) {
		strcpy(result,def_dir);
		if ((leng=strlen(result)) && result[leng-1] != ':')
			strcat(result,"/");
		strcat(result,def_name);
	}
	else *result = '\0';

    /* ALWAYS RESTORE pr_WindowPtr BEFORE CLOSING THE WINDOW!!! */
    OurTask->pr_WindowPtr = old_pr_WindowPtr;

    CloseWindow(eW);
    CloseScreen(eS);
    
    CloseLibrary(GfxBase);
    CloseLibrary(IntuitionBase);
	return code;
}

SHAR_EOF
fi # end of overwriting check
cd ..
#	End of shell archive
exit 0
-- 
| Mark R. Rinfret, SofTech, Inc.		mark@unisec.usi.com |
| Guest of UniSecure Systems, Inc., Newport, RI                     |
| UUCP:  {gatech|mirror|cbosgd|uiucdcs|ihnp4}!rayssd!unisec!mark    |
| work: (401)-849-4174	home: (401)-846-7639                        |