home *** CD-ROM | disk | FTP | other *** search
- /*
- * 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 */
-