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 |