home *** CD-ROM | disk | FTP | other *** search
- /* > $.CLIB.C.graphics
- *
- * HASWIN Graphics Library
- * =========================
- *
- * Copyright (C) H.A.Shaw 1990.
- * Howard A. Shaw.
- * The Unit for Space Sciences,
- * Room 165,
- * Physics Building,
- * University of Kent at Canterbury.
- * Canterbury.
- * Kent. CT2 7NJ
- * You may use and distribute this code freely, however please leave
- * it alone. If you find bugs (and there will be many) please contact
- * me and the master source can be modified. If you keep me informed
- * of who you give copies of this to then I can get release upgrades
- * to them.
- *
- * low level graphics routines that actually draw on the screen.
- */
- #include "includes.h"
- #include <stdarg.h>
-
- void graphics_plotxy(int code, int x, int y) {
-
- _kernel_swi_regs regs;
-
- regs.r[0] = code;
- regs.r[1] = x;
- regs.r[2] = y;
- haswin_swi(OS_Plot, ®s);
- }
-
- /*
- * routines to perform basic graphics actions in a HASWIN window.
- * Draw if any part of the object's enclosing rectangle is in the
- * window.
- * We assume that graphics windows are set and drawing can be done
- * immediatly.
- * in these routines...
- * x,y is a coord
- * r is a radius
- * w is a width
- * h is a hieght
- * c is a colour
- */
- void haswin_circle(window *win, int x, int y, int r) {
-
- if ((!win) || (r < 0) || ((x-r) > haswin_getwindowxmax(win)) ||
- ((x+r) < haswin_getwindowxmin(win)) ||
- ((y-r) > haswin_getwindowymax(win)) ||
- ((y+r) < haswin_getwindowymin(win)))
- return;
- haswin_convertwinxytoscr(win, &x, &y);
- graphics_circle(x, y, r);
- }
-
- void haswin_circlefill(window *win, int x, int y, int r) {
- if ((!win) || (r < 0) || ((x-r) > haswin_getwindowxmax(win)) ||
- ((x+r) < haswin_getwindowxmin(win)) ||
- ((y-r) > haswin_getwindowymax(win)) ||
- ((y+r) < haswin_getwindowymin(win)))
- return;
- haswin_convertwinxytoscr(win, &x, &y);
- graphics_circlefill(x, y, r);
- }
-
- void haswin_draw(window *win, int x, int y) {
- if ((!win) || (x > haswin_getwindowxmax(win)) ||
- (x < haswin_getwindowxmin(win)) ||
- (y > haswin_getwindowymax(win)) ||
- (y < haswin_getwindowymin(win)))
- return;
- haswin_convertwinxytoscr(win, &x, &y);
- graphics_draw(x, y);
- }
-
- void haswin_drawby(window *win, int x, int y) {
- if (!win)
- return;
- graphics_drawby(x, y);
- }
-
- void haswin_fill(window *win, int x, int y) {
- if (!win)
- return;
- haswin_convertwinxytoscr(win, &x, &y);
- graphics_fill(x, y);
- }
-
- void haswin_rectangle(window *win, int x, int y, int w, int h) {
- if ((!win) || (x > haswin_getwindowxmax(win)) ||
- ((x+w) < haswin_getwindowxmin(win)) ||
- (y > haswin_getwindowymax(win)) ||
- ((y+h) < haswin_getwindowymin(win)))
- return;
- haswin_convertwinxytoscr(win, &x, &y);
- graphics_rectangle(x, y, w, h);
- }
-
- void haswin_rectanglefill(window *win, int x, int y, int w, int h) {
- if ((!win) || (x > haswin_getwindowxmax(win)) ||
- ((x+w) < haswin_getwindowxmin(win)) ||
- (y > haswin_getwindowymax(win)) ||
- ((y+h) < haswin_getwindowymin(win)))
- return;
- haswin_convertwinxytoscr(win, &x, &y);
- graphics_rectanglefill(x, y, w, h);
- }
-
-
- /*
- * take the string pointed to by "string" and display on the
- * graphics screen adjusting for a start at adjx,adjy.
- *
- * We try to be a little intellegent about what we don't have to draw.
- * The calculations for filled rectangles are easy, but others are
- * approximate only and still draw too often. Circles especially.
- *
- * The following control codes are understood.
- * $ is escape sequence start/end.
- *
- * cx,y,r circle at x,y radius r
- * Cx,y,r filled circle at x,y radius r
- * dx,y draw line to x,y
- * Dx,y draw line relative to x,y
- * fn select foreground colour n
- * (background can't be changed)
- * mx,y move to x,y
- * Mx,y move relative to x,y
- * rx,y,w,h rectangle x,y width w, height h
- * Rx,y,w,h filled rectangle x,y width w, height h
- *
- * a single $$ pair can enclose many control sequences. any non
- * control symbol (0-9cCdDfmMrR) seperates within $$
- */
-
- static char *c;
- int ato_int(void);
-
- void graphics_plot(char *string, int adjx, int adjy, int gx0, int gx1,
- int gy0, int gy1) {
-
- register int x, y, r, h;
- int line, col, movepend, incontrol, charx, chary;
-
- if (!string)
- return;
- line = adjy;
- col = adjx;
- movepend=0;
- charx = haswin_readvduvariable(VDUVAR_CharXsize);
- chary = haswin_readvduvariable(VDUVAR_CharYsize);
- incontrol=HASWIN_FALSE;
- for (c=string; *c; c++) {
- switch (*c) {
- case '\n':
- line -= chary;
- /* FALL THRU */
- case '\r':
- movepend++;
- col = adjx;
- break;
- case '$':
- if (incontrol)
- incontrol = HASWIN_FALSE;
- else
- incontrol = HASWIN_TRUE;
- break;
- default:
- if (incontrol) {
- switch (*c) {
- case 'm':
- c++; col = adjx+ato_int();
- c++; line= adjy+ato_int();
- movepend++;
- break;
- case 'M':
- c++; col += ato_int();
- c++; line += ato_int();
- movepend++;
- break;
- case 'c':
- c++; x = adjx+ato_int();
- c++; y = adjy+ato_int();
- c++; r = ato_int();
- if ((x-r>gx1) || (x+r<gx0))
- break;
- if ((y-r>gy1) || (y+r<gy0))
- break;
- graphics_circle(x, y, r);
- break;
- case 'C':
- c++; x = adjx+ato_int();
- c++; y = adjy+ato_int();
- c++; r = ato_int();
- if ((x-r>gx1) || (x+r<gx0))
- break;
- if ((y-r>gy1) || (y+r<gy0))
- break;
- graphics_circlefill(x, y, r);
- break;
- case 'd':
- if (movepend) {
- movepend = 0;
- graphics_move(col, line);
- }
- c++; x = adjx+ato_int();
- c++; y = adjy+ato_int();
- graphics_draw(x, y);
- break;
- case 'D':
- if (movepend) {
- movepend = 0;
- graphics_move(col, line);
- }
- c++; x = adjx+ato_int();
- c++; y = adjy+ato_int();
- graphics_drawby(x, y);
- break;
- case 'f':
- c++; x = ato_int();
- graphics_gcol(0, x);
- break;
- case 'r':
- c++; x = adjx+ato_int();
- c++; y = adjy+ato_int();
- c++; r = ato_int();
- c++; h = ato_int();
- if ((x > gx1) || (x+r < gx0))
- break;
- if ((y > gy1) || (y+h < gy0))
- break;
- graphics_rectangle(x, y, r, h);
- break;
- case 'R':
- c++; x = adjx+ato_int();
- c++; y = adjy+ato_int();
- c++; r = ato_int();
- c++; h = ato_int();
- if ((x > gx1) || (x+r < gx0))
- break;
- if ((y > gy1) || (y+h < gy0))
- break;
- graphics_rectanglefill(x, y, r, h);
- break;
- default:
- break;
- }
- } else {
- if (( col+charx >gx0) && ( col-charx <gx1) &&
- (line+chary >gy0) && (line-chary <gy1)) {
- if (movepend) {
- movepend = 0;
- graphics_move(col, line);
- }
- haswin_swi(OS_WriteI+(*c), 0);
- }
- col += charx;
- }
- }
- }
- }
-
- /*
- * remove leading spaces and commas, find a number, and return it
- * c is left pointing to the last digit in the number.
- */
- int ato_int() {
-
- register int b = 0;
-
- while ((*c == ' ') || (*c == ','))
- c++;
- if (*c == '-') {
- c++;
- while ((*c >= '0') && ( *c <= '9'))
- b = b*10 + (*(c++)-'0');
- c--;
- return(-b);
- }
- while ((*c >= '0') && ( *c <= '9'))
- b = b*10 + (*(c++)-'0');
- c--;
- return(b);
- }
-
- int haswin_addgraphics(window *win, char *str) {
-
- int max;
-
- if (!win)
- return(HASWIN_FALSE);
- max = strlen(str);
- if (win->picture)
- win->picture = haswin_mallocblock(win->picture, max+((int *)win->picture)[-1]+1, "haswin_addgraphics", "window picture");
- else {
- win->picture = haswin_mallocblock(0, max+1, "haswin_addgraphics", "window picture");
- win->picture[0] = '\0';
- }
- strcat(win->picture, str);
- return(HASWIN_TRUE);
- }
-
- int haswin_cleargraphics(window *win) {
-
- if (!win)
- return(HASWIN_FALSE);
- if (win->picture) {
- haswin_freeblock(win->picture);
- win->picture = 0;
- }
- return(HASWIN_TRUE);
- }
-
- /*
- * perform printf() on the graphics in a given window.
- *
- * The final string is passed to haswin_addgraphics() for display.
- */
- int haswin_graphicsprintf(window *win, char *fmt, ...) {
-
- va_list ap;
- /* we have to use fixed length strings, guess at 10K in total */
- char str[10240];
- int len;
-
- if ((!win) || (!fmt))
- return(HASWIN_FALSE);
- va_start(ap, fmt);
- len = vsprintf(str, fmt, ap);
- haswin_addgraphics(win, str);
- va_end(ap);
- return(len);
- }
-
-