home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
World of A1200
/
World_Of_A1200.iso
/
programs
/
monitors
/
rsys
/
source.lha
/
src
/
RSysAction.c
< prev
next >
Wrap
C/C++ Source or Header
|
1995-01-09
|
22KB
|
729 lines
/*
***************************************************************************
*
* 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);
}