home *** CD-ROM | disk | FTP | other *** search
- /*
- ***************************************************************************
- *
- * Datei:
- * RSysAction.c
- *
- * Inhalt:
- * void BuildActionList(void);
- * int StartAction(int ftype, char *file, short last);
- *
- * Bemerkungen:
- * Actioning-Routinen von RSys. Wird ein Icon auf das AppIcon von
- * RSys gezogen, werden entsprechend des Dateityps Aktionen
- * gestartet.
- *
- * Erstellungsdatum:
- * 07-Jan-93 Rolf Böhme
- *
- * Änderungen:
- * 07-Jan-93 Rolf Böhme Erstellung
- *
- ***************************************************************************
- */
-
- #include "RSysDebug.h"
- #include "RSysFunc.h"
-
- /*
- * Der Zeiger auf alle Actions, die aus der Datei
- * sys.act eingelesen werden.
- */
- struct _acts *Actions;
-
- /*
- * Die Liste aller gelesenen Aktionen.
- */
- struct List ActionList,
- DisplayList;
- /*
- * Ein globaler Zähler für die eingelesenen Aktionen.
- */
- int counter;
- /*
- * Liste aller Aktionen zu einem Dateityp.
- */
- struct List DL;
-
- /*
- * Die Intuition-Objekte für den Aufbau des
- * "Auswahl-Fensters der Aktionen".
- */
- static struct Window *ActionWnd = NULL;
- static struct Gadget *ActionGList = NULL;
- static struct Gadget *ActionGadgets[4];
- static UWORD ActionLeft = 211;
- static UWORD ActionTop = 43;
- static UWORD ActionWidth = 149;
- static UWORD ActionHeight;
- static UBYTE ActionWdt[14] = (UBYTE *) "Action";
-
- /*
- * Die Funktion OpenActionWindow() öffnet ein Fenster
- * mit einem ListView und zwei Gadgets. Im ListView
- * werden die Aktionen zu einem erkannten Dateitypen
- * angezeigt. Werden mehrere Dateien behandelt, so
- * erscheint ein weiteres Gadget, mit dem man zur
- * nächsten Datei wechseln kann.
- */
- static long
- OpenActionWindow(struct List *AL, BOOL last)
- {
- struct NewGadget ng;
- struct Gadget *g;
- UWORD wleft = ActionLeft,
- wtop = ActionTop,
- ww,
- wh;
- int gl[] = {GD_FileTypeTGad,GD_ActionLV};
-
- /*
- * Die Höhe des Fensters wird entsprechend der
- * Gadgetanzahl bestimmt. Ist last TRUE, gibt es nur
- * drei Gadgets, sonst vier.
- */
- ActionHeight = (last ? 92 : 108);
-
- /*
- * Der Font wird für das neue Fenster festgelegt. Ist
- * der Font zu groß, wird automatisch topaz 8
- * genommen.
- */
- ComputeFont(Scr,ActionWidth, ActionHeight);
-
- /*
- * Die Höhe und Weite des Fensters wird fontsensitiv
- * bestimmt.
- */
- ww = compute((UWORD) 0, FontX, (int)ActionWidth);
- wh = compute((UWORD) 0, FontY, (int)ActionHeight);
-
- if ((wleft + ww + OffX + Scr->WBorRight) > Scr->Width)
- wleft = Scr->Width - ww;
- if ((wtop + wh + OffY + Scr->WBorBottom) > Scr->Height)
- wtop = Scr->Height - wh;
-
- ww = compute((UWORD) (OffX + Scr->WBorRight), FontX, (int)ActionWidth);
- wh = compute((UWORD) (OffY + Scr->WBorBottom), FontY, (int)ActionHeight);
-
- /*
- * Das Fenster wird zentriert auf den aktiven Screen
- * gebracht.
- */
- CenterWindow(Scr, &wtop, &wleft, ww, wh);
-
- /*
- * Der Gadtools-Kontext dr Benutzeroberfläche wird
- * erzeugt.
- */
- if (NOT(g = CreateContext(&ActionGList)))
- return (1L);
-
- /*
- * Der Reihe nach werden alle Gadgets des Fensters
- * erzeugt und in den Kontext eingebunden. Dabei
- * werden pro Gadget nur die Werte verändert, die
- * sich gegenüber dem vorhergehenden gändert haben.
- */
- ng.ng_LeftEdge = compute(OffX, FontX, 4);
- ng.ng_TopEdge = compute(OffY, FontY, 1);
- ng.ng_Width = compute((UWORD) 0, FontX, 141);
- ng.ng_Height = compute((UWORD) 0, FontY, 15);
- ng.ng_GadgetText = NULL;
- ng.ng_TextAttr = Font;
- ng.ng_GadgetID = GD_FileTypeTGad;
- ng.ng_Flags = 0;
- ng.ng_VisualInfo = VisualInfo;
-
- g = CreateGadget(TEXT_KIND, g, &ng, GTTX_Text, NULL, GTTX_Border, TRUE, TAG_DONE);
-
- ActionGadgets[0] = g;
-
- ng.ng_TopEdge = compute(OffY, FontY, 17);
- ng.ng_Height = compute((UWORD) 0, FontY, 60);
- ng.ng_GadgetID = GD_ActionLV;
-
- g = CreateGadget(LISTVIEW_KIND, g, &ng, GTLV_Labels, AL, TAG_DONE);
-
- ActionGadgets[1] = g;
-
- ng.ng_TopEdge = compute(OffY, FontY, 78);
- ng.ng_Height = compute((UWORD) 0, FontY, 13);
- ng.ng_GadgetText = (UBYTE *) "_Info";
- ng.ng_GadgetID = GD_FInfo;
- ng.ng_Flags = PLACETEXT_IN;
-
- g = CreateGadget(BUTTON_KIND, g, &ng, GT_Underscore, '_', TAG_DONE);
-
- ActionGadgets[2] = g;
-
- /*
- * Falls es sich nicht um die letzte Datei handelt,
- * wird ein weiteres Gadget eingebunden.
- */
- if (NOT(last))
- {
- ng.ng_TopEdge = compute(OffY, FontY, 92);
- ng.ng_GadgetText = (UBYTE *) "Next Entry";
- ng.ng_GadgetID = GD_NextEntryGad;
-
- g = CreateGadget(BUTTON_KIND, g, &ng, TAG_DONE);
-
- ActionGadgets[3] = g;
- }
-
- if (NOT g)
- return (2L);
-
- /*
- * Das Fenster wird mit den entsprechenden
- * Attributen versehen geöffnet.
- */
- if (NOT(ActionWnd = OpenWindowTags(NULL,
- WA_Left, wleft,
- WA_Top, wtop,
- WA_Width, ww,
- WA_Height, wh,
- WA_IDCMP, TEXTIDCMP | LISTVIEWIDCMP |
- IDCMP_MOUSEBUTTONS | IDCMP_MOUSEMOVE |
- IDCMP_CLOSEWINDOW |
- IDCMP_REFRESHWINDOW | VANILLAKEY,
- WA_Flags, WFLG_DRAGBAR | WFLG_DEPTHGADGET |
- WFLG_CLOSEGADGET | WFLG_SMART_REFRESH |
- WFLG_RMBTRAP | WFLG_ACTIVATE,
- WA_Gadgets, ActionGList,
- WA_Title, ActionWdt,
- WA_PubScreenName, (UBYTE *)"Workbench",
- TAG_DONE)))
- return (4L);
-
- RefreshRastPort(ActionWnd,ActionGadgets,gl, 2);
-
- if(Flags.autofront)
- {
- WindowToFront(ActionWnd);
- ActivateWindow(ActionWnd);
- }
-
-
- return (NULL);
- }
-
- /*
- * Diese Procedure erzeugt ein Listenelement in der
- * Aktionsliste. Dazu wird eine eingelesene Zeile mit
- * der C-Library-Funktion strtok() in einzelne Teile
- * zerlegt, die durch ein '#' getrennt sind.
- */
- static void
- BuildActionEntry(UBYTE * line, struct _acts *Act)
- {
- /*
- * Die Token für den weiteren Duchlauf
- * initialisieren.
- */
- char *token = strtok((char *)line, ACTION_TOKEN);
-
- /*
- * Der Listenknoten wird gemäß der C=-Richtlinien
- * initialisiert.
- */
- Act->act_Node.ln_Pri = 0;
- Act->act_Node.ln_Type = NT_USER;
- Act->act_Node.ln_Name = Act->act_name;
-
- /*
- * Das erste Token enthält die Dateitypnummer des
- * entsprechenden Eintrags, die auch der intern
- * verwendeten Nummer entspricht.
- */
- Act->act_filetype = atoi(token);
-
- /*
- * Dieses Token enthält den Dateityp als String, der
- * in dem Textgadget über dem ListView erscheint.
- */
- token = strtok(STRINGEND, ACTION_TOKEN);
- strcpy(Act->act_listviewheader, token);
-
- /*
- * Dieser Token enthält die Aktionsbezeichnung, die
- * in dem ListView angezeigt wird.
- */
- token = strtok(STRINGEND, ACTION_TOKEN);
- strcpy(Act->act_name, token);
-
- /*
- * Dieser Token enthält die Aktion, die nach der
- * Anwahl des entsprechenden ListView-Eintrags
- * ausgeführt wird.
- */
- token = strtok(STRINGEND, ACTION_TOKEN);
- strcpy(Act->act_command, token);
-
- /*
- * Das Prioritätsfeld des Knotens in der
- * Actions-Struktur mißbrauchen wir als Flag, das
- * festlegt, ob nach dieser Aktion das Action-Fenster
- * geschlossen werden soll oder nicht.
- */
- token = strtok(STRINGEND, ACTION_TOKEN);
- Act->act_Node.ln_Pri = (*token == 'W') ? 1 : 0;
-
- return;
- }
-
- /*
- * Die Funktion BuildActionList() holt aus der
- * Environmentvariablen SYSACTION die
- * Bezeichnung der Datei, die die Aktionen für die
- * einzelnen Dateitypen enthält und baut aus den
- * Inhalten dieser Datei eine Liste auf.
- */
- void
- BuildActionList(void)
- {
- BPTR actfile;
- UBYTE actfilename[MAXFULLNAME+1];
- int i = 0;
- UBYTE line[MAXLINESIZE+1],
- *buf;
-
- DPOS;
-
- /*
- * Falls bereits zuvor die Datei gelesen und eine
- * Liste aufgebaut wurde, wird der Speicher jetzt
- * freigegeben und der Zeiger initialisiert.
- */
- MyFreeVec(Actions);
- Actions = NULL;
-
- /*
- * Die Environmentvariable SYSACTION wird gelesen und
- * die Datei geöffnet, falls die Variable korrekt
- * ausgelesen werden konnte.
- */
- if (GetVar((UBYTE *) "RSYSACTION", actfilename, MAXFULLNAME, GVF_GLOBAL_ONLY) > 0)
- if (actfile = Open(actfilename, MODE_OLDFILE))
- {
- /*
- * Der erste Eintrag in der Datei enthält die Anzahl
- * der eingetragenen Aktionen.
- */
- FGets(actfile, line, MAXLINESIZE);
- counter = atoi((char *)line);
-
- /*
- * Falls der Eintrag keine gültige Zahl war, lieferte
- * atoi() den Wert 0 zurück. In diesem Falle wird
- * das Unterprogramm mit dem Schließen der Datei und
- * einer Fehlermeldung abgebrochen.
- */
- if (!counter)
- {
- Close(actfile);
- ErrorHandle(FILE_ERR, WRONG_FAIL, NO_KILL);
- return;
- }
-
- /*
- * Für die Liste wird entsprechend der Anzahl der
- * Einträge Speicherplatz besorgt.
- */
- Actions = MyAllocVec(counter * sizeof(struct _acts),
- MEMF_ANY | MEMF_CLEAR, NO_KILL);
-
- if (Actions)
- {
- /*
- * Die Action-Liste wird aktualisiert.
- */
- NewList(&ActionList);
-
- /*
- * Die erste Zeile wird gelesen.
- */
- buf = FGets(actfile, line, MAXLINESIZE);
-
- /*
- * In dieser Zeile werden alle Aktionen eingelesen
- * und die Liste aufgebaut.
- */
- for (i = 0; (i < counter) && buf; i++)
- {
- BuildActionEntry(line, &Actions[i]);
-
- AddTail(&ActionList, &Actions[i].act_Node);
- buf = FGets(actfile, line, MAXLINESIZE);
- }
-
- /*
- * Falls ein Fehler beim Lesen auftrat oder weniger
- * Zeilen in der Datei waren, als counter angibt,
- * wird eine Fehlermeldung erzeugt.
- */
- if (!buf && IoErr())
- ErrorHandle(FILE_ERR, READ_FAIL, NO_KILL);
- }
-
- /*
- * Die Datei wird nach dem Auslesen geschlossen.
- */
- Close(actfile);
-
- return;
- }
- else
- ErrorHandle(FILE_ERR, FIND_FAIL, NO_KILL);
- else
- ErrorHandle(ENV_ERR, FIND_FAIL, NO_KILL);
-
- return;
- }
-
- /*
- * Die Prozedur ShowInfo() zeigt entsprechend des
- * Dateityps Directory, Device oder File eine Info
- * in Form eines Systemrequesters.
- */
- static void
- ShowInfo(char *file)
- {
- APTR req;
- struct objectid obj;
-
- /*
- * Das Actionwindow wird mit einem unsichtbaren
- * Requester gegen Eingaben geschützt, während die
- * Anzeige aktiv ist.
- */
- req = LockWindow(ActionWnd);
-
- /*
- * Entsprechend des letzten Zeichens der Datei wird
- * entschieden, ob es sich um ein Device, ein
- * Verzeichnis oder eine Datei handelt.
- */
- switch (file[strlen(file) - 1])
- {
- /*
- * Die Datei ist eine Disk. Auf Wunsch wird eine
- * Verzeichnisstruktur dieser Disk gezeigt.
- */
- case ':':
- if (NOT(DisplayDiskInfo(file, TRUE)))
- {
- strcpy(obj.fullname, file);
- PrintTree(&obj);
- }
- break;
-
- /*
- * Die Datei ist ein Verzeichnis. Auf Wunsch wird
- * eine Verzeichnisstruktur diese Verzeichnisses
- * gezeigt.
- */
- case '/':
- DisplayDirectoryInfo(file);
- break;
-
- /*
- * Ist jedem anderen Fall wird eine allgemeine
- * Fileinfo angezeigt. Die Routine PrintHunkStruct()
- * entscheidet außerdem, ob es ein Executable ist und
- * bietet entsprechend die Möglichkeit an, ein
- * Hunklisting zu erzeugen.
- */
- default:
- if (NOT(DisplayFileInfo(file)))
- PrintHunkStruct(file);
- break;
- }
-
- /*
- * Das Actionwindow wird wieder freigegeben.
- */
- UnlockWindow(req);
-
- return;
- }
-
- /*
- * Die Funktion StartAction() baut eine Teilliste für
- * den entsprechenden Dateitypen auf und präsentiert
- * ein Fenster mit drei oder vier Gadgets. Wenn last
- * TRUE ist, handelt es sich um die letzte oder nur
- * eine Datei. Andernfalls wurden mehrere Gadgets
- * über das AppIcon von RSys gezogen und es erscheint
- * ein viertes Gadget "Next".
- */
- int
- StartAction(int ftype, char *file, BOOL last)
- {
- register struct IntuiMessage *message;
- ULONG class,
- code;
- APTR object;
- ULONG mask;
- struct Node *node = NULL;
- struct _acts *act = NULL;
- int GID,
- cnt = 0,
- j,
- ret = TRUE,
- new;
- UBYTE *basename = FilePart((UBYTE *) file);
- UBYTE *dirname = PathPart((UBYTE *) file);
-
- DPOS;
-
- Flags.quit_action_flag = 0;
- /*
- * Initialisierung der Anzeigeliste.
- */
- NewList(&DL);
-
- /*
- * Die Actions, die dem Filetypen entsprechen, werden
- * gezählt.
- */
- for (j = 0; j < counter; j++)
- if (Actions[j].act_filetype == ftype)
- cnt++;
-
- /*
- * Falls Actionen gefunden wurden...
- */
- if(cnt)
- {
- /*
- * ...wird entsprechend Speicher besorgt.
- */
- act = MyAllocVec((cnt+1) * sizeof(struct _acts),
- MEMF_CLEAR | MEMF_ANY, NO_KILL);
-
- /*
- * Das Unterprogramm wird verlassen, falls nicht
- * genügend Speicher reserviert werden konnte.
- */
- if (NOT(act))
- return (FALSE);
-
- /*
- * Der Zähler für die Teilliste wird initialisiert.
- */
- new = 0;
-
- /*
- * Die neue Displayliste wird aufgebaut und die
- * Einträge gezählt.
- */
- for (j = 0; (j < counter) && (new < cnt); j++)
- if (Actions[j].act_filetype == ftype)
- {
- CopyMem((APTR) & Actions[j], (APTR) & act[new], sizeof(struct _acts));
- AddTail(&DL, &act[new++].act_Node);
- }
- }
-
- /*
- * Falls die Datei kein Verzeichnis ist, wird für den
- * Windowtitle der Basisname der Datei gebildet, also
- * Filename ohne Pfad.
- */
- if (ftype != TYPE_DIR)
- strncpy((char *)ActionWdt, (char *)basename, 13);
- else
- {
- /*
- * Falls es ein Verzeichnis ist, werden maximal 13
- * Zeichen des Strings für die Titelzeile kopiert.
- */
- int dirlen = MIN(13, ((char *)dirname - (char *)file));
-
- strncpy((char *)ActionWdt, (char *)file, dirlen);
-
- ActionWdt[dirlen] = STRINGEND;
- }
-
- /*
- * Die Bildschirmattribute werden bestimmt und das
- * Actionwindow geöffnet.
- */
- if (!SetupScreen() && !OpenActionWindow(&DL, last))
- {
- /*
- * Der Dateityp wird in das Textgadget eingetragen.
- */
- GT_SetGadgetAttrs(ActionGadgets[GD_FileTypeTGad], ActionWnd,
- NULL,
- GTTX_Text, mess[ftype],
- TAG_DONE);
-
- do
- {
- /*
- * Es wird auf ein ^C oder ein Signal vom
- * Actionwindow gewartet.
- */
- mask = Wait(SIGBREAKF_CTRL_C |
- (1L << ActionWnd->UserPort->mp_SigBit));
-
- /*
- * Falls ein ^C erkannt wurde, wird das Actioning
- * beendet.
- */
- if (mask & SIGBREAKF_CTRL_C)
- Flags.quit_action_flag = 1;
-
- /*
- * Es ist eine Nachricht am Userport des
- * Actionwindows eingetroffen.
- */
- if (mask & (1L << ActionWnd->UserPort->mp_SigBit))
- while ((message = (struct IntuiMessage *)
- GT_GetIMsg(ActionWnd->UserPort)) != NULL)
- {
- /*
- * Die notwendigen Daten werden aus der
- * Message-Struktur kopiert.
- */
- object = message->IAddress;
- class = message->Class;
- code = message->Code;
-
- /*
- * Damit Intuition nicht wartet, wird die Nachricht
- * sofort beantwortet.
- */
- GT_ReplyIMsg(message);
-
- switch(class)
- {
- /*
- * Falls ein angeklicktes Gadget losgelassen wurde,
- * wird entsprechend der GadgetID eine Aktion
- * gestartet.
- */
- case IDCMP_GADGETUP:
- GID = ((struct Gadget *)object)->GadgetID;
- switch(GID)
- {
- /*
- * Falls es sich nicht um die letzte Datei handelt,
- * wird das Unterprogramm beendet, wenn das
- * "Next"-Gadget geklickt wird.
- */
- case GD_NextEntryGad:
- if (NOT(last))
- {
- Flags.quit_action_flag = 1;
- node = NULL;
- }
- break;
-
- /*
- * Falls das "Info"-Gadget geklickt wurde, wird eine
- * Info in Form eines Systemrequesters angezeigt.
- * Falls es zu diesem Dateityp keine Aktionen gibt,
- * die Liste DL also leer ist, wird das Unterprogramm
- * beendet. Zuvor wird dann der MessagePort des
- * ActionWindows geleert.
- */
- case GD_FInfo:
- ShowInfo(file);
- node = NULL;
-
- if(IsListEmpty(&DL))
- {
- ClearIntuiMsgPort(ActionWnd);
- Flags.quit_action_flag = 1;
- }
- break;
-
- /*
- * Wenn das ListView angeklickt wurde, wird der
- * angeklickte Eintrag bestimmt, das assozierte
- * Action command ausgeführt und das Unterprogramm
- * zum Beenden vorbereitet, falls nach Aktion das
- * Fenster geschlossen werden soll.
- */
- case GD_ActionLV:
- if (node = GetNode(&DL, code))
- Command(node, file);
-
- if(node->ln_Pri == 0)
- {
- ClearIntuiMsgPort(ActionWnd);
- Flags.quit_action_flag = 1;
- }
- else
- node = NULL;
- break;
- }
- break;
-
- /*
- * Falls eine Taste betätigt wurde, wird diese
- * ermittelt und verarbeitet.
- */
- case IDCMP_VANILLAKEY:
- switch(code)
- {
- /*
- * Diese Tasten entsprechen dem Anklicken des
- * "Info"-Gadgets.
- */
- case 'i':
- case 'I':
- ShowInfo(file);
- node = NULL;
- break;
-
- /*
- * Diese Tasten entsprechen dem Anklicken des
- * Closegadgets des Action windows..
- */
- case '\33':
- Flags.quit_action_flag = 1;
- ret = FALSE;
- node = NULL;
- break;
- }
- break;
-
- /*
- * Das Fenster wird zum Beenden des Unterprogrammes
- * vorbereitet.
- */
- case IDCMP_CLOSEWINDOW:
- Flags.quit_action_flag = 1;
- ret = FALSE;
- node = NULL;
- break;
- }
- }
- }
- while (NOT(Flags.quit_action_flag));
-
- /*
- * Das Action window wird geschlossen und der
- * PublicScreen freigegeben.
- */
- CloseASysWindow(&ActionWnd, &ActionGList, NULL);
- CloseDownScreen();
- }
- else
- ErrorHandle(WINDOW_ERR, OPEN_FAIL, NO_KILL);
-
- /*
- * Der Speicher, der für die Liste der Aktionen
- * angelegt wurde, wird freigegeben.
- */
- MyFreeVec(act);
-
- return (ret);
- }
-
-