home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
M.u.C.S. Disc 2000
/
MUCS2000.iso
/
anwend
/
bkite213
/
develop_
/
bsp_fslx.c
< prev
next >
Wrap
C/C++ Source or Header
|
1998-04-11
|
17KB
|
719 lines
/*
* Beispiel-Programm zur Benutzung der FSLX-Schnittstelle mit BoxKite
* unter TOS/MiNT/MultiTOS/MagiC/MagiC Mac/N.AES
* (c) Harald Becker, 30.3.1998. Übersetzt mit Pure C und DEFAULT.PRJ.
*/
#include <aes.h>
#include <vdi.h>
#include <tos.h>
#include <string.h>
#include <stdlib.h>
#include <stdio.h>
/* Sortiermodi */
#define SORTBYNAME 0
#define SORTBYDATE 1
#define SORTBYSIZE 2
#define SORTBYTYPE 3
#define SORTBYNONE 4
/* Flags für Dateiauswahl */
#define DOSMODE 1
#define NFOLLOWSLKS 2
#define GETMULTI 8
/*
* In dieser Struktur erwarten die FSLX-Aufrufe die Daten
* über ein Ereignis.
*/
typedef struct
{ int mwhich;
int mx;
int my;
int mbutton;
int kstate;
int key;
int mclicks;
int reserved[9];
int msg[16];
}
EVNT;
typedef struct
{ unsigned int branch; /* Sprungbefehl um den struct herum */
unsigned long magic; /* Wert immer 'BxKt' */
unsigned int version; /* Versionsnummer: 0x200 für 2.00 */
}
BXKT_STR;
typedef struct
{ long id;
long value;
}
COOKIE;
typedef int cdecl XFSL_FILTER(char *path, char *name, XATTR *xa);
char path[256] = "";
char name[256] = "";
char alert[256];
char extlist[] = "*.*\0*.CFG\0*\0*.C\0*.H\0*.RSC\0\0";
char pathlist[] = "C:\\AUTO\\\0C:\\GEMINI2\\\0\0";
void *fsel = NULL; /* Handle der Dateiauswahlbox */
int window; /* Fensterkennung */
OBJECT contents = /* Fensterinhalt */
{ -1, -1, -1, G_BOXCHAR, 0, 0, 0x2dff11f0, 1, 1, 1, 1 };
char animate[] = "-\\|/";
char *animate_p = &animate[1];
int xdesk, ydesk, wdesk, hdesk;
/*
* Gibt die Adresse des Cookie-Jar zurück. Mit Supexec() aufrufen.
*/
long get_cookiejar(void)
{ return *((long *)0x05a0l);
}
/*
* Durchsucht den Cookie Jar nach einem cookie mit gegebener id und
* liefert dessen Wert zurück.
*/
int get_cookie(long id, long *pval)
{ long sav;
COOKIE *cookiejar;
int i = 0;
cookiejar = (COOKIE *)Supexec(get_cookiejar);
if ( cookiejar )
{ while ( cookiejar[i].id )
{ if ( cookiejar[i].id == id )
{ *pval = cookiejar[i].value;
return 1;
}
i++;
}
}
return 0;
}
/*
* Fragt das aktuelle Laufwerk und den aktuellen Pfad ab.
*/
void getpath(char *p)
{ int drv;
drv = Dgetdrv();
*p++ = drv + 'A';
*p++ = ':';
Dgetpath(p, drv);
p += strlen(p) - 1;
if ( *p != '\\' )
{ p++;
*p++ = '\\';
*p = 0;
}
}
/*
* Die folgenden vier Funktionen befassen sich nur mit dem Zeichnen
* des Fensterinhaltes. Ich denke, die Methode hat sich inzwischen
* herumgesprochen.
*/
int min(int a, int b)
{ return ( a < b ? a : b );
}
int max(int a, int b)
{ return ( a > b ? a : b );
}
int rc_intersect(GRECT *p1, GRECT *p2)
{ int tx, ty, tw, th;
tw = min(p2->g_x + p2->g_w, p1->g_x + p1->g_w);
th = min(p2->g_y + p2->g_h, p1->g_y + p1->g_h);
tx = max(p2->g_x, p1->g_x);
ty = max(p2->g_y, p1->g_y);
p2->g_x = tx;
p2->g_y = ty;
p2->g_w = tw - tx;
p2->g_h = th - ty;
return( (tw > tx) && (th > ty) );
}
void window_redraw(int handle, int x, int y, int w, int h)
{ GRECT r1, r2, world;
wind_update(BEG_UPDATE);
r2.g_x = x;
r2.g_y = y;
r2.g_w = w;
r2.g_h = h;
world.g_x = xdesk;
world.g_y = ydesk;
world.g_w = wdesk;
world.g_h = hdesk;
wind_get(handle, WF_FIRSTXYWH, &r1.g_x, &r1.g_y, &r1.g_w, &r1.g_h);
while ( r1.g_w && r1.g_h )
{ if ( rc_intersect(&world, &r1) && rc_intersect(&r2, &r1) )
objc_draw(&contents, ROOT, MAX_DEPTH, r1.g_x, r1.g_y, r1.g_w, r1.g_h);
wind_get(handle, WF_NEXTXYWH, &r1.g_x, &r1.g_y, &r1.g_w, &r1.g_h);
}
wind_update(END_UPDATE);
}
/*
* Hier stehen die Bindings der benötigten AES-Aufrufe, soweit
* sie nicht in jeder Standard-Library enthalten sind.
* Bei allen Funktionen werden die AES-Parameterfelder lokal
* deklariert; und das global[]-Feld wird als erster Parameter
* explizit übergeben. Damit sind diese Bindings multithreading-
* fähig.
* Ich wei₧, da₧ sich diese Routinen in C auch effizienter schreiben
* lie₧en. Es ging mir aber bei dieser Codierung darum, sie auch
* für jemanden lesbar zu halten, der sich mit C nicht so auskennt.
* Das folgende '#pragma' unterdrückt die Compilerwarnungen, die
* entsehen, weil (zumindest in der mir vorliegenden Version der
* PC-Header) die Struktur 'AESPB' ein bi₧chen daneben ist: 'addrin[]'
* und 'addrout[]' sind als Zeiger auf 'int' deklariert.
*/
#pragma warn -sus
void *fslx_open(int *global,
char *title,
int x, int y,
int *handle,
char *path, int pathlen,
char *fname, int fnamelen,
char *patterns,
XFSL_FILTER *filter,
char *paths,
int sort_mode,
int flags)
{ AESPB aespb;
void *addrin[6], *addrout[6];
int contrl[5], intin[16], intout[7];
aespb.contrl = contrl;
aespb.global = global;
aespb.intin = intin;
aespb.intout = intout;
aespb.addrin = addrin;
aespb.addrout = addrout;
contrl[0] = 190;
contrl[1] = 6;
contrl[2] = 1;
contrl[3] = 6;
contrl[4] = 1;
intin[0] = x;
intin[1] = y;
intin[2] = pathlen;
intin[3] = fnamelen;
intin[4] = sort_mode;
intin[5] = flags;
addrin[0] = title;
addrin[1] = path;
addrin[2] = fname;
addrin[3] = patterns;
addrin[4] = filter;
addrin[5] = paths;
_crystal(&aespb);
*handle = intout[0];
return addrout[0];
}
int fslx_evnt(int *global,
void *fsd,
EVNT *events,
char *path,
char *fname,
int *button,
int *nfiles,
int *sort_mode,
char **pattern)
{ AESPB aespb;
void *addrin[6], *addrout[6];
int contrl[5], intin[16], intout[7];
aespb.contrl = contrl;
aespb.global = global;
aespb.intin = intin;
aespb.intout = intout;
aespb.addrin = addrin;
aespb.addrout = addrout;
contrl[0] = 193;
contrl[1] = 0;
contrl[2] = 4;
contrl[3] = 4;
contrl[4] = 1;
addrin[0] = fsd;
addrin[1] = events;
addrin[2] = path;
addrin[3] = fname;
_crystal(&aespb);
*button = intout[1];
*nfiles = intout[2];
*sort_mode = intout[3];
*pattern = addrout[0];
return intout[0];
}
int fslx_close(int *global, void *fsd)
{ AESPB aespb;
void *addrin[6], *addrout[6];
int contrl[5], intin[16], intout[7];
aespb.contrl = contrl;
aespb.global = global;
aespb.intin = intin;
aespb.intout = intout;
aespb.addrin = addrin;
aespb.addrout = addrout;
contrl[0] = 191;
contrl[1] = 0;
contrl[2] = 1;
contrl[3] = 1;
contrl[4] = 0;
addrin[0] = fsd;
_crystal(&aespb);
return intout[0];
}
int fslx_getnxtfile(int *global, void *fsd, char *fname)
{ AESPB aespb;
void *addrin[6], *addrout[6];
int contrl[5], intin[16], intout[7];
aespb.contrl = contrl;
aespb.global = global;
aespb.intin = intin;
aespb.intout = intout;
aespb.addrin = addrin;
aespb.addrout = addrout;
contrl[0] = 192;
contrl[1] = 0;
contrl[2] = 1;
contrl[3] = 2;
contrl[4] = 0;
addrin[0] = fsd;
addrin[1] = fname;
_crystal(&aespb);
return intout[0];
}
void *fslx_do(int *global,
char *title,
char *path, int pathlen,
char *fname, int fnamelen,
char *patterns,
XFSL_FILTER *filter,
char *paths,
int *sort_mode,
int flags,
int *button,
int *nfiles,
char **pattern)
{ AESPB aespb;
void *addrin[6], *addrout[6];
int contrl[5], intin[16], intout[7];
aespb.contrl = contrl;
aespb.global = global;
aespb.intin = intin;
aespb.intout = intout;
aespb.addrin = addrin;
aespb.addrout = addrout;
contrl[0] = 194;
contrl[1] = 4;
contrl[2] = 4;
contrl[3] = 6;
contrl[4] = 2;
intin[0] = pathlen;
intin[1] = fnamelen;
intin[2] = *sort_mode;
intin[3] = flags;
addrin[0] = title;
addrin[1] = path;
addrin[2] = fname;
addrin[3] = patterns;
addrin[4] = filter;
addrin[5] = paths;
_crystal(&aespb);
*button = intout[1];
*nfiles = intout[2];
*sort_mode = intout[3];
*pattern = addrout[1];
return addrout[0];
}
/*
* Die folgende Routine dürfte in den meisten neueren GEM-Libraries
* schon enthalten sein.
*/
int appl_getinfo(int *global, int ap_gtype, int *ap_gout1, int *ap_gout2, int *ap_gout3, int *ap_gout4)
{ AESPB aespb;
void *addrin[6], *addrout[6];
int contrl[5], intin[16], intout[7];
aespb.contrl = contrl;
aespb.global = global;
aespb.intin = intin;
aespb.intout = intout;
aespb.addrin = addrin;
aespb.addrout = addrout;
contrl[0] = 130;
contrl[1] = 1;
contrl[2] = 5;
contrl[3] = 0;
contrl[4] = 0;
intin[0] = ap_gtype;
_crystal(&aespb);
*ap_gout1 = intout[1];
*ap_gout2 = intout[2];
*ap_gout3 = intout[3];
*ap_gout4 = intout[4];
return intout[0];
}
/*
* Die folgende Routine wird zwar im vorliegenden Demoprogramm
* nicht genutzt; sie ist der Vollständigkeit halber trotzdem
* aufgeführt.
*/
int fslx_set_flags(int *global, int flags, int *oldval)
{ AESPB aespb;
void *addrin[6], *addrout[6];
int contrl[5], intin[16], intout[7];
aespb.contrl = contrl;
aespb.global = global;
aespb.intin = intin;
aespb.intout = intout;
aespb.addrin = addrin;
aespb.addrout = addrout;
contrl[0] = 195;
contrl[1] = 2;
contrl[2] = 2;
contrl[3] = 0;
contrl[4] = 0;
intin[0] = 0;
intin[1] = flags;
_crystal(&aespb);
*oldval = intout[1];
return intout[0];
}
#pragma warn .sus
/*
* Diese Routine ruft 'appl_getinfo()' auf und prüft zuvor, ob das
* aktuelle Betriebssystem diese Routine überhaupt enthält.
* Sie benötigt ebenfalls ein korrekt initialsiertes 'global[]'-Feld.
*/
int appl_xgetinfo(int *global, int code, int *rv1, int *rv2, int *rv3, int *rv4)
{ int magx, j, aes_version;
int **value;
#define WF_WINX 22360
aes_version = global[0];
magx = ( get_cookie('MagX', (long *)&value) && value[2][24] >= 0x200 );
if ( code > 3 && !magx && aes_version <= 0x400 )
return 0;
if ( aes_version >= 0x400 || magx || wind_get(0, WF_WINX, &j, &j, &j, &j) == WF_WINX || appl_find("?AGI") == 0 )
return appl_getinfo(global, code, rv1, rv2, rv3, rv4);
return 0;
}
/*
* Diese Routine findet heraus, ob das vorhandene System die
* FSLX-Aufrufe unterstützt.
* Einziger Parameter ist ein Zeiger auf das global[]-Feld,
* der zum Ermitteln der AES-Version benötigt wird.
*/
int system_has_fslx(int *global)
{ int gout1, gout2, gout3, gout4;
BXKT_STR *value;
if ( appl_xgetinfo(global, 7, &gout1, &gout2, &gout3, &gout4) )
{ /*
* 'appl_getinfo()' mit Modus 7 aufrufen, bei Erfolg das Ergebnis
* auswerten.
*/
if ( gout1 & 8 )
return 1;
else
return 0;
}
else
{ /*
* Wenn 'appl_getinfo()' nicht geht, auf den 'HBFS'-Cookie
* zurückgreifen.
*/
if ( get_cookie('HBFS', (long *)&value) )
if ( value->magic == 'BxKt' && value->version >= 0x200 )
return 1;
}
return 0;
}
/*
* Diese Funktion bekommt die AES-Messages, die der Fileselektor übriglä₧t.
* Sie verarbeitet die Ereignisse, die für das Demofenster bestimmt sind.
*/
void message_handler(int *msg)
{ switch ( msg[0] )
{ case WM_REDRAW:
wind_get(msg[3], WF_WORKXYWH, &contents.ob_x, &contents.ob_y, &contents.ob_width, &contents.ob_height);
window_redraw(msg[3], msg[4], msg[5], msg[6], msg[7]);
break;
case WM_MOVED:
wind_set(msg[3], WF_CURRXYWH, msg[4], msg[5], msg[6], msg[7]);
break;
case WM_TOPPED:
wind_set(msg[3], WF_TOP, 0, 0, 0, 0);
break;
case WM_CLOSED:
/*
* Demofenster wird geschlossen: Alles freigeben und Programm beenden.
*/
if ( fsel != NULL )
fslx_close(_GemParBlk.global, fsel);
wind_close(msg[3]);
wind_delete(msg[3]);
appl_exit();
exit(0);
}
}
/*
* Diese Funktion verarbeitet Timer-Events und realisiert darüber
* eine 'Mini-Animation' im Hintergrundfenster
*/
void timer_handler(int window)
{ contents.ob_spec.obspec.character = *animate_p++;
if ( *animate_p == 0 )
animate_p = animate;
wind_get(window, WF_WORKXYWH, &contents.ob_x, &contents.ob_y, &contents.ob_width, &contents.ob_height);
window_redraw(window, contents.ob_x, contents.ob_y, contents.ob_width, contents.ob_height);
}
int main(void)
{ int rv, button, window, f_window, result, nfiles, sortmode, boxmode;
int msg[8], which, mx, my, kreturn, breturn, kstate;
EVNT evnt;
char *pattern;
appl_init();
wind_get(0, WF_WORKXYWH, &xdesk, &ydesk, &wdesk, &hdesk);
graf_mouse(ARROW, NULL);
Pdomain(1); /* Damit auch wirklich lange Namen rauskommen */
getpath(path);
/*
* Prüfen, ob das OS die FSLX-Aufrufe versteht.
*/
if ( system_has_fslx(_GemParBlk.global) == 0 )
{ form_alert(1, "[1][Kein kompatibler Fileselector|installiert.][ Ok ]");
appl_exit();
return 0;
}
boxmode = form_alert(1, "[2][Wie soll die Box verwaltet|werden?][ Fenster | Dialog ]");
if ( boxmode == 1 )
{ /*
* Ein Fenster neben dem Fileselector öffenen, damit man sieht,
* da₧ der Fileselektor ein echtes Applikationsfenster und kein
* lokaler Modus ist.
*/
window = wind_create(NAME | MOVER | CLOSER, xdesk, ydesk, wdesk, hdesk);
if ( window < 0 )
{ form_alert(1, "[1][Das Fenster klemmt mal wieder!][ Ok ]");
appl_exit();
return 0;
}
wind_set(window, WF_NAME, "Noch'n Fenster");
wind_open(window, xdesk + 50, ydesk + 50, 300, 200);
window_redraw(window, xdesk, ydesk, wdesk, hdesk);
fsel = fslx_open(
_GemParBlk.global,
"BoxKite",
-1,-1,
&f_window,
path, 258,
name, 258,
extlist, /* ext list */
0L, /* no filter */
pathlist, /* path list */
SORTBYDATE,
GETMULTI);
if ( fsel == NULL )
form_alert(1, "[3][Der Fileselector lä₧t sich|nicht öffnen!][ Ok ]");
/*
* Hier beginnt die Hauptschleife. Sie wird auch dann betreten, wenn
* der Fileselektor sich nicht öffnen lä₧t. Das Programm wird beendet,
* wenn das Hintergrundfenster geschlossen wird.
*/
do
{ which = evnt_multi(MU_KEYBD | MU_BUTTON | MU_MESAG | MU_TIMER,
2, 1, 1,
0, 0, 0, 0, 0,
0, 0, 0, 0, 0,
msg,
500, 0,
&mx, &my, &button,
&kstate, &kreturn, &breturn);
if ( fsel != NULL )
{ /*
* Wenn wir einen offenen Fileselektor haben,
* dann bekommt der jedes Ereignis zuerst.
*/
evnt.mwhich = which;
evnt.mx = mx;
evnt.my = my;
evnt.mbutton = button;
evnt.kstate = kstate;
evnt.key = kreturn;
evnt.mclicks = breturn;
memcpy(evnt.msg, msg, 16);
result = fslx_evnt(
_GemParBlk.global,
fsel,
&evnt,
path,
name,
&button,
&nfiles,
&sortmode,
&pattern);
if ( result == 0 )
{ /*
* Ein Returncode von 0 an dieser Stelle bedeutet, da₧
* der Fileselektor beendet wurde und die evtl. gewählten
* Dateien verarbeitet werden müssen.
*/
if ( button == 0 )
form_alert(1, "[3][ Dialog abgebochen.][ Ok ]");
else
{ sprintf(alert, "[2][ Anzahl: %d | Sortmode: %d | Muster: %s | Auswahl: %s ][ Ok ]", nfiles, sortmode, pattern, name);
form_alert(1, alert);
while ( --nfiles )
{ fslx_getnxtfile(_GemParBlk.global, fsel, name);
sprintf(alert, "[2][ Auswahl: %s ][ Ok ]", name);
form_alert(1, alert);
}
}
fslx_close(_GemParBlk.global, fsel);
fsel = NULL;
}
/*
* Da 'fslx_evnt()' die Bits der verarbeiteten Events aus
* 'evnt.mwhich' löscht, mu₧ dieser modifizierte Wert weiter
* analysiert werden.
*/
which = evnt.mwhich;
}
/*
* Hier werden endlich die Ereignisse, die der Fileselektor
* übriggelassen hat, vom Programm selbst verarbeitet.
*/
if ( which & MU_MESAG )
message_handler(msg);
if ( which & MU_TIMER )
timer_handler(window);
}
while ( 1 );
}
else
{ /*
* In diesem Zweig wird der Fileselektor als modaler
* Dialog über 'fslx_do()' aufgerufen.
*/
sortmode = SORTBYDATE;
fsel = fslx_do(
_GemParBlk.global,
"BoxKite",
path, 258,
name, 258,
extlist, /* ext list */
0L, /* no filter */
pathlist, /* path list */
&sortmode,
GETMULTI,
&button,
&nfiles,
&pattern
);
if ( fsel == NULL )
form_alert(1, "[3][Der Fileselector lä₧t sich|nicht öffnen!][ Ok ]");
else
{ if ( button == 0 )
form_alert(1, "[3][ Dialog abgebochen.][ Ok ]");
else
{ sprintf(alert, "[2][ Anzahl: %d | Sortmode: %d | Muster: %s | Auswahl: %s ][ Ok ]", nfiles, sortmode, pattern, name);
form_alert(1, alert);
while ( --nfiles )
{ fslx_getnxtfile(_GemParBlk.global, fsel, name);
sprintf(alert, "[2][ Auswahl: %s ][ Ok ]", name);
form_alert(1, alert);
}
}
fslx_close(_GemParBlk.global, fsel);
}
}
appl_exit();
return 0;
}