xmb, fast mandelbrot for x-windows, part02/02
Hannu Helminen
dm at rainbow.oulu.fi
Fri May 24 01:02:34 AEST 1991
#! /bin/sh
# This is a shell archive. Remove anything before this line, then unpack
# it by saving it into a file and typing "sh file". To overwrite existing
# files, type "sh file -c". You can also feed this as standard input via
# unshar, or by typing "sh <file", e.g.. If this archive is complete, you
# will see the following message at the end:
# "End of archive 2 (of 2)."
# Contents: cmap.c x.c
# Wrapped by dm at stekt2 on Thu May 23 16:38:45 1991
PATH=/bin:/usr/bin:/usr/ucb ; export PATH
if test -f cmap.c -a "${1}" != "-c" ; then
echo shar: Will not over-write existing file \"cmap.c\"
else
echo shar: Extracting \"cmap.c\" \(15828 characters\)
sed "s/^X//" >cmap.c <<'END_OF_cmap.c'
X
X/* This module is a dull one. It is somewhat important, however,
X * because it handles most of the interface between the program
X * and the user.
X
X * This module will allocate colors, free them; handle events of the
X * colormap window, including gadgets, sliders and spectrum;
X * it will also handle the mapping between iteration levels and
X * colors.
X
X * callable functios:
X * void ToggleCWin(display, window, mode);
X * int HandleCEvent(Display *display, int screen, Window window,
X GC gc1, GC gc2, GC gc3, Xevent *event);
X * void AllocColors(Display *display, int screen);
X * void FreeColors(Display *display, int screen);
X * void SetNColors(int number_of_colors);
X * unsigned long ToPixel(int level);
X
X */
X
X#include <X11/Xlib.h>
X#include <math.h>
X#include <stdio.h>
X#include "cmap.h"
X#include "misc.h"
X
X/* Geometries of gadgets.. */
X#define GAD_Y1 5
X#define GAD_Y2 20
X#define GAD_LEFT 10
X#define GAD_GAP 8
X/* ...Sliders... */
X#define TOP_GAP 25
X#define CHAR_X 5
X#define LINE_X 20
X#define BOX_X1 30
X#define BOX_X2 10
X#define BOX_Y1 3
X#define BOX_Y2 3
X#define BOTTOM_GAP 25
X/* ... cmap */
X#define CMAP_Y1 20
X#define CMAP_Y2 5
X#define BLACK_SIZE 4
X
X#define SLIDERSTEPS 64
X#define MAXSLIDE 65536
X
X#define GAMMA 2.2
X
Xstatic char *gadget[]= {"Apply", "Redraw", "Previous", "Restart", "Quit"};
X#define NUMGAD (sizeof(gadget)/sizeof(char *))
Xstatic struct gad_pos{
X int s, e;
X } gadpos[NUMGAD];
X
Xstatic long red[SLIDERSTEPS], green[SLIDERSTEPS],
X blue[SLIDERSTEPS];
Xstatic long red0, green0, blue0;
Xstatic int coff= 0; /* color offset */
X
Xstatic unsigned long *pixel;
Xstatic char *alloc;
Xstatic int allocated= 0;
Xstatic int ncolors= 0;
X/* Does the current colormap reflect position of sliders? */
Xstatic int applied= 0;
X
Xstatic int mapped= 0;
X
Xstatic int width, height;
X
Xvoid ToggleCWin(display, win, mode)
XDisplay *display;
XWindow win;
Xint mode;
X{
Xif (mapped && (mode == CMAP_TOGGLE || mode == CMAP_CLOSE)) {
X XUnmapWindow(display, win);
X mapped= 0;
X }
Xelse if (!mapped && (mode == CMAP_TOGGLE || mode == CMAP_OPEN)) {
X XMapWindow(display, win);
X mapped= 1;
X }
X}
X
X
Xvoid DrawHotSpot(display, win, gc, x, y)
XDisplay *display;
XWindow win;
XGC gc;
Xint x,y;
X{
XXDrawRectangle(display, win, gc, x-3, y-3, 6, 6);
XXDrawRectangle(display, win, gc, x-2, y-2, 4, 4);
X}
X
X
Xvoid DrawSliders(display, win, gc, n)
XDisplay *display;
XWindow win;
XGC gc;
Xint n;
X{
Xint i;
Xint zone= (height-TOP_GAP-BOTTOM_GAP)/3;
Xlong *color;
X
Xswitch(n) {
X case 0: color= red; break;
X case 1: color= green; break;
X case 2: color= blue; break;
X }
Xfor (i= 0; i < SLIDERSTEPS; i++) {
X int j= (i+1) % SLIDERSTEPS;
X int x1= BOX_X1 + 1+i*(width-BOX_X1-BOX_X2-2)/SLIDERSTEPS;
X int x2= BOX_X1 + 1+(i+1)*(width-BOX_X1-BOX_X2-2)/SLIDERSTEPS;
X int y1= TOP_GAP + n*zone + BOX_Y1 +
X 1 + ((zone-BOX_Y1-BOX_Y2-2)*(MAXSLIDE-color[i]))/MAXSLIDE;
X int y2= TOP_GAP + n*zone + BOX_Y1 +
X 1 + ((zone-BOX_Y1-BOX_Y2-2)*(MAXSLIDE-color[j]))/MAXSLIDE;
X
X XDrawLine(display, win, gc, x1, y1, x2, y2);
X }
X}
X
X
Xvoid DrawSlider(display, win, gc1, gc2, n, trash)
XDisplay *display;
XWindow win;
XGC gc1, gc2;
Xint n, trash;
X{
Xint zone =(height-TOP_GAP-BOTTOM_GAP) / 3;
Xstatic int oy[3]= {-1, -1, -1};
Xint y;
Xint h;
X
Xswitch(n) {
X case 0: h= red0; break;
X case 1: h= green0; break;
X case 2: h= blue0; break;
X default: break;
X }
Xy= TOP_GAP + n*zone + BOX_Y1 + ((zone-BOX_Y1-BOX_Y2)*(MAXSLIDE-h))/MAXSLIDE;
X
Xif (y != oy[n] || trash) {
X if (oy[n] >= 0)
X DrawHotSpot(display, win, gc2, LINE_X, oy[n]);
X DrawHotSpot(display, win, gc1, LINE_X, y);
X oy[n]= y;
X XDrawLine(display, win, gc1,
X LINE_X, TOP_GAP+n*zone+BOX_Y1, LINE_X, TOP_GAP+(n+1)*zone-BOX_Y2);
X }
X}
X
X
Xvoid DrawSliderBox(display, win, gc, n)
XDisplay *display;
XWindow win;
XGC gc;
Xint n;
X{
Xint zone= (height-TOP_GAP-BOTTOM_GAP)/3;
Xchar ch[2];
X
Xch[1]= '\0';
Xswitch(n) {
X case 0: ch[0]= 'R'; break;
X case 1: ch[0]= 'G'; break;
X case 2: ch[0]= 'B'; break;
X }
XXDrawRectangle(display, win, gc,
X BOX_X1, TOP_GAP + n*zone + BOX_Y1,
X width-BOX_X1-BOX_X2, zone-BOX_Y1-BOX_Y2);
XWriteText(display, win, gc, ch, CHAR_X,
X TOP_GAP + n*zone + BOX_Y1 + (zone-BOX_Y1-BOX_Y2)/2-6 );
X}
X
X
Xvoid DrawColorBox(display, win, gc, gc1)
XDisplay *display;
XWindow win;
XGC gc, gc1;
X{
Xint i;
XXGCValues gcval;
X
Xgcval.foreground= pixel[0];
XXChangeGC(display, gc, GCForeground, &gcval);
X
XXFillRectangle(display, win, gc,
X LINE_X-BLACK_SIZE, height-CMAP_Y1,
X 2*BLACK_SIZE, CMAP_Y1-CMAP_Y2);
XXDrawRectangle(display, win, gc1,
X LINE_X-BLACK_SIZE, height-CMAP_Y1,
X 2*BLACK_SIZE, CMAP_Y1-CMAP_Y2);
X
Xfor (i= 1; i < ncolors; i++) {
X int x1= ((width-BOX_X2-BOX_X1)*(i-1)/(ncolors-1));
X int x2= ((width-BOX_X2-BOX_X1)*i/(ncolors-1));
X
X gcval.foreground= pixel[i];
X XChangeGC(display, gc, GCForeground, &gcval);
X
X XFillRectangle(display, win, gc,
X BOX_X1+x1, height-CMAP_Y1,
X x2-x1, CMAP_Y1-CMAP_Y2);
X }
XXDrawRectangle(display, win, gc1,
X BOX_X1, height-CMAP_Y1,
X width-BOX_X2-BOX_X1, CMAP_Y1-CMAP_Y2);
X} /* DrawColorBox() */
X
X
Xint InCmap(x, y)
Xint x, y;
X{
Xint c;
Xif (y < height-CMAP_Y1 || y > height-CMAP_Y2)
X return(0);
Xc= (x-BOX_X1)*ncolors/(width-BOX_X2-BOX_X1);
Xif (c<= 0 || c >= ncolors)
X return(0);
Xreturn(c);
X}
X
X
Xint InSlider(x, y, n)
Xint x, y, n;
X{
Xint zone= (height-TOP_GAP-BOTTOM_GAP)/3;
X
Xif (y < TOP_GAP + (n%3)*zone + BOX_Y1 || y > TOP_GAP + ((n%3)+1)*zone - BOX_Y2)
X return 0;
Xif (n < 3) {
X if (x > (3*LINE_X - BOX_X1) / 2 && x < (LINE_X+BOX_X1) / 2)
X return 1;
X }
Xelse {
X if (x > BOX_X1 && x < width-BOX_X2)
X return 1;
X }
Xreturn 0;
X}
X
X
Xvoid DragSlider(display, win, gc1, gc2, n, x1, y1, x2, y2)
XDisplay *display;
XWindow win;
XGC gc1, gc2;
Xint n, x1, y1, x2, y2;
X{
Xint zone= (height-TOP_GAP-BOTTOM_GAP)/3;
Xint s1= (x1-BOX_X1)*SLIDERSTEPS / (width-BOX_X1-BOX_X2+1);
Xint s2= (x2-BOX_X1)*SLIDERSTEPS / (width-BOX_X1-BOX_X2+1);
Xint c1= ((TOP_GAP + ((n%3)+1)*zone - BOX_Y2) - y1) *
X (MAXSLIDE-1) / (zone - BOX_Y2 - BOX_Y1);
Xint c2= ((TOP_GAP + ((n%3)+1)*zone - BOX_Y2) - y2) *
X (MAXSLIDE-1) / (zone - BOX_Y2 - BOX_Y1);
X
Xif (c1 < 0) c1= 0;
Xif (c2 < 0) c2= 0;
Xif (c1 >= MAXSLIDE) c1= MAXSLIDE-1;
Xif (c2 >= MAXSLIDE) c2= MAXSLIDE-1;
Xif (s1 < 0) s1= 0;
Xif (s2 < 0) s2= 0;
Xif (s1 >= SLIDERSTEPS) s1= SLIDERSTEPS-1;
Xif (s2 >= SLIDERSTEPS) s2= SLIDERSTEPS-1;
Xif (s1 > s2) {
X int tmp= s2; s2= s1; s1= tmp;
X tmp= c2; c2= c1; c1= tmp;
X }
X
Xapplied= 0; /* colormap no longer valid */
Xif (n < 3) {
X switch(n) {
X case 0: red0= c2; break;
X case 1: green0= c2; break;
X case 2: blue0= c2; break;
X }
X DrawSlider(display, win, gc1, gc2, n, 0);
X } /* if */
Xelse {
X long *color;
X int i;
X n -= 3;
X switch(n) {
X case 0: color= red; break;
X case 1: color= green; break;
X case 2: color= blue; break;
X }
X for (i= s1-1; i <= s2; i++) {
X int j= i;
X int k= (i+1) % SLIDERSTEPS;
X int x1, x2, y1, y2;
X
X if (j < 0) j += SLIDERSTEPS;
X x1= BOX_X1 + 1+j*(width-BOX_X1-BOX_X2-2)/SLIDERSTEPS;
X x2= BOX_X1 + 1+(j+1)*(width-BOX_X1-BOX_X2-2)/SLIDERSTEPS;
X y1= TOP_GAP + n*zone + BOX_Y1 +
X 1 + ((zone-BOX_Y1-BOX_Y2-2)*(MAXSLIDE-color[j]))/MAXSLIDE;
X y2= TOP_GAP + n*zone + BOX_Y1 +
X 1 + ((zone-BOX_Y1-BOX_Y2-2)*(MAXSLIDE-color[k]))/MAXSLIDE;
X XDrawLine(display, win, gc2, x1, y1, x2, y2);
X }
X if (s1 == s2)
X color[s1]= c1;
X else
X for (i= 0; i <= s2-s1; i++)
X color[s1+i]= c1*(s2-s1-i)/(s2-s1) + c2*i/(s2-s1);
X for (i= s1-1; i <= s2; i++) {
X int j= i;
X int k= (i+1) % SLIDERSTEPS;
X int x1, x2, y1, y2;
X
X if (j < 0) j += SLIDERSTEPS;
X x1= BOX_X1 + 1+j*(width-BOX_X1-BOX_X2-2)/SLIDERSTEPS;
X x2= BOX_X1 + 1+(j+1)*(width-BOX_X1-BOX_X2-2)/SLIDERSTEPS;
X y1= TOP_GAP + n*zone + BOX_Y1 +
X 1 + ((zone-BOX_Y1-BOX_Y2-2)*(MAXSLIDE-color[j]))/MAXSLIDE;
X y2= TOP_GAP + n*zone + BOX_Y1 +
X 1 + ((zone-BOX_Y1-BOX_Y2-2)*(MAXSLIDE-color[k]))/MAXSLIDE;
X XDrawLine(display, win, gc1, x1, y1, x2, y2);
X }
X } /* else */
X} /* DragSlider() */
X
X
Xvoid DrawGadgets(display, win, gc)
XDisplay *display;
XWindow win;
XGC gc;
X{
Xint i;
Xint x= GAD_LEFT;
Xfor (i= 0; i < NUMGAD; i++) {
X int len= WriteText(display, win, gc, gadget[i], x+3, GAD_Y1+1);
X gadpos[i].s= x;
X gadpos[i].e= x+len+6;
X XDrawRectangle(display, win, gc, x, GAD_Y1,
X len+6, GAD_Y2-GAD_Y1);
X x+= len+6 + GAD_GAP;
X }
X}
X
X
Xint CheckGadget(display, win, gc1, gc2, x, y)
XDisplay *display;
XWindow win;
XGC gc1, gc2;
Xint x, y;
X{
Xint i;
Xstatic int drawn= -1;
Xif (y >= GAD_Y1 && y <= GAD_Y2) {
X for (i= 0; i < NUMGAD; i++) {
X if (x >= gadpos[i].s && x <= gadpos[i].e) {
X if (drawn >= 0 && drawn != i)
X XDrawRectangle(display, win, gc2, gadpos[drawn].s+1, GAD_Y1+1,
X gadpos[drawn].e-gadpos[drawn].s-2, GAD_Y2-GAD_Y1-2);
X if (drawn != i)
X XDrawRectangle(display, win, gc1, gadpos[i].s+1, GAD_Y1+1,
X gadpos[i].e-gadpos[i].s-2, GAD_Y2-GAD_Y1-2);
X drawn= i;
X return(i);
X }
X } /* for */
X } /* if */
Xif (drawn >= 0) {
X XDrawRectangle(display, win, gc2, gadpos[drawn].s+1, GAD_Y1+1,
X gadpos[drawn].e-gadpos[drawn].s-2, GAD_Y2-GAD_Y1-2);
X drawn= -1;
X }
Xreturn(-1);
X}
X
X
Xint HandleCEvent(display, screen, win, gc, gc1, gc2, event)
XDisplay *display;
Xint screen;
XWindow win;
XGC gc, gc1, gc2;
XXEvent *event;
X{
Xint i;
Xstatic int dragging= -1;
Xstatic int cmaphandle= 0, c1, c2;
Xstatic int dragx, dragy;
Xint gadget;
X
Xswitch (event->type) {
X case Expose:
X /* This is a simple application, redraw the whole
X * window only when no more expose events exist.
X */
X if (event->xexpose.count)
X break;
X for (i= 0; i < 3; i++) {
X DrawSliderBox(display, win, gc1, i);
X DrawSliders(display, win, gc1, i);
X DrawSlider(display, win, gc1, gc2, i, 1);
X }
X DrawColorBox(display, win, gc, gc1);
X DrawGadgets(display, win, gc1);
X break;
X
X case ConfigureNotify:
X width= event->xconfigure.width;
X height= event->xconfigure.height;
X break;
X
X case ButtonPress:
X switch(event->xbutton.button) {
X case 1:
X for (i= 0; i < 6; i++) {
X dragx= event->xbutton.x;
X dragy= event->xbutton.y;
X if (InSlider(dragx, dragy, i)) {
X dragging= i;
X SlideCursor(display, win);
X DragSlider(display, win, gc1, gc2, dragging,
X dragx, dragy, dragx, dragy);
X }
X }
X if (dragging >= 0)
X break;
X gadget= CheckGadget(display, win, gc1, gc2,
X event->xbutton.x, event->xbutton.y);
X switch(gadget) {
X case 0: /* apply */
X case 1: /* redraw */
X if (!applied) {
X WaitCursor(display, win);
X AllocColors(display, screen);
X NormalCursor(display, win);
X DrawColorBox(display, win, gc, gc1);
X }
X if (gadget == 1)
X return(DO_REDRAW);
X break;
X case 2:
X return(DO_PREVIOUS);
X case 3:
X return(DO_RESTART);
X case 4:
X return(DO_QUIT);
X } /* switch */
X if (gadget >= 0)
X break;
X if (c1= InCmap(event->xbutton.x, event->xbutton.y)) {
X cmaphandle= 1;
X VertCursor(display, win);
X }
X break;
X case 2:
X dragging= -1;
X WaitCursor(display, win);
X AllocColors(display, screen);
X NormalCursor(display, win);
X DrawColorBox(display, win, gc, gc1);
X break;
X default:
X dragging= -1;
X ToggleCWin(display, win, CMAP_CLOSE);
X break;
X }
X break;
X case ButtonRelease:
X if (dragging >= 0) {
X dragging= -1;
X NormalCursor(display, win);
X }
X if (cmaphandle) {
X if (c2= InCmap(event->xbutton.x, event->xbutton.y)) {
X coff = (coff + c2 - c1) % ncolors;
X }
X cmaphandle= 0;
X NormalCursor(display, win);
X }
X break;
X case MotionNotify:
X if (dragging >= 0) {
X DragSlider(display, win, gc1, gc2, dragging, dragx, dragy,
X event->xmotion.x, event->xmotion.y);
X dragx= event->xmotion.x;
X dragy= event->xmotion.y;
X }
X else CheckGadget(display, win, gc1, gc2,
X event->xmotion.x, event->xmotion.y);
X break;
X case KeyPress:
X dragging= -1;
X NormalCursor(display, win);
X ToggleCWin(display, win, CMAP_CLOSE);
X break;
X case MapNotify:
X case ReparentNotify:
X case UnmapNotify:
X dragging= -1;
X break;
X default:
X printf("Unknown Event %d\n", event->type);
X break;
X } /* switch */
Xreturn(-1);
X} /* HandleCEvent */
X
X
Xvoid SetNColors(nc)
Xint nc;
X{
Xint i;
Xncolors= nc;
X/* Initialize some nice-looking colors... */
Xfor (i= 0; i < SLIDERSTEPS; i++) {
X float c= i/((double)SLIDERSTEPS) * 3;
X float r, g, b;
X if (c < 1) {r= 1-c; g= c; b= 0;}
X else if (c < 2) {r= 0; g= 2-c; b= c-1;}
X else {r= c-2; g= 0; b= 3-c;}
X red[i]= r*(MAXSLIDE-1);
X green[i]= g*(MAXSLIDE-1);
X blue[i]= b*(MAXSLIDE-1);
X }
Xred0= green0= blue0= 0;
X}
X
X
Xvoid AllocColors(display, screen)
XDisplay *display;
Xint screen;
X{
Xint i, first= -1;
Xint d;
XXColor color;
X
Xif (allocated)
X FreeColors(display, screen);
X
Xallocated= 1;
Xapplied= 1; /* colormap is being made valid again */
Xalloc= (char *)malloc(ncolors);
Xpixel= (unsigned long *)malloc(ncolors * sizeof(unsigned long));
Xfor (i= 0; i < ncolors; i++)
X alloc[i]= 0;
X
Xif (ncolors == 3) {
X pixel[0]= BlackPixel(display, screen);
X pixel[1]= WhitePixel(display, screen);
X pixel[2]= BlackPixel(display, screen);
X return;
X }
Xif (ncolors <= 2) {
X pixel[0]= BlackPixel(display, screen);
X pixel[1]= WhitePixel(display, screen);
X return;
X }
X
X/* Because first entry of colormap is so special, allocate it first. */
Xcolor.red= red0;
Xcolor.green= green0;
Xcolor.blue= blue0;
Xcolor.flags= DoRed | DoGreen | DoBlue;
Xif (XAllocColor(display, DefaultColormap(display, screen), &color)) {
X pixel[0]= color.pixel;
X alloc[0]= 1;
X }
Xelse
X pixel[0]= BlackPixel(display, screen);
X
X/* Try to allocate colors. The order in which this is done should
X * be as "random" as possible, so that failing requests would
X * not be grouped at the end.
X */
Xd= 1;
Xwhile (d < ncolors) d <<= 1;
Xwhile (d > 1) {
X int c= d >> 1;
X do {
X double r, g, b;
X int s1= c*SLIDERSTEPS/ncolors;
X int s2= s1+1;
X int j= (c*SLIDERSTEPS)%ncolors;
X
X if (s2 >= SLIDERSTEPS)
X s2= 0;
X
X r= (red[s1]*(ncolors-j)/ncolors + red[s2]*j/ncolors)/(double)MAXSLIDE;
X g= (green[s1]*(ncolors-j)/ncolors + green[s2]*j/ncolors)/(double)MAXSLIDE;
X b= (blue[s1]*(ncolors-j)/ncolors + blue[s2]*j/ncolors)/(double)MAXSLIDE;
X
X /* Do reverse gamma correction... */
X color.red= pow(r, (1/GAMMA))*65535;
X color.green= pow(g, (1/GAMMA))*65535;
X color.blue= pow(b, (1/GAMMA))*65535;
X
X if (XAllocColor(display, DefaultColormap(display, screen), &color)) {
X pixel[c]= color.pixel;
X alloc[c]= 1;
X if (first < 0) first= c; else if (first > c) first= c;
X } /* if */
X c += d;
X } while (c < ncolors);
X d >>= 1;
X } /* while */
X
X/* If no colors could be allocated, use black&white. */
Xif (first < 0) {
X for (i= 1; i < ncolors; i++)
X pixel[i]= WhitePixel(display, screen);
X return;
X }
X/* Fill in gaps... */
Xfor (i= 1; i < ncolors; i++) {
X if (!alloc[i])
X pixel[i]= pixel[first];
X else
X first= i;
X }
X} /* AllocColors */
X
X
Xvoid FreeColors(display, screen)
XDisplay *display;
Xint screen;
X{
Xint i;
X
Xif (allocated) {
X for (i= 0; i < ncolors; i++)
X if (alloc[i])
X XFreeColors(display, DefaultColormap(display, screen),
X &pixel[i], 1L, 0);
X free(alloc);
X free(pixel);
X }
X}
X
X
Xunsigned long ToPixel(level)
Xint level;
X{
Xif (level != 0)
X level= ((level+coff) % (ncolors - 1)) + 1;
Xreturn(pixel[level]);
X}
X
END_OF_cmap.c
if test 15828 -ne `wc -c <cmap.c`; then
echo shar: \"cmap.c\" unpacked with wrong size!
fi
# end of overwriting check
fi
if test -f x.c -a "${1}" != "-c" ; then
echo shar: Will not over-write existing file \"x.c\"
else
echo shar: Extracting \"x.c\" \(22670 characters\)
sed "s/^X//" >x.c <<'END_OF_x.c'
X
X#include <X11/Xlib.h>
X#include <X11/Xutil.h>
X#include <X11/Xos.h>
X#include <sys/types.h>
X#include <sys/time.h>
X#include <sys/resource.h>
X#include <sys/param.h>
X#include <termio.h>
X#include <stdio.h>
X#include <strings.h>
X#include "mb.h"
X#include "cmap.h"
X#include "misc.h"
X#include "pix.h"
X
X#ifdef USE_NETWORK
X#include "ipc.h"
X#endif
X
X#define GEOM_PLACE 1
X#define GEOM_RIGHT 2
X#define GEOM_DOWN 4
X#define GEOM_SIZE 8
X#define GEOM_ERROR 16
X
X/* Just to make sure that the number of colors will be reasonable
X * on a 24-bit true-color display ;)
X */
X#define MAXCOLORS 1024
X
X/* dummy procedure for XCheckIfEvent */
XBool dummy() {return(1);}
X
X#ifdef USE_NETWORK
X/* Terminology: server is the one who shows pictures, and
X * clients do the calculations.
X */
X
X#define MODE_STANDALONE 0
X#define MODE_SERVER 1
X#define MODE_CLIENT 2
X
X#define RSHCMD "rsh %s \"xnetmb -nice 10 -port %d -server %s&\" </dev/null >/dev/null"
X#endif
X
Xstatic Display *display;
Xstatic int screen;
Xstatic Window win= 0, cwin= 0;
Xstatic GC gc, gc_inv, gc_set, gc_clear;
X#ifdef USE_NETWORK
Xstatic int mode= MODE_STANDALONE;
Xstatic int portnum= DEF_PORT;
Xstatic char *server;
X#endif
X
Xvoid DrawSplitImage();
Xvoid CalcImage();
Xvoid DrawImage();
Xvoid DrawRect();
X#define EraseRect() DrawRect(0, 0,0, 0,0, 0,0);
X
Xstatic double xc= 0.0, yc= 0.0, cx= 0.0, cy= 0.0, d= 0.0, scale= 8.0;
Xstatic int iter= 500, flags= 0;
Xunsigned int width= 300, height= 300;
X
X
Xint ParseComplex(string, x, y)
Xchar *string;
Xdouble *x, *y;
X{
Xchar ii, sign;
X/* x+-yi */
Xif (sscanf(string, "%lf%lf%c", x, y, &ii) == 3 &&
X ii == 'i')
X ;
X/* x+-iy */
Xelse if (sscanf(string, "%lf%ci%lf", x, &sign, y) == 3 &&
X (sign == '+' || sign == '-')) {
X if (sign == '-') *y = -*y;
X }
X/* x+-i */
Xelse if (sscanf(string, "%lf%c%c", x, &sign, &ii) == 3 &&
X (sign == '+' || sign == '-') && ii == 'i') {
X if (sign == '-')
X *y= -1.0;
X else
X *y= 1.0;
X }
X/* +-iy */
Xelse if (sscanf(string, "%c%c%lf", &ii, &sign, y) == 3 &&
X (sign == '+' || sign == '-') && ii == 'i') {
X *x= 0.0;
X if (sign == '-')
X *y= -*y;
X }
X/* yi */
Xelse if (sscanf(string, "%lf%c", y, &ii) == 2 && ii == 'i')
X *x= 0.0;
X/* iy */
Xelse if (sscanf(string, "%c%lf", &ii, y) == 2 && ii == 'i')
X *x= 0.0;
X/* +-i */
Xelse if (sscanf(string, "%c%c", &sign, &ii) == 2 &&
X (sign == '-' || sign == '+') && ii == 'i') {
X *x= 0.0;
X if (sign == '-')
X *y= -1.0;
X else
X *y= 1.0;
X }
X/* i */
Xelse if (sscanf(string, "%c", &ii) == 1 && ii == 'i') {
X *x= 0.0;
X *y= 1.0;
X }
X/* x */
Xelse if (sscanf(string, "%lf", x) == 1)
X *y= 0.0;
Xelse
X return(0);
Xreturn(1);
X}
X
X
Xmain(argc, argv)
Xint argc;
Xchar *argv[];
X{
XXSizeHints size_hints;
XXEvent event;
XXGCValues gcval;
XXWindowAttributes xwattr;
XXSetWindowAttributes xswattr;
Xunsigned int border_width= 1;
Xunsigned int display_width, display_height;
Xint win_x= 0, win_y= 0;
Xint cwin_x= 0, cwin_y= 0;
Xint dragx, dragy;
Xint buttonpressed;
Xint ncolors= 0;
Xint zebra= 0;
Xdouble xstore1= xc, ystore1= yc, scalestore1= scale;
Xdouble xstore2= xc, ystore2= yc, scalestore2= scale;
Xint flagstore= flags;
Xint wingeom= 0;
Xchar **mach;
Xint nmach= 0;
Xchar *window_name= "XMandelbrot";
Xchar *icon_name= "XMandel";
Xchar *cwindow_name= "MBcolors";
Xchar *cicon_name= "MBcolors";
Xchar *display_name= NULL;
X
Xint i;
X
X/* Command line options... boring.
X * (OH NO, it is my pseudo-intelligent commenting style attack again.
X * Sigh... Please be patient and hope for the best.)
X */
Xfor (i= 1; i < argc; i++) {
X if (!strcmp(argv[i], "-d") || !strcmp(argv[i], "-display")) {
X if (++i >= argc) {
X fprintf(stderr, "%s: error in cmd line option 'display'\n",
X argv[0]);
X exit(1);
X }
X display_name= argv[i];
X }
X
X else if (!strcmp(argv[i], "-g") || !strcmp(argv[i], "-geometry")) {
X char sign1, sign2;
X if (++i >= argc) {
X fprintf(stderr, "%s: error in cmd line option 'geometry'\n",
X argv[0]);
X exit(1);
X }
X switch (sscanf(argv[i], "%ux%u%c%d%c%d",
X &width, &height, &sign1, &win_x, &sign2, &win_y)) {
X case 6:
X wingeom= GEOM_PLACE | GEOM_SIZE;
X if (sign1 == '-') wingeom |= GEOM_RIGHT;
X else if (sign1 != '+') wingeom |= GEOM_ERROR;
X if (sign2 == '-') wingeom |= GEOM_DOWN;
X else if (sign2 != '+') wingeom |= GEOM_ERROR;
X if (wingeom & GEOM_ERROR) {
X fprintf(stderr,
X "%s: error in cmd line option 'geometry'\n",
X argv[0]);
X exit(1);
X }
X break;
X case 2:
X wingeom= GEOM_SIZE;
X /* There is nothing else here to be done. */
X break;
X default:
X fprintf(stderr, "%s: error in cmd line option 'geometry'\n",
X argv[0]);
X exit(1);
X }
X }
X
X else if (!strcmp(argv[i], "-z") || !strcmp(argv[i], "-zebra")) {
X /* Need to know which of the two -z options this is... */
X if (!strcmp(argv[i], "-z") && i+1 < argc &&
X ParseComplex(argv[i+1], &xc, &yc)) {
X i++;
X xstore1= xc; ystore1= yc;
X }
X else
X zebra= 1;
X }
X
X else if (!strcmp(argv[i], "-n") || !strcmp(argv[i], "-nice")) {
X if (++i >= argc) {
X fprintf(stderr, "%s: error in cmd line option 'nice'\n",
X argv[0]);
X exit(1);
X }
X setpriority(PRIO_PROCESS,getpid(), atoi(argv[i]));
X }
X
X else if (!strcmp(argv[i], "-i") || !strcmp(argv[i], "-iters")) {
X if (++i >= argc) {
X fprintf(stderr, "%s: error in cmd line option 'iters'\n",
X argv[0]);
X exit(1);
X }
X iter= atoi(argv[i]);
X }
X
X else if (!strcmp(argv[i], "-c") || !strcmp(argv[i], "-colors")) {
X if (++i >= argc) {
X fprintf(stderr, "%s: error in cmd line option 'colors\n",
X argv[0]);
X exit(1);
X }
X ncolors= atoi(argv[i]);
X if (ncolors < 2)
X ncolors= 2;
X }
X
X else if (!strcmp(argv[i], "-j")) {
X if (++i >= argc || !ParseComplex(argv[i], &cx, &cy)) {
X fprintf(stderr, "%s: error in cmd line option 'j'\n",
X argv[0]);
X exit(1);
X }
X flagstore = (flags |= JULIA);
X }
X
X else if (!strcmp(argv[i], "-x")) {
X if (++i >= argc || sscanf(argv[i], "%lf", &scale) < 1) {
X fprintf(stderr, "%s: error in cmd line option 'x'\n",
X argv[0]);
X exit(1);
X }
X scalestore1 = (scale *= 2);
X }
X
X#ifdef USE_NETWORK
X else if (!strcmp(argv[i], "-s") || !strcmp(argv[i], "-server")) {
X int k;
X if (++i >= argc || mode != MODE_STANDALONE) {
X fprintf(stderr, "%s: error in cmd line option 'server'\n",
X argv[0]);
X exit(1);
X }
X /* We are the client, and server is specified here. */
X mode= MODE_CLIENT;
X server= argv[i];
X /* daemon */
X for (k= getdtablesize() - 1; k >= 0; --k)
X close(k);
X k= open("/dev/null", O_RDONLY);
X if (k >= 0) {
X ioctl(k, TIOCNOTTY, 0);
X close(k);
X }
X }
X#endif
X
X#ifdef USE_NETWORK
X else if (!strcmp(argv[i], "-p") || !strcmp(argv[i], "-port")) {
X if (++i >= argc) {
X fprintf(stderr, "%s: error in cmd line option 'iters'\n",
X argv[0]);
X exit(1);
X }
X portnum= atoi(argv[i]);
X }
X#endif
X
X#ifdef USE_NETWORK
X else if (!strcmp(argv[i], "-m") || !strcmp(argv[i], "-machines")) {
X if (mode != MODE_STANDALONE) {
X fprintf(stderr, "%s: error in command line option 'machines'\n",
X argv[0]);
X exit(1);
X }
X
X mode= MODE_SERVER;
X mach= &argv[i+1];
X while (++i < argc && argv[i][0] != '-')
X nmach++;
X --i;
X }
X#endif
X
X else if (!strcmp(argv[i], "-guru")) {
X if (++i >= argc) {
X fprintf(stderr, "%s: You are not a guru.\n", argv[0]);
X exit(1);
X }
X if (!strcmp(argv[i], "fast")) {
X flagstore= (flags |= FAST);
X }
X else {
X fprintf(stderr, "%s: You are not a guru.\n", argv[0]);
X exit(1);
X }
X }
X
X else {
X fprintf(stderr, "%s: unrecognized cmd line option '%s'\n\n",
X argv[0], argv[i]);
X fprintf(stderr,
X "Usage: %s -display <name> -geometry <geometry>\n",
X argv[0]);
X fprintf(stderr,
X "-zebra -nice <value> -iters <i> -colors <number>\n");
X fprintf(stderr,
X "-z <x+yi> -j <cx+cyi> -x <scale>\n");
X#ifdef USE_NETWORK
X fprintf(stderr,
X "-server <name> -port <port> -machines [list of rsh machines]\n");
X#endif
X fprintf(stderr, "\nAll options may be abbreviated.\n\n");
X exit(1);
X }
X } /* for */
X
X#ifdef USE_NETWORK
Xif (mode == MODE_CLIENT) {
X Client_run(server, portnum);
X exit(0);
X }
Xelse if (mode == MODE_SERVER) {
X char cmd[sizeof(RSHCMD) + 2*MAXHOSTNAMELEN], host[MAXHOSTNAMELEN];
X if (gethostname(host, MAXHOSTNAMELEN) < 0) {
X perror("unable to find my name");
X exit(1);
X }
X CreateServer(portnum);
X printf("Starting remote machines:");
X for (i= 0; i < nmach; i++) {
X sprintf(cmd, RSHCMD, mach[i], portnum, host);
X printf (" %s", mach[i]); fflush(stdout);
X if ((system(cmd) >> 8) > 0) {
X fprintf(stderr, "%s: unable to rsh %s\n", argv[0],
X mach[i]);
X }
X }
X --i;
X putchar('\n');
X }
X#endif
X
X/* Open the display, if possible. */
Xif(!(display= XOpenDisplay(display_name))) {
X fprintf(stderr, "cannot reach X server %s\n",
X XDisplayName(display_name));
X exit(1);
X }
X
Xscreen= DefaultScreen(display);
X
Xdisplay_width= DisplayWidth(display, screen);
Xdisplay_height= DisplayHeight(display, screen);
X
Xif (!(wingeom & GEOM_PLACE)) {
X win_x= display_width / 2 - (int)width;
X win_y= 2 * display_height / 3;
X }
Xelse {
X if (wingeom & GEOM_RIGHT) win_x= (int)display_width - win_x - (int)width;
X if (wingeom & GEOM_DOWN) win_y= (int)display_height - win_y - (int)height;
X }
X
Xcwin_x= display_width / 2 - 200;
Xcwin_y= display_height - 250;
X
X
Xif (ncolors == 0)
X ncolors= 1 << (DefaultDepth(display, screen));
Xif (zebra) ncolors= 3;
Xif (ncolors > MAXCOLORS)
X ncolors= MAXCOLORS;
XSetNColors(ncolors);
X
Xxswattr.background_pixel= WhitePixel(display, screen);
Xxswattr.border_pixel= BlackPixel(display, screen);
Xwin= XCreateWindow(display, RootWindow(display, screen), win_x, win_y,
X width, height, border_width, CopyFromParent,
X InputOutput, CopyFromParent,
X CWBackPixel | CWBorderPixel, &xswattr);
Xcwin= XCreateWindow(display, RootWindow(display, screen), cwin_x, cwin_y,
X 400, 200, border_width, CopyFromParent,
X InputOutput, CopyFromParent,
X CWBackPixel | CWBorderPixel, &xswattr);
X
Xif (!win || !cwin) {
X#ifdef USE_NETWORK
X if (mode == MODE_SERVER)
X CloseDown();
X#endif
X perror("could not open window");
X myExit();
X exit(0);
X }
X
Xsize_hints.flags= PMinSize;
Xif (wingeom & GEOM_PLACE) size_hints.flags |= PPosition;
Xif (wingeom & GEOM_SIZE) size_hints.flags |= PSize;
X
Xsize_hints.width= width;
Xsize_hints.height= height;
Xsize_hints.min_width= 50;
Xsize_hints.min_height= 50;
Xsize_hints.x= win_x;
Xsize_hints.y= win_y;
XXSetStandardProperties(display, win, window_name, icon_name,
X None, NULL, 0, &size_hints);
X
Xsize_hints.flags= PPosition | PSize | PMinSize;
Xsize_hints.width= 400;
Xsize_hints.height= 200;
Xsize_hints.min_width= 200;
Xsize_hints.min_height= 100;
Xsize_hints.x= cwin_x;
Xsize_hints.y= cwin_y;
XXSetStandardProperties(display, cwin, cwindow_name, cicon_name,
X None, NULL, 0, &size_hints);
X
XXSelectInput(display, win, ExposureMask | KeyPressMask |
X ButtonPressMask | ButtonReleaseMask |
X PointerMotionMask | StructureNotifyMask);
XXSelectInput(display, cwin, ExposureMask | KeyPressMask |
X ButtonPressMask | ButtonReleaseMask |
X PointerMotionMask | StructureNotifyMask);
X
Xgcval.foreground= BlackPixel(display, screen);
Xgcval.background= WhitePixel(display, screen);
Xgc= XCreateGC(display, win, GCForeground | GCBackground, &gcval);
Xgc_set= XCreateGC(display, win, GCForeground | GCBackground, &gcval);
X
Xgcval.foreground= WhitePixel(display, screen);
Xgc_clear= XCreateGC(display, win, GCForeground | GCBackground, &gcval);
X
Xgcval.function= GXinvert;
Xgc_inv= XCreateGC(display, win, GCFunction, &gcval);
X
Xif (!AllocFonts(display, gc_set)) {
X fprintf(stderr, "Could not open fonts... no text will be drawn");
X }
XAllocColors(display, screen);
X
XAllocCursors(display);
XNormalCursor(display, win);
XNormalCursor(display, cwin);
X
XXMapWindow(display, win);
Xbuttonpressed= 0;
X
Xfor (;;) {
X#ifdef USE_NETWORK
X if (mode == MODE_SERVER)
X CheckClients(NOBLOCK);
X
X if (mode == MODE_SERVER && PendingRequests()) {
X while (!XCheckIfEvent(display, &event, dummy, (char *)NULL))
X CheckClients(1);
X if (!PendingRequests()) {
X NormalCursor(display, win);
X NormalCursor(display, cwin);
X }
X }
X else
X XNextEvent(display, &event);
X#else
X XNextEvent(display, &event);
X#endif
X
X if (event.xany.window == cwin) {
X switch (HandleCEvent(display, screen, cwin, gc,
X gc_set, gc_clear, &event)) {
X case DO_REDRAW:
X#ifdef USE_NETWORK
X if (mode == MODE_SERVER) Invalidate();
X#endif
X XClearArea(display, win, 0, 0, width, height, 1);
X break;
X case DO_PREVIOUS:
X if (xc != xstore1 || yc != ystore1 ||
X scale != scalestore1 || flags != flagstore) {
X xc= xstore1; yc= ystore1;
X scale= scalestore1;
X flags= flagstore;
X d= scale / (width + height);
X#ifdef USE_NETWORK
X if (mode == MODE_SERVER) Invalidate();
X#endif
X XClearArea(display, win, 0, 0, width, height, 1);
X }
X break;
X case DO_RESTART:
X xstore1= xc; ystore1= yc;
X scalestore1= scale;
X flagstore= flags;
X
X xc= 0.0; yc= 0.0;
X scale= 8.0; flags &= ~JULIA;
X d= scale / (width + height);
X#ifdef USE_NETWORK
X if (mode == MODE_SERVER) Invalidate();
X#endif
X XClearArea(display, win, 0, 0, width, height, 1);
X break;
X
X case DO_QUIT:
X#ifdef USE_NETWORK
X if (mode == MODE_SERVER)
X CloseDown();
X#endif
X myExit();
X exit(0);
X } /* switch */
X }
X else switch(event.type) {
X case Expose:
X WaitCursor(display, win);
X WaitCursor(display, cwin);
X CalcImage (event.xexpose.x, event.xexpose.y,
X event.xexpose.width, event.xexpose.height);
X break;
X
X case ConfigureNotify:
X#ifdef USE_NETWORK
X if (mode == MODE_SERVER) {
X if (width != event.xconfigure.width ||
X height != event.xconfigure.height)
X Invalidate();
X }
X#endif
X width= event.xconfigure.width;
X height= event.xconfigure.height;
X d= scale / (width + height);
X break;
X
X case ButtonPress:
X switch (event.xbutton.button) {
X case 1:
X ZoomCursor(display, win);
X dragx= event.xbutton.x;
X dragy= event.xbutton.y;
X buttonpressed= 1;
X break;
X
X case 2: /* julia stuff here */
X if (buttonpressed) {
X EraseRect();
X buttonpressed= 0;
X NormalCursor(display, win);
X }
X else if (!(flags & JULIA)) {
X /* toggle to julia set; save current context */
X xstore1= xstore2= xc; ystore1= ystore2= yc;
X scalestore1= scalestore2= scale;
X flagstore= flags;
X
X flags |= JULIA;
X cx= xc - d * (width/2.0 - event.xbutton.x);
X cy= yc + d * (height/2.0 - event.xbutton.y);
X xc= 0.0; yc= 0.0;
X scale= 8.0;
X d= scale / (width + height);
X#ifdef USE_NETWORK
X if (mode == MODE_SERVER) Invalidate();
X#endif
X XClearArea(display, win, 0, 0, width, height, 1);
X }
X else {
X /* toggle to mb set; restore context */
X xc= xstore2; yc= ystore2;
X scale= scalestore2;
X flags &= ~JULIA;
X d= scale / (width + height);
X#ifdef USE_NETWORK
X if (mode == MODE_SERVER) Invalidate();
X#endif
X XClearArea(display, win, 0, 0, width, height, 1);
X }
X break;
X
X case 3: /* open colormap window */
X if (buttonpressed) {
X EraseRect();
X buttonpressed= 0;
X NormalCursor(display, win);
X }
X else
X ToggleCWin(display, cwin, CMAP_TOGGLE);
X break;
X default:
X break;
X }
X break;
X
X case ButtonRelease:
X switch (event.xbutton.button) {
X case 1:
X if (buttonpressed) {
X int xdiff, ydiff;
X xstore1= xc; ystore1= yc;
X scalestore1= scale;
X flagstore= flags;
X
X xdiff= dragx - event.xbutton.x;
X ydiff= dragy - event.xbutton.y;
X if (xdiff < 0) xdiff= -xdiff;
X if (ydiff < 0) ydiff= -ydiff;
X if (xdiff/(double)width < ydiff/(double)height)
X scale *= (ydiff/(double)height);
X else
X scale *= (xdiff/(double)width);
X buttonpressed= 0;
X EraseRect();
X
X xc= xc - d * ((int)width - (dragx + event.xbutton.x)) / 2.0;
X yc= yc + d * ((int)height - (dragy + event.xbutton.y)) / 2.0;
X d= scale / (width + height);
X#ifdef USE_NETWORK
X if (mode == MODE_SERVER) Invalidate();
X#endif
X XClearArea(display, win, 0, 0, width, height, 1);
X }
X default:
X break;
X }
X break;
X
X case MotionNotify:
X if (buttonpressed)
X DrawRect(1, dragx, dragy, event.xmotion.x, event.xmotion.y,
X (int)width, (int)height);
X break;
X
X case KeyPress:
X#ifdef USE_NETWORK
X if (mode == MODE_SERVER)
X CloseDown();
X#endif
X myExit();
X exit(0);
X
X case MapNotify:
X /* Determine size of set (depends on width & height) */
X XGetWindowAttributes(display, win, &xwattr);
X width= xwattr.width; height= xwattr.height;
X d= scale / (width + height);
X break;
X
X case ReparentNotify:
X case UnmapNotify:
X /* I can't think of anything reasonable to do here... */
X break;
X
X default:
X printf("Unknown Event %d\n", event.type);
X break;
X } /* switch */
X } /* for(ever) */
X} /* main */
X
X
XmyExit()
X{
XFreeFonts(display);
XXFreeGC(display, gc);
XXFreeGC(display, gc_inv);
XXFreeGC(display, gc_set);
XXFreeGC(display, gc_clear);
X
XFreeColors(display, screen);
Xif (win) XDestroyWindow(display, win);
Xif (cwin) XDestroyWindow(display, cwin);
XXCloseDisplay(display);
X}
X
X
X/* Split the image into comfortably small chunks, which
X * are then fed to DrawSplitImage()
X */
Xvoid CalcImage(xoff, yoff, w, h)
Xint xoff, yoff, w, h;
X{
Xint xd=1, yd=1, xn, yn;
X/* do not accidentally crawl arond some area...
X */
Xif (xc - d*(width/2.0 - xoff) < -.5 &&
X yc + d*(height/2.0 - yoff) > .5 &&
X xc - d*(width/2.0 - xoff-w) > .5 &&
X yc + d*(height/2.0 - yoff-h) < -.5) {
X int x0= width/2 - xc/d;
X int y0= height/2 + yc/d;
X int xdist= x0 - xoff;
X int ydist= y0 - yoff;
X if (w > 2*xdist) xdist= w-xdist;
X if (h > 2*ydist) ydist= h-ydist;
X if (xdist > ydist) {
X CalcImage(xoff, yoff, x0-xoff, h);
X CalcImage(x0, yoff, w-(x0-xoff), h);
X }
X else {
X CalcImage(xoff, yoff, w, y0-yoff);
X CalcImage(xoff, y0, w, h-(y0-yoff));
X }
X return;
X } /* if */
Xwhile (w*h/(xd*yd) > 65536) {
X if (w*yd < h*xd) /* <==> w/xd<h/yd */
X yd++;
X else
X xd++;
X }
Xfor (yn= 0; yn < yd; yn++)
X for (xn= 0; xn < xd; xn++) {
X DrawSplitImage(xoff + xn*w/xd, yoff+yn*h/yd,
X (xn+1)*w/xd - xn*w/xd,
X (yn+1)*h/yd - yn*h/yd);
X }
X#ifdef USE_NETWORK
Xif (mode == MODE_STANDALONE || !PendingRequests() ) {
X NormalCursor(display, win);
X NormalCursor(display, cwin);
X }
X#else
XNormalCursor(display, win);
XNormalCursor(display, cwin);
X#endif
X}
X
X
X/* Calculate chunks either in local or in remote machines
X */
Xvoid DrawSplitImage(xoff, yoff, w, h)
Xint xoff, yoff, w, h;
X{
Xdouble x,y;
Xu_short *dest;
Xint tmpflags;
X
Xx= xc - d*(width/2.0 - xoff);
Xy= yc + d*(height/2.0 - yoff);
X
XXDrawRectangle(display, win, gc_set, xoff, yoff, w-1, h-1);
XXFlush(display);
X
X#ifdef USE_NETWORK
Xif (mode == MODE_SERVER) {
X /* Try to delegate */
X if (CalcRequest(x, y, d, d, cx, cy, w, h, iter, flags, xoff, yoff))
X return;
X }
X#endif
X/* Always use FASTmode when using local machine */
Xtmpflags= flags;
Xflags |= FAST;
Xiterate(x, y, d, d, cx, cy, w, h, iter, flags, &dest);
XDrawImage(xoff, yoff, w, h, dest);
Xflags= tmpflags;
X}
X
X
Xvoid DrawImage(xoff, yoff, w, h, dest)
Xint xoff, yoff, w, h;
Xu_short *dest;
X{
Xint px, py;
Xu_short *ptr, color;
Xlong len, i;
XXGCValues gcval;
XXPoint *xpts;
Xlong npts= 512;
Xint fastmode= flags & FAST;
X
Xptr= dest;
Xxpts= (XPoint *)malloc(npts * sizeof(XPoint));
X
Xif (!fastmode)
X initialize(w, h);
Xfor (;;) {
X /* In fast mode, first_point() and next_point() are omitted.
X * Server will be faster but there will be over 100% more traffic
X * in the net.
X */
X if (fastmode) {
X px= *ptr++;
X if (px != LASTPIX)
X py= *ptr++;
X }
X if (fastmode && px == LASTPIX)
X break;
X if (!fastmode && first_point(&px, &py) ==0)
X break;
X color= *ptr++;
X gcval.foreground= ToPixel((int)(color & 0x7fff));
X XChangeGC(display, gc, GCForeground, &gcval);
X
X if (color & 0x8000) {
X XDrawPoint(display, win, gc, px+xoff, py+yoff);
X }
X else {
X int dir, bitindex= 7;
X
X len= *ptr++;
X if (len > npts) {
X free(xpts);
X xpts= (XPoint *)malloc((npts= len) * sizeof(XPoint));
X }
X for (i= 0; i < len; i++) {
X dir= ((*ptr) >> (bitindex*2)) & 3;
X if (!fastmode)
X next_point(dir);
X
X XDrawPoint(display, win, gc, px+xoff, py+yoff);
X xpts[i].x= px+xoff;
X xpts[i].y= py+yoff;
X switch (dir) {
X case UP: py--; break;
X case DOWN: py++; break;
X case LEFT: px--; break;
X case RIGHT: px++; break;
X }
X if (--bitindex < 0) {
X ptr++;
X bitindex= 7;
X }
X }
X if (bitindex != 7)
X ptr++;
X XFillPolygon(display, win, gc, xpts, len, Complex, CoordModeOrigin);
X } /* else */
X } /* for */
Xif (!fastmode)
X deinit();
Xfree(dest);
Xfree(xpts);
X} /* DrawImage */
X
X
Xvoid DrawRect(mode, x1, y1, x2, y2, w, h)
Xint mode, x1, y1, x2, y2, w, h;
X{
Xstatic int drawn= 0;
Xstatic int dx, dy, dw, dh;
X
Xif (drawn)
X XDrawRectangle(display, win, gc_inv, dx, dy, dw, dh);
Xdrawn= 0;
X
Xif (mode == 0)
X return;
X
Xdw= x2 - x1; dh= y2 - y1;
Xif (dw == 0 && dh == 0)
X return;
X
Xdx= x1; dy= y1;
Xif (dw < 0) {
X dw= -dw;
X dx= x2;
X }
Xif (dh < 0) {
X dh= -dh;
X dy= y2;
X }
X
Xif (dw/(double)w > dh/(double)h) {
X dh= dw * (h/(double)w);
X dy= (y1 + y2 - dh)/2;
X }
Xelse {
X dw= dh * (w/(double)h);
X dx= (x1 + x2 - dw)/2;
X }
XXDrawRectangle(display, win, gc_inv, dx, dy, dw, dh);
Xdrawn= 1;
X} /* drawrect */
X
END_OF_x.c
if test 22670 -ne `wc -c <x.c`; then
echo shar: \"x.c\" unpacked with wrong size!
fi
# end of overwriting check
fi
echo shar: End of archive 2 \(of 2\).
cp /dev/null ark2isdone
MISSING=""
for I in 1 2 ; do
if test ! -f ark${I}isdone ; then
MISSING="${MISSING} ${I}"
fi
done
if test "${MISSING}" = "" ; then
echo You have unpacked both archives.
rm -f ark[1-9]isdone
else
echo You still need to unpack the following archives:
echo " " ${MISSING}
fi
## End of shell archive.
exit 0
More information about the Alt.sources
mailing list