home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
GEMini Atari
/
GEMini_Atari_CD-ROM_Walnut_Creek_December_1993.iso
/
zip
/
utility
/
zoom.zoo
/
zoomacc.c
< prev
next >
Wrap
C/C++ Source or Header
|
1991-04-07
|
8KB
|
369 lines
/*
* Zoom accessory
*
*/
#include <osbind.h>
#include <linea.h>
#include <aes.h>
#include <vdi.h>
#define elements(p) (p).g_x, (p).g_y, (p).g_w, (p).g_h
#define pointers(p) &(p).g_x, &(p).g_y, &(p).g_w, &(p).g_h
#define clip(lower, val, upper) min((upper), max((lower), (val)))
#define WF_PARTS (NAME+CLOSE+MOVE)
typedef unsigned char uchar;
typedef unsigned short ushort;
typedef unsigned long ulong;
#ifdef LATTICE
extern long _STACK = 2048;
#endif
/*
* Assembler functions to zoom up a single screen line and to blit the zoomed
* buffer onto the screen *fast*
*
*/
extern void zoomLine(void *, void *, short, short);
extern void qblit(void *, void *, short);
#ifdef ACCorPRG
extern int _XMODE; /* Lattice startup stub variable: 2 = DA */
#endif
short handle; /* VDI handle */
short m[8]; /* AES message buffer */
short err; /* Accessory installed? */
uchar zoomed[128][16]; /* Array of zoomed pixels */
struct la_data *data; /* Line A data */
uchar *display; /* Pointer to screen memory */
char *title = " Zoom "; /* The DA title as well as the window title */
MFDB zoomarea = {zoomed, 128, 128, 8, 0, 1, 0, 0, 0};
MFDB screen;
/*
* Function: Convert a window work area so that it lies on a word boundary
*
* Parameters: Original work area, result work area
*
* Returns: None
*
*/
void
work2work(GRECT *work1, GRECT *work2)
{
work2->g_x = (work1->g_x + 15) / 16;
work2->g_x = work2->g_x * 16 - 1;
work2->g_y = work1->g_y;
work2->g_w = work1->g_w;
work2->g_h = work1->g_h;
}
/*
* Function: Convert a window border to a word-aligned work area
*
* Parameters: Border area, result work area
*
* Returns: None
*
*/
void
curr2work(GRECT *curr, GRECT *work)
{
GRECT temp;
wind_calc(WC_WORK, WF_PARTS, elements(*curr), pointers(temp));
work2work(&temp, work);
}
/*
* Function: Convert a window border area so that it lies on screen and has
* a word-aligned work area
*
* Parameters: Original border area, result border area
*
* Returns: None
*
*/
void
curr2curr(GRECT *curr1, GRECT *curr2)
{
GRECT temp;
wind_get(0, WF_WORKXYWH, pointers(temp));
curr1->g_x = min(curr1->g_x, temp.g_x + temp.g_w - curr1->g_w - 2);
curr1->g_y = min(curr1->g_y, temp.g_y + temp.g_h - curr1->g_h - 2);
curr2work(curr1, &temp);
wind_calc(WC_BORDER, WF_PARTS, elements(temp), pointers(*curr2));
}
/*
* Function: Produce a zoomed display in the global zoomed array (assuming
* a THIN_CROSS mouse, the area is offset by the hot-spot of 7,7)
*
* Parameters: Mouse x and y coordinates of top-left corner of area
*
* Returns: None
*
*/
void
zoom(short x, short y)
{
uchar *scr;
x = clip(0, x - 7, data->ld_vwrap * 8 - 16);
y = clip(0, y - 7, V_Y_MAX - 16);
scr = display + 2 * (x / 16);
scr += (long)y * data->ld_vwrap;
graf_mouse(M_OFF, NULL);
zoomLine(scr, zoomed, data->ld_vwrap, x % 16);
graf_mouse(M_ON, NULL);
}
/*
* Function: Function called by wind_redraw to redraw the window from the
* zoomed buffer. Also, a white pixel border is drawn on 2 sides
*
* Parameters: Window handle, area to redraw
*
* Returns: 1 (continue redrawing)
*
*/
int
redraw(int win, GRECT *p)
{
GRECT work;
short pxy[8];
pxy[0] = p->g_x; pxy[1] = p->g_y;
pxy[2] = p->g_x + p->g_w - 1;
pxy[3] = p->g_y + p->g_h - 1;
vs_clip(handle, 1, pxy);
wind_get(win, WF_WORKXYWH, pointers(work));
pxy[0] = work.g_x + work.g_w - 1;
pxy[1] = work.g_y;
pxy[2] = work.g_x;
pxy[3] = work.g_y;
pxy[4] = work.g_x;
pxy[5] = work.g_y + work.g_h - 1;
vsl_color(handle, WHITE);
v_pline(handle, 3, pxy); /* Draw a pixel border on the top & left */
vs_clip(handle, 0, pxy);
work.g_x++; work.g_y++;
work.g_w--; work.g_h--;
rc_intersect(&work, p);
pxy[0] = p->g_x - work.g_x; pxy[1] = p->g_y - work.g_y;
pxy[2] = pxy[0] + p->g_w - 1; pxy[3] = pxy[1] + p->g_h - 1;
pxy[4] = p->g_x; pxy[5] = p->g_y;
pxy[6] = p->g_x + p->g_w - 1; pxy[7] = p->g_y + p->g_h - 1;
vro_cpyfm(handle, S_ONLY, pxy, &zoomarea, &screen);
return 1;
}
#ifndef LATTICE
/*
* Function: Manage window redraws by calling a supplied function for
* each valid screen rectangle
* From the Lattice C Atari Library Manual pp73-74
*
* Parameters: Window handle, redraw area, redrawing function
*
* Returns: 1 if OK, 0 otherwise
*
*/
int
wind_redraw(int win, GRECT *area, int (*redraw)(int, GRECT *))
{
GRECT box;
int ok = 1;
graf_mouse(M_OFF, NULL);
wind_update(BEG_UPDATE);
wind_get(win, WF_FIRSTXYWH, pointers(box));
while (box.g_w && box.g_h) {
if (rc_intersect(area, &box))
if (!(ok = redraw(win, &box)))
break;
wind_get(win, WF_NEXTXYWH, pointers(box));
}
wind_update(END_UPDATE);
graf_mouse(M_ON, NULL);
return ok;
}
#endif
/*
* Function: Handle the opened zoom window
*
* Parameters: None
*
* Returns: None
*
*/
void
doZoom(void)
{
GRECT work = {127, 127, 129, 129};
GRECT curr;
uchar *scr;
short win;
short x, y, junk;
short ev;
short top;
int done = 0;
wind_calc(WC_BORDER, WF_PARTS, elements(work), pointers(curr));
win = wind_create(WF_PARTS, elements(curr));
if (win < 0)
return;
wind_title(win, title + 1);
wind_open(win, elements(curr));
graf_mkstate(&x, &y, &junk, &junk);
zoom(x, y);
graf_mouse(THIN_CROSS, NULL);
do {
ev = evnt_multi(MU_M1 | MU_MESAG,
0, 0, 0,
1, x, y, 1, 1,
0, 0, 0, 0, 0,
m,
0, 0,
&x, &y,
&junk, &junk, &junk, &junk);
wind_update(BEG_UPDATE);
wind_get(win, WF_TOP, &top, &junk, &junk, &junk);
/*
* It IS possible to get MU_M1 events if the window is NOT topped!!
*
*/
if (top == win && (ev & MU_M1)) {
zoom(x, y);
scr = display + (work.g_x + 1) / 8;
scr += (long)(work.g_y + 1) * data->ld_vwrap;
graf_mouse(M_OFF, NULL);
qblit(scr, zoomed, data->ld_vwrap);
graf_mouse(M_ON, NULL);
}
if (ev & MU_MESAG)
switch (m[0]) {
case WM_CLOSED:
wind_close(win);
wind_delete(win); /* Fall through */
case AC_CLOSE:
done = 1;
break;
case AC_OPEN:
wind_set(win, WF_TOP);
break;
case WM_TOPPED:
if (m[3] == win) {
wind_set(win, WF_TOP);
graf_mouse(THIN_CROSS, NULL);
}
break;
case WM_REDRAW:
wind_redraw(win, (GRECT *)&m[4], redraw);
break;
case WM_MOVED:
curr2curr((GRECT *)&m[4], &curr);
wind_set(win, WF_CURRXYWH, elements(curr));
wind_get(win, WF_WORKXYWH, pointers(work));
break;
default:
break;
}
wind_update(END_UPDATE);
} while (!done);
graf_mouse(ARROW, NULL);
}
/*
* Function: Initialise GEM, install as a DA, get screen address.
*
* Parameters: None
*
* Returns: None (sets err global)
*
*/
void
init(void)
{
short workin[] = {1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2};
short workout[57];
short junk;
short id;
err = 0;
data = linea0();
if (data->ld_vplanes != 1)
err = -1;
display = (uchar *)Logbase();
id = appl_init();
#ifdef ACCorPRG
if (_XMODE == 2)
#endif
err = menu_register(id, title);
#ifdef ACCorPRG
else
err = 0;
#endif
screen.fd_addr = NULL;
handle = graf_handle(&junk, &junk, &junk, &junk);
v_opnvwk(workin, &handle, workout);
}
/*
* Function: Main program
*
* Parameters: None
*
* Returns: None (never returns if run as an accessory)
*
*/
void
main(void)
{
init();
#ifdef ACCorPRG
if (_XMODE == 2) {
#endif
if (err == -1)
Cconws("Error installing \033pZoomAcc\033q!\r\n");
for (;;) {
evnt_mesag(m);
if (err != -1 && m[0] == AC_OPEN)
doZoom();
}
#ifdef ACCorPRG
} else {
doZoom();
v_clsvwk(handle);
appl_exit();
}
#endif
}
/* End of zoomacc.c */