Dokumentation zu "FileRequest" Modul zum Aufbau von Dateiauswahl-Requestern Autor: Nicolas Benezan, Postwiesenstr. 2, D7000 Stuttgart 60 ---------------------------------------------------------------------- Das Paket FileRequest --------------------- folgende Dateien gehören zum Modul FileRequest V1.0: * FileRequest.def * FileRequest.mod * FileReqTest * FileRequest.dok * LiesMich© Bitte beachten Sie die Kopierrecht-Hinweise in "LiseMich©" Einleitung ---------- Kein professionelles Programm kommt heute noch ohne Dateiauswahl- Requester aus. Sie ermöglchen eine sehr viel bequemere Auswahl von Projekten, Verzeichnissen, und Dateien als dies mit dem simplen Eintippen von Pfad und Dateiname möglich wäre. Der Requester soll also dem Benutzer einen möglichst bequemen Umgang mit dem FileSystem, der Verzeichnishirarchie und den verschie- denen Geräten bereitstellen. Das hier vorgestellte Modul unterstützt solche Requester. Dem Modula-2- Programmierer werden damit Prozeduren zur Verfügung gestellt, die einerseits eine einfache Implementierung eines solchen Requesters ermöglichen, andererseits aber auch große Flexibilität besitzen. * Ohne das Implementationsmodul ändern zu müssen können Größe und Position des Requesters und der Gadgets verändert werden. Es können sogar Gadgets hinzugefügt oder weggelassen werden. * Der Requester schreibt keine bestimmte Gerätekonfiguration vor (zB. bekanntes DH0:/JH0:-Problem), sondern erkennt alle angeschlossenen Geräte bzw. alle eingelegten Disketten selbstständig. * Alle Elemente des FileRequesters können auch direkt in einem Window liegen (also ohne einen eigentlichen Intuition-Requester). Dadurch ist es möglich, während der Dateiauswahl auch noch andere Gadgets und sogar Menus zu bearbeiten. Außerdem kann die Größe mit dem Sizing-Gadget des Windows verändert werden. * Der Pfadname kann mit der Maus ausgewählt, mit der Tastatur einge- tippt und auch gemischt eingegeben werden. * Der Programmierer kann bestimmen, welche Dateien überhaupt angezeigt werden. Es ist zB. denkbar, daß ein Programm seine Projekte erkennt und Dateien anderer Programme gar nicht angezeigt werden sollen. * Es werden alle Bildschirmauflösungen und -tiefen sowie alle Zeichen- sätze (mit Ausname von Proportionalschrift) unterstützt. Das Programm verdaut auch die 60Zeichen/Zeile Einstellung von Preferences. * Das Programm arbeitet mit SuperLists1.3 [bne]. Die Directories werden als dynamische Liste eingelesen. Proportional- und Einzel- schritt-Scrollgadgets werden verwendet. * Prozeduren zum Speicherallozieren/deallozieren können durch Prozedur- variablen frei gewählt werden (siehe MemSystem [bne]). * Prozeduren wie zB. GetPath, ReadDeviceList und ReadDirectory können auch für andere Zwecke verwendet werden. Übersicht --------- Das Modul versucht, den Vorgang der Dateiauswahl möglichst vom Haupt- programm geheim zu halten. Dh. das Hauptprogramm muß den Auswahl- requester nur vorbereiten, die Auswahlprozedur aufrufen und bekommt dann das fertige Ergebnis (Pfad und Dateiname) präsentiert. Nur in Ausnahmefällen, zB. wenn ein Gadget geklickt wurde, das nicht zu den Standardgadgets des Moduls gehört, muß das Hauptprogramm eingreifen. Die folgende Liste zeigt die einzelnen Schritte, wie ein FileRequester programmiert wird: * Initialisieren der Gadgets * Erzeugen des Windows/Requesters * Initialisieren der SuperList * Aufruf von RequestFile() * Entfernen des Windows/Requesters Werden Sonderfunktionen gewünscht, sind auch eventuell noch folgende Dinge nötig * Handler für IDCMP-Messages, die nicht standardmäßig von FileRequest verarbeitet werden * Eine Prozedur, die aus FileInfoBlocks (siehe Dos) SuperList-Entries macht und dabei möglicherweise Dateien aussiebt Initialisieren der Gadgets -------------------------- Die Standard-Gadgets (siehe FileReqTest - Demo) werden mit InitStdGadgets() initialisiert. Dabei bedeutet ActionText: Text, der im "Ok"-Gadget stehen soll (zB. Load, Save) Requester: TRUE falls die Gadgets in einem Requester stehen sollen FALSE wenn sie zu einem Window gehören Kleine Veränderungen können nach dem Aufruf dieser Prozedur vorgenommen werden. Wer völlig andere Gadgets will, läßt InitStdGadgets aber am besten weg und initialisiert die Gadgets selbst. Dabei ist folgendes zu beachten: * Gadgets mit gleicher Funktion wie die StandarddGadgets sollen eine gleiche ID, andere Gadgets andere IDs haben (siehe CONST CancelID bis PathID) * Bei k e i n e m Gadget darf das endGadget-Flag gesetzt sein. Grund: Klickt der Benutzer sofort nach dem Erscheinen des Requesters ein endGadget an, verschwindet dieser und der zugehörige RastPort sofort in den ewigen Bitgründen. Die SuperList wird dann in den nicht existierenden RastPort aufgebaut, worüber sich der Guru freut. Leider haben die Intuition-Entwickler zwar an eine reqVerify- aber nicht an eine reqClearVerify Funktion gedacht! * Das PathGadg und BoxGadg haben einen Sonderstatus, man verändert hier besser nichts grundlegendes. Die Größe und Lage des BoxGadg und der damit verbundenen SuperList kann man mit ResizeList() ändern. Erzeugen des Windows/Requesters ------------------------------- Soll der Standard-Requester verwendet werden, wird dieser mit der Prozedur BuildRequest() erzeugt. Als Parameter werden Position und Größe übergeben (siehe StdWidth, StdHeight). Es ist zu beachten, daß der Requester ganz in das Window passen sollte, auch wenn dieses mit dem Sizing-Gadget so klein als möglich gemacht wird. Nach dem Initalisieren muß der Requester mit Request() (siehe Intuition) aktiviert werden. Es kann aber auch ein eigener oder gar kein Requester verwendet werden. Dann muß die GadgetList in den entsprechenden Requester bzw. in ein Window installiert werden. Initialisieren der SuperList ---------------------------- Auch hier gibt es wieder eine Prozedur zum Initialisieren der Standard- werte. InitList braucht als Parameter den RastPort des Requesters (Requester.reqLayer^.rp) oder des Windows (Window.rPort), falls ohne Requester gearbeitet wird. Falls Sie Position oder Größe der Liste ändern wollen, geschieht dies am besten mit ResizeList() (siehe auch CONST StdBoxLeft bis StdBoxHeight). Sonstige Änderungen sollten Sie nur vornehmen, wenn Sie sich mit dem Modul SuperLists auskennen. RequestFile() ------------- Mit dieser Prozedur wird der eigentliche Auswahlvorgang gestartet. Die Parameter haben folgende Bedeutung: Dir: enthält die FileLock-Struktur des aktuellen Directories. RequestFile beginnt die Auswahl in diesem Directory, dh. man muß sich nicht immer wieder durch die Datei- Hirarchie arbeiten, sondern kann in dem Directory beginnen, in dem man zuletzt war bzw. mit dem das Programm gestartet wurde. Wurde RequestFile TRUE beendet, enthält Dir das aus- gewählte Directory, das außerdem zum CurrentDir gemacht wurde. Dir=NIL entspricht der Geräte/Volume-Ebene. Name: enthält den ausgewählten Dateinamen (ohne Pfad), falls Requestfile TRUE beendet wurde. Der Anfangswert von Name wird bei der jetztigen Version ignoriert. Window: Zeiger auf das Window, in dem der Requester steht. RequestFile setzt während der Auswahl die von ihm benötigten IDCMPFlags, sodaß Sie sich beim öffnen des Windows keine Gedanken darüber zu machen brauchen. Der IDCMP wird zum Schluß wieder auf den alten Zustand gesetzt. Die aktuelle Version verwendet nur das IDCMPFlag gadgetUp, es können zukünftig aber auch andere Flags benutzt werden. Requester: Zeiger auf den Requester bzw. NIL, wenn die Gadgets direkt im Window stehen CreateEntry: Prozedur zum Erzeugen der Directory-Listeneinträge. Normalerweise wird hier CreateStdEntry() übergeben. Wer Sonderfunktionen wünscht, kann eine eigene Prozedur angeben (wird später noch ausführlich beschrieben). OtherMsgHandler:Prozedur, die alle IntuiMessages bearbeitet, für die sich RequestFile nicht zuständig fühlt. Dies sind gadgetUp-Messages von Gadgets anderer IDs als CancelID bis PathID und Messages anderer Classes. (siehe auch Kapitel OtherMsgHandler) Resultat:BOOLEAN ergibt TRUE, wenn die Auswahl mit dem OkGadget oder dem Eintippen eines gültigen Dateinamens und Return beendet wurde. Ergibt FALSE, wenn Cancel geklickt wurde, oder ein Fehler aufgetreten ist. Entfernen des Windows/Requesters -------------------------------- Da der endGadget-Mechanismus nicht verwendet werden kann (Erklärung siehe Kapitel Initialisieren der Gadgets), muß der Requester mit Intuition.EndRequest() entfernt werden. Falls direkt im Window gearbeitet wird, müssen die Gadgets des File- Requesters aus der GadgetList des Windows entfernt werden. Wer ganz sicher gehen will sollte auch noch IDCMP.EmptyIDCMP() durch- führen. Sonst wäre es möglich, daß noch Messages von Gadgets ankommen, die kurz vor dem Requesterabbau geklickt wurden. Andere nützliche Prozeduren --------------------------- GetPath ------- Diese Prozedur ermittelt den vollständigen Pfadnamen zu einer beliebigen FileLock-Struktur. Es sollte darauf geachtet werden, daß der Path- Parameter eine ausreichende Länge besitzt, sonst wird der Pfadnamen abgeschnitten. ReadDeviceList -------------- Liest die Dos-Device-Liste aus und schreibt sie in eine SuperList. Dabei wird unter den Eintragstypen unterschieden (Dos.DeviceListType): device: Geräte an sich (zB. DF0:, RAM:, CON:) volume: Namen von Disketten oder Festplatten (zB. WorckBench:) directory: Mit assign zugewiesene logische Geräte (zB. SYS: C:) der Parameter Types bestimmt, welche Gerätetypen gelesen werden sollen. ReadDirectory ------------- Liest ein Directory in eine SuperList. Dabei kann eine eigene Prozedur übergeben werden, die die SuperList-Einträge erzeugt. Der Parameter InsertAt bestimmt, an welcher stelle der Liste die Directory-Einträge eingefügt werden. Ist InsertAt=-1 wird am Ende angefügt, ist InsertAt=0 am Anfang. InsertAt=0 ist ein Sonderfall. Dabei wächst nämlich die Liste rückwärts, da die Einträge nacheinander an erster Stelle eingefügt werden. Bei InsertAt>0 wird nacheinander jeweils bei der nächsthöheren Position eingefügt (Liste wächst vorwärts). CreateEntry / CreateStdEntry ---------------------------- Die Prozedur CreateStdEntry dient als Standardparameter für CreateEntry bei ReadDirectory() und RequestFile(). Diese Prozedur macht folgendes: * Es wird mit SuperLists.MakeEntry() ein Eintrag alloziert und initialisiert. * Dabei wird der Name des Files im FileInfoBlock in den Eintrag einge- tragen. * Das Feld Entry.userData wird auf die Länge des Filenamens gesetzt * Je nach Typ (Directory oder File) wird das Flag "dir" oder "file" in Entry.userFlags gesetzt. Wird statt CreateStdEntry eine eigene Prozedur verwendet, muß unbedingt darauf geachtet werden, daß diese mindestens die obigen Schritte korrekt ausführt. Besonders bei der Länge des Filenamens muß beachtet werden, das selbst angehängte Bemerkungen wie zB. "(dir)" nicht mitgezählt werden. Ein Sonderfall ist jedoch erlaubt: * CreateEntry() darf einzelne Einträge seiner Wahl aussieben. In diesem Fall wird kein Eintrag erzeugt sondern NIL zurückgegeben. Das File erscheint dann nicht in der Liste. Dies kann sinnvoll sein, um zB. nur die Projekte des eigenen Tools selektierbar zu machen. Wie die Prozedur die Files unterscheidet ist ihr Bier. Die Prozedur CreateEntry() kann auch indirekt rekursiv ReadDirectory() aufrufen, um verschachtelte Directories einzulesen. OtherMsgHandler --------------- Mit dieser Prozedur kann bei RequestFile() ein Handler für Messages angegeben, die nicht standardmäßig verarbeitet werden. Dies ist dann notwendig, wenn eigene zusätzliche Gadgets oder Menus installiert werden. RequestFile() verarbeitet Messages von Gadgets mit den im Definitionsmodul angegebenen IDs, ohne das andere Module davon etwas mitbekommen. Zusätzlich wird noch eine undefinierte (implementations- und versionsabhängige) Menge von Messages ausgewertet u n d weiter- geleitet (eventuell diskInserted... ). Message, für die sich FileRequest überhaupt nicht zuständig fühlt werden sofort an OtherMsgHandler() geleitet. OtherMsgHandler() braucht sich n i c h t um den IDCMPort und ReplyMsg() kümmern sondern die Message nur auswerten.