home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Dream 48
/
Amiga_Dream_48.iso
/
Atari
/
c
/
wrc_1_0.lzh
/
WRC.1_0
/
WRC.C
next >
Wrap
C/C++ Source or Header
|
1992-10-04
|
11KB
|
455 lines
/*********************************************************************
*
* WRC
*
* Kurzbeschreibung:
* Modul zur Verwaltung und Bearbeitung von Rechtecklisten
*
* Versionen:
* 1.0 mo 12.08.92 Basisversion
*
* Autoren:
* mo (\/) Martin Osieka, Erbacherstr. 2, D-6100 Darmstadt
*
*********************************************************************/
#include <stddef.h>
#define MIN( a, b) ((a) <= (b) ? (a) : (b))
#define MAX( a, b) ((a) >= (b) ? (a) : (b))
#define FALSE 0
#define TRUE 1
#include <aes.h>
#if 0
#include <aesr.h>
#else
/* Nachbildung von Funktionen aus aesr.h */
extern int rc_intersect( GRECT *r1, GRECT *r2);
#define rc_set( r, x, y, w, h) \
(r)->g_x = (x); (r)->g_y = (y); (r)->g_w = (w); (r)->g_h = (h)
#define wind_rget( win, mode, r) \
wind_get( win, mode, &(r)->g_x, &(r)->g_y, &(r)->g_w, &(r)->g_h)
#define wind_gdesk( r) \
wind_rget( 0, WF_WORKXYWH, r)
#define wind_gfirst( win, r) \
wind_rget( win, WF_FIRSTXYWH, r)
#define wind_gnext( win, r) \
wind_rget( win, WF_NEXTXYWH, r)
#endif
#include <wrc.h>
/********************************************************************/
#define MAXWRS 64
static wrectS wrctable[ MAXWRS]; /* Speicherbereich fuer Rechtecke */
static wrectS *wrcfree; /* Liste freier Rechtecke */
static int wrcinit; /* TRUE: Modul ist initialisiert */
/*
| Diese Rechteckverwaltung arbeitet auf einem statischen Speicher-
| bereich, da sich bei einer zu grossen Zersplitterung der
| sichtbaren Bereiche eines Fensters Scrollen nicht mehr lohnt.
*/
/*------------------------------------------------------------------*/
void wrc_init( void)
{
wrectS *pwr;
if (!wrcinit) {
wrcinit = TRUE;
wrcfree = NULL;
for (pwr = &wrctable[ MAXWRS-1]; pwr >= wrctable; pwr--) {
pwr->next = wrcfree;
wrcfree = pwr;
};
};
} /* wrc_init */
void wrc_exit( void)
{
wrcinit = FALSE;
} /* wrc_exit */
wrectS *wrc_alloc( void)
/*
| Die Funktion liefert einen Zeiger auf eine freie Rechteck-
| beschreibung (im Fehlerfall NULL).
*/
{
wrectS *pwr;
if (!wrcinit) wrc_init();
if ((pwr = wrcfree) != NULL) {
wrcfree = pwr->next;
};
return( pwr);
} /* wrc_alloc */
void wrc_free( wrectS *pwr)
/*
| Gibt die Rechteckbeschreibung <wr> frei.
*/
{
pwr->next = wrcfree;
wrcfree = pwr;
} /* wrc_free */
wrectS *wrc_extract( wrectS *pwrprev)
/*
| Extrahiert die Rechteckbeschreibung hinter <wrprev> aus der Liste.
*/
{
wrectS *pwr;
pwr = pwrprev->next;
if (pwr != NULL) {
pwrprev->next = pwr->next;
};
return( pwr);
} /* wrc_extract */
wrectS *wrc_insert( wrectS *pwrprev, wrectS *pwr)
/*
| Fuegt die Rechteckbeschreibung <wr> hinter <wrprev> in die
| Liste ein.
*/
{
pwr->next = pwrprev->next;
pwrprev->next = pwr;
return( pwr);
} /* wrc_insert */
wrectS *wrc_add( wrectS *pwrprev, GRECT *rect)
/*
| Erzeugt eine neue Rechteckbeschreibung und fügt sie
| hinter <wrprev> in die Liste ein.
*/
{
wrectS *pwr;
if ((pwr = wrc_alloc()) != NULL) {
pwr->next = pwrprev->next;
pwrprev->next = pwr;
pwr->r = *rect;
pwr->scroll = FALSE;
};
return( pwr);
} /* wrc_add */
void wrc_delete( wrectS *pwrprev)
/*
| Entfernt die Rechteckbeschreibung hinter <wrprev>
| aus der Liste und gibt sie frei.
*/
{
wrectS *pwr;
if ((pwr = wrc_extract( pwrprev)) != NULL) {
wrc_free( pwr);
};
} /* wrc_delete */
wrectS *wrc_split( wrectS *pwrprev, GRECT *rcut, int del)
/*
| Zerlegt die Rechteckbeschreibung hinter <wrprev>, falls ein
| Schnitt mit dem Rechteck <rcut> besteht. Dabei wird das
| Schnittrechteck als kopierbar definiert und die ueberstehenden
| Teile als Ausgaberechtecke in die Liste eingefuegt.
| Ist <del>==TRUE, wird das Schnittrechteck nicht eingefuegt.
*/
{
wrectS *pwr;
GRECT rect;
int x1, y1;
int x2, y2;
int w, h;
pwr = pwrprev->next;
if (pwr->scroll) return( pwr);
/*** Schnittrechteck bestimmen ***/
x1 = MAX( pwr->r.g_x, rcut->g_x);
x2 = MIN( pwr->r.g_x + pwr->r.g_w, rcut->g_x + rcut->g_w);
y1 = MAX( pwr->r.g_y, rcut->g_y);
y2 = MIN( pwr->r.g_y + pwr->r.g_h, rcut->g_y + rcut->g_h);
w = x2 - x1;
h = y2 - y1;
/*** Fertig, falls kein Schnitt besteht ***/
if ((w <= 0) || (h <= 0)) return( pwr);
/*** Ueberstehende Teile als Rechtecke einfuegen ***/
if (pwr->r.g_y < y1) { /* Oberhalb */
rc_set( &rect, pwr->r.g_x, pwr->r.g_y, pwr->r.g_w, y1 - pwr->r.g_y);
if ((pwrprev = wrc_add( pwrprev, &rect)) == NULL) return( NULL);
};
if (pwr->r.g_x < x1) { /* Links */
rc_set( &rect, pwr->r.g_x, y1, x1 - pwr->r.g_x, h);
if ((pwrprev = wrc_add( pwrprev, &rect)) == NULL) return( NULL);
};
if (del) {
wrc_extract( pwrprev);
}
else {
pwrprev = pwr;
};
if (pwr->r.g_x + pwr->r.g_w > x2) { /* Rechts */
rc_set( &rect, x2, y1, (pwr->r.g_x + pwr->r.g_w) - x2, h);
if ((pwrprev = wrc_add( pwrprev, &rect)) == NULL) return( NULL);
};
if (pwr->r.g_y + pwr->r.g_h > y2) { /* Unterhalb */
rc_set( &rect, pwr->r.g_x, y2, pwr->r.g_w, (pwr->r.g_y + pwr->r.g_h) - y2);
if ((pwrprev = wrc_add( pwrprev, &rect)) == NULL) return( NULL);
};
if (del) {
/*** Schnittrechteck freigeben ***/
wrc_free( pwr);
}
else {
/*** Schnittrechteck uebernehmen ***/
rc_set( &pwr->r, x1, y1, w, h);
pwr->scroll = TRUE;
};
return( pwrprev);
} /* wrc_split */
/*------------------------------------------------------------------*/
wrectS *wrc_lnew( wlistT *wl)
/*
| Initialisiert eine Rechteckliste.
| Liefert den 'Vorgaenger' des ersten Elements.
*/
{
*wl = NULL;
return( (wrectS *)wl);
} /* wrc_lnew */
void wrc_lfree( wlistT *wl)
/*
| Gibt alle Elemente einer Rechteckliste frei.
*/
{
wrectS *pwr;
while (*wl != NULL) {
pwr = *wl;
*wl = pwr->next;
wrc_free( pwr);
};
} /* wrc_lfree */
int wrc_ldup( wlistT *wldest, wlistT *wlsour, GRECT *rclip)
/*
| Dupliziert die Rechteckliste <wlsour> unter Beruecksichtigung
| des Cliprechtecks <rclip> nach <wldest>.
*/
{
wrectS *pwrd, *pwrs;
GRECT rect;
pwrd = wrc_lnew( wldest);
for (pwrs = *wlsour; pwrs != NULL; pwrs = pwrs->next) {
rect = pwrs->r;
if ((rclip == NULL) || rc_intersect( rclip, &rect)) {
if ((pwrd = wrc_add( pwrd, &rect)) == NULL) {
wrc_lfree( wldest);
return( FALSE);
};
pwrd->scroll = pwrs->scroll;
};
};
return( TRUE);
} /* wrc_ldup */
void wrc_lmove( wlistT wl, int offsx, int offsy)
/*
| Verschiebt alle Elemente der Rechteckliste um den Betrag <offsx/y>.
*/
{
wrectS *pwr;
for (pwr = wl; pwr != NULL; pwr = pwr->next) {
pwr->r.g_x += offsx;
pwr->r.g_y += offsy;
};
} /* wrc_lmove */
void wrc_lmerge( wlistT *wl)
/*
| Versucht einzelne Rechtecke der Rechteckliste zu verschmelzen.
*/
{
wrectS *pwr, *pwr2, *pwr2prev;
for (pwr = *wl; pwr != NULL; pwr = pwr->next) {
pwr2prev = pwr;
for (pwr2 = pwr2prev->next; pwr2 != NULL; pwr2 = pwr2prev->next) {
if ((pwr->r.g_x == pwr2->r.g_x) && (pwr->r.g_w == pwr2->r.g_w) &&
(pwr->r.g_y + pwr->r.g_h == pwr2->r.g_y) &&
(pwr->scroll == pwr2->scroll) ) {
pwr->r.g_h += pwr2->r.g_h;
wrc_delete( pwr2prev);
}
else {
pwr2prev = pwr2;
};
};
};
} /* wrc_lmerge */
int wrc_test( wrectS *pwr1, wrectS *pwr2, int scrollx, int scrolly)
/*
| Liefert TRUE, falls <wr2> vor <wr1> ausgegeben werden soll.
*/
{
int left, right, above, below;
left = pwr2->r.g_x+pwr2->r.g_w <= pwr1->r.g_x;
right = pwr2->r.g_x >= pwr1->r.g_x+pwr1->r.g_w;
above = pwr2->r.g_y+pwr2->r.g_h <= pwr1->r.g_y;
below = pwr2->r.g_y >= pwr1->r.g_y+pwr1->r.g_h;
if (scrolly <= 0) {
if (above) {
return( TRUE);
}
else if (scrollx <= 0) {
return( left ? !below : FALSE);
}
else {
return( right ? !below : FALSE);
};
}
else {
if (below) {
return( TRUE);
}
else if (scrollx <= 0) {
return( left ? !above : FALSE);
}
else {
return( right ? !above : FALSE);
};
};
} /* wrc_test */
void wrc_lsort( wlistT *wl, int scrollx, int scrolly)
/*
| Sortiert die Rechteckliste so, da₧ Bereiche, die kopiert werden,
| nicht vorher neu ausgegeben werden.
*/
{
wrectS *pwr1, *pwr2, *pwr3;
if ((pwr1 = *wl) != NULL) {
while ((pwr2 = pwr1->next) != NULL) {
if (wrc_test( pwr1, pwr2, scrollx, scrolly)) {
for (pwr3 = (wrectS *)wl; pwr3->next != pwr1; pwr3 = pwr3->next) {
if (wrc_test( pwr3->next, pwr2, scrollx, scrolly)) break;
};
wrc_insert( pwr3, wrc_extract( pwr1));
}
else {
pwr1 = pwr2;
};
};
};
} /* wrc_lsort */
int wrc_lwin( wlistT *wl, int win, GRECT *rect)
/*
| Erzeugt aus den sichtbaren Rechtecken eines Fensters eine
| Rechteckliste.
*/
{
GRECT rvis, rclip;
wrectS *pwr;
pwr = wrc_lnew( wl);
wind_gdesk( &rclip);
if ((rect == NULL) || rc_intersect( rect, &rclip)) {
wind_gfirst( win, &rvis);
while ((rvis.g_w > 0) && (rvis.g_h > 0)) {
if (rc_intersect( &rclip, &rvis)) {
if ((pwr = wrc_add( pwr, &rvis)) == NULL) {
wrc_lfree( wl);
return( FALSE);
};
};
wind_gnext( win, &rvis);
};
wrc_lmerge( wl);
};
return( TRUE);
} /* wrc_lwin */
int wrc_lscroll( wlistT *wlvis, int scrollx, int scrolly)
/*
| Wandelt die Rechteckliste <wlvis> in eine Liste um, die
| aus kopierbaren und aus normalen Rechtecken besteht.
| Ein Rechteck gilt als kopierbar, wenn seine Flaeche durch
| Verschieben einer beliebigen Flaeche der Rechteckliste um
| den Betrag <scrollx/y> erzeugt werden kann. Die Reihenfolge
| der entstehenden Liste muss bei der Ausgabe beachtet werden.
| Die Funktion liefert bei Erfolg TRUE, sonst FALSE.
| Im Fehlerfall enthaelt <wlvis> eine Kopie der urspruenglichen
| Liste.
*/
{
wlistT wl;
wrectS *pwr, *pwrvis;
/*** Liste der verschobenen Rechtecke bestimmen ***/
if (!wrc_ldup( &wl, wlvis, NULL)) return( FALSE);
wrc_lmove( wl, scrollx, scrolly);
/*** sichtbare Rechtecke aufteilen ***/
for (pwr = wl; pwr != NULL; pwr = pwr->next) {
pwrvis = (wrectS *)&wlvis;
while (pwrvis->next != NULL) {
if ((pwrvis = wrc_split( pwrvis, &pwr->r, FALSE)) == NULL) {
/*** Fehler: alte Liste wiederherstellen ***/
wrc_lfree( wlvis);
wrc_lmove( wl, -scrollx, -scrolly);
*wlvis = wl;
return( FALSE);
};
};
};
wrc_lfree( &wl);
wrc_lmerge( wlvis);
/*** Ausgabereihenfolge der Rechtecke bestimmen ***/
wrc_lsort( wlvis, scrollx, scrolly);
return( TRUE);
} /* wrc_lscroll */