karl@sugar.uu.net (Karl Lehenbauer) (10/28/88)
Speaking of file requesters, it's really nice when the file requester puts the scroll bar back where it was (showing the same files) as the last time one was in the file requester. This is great when using a requester to access every file in a directory, as when listening to all the sounds in an audio program's sound directory, for example. -- -- "We've been following your progress with considerable interest, not to say -- contempt." -- Zaphod Beeblebrox IV -- uunet!sugar!karl, Unix BBS (713) 438-5018
rap@rap.ardent.com (Rob Peck) (05/06/89)
Perry's posting about file requesters made me think just a little bit
about my own preferences on file requesters.
My BIGGEST problem with them is that all that I have seen thusfar
place the FIRST 8 (5, 7 10?) files in the directory as the available
choices and you have to scroll down to get to the file you want.
Often when I am transferring files and so on, I wanna do the files
in sequence, so the file requester should present me with my list
of files, with its pointer positioned WHERE I LAST LEFT IT.
Also related to that same topic, I'd like to see an option that could
be enabled to allow me to delete a file from a file requester, in
addition to all of the other things that the file requester does.
If using a re-entrant file requester, this option should be disable-able
on a per-task basis. E.G. if I have transferred this file already,
I may want to remove it and therefore not see it in the requester
any more.
Third wish - cacheing of the file directory contents on a per-task
basis, so that it is not necessary to seek all over creation to
build the file list for the requester. Especially if there are
120 file and so on in a single directory (strange practice, but
it happens). Suggest that each task pass a pointer to a data
structure of some kind similar to this:
#define NEWFILEDIR 0
#define SEARCHFILE 1
#define ENDFILEDIR 2
struct FileDir {
char *dir; /* pointer to full pathname */
char *dirlist; /* pointer to first character of
* a string of filenames,
* each name a null-terminated string*/
char *chosen; /* pointer to the filename that was chosen
* or to a string that describes a directory
* for which a list is to be built */
int pathsize; /* size of the pathname string */
/* (REDUNDANT, available from strlen) */
int listsize; /* size of the filename list */
int chosensize; /* size of the chosen filename */
/* (REDUNDANT, available from strlen) */
int action; /* what to do this time */
int sliderpos; /* where did I leave the slider? */
struct DateStamp ds; /* when did we build this list */
};
User allocates one of these data structures for EACH directory
he wishes to cache. Then sends the address of this data structure
to the file requester.
(BEGIN PSEUDOCODE)
switch (pointer->action)
case NEWFILEDIR - (also to "reuse" an existing one, "pointer" is
address of start of the data structure,
does NOT present the file requester to the user)
if (pointer->path != NULL)
FreeMem(pointer->path, pathsize)
if (pointer->dirlist != NULL)
FreeMem(pointer->dirlist, listsize)
if chosen == NULL, build path string for CURRENT dir.
else build pathstring for CHOSEN dir.
pointer->path = AllocMem(sizeof(pathstring+TRAILING NULL)
COPY pathstring to pointer->path
pointer->pathsize = 1 + strlen(pointer->path)
BuildFileList() [ searches files in chosen path,
allocates memory for dirlist
and sets listsize
and sets datestamp
and sets slider to first file]
return(0) if no errors along the way, else return error value
case SEARCHFILE
See if file directory's last-modified date is later than
the datestamp in the data structure. If directory modified,
do NEWFILE case, otherwise present the directory from the
current dirlist. (No disk seeking -- super-speedy because
the lists are already in memory) If user chooses a directory
rather than a file, modify everything in the structure and present
the information for that new directory instead. When user chooses
a file instead of a directory, return (0) and delete the file
requestor. Set sliderpos to have this file name at the top
of the list the next time the requester is presented.
User finds the chosen path in "path" and the
file in "chosen". Otherwise error code is the return value.
case ENDFILEDIR
Deallocate everything "attached" to the passed in FileDir
structure, and set the pointer values to NULL and the
sizes to zero.
(END PSEUDOCODE)
The reason I propose something like this is then a program can
maintain as many "cached" directories as it wishes, and pass to the
file requester the pointer to the one it wants to choose from.
The above proposal may, of course, be incomplete, but I hope it
gives the re-entrant file requester writers something to think about.
And, for that matter, perhaps this pointer can be part of an AREXX
message so that we get the benefit of AREXX compatibility at the
same time.
Rob Peck ...uunet!ardent!rap
youngb@pur-ee.UUCP (H. Bret Young) (05/06/89)
From article <6342@ardent.UUCP>, by rap@rap.ardent.com (Rob Peck): -> Perry's posting about file requesters made me think just a little bit -> about my own preferences on file requesters. -> - [stuff deleted] -> -> Third wish - cacheing of the file directory contents on a per-task -> basis, so that it is not necessary to seek all over creation to -> build the file list for the requester. Especially if there are -> 120 file and so on in a single directory (strange practice, but -> it happens). Suggest that each task pass a pointer to a data -> structure of some kind similar to this: -> -> #define NEWFILEDIR 0 -> #define SEARCHFILE 1 -> #define ENDFILEDIR 2 -> -> struct FileDir { -> char *dir; /* pointer to full pathname */ -> char *dirlist; /* pointer to first character of -> * a string of filenames, -> * each name a null-terminated string*/ -> char *chosen; /* pointer to the filename that was chosen -> * or to a string that describes a directory -> * for which a list is to be built */ -> int pathsize; /* size of the pathname string */ -> /* (REDUNDANT, available from strlen) */ -> int listsize; /* size of the filename list */ -> int chosensize; /* size of the chosen filename */ -> /* (REDUNDANT, available from strlen) */ -> int action; /* what to do this time */ -> int sliderpos; /* where did I leave the slider? */ -> struct DateStamp ds; /* when did we build this list */ -> }; -> -> User allocates one of these data structures for EACH directory -> he wishes to cache. Then sends the address of this data structure -> to the file requester. -> -> (BEGIN PSEUDOCODE) -> - [code deleted] -> -> (END PSEUDOCODE) -> -> The reason I propose something like this is then a program can -> maintain as many "cached" directories as it wishes, and pass to the -> file requester the pointer to the one it wants to choose from. -> -> The above proposal may, of course, be incomplete, but I hope it -> gives the re-entrant file requester writers something to think about. -> -> And, for that matter, perhaps this pointer can be part of an AREXX -> message so that we get the benefit of AREXX compatibility at the -> same time. -> -> Rob Peck ...uunet!ardent!rap You know ... I was just thinking today that I wish I had file completion in my ARP shell. I was trying to figure out a nice way to do this (i.e. fast) when I read the above posting. Unless I am missing something, wouldn't the above method of cacheing file directories to get faster and better file requestors also give as an immediate side effect the ability to implement file completion with almost no extra cost. I like it. What do you think? Bret ARPA: youngb@eg.ecn.purdue.edu UUCP: youngb@pur-ee.uucp
papa@pollux.usc.edu (Marco Papa) (05/06/89)
The RJ Mical file requester seems to implement all of your requsted features (caching, leaving pointer fixed among separate invocations). One thing that I really don't like (for example) of the new Arp1.3 file requester is the fact that each time I the programs call it, it recomputes the list of files again. Is this an inherent flaw of the file requester or of the application program that uses it? -- Marco Papa 'Doc' BTW, the RJ mical file requster is not reentrant but can be "multiply" instantiated. -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= uucp:...!pollux!papa BIX:papa ARPAnet:pollux!papa@oberon.usc.edu "There's Alpha, Beta, Gamma and Diga!" -- Leo Schwab [quoting Rick Unland] -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
cmcmanis%pepper@Sun.COM (Chuck McManis) (05/06/89)
In article <6342@ardent.UUCP> rap@rap.ardent.com (Rob Peck) writes: > ... Suggest that each task pass a pointer to a data >structure of some kind similar to this: You were doing great up until right here. Having designed a file requester from scratch I thought about many of the same issues. The point I kept coming back to was : Q) What does a file requester replace ? A) A text exchange between user/program which requests a a filename and returns it. This is a very simple operation. And to be effective should stay simple. Generally, some guidelines I had considered when looking at this : o Colors/Layout - There are two choices here, Tool Compatibile so that the requester has the same "look" as the rest of the tool, or User Preferred which is set up via some preferences mechanisim. The second case implies an out of band interface to the users preferences. o No clicking/sliding required. What we are replacing is : "enter filename :" with a sophisticated file selection` service. We shouldn't lose sight of the fact that this original technique was quite functional. o No worries about resource/directory/memory tracking. Let the requester worry about that for me. My ideal interface is : FileLock = Request("Prompt", DirLock, Access_mode); Everything else should be handled inside the requester. --Chuck McManis uucp: {anywhere}!sun!cmcmanis BIX: cmcmanis ARPAnet: cmcmanis@sun.com These opinions are my own and no one elses, but you knew that didn't you. "A most excellent barbarian ... Genghis Kahn!"
peter@sugar.hackercorp.com (Peter da Silva) (05/08/89)
In article <103440@sun.Eng.Sun.COM>, cmcmanis%pepper@Sun.COM (Chuck McManis) writes: > This is a very simple operation. And to be effective should stay simple. > FileLock = Request("Prompt", DirLock, Access_mode); Too complex. What if I want a file name? What if I want to open it later? How about handling overwritten/nonexistent files? Status = Request(Title, DirectoryLock, Buffer) Buffer should be initialised to the default file name, so you can provide a hint. Also, it's sometimes useful to provide a pattern: Status = Request(Title, Pattern, DirectoryLock, Buffer); -- Peter "Have you hugged your wolf today" da Silva `-_-' ...texbell!sugar!peter, or peter@sugar.hackercorp.com 'U`
rap@rap.ardent.com (Rob Peck) (05/09/89)
While at the Amy Forum in Dallas yesterday, I mentioned file requesters to a few folks and received another few ideas, among them was to have the requester implement a keyboard shortcut as well as the other stuff I had suggested earlier. Also, have pattern matching of sorts, so as to show only particular kinds (or NOT show) of files. E.G. don't list the .info files and remember this next time. So, for example, if string-gadget for file name or for path-name is NOT active, interpret keyboard entries as the first, second etc character of the file we wanna find and have the file listing jump to put the selected file name at the top of the (alphabetical) list of files that become selectable. For the other case, setting file requester preferences would enable or disable the pattern matching to a user's specs. Re Chuck's comment about having the file requester manage everything, thereby keeping the program simple... that is exactly what I WAS proposing, but with the re-entrant approach, give the program the OPPORTUNITY to receive pointers to these lists of files and the controlling structure THAT THE FILE REQUESTER ITSELF creates and destroys for you, and USES when you pass that pointer to it. Maybe I did not make that point clear enough in the original posting. And if one makes the file requester code a part of a sharable (reentrant) library, the function "malloc" could be used to allocate these buffers in the first place so that the user code need never even "free" the buffers on exit since this is usually done when a program exists anyhow. Of course it is not good programming practice but if one forgets to tell the file requester to deallocate all of the cached file buffers, if the filereq.library used malloc, it should not cause any problems. Rob Peck
shf@well.UUCP (Stuart H. Ferguson) (05/09/89)
+-- peter@sugar.hackercorp.com (Peter da Silva) writes: | In article <>, cmcmanis%pepper@Sun.COM (Chuck McManis) writes: | > This is a very simple operation. And to be effective should stay simple. | > FileLock = Request("Prompt", DirLock, Access_mode); | | Too complex. What if I want a file name? What if I want to open it later? | How about handling overwritten/nonexistent files? [...] | Status = Request(Title, Pattern, DirectoryLock, Buffer); What if I want a LIST of files? Like, open a requester and let the user select a whole bunch then say OK and crunch on them in sequence. Is a filename equivalent to a lock? A lock would have the advantage that the file won't go away while you're waiting to process it, but a name would have the advantage that you could handle the exceptions yourself. What's the tradeoff here? -- Stuart Ferguson (shf@well.UUCP) Action by HAVOC
new@udel.EDU (Darren New) (05/10/89)
In article <11584@well.UUCP> shf@well.UUCP (Stuart H. Ferguson) writes: >Is a filename equivalent to a lock? A lock would have the advantage that >the file won't go away while you're waiting to process it, but a name >would have the advantage that you could handle the exceptions yourself. >What's the tradeoff here? One obvious problem with returning a Lock is that the file must exist for you to lock it. If I want a "Save File" requester, this is clearly unacceptable. Possibly yet another flag to indicate whether locks or names should be returned is appropriate, given that we are building the Ultimate File Requester (tm). -- Darren
reynaldo@athena.mit.edu (Reynaldo Villareal) (05/10/89)
******************************************************************************* * Why be nice when you look good - Me Nice guys are the doormat of the * * of the world. * *******************************************************************************
elg@killer.Dallas.TX.US (Eric Green) (05/11/89)
in article <6374@ardent.UUCP>, rap@rap.ardent.com (Rob Peck) says: [lots of stuff about file requesters... then:] > clear enough in the original posting. And if one makes the file > requester code a part of a sharable (reentrant) library, the function > "malloc" could be used to allocate these buffers in the first place > so that the user code need never even "free" the buffers on exit > since this is usually done when a program exists anyhow. Of course Uh, Rob, slight problem here. "malloc" works somewhat like the Intuition function "AllocRemember", i.e., it calls AllocMem and then adds an entry into its memory list. The pointer to its memory list is in the program's static memory, and the address of that pointer is hard-wired into "malloc" and "exit" at link time. A shared library's copy of "malloc" will thus have a different RememberList than the program's copy of "malloc"... meaning that when the program's copy of Exit goes and cleans up the RememberList, it will only clean up the stuff allocated by the program's copy of "malloc", not by the shared library's. What this means is that any call to malloc will have to be done in the link library/calling program, not in the shared library. No big deal, really... just put a wrapper around it. As far as the programmer's concerned, he's just calling "FileRequest" with a bunch of parameters (or maybe a struct, considering that's what most Amiga OS functions expect ;-) The fact that his wrapper is malloc'ing the needed buffers shouldn't be something he should worry about (unless he has already allocated his own buffers and doesn't want the "malloc" routine linked into his program....). -- | // Eric Lee Green P.O. Box 92191, Lafayette, LA 70509 | | // ..!{ames,decwrl,mit-eddie,osu-cis}!killer!elg (318)989-9849 | | // Join the Church of HAL, and worship at the altar of all computers | |\X/ with three-letter names (e.g. IBM and DEC). White lab coats optional.|
rap@rap.ardent.com (Rob Peck) (05/12/89)
In article <8077@killer.Dallas.TX.US> elg@killer.Dallas.TX.US (Eric Green) writes: >in article <6374@ardent.UUCP>, rap@rap.ardent.com (Rob Peck) says: >[lots of stuff about file requesters... then:] > >> clear enough in the original posting. And if one makes the file >> requester code a part of a sharable (reentrant) library, the function >> "malloc" could be used to allocate these buffers in the first place > >Uh, Rob, slight problem here. "malloc" works somewhat like the >Intuition function "AllocRemember", i.e., it calls AllocMem and then >adds an entry into its memory list. The pointer to its memory list is >in the program's static memory, and the address of that pointer is >hard-wired into "malloc" and "exit" at link time. A shared library's >copy of "malloc" will thus have a different RememberList than the >program's copy of "malloc"... meaning that when the program's copy of OK, thanks for the feedback. I guess the best thing to suggest, (based on my original posting then, with the data structure, would be to add to that structure an AllocRemember base pointer and INSIST that the user call the file requester one last time to clean up for every file directory that be cached. Sounds reasonable. To all who replied, directly or via the net, thanks for the info about the actual implementation of malloc. If the Amiga ROM had malloc built in and could tell which task did each allocation (bigger memlists, eh?) then as a task exited, the UnloadSeg or something could walk the internal malloc lists looking to free everything associated with a particular task. But with the malloc code in its current state, as described above, and linked into the file-requester code, it would not be reentrant and would indeed cause problems. Hmm, maybe if we make it a full process instead of a shared library, and then REZ it (instead of RESIDENT), we have yet another way to solve the single global pointer malloc problem... REZ is (Jim Goodnow's equivalent of RESIDENT, but done differently. Each incarnation of the program would get its own private data segment, thereby providing a local copy of what woulda been a global pointer. Yet another way to go perhaps. Rob Peck
jdow@gryphon.COM (J. Dow) (05/12/89)
In article <17044@usc.edu> papa@pollux.usc.edu (Marco Papa) writes: >The RJ Mical file requester seems to implement all of your requsted features >(caching, leaving pointer fixed among separate invocations). One thing that I >really don't like (for example) of the new Arp1.3 file requester is the fact >that each time I the programs call it, it recomputes the list of files >again. Is this an inherent flaw of the file requester or of the application >program that uses it? > >-- Marco Papa 'Doc' >BTW, the RJ mical file requster is not reentrant but can be "multiply" >instantiated. >-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= >uucp:...!pollux!papa BIX:papa ARPAnet:pollux!papa@oberon.usc.edu > "There's Alpha, Beta, Gamma and Diga!" -- Leo Schwab [quoting Rick Unland] >-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= I have been using ATALK3 of late for some modeming work. Alas it uses the RJMical file requester. It drives me to distraction with its asumptions, behavior, and very small size. Other than that it is "cute". I much prefer the ARP file requester and others that are generally laid out similarly. -- Sometimes a bird in the hand leaves a sticky deposit. Perhaps it were best it remain there in the bush with the other one. {@_@} jdow on bix (where else?) Sometimes the dragon wins. Sometimes jdow@gryphon.CTS.COM the knight. Does the fair maiden ever {backbone}!gryphon!jdow win? Surely both the knight and dragon stink. Maybe the maiden should suicide? Better yet - she should get an Amiga and quit playing with dragons and knights.
peter@sugar.hackercorp.com (Peter da Silva) (05/12/89)
In article <11584@well.UUCP>, shf@well.UUCP (Stuart H. Ferguson) writes: > +-- peter@sugar.hackercorp.com (Peter da Silva) writes: > | In article <>, cmcmanis%pepper@Sun.COM (Chuck McManis) writes: > | > This is a very simple operation. And to be effective should stay simple. > | > FileLock = Request("Prompt", DirLock, Access_mode); > | Too complex. What if I want a file name? What if I want to open it later? > | How about handling overwritten/nonexistent files? > | Status = Request(Title, Pattern, DirectoryLock, Buffer); > What if I want a LIST of files? Like, open a requester and let the user > select a whole bunch then say OK and crunch on them in sequence. You can use my InstantApplication tool, which works something like: Status = Instant(Title, Pattern, DirectoryLock, Buffer, Funclist); Where FuncList looks something like: struct { int (*Function)(); char *Tag; } FuncList[]; And it provides a menu and lets the user can select files and pass them to your functions. A very early version of what became Browser. [ locks versus names ] What Browser uses internally, by the way, is a WBArg structure containing a lock and a pointer to a filename in the directory referred to by that lock. This gives you the best of both worlds. -- Peter "Have you hugged your wolf today" da Silva `-_-' ...texbell!sugar!peter, or peter@sugar.hackercorp.com 'U`
dillon@HERMES.BERKELEY.EDU (Matt Dillon) (05/13/89)
Should one return a lock or list of locks for the selected files or just the filename? What happens when somebody selects a file that does not exist yet? ... Obviously a list of names should be returned... -Matt