mrr@amanpt1.Newport.RI.US (Mark Rinfret) (10/12/89)
#! /bin/sh # This is a shell archive. Remove anything before this line, then unpack # it by saving it into a file and typing "sh file". To overwrite existing # files, type "sh file -c". You can also feed this as standard input via # unshar, or by typing "sh <file", e.g.. If this archive is complete, you # will see the following message at the end: # "End of archive 3 (of 5)." # Contents: MRDateReq.c # Wrapped by mrr@mrramiga on Wed Oct 11 18:11:04 1989 # This shar was created for Amiga and may have pathnames which # are incompatible with Unix. Replace colon (:) with slash (/) # in offending pathnames. if test -f MRDateReq.c -a "${1}" != "-c" ; then echo shar: Will not over-write existing file \"MRDateReq.c\" else echo shar: Extracting \"MRDateReq.c\" \(25328 characters\) sed "s/^X//" >MRDateReq.c <<'END_OF_MRDateReq.c' X/* Date Requester Package X * Filename: MRDateReq.c X * Author: Mark R. Rinfret X * Description: X * X * This package contains an ARP-compatible (dependent) date requester. X * The primary function, MRDateRequest(), displays a requester in the X * caller's window and allows the user to interactively enter/edit the X * date value. All information is passed via a pointer to a special X * packet structure. X * X * This code is not entirely reentrant. In order to accomplish this, X * the requester and associated gadgets would have to be duplicated and X * a method for obtaining gadget pointers from gadget ID's implemented. X * If someone wants to put this in a shared library, that, at a minimum X * must be done. X * X * 09/01/89 -MRR- Rewritten to use ARP date functions; new requester layout. X * X */ X X#include <exec/memory.h> X#include <intuition/intuition.h> X#include <intuition/intuitionbase.h> X#include <libraries/dosextens.h> X#include <libraries/arpbase.h> X#include <graphics/gfxbase.h> X#include <graphics/gfx.h> X#include <graphics/display.h> X X#include <graphics/text.h> X#include <functions.h> X#include <arpfunctions.h> X X#include <ctype.h> X#include "MRDates.h" X#include "MRGadgets.h" X#include "MRDateReq.h" X X/*==================================================================*/ X X#define SetImageData(img, dat) ((struct Image *)(img))->ImageData = dat X#define daterequest RequesterStructure1 X X#define UP_MONTH_GADGET 1 X#define UP_DAY_GADGET 2 X#define UP_YEAR_GADGET 3 X#define UP_HOUR_GADGET 4 X#define UP_MINUTE_GADGET 5 X#define UP_SECOND_GADGET 6 X#define DOWN_MONTH_GADGET 7 X#define DOWN_DAY_GADGET 8 X#define DOWN_YEAR_GADGET 9 X#define DOWN_HOUR_GADGET 10 X#define DOWN_MINUTE_GADGET 11 X#define DOWN_SECOND_GADGET 12 X#define NOW_GADGET 13 X#define ZERO_GADGET 14 X#define OK_GADGET 15 X#define CANCEL_GADGET 16 X#define YEAR_GADGET 17 X#define MONTH_GADGET 18 X#define DAY_GADGET 19 X#define HOUR_GADGET 20 X#define MINUTE_GADGET 21 X#define SECOND_GADGET 22 X#define DATE_FORMAT_GADGET 23 X#define DATE_GADGET 24 X#define TIME_GADGET 25 X#define DAYNAME_GADGET 26 X#define WEEK_PLUS_GADGET 27 X#define WEEK_MINUS_GADGET 28 X#define PROMPT_GADGET 29 X X X#include "MRDateReq.pw.c" X Xstatic void RedrawDateRequester(); X X#define MAX_DATE_FORMAT 3 X Xstatic char *dateFormats[FORMAT_MAX+1] = { X "DD-MMM-YY", /* FORMAT_DOS */ X "YY-MM-DD", /* FORMAT_INT */ X "MM-DD-YY", /* FORMAT_USA */ X "DD-MM-YY" /* FORMAT_CDN */ X }; X X/*===================================================================*/ X X/* FUNCTION X DupImage - duplicate an image into CHIP ram. X X SYNOPSIS X static USHORT *DupImage(theImage, imageSize) X struct Image *theImage; X long *imageSize; X X DESCRIPTION X DupImage calculates the size of the imageData required by X <theImage> and stores this value into the variable pointed to X by <imageSize>. It then attempts to allocate memory for the X image in CHIP ram. If the allocation is successful, the image X data is copied and the pointer to the CHIP copy is returned. X If the allocation fails, NULL is returned. X X DupImage is "smart" about the duplication process. It uses the X PlanePick field of <theImage> to determine how many planes of X data are actually present in <theImage>. X*/ Xstatic USHORT * XDupImage(theImage, imageSize) X struct Image *theImage; X ULONG *imageSize; X{ X USHORT mask; X USHORT *newImageData = NULL; X long planeSize, totalSize = 0; X X if (theImage) { X /* The size of a plane is X the number of 16 bit words of width times X the number of pixels of height times X the number of bytes per 16 bit word (USHORT). X */ X planeSize = (ULONG) X ( ( (theImage->Width + 15L) >> 4L) * X theImage->Height * sizeof(USHORT) ); X for (mask = 1L; mask; mask <<= 1L) { X if (theImage->PlanePick & mask) X totalSize += planeSize; X } X } X if (*imageSize = totalSize) { X newImageData = (USHORT *) AllocMem(totalSize, MEMF_CHIP); X if (newImageData) X CopyMem(theImage->ImageData, newImageData, totalSize); X } X return newImageData; X} X X/* FUNCTION X FreeMRDatePacket - free memory allocated to an MRDatePacket. X X SYNOPSIS X void FreeMRDatePacket(thePacket) X MRDatePacket *thePacket; X X DESCRIPTION X FreeMRDatePacket simply frees the memory allocated to an X MRDateRequest packet, specified by <thePacket>. X*/ X Xvoid XFreeMRDatePacket(thePacket) X MRDatePacket *thePacket; X{ X if (thePacket->myStrings) { /* Did I allocate the strings? */ X if (thePacket->ARPDatePacket.dat_StrDay) X FreeMem(thePacket->ARPDatePacket.dat_StrDay, LEN_DATSTRING); X if (thePacket->ARPDatePacket.dat_StrDate) X FreeMem(thePacket->ARPDatePacket.dat_StrDate, LEN_DATSTRING); X if (thePacket->ARPDatePacket.dat_StrTime) X FreeMem(thePacket->ARPDatePacket.dat_StrTime, LEN_DATSTRING); X } X FreeMem(thePacket, (long) sizeof(*thePacket)); X} X X/* FUNCTION X CreateMRDatePacket - allocate and initialize an MRDatePacket. X X SYNOPSIS X MRDatePacket *CreateMRDatePacket(theDate, theFormat, makeStrings) X struct DateStamp *theDate; X int theFormat; X int makeStrings; X X DESCRIPTION X InitMRDateRequest() allocates an MRDateRequest packet and initializes X several of its fields. <theDate> may be a pointer to a DateStamp X structure containing the initial (default) date value or it may be X NULL. If NULL, the current date and time are used as the default. X <theFormat> is expected to be a value in the range of 0 through X FORMAT_MAX, as defined in <libraries/arpbase.h>, and is the desired X date format. If <makeStrings> is non-zero, CreateMRDatePacket() also X allocates the strings for the string fields in the embedded X ARPDatePacket. X X A pointer to an MRDateRequest packet is returned if successful. X Otherwise, NULL is returned, indicating an out-of-memory X condition. X*/ XMRDatePacket * XCreateMRDatePacket(theDate, theFormat, makeStrings) X struct DateStamp *theDate; X int theFormat, makeStrings; X{ X MRDatePacket *dr; X X dr = (MRDatePacket *) AllocMem((long)sizeof(*dr), MEMF_CLEAR); X if (dr) { X if ( (theFormat < 0) || (theFormat > FORMAT_MAX)) X theFormat = FORMAT_USA; X dr->ARPDatePacket.dat_Format = theFormat; X dr->requester = &daterequest; X if (theDate) X dr->ARPDatePacket.dat_Stamp = *theDate; X else X DateStamp(&dr->ARPDatePacket.dat_Stamp); X DSToDate(&dr->ARPDatePacket.dat_Stamp, &dr->newDate); X if (dr->newDate.Dyear == 0) { X dr->newDate.Dyear = 1978; X DateToDS(&dr->newDate, &dr->ARPDatePacket.dat_Stamp); X } X if (makeStrings) { X dr->myStrings = 1; X dr->ARPDatePacket.dat_StrDay = (BYTE *) X AllocMem(LEN_DATSTRING, MEMF_CLEAR); X dr->ARPDatePacket.dat_StrDate = (BYTE *) X AllocMem(LEN_DATSTRING, MEMF_CLEAR); X dr->ARPDatePacket.dat_StrTime = (BYTE *) X AllocMem(LEN_DATSTRING, MEMF_CLEAR); X X if ((dr->ARPDatePacket.dat_StrDay == NULL) || X (dr->ARPDatePacket.dat_StrDate == NULL) || X (dr->ARPDatePacket.dat_StrTime == NULL)) { X FreeMRDatePacket(dr); X dr = NULL; X } X } X } X return dr; X} X X/* FUNCTION X MRDateRequest - request a date from the user. X X SYNOPSIS X int MRDateRequest(datePacket) X MRDatePacket *datePacket; X DESCRIPTION X Prior to calling MRDateRequest(), the caller must allocate the X <datePacket> and initialize the following <datePacket> fields: X ARPDatePacket.dat_Stamp - the initial date value X ARPDatePacket.dat_Format - one of the ARP date format values X prompt - a short prompt string X window - window in which requester will X appear X X Part of this initialization can be performed by InitMRDateRequest(). X X A requester will be created and initialized with the values X provided by the user. The user may then interact with the requester X to specify a new date. Upon return, the following fields of X <datePacket->ARPDatePacket> will be meaningful: X dat_Format - contains final date format X dat_Stamp - contains return date value (DateStamp) X X In addition, the following fields of <datePacket> contain info: X newDate - contains date in MRDate format X status - 0 = OK, 1 => error or CANCEL X X */ Xint XMRDateRequest(datePacket) X MRDatePacket *datePacket; X{ X#define MYFLAGS (REQSET | GADGETUP | GADGETDOWN) X X ULONG class; /* message class */ X USHORT code; /* message code */ X struct Gadget *gadget; /* pointer to gadget affected */ X USHORT gadgid; /* gadget ID */ X USHORT i; X USHORT *downImage = NULL, *upImage = NULL; X LONG downImageSize, upImageSize; X struct Image *image; X struct IntuiMessage *msg; /* Intuition message pointer */ X ULONG IDCMPFlags; /* current IDCMP flags */ X BOOL ready; X BOOL redraw; /* TRUE => redraw requester */ X USHORT *saveDownImage, *saveUpImage; X LONG value; X SHORT x,y; /* mouse x and y position */ X X if ( (datePacket->ARPDatePacket.dat_Format < 0) || X (datePacket->ARPDatePacket.dat_Format > FORMAT_MAX) ) X datePacket->ARPDatePacket.dat_Format = FORMAT_DOS; X X saveDownImage = GadgetImageData(&downYearGadget); X saveUpImage = GadgetImageData(&upYearGadget); X downImage = DupImage(downYearGadget.GadgetRender, &downImageSize); X if (downImage) { X image = (struct Image *) downYearGadget.GadgetRender; X SetImageData(image, downImage); X downMonthGadget.GadgetRender = (APTR) image; X downDayGadget.GadgetRender = (APTR) image; X downHourGadget.GadgetRender = (APTR) image; X downMinuteGadget.GadgetRender = (APTR) image; X downMinuteGadget.GadgetRender = (APTR) image; X downSecondGadget.GadgetRender = (APTR) image; X } X upImage = DupImage(upYearGadget.GadgetRender, &upImageSize); X if (upImage) { X image = (struct Image *) upYearGadget.GadgetRender; X SetImageData(image, upImage); X upMonthGadget.GadgetRender = (APTR) image; X upDayGadget.GadgetRender = (APTR) image; X upHourGadget.GadgetRender = (APTR) image; X upMinuteGadget.GadgetRender = (APTR) image; X upMinuteGadget.GadgetRender = (APTR) image; X upSecondGadget.GadgetRender = (APTR) image; X } X datePacket->status = 0; X daterequest.BackFill = 0; X /* Make sure that the requester's window can see a REQSET message. X * This allows us to ignore messages until our requester is up. X */ X IDCMPFlags = datePacket->window->IDCMPFlags; X ModifyIDCMP(datePacket->window, IDCMPFlags | MYFLAGS); X if (! Request(&daterequest, datePacket->window)) { X datePacket->status = 1; X goto done; X } X SetBPen(daterequest.ReqLayer->rp, 1L); X SetStringGadget(&promptGadget, datePacket->window, X datePacket->requester, datePacket->prompt); X X datePacket->requester = &daterequest; X DSToDate(&datePacket->ARPDatePacket.dat_Stamp, &datePacket->newDate); X RedrawDateRequester(datePacket); X X for (ready = 0; ! ready ;) { /* Wait for REQSET message. */ X Wait(1L << datePacket->window->UserPort->mp_SigBit); X while (msg = (struct IntuiMessage *) X GetMsg(datePacket->window->UserPort)) { X if (msg->Class == REQSET) ready = 1; X ReplyMsg(msg); X } X } X X for (;;) { X Wait(1L << datePacket->window->UserPort->mp_SigBit); X while (msg = (struct IntuiMessage *) X GetMsg(datePacket->window->UserPort)) { X class = msg->Class; X code = msg->Code; X gadget = (struct Gadget *) msg->IAddress; X x = msg->MouseX; X y = msg->MouseY; X ReplyMsg(msg); /* acknowledge the message */ X X redraw = TRUE; /* Assume a redraw will be needed. */ X switch (class) { X X#ifdef undef X case REQSET: X redraw = FALSE; X break; X#endif X#ifdef undef X case GADGETDOWN: X gadgid = gadget->GadgetID; X switch (gadgid) { X default: X break; X } X break; X#endif X case GADGETUP: X gadgid = gadget->GadgetID; X switch (gadgid) { X case NOW_GADGET: X DateStamp(&datePacket->ARPDatePacket.dat_Stamp); X DSToDate(&datePacket->ARPDatePacket.dat_Stamp, X &datePacket->newDate); X break; X X case ZERO_GADGET: X setmem(&datePacket->newDate, X sizeof(datePacket->newDate), 0); X datePacket->newDate.Dmonth = 1; X datePacket->newDate.Dday = 1; X break; X X case WEEK_PLUS_GADGET: X datePacket->ARPDatePacket.dat_Stamp.ds_Days += 7; X DSToDate(&datePacket->ARPDatePacket.dat_Stamp, X &datePacket->newDate); X break; X X case WEEK_MINUS_GADGET: X if (datePacket->ARPDatePacket.dat_Stamp.ds_Days >= 7) X datePacket->ARPDatePacket.dat_Stamp.ds_Days -= 7; X else X datePacket->ARPDatePacket.dat_Stamp.ds_Days = 0; X DSToDate(&datePacket->ARPDatePacket.dat_Stamp, X &datePacket->newDate); X break; X X case OK_GADGET: X goto done; X break; X X case CANCEL_GADGET: X datePacket->status = 1; X goto done; X break; X X case YEAR_GADGET: X value = GadgetValue(&yearGadget); X if ((value >= 1978) && (value <= 2100)) X datePacket->newDate.Dyear = value; X break; X X case MONTH_GADGET: X break; X X case DAY_GADGET: X value = GadgetValue(&dayGadget); X if ((value >= 1) && (value <= 31)) X datePacket->newDate.Dday = value; X break; X X case HOUR_GADGET: X value = GadgetValue(&hourGadget); X if ((value >= 0) && (value < 24)) X datePacket->newDate.Dhour = value; X break; X X case MINUTE_GADGET: X value = GadgetValue(&minuteGadget); X if ((value >= 0) && (value < 60)) X datePacket->newDate.Dminute = value; X break; X X case SECOND_GADGET: X value = GadgetValue(&secondGadget); X if ((value >= 0) && (value < 60)) X datePacket->newDate.Dsecond = value; X break; X X case UP_YEAR_GADGET: X ++datePacket->newDate.Dyear; X break; X X case DOWN_YEAR_GADGET: X if (datePacket->newDate.Dyear > 1978) X --datePacket->newDate.Dyear; X break; X X case UP_MONTH_GADGET: X if (++datePacket->newDate.Dmonth > 12) X datePacket->newDate.Dmonth = 1; X break; X X case DOWN_MONTH_GADGET: X if (--datePacket->newDate.Dmonth < 1) X datePacket->newDate.Dmonth = 12; X break; X X case UP_DAY_GADGET: X if (datePacket->newDate.Dday < 31) { X ++datePacket->newDate.Dday; X } X break; X X case DOWN_DAY_GADGET: X if (datePacket->newDate.Dday > 1) X --datePacket->newDate.Dday; X break; X X case UP_HOUR_GADGET: X if (++datePacket->newDate.Dhour > 23) X datePacket->newDate.Dhour = 0; X break; X X case DOWN_HOUR_GADGET: X if (--datePacket->newDate.Dhour < 0) X datePacket->newDate.Dhour = 23; X break; X X case UP_MINUTE_GADGET: X if (++datePacket->newDate.Dminute > 59) X datePacket->newDate.Dminute = 0; X break; X X case DOWN_MINUTE_GADGET: X if (--datePacket->newDate.Dminute < 0) X datePacket->newDate.Dminute = 59; X break; X X case UP_SECOND_GADGET: X if (++datePacket->newDate.Dsecond > 59) X datePacket->newDate.Dsecond = 0; X break; X X case DOWN_SECOND_GADGET: X if (--datePacket->newDate.Dsecond < 0) X datePacket->newDate.Dsecond = 59; X break; X X case DATE_FORMAT_GADGET: X if (++datePacket->ARPDatePacket.dat_Format>FORMAT_MAX) X datePacket->ARPDatePacket.dat_Format = 0; X SetOptionGadget(&dateFormatGadget, datePacket->window, X datePacket->requester, X dateFormats[datePacket->ARPDatePacket.dat_Format]); X break; X X default: X redraw = FALSE; X break; X } /* end switch(gadgid) */ X X /* Reformat the new date value. */ X if (redraw) { X DateToDS(&datePacket->newDate, X &datePacket->ARPDatePacket.dat_Stamp); X DSToDate(&datePacket->ARPDatePacket.dat_Stamp, X &datePacket->newDate); X RedrawDateRequester(datePacket); X } X break; X X default: X break; /* ignore the rest */ X } /* end switch(class) */ X } X } Xdone: X /* Restore gadget image data pointers. */ X SetImageData(GadgetImage(&downYearGadget), saveDownImage); X SetImageData(GadgetImage(&upYearGadget), saveUpImage); X X /* Restore window's IDCMP flags. */ X ModifyIDCMP(datePacket->window, IDCMPFlags); X if (downImage) FreeMem(downImage, downImageSize); X if (upImage) FreeMem(upImage, upImageSize); X DateToDS(&datePacket->newDate, &datePacket->ARPDatePacket.dat_Stamp); X return datePacket->status; X} X X/* FUNCTION X * RedrawDateRequester - reformat and redisplay the date requester X * X * SYNOPSIS X * static void RedrawDateRequester(datePacket) X * MRDatePacket *datePacket; X */ Xstatic void XRedrawDateRequester(datePacket) X MRDatePacket *datePacket; X{ X char *p, s[20]; X X X sprintf(s,"%4d", datePacket->newDate.Dyear); X SetStringGadget(&yearGadget, datePacket->window, X datePacket->requester, s); X SetStringGadget(&monthGadget, datePacket->window, datePacket->requester, X calendar[datePacket->newDate.Dmonth-1].Mname); X sprintf(s,"%02d", datePacket->newDate.Dday); X SetStringGadget(&dayGadget, datePacket->window, datePacket->requester, s); X sprintf(s,"%02d", datePacket->newDate.Dhour); X SetStringGadget(&hourGadget, datePacket->window, X datePacket->requester, s); X sprintf(s,"%02d", datePacket->newDate.Dminute); X SetStringGadget(&minuteGadget, datePacket->window, X datePacket->requester, s); X sprintf(s,"%02d", datePacket->newDate.Dsecond); X SetStringGadget(&secondGadget, datePacket->window, X datePacket->requester, s); X X StamptoStr(datePacket); X /* There appears to be a bug in ARP's formatting of the time X * string. A trash character appears where the terminating null X * should be. X */ X datePacket->ARPDatePacket.dat_StrTime[8] = 0; X SetStringGadget(&dateGadget, datePacket->window, X datePacket->requester, X datePacket->ARPDatePacket.dat_StrDate); X X SetStringGadget(&timeGadget, datePacket->window, X datePacket->requester, X datePacket->ARPDatePacket.dat_StrTime); X X SetStringGadget(&dayNameGadget, datePacket->window, X datePacket->requester, X datePacket->ARPDatePacket.dat_StrDay); X X SetOptionGadget(&dateFormatGadget, datePacket->window, X datePacket->requester, X dateFormats[datePacket->ARPDatePacket.dat_Format]); X X} X X X#ifdef DEBUG X X/* --- Only compiled in the debug version --- */ X X#include <exec/memory.h> X X/* New window structure */ X Xstruct NewWindow newwindow = { X 0,0,640,200,0,1, X X/* IDCMP Flags */ X X MOUSEMOVE | MENUPICK | MOUSEBUTTONS | X CLOSEWINDOW | GADGETDOWN | GADGETUP | REQSET, X X/* Flags */ X WINDOWCLOSE | WINDOWDEPTH | ACTIVATE | RMBTRAP | REPORTMOUSE, X X NULL, /* First gadget */ X NULL, /* Checkmark */ X (UBYTE *)"Date Requester Test Program", /* Window title */ X NULL, /* No custom streen */ X NULL, /* Not a super bitmap window */ X 0,0,640,200, /* Not used, but set up anyway */ X WBENCHSCREEN X}; X Xstatic struct IntuiText MoreText = { X AUTOFRONTPEN, /* FrontPen */ X AUTOBACKPEN, /* BackPen */ X JAM2, /* DrawMode */ X AUTOLEFTEDGE, /* LeftEdge */ X AUTOTOPEDGE, /* TopEdge */ X AUTOITEXTFONT, /* ITextFont */ X (UBYTE *) "Want to play some more?", /* IText */ X NULL /* NextText */ X }; X Xstatic struct IntuiText YesText = { X AUTOFRONTPEN, /* FrontPen */ X AUTOBACKPEN, /* BackPen */ X AUTODRAWMODE, /* DrawMode */ X AUTOLEFTEDGE, /* LeftEdge */ X AUTOTOPEDGE, /* TopEdge */ X AUTOITEXTFONT, /* ITextFont */ X (UBYTE *) "Sure!", /* IText */ X NULL /* NextText */ X }; X Xstatic struct IntuiText NoText = { X AUTOFRONTPEN, /* FrontPen */ X AUTOBACKPEN, /* BackPen */ X JAM2, /* DrawMode */ X AUTOLEFTEDGE, /* LeftEdge */ X AUTOTOPEDGE, /* TopEdge */ X AUTOITEXTFONT, /* ITextFont */ X (UBYTE *) "Nope!", /* IText */ X NULL /* NextText */ X }; X Xstruct ArpBase *ArpBase; Xstruct GfxBase *GfxBase; Xstruct IntuitionBase *IntuitionBase; Xstruct Window *mywindow; Xlong *ds; X Xmain() X{ X static char *arpNotOpen = "I can not open the ARP library!\n"; X short keep_going; X MRDatePacket *datePacket = NULL; X X ArpBase = (struct ArpBase *) OpenLibrary(ArpName, ArpVersion); X if (ArpBase == NULL) { X Write(Output(), arpNotOpen , (long) sizeof(arpNotOpen)); X goto done; X } X GfxBase = (struct GfxBase *) ArpBase->GfxBase; X IntuitionBase = (struct IntuitionBase *) ArpBase->IntuiBase; X X datePacket = CreateMRDatePacket(NULL, FORMAT_USA, 1); X X mywindow = OpenWindow(&newwindow); X /* Set initial values in date packet. */ X datePacket->window = mywindow; X do { X MRDateRequest(datePacket); X keep_going = AutoRequest(mywindow, &MoreText, &YesText, &NoText, X NULL, NULL, 220L, 50L); X } while (keep_going); X Xdone: X if (datePacket) X FreeMRDatePacket(datePacket); X X if (mywindow) X CloseWindow(mywindow); X X if (IntuitionBase) X CloseLibrary(IntuitionBase); X X} X X#endif X END_OF_MRDateReq.c if test 25328 -ne `wc -c <MRDateReq.c`; then echo shar: \"MRDateReq.c\" unpacked with wrong size! fi # end of overwriting check fi echo shar: End of archive 3 \(of 5\). cp /dev/null ark3isdone MISSING="" for I in 1 2 3 4 5 ; do if test ! -f ark${I}isdone ; then MISSING="${MISSING} ${I}" fi done if test "${MISSING}" = "" ; then echo You have unpacked all 5 archives. rm -f ark[1-9]isdone else echo You still need to unpack the following archives: echo " " ${MISSING} fi ## End of shell archive. exit 0 -- # Mark R. Rinfret mrr@amanpt1.Newport.RI.US # HyperView Systems Corp. Hypermedia Solutions for Documentation/Training # 28 Jacome Way Work: 401-849-9390 x301 # Middletown, RI 02840 Home: 401-846-7639