home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Dream 48
/
Amiga_Dream_48.iso
/
Atari
/
c
/
wrc_1_0.lzh
/
WRC.1_0
/
WRCFUNCS.C
< prev
next >
Wrap
C/C++ Source or Header
|
1992-10-04
|
14KB
|
480 lines
/*********************************************************************
*
* WRCFUNCS
*
* Kurzbeschreibung:
* Das Modul stellt Fensterfunktionen zur Verfuegung, die auf Rechteck-
* listen arbeiten: wind_redraw(), wind_rscroll(), wind_rubberbox()
*
* Versionen:
* 1.0 mo 12.08.92 Basisversion uebernommen aus VDIX und WX
*
* Autoren:
* mo (\/) Martin Osieka, Erbacherstr. 2, D-6100 Darmstadt
*
*********************************************************************/
#include <stddef.h>
#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 *rclip, GRECT *rect);
#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)
int graf_rmkstate( GRECT *rmouse, int *kstate)
{
int mstate;
graf_mkstate( &rmouse->g_x, &rmouse->g_y, &mstate, kstate);
rmouse->g_w = rmouse->g_h = 1;
return( mstate);
} /* graf_rmkstate */
GRECT *rc_catch( GRECT *rmax, GRECT *rect)
/* Faengt das Rechteck <rect> in <rmax> */
{
if (rect->g_w >= rmax->g_w) {
rect->g_x = rmax->g_x + (rmax->g_w - rect->g_w) / 2;
}
else {
if (rect->g_x < rmax->g_x) rect->g_x = rmax->g_x;
if (rect->g_x + rect->g_w >= rmax->g_x + rmax->g_w) {
rect->g_x = rmax->g_x + rmax->g_w - rect->g_w;
};
};
if (rect->g_h >= rmax->g_h) {
rect->g_y = rmax->g_y + (rmax->g_h - rect->g_h) / 2;
}
else {
if (rect->g_y < rmax->g_y) rect->g_y = rmax->g_y;
if (rect->g_y + rect->g_h >= rmax->g_y + rmax->g_h) {
rect->g_y = rmax->g_y + rmax->g_h - rect->g_h;
};
};
return( rect);
} /* rc_catch */
#endif
#include <wrc.h>
#include <vdi.h>
extern int vhandle;
#include <wrcfuncs.h>
/********************************************************************/
static void wind_sredraw( int win, GRECT *rect, wdrawF drawfunc)
/*
| Gibt den Inhalt des Rechtecks <rect> im Fenster <win> neu aus.
| Ist <rect>==NULL wird als Rechteck die Ausgabeflaeche des Fensters
| benutzt.
| Diese Funktion sollte nur benutzt werden, falls die Rechteckliste
| des Fensters nicht komplett gespeichert werden konnte.
*/
{
GRECT rvis, rclip;
wind_update( BEG_UPDATE);
graf_mouse( M_OFF, NULL);
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)) {
drawfunc( win, &rvis);
};
wind_gnext( win, &rvis);
};
};
graf_mouse( M_ON, NULL);
wind_update( END_UPDATE);
} /* wind_sredraw */
void wind_redraw( int win, GRECT *rect, wdrawF drawfunc)
/*
| Gibt den Inhalt des Rechtecks <rect> im Fenster <win> neu aus.
| Ist <rect>==NULL wird als Rechteck die Ausgabeflaeche des Fensters
| benutzt.
| ACHTUNG: <drawfunc> muss sich selbst um das Clipping kuemmern
*/
{
wlistT wl;
wrectS *pwr;
wind_update( BEG_UPDATE);
graf_mouse( M_OFF, NULL);
if (wrc_lwin( &wl, win, rect)) {
for (pwr = wl; pwr != NULL; pwr = pwr->next) {
drawfunc( win, &pwr->r);
};
wrc_lfree( &wl);
}
else {
wind_sredraw( win, rect, drawfunc);
};
graf_mouse( M_ON, NULL);
wind_update( END_UPDATE);
} /* wind_redraw */
/*------------------------------------------------------------------*/
void vs_rclip( int vh, GRECT *rclip)
/*
| vs_clip() mit Rechteck-Schnittstelle
*/
{
int xyclip[ 4];
if (rclip == NULL) {
vs_clip( vh, FALSE, xyclip);
}
else {
xyclip[ 0] = rclip->g_x;
xyclip[ 1] = rclip->g_y;
xyclip[ 2] = rclip->g_x + rclip->g_w - 1;
xyclip[ 3] = rclip->g_y + rclip->g_h - 1;
vs_clip( vh, TRUE, xyclip);
};
} /* vs_rclip */
void v_rcpy( int vh, GRECT *rdest, int scrollx, int scrolly)
/*
| Kopiert einen Bildschirmbereich nach <rdest>.
| Die Funktion erwartet, dass sich sowohl das Quell- als auch das
| Zielrechteck komplett im sichtbaren Bereich des Bildschirms
| befindet, da ohne Clipping kopiert wird!
*/
{
MFDB scrmfdb;
int xy[ 8];
scrmfdb.fd_addr = NULL;
xy[ 0] = rdest->g_x - scrollx;
xy[ 1] = rdest->g_y - scrolly;
xy[ 2] = xy[ 0] + rdest->g_w - 1;
xy[ 3] = xy[ 1] + rdest->g_h - 1;
xy[ 4] = rdest->g_x;
xy[ 5] = rdest->g_y;
xy[ 6] = xy[ 4] + rdest->g_w - 1;
xy[ 7] = xy[ 5] + rdest->g_h - 1;
vs_rclip( vh, NULL);
v_hide_c( vh);
vro_cpyfm( vh, S_ONLY, xy, &scrmfdb, &scrmfdb);
v_show_c( vh, 1);
} /* v_rcpy */
void wind_rscroll( int win,
GRECT *rscroll, int scrollx, int scrolly, wdrawF drawfunc)
/*
| Verschiebt den Inhalt des Rechtecks <rscroll> im Fenster <win>
| um den Betrag <scrollx/y>. Ist <rscroll>==NULL wird als Rechteck
| die Ausgabeflaeche des Fensters benutzt.
| Alle Bereiche, die nicht durch Verschieben erzeugt werden
| koennen, werden ueber <drawfunc> neu ausgegeben.
| ACHTUNG: <drawfunc> muss sich selbst um das Clipping kuemmern
*/
{
wlistT wlvis;
wrectS *pwrvis;
if ((scrollx == 0) && (scrolly == 0)) return;
wind_update( BEG_UPDATE);
graf_mouse( M_OFF, NULL);
/*** sichtbare Rechtecke des Fensters bestimmen ***/
if (wrc_lwin( &wlvis, win, rscroll)) {
/*** Rechteckliste aufteilen ***/
wrc_lscroll( &wlvis, scrollx, scrolly);
/*** Rechtecke ausgeben ***/
for (pwrvis = wlvis; pwrvis != NULL; pwrvis = pwrvis->next) {
if (pwrvis->scroll) {
v_rcpy( vhandle, &pwrvis->r, scrollx, scrolly);
}
else {
drawfunc( win, &pwrvis->r);
};
};
wrc_lfree( &wlvis);
}
else {
wind_sredraw( win, NULL, drawfunc);
};
graf_mouse( M_ON, NULL);
wind_update( END_UPDATE);
} /* wind_rscroll */
/*------------------------------------------------------------------*/
static void v_userline( int vh, GRECT *rline)
/*
| Zeichnet die durch <rline> definierte Gerade.
| Das Muster beginnt mit einem Punkt
| - waagrechte Gerade: falls die Zeile ungerade ist
| - senkrechte Gerade: falls entweder die Startzeile oder
| die Spalte ungerade sind (exklusiv)
| Eine schnellere Loesung waere es nur Koordinaten zu benutzen,
| die ein Vielfaches von zwei sind (dann muss das Muster
| nur einmal gesetzt werden)
| (Dieser Algorithmus entspricht dem Vorgehen des GEM beim
| Zeichnen von Geisterrahmen)
*/
{
int pat;
int xyline[ 4];
xyline[ 0] = rline->g_x;
xyline[ 1] = rline->g_y;
xyline[ 2] = rline->g_x + rline->g_w - 1;
xyline[ 3] = rline->g_y + rline->g_h - 1;
if (xyline[ 1] == xyline[ 3]) { /* waagrecht */
pat = (xyline[1] & 1) ? 0xAAAA : 0x5555;
}
else { /* senkrecht */
pat = ((xyline[0] ^ xyline[1]) & 1) ? 0xAAAA : 0x5555;
};
vsl_udsty( vh, pat);
v_pline( vh, 2, xyline);
} /* v_userline */
#define NONO 0 /* Beide Endpunkte ausgeben */
#define NOS 1 /* Startpunkt nicht ausgeben */
#define NOE 2 /* Endpunkt nicht ausgeben */
#define NOSE 3 /* Keinen der Endpunkte ausgeben */
static void v_rubberline( int vh,
int x1, int y1, int x2, int y2,
int mode, wlistT wl)
/*
| Zeichnet eine Gerade zwischen dem Anfangspunkt <x1/y1> und dem
| Endpunkt <x2/y2>, wobei die Liste der Cliprechtecke in <wl>
| beachtet wird. <mode> bestimmt die Ausgabe des Anfangs- und End-
| punkts der Geraden. Die Gerade wird immer von links nach rechts
| bzw. von oben nach unten gezogen.
| HINWEIS: Oft ist die Segmentierung eine Geraden unnoetig.
| Das Zusammenlegen erfordert allerdings einigen Aufwand.
*/
{
int x, y;
GRECT rline, rlinep;
wrectS *pwr;
/*** Anfangspunkt entfernen ***/
if (mode & NOS) {
if ((x1 == x2) && (y1 == y2)) return;
if (x1 != x2) {
x1 += (x1 < x2) ? 1 : -1;
}
else {
y1 += (y1 < y2) ? 1 : -1;
};
};
/*** Endpunkt entfernen ***/
if (mode & NOE) {
if ((x1 == x2) && (y1 == y2)) return;
if (x1 != x2) {
x2 -= (x1 < x2) ? 1 : -1;
}
else {
y2 -= (y1 < y2) ? 1 : -1;
};
};
/*** Erst jetzt Punkte sortieren ***/
if (x1 > x2) { x = x1; x1 = x2; x2 = x; };
if (y1 > y2) { y = y1; y1 = y2; y2 = y; };
/*** Linienrechteck erzeugen ***/
rline.g_x = x1;
rline.g_y = y1;
rline.g_w = x2 - x1 + 1;
rline.g_h = y2 - y1 + 1;
/*** Linie clippen und zeichnen ***/
for (pwr = wl; pwr != NULL; pwr = pwr->next) {
rlinep = rline;
if (rc_intersect( &pwr->r, &rlinep)) {
v_userline( vh, &rlinep);
};
};
} /* v_rubberline */
int wind_rubberbox( int win, GRECT *rmouse, GRECT *rsel)
/*
| Erlaubt dem Anwender ein Selektionsrechteck in einem Fenster <win>
| aufzuziehen, beginnend an der Position <rmouse> (Das Desktop hat
| die Fensterkennung 0). Das Rechteck kann maximal die Groesse der
| Arbeitsflaeche des Fensters annehmen und ist auch nur in ihm
| sichtbar. Reicht der Speicher nicht fuer eine Liste der
| Cliprechtecke des Fensters wird nicht geclippt und es ist
| somit auch in den anderen Fenstern sichtbar.
| Die Funktion liefert den Status der Sondertasten der Tastatur
| beim Loslassen des Mausknopfs.
|
| o S - Startpunkt
| S+-------+ M - Maus
| | | o - aeussere Geraden
| o| |i i - innere Geraden
| | |
| +-------+
| i
*/
{
wlistT wl; /* Liste der Cliprechtecke von <win> */
wrectS wrdummy;
GRECT rmaxsel; /* Ausgabeflaeche von <win> */
int x1, y1; /* Startposition */
int x2, y2; /* Letzte Mausposition */
int newx2, newy2; /* Neue Mausposition */
int mstate, kstate; /* Maustasten und Status der Sondertasten */
int xbigger, ybigger; /* TRUE falls Selektionsrechteck in einer
Richtung absolut groesser wird */
wind_update( BEG_UPDATE);
wind_update( BEG_MCTRL);
/*** Rechtecke und Startposition bestimmen ***/
wind_rget( win, WF_WORKXYWH, &rmaxsel); /* Maximalrechteck */
if (!wrc_lwin( &wl, win, &rmaxsel)) { /* Cliprechtecke */
wl = &wrdummy;
wrdummy.next = NULL;
wrdummy.r = rmaxsel;
};
x1 = x2 = rmouse->g_x; /* Startposition */
y1 = y2 = rmouse->g_y;
/*** VDI-Voreinstellung ***/
vswr_mode( vhandle, MD_XOR);
vs_rclip( vhandle, NULL); /* mach ich selbst */
vsl_color( vhandle, BLACK);
vsl_type( vhandle, 7); /* Linientyp wird selbst definiert */
/*** Zeichnen des Startpunkt (dieser wird nie mehr veraendert) ***/
v_hide_c( vhandle);
v_rubberline( vhandle, x1, y1, x2, y2, NONO, wl);
v_show_c( vhandle, 1);
while (TRUE) {
/*** Neue Position innerhalb des Maximalrechtecks bestimmen ***/
mstate = graf_rmkstate( rmouse, &kstate);
if ((mstate & 1) == 0) break;
rc_catch( &rmaxsel, rmouse);
newx2 = rmouse->g_x;
newy2 = rmouse->g_y;
/*** Keine abrupte Richtungsumkehr ***/
if ((x2 < x1) && (newx2 > x1)) newx2 = x1;
if ((x2 > x1) && (newx2 < x1)) newx2 = x1;
if ((y2 < y1) && (newy2 > y1)) newy2 = y1;
if ((y2 > y1) && (newy2 < y1)) newy2 = y1;
/*** Es hat sich was veraendert? ... dann neu zeichnen ***/
if ((newx2 != x2) || (newy2 != y2)) {
v_hide_c( vhandle);
/*** Loeschen der aeusseren Linien ***/
if ((y1 != y2) && (y2 != newy2)) {
v_rubberline( vhandle, x1, y2, x2, y2, (x2 == newx2) ? NOSE : NOS, wl);
};
if ((x1 != x2) && (x2 != newx2)) {
v_rubberline( vhandle, x2, y1, x2, y2, NOSE, wl);
};
/*** Veraendern der inneren Linien (eventuell auch aeussere) ***/
xbigger = (x2 == x1) || ((newx2 < x2) && (x2 < x1)) || ((newx2 > x2) && (x2 > x1));
ybigger = (y2 == y1) || ((newy2 < y2) && (y2 < y1)) || ((newy2 > y2) && (y2 > y1));
v_rubberline( vhandle, x2, y1, newx2, y1, xbigger ? NOS : NOE, wl);
if ((y1 != y2) && (y2 == newy2)) {
v_rubberline( vhandle, x2, y2, newx2, y2, xbigger ? NOS : NOE, wl);
};
v_rubberline( vhandle, x1, y2, x1, newy2, ybigger ? NOS : NOE, wl);
if ((x1 != x2) && (x2 == newx2)) {
v_rubberline( vhandle, x2, y2, x2, newy2, ybigger ? NOS : NOE, wl);
};
/*** Neuzeichnen der aeusseren Linien ***/
if ((y1 != newy2) && (y2 != newy2)) {
v_rubberline( vhandle, x1, newy2, newx2, newy2, (x2 == newx2) ? NOSE : NOS, wl);
};
if ((x1 != newx2) && (x2 != newx2)) {
v_rubberline( vhandle, newx2, y1, newx2, newy2, NOSE, wl);
};
v_show_c( vhandle, 1);
/*** Neue Mausposition uebernehmen ***/
x2 = newx2;
y2 = newy2;
};
};
/*** Loeschen der aeusseren und inneren Linien ***/
v_hide_c( vhandle);
v_rubberline( vhandle, x1, y1, x2, y1, NONO, wl);
if (y1 != y2) {
v_rubberline( vhandle, x1, y1, x1, y2, NOSE, wl);
if (x1 != x2) v_rubberline( vhandle, x2, y1, x2, y2, NOSE, wl);
v_rubberline( vhandle, x1, y2, x2, y2, NONO, wl);
};
v_show_c( vhandle, 1);
vswr_mode( vhandle, MD_REPLACE);
if (wl != &wrdummy) {
wrc_lfree( &wl); /* Cliprechtecke wieder freigeben */
};
/*** Selektionsrechteck zurueckgeben ***/
if (x1 > x2) { newx2 = x2; x2 = x1; x1 = newx2; };
if (y1 > y2) { newy2 = y2; y2 = y1; y1 = newy2; };
rc_set( rsel, x1, y1, x2 - x1 + 1, y2 - y1 + 1);
wind_update( END_MCTRL);
wind_update( END_UPDATE);
return( kstate);
} /* wind_rubberbox */
/********************************************************************/